From f201d522472acb88c4ca689933f208e4633856e5 Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Fri, 28 Mar 2008 02:00:37 -0800 Subject: [PATCH] Add hyperlink and colour support to the text window. Don't redraw the text window every time we refresh the graphics window, because that's slow. Use classes instead of structs for everything; I don't understand the template handling for structs. And implement the IdList, which I will try to use in many places. [git-p4: depot-paths = "//depot/solvespace/": change = 1655] --- Makefile | 2 +- cmdline.cpp | 79 +++++++++++++++++++++++++++++++++++++++-------- dsc.h | 69 ++++++++++++++++++++++++++++++++++------- graphicswin.cpp | 16 +++++++--- sketch.h | 50 ++++++++++++++++++------------ solvespace.cpp | 9 ++++++ solvespace.h | 20 ++++++++---- ui.h | 28 +++++++++++------ util.cpp | 16 +++------- win32/w32main.cpp | 51 +++++++++++++++++++++++++----- 10 files changed, 258 insertions(+), 82 deletions(-) diff --git a/Makefile b/Makefile index ff99717..132acb1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -DEFINES = /D_WIN32_WINNT=0x400 /DISOLATION_AWARE_ENABLED /D_WIN32_IE=0x500 /DWIN32_LEAN_AND_MEAN /DWIN32 +DEFINES = /D_WIN32_WINNT=0x500 /DISOLATION_AWARE_ENABLED /D_WIN32_IE=0x500 /DWIN32_LEAN_AND_MEAN /DWIN32 CFLAGS = /W3 /nologo -I..\common\win32 /O2 /D_DEBUG /D_CRT_SECURE_NO_WARNINGS /Zi /I. HEADERS = ..\common\win32\freeze.h ui.h solvespace.h dsc.h sketch.h diff --git a/cmdline.cpp b/cmdline.cpp index 171147c..e432258 100644 --- a/cmdline.cpp +++ b/cmdline.cpp @@ -1,6 +1,16 @@ #include "solvespace.h" #include +const TextWindow::Color TextWindow::colors[] = { + { COLOR_FG_DEFAULT, COLOR_BG_DEFAULT, }, // 0 + { RGB(255, 40, 40), COLOR_BG_DEFAULT, }, // 1 + { RGB(255, 255, 0), COLOR_BG_DEFAULT, }, // 2 + { RGB( 40, 255, 40), COLOR_BG_DEFAULT, }, // 3 + { RGB( 0, 255, 255), COLOR_BG_DEFAULT, }, // 4 + { RGB(140, 140, 255), COLOR_BG_DEFAULT, }, // 5 + { RGB(255, 0, 255), COLOR_BG_DEFAULT, }, // 6 +}; + void TextWindow::Init(void) { ClearScreen(); ClearCommand(); @@ -37,34 +47,77 @@ void TextWindow::Printf(char *fmt, ...) { } int color = COLOR_NORMAL; + int link = NOT_A_LINK; + DWORD data = 0; + LinkFunction *f = NULL; c = 0; while(*fmt) { + char buf[1024]; + if(*fmt == '%') { fmt++; if(*fmt == '\0') goto done; + strcpy(buf, ""); switch(*fmt) { - case 's': { - char *s = va_arg(vl, char *); - memcpy(&(text[r][c]), s, strlen(s)); - c += strlen(s); - break; - } case 'd': { int v = va_arg(vl, int); - sprintf((char *)&(text[r][c]), "%d", v); - c += strlen((char *)&(text[r][c])); - text[r][c] = ' '; + sprintf(buf, "%d", v); break; } + case 'x': { + DWORD v = va_arg(vl, DWORD); + sprintf(buf, "%08x", v); + break; + } + case 's': { + char *s = va_arg(vl, char *); + memcpy(buf, s, min(sizeof(buf), strlen(s)+1)); + break; + } + case 'E': + color = COLOR_NORMAL; + link = NOT_A_LINK; + data = 0; + f = NULL; + break; + + case 'C': + if(fmt[1] == '\0') goto done; + fmt++; + color = *fmt - '0'; + if(color < 0 || color >= arraylen(colors)) color = 0; + break; + + case 'L': + if(fmt[1] == '\0') goto done; + fmt++; + link = *fmt; + break; + + case 'D': + data = va_arg(vl, DWORD); + break; + case '%': - text[r][c++] = '%'; + strcpy(buf, "%"); break; } } else { - if(c >= MAX_COLS) goto done; - text[r][c++] = *fmt; + buf[0] = *fmt; + buf[1]= '\0'; } + + for(unsigned i = 0; i < strlen(buf); i++) { + if(c >= MAX_COLS) goto done; + text[r][c] = buf[i]; + meta[r][c].color = color; + meta[r][c].link = link; + meta[r][c].data = data; + meta[r][c].f = f; + c++; + } + fmt++; } @@ -84,7 +137,7 @@ void TextWindow::ClearCommand(void) { void TextWindow::ProcessCommand(char *cmd) { - Printf("command: '%s'", cmd); + Printf("%C2command:%E '%s' done %C3(green)%E %C5%LaLink%E", cmd); } void TextWindow::KeyPressed(int c) { diff --git a/dsc.h b/dsc.h index 685de7b..2313dd6 100644 --- a/dsc.h +++ b/dsc.h @@ -5,9 +5,8 @@ typedef unsigned long DWORD; typedef unsigned char BYTE; -typedef struct VectorTag Vector; - -typedef struct VectorTag { +class Vector { +public: double x, y, z; Vector Cross(Vector b); @@ -16,26 +15,74 @@ typedef struct VectorTag { double Magnitude(void); Vector ScaledBy(double v); -} Vector; +}; -typedef struct { +class Point2d { +public: double x, y; -} Point2d; +}; -template struct IdList { +template +class IdList { +public: typedef struct { T v; + H h; int tag; } Elem; - Elem elem; + Elem *elem; int elems; int elemsAllocated; - void addAndAssignId(T *v); - void removeTagged(void); + void AddAndAssignId(T *v) { + int i; + int id = 0; + + for(i = 0; i < elems; i++) { + id = max(id, elem[i].h.v); + } + + H h; + h.v = id + 1; + AddById(v, h); + } + + void AddById(T *v, H h) { + if(elems >= elemsAllocated) { + elemsAllocated = (elemsAllocated + 32)*2; + elem = (Elem *)realloc(elem, elemsAllocated*sizeof(elem[0])); + if(!elem) oops(); + } + + elem[elems].v = *v; + elem[elems].h = h; + elem[elems].tag = 0; + elems++; + } + + void RemoveTagged(void) { + int src, dest; + dest = 0; + for(src = 0; src < elems; src++) { + if(elem[src].tag) { + // this item should be deleted + } else { + if(src != dest) { + elem[dest] = elem[src]; + } + dest++; + } + } + elems = dest; + // and elemsAllocated is untouched + } + + void Clear(void) { + elemsAllocated = elems = 0; + if(elem) free(elem); + } - void clear(void); }; #endif diff --git a/graphicswin.cpp b/graphicswin.cpp index d6c5fdc..a22ea65 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -127,9 +127,17 @@ void GraphicsWindow::Paint(int w, int h) { glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - GLUquadricObj *quadObj; - quadObj = gluNewQuadric(); - gluQuadricDrawStyle(quadObj, GLU_LINE); - gluSphere(quadObj, 300, 4, 4); + glBegin(GL_QUADS); + glVertex3f(-200, -200, 0); + glVertex3f(-200, 200, 0); + glVertex3f( 200, 200, 0); + glVertex3f( 200, -200, 0); + glEnd(); + glBegin(GL_QUADS); + glVertex3f(-200, -200, 200); + glVertex3f(-200, 200, 200); + glVertex3f( 200, 200, 200); + glVertex3f( 200, -200, 200); + glEnd(); } diff --git a/sketch.h b/sketch.h index e586dfb..0d62db0 100644 --- a/sketch.h +++ b/sketch.h @@ -2,57 +2,67 @@ #ifndef __SKETCH_H #define __SKETCH_H -typedef struct hRequestTag hRequest; -typedef struct hEntityTag hEntity; -typedef struct hPointTag hPoint; -typedef struct hParamTag hParam; +class hEntity; +class hPoint; +class hRequest; +class hParam; -typedef struct hRequestTag { +class hRequest { +public: int v; hEntity entity(int i); -} hRequest; +}; -typedef struct { +class Request { +public: static const int REQUEST_LINE_SEGMENT = 0; static const int REQUEST_STEP_REPEAT_TRANSLATE = 1; static const int REQUEST_STEP_REPEAT_TRANSLATE_SYM = 2; int type; hRequest h; -} Request; +}; -typedef struct hEntityTag { +class hEntity { +public: int v; hRequest request(int i); hPoint point(int i); -} hEntity; +}; -typedef struct { +class Entity { +public: static const int ENTITY_LINE_SEGMENT = 0; static const int ENTITY_PWL_SEGMENT = 1; int type; hEntity h; -} Entity; +}; -typedef struct hPointTag { -} hPoint; +class hPoint { +public: + int v; +}; -typedef struct { +class Point { +public: hPoint h; -} Point; +}; -typedef struct hParamTag { -} hParam; +class hParam { +public: + int v; +}; -typedef struct { +class Param { +public: double val; hParam h; -} Param; +}; #endif diff --git a/solvespace.cpp b/solvespace.cpp index ad64dec..eb0cd9a 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -1,11 +1,20 @@ #include "solvespace.h" +template IdList; +template IdList; +template IdList; + SolveSpace SS; void SolveSpace::Init(void) { TW.Init(); GW.Init(); + req.Clear(); + entity.Clear(); + point.Clear(); + param.Clear(); + int i; for(i = 0; i < 20; i++) { TW.Printf("this is line number %d", i); diff --git a/solvespace.h b/solvespace.h index b66bd22..318315c 100644 --- a/solvespace.h +++ b/solvespace.h @@ -2,6 +2,17 @@ #ifndef __SOLVESPACE_H #define __SOLVESPACE_H +// Debugging functions +#define oops() do { dbp("oops at line %d, file %s", __LINE__, __FILE__); \ + exit(-1); } while(0) +#ifndef min +#define min(x, y) ((x) < (y) ? (x) : (y)) +#endif +#ifndef max +#define max(x, y) ((x) > (y) ? (x) : (y)) +#endif + +void dbp(char *str, ...); #include #include #include @@ -10,10 +21,6 @@ #include "ui.h" #include "sketch.h" -// Debugging functions -#define oops() do { dbp("oops at line %d, file %s", __LINE__, __FILE__); \ - exit(-1); } while(0) -void dbp(char *str, ...); void Invalidate(void); @@ -26,7 +33,8 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, double a41, double a42, double a43, double a44); -typedef struct { +class SolveSpace { +public: TextWindow TW; GraphicsWindow GW; @@ -36,7 +44,7 @@ typedef struct { IdList param; void Init(void); -} SolveSpace; +}; extern SolveSpace SS; diff --git a/ui.h b/ui.h index c0d315d..a477a2e 100644 --- a/ui.h +++ b/ui.h @@ -2,9 +2,10 @@ #ifndef __UI_H #define __UI_H -typedef struct { - static const int MAX_COLS = 200; - static const int MAX_ROWS = 500; +class TextWindow { +public: + static const int MAX_COLS = 150; + static const int MAX_ROWS = 300; #ifndef RGB #define RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16)) @@ -14,6 +15,12 @@ typedef struct { static const int COLOR_BG_CMDLINE = RGB( 0, 20, 80); static const int COLOR_FG_CMDLINE = RGB(255, 255, 255); + typedef struct { + int fg; + int bg; + } Color; + static const Color colors[]; + // The line with the user-typed command, that is currently being edited. char cmd[MAX_COLS]; int cmdInsert; @@ -27,10 +34,12 @@ typedef struct { static const int COLOR_NORMAL = 0; BYTE text[MAX_ROWS][MAX_COLS]; + typedef void LinkFunction(int link, DWORD v); struct { - int color; - int link; - DWORD data; + int color; + int link; + DWORD data; + LinkFunction *f; } meta[MAX_ROWS][MAX_COLS]; int row0, rows; @@ -46,9 +55,10 @@ typedef struct { // These are called by the platform-specific code. void KeyPressed(int c); bool IsHyperlink(int width, int height); -} TextWindow; +}; -typedef struct { +class GraphicsWindow { +public: // This table describes the top-level menus in the graphics winodw. typedef void MenuHandler(int id); typedef struct { @@ -85,7 +95,7 @@ typedef struct { void MouseLeftDoubleClick(double x, double y); void MouseMiddleDown(double x, double y); void MouseScroll(int delta); -} GraphicsWindow; +}; #endif diff --git a/util.cpp b/util.cpp index 3b4806c..547a375 100644 --- a/util.cpp +++ b/util.cpp @@ -24,8 +24,7 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, } -Vector Vector::Cross(Vector b) -{ +Vector Vector::Cross(Vector b) { Vector r; r.x = -(z*b.y) + (y*b.z); @@ -35,13 +34,11 @@ Vector Vector::Cross(Vector b) return r; } -double Vector::Dot(Vector b) -{ +double Vector::Dot(Vector b) { return (x*b.x + y*b.y + z*b.z); } -Vector Vector::RotatedAbout(Vector axis, double theta) -{ +Vector Vector::RotatedAbout(Vector axis, double theta) { double c = cos(theta); double s = sin(theta); @@ -62,13 +59,11 @@ Vector Vector::RotatedAbout(Vector axis, double theta) return r; } -double Vector::Magnitude(void) -{ +double Vector::Magnitude(void) { return sqrt(x*x + y*y + z*z); } -Vector Vector::ScaledBy(double v) -{ +Vector Vector::ScaledBy(double v) { Vector r; r.x = x * v; @@ -77,4 +72,3 @@ Vector Vector::ScaledBy(double v) return r; } - diff --git a/win32/w32main.cpp b/win32/w32main.cpp index 3fee7a0..9388a1e 100644 --- a/win32/w32main.cpp +++ b/win32/w32main.cpp @@ -25,7 +25,7 @@ HMENU SubMenus[100]; int ClientIsSmallerBy; -HFONT FixedFont; +HFONT FixedFont, LinkFont; void dbp(char *str, ...) { @@ -80,6 +80,15 @@ static void PaintTextWnd(HDC hdc) for(c = 0; c < SS.TW.MAX_COLS; c++) { char v = '0' + (c % 10); + int color = SS.TW.meta[rr][c].color; + SetTextColor(backDc, SS.TW.colors[color].fg); + SetBkColor(backDc, SS.TW.colors[color].bg); + + if(SS.TW.meta[rr][c].link) { + SelectObject(backDc, LinkFont); + } else { + SelectObject(backDc, FixedFont); + } TextOut(backDc, 4 + c*TEXT_WIDTH, (r-TextWndScrollPos)*TEXT_HEIGHT, (char *)&(SS.TW.text[rr][c]), 1); } @@ -107,11 +116,11 @@ void HandleTextWindowScrollBar(WPARAM wParam, LPARAM lParam) { int prevPos = TextWndScrollPos; switch(LOWORD(wParam)) { - case SB_LINEUP: - case SB_PAGEUP: TextWndScrollPos--; break; + case SB_LINEUP: TextWndScrollPos--; break; + case SB_PAGEUP: TextWndScrollPos -= 4; break; - case SB_LINEDOWN: - case SB_PAGEDOWN: TextWndScrollPos++; break; + case SB_LINEDOWN: TextWndScrollPos++; break; + case SB_PAGEDOWN: TextWndScrollPos += 4; break; case SB_TOP: TextWndScrollPos = 0; break; @@ -171,6 +180,30 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) break; } + case WM_LBUTTONDOWN: + case WM_MOUSEMOVE: { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + + // Find the corresponding character in the text buffer + int r = (y / TEXT_HEIGHT); + int c = (x / TEXT_WIDTH); + if(msg == WM_MOUSEMOVE && r >= TextWndRows) { + SetCursor(LoadCursor(NULL, IDC_ARROW)); + break; + } + r += TextWndScrollPos; + + if(msg == WM_MOUSEMOVE) { + if(SS.TW.meta[r][c].link) { + SetCursor(LoadCursor(NULL, IDC_HAND)); + } else { + SetCursor(LoadCursor(NULL, IDC_ARROW)); + } + } + break; + } + case WM_CHAR: SS.TW.KeyPressed(wParam); HandleTextWindowScrollBar(SB_BOTTOM, 0); @@ -230,7 +263,6 @@ static HGLRC CreateGlContext(HDC hdc) void Invalidate(void) { InvalidateRect(GraphicsWnd, NULL, FALSE); - InvalidateRect(TextWnd, NULL, FALSE); } LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam, @@ -375,7 +407,7 @@ static void CreateMainWindows(void) wc.lpfnWndProc = (WNDPROC)TextWndProc; wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszClassName = "TextWnd"; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hCursor = NULL; if(!RegisterClassEx(&wc)) oops(); // We get the desired Alt+Tab behaviour by specifying that the text @@ -418,8 +450,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, FixedFont = CreateFont(TEXT_HEIGHT-1, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, "Lucida Console"); + LinkFont = CreateFont(TEXT_HEIGHT-1, TEXT_WIDTH, 0, 0, FW_REGULAR, TRUE, + TRUE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FF_DONTCARE, "Lucida Console"); if(!FixedFont) FixedFont = (HFONT)GetStockObject(SYSTEM_FONT); + if(!LinkFont) + LinkFont = (HFONT)GetStockObject(SYSTEM_FONT); // Call in to the platform-independent code, and let them do their init SS.Init();