Tear apart the text window, mostly to beautify things. The

foreground and background colours are now specified separately, and
it's possible to insert half-line spaces. So now I have a window
that lets me show/hide groups, and select the active one.

[git-p4: depot-paths = "//depot/solvespace/": change = 1695]
This commit is contained in:
Jonathan Westhues 2008-04-27 23:18:39 -08:00
parent 01cff278bd
commit 598d456d8d
8 changed files with 185 additions and 121 deletions

View File

@ -2,7 +2,7 @@
char *Constraint::DescriptionString(void) { char *Constraint::DescriptionString(void) {
static char ret[1024]; static char ret[1024];
sprintf(ret, "c%04x", h.v); sprintf(ret, "c%03x", h.v);
return ret; return ret;
} }

View File

@ -27,6 +27,10 @@ void Constraint::LineDrawOrGetDistance(Vector a, Vector b) {
void Constraint::DrawOrGetDistance(Vector *labelPos) { void Constraint::DrawOrGetDistance(Vector *labelPos) {
if(!SS.GW.showConstraints) return; if(!SS.GW.showConstraints) return;
Group *g = SS.GetGroup(group);
// If the group is hidden, then the constraints are hidden and not
// able to be selected.
if(!(g->visible)) return;
// Unit vectors that describe our current view of the scene. // Unit vectors that describe our current view of the scene.
Vector gr = SS.GW.projRight; Vector gr = SS.GW.projRight;

View File

@ -300,6 +300,11 @@ double Entity::GetDistance(Point2d mp) {
} }
void Entity::DrawOrGetDistance(int order) { void Entity::DrawOrGetDistance(int order) {
Group *g = SS.GetGroup(group);
// If an entity is invisible, then it doesn't get shown, and it doesn't
// contribute a distance for the selection, but it still generates edges.
if(!(g->visible) && !dogd.edges) return;
glxColor3d(1, 1, 1); glxColor3d(1, 1, 1);
switch(type) { switch(type) {

View File

@ -226,7 +226,6 @@ void GraphicsWindow::EnsureValidActives(void) {
activeWorkplane = Entity::FREE_IN_3D; activeWorkplane = Entity::FREE_IN_3D;
change = true; change = true;
} }
if(change) SS.TW.Show();
bool in3d = (activeWorkplane.v == Entity::FREE_IN_3D.v); bool in3d = (activeWorkplane.v == Entity::FREE_IN_3D.v);
CheckMenuById(MNU_FREE_IN_3D, in3d); CheckMenuById(MNU_FREE_IN_3D, in3d);

View File

@ -45,9 +45,9 @@ void Group::MenuGroup(int id) {
char *Group::DescriptionString(void) { char *Group::DescriptionString(void) {
static char ret[100]; static char ret[100];
if(name.str[0]) { if(name.str[0]) {
sprintf(ret, "g%04x-%s", h.v, name.str); sprintf(ret, "g%03x-%s", h.v, name.str);
} else { } else {
sprintf(ret, "g%04x-(unnamed)", h.v); sprintf(ret, "g%03x-(unnamed)", h.v);
} }
return ret; return ret;
} }
@ -135,6 +135,8 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz) {
} }
void Group::Draw(void) { void Group::Draw(void) {
if(!visible) return;
edges.l.Clear(); edges.l.Clear();
int i; int i;
for(i = 0; i < SS.entity.n; i++) { for(i = 0; i < SS.entity.n; i++) {

View File

@ -1,19 +1,22 @@
#include "solvespace.h" #include "solvespace.h"
#include <stdarg.h> #include <stdarg.h>
#define COLOR_BG_HEADER RGB(50, 20, 50) const TextWindow::Color TextWindow::fgColors[] = {
const TextWindow::Color TextWindow::colors[] = { { 'd', RGB(255, 255, 255) },
{ 'd', RGB(255, 255, 255), COLOR_BG_DEFAULT, }, // default { 'l', RGB(100, 100, 255) },
{ 'l', RGB(100, 100, 255), COLOR_BG_DEFAULT, }, // link { 't', RGB(255, 200, 0) },
{ 'h', RGB(170, 0, 0) },
// These are for the header { 's', RGB( 40, 255, 40) },
{ 'D', RGB(255, 255, 255), COLOR_BG_HEADER, }, // default { 'm', RGB(200, 200, 0) },
{ 'H', RGB(170, 0, 0), COLOR_BG_HEADER, }, // hidden { 'r', RGB( 0, 0, 0) },
{ 'S', RGB( 40, 255, 40), COLOR_BG_HEADER, }, // shown { 0, 0 },
{ 'M', RGB(200, 200, 0), COLOR_BG_HEADER, }, // mixed h/s };
{ 'T', RGB(255, 200, 40), COLOR_BG_HEADER, }, // title const TextWindow::Color TextWindow::bgColors[] = {
{ 'd', RGB( 0, 0, 0) },
{ 0, 0, 0 }, { 't', RGB( 30, 10, 30) },
{ 'a', RGB( 25, 25, 25) },
{ 'r', RGB(255, 255, 255) },
{ 0, 0 },
}; };
void TextWindow::Init(void) { void TextWindow::Init(void) {
@ -28,14 +31,16 @@ void TextWindow::ClearScreen(void) {
for(i = 0; i < MAX_ROWS; i++) { for(i = 0; i < MAX_ROWS; i++) {
for(j = 0; j < MAX_COLS; j++) { for(j = 0; j < MAX_COLS; j++) {
text[i][j] = ' '; text[i][j] = ' ';
meta[i][j].color = 'd'; meta[i][j].fg = 'd';
meta[i][j].bg = 'd';
meta[i][j].link = NOT_A_LINK; meta[i][j].link = NOT_A_LINK;
} }
top[i] = i*2;
} }
rows = 0; rows = 0;
} }
void TextWindow::Printf(char *fmt, ...) { void TextWindow::Printf(bool halfLine, char *fmt, ...) {
va_list vl; va_list vl;
va_start(vl, fmt); va_start(vl, fmt);
@ -43,6 +48,7 @@ void TextWindow::Printf(char *fmt, ...) {
int r, c; int r, c;
r = rows; r = rows;
top[r] = (r == 0) ? 0 : (top[r-1] + (halfLine ? 3 : 2));
rows++; rows++;
for(c = 0; c < MAX_COLS; c++) { for(c = 0; c < MAX_COLS; c++) {
@ -50,7 +56,7 @@ void TextWindow::Printf(char *fmt, ...) {
meta[r][c].link = NOT_A_LINK; meta[r][c].link = NOT_A_LINK;
} }
int color = 'd'; int fg = 'd', bg = 'd';
int link = NOT_A_LINK; int link = NOT_A_LINK;
DWORD data = 0; DWORD data = 0;
LinkFunction *f = NULL; LinkFunction *f = NULL;
@ -80,23 +86,31 @@ void TextWindow::Printf(char *fmt, ...) {
break; break;
} }
case 'E': case 'E':
color = 'd'; fg = 'd';
// leave the background, though
link = NOT_A_LINK; link = NOT_A_LINK;
data = 0; data = 0;
f = NULL; f = NULL;
break; break;
case 'C': case 'F':
case 'B': {
int color;
if(fmt[1] == '\0') goto done; if(fmt[1] == '\0') goto done;
fmt++; if(fmt[1] == 'p') {
if(*fmt == 'p') {
color = va_arg(vl, int); color = va_arg(vl, int);
} else { } else {
color = *fmt; color = fmt[1];
} }
if(color < 0 || color > 255) color = 0; if(color < 0 || color > 255) color = 0;
if(*fmt == 'F') {
fg = color;
} else {
bg = color;
}
fmt++;
break; break;
}
case 'L': case 'L':
if(fmt[1] == '\0') goto done; if(fmt[1] == '\0') goto done;
fmt++; fmt++;
@ -123,7 +137,8 @@ void TextWindow::Printf(char *fmt, ...) {
for(unsigned i = 0; i < strlen(buf); i++) { for(unsigned i = 0; i < strlen(buf); i++) {
if(c >= MAX_COLS) goto done; if(c >= MAX_COLS) goto done;
text[r][c] = buf[i]; text[r][c] = buf[i];
meta[r][c].color = color; meta[r][c].fg = fg;
meta[r][c].bg = bg;
meta[r][c].link = link; meta[r][c].link = link;
meta[r][c].data = data; meta[r][c].data = data;
meta[r][c].f = f; meta[r][c].f = f;
@ -133,7 +148,8 @@ void TextWindow::Printf(char *fmt, ...) {
fmt++; fmt++;
} }
while(c < MAX_COLS) { while(c < MAX_COLS) {
meta[r][c].color = color; meta[r][c].fg = fg;
meta[r][c].bg = bg;
c++; c++;
} }
@ -149,8 +165,8 @@ void TextWindow::Show(void) {
if(SS.GW.pendingDescription) { if(SS.GW.pendingDescription) {
// A pending operation (that must be completed with the mouse in // A pending operation (that must be completed with the mouse in
// the graphics window) will preempt our usual display. // the graphics window) will preempt our usual display.
Printf(""); Printf(false, "");
Printf("%s", SS.GW.pendingDescription); Printf(false, "%s", SS.GW.pendingDescription);
} else { } else {
switch(shown->screen) { switch(shown->screen) {
default: default:
@ -201,7 +217,7 @@ void TextWindow::ShowHeader(void) {
SS.GW.EnsureValidActives(); SS.GW.EnsureValidActives();
if(SS.GW.pendingDescription) { if(SS.GW.pendingDescription) {
Printf(" %CT group:%s", Printf(false, " %Bt%Ft group:%s",
SS.group.FindById(SS.GW.activeGroup)->DescriptionString()); SS.group.FindById(SS.GW.activeGroup)->DescriptionString());
} else { } else {
// Navigation buttons // Navigation buttons
@ -211,35 +227,35 @@ void TextWindow::ShowHeader(void) {
} else { } else {
cd = SS.GetEntity(SS.GW.activeWorkplane)->DescriptionString(); cd = SS.GetEntity(SS.GW.activeWorkplane)->DescriptionString();
} }
Printf(" %Lb%f<<%E %Lh%fhome%E %CT workplane:%CD %s", Printf(false, " %Lb%f<<%E %Lh%fhome%E %Bt%Ft workplane:%Fd %s",
(&TextWindow::ScreenNavigation), (&TextWindow::ScreenNavigation),
(&TextWindow::ScreenNavigation), (&TextWindow::ScreenNavigation),
cd); cd);
} }
int datumColor; int datumColor;
if(SS.GW.showWorkplanes && SS.GW.showAxes && SS.GW.showPoints) { if(SS.GW.showWorkplanes && SS.GW.showAxes && SS.GW.showPoints) {
datumColor = 'S'; // shown datumColor = 's'; // shown
} else if(!(SS.GW.showWorkplanes || SS.GW.showAxes || SS.GW.showPoints)) { } else if(!(SS.GW.showWorkplanes || SS.GW.showAxes || SS.GW.showPoints)) {
datumColor = 'H'; // hidden datumColor = 'h'; // hidden
} else { } else {
datumColor = 'M'; // mixed datumColor = 'm'; // mixed
} }
#define hs(b) ((b) ? 'S' : 'H') #define hs(b) ((b) ? 's' : 'h')
Printf("%CTshow: " Printf(false, "%Bt%Ftshow: "
"%Cp%Ll%D%fworkplanes%E%CT " "%Fp%Ll%D%fworkplanes%E "
"%Cp%Ll%D%faxes%E%CT " "%Fp%Ll%D%fvectors%E "
"%Cp%Ll%D%fpoints%E%CT " "%Fp%Ll%D%fpoints%E "
"%Cp%Ll%fany-datum%E%CT", "%Fp%Ll%fany-datum%E",
hs(SS.GW.showWorkplanes), (DWORD)&(SS.GW.showWorkplanes), &(SS.GW.ToggleBool), hs(SS.GW.showWorkplanes), (DWORD)&(SS.GW.showWorkplanes), &(SS.GW.ToggleBool),
hs(SS.GW.showAxes), (DWORD)&(SS.GW.showAxes), &(SS.GW.ToggleBool), hs(SS.GW.showAxes), (DWORD)&(SS.GW.showAxes), &(SS.GW.ToggleBool),
hs(SS.GW.showPoints), (DWORD)&(SS.GW.showPoints), &(SS.GW.ToggleBool), hs(SS.GW.showPoints), (DWORD)&(SS.GW.showPoints), &(SS.GW.ToggleBool),
datumColor, &(SS.GW.ToggleAnyDatumShown) datumColor, &(SS.GW.ToggleAnyDatumShown)
); );
Printf("%CT " Printf(false, "%Bt%Ft "
"%Cp%Ll%D%fall-groups%E%CT " "%Fp%Ll%D%fall-groups%E "
"%Cp%Ll%D%fconstraints%E%CT", "%Fp%Ll%D%fconstraints%E",
hs(SS.GW.showAllGroups), (DWORD)(&SS.GW.showAllGroups), &(SS.GW.ToggleBool), hs(SS.GW.showAllGroups), (DWORD)(&SS.GW.showAllGroups), &(SS.GW.ToggleBool),
hs(SS.GW.showConstraints), (DWORD)(&SS.GW.showConstraints), &(SS.GW.ToggleBool) hs(SS.GW.showConstraints), (DWORD)(&SS.GW.showConstraints), &(SS.GW.ToggleBool)
); );
@ -253,14 +269,48 @@ void TextWindow::ScreenSelectGroup(int link, DWORD v) {
SS.TW.Show(); SS.TW.Show();
} }
void TextWindow::ScreenToggleGroupShown(int link, DWORD v) {
hGroup hg = { v };
Group *g = SS.GetGroup(hg);
g->visible = !(g->visible);
InvalidateGraphics();
SS.TW.Show();
}
void TextWindow::ScreenActivateGroup(int link, DWORD v) {
hGroup hg = { v };
Group *g = SS.GetGroup(hg);
g->visible = true;
SS.GW.activeGroup.v = v;
InvalidateGraphics();
SS.TW.Show();
}
void TextWindow::ShowListOfGroups(void) { void TextWindow::ShowListOfGroups(void) {
Printf("%Cd[[all groups in sketch follow]]%E"); Printf(true, "%Ftactive show group-name%E");
int i; int i;
for(i = 0; i < SS.group.n; i++) { for(i = 0; i < SS.group.n; i++) {
char *s;
Group *g = &(SS.group.elem[i]); Group *g = &(SS.group.elem[i]);
s = g->DescriptionString(); char *s = g->DescriptionString();
Printf(" %Cl%Ll%D%f%s%E", bool active = (g->h.v == SS.GW.activeGroup.v);
bool shown = g->visible;
bool ref = (g->h.v == Group::HGROUP_REFERENCES.v);
Printf(false, "%Bp%Fd "
"%Fp%D%f%s%Ll%s%E%s "
"%Fp%D%f%Ll%s%E%s "
"%Fl%Ll%D%f%s",
// Alternate between light and dark backgrounds, for readability
(i & 1) ? 'd' : 'a',
// Link that activates the group
active ? 's' : 'h', g->h.v, (&TextWindow::ScreenActivateGroup),
active ? "yes" : (ref ? " " : ""),
active ? "" : (ref ? "" : "no"),
active ? "" : " ",
// Link that hides or shows the group
shown ? 's' : 'h', g->h.v, (&TextWindow::ScreenToggleGroupShown),
shown ? "yes" : "no",
shown ? "" : " ",
// Link to a screen that gives more details on the group
g->h.v, (&TextWindow::ScreenSelectGroup), s); g->h.v, (&TextWindow::ScreenSelectGroup), s);
} }
} }
@ -274,10 +324,6 @@ void TextWindow::ScreenSelectConstraint(int link, DWORD v) {
SS.TW.Show(); SS.TW.Show();
} }
void TextWindow::ScreenActivateGroup(int link, DWORD v) {
SS.GW.activeGroup.v = v;
SS.TW.Show();
}
void TextWindow::ScreenSelectRequest(int link, DWORD v) { void TextWindow::ScreenSelectRequest(int link, DWORD v) {
SS.TW.OneScreenForward(); SS.TW.OneScreenForward();
@ -288,40 +334,45 @@ void TextWindow::ScreenSelectRequest(int link, DWORD v) {
} }
void TextWindow::ShowGroupInfo(void) { void TextWindow::ShowGroupInfo(void) {
Group *g = SS.group.FindById(shown->group); Group *g = SS.group.FindById(shown->group);
Printf("%Cd[[group %s]]", g->DescriptionString()); char *s;
if(SS.GW.activeGroup.v == shown->group.v) { if(SS.GW.activeGroup.v == shown->group.v) {
Printf("%Cd[[this is the active group]]"); s = "active ";
} else if(shown->group.v == Group::HGROUP_REFERENCES.v) { } else if(shown->group.v == Group::HGROUP_REFERENCES.v) {
Printf("%Cd[[this group contains the references]]"); s = "special ";
} else { } else {
Printf("%Cd[[not active; %Cl%Ll%D%factivate group%E%Cd]]", s = "";
g->h.v, (&TextWindow::ScreenActivateGroup));
} }
Printf("%Cd[[requests in group]]%E"); Printf(true, "%Ft%sgroup %E%s", s, g->DescriptionString());
Printf(true, "%Ftrequests in group");
int i; int i, a = 0;
for(i = 0; i < SS.request.n; i++) { for(i = 0; i < SS.request.n; i++) {
Request *r = &(SS.request.elem[i]); Request *r = &(SS.request.elem[i]);
if(r->group.v == shown->group.v) { if(r->group.v == shown->group.v) {
char *s = r->DescriptionString(); char *s = r->DescriptionString();
Printf(" %Cl%Ll%D%f%s%E", Printf(false, "%Bp %Fl%Ll%D%f%s%E",
(a & 1) ? 'd' : 'a',
r->h.v, (&TextWindow::ScreenSelectRequest), s); r->h.v, (&TextWindow::ScreenSelectRequest), s);
a++;
} }
} }
if(SS.request.n == 0) Printf(" (none)"); if(a == 0) Printf(false, "%Ba (none)");
Printf(""); a = 0;
Printf("[[constraints in group]]"); Printf(true, "%Ftconstraints in group");
for(i = 0; i < SS.constraint.n; i++) { for(i = 0; i < SS.constraint.n; i++) {
Constraint *c = &(SS.constraint.elem[i]); Constraint *c = &(SS.constraint.elem[i]);
if(c->group.v == shown->group.v) { if(c->group.v == shown->group.v) {
char *s = c->DescriptionString(); char *s = c->DescriptionString();
Printf(" %Cl%Ll%D%f%s%E", Printf(false, "%Bp %Fl%Ll%D%f%s%E",
(a & 1) ? 'd' : 'a',
c->h.v, (&TextWindow::ScreenSelectConstraint), s); c->h.v, (&TextWindow::ScreenSelectConstraint), s);
a++;
} }
} }
if(a == 0) Printf(false, "%Ba (none)");
} }
void TextWindow::ShowRequestInfo(void) { void TextWindow::ShowRequestInfo(void) {
@ -334,13 +385,13 @@ void TextWindow::ShowRequestInfo(void) {
case Request::LINE_SEGMENT: s = "line segment"; break; case Request::LINE_SEGMENT: s = "line segment"; break;
default: oops(); default: oops();
} }
Printf("%Cd[[request for %s]]%E", s); Printf(false, "[[request for %s]]", s);
} }
void TextWindow::ShowConstraintInfo(void) { void TextWindow::ShowConstraintInfo(void) {
Constraint *c = SS.GetConstraint(shown->constraint); Constraint *c = SS.GetConstraint(shown->constraint);
Printf("[[constraint]]"); Printf(false, "[[constraint]]");
} }

21
ui.h
View File

@ -10,33 +10,30 @@ public:
#ifndef RGB #ifndef RGB
#define RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16)) #define RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16))
#endif #endif
static const int COLOR_BG_DEFAULT = RGB( 15, 15, 0);
typedef struct { typedef struct {
char c; char c;
int fg; int color;
int bg;
} Color; } Color;
static const Color colors[]; static const Color fgColors[];
static const Color bgColors[];
// The rest of the window, text displayed in response to typed commands;
// some of this might do something if you click on it.
static const int NOT_A_LINK = 0;
BYTE text[MAX_ROWS][MAX_COLS]; BYTE text[MAX_ROWS][MAX_COLS];
typedef void LinkFunction(int link, DWORD v); typedef void LinkFunction(int link, DWORD v);
static const int NOT_A_LINK = 0;
struct { struct {
int color; char fg;
char bg;
int link; int link;
DWORD data; DWORD data;
LinkFunction *f; LinkFunction *f;
} meta[MAX_ROWS][MAX_COLS]; } meta[MAX_ROWS][MAX_COLS];
int top[MAX_ROWS]; // in half-line units, or -1 for unused
int rows; int rows;
void Init(void); void Init(void);
void Printf(char *fmt, ...); void Printf(bool half, char *fmt, ...);
void ClearScreen(void); void ClearScreen(void);
void Show(void); void Show(void);
@ -71,6 +68,8 @@ public:
void OneScreenForward(void); void OneScreenForward(void);
static void ScreenSelectGroup(int link, DWORD v); static void ScreenSelectGroup(int link, DWORD v);
static void ScreenActivateGroup(int link, DWORD v); static void ScreenActivateGroup(int link, DWORD v);
static void ScreenToggleGroupShown(int link, DWORD v);
static void ScreenSelectRequest(int link, DWORD v); static void ScreenSelectRequest(int link, DWORD v);
static void ScreenSelectConstraint(int link, DWORD v); static void ScreenSelectConstraint(int link, DWORD v);
static void ScreenNavigation(int link, DWORD v); static void ScreenNavigation(int link, DWORD v);

View File

@ -13,19 +13,15 @@
#include "freeze.h" #include "freeze.h"
#define MIN_COLS 45 #define MIN_COLS 45
#define TEXT_HEIGHT 18 #define TEXT_HEIGHT 20
#define TEXT_WIDTH 9 #define TEXT_WIDTH 9
// There's a half-line offset between the header and the rest of the window
#define OFFSET_LINE 3
#define OFFSET_HEIGHT 9
HINSTANCE Instance; HINSTANCE Instance;
HWND TextWnd; HWND TextWnd;
HWND TextWndScrollBar; HWND TextWndScrollBar;
int TextWndScrollPos; int TextWndScrollPos; // The scrollbar position, in half-row units
int TextWndRows; int TextWndHalfRows; // The height of our window, in half-row units
HWND GraphicsWnd; HWND GraphicsWnd;
HWND GraphicsEditControl; HWND GraphicsEditControl;
@ -95,14 +91,18 @@ static void PaintTextWnd(HDC hdc)
static HBRUSH FillBrush; static HBRUSH FillBrush;
if(!MadeBrushes) { if(!MadeBrushes) {
// Generate the color table. // Generate the color table.
for(i = 0; SS.TW.colors[i].c != 0; i++) { for(i = 0; SS.TW.fgColors[i].c != 0; i++) {
int c = SS.TW.colors[i].c; int c = SS.TW.fgColors[i].c;
if(c < 0 || c > 255) oops(); if(c < 0 || c > 255) oops();
BgColor[c] = SS.TW.colors[i].bg; FgColor[c] = SS.TW.fgColors[i].color;
FgColor[c] = SS.TW.colors[i].fg; }
for(i = 0; SS.TW.bgColors[i].c != 0; i++) {
int c = SS.TW.bgColors[i].c;
if(c < 0 || c > 255) oops();
BgColor[c] = SS.TW.bgColors[i].color;
BgBrush[c] = CreateSolidBrush(BgColor[c]); BgBrush[c] = CreateSolidBrush(BgColor[c]);
} }
FillBrush = CreateSolidBrush(SS.TW.COLOR_BG_DEFAULT); FillBrush = CreateSolidBrush(RGB(0, 0, 0));
MadeBrushes = TRUE; MadeBrushes = TRUE;
} }
@ -118,12 +118,13 @@ static void PaintTextWnd(HDC hdc)
FillRect(backDc, &rect, FillBrush); FillRect(backDc, &rect, FillBrush);
SelectObject(backDc, FixedFont); SelectObject(backDc, FixedFont);
SetBkColor(backDc, SS.TW.COLOR_BG_DEFAULT); SetBkColor(backDc, RGB(0, 0, 0));
int rows = height / TEXT_HEIGHT; int halfRows = height / (TEXT_HEIGHT/2);
TextWndRows = rows; TextWndHalfRows = halfRows;
TextWndScrollPos = min(TextWndScrollPos, SS.TW.rows - rows); int bottom = SS.TW.top[SS.TW.rows-1] + 2;
TextWndScrollPos = min(TextWndScrollPos, bottom - halfRows);
TextWndScrollPos = max(TextWndScrollPos, 0); TextWndScrollPos = max(TextWndScrollPos, 0);
// Let's set up the scroll bar first // Let's set up the scroll bar first
@ -132,20 +133,22 @@ static void PaintTextWnd(HDC hdc)
si.cbSize = sizeof(si); si.cbSize = sizeof(si);
si.fMask = SIF_DISABLENOSCROLL | SIF_ALL; si.fMask = SIF_DISABLENOSCROLL | SIF_ALL;
si.nMin = 0; si.nMin = 0;
si.nMax = SS.TW.rows - 1; si.nMax = SS.TW.top[SS.TW.rows - 1] + 1;
si.nPos = TextWndScrollPos; si.nPos = TextWndScrollPos;
si.nPage = rows; si.nPage = halfRows;
SetScrollInfo(TextWndScrollBar, SB_CTL, &si, TRUE); SetScrollInfo(TextWndScrollBar, SB_CTL, &si, TRUE);
int r, c; int r, c;
for(r = TextWndScrollPos; r < (TextWndScrollPos+rows); r++) { for(r = 0; r < SS.TW.rows; r++) {
if(r < 0) continue; int top = SS.TW.top[r];
if(r >= SS.TW.MAX_ROWS) continue; if(top < (TextWndScrollPos-1)) continue;
if(top > TextWndScrollPos+halfRows) break;
for(c = 0; c < min((width/TEXT_WIDTH)+1, SS.TW.MAX_COLS); c++) { for(c = 0; c < min((width/TEXT_WIDTH)+1, SS.TW.MAX_COLS); c++) {
int color = SS.TW.meta[r][c].color; int fg = SS.TW.meta[r][c].fg;
SetTextColor(backDc, FgColor[color]); int bg = SS.TW.meta[r][c].bg;
SetBkColor(backDc, BgColor[color]); SetTextColor(backDc, FgColor[fg]);
SetBkColor(backDc, BgColor[bg]);
if(SS.TW.meta[r][c].link) { if(SS.TW.meta[r][c].link) {
SelectObject(backDc, LinkFont); SelectObject(backDc, LinkFont);
@ -154,15 +157,14 @@ static void PaintTextWnd(HDC hdc)
} }
int x = 4 + c*TEXT_WIDTH; int x = 4 + c*TEXT_WIDTH;
int y = (r-TextWndScrollPos)*TEXT_HEIGHT + 1 + int y = (top-TextWndScrollPos)*(TEXT_HEIGHT/2);
(r >= OFFSET_LINE ? OFFSET_HEIGHT : 0);
RECT a; RECT a;
a.left = x; a.right = x+TEXT_WIDTH; a.left = x; a.right = x+TEXT_WIDTH;
a.top = y; a.bottom = y+TEXT_HEIGHT; a.top = y; a.bottom = y+TEXT_HEIGHT;
FillRect(backDc, &a, BgBrush[color]); FillRect(backDc, &a, BgBrush[bg]);
TextOut(backDc, x, y, (char *)&(SS.TW.text[r][c]), 1); TextOut(backDc, x, y+2, (char *)&(SS.TW.text[r][c]), 1);
} }
} }
@ -189,8 +191,9 @@ void HandleTextWindowScrollBar(WPARAM wParam, LPARAM lParam)
case SB_THUMBTRACK: case SB_THUMBTRACK:
case SB_THUMBPOSITION: TextWndScrollPos = HIWORD(wParam); break; case SB_THUMBPOSITION: TextWndScrollPos = HIWORD(wParam); break;
} }
TextWndScrollPos = max(0, TextWndScrollPos); int bottom = SS.TW.top[SS.TW.rows-1] + 2;
TextWndScrollPos = min(SS.TW.rows - TextWndRows, TextWndScrollPos); TextWndScrollPos = min(TextWndScrollPos, bottom - TextWndHalfRows);
TextWndScrollPos = max(TextWndScrollPos, 0);
if(prevPos != TextWndScrollPos) { if(prevPos != TextWndScrollPos) {
SCROLLINFO si; SCROLLINFO si;
si.cbSize = sizeof(si); si.cbSize = sizeof(si);
@ -224,8 +227,7 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_SIZING: { case WM_SIZING: {
RECT *r = (RECT *)lParam; RECT *r = (RECT *)lParam;
int hc = (r->bottom - r->top) - ClientIsSmallerBy; int hc = (r->bottom - r->top) - ClientIsSmallerBy;
hc += TEXT_HEIGHT/2; int extra = hc % (TEXT_HEIGHT/2);
int extra = hc % TEXT_HEIGHT;
switch(wParam) { switch(wParam) {
case WMSZ_BOTTOM: case WMSZ_BOTTOM:
case WMSZ_BOTTOMLEFT: case WMSZ_BOTTOMLEFT:
@ -263,18 +265,20 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
int x = LOWORD(lParam); int x = LOWORD(lParam);
int y = HIWORD(lParam); int y = HIWORD(lParam);
if(y >= TEXT_HEIGHT*OFFSET_LINE) {
y -= OFFSET_HEIGHT;
}
// Find the corresponding character in the text buffer // Find the corresponding character in the text buffer
int r = (y / TEXT_HEIGHT);
int c = (x / TEXT_WIDTH); int c = (x / TEXT_WIDTH);
if(msg == WM_MOUSEMOVE && r >= TextWndRows) { int hh = (TEXT_HEIGHT)/2;
y += TextWndScrollPos*hh;
int r;
for(r = 0; r < SS.TW.rows; r++) {
if(y >= SS.TW.top[r]*hh && y <= (SS.TW.top[r]+2)*hh) {
break;
}
}
if(r >= SS.TW.rows) {
SetCursor(LoadCursor(NULL, IDC_ARROW)); SetCursor(LoadCursor(NULL, IDC_ARROW));
break; break;
} }
r += TextWndScrollPos;
if(msg == WM_MOUSEMOVE) { if(msg == WM_MOUSEMOVE) {
if(SS.TW.meta[r][c].link) { if(SS.TW.meta[r][c].link) {
@ -728,10 +732,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
InitCommonControls(); InitCommonControls();
// A monospaced font // A monospaced font
FixedFont = CreateFont(TEXT_HEIGHT-2, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE, FixedFont = CreateFont(TEXT_HEIGHT-4, 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-2, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE, LinkFont = CreateFont(TEXT_HEIGHT-4, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE,
TRUE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, TRUE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FF_DONTCARE, "Lucida Console"); DEFAULT_QUALITY, FF_DONTCARE, "Lucida Console");
if(!FixedFont) if(!FixedFont)