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]
solver
Jonathan Westhues 2008-03-28 02:00:37 -08:00
parent e426fe8a53
commit f201d52247
10 changed files with 258 additions and 82 deletions

View File

@ -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. 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 HEADERS = ..\common\win32\freeze.h ui.h solvespace.h dsc.h sketch.h

View File

@ -1,6 +1,16 @@
#include "solvespace.h" #include "solvespace.h"
#include <stdarg.h> #include <stdarg.h>
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) { void TextWindow::Init(void) {
ClearScreen(); ClearScreen();
ClearCommand(); ClearCommand();
@ -37,34 +47,77 @@ void TextWindow::Printf(char *fmt, ...) {
} }
int color = COLOR_NORMAL; int color = COLOR_NORMAL;
int link = NOT_A_LINK;
DWORD data = 0;
LinkFunction *f = NULL;
c = 0; c = 0;
while(*fmt) { while(*fmt) {
char buf[1024];
if(*fmt == '%') { if(*fmt == '%') {
fmt++; fmt++;
if(*fmt == '\0') goto done; if(*fmt == '\0') goto done;
strcpy(buf, "");
switch(*fmt) { switch(*fmt) {
case 's': {
char *s = va_arg(vl, char *);
memcpy(&(text[r][c]), s, strlen(s));
c += strlen(s);
break;
}
case 'd': { case 'd': {
int v = va_arg(vl, int); int v = va_arg(vl, int);
sprintf((char *)&(text[r][c]), "%d", v); sprintf(buf, "%d", v);
c += strlen((char *)&(text[r][c]));
text[r][c] = ' ';
break; 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 '%': case '%':
text[r][c++] = '%'; strcpy(buf, "%");
break; break;
} }
} else { } else {
if(c >= MAX_COLS) goto done; buf[0] = *fmt;
text[r][c++] = *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++; fmt++;
} }
@ -84,7 +137,7 @@ void TextWindow::ClearCommand(void) {
void TextWindow::ProcessCommand(char *cmd) 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) { void TextWindow::KeyPressed(int c) {

69
dsc.h
View File

@ -5,9 +5,8 @@
typedef unsigned long DWORD; typedef unsigned long DWORD;
typedef unsigned char BYTE; typedef unsigned char BYTE;
typedef struct VectorTag Vector; class Vector {
public:
typedef struct VectorTag {
double x, y, z; double x, y, z;
Vector Cross(Vector b); Vector Cross(Vector b);
@ -16,26 +15,74 @@ typedef struct VectorTag {
double Magnitude(void); double Magnitude(void);
Vector ScaledBy(double v); Vector ScaledBy(double v);
} Vector; };
typedef struct { class Point2d {
public:
double x, y; double x, y;
} Point2d; };
template <class T, class H> struct IdList { template <class T, class H>
class IdList {
public:
typedef struct { typedef struct {
T v; T v;
H h;
int tag; int tag;
} Elem; } Elem;
Elem elem; Elem *elem;
int elems; int elems;
int elemsAllocated; int elemsAllocated;
void addAndAssignId(T *v); void AddAndAssignId(T *v) {
void removeTagged(void); 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 #endif

View File

@ -127,9 +127,17 @@ void GraphicsWindow::Paint(int w, int h) {
glClearDepth(1.0); glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLUquadricObj *quadObj; glBegin(GL_QUADS);
quadObj = gluNewQuadric(); glVertex3f(-200, -200, 0);
gluQuadricDrawStyle(quadObj, GLU_LINE); glVertex3f(-200, 200, 0);
gluSphere(quadObj, 300, 4, 4); 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();
} }

View File

@ -2,57 +2,67 @@
#ifndef __SKETCH_H #ifndef __SKETCH_H
#define __SKETCH_H #define __SKETCH_H
typedef struct hRequestTag hRequest; class hEntity;
typedef struct hEntityTag hEntity; class hPoint;
typedef struct hPointTag hPoint; class hRequest;
typedef struct hParamTag hParam; class hParam;
typedef struct hRequestTag { class hRequest {
public:
int v; int v;
hEntity entity(int i); hEntity entity(int i);
} hRequest; };
typedef struct { class Request {
public:
static const int REQUEST_LINE_SEGMENT = 0; static const int REQUEST_LINE_SEGMENT = 0;
static const int REQUEST_STEP_REPEAT_TRANSLATE = 1; static const int REQUEST_STEP_REPEAT_TRANSLATE = 1;
static const int REQUEST_STEP_REPEAT_TRANSLATE_SYM = 2; static const int REQUEST_STEP_REPEAT_TRANSLATE_SYM = 2;
int type; int type;
hRequest h; hRequest h;
} Request; };
typedef struct hEntityTag { class hEntity {
public:
int v; int v;
hRequest request(int i); hRequest request(int i);
hPoint point(int i); hPoint point(int i);
} hEntity; };
typedef struct { class Entity {
public:
static const int ENTITY_LINE_SEGMENT = 0; static const int ENTITY_LINE_SEGMENT = 0;
static const int ENTITY_PWL_SEGMENT = 1; static const int ENTITY_PWL_SEGMENT = 1;
int type; int type;
hEntity h; hEntity h;
} Entity; };
typedef struct hPointTag { class hPoint {
} hPoint; public:
int v;
};
typedef struct { class Point {
public:
hPoint h; hPoint h;
} Point; };
typedef struct hParamTag { class hParam {
} hParam; public:
int v;
};
typedef struct { class Param {
public:
double val; double val;
hParam h; hParam h;
} Param; };
#endif #endif

View File

@ -1,11 +1,20 @@
#include "solvespace.h" #include "solvespace.h"
template IdList<Request,hRequest>;
template IdList<Entity,hEntity>;
template IdList<Point,hPoint>;
SolveSpace SS; SolveSpace SS;
void SolveSpace::Init(void) { void SolveSpace::Init(void) {
TW.Init(); TW.Init();
GW.Init(); GW.Init();
req.Clear();
entity.Clear();
point.Clear();
param.Clear();
int i; int i;
for(i = 0; i < 20; i++) { for(i = 0; i < 20; i++) {
TW.Printf("this is line number %d", i); TW.Printf("this is line number %d", i);

View File

@ -2,6 +2,17 @@
#ifndef __SOLVESPACE_H #ifndef __SOLVESPACE_H
#define __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 <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -10,10 +21,6 @@
#include "ui.h" #include "ui.h"
#include "sketch.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); 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); double a41, double a42, double a43, double a44);
typedef struct { class SolveSpace {
public:
TextWindow TW; TextWindow TW;
GraphicsWindow GW; GraphicsWindow GW;
@ -36,7 +44,7 @@ typedef struct {
IdList<Param,hParam> param; IdList<Param,hParam> param;
void Init(void); void Init(void);
} SolveSpace; };
extern SolveSpace SS; extern SolveSpace SS;

28
ui.h
View File

@ -2,9 +2,10 @@
#ifndef __UI_H #ifndef __UI_H
#define __UI_H #define __UI_H
typedef struct { class TextWindow {
static const int MAX_COLS = 200; public:
static const int MAX_ROWS = 500; static const int MAX_COLS = 150;
static const int MAX_ROWS = 300;
#ifndef RGB #ifndef RGB
#define RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16)) #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_BG_CMDLINE = RGB( 0, 20, 80);
static const int COLOR_FG_CMDLINE = RGB(255, 255, 255); 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. // The line with the user-typed command, that is currently being edited.
char cmd[MAX_COLS]; char cmd[MAX_COLS];
int cmdInsert; int cmdInsert;
@ -27,10 +34,12 @@ typedef struct {
static const int COLOR_NORMAL = 0; static const int COLOR_NORMAL = 0;
BYTE text[MAX_ROWS][MAX_COLS]; BYTE text[MAX_ROWS][MAX_COLS];
typedef void LinkFunction(int link, DWORD v);
struct { struct {
int color; int color;
int link; int link;
DWORD data; DWORD data;
LinkFunction *f;
} meta[MAX_ROWS][MAX_COLS]; } meta[MAX_ROWS][MAX_COLS];
int row0, rows; int row0, rows;
@ -46,9 +55,10 @@ typedef struct {
// These are called by the platform-specific code. // These are called by the platform-specific code.
void KeyPressed(int c); void KeyPressed(int c);
bool IsHyperlink(int width, int height); bool IsHyperlink(int width, int height);
} TextWindow; };
typedef struct { class GraphicsWindow {
public:
// This table describes the top-level menus in the graphics winodw. // This table describes the top-level menus in the graphics winodw.
typedef void MenuHandler(int id); typedef void MenuHandler(int id);
typedef struct { typedef struct {
@ -85,7 +95,7 @@ typedef struct {
void MouseLeftDoubleClick(double x, double y); void MouseLeftDoubleClick(double x, double y);
void MouseMiddleDown(double x, double y); void MouseMiddleDown(double x, double y);
void MouseScroll(int delta); void MouseScroll(int delta);
} GraphicsWindow; };
#endif #endif

View File

@ -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; Vector r;
r.x = -(z*b.y) + (y*b.z); r.x = -(z*b.y) + (y*b.z);
@ -35,13 +34,11 @@ Vector Vector::Cross(Vector b)
return r; return r;
} }
double Vector::Dot(Vector b) double Vector::Dot(Vector b) {
{
return (x*b.x + y*b.y + z*b.z); 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 c = cos(theta);
double s = sin(theta); double s = sin(theta);
@ -62,13 +59,11 @@ Vector Vector::RotatedAbout(Vector axis, double theta)
return r; return r;
} }
double Vector::Magnitude(void) double Vector::Magnitude(void) {
{
return sqrt(x*x + y*y + z*z); return sqrt(x*x + y*y + z*z);
} }
Vector Vector::ScaledBy(double v) Vector Vector::ScaledBy(double v) {
{
Vector r; Vector r;
r.x = x * v; r.x = x * v;
@ -77,4 +72,3 @@ Vector Vector::ScaledBy(double v)
return r; return r;
} }

View File

@ -25,7 +25,7 @@ HMENU SubMenus[100];
int ClientIsSmallerBy; int ClientIsSmallerBy;
HFONT FixedFont; HFONT FixedFont, LinkFont;
void dbp(char *str, ...) void dbp(char *str, ...)
{ {
@ -80,6 +80,15 @@ static void PaintTextWnd(HDC hdc)
for(c = 0; c < SS.TW.MAX_COLS; c++) { for(c = 0; c < SS.TW.MAX_COLS; c++) {
char v = '0' + (c % 10); 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, TextOut(backDc, 4 + c*TEXT_WIDTH, (r-TextWndScrollPos)*TEXT_HEIGHT,
(char *)&(SS.TW.text[rr][c]), 1); (char *)&(SS.TW.text[rr][c]), 1);
} }
@ -107,11 +116,11 @@ void HandleTextWindowScrollBar(WPARAM wParam, LPARAM lParam)
{ {
int prevPos = TextWndScrollPos; int prevPos = TextWndScrollPos;
switch(LOWORD(wParam)) { switch(LOWORD(wParam)) {
case SB_LINEUP: case SB_LINEUP: TextWndScrollPos--; break;
case SB_PAGEUP: TextWndScrollPos--; break; case SB_PAGEUP: TextWndScrollPos -= 4; break;
case SB_LINEDOWN: case SB_LINEDOWN: TextWndScrollPos++; break;
case SB_PAGEDOWN: TextWndScrollPos++; break; case SB_PAGEDOWN: TextWndScrollPos += 4; break;
case SB_TOP: TextWndScrollPos = 0; break; case SB_TOP: TextWndScrollPos = 0; break;
@ -171,6 +180,30 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
break; 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: case WM_CHAR:
SS.TW.KeyPressed(wParam); SS.TW.KeyPressed(wParam);
HandleTextWindowScrollBar(SB_BOTTOM, 0); HandleTextWindowScrollBar(SB_BOTTOM, 0);
@ -230,7 +263,6 @@ static HGLRC CreateGlContext(HDC hdc)
void Invalidate(void) void Invalidate(void)
{ {
InvalidateRect(GraphicsWnd, NULL, FALSE); InvalidateRect(GraphicsWnd, NULL, FALSE);
InvalidateRect(TextWnd, NULL, FALSE);
} }
LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam, LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
@ -375,7 +407,7 @@ static void CreateMainWindows(void)
wc.lpfnWndProc = (WNDPROC)TextWndProc; wc.lpfnWndProc = (WNDPROC)TextWndProc;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszClassName = "TextWnd"; wc.lpszClassName = "TextWnd";
wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hCursor = NULL;
if(!RegisterClassEx(&wc)) oops(); if(!RegisterClassEx(&wc)) oops();
// We get the desired Alt+Tab behaviour by specifying that the text // 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, FixedFont = CreateFont(TEXT_HEIGHT-1, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE,
FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FF_DONTCARE, "Lucida Console"); 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) if(!FixedFont)
FixedFont = (HFONT)GetStockObject(SYSTEM_FONT); 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 // Call in to the platform-independent code, and let them do their init
SS.Init(); SS.Init();