From 69eb2273ace517ba237335ea23dbd546aaa6b79b Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Thu, 29 May 2008 22:09:41 -0800 Subject: [PATCH] Add color. Now each triangle has metadata, which are preserved in csg ops; so the union of a red part and a blue part has both red and blue faces. And some user interface to pick the color in the text window. The metadata also include a face, which will be an entity; I can use that to constrain against. But none of that is yet implemented. [git-p4: depot-paths = "//depot/solvespace/": change = 1757] --- file.cpp | 10 +++++-- glhelper.cpp | 14 ++++++++- mesh.cpp | 75 ++++++++++++++++++++++++++--------------------- polygon.cpp | 5 ++++ polygon.h | 25 ++++++++++------ sketch.cpp | 26 +++++++++------- sketch.h | 1 + solvespace.h | 2 +- textwin.cpp | 34 ++++++++++++++++++++- ui.h | 5 +++- win32/w32main.cpp | 17 ++++++++--- 11 files changed, 149 insertions(+), 65 deletions(-) diff --git a/file.cpp b/file.cpp index a2c9c3e..c1aebd2 100644 --- a/file.cpp +++ b/file.cpp @@ -57,6 +57,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = { { 'g', "Group.activeWorkplane.v", 'x', &(SS.sv.g.activeWorkplane.v) }, { 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) }, { 'g', "Group.exprA", 'E', &(SS.sv.g.exprA) }, + { 'g', "Group.color", 'x', &(SS.sv.g.color) }, { 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) }, { 'g', "Group.meshCombine", 'd', &(SS.sv.g.meshCombine) }, { 'g', "Group.wrkpl.q.w", 'f', &(SS.sv.g.wrkpl.q.w) }, @@ -223,8 +224,9 @@ bool SolveSpace::SaveToFile(char *filename) { SMesh *m = &(group.elem[group.n-1].mesh); for(i = 0; i < m->l.n; i++) { STriangle *tr = &(m->l.elem[i]); - fprintf(fh, "Triangle " + fprintf(fh, "Triangle %08x %08x " "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n", + tr->meta.face, tr->meta.color, CO(tr->a), CO(tr->b), CO(tr->c)); } @@ -376,10 +378,12 @@ bool SolveSpace::LoadEntitiesFromFile(char *file, EntityList *le, SMesh *m) { } else if(memcmp(line, "Triangle", 8)==0) { STriangle tr; ZERO(&tr); - if(sscanf(line, "Triangle %lf %lf %lf %lf %lf %lf %lf %lf %lf", + if(sscanf(line, "Triangle %x %x " + "%lf %lf %lf %lf %lf %lf %lf %lf %lf", + &(tr.meta.face), &(tr.meta.color), &(tr.a.x), &(tr.a.y), &(tr.a.z), &(tr.b.x), &(tr.b.y), &(tr.b.z), - &(tr.c.x), &(tr.c.y), &(tr.c.z)) != 9) + &(tr.c.x), &(tr.c.y), &(tr.c.z)) != 11) { oops(); } diff --git a/glhelper.cpp b/glhelper.cpp index 20aef05..1464b3e 100644 --- a/glhelper.cpp +++ b/glhelper.cpp @@ -111,15 +111,27 @@ void glxColor4d(double r, double g, double b, double a) if(!ColorLocked) glColor4d(r, g, b, a); } -void glxFillMesh(SMesh *m) +void glxFillMesh(bool useModelColor, SMesh *m) { glEnable(GL_NORMALIZE); + int prevColor = -1; glBegin(GL_TRIANGLES); for(int i = 0; i < m->l.n; i++) { STriangle *tr = &(m->l.elem[i]); Vector n = tr->Normal(); glNormal3d(n.x, n.y, n.z); + int color = tr->meta.color; + if(useModelColor && color != prevColor) { + GLfloat mpf[] = { ((color >> 0) & 0xff) / 255.0f, + ((color >> 8) & 0xff) / 255.0f, + ((color >> 16) & 0xff) / 255.0f, 1.0 }; + glEnd(); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf); + prevColor = color; + glBegin(GL_TRIANGLES); + } + glxVertex3v(tr->a); glxVertex3v(tr->b); glxVertex3v(tr->c); diff --git a/mesh.cpp b/mesh.cpp index 643d379..b7f048c 100644 --- a/mesh.cpp +++ b/mesh.cpp @@ -11,14 +11,16 @@ void SMesh::AddTriangle(Vector n, Vector a, Vector b, Vector c) { // ugh; gl sometimes tesselates to collinear triangles return; } + STriMeta meta; ZERO(&meta); if(np.Dot(n) > 0) { - AddTriangle(a, b, c); + AddTriangle(meta, a, b, c); } else { - AddTriangle(c, b, a); + AddTriangle(meta, c, b, a); } } -void SMesh::AddTriangle(Vector a, Vector b, Vector c) { +void SMesh::AddTriangle(STriMeta meta, Vector a, Vector b, Vector c) { STriangle t; ZERO(&t); + t.meta = meta; t.a = a; t.b = b; t.c = c; @@ -53,6 +55,8 @@ void SMesh::Simplify(int start) { #define MAX_TRIANGLES 2000 if(l.n - start > MAX_TRIANGLES) oops(); + STriMeta meta = l.elem[start].meta; + STriangle tout[MAX_TRIANGLES]; int toutc = 0; @@ -161,7 +165,7 @@ void SMesh::Simplify(int start) { } for(i = 0; i < convc - 2; i++) { - STriangle tr = { 0, conv[0], conv[i+1], conv[i+2] }; + STriangle tr = STriangle::From(meta, conv[0], conv[i+1], conv[i+2]); if((tr.Normal()).Magnitude() > LENGTH_EPS*LENGTH_EPS) { tout[toutc++] = tr; } @@ -185,9 +189,9 @@ void SMesh::AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3) { if(!atLeastOneDiscarded && (l.n != (pn+1))) { l.n = pn; if(flipNormal) { - AddTriangle(st->c, st->b, st->a); + AddTriangle(st->meta, st->c, st->b, st->a); } else { - AddTriangle(st->a, st->b, st->c); + AddTriangle(st->meta, st->a, st->b, st->c); } } if(l.n - pn > 1) { @@ -287,11 +291,11 @@ void SBsp3::InsertInPlane(bool pos2, STriangle *tr, SMesh *m) { } if(m->flipNormal && ((!pos2 && !onFace) || (onFace && !sameNormal))) { - m->AddTriangle(tr->c, tr->b, tr->a); + m->AddTriangle(tr->meta, tr->c, tr->b, tr->a); } else if(!(m->flipNormal) && ((pos2 && !onFace) || (onFace && sameNormal && m->keepCoplanar))) { - m->AddTriangle(tr->a, tr->b, tr->c); + m->AddTriangle(tr->meta, tr->a, tr->b, tr->c); } else { m->atLeastOneDiscarded = true; } @@ -325,9 +329,9 @@ void SBsp3::InsertHow(int how, STriangle *tr, SMesh *instead) { alt: if(how == POS && !(instead->flipNormal)) { - instead->AddTriangle(tr->a, tr->b, tr->c); + instead->AddTriangle(tr->meta, tr->a, tr->b, tr->c); } else if(how == NEG && instead->flipNormal) { - instead->AddTriangle(tr->c, tr->b, tr->a); + instead->AddTriangle(tr->meta, tr->c, tr->b, tr->a); } else if(how == COPLANAR) { if(edges) { edges->InsertTriangle(tr, instead, this); @@ -341,18 +345,20 @@ alt: } } -void SBsp3::InsertConvexHow(int how, Vector *vertex, int n, SMesh *instead) { +void SBsp3::InsertConvexHow(int how, STriMeta meta, Vector *vertex, int n, + SMesh *instead) +{ switch(how) { case POS: if(pos) { - pos = pos->InsertConvex(vertex, n, instead); + pos = pos->InsertConvex(meta, vertex, n, instead); return; } break; case NEG: if(neg) { - neg = neg->InsertConvex(vertex, n, instead); + neg = neg->InsertConvex(meta, vertex, n, instead); return; } break; @@ -361,12 +367,15 @@ void SBsp3::InsertConvexHow(int how, Vector *vertex, int n, SMesh *instead) { } int i; for(i = 0; i < n - 2; i++) { - STriangle tr = { 0, vertex[0], vertex[i+1], vertex[i+2] }; + STriangle tr = STriangle::From(meta, + vertex[0], vertex[i+1], vertex[i+2]); InsertHow(how, &tr, instead); } } -SBsp3 *SBsp3::InsertConvex(Vector *vertex, int cnt, SMesh *instead) { +SBsp3 *SBsp3::InsertConvex(STriMeta meta, Vector *vertex, int cnt, + SMesh *instead) +{ Vector e01 = (vertex[1]).Minus(vertex[0]); Vector e12 = (vertex[2]).Minus(vertex[1]); Vector out = e01.Cross(e12); @@ -407,11 +416,11 @@ SBsp3 *SBsp3::InsertConvex(Vector *vertex, int cnt, SMesh *instead) { } if(posc == 0) { - InsertConvexHow(NEG, vertex, cnt, instead); + InsertConvexHow(NEG, meta, vertex, cnt, instead); return this; } if(negc == 0) { - InsertConvexHow(POS, vertex, cnt, instead); + InsertConvexHow(POS, meta, vertex, cnt, instead); return this; } @@ -459,15 +468,16 @@ SBsp3 *SBsp3::InsertConvex(Vector *vertex, int cnt, SMesh *instead) { } if(nneg < 3 || npos < 3) oops(); - InsertConvexHow(NEG, vneg, nneg, instead); - InsertConvexHow(POS, vpos, npos, instead); + InsertConvexHow(NEG, meta, vneg, nneg, instead); + InsertConvexHow(POS, meta, vpos, npos, instead); return this; triangulate: // We don't handle the special case for this; do it as triangles SBsp3 *r = this; for(i = 0; i < cnt - 2; i++) { - STriangle tr = { 0, vertex[0], vertex[i+1], vertex[i+2] }; + STriangle tr = STriangle::From(meta, + vertex[0], vertex[i+1], vertex[i+2]); r = r->Insert(&tr, instead); } return r; @@ -479,7 +489,7 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { if(instead->flipNormal) { instead->atLeastOneDiscarded = true; } else { - instead->AddTriangle(tr->a, tr->b, tr->c); + instead->AddTriangle(tr->meta, tr->a, tr->b, tr->c); } return NULL; } @@ -551,8 +561,8 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { } else oops(); Vector bPc = IntersectionWith(b, c); - STriangle btri = { 0, a, b, bPc }; - STriangle ctri = { 0, c, a, bPc }; + STriangle btri = STriangle::From(tr->meta, a, b, bPc); + STriangle ctri = STriangle::From(tr->meta, c, a, bPc); if(bpos) { InsertHow(POS, &btri, instead); @@ -587,17 +597,14 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { Vector aPb = IntersectionWith(a, b); Vector cPa = IntersectionWith(c, a); - STriangle alone = { 0, a, aPb, cPa }; - + STriangle alone = STriangle::From(tr->meta, a, aPb, cPa); Vector quad[4] = { aPb, b, c, cPa }; - STriangle quad1 = { 0, aPb, b, c }; - STriangle quad2 = { 0, aPb, c, cPa }; if(posc == 2 && negc == 1) { - InsertConvexHow(POS, quad, 4, instead); + InsertConvexHow(POS, tr->meta, quad, 4, instead); InsertHow(NEG, &alone, instead); } else { - InsertConvexHow(NEG, quad, 4, instead); + InsertConvexHow(NEG, tr->meta, quad, 4, instead); InsertHow(POS, &alone, instead); } if(!instead) { @@ -799,8 +806,8 @@ void SBsp2::InsertTriangle(STriangle *tr, SMesh *m, SBsp3 *bsp3) { } else oops(); Vector bPc = IntersectionWith(b, c); - STriangle btri = { 0, a, b, bPc }; - STriangle ctri = { 0, c, a, bPc }; + STriangle btri = STriangle::From(tr->meta, a, b, bPc); + STriangle ctri = STriangle::From(tr->meta, c, a, bPc); if(bpos) { InsertTriangleHow(POS, &btri, m, bsp3); @@ -830,9 +837,9 @@ void SBsp2::InsertTriangle(STriangle *tr, SMesh *m, SBsp3 *bsp3) { Vector aPb = IntersectionWith(a, b); Vector cPa = IntersectionWith(c, a); - STriangle alone = { 0, a, aPb, cPa }; - STriangle quad1 = { 0, aPb, b, c }; - STriangle quad2 = { 0, aPb, c, cPa }; + STriangle alone = STriangle::From(tr->meta, a, aPb, cPa); + STriangle quad1 = STriangle::From(tr->meta, aPb, b, c ); + STriangle quad2 = STriangle::From(tr->meta, aPb, c, cPa); if(posc == 2 && negc == 1) { InsertTriangleHow(POS, &quad1, m, bsp3); diff --git a/polygon.cpp b/polygon.cpp index 36ebe0f..f183f87 100644 --- a/polygon.cpp +++ b/polygon.cpp @@ -22,6 +22,11 @@ bool STriangle::ContainsPoint(Vector p) { return true; } +STriangle STriangle::From(STriMeta meta, Vector a, Vector b, Vector c) { + STriangle tr = { 0, meta, a, b, c }; + return tr; +} + void SEdgeList::Clear(void) { l.Clear(); } diff --git a/polygon.h b/polygon.h index a487d64..27cc55e 100644 --- a/polygon.h +++ b/polygon.h @@ -99,11 +99,17 @@ public: void Clear(void); }; +typedef struct { + DWORD face; + int color; +} STriMeta; class STriangle { public: - int tag; - Vector a, b, c; + int tag; + STriMeta meta; + Vector a, b, c; + static STriangle From(STriMeta meta, Vector a, Vector b, Vector c); Vector Normal(void); bool ContainsPoint(Vector p); }; @@ -153,8 +159,9 @@ public: void InsertHow(int how, STriangle *str, SMesh *instead); SBsp3 *Insert(STriangle *str, SMesh *instead); - void InsertConvexHow(int how, Vector *vertex, int n, SMesh *instead); - SBsp3 *InsertConvex(Vector *vertex, int n, SMesh *instead); + void InsertConvexHow(int how, STriMeta meta, Vector *vertex, int n, + SMesh *instead); + SBsp3 *InsertConvex(STriMeta meta, Vector *vertex, int n, SMesh *instead); void InsertInPlane(bool pos2, STriangle *tr, SMesh *m); @@ -171,7 +178,7 @@ public: void Clear(void); void AddTriangle(STriangle *st); - void AddTriangle(Vector a, Vector b, Vector c); + void AddTriangle(STriMeta meta, Vector a, Vector b, Vector c); void AddTriangle(Vector n, Vector a, Vector b, Vector c); void DoBounding(Vector v, Vector *vmax, Vector *vmin); void GetBounding(Vector *vmax, Vector *vmin); @@ -203,7 +210,7 @@ public: STriangleLl2 *next; }; -class SAxisAligned { +class SKdTree { public: static const int BY_X = 1; static const int BY_Y = 2; @@ -211,10 +218,10 @@ public: int which; double c; - SAxisAligned *gt; - SAxisAligned *lt; + SKdTree *gt; + SKdTree *lt; - STriangleLl2 *tris; + STriangleLl2 *tris; }; #endif diff --git a/sketch.cpp b/sketch.cpp index b91bc37..f797517 100644 --- a/sketch.cpp +++ b/sketch.cpp @@ -79,6 +79,7 @@ void Group::MenuGroup(int id) { case GraphicsWindow::MNU_GROUP_EXTRUDE: g.type = EXTRUDE; g.opA = SS.GW.activeGroup; + g.color = RGB(150, 150, 150); g.wrkpl.entityB = SS.GW.ActiveWorkplane(); g.subtype = ONE_SIDED; g.name.strcpy("extrude"); @@ -512,6 +513,8 @@ void Group::MakePolygons(void) { SMesh srcm; ZERO(&srcm); (src->poly).TriangulateInto(&srcm); + STriMeta meta = { 0, color }; + // Do the bottom; that has normal pointing opposite from translate for(i = 0; i < srcm.l.n; i++) { STriangle *st = &(srcm.l.elem[i]); @@ -519,9 +522,9 @@ void Group::MakePolygons(void) { bt = (st->b).Plus(tbot), ct = (st->c).Plus(tbot); if(flipBottom) { - outm.AddTriangle(ct, bt, at); + outm.AddTriangle(meta, ct, bt, at); } else { - outm.AddTriangle(at, bt, ct); + outm.AddTriangle(meta, at, bt, ct); } } // And the top; that has the normal pointing the same dir as translate @@ -531,9 +534,9 @@ void Group::MakePolygons(void) { bt = (st->b).Plus(ttop), ct = (st->c).Plus(ttop); if(flipBottom) { - outm.AddTriangle(at, bt, ct); + outm.AddTriangle(meta, at, bt, ct); } else { - outm.AddTriangle(ct, bt, at); + outm.AddTriangle(meta, ct, bt, at); } } srcm.Clear(); @@ -547,11 +550,11 @@ void Group::MakePolygons(void) { Vector abot = (edge->a).Plus(tbot), bbot = (edge->b).Plus(tbot); Vector atop = (edge->a).Plus(ttop), btop = (edge->b).Plus(ttop); if(flipBottom) { - outm.AddTriangle(bbot, abot, atop); - outm.AddTriangle(bbot, atop, btop); + outm.AddTriangle(meta, bbot, abot, atop); + outm.AddTriangle(meta, bbot, atop, btop); } else { - outm.AddTriangle(abot, bbot, atop); - outm.AddTriangle(bbot, btop, atop); + outm.AddTriangle(meta, abot, bbot, atop); + outm.AddTriangle(meta, bbot, btop, atop); } } } else if(type == IMPORTED) { @@ -593,12 +596,13 @@ void Group::Draw(void) { // Show this even if the group is not visible. It's already possible // to show or hide just this with the "show solids" flag. + bool useModelColor; if(type == DRAWING_3D || type == DRAWING_WORKPLANE) { GLfloat mpf[] = { 0.1f, 0.1f, 0.1f, 1.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf); + useModelColor = false; } else { - GLfloat mpf[] = { 0.4f, 0.4f, 0.4f, 1.0 }; - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf); + useModelColor = true; } // The back faces are drawn in red; should never seem them, since we // draw closed shells, so that's a debugging aid. @@ -606,7 +610,7 @@ void Group::Draw(void) { glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, mpb); glEnable(GL_LIGHTING); - if(SS.GW.showShaded) glxFillMesh(&mesh); + if(SS.GW.showShaded) glxFillMesh(useModelColor, &mesh); glDisable(GL_LIGHTING); if(SS.GW.showMesh) glxDebugMesh(&mesh); diff --git a/sketch.h b/sketch.h index 0c10684..1a730c2 100644 --- a/sketch.h +++ b/sketch.h @@ -90,6 +90,7 @@ public: bool visible; hEntity activeWorkplane; Expr *exprA; + DWORD color; static const int SOLVED_OKAY = 0; static const int DIDNT_CONVERGE = 10; diff --git a/solvespace.h b/solvespace.h index 7b73deb..a3e09ce 100644 --- a/solvespace.h +++ b/solvespace.h @@ -100,7 +100,7 @@ void glxVertex3v(Vector u); typedef void GLX_CALLBACK glxCallbackFptr(void); void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p); void glxFillPolygon(SPolygon *p); -void glxFillMesh(SMesh *m); +void glxFillMesh(bool useModelColor, SMesh *m); void glxDebugPolygon(SPolygon *p); void glxDebugEdgeList(SEdgeList *l); void glxDebugMesh(SMesh *m); diff --git a/textwin.cpp b/textwin.cpp index 4068fbc..b0bd08c 100644 --- a/textwin.cpp +++ b/textwin.cpp @@ -24,6 +24,16 @@ void TextWindow::Init(void) { memset(this, 0, sizeof(*this)); shown = &(showns[shownIndex]); + // Default list of colors for the model material + modelColor[0] = RGB(150, 150, 150); + modelColor[1] = RGB(100, 100, 100); + modelColor[2] = RGB( 30, 30, 30); + modelColor[3] = RGB(150, 0, 0); + modelColor[4] = RGB( 0, 150, 0); + modelColor[5] = RGB( 0, 80, 80); + modelColor[6] = RGB( 0, 0, 150); + modelColor[7] = RGB( 80, 0, 80); + ClearScreen(); } @@ -104,7 +114,9 @@ void TextWindow::Printf(bool halfLine, char *fmt, ...) { } else { color = fmt[1]; } - if(color < 0 || color > 255) color = 0; + if((color < 0 || color > 255) && !(color & 0x80000000)) { + color = 0; + } if(*fmt == 'F') { fg = color; } else { @@ -385,6 +397,13 @@ void TextWindow::ScreenChangeMeshCombine(int link, DWORD v) { SS.GW.GeneratePerSolving(); SS.GW.ClearSuper(); } +void TextWindow::ScreenColor(int link, DWORD v) { + Group *g = SS.GetGroup(SS.TW.shown->group); + if(v < 0 || v >= MODEL_COLORS) return; + g->color = SS.TW.modelColor[v]; + SS.GW.GeneratePerSolving(); + SS.GW.ClearSuper(); +} void TextWindow::ScreenChangeExprA(int link, DWORD v) { Group *g = SS.GetGroup(SS.TW.shown->group); ShowTextEditControl(13, 10, g->exprA->Print()); @@ -446,6 +465,19 @@ void TextWindow::ShowGroupInfo(void) { (diff ? "" : "as difference"), (diff ? "as difference" : "")); } + if(g->type == Group::EXTRUDE) { +#define TWOX(v) v v + Printf(true, "%FtMCOLOR%E " TWOX(TWOX(TWOX("%Bp%D%f%Ln %Bd%E "))), + 0x80000000 | modelColor[0], 0, &TextWindow::ScreenColor, + 0x80000000 | modelColor[1], 1, &TextWindow::ScreenColor, + 0x80000000 | modelColor[2], 2, &TextWindow::ScreenColor, + 0x80000000 | modelColor[3], 3, &TextWindow::ScreenColor, + 0x80000000 | modelColor[4], 4, &TextWindow::ScreenColor, + 0x80000000 | modelColor[5], 5, &TextWindow::ScreenColor, + 0x80000000 | modelColor[6], 6, &TextWindow::ScreenColor, + 0x80000000 | modelColor[7], 7, &TextWindow::ScreenColor); + } + Printf(true, "%Ftrequests in group"); int i, a = 0; diff --git a/ui.h b/ui.h index 856c355..346ed83 100644 --- a/ui.h +++ b/ui.h @@ -17,13 +17,15 @@ public: static const Color fgColors[]; static const Color bgColors[]; + static const int MODEL_COLORS = 8; + int modelColor[MODEL_COLORS]; BYTE text[MAX_ROWS][MAX_COLS]; typedef void LinkFunction(int link, DWORD v); static const int NOT_A_LINK = 0; struct { char fg; - char bg; + int bg; int link; DWORD data; LinkFunction *f; @@ -91,6 +93,7 @@ public: static void ScreenChangeOneOrTwoSides(int link, DWORD v); static void ScreenChangeMeshCombine(int link, DWORD v); + static void ScreenColor(int link, DWORD v); // These ones do stuff with the edit control static void ScreenChangeExprA(int link, DWORD v); diff --git a/win32/w32main.cpp b/win32/w32main.cpp index 52e38fe..fa4ff27 100644 --- a/win32/w32main.cpp +++ b/win32/w32main.cpp @@ -183,10 +183,19 @@ static void PaintTextWnd(HDC hdc) for(c = 0; c < min((width/TEXT_WIDTH)+1, SS.TW.MAX_COLS); c++) { int fg = SS.TW.meta[r][c].fg; int bg = SS.TW.meta[r][c].bg; - SetTextColor(backDc, FgColor[fg]); - SetBkColor(backDc, BgColor[bg]); - if(SS.TW.meta[r][c].link) { + SetTextColor(backDc, FgColor[fg]); + + HBRUSH bgb; + if(bg & 0x80000000) { + bgb = (HBRUSH)GetStockObject(BLACK_BRUSH); + SetBkColor(backDc, bg & 0xffffff); + } else { + bgb = BgBrush[bg]; + SetBkColor(backDc, BgColor[bg]); + } + + if(SS.TW.meta[r][c].link && SS.TW.meta[r][c].link != 'n') { SelectObject(backDc, LinkFont); } else { SelectObject(backDc, FixedFont); @@ -198,7 +207,7 @@ static void PaintTextWnd(HDC hdc) RECT a; a.left = x; a.right = x+TEXT_WIDTH; a.top = y; a.bottom = y+TEXT_HEIGHT; - FillRect(backDc, &a, BgBrush[bg]); + FillRect(backDc, &a, bgb); TextOut(backDc, x, y+2, (char *)&(SS.TW.text[r][c]), 1); }