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

View File

@ -1,6 +1,16 @@
#include "solvespace.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) {
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) {

69
dsc.h
View File

@ -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 <class T, class H> struct IdList {
template <class T, class H>
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

View File

@ -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();
}

View File

@ -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

View File

@ -1,11 +1,20 @@
#include "solvespace.h"
template IdList<Request,hRequest>;
template IdList<Entity,hEntity>;
template IdList<Point,hPoint>;
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);

View File

@ -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 <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -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,hParam> param;
void Init(void);
} SolveSpace;
};
extern SolveSpace SS;

22
ui.h
View File

@ -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;
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

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;
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;
}

View File

@ -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();