]> Shamusworld >> Repos - ttedit/blob - src/editwindow.cpp
63e8b3f4a9e2e1674a804fdac3b627fbb52b49d4
[ttedit] / src / editwindow.cpp
1 //\r
2 // TTEDIT.CPP - The TrueType Editor\r
3 // by James L. Hammons\r
4 // (C) 2004 Underground Software\r
5 //\r
6 // JLH = James L. Hammons <jlhamm@acm.org>\r
7 //\r
8 // Who  When        What\r
9 // ---  ----------  -------------------------------------------------------------\r
10 // JLH  08/28/2008  Created this file\r
11 //\r
12 \r
13 // FIXED:\r
14 //\r
15 // STILL TO BE DONE:\r
16 //\r
17 // - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font\r
18 // - Fix scrolling, zooming, settings (ini)\r
19 //\r
20 \r
21 // Uncomment this for debugging...\r
22 #define DEBUG\r
23 #define DEBUGFOO            // Various tool debugging...\r
24 #define DEBUGTP                         // Toolpalette debugging...\r
25 \r
26 #include "editwindow.h"\r
27 #include "bezier.h"\r
28 #include "toolwindow.h"\r
29 #include "debug.h"\r
30 #include "vector.h"\r
31 \r
32 \r
33 BEGIN_EVENT_TABLE(TTEditWindow, wxWindow)\r
34         EVT_PAINT(TTEditWindow::OnPaint)\r
35         EVT_MOUSE_EVENTS(TTEditWindow::OnMouseEvent)\r
36 END_EVENT_TABLE()\r
37 \r
38 TTEditWindow::TTEditWindow(wxFrame * parent, const wxPoint &pos, const wxSize &size, long style):\r
39         wxWindow(parent, -1, pos, size, style | wxFULL_REPAINT_ON_RESIZE),\r
40         app(wxGetApp()), scale(1.0), offsetX(-10), offsetY(-10), tool(TOOLSelect),\r
41         ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1), oldPtNextHighlight(-1),\r
42         polyFirstPoint(true), bmp(NULL)\r
43\r
44         SetCursor(*(app.cur[tool]));\r
45         SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF));\r
46 \r
47         wxString s;\r
48         s.Printf(_("Zoom: %.2f%%"), scale * 100.0);\r
49         parent->SetStatusText(s, 1);\r
50 }\r
51 \r
52 TTEditWindow::~TTEditWindow(void)\r
53 {\r
54         if (bmp)\r
55                 delete bmp;\r
56 }\r
57 \r
58 void TTEditWindow::OnPaint(wxPaintEvent &e)\r
59 {\r
60         wxPaintDC dc(this);\r
61 //Doesn't do crap!\r
62 //dc.SetBackground(*wxWHITE_BRUSH);\r
63 \r
64 // Due to the screwiness of wxWidgets coord system, the origin is ALWAYS\r
65 // the upper left corner--regardless of axis orientation, etc...\r
66         wxCoord width, height;\r
67         dc.GetSize(&width, &height);\r
68 \r
69         dc.SetDeviceOrigin(-offsetX, height - (-offsetY));\r
70         dc.SetAxisOrientation(true, true);\r
71 \r
72 // Scrolling can be done by using OffsetViewportOrgEx\r
73 // Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform)\r
74 // you'd use: % = ViewportExt / WindowExt\r
75 // But it makes the window look like crap: fuggetuboutit.\r
76 // Instead, we have to scale EVERYTHING by hand. Crap!\r
77 // It's not *that* bad, but not as convenient either...\r
78 \r
79         dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0xFF), 1, wxDOT)));\r
80 //      dc.DrawLine(0, 0, 10, 10);\r
81 \r
82     // Draw coordinate axes\r
83 \r
84         dc.CrossHair(0, 0);\r
85 \r
86     // Draw points\r
87 \r
88         for(int i=0; i<pts.GetNumPoints(); i++)\r
89         {\r
90                 if (i == ptHighlight)\r
91                 {\r
92                         dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));\r
93 //                      SelectObject(hdc, hRedPen1);\r
94 \r
95                         if (pts.GetOnCurve(i))\r
96                         {\r
97                                 DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7);\r
98                                 DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9);\r
99                         }\r
100                         else\r
101                         {\r
102                                 DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7);\r
103                                 DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9);\r
104                         }\r
105                 }\r
106                 else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt)\r
107                 {\r
108                         dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0xAF, 0x00), 1, wxSOLID)));\r
109 //                      SelectObject(hdc, hGreenPen1);\r
110 \r
111                         if (pts.GetOnCurve(i))\r
112                         {\r
113                                 DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7);\r
114                                 DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9);\r
115                         }\r
116                         else\r
117                         {\r
118                                 DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7);\r
119                                 DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9);\r
120                         }\r
121                 }\r
122                 else\r
123                 {\r
124                         dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));\r
125 //                      SelectObject(hdc, hBlackPen1);\r
126 \r
127                         if (pts.GetOnCurve(i))\r
128                                 DrawSquareDot(dc, pts.GetX(i), pts.GetY(i));\r
129                         else\r
130                                 DrawRoundDot(dc, pts.GetX(i), pts.GetY(i));\r
131                 }\r
132 \r
133                 if (tool == TOOLDelPt && i == ptHighlight)\r
134                 {\r
135                         dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));\r
136 //                      SelectObject(hdc, hRedPen1);\r
137 //                      MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL);\r
138 //                      LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5);\r
139 //                      LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness!\r
140 //                      MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL);\r
141 //                      LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5);\r
142 //                      LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!!\r
143                         dc.DrawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);\r
144                         dc.DrawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);\r
145                 }\r
146         }\r
147 \r
148 //              SelectObject(hdc, hBlackPen1);\r
149         dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));\r
150 \r
151         // Draw curve formed by points\r
152 \r
153         for(int poly=0; poly<pts.GetNumPolys(); poly++)\r
154         {\r
155                 if (pts.GetNumPoints(poly) > 2)\r
156                 {\r
157                         // Initial move...\r
158                         // If it's not on curve, then move to it, otherwise move to last point...\r
159 \r
160                         wxCoord x, y;\r
161         \r
162                         if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1))\r
163                                 x = (wxCoord)pts.GetX(poly, pts.GetNumPoints(poly) - 1), y = (wxCoord)pts.GetY(poly, pts.GetNumPoints(poly) - 1);\r
164                         else\r
165                                 x = (wxCoord)pts.GetX(poly, 0), y = (wxCoord)pts.GetY(poly, 0);\r
166         \r
167                         for(int i=0; i<pts.GetNumPoints(poly); i++)\r
168                         {\r
169                                 if (pts.GetOnCurve(poly, i))\r
170 //                                      LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));\r
171                                 {\r
172                                         dc.DrawLine(x, y, pts.GetX(poly, i), pts.GetY(poly, i));\r
173                                         x = (wxCoord)pts.GetX(poly, i), y = (wxCoord)pts.GetY(poly, i);\r
174                                 }\r
175                                 else\r
176                                 {\r
177                                         uint32 prev = pts.GetPrev(poly, i), next = pts.GetNext(poly, i);\r
178                                         float px = pts.GetX(poly, prev), py = pts.GetY(poly, prev),\r
179                                                 nx = pts.GetX(poly, next), ny = pts.GetY(poly, next);\r
180         \r
181                                         if (!pts.GetOnCurve(poly, prev))\r
182                                                 px = (px + pts.GetX(poly, i)) / 2.0f,\r
183                                                 py = (py + pts.GetY(poly, i)) / 2.0f;\r
184         \r
185                                         if (!pts.GetOnCurve(poly, next))\r
186                                                 nx = (nx + pts.GetX(poly, i)) / 2.0f,\r
187                                                 ny = (ny + pts.GetY(poly, i)) / 2.0f;\r
188         \r
189                                         Bezier(dc, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));\r
190                                         x = (wxCoord)nx, y = (wxCoord)ny;\r
191         \r
192                                         if (pts.GetOnCurve(poly, next))\r
193                                                 i++;                                    // Following point is on curve, so move past it\r
194                                 }\r
195                         }\r
196                 }\r
197         }\r
198 \r
199 //              SelectObject(hdc, oldPen);                              // Restore the stuff we disrupted...\r
200         dc.SetPen(wxNullPen);\r
201 //              SelectObject(hdc, oldBrush);\r
202 //              EndPaint(hWnd, &ps);\r
203 }\r
204 \r
205 void TTEditWindow::OnMouseEvent(wxMouseEvent &e)\r
206 {\r
207 #ifdef DEBUGTP\r
208 //printf("!!! This window %s focus...!\n", (HasCapture() ? "has" : "doesn't have"));\r
209 #endif\r
210         if (e.RightDown())\r
211         {\r
212                 // Handle tool palette (NOTE: tool palette deals with RightUp event.)\r
213 \r
214                 wxPoint pt = ClientToScreen(e.GetPosition());\r
215                 app.toolPalette->Move(pt);\r
216                 app.toolPalette->Show(true);\r
217                 SetCursor(*wxSTANDARD_CURSOR);\r
218                 app.toolPalette->SetCursor(*wxSTANDARD_CURSOR);\r
219                 app.toolPalette->prevTool = TOOLSelect;\r
220                 app.toolPalette->Refresh(false);\r
221                 CaptureMouse();\r
222         }\r
223         else if (e.RightUp())\r
224         {\r
225                 ToolType newTool = app.toolPalette->FindSelectedTool();//, oldTool = tool;\r
226 \r
227                 // We only change the tool if a new one was actually selected. Otherwise, we do nothing.\r
228                 if (newTool != TOOLNone)\r
229                 {\r
230                         tool = newTool;\r
231 \r
232                         if (tool == TOOLScroll || tool == TOOLZoom || tool == TOOLAddPoly\r
233                                 || tool == TOOLDelPoly)\r
234                                 ptHighlight = -1;\r
235 \r
236                         if (tool == TOOLAddPoly)\r
237                                 polyFirstPoint = true;\r
238                 }\r
239 \r
240                 ReleaseMouse();\r
241                 app.toolPalette->Show(false);\r
242                 SetCursor(*(app.cur[tool]));\r
243         }\r
244         else if (e.LeftDown())\r
245         {\r
246                 if (tool == TOOLScroll || tool == TOOLZoom)\r
247                         CaptureMouse();                                         // Make sure we capture the mouse when in scroll/zoom mode\r
248                 else if (tool == TOOLAddPt)             // "Add Point" tool\r
249                 {\r
250                         if (pts.GetNumPoints() > 0)\r
251                         {\r
252                                 wxPoint pt = GetAdjustedMousePosition(e);\r
253                                 pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true));\r
254                                 ptHighlight = ptNextHighlight;\r
255                                 Refresh();\r
256                         }\r
257                 }\r
258                 else if (tool == TOOLAddPoly)   // "Add Poly" tool\r
259                 {\r
260 #ifdef DEBUGFOO\r
261 WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());\r
262 #endif\r
263                         if (polyFirstPoint)\r
264                         {\r
265                                 polyFirstPoint = false;\r
266                                 pts.AddNewPolyAtEnd();\r
267                         }\r
268 \r
269                         wxPoint pt = GetAdjustedMousePosition(e);\r
270                         // Append a point to the end of the structure\r
271                         pts += IPoint(pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true));\r
272                         ptHighlight = pts.GetNumPoints() - 1;\r
273                         Refresh();\r
274 #ifdef DEBUGFOO\r
275 WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints());\r
276 #endif\r
277                 }\r
278                 else if (tool == TOOLSelect || tool == TOOLPolySelect)\r
279                 {\r
280                         if (pts.GetNumPoints() > 0)\r
281                         {\r
282                                 pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));\r
283                                 WarpPointer(pt.x, pt.y);\r
284 \r
285                                 if (e.ShiftDown() | e.ControlDown())\r
286                                         pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight));\r
287                         }\r
288                 }\r
289                 else if (tool == TOOLDelPt)\r
290                 {\r
291                         if (pts.GetNumPoints() > 0)\r
292 //Or could use:\r
293 //                      if (ptHighlight != -1)\r
294                         {\r
295 //This assumes that WM_MOUSEMOVE happens before this!\r
296 //The above commented out line should take care of this contingency... !!! FIX !!!\r
297                                 pts.DeletePoint(ptHighlight);\r
298                                 Refresh();\r
299                         }\r
300                 }\r
301         }\r
302         else if (e.LeftUp())\r
303         {\r
304 //              mouseDown = false;\r
305 \r
306                 if (tool == TOOLScroll || tool == TOOLZoom)\r
307                         ReleaseMouse();\r
308         }\r
309         else if (e.Dragging())\r
310         {\r
311                 if (e.RightIsDown())\r
312                 {\r
313                         ToolType newTool = app.toolPalette->FindSelectedTool();\r
314 \r
315                         if (newTool != app.toolPalette->prevTool)\r
316                         {\r
317                                 app.toolPalette->prevTool = newTool;\r
318                                 app.toolPalette->Refresh(false);\r
319                         }\r
320 \r
321                         return;\r
322                 }\r
323 \r
324             // Extract current point from lParam/calc offset from previous point\r
325 \r
326                 pt = e.GetPosition();\r
327                 ptOffset.x = pt.x - ptPrevious.x,\r
328                 ptOffset.y = pt.y - ptPrevious.y;\r
329 \r
330 //              if (e.LeftIsDown())\r
331 //              {\r
332                         if (tool == TOOLScroll)\r
333                         {\r
334                                 // NOTE: OffsetViewportOrg operates in DEVICE UNITS...\r
335 \r
336 //Seems there's no equivalent for this in wxWidgets...!\r
337 //!!! FIX !!!\r
338 //                              hdc = GetDC(hWnd);\r
339 //                              OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL);\r
340 //                              ReleaseDC(hWnd, hdc);\r
341 \r
342 // this shows that it works, so the logic above must be faulty...\r
343 // And it is. It should convert the coords first, then do the subtraction to figure the offset...\r
344 // Above: DONE\r
345 // Then multiply it by the scaling factor. Whee!\r
346                                 // This looks wacky because we're using screen coords for the offset...\r
347                                 // Otherwise, we would subtract both offsets!\r
348                                 offsetX -= ptOffset.x, offsetY += ptOffset.y;\r
349                                 Refresh();\r
350                         }\r
351                         else if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)\r
352                         {\r
353                                 if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.\r
354                                 {\r
355 //temporary, for testing. BTW, Select drag bug is here...!\r
356 #if 0\r
357                                         wxPoint pt2 = GetAdjustedMousePosition(e);\r
358                                         pts.SetXY(ptHighlight, pt2.x, pt2.y);\r
359                                         Refresh();\r
360 #endif\r
361                                 }\r
362                         }\r
363                         else if (tool == TOOLPolySelect)\r
364                         {\r
365                                 if (pts.GetNumPoints() > 0)\r
366                                 {\r
367                                         wxPoint pt2 = GetAdjustedMousePosition(e);\r
368                                         // Should also set onCurve here as well, depending on keystate\r
369 //Or should we?\r
370                                         pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));\r
371                                         Refresh();\r
372                                 }\r
373                         }\r
374 //              }\r
375 \r
376                 ptPrevious = pt;\r
377         }\r
378         else if (e.Moving())\r
379         {\r
380 //              else    // Moving, not dragging...\r
381 //              {\r
382                         if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt\r
383                                 || tool == TOOLPolySelect)// || tool == TOOLAddPoly)\r
384                         {\r
385                                 wxPoint pt2 = GetAdjustedMousePosition(e);\r
386                                 double closest = 1.0e+99;\r
387 \r
388                                 for(int i=0; i<pts.GetNumPoints(); i++)\r
389                                 {\r
390                                         double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))\r
391                                                 + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));\r
392 \r
393                                         if (dist < closest)\r
394                                                 closest = dist, ptHighlight = i;\r
395                                 }\r
396 \r
397                                 if (ptHighlight != oldPtHighlight)\r
398                                 {\r
399                                         oldPtHighlight = ptHighlight;\r
400                                         Refresh();\r
401                                 }\r
402 \r
403                                 // What follows here looks like voodoo, but is really simple. What we do is\r
404                                 // check to see if the mouse point has a perpendicular intersection with any of\r
405                                 // the line segments. If it does, calculate the length of the perpendicular\r
406                                 // and choose the smallest length. If there is no perpendicular, then choose the\r
407                                 // length of line connecting the closer of either the first endpoint or the\r
408                                 // second and choose the smallest of those.\r
409 \r
410                                 // There is one bit of math that looks like voodoo to me ATM--will explain once\r
411                                 // I understand it better (the calculation of the length of the perpendicular).\r
412 \r
413                                 if (pts.GetNumPoints() > 1 && tool == TOOLAddPt)\r
414                                 {\r
415                                         double smallest = 1.0e+99;\r
416 \r
417                                         for(int i=0; i<pts.GetNumPoints(); i++)\r
418                                         {\r
419                                                 int32 p1x = pts.GetX(i), p1y = pts.GetY(i),\r
420                                                         p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));\r
421 \r
422                                                 vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x, pt2.y, 0, p1x, p1y, 0),\r
423                                                         v2(pt2.x, pt2.y, 0, p2x, p2y, 0);\r
424                                                 double pp = ls.dot(v1) / ls.length(), dist;\r
425 // Geometric interpretation:\r
426 // pp is the paremeterized point on the vector ls where the perpendicular intersects ls.\r
427 // If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,\r
428 // then the perpendicular lies beyond the 2nd endpoint.\r
429 \r
430                                                 if (pp < 0.0)\r
431                                                         dist = v1.length();\r
432                                                 else if (pp > ls.length())\r
433                                                         dist = v2.length();\r
434                                                 else                                    // distance = ?Det?(ls, v1) / |ls|\r
435                                                         dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.length());\r
436 \r
437 //The answer to the above looks like it might be found here:\r
438 //\r
439 //If the segment endpoints are s and e, and the point is p, then the test for the perpendicular\r
440 //intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and\r
441 //{e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is\r
442 //computed by first computing the area of the triangle the three points form, then dividing by the\r
443 //length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the\r
444 //triangle formed by three points is the determinant of the following matrix:\r
445 //\r
446 //sx sy 1\r
447 //ex ey 1\r
448 //px py 1\r
449 //\r
450 //(???) By translating the start point to the origin, this can be rewritten as:\r
451 //By subtracting row 1 from all rows, you get the following:\r
452 //\r
453 //0         0         0\r
454 //(ex - sx) (ey - sy) 0\r
455 //(px - sx) (py - sy) 0\r
456 //\r
457 //which greatly simplifies the calculation of the determinant.\r
458 \r
459                                                 if (dist < smallest)\r
460                                                         smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i;\r
461                                         }\r
462 \r
463                                         if (ptNextHighlight != oldPtNextHighlight)\r
464                                         {\r
465                                                 oldPtNextHighlight = ptNextHighlight;\r
466                                                 Refresh();\r
467                                         }\r
468                                 }\r
469                         }\r
470 //              }\r
471 \r
472                 ptPrevious = e.GetPosition();\r
473         }\r
474 }\r
475 \r
476 wxPoint TTEditWindow::GetAdjustedMousePosition(wxMouseEvent &e)\r
477 {\r
478         wxCoord width, height;\r
479         wxClientDC dc(this);\r
480 \r
481         dc.GetSize(&width, &height);\r
482         dc.SetDeviceOrigin(-offsetX, height - (-offsetY));\r
483         dc.SetAxisOrientation(true, true);\r
484 \r
485 #if 0\r
486 wxStatusBar * sb = ((wxFrame *)GetParent())->GetStatusBar();\r
487 wxString s;\r
488 s.Printf("Logical mouse pos: %d, %d (%d, %d)", pt.x, pt.y, width, height);\r
489 sb->SetStatusText(s);\r
490 #endif\r
491 \r
492         return e.GetLogicalPosition(dc);\r
493 }\r
494 \r
495 wxPoint TTEditWindow::GetAdjustedClientPosition(wxCoord x, wxCoord y)\r
496 {\r
497         wxCoord width, height;\r
498         wxClientDC dc(this);\r
499 \r
500         dc.GetSize(&width, &height);\r
501         dc.SetDeviceOrigin(-offsetX, height - (-offsetY));\r
502         dc.SetAxisOrientation(true, true);\r
503 \r
504         return wxPoint(dc.LogicalToDeviceX(x), dc.LogicalToDeviceY(y));\r
505 }\r
506 \r
507 //\r
508 // Draw a round dot (5x5, centered on [x, y])\r
509 //\r
510 void TTEditWindow::DrawRoundDot(wxDC &dc, int32 x, int32 y)\r
511 {\r
512         wxPoint pt[8];\r
513 \r
514         pt[0].x = x - 1, pt[0].y = y - 2;\r
515         pt[1].x = x + 1, pt[1].y = y - 2;\r
516         pt[2].x = x + 2, pt[2].y = y - 1;\r
517         pt[3].x = x + 2, pt[3].y = y + 1;\r
518         pt[4].x = x + 1, pt[4].y = y + 2;\r
519         pt[5].x = x - 1, pt[5].y = y + 2;\r
520         pt[6].x = x - 2, pt[6].y = y + 1;\r
521         pt[7].x = x - 2, pt[7].y = y - 1;\r
522 \r
523         dc.DrawPolygon(8, pt);\r
524 }\r
525 \r
526 //\r
527 // Draw a sqaure dot (5x5, centered on [x, y])\r
528 //\r
529 void TTEditWindow::DrawSquareDot(wxDC &dc, int32 x, int32 y)\r
530 {\r
531         wxPoint pt[4];\r
532 \r
533         pt[0].x = x - 2, pt[0].y = y - 2;\r
534         pt[1].x = x + 2, pt[1].y = y - 2;\r
535         pt[2].x = x + 2, pt[2].y = y + 2;\r
536         pt[3].x = x - 2, pt[3].y = y + 2;\r
537 \r
538         dc.DrawPolygon(4, pt);\r
539 }\r
540 \r
541 //\r
542 // Draw a sqaure dot (nxn, centered on [x, y])\r
543 //\r
544 void TTEditWindow::DrawSquareDotN(wxDC &dc, int32 x, int32 y, uint32 n)\r
545 {\r
546         wxPoint pt[4];\r
547         uint32 offset = (n - 1) / 2;\r
548 \r
549         pt[0].x = x - offset, pt[0].y = y - offset;\r
550         pt[1].x = x + offset, pt[1].y = y - offset;\r
551         pt[2].x = x + offset, pt[2].y = y + offset;\r
552         pt[3].x = x - offset, pt[3].y = y + offset;\r
553 \r
554         dc.DrawPolygon(4, pt);\r
555 }\r
556 \r
557 //\r
558 // Draw a round dot (nxn, centered on [x, y])\r
559 //\r
560 void TTEditWindow::DrawRoundDotN(wxDC &dc, int32 x, int32 y, uint32 n)\r
561 {\r
562         dc.DrawCircle(x, y, (n / 2) + 1);\r
563 }\r
564 \r
565 \r
566 #if 0\r
567 \r
568 !!! OLD STUFF !!!\r
569 \r
570 \r
571 LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)\r
572 {\r
573         RECT rc1, rc2;\r
574         HDC hdc;\r
575         POINT pt, ptOffset;\r
576         SIZE sz;\r
577         PAINTSTRUCT ps;\r
578 \r
579         switch (msgID)\r
580         {\r
581         case WM_CREATE:\r
582 \r
583                 MiscCenterWnd(hWnd, GetDesktopWindow());\r
584                 InitCommonControls();\r
585                 hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, statusBarTxt, hWnd, ID_STATUSBAR);\r
586 \r
587                 if (!hStatusBar)\r
588                         return -1;\r
589 \r
590 // clean this crap up!\r
591 // well, the only crappy thing here is using a POINT as an int array, but otherwise, this is OK\r
592                 wsprintf(strBuf, zoom, 1000);\r
593                 hdc = GetDC(hWnd);\r
594                 GetTextExtentPoint32(hdc, strBuf, lstrlen(strBuf), &sz);\r
595                 ReleaseDC(hWnd, hdc);\r
596                 zoomWndWidth = sz.cx;\r
597                 wsprintf(strBuf, zoom, 100);\r
598 \r
599                 GetClientRect(hWnd, &rc1);\r
600                 pt.x = rc1.right - zoomWndWidth, pt.y = -1;\r
601                 SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&pt);\r
602                 SendMessage(hStatusBar, SB_SETTEXT, (0 | SBT_NOBORDERS), (LPARAM)statusBarTxt);\r
603                 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM)strBuf);\r
604 \r
605                 hToolBar = CreateToolbarEx(hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS,\r
606                         IDR_TOOLBAR1, 3, hInst, IDB_TOOLBAR1, tbButtons, 4, 16, 16, 16, 16, sizeof(TBBUTTON));\r
607 \r
608                 if (!hToolBar)\r
609                         return -1;\r
610 \r
611                 CreateNewDoc();\r
612 \r
613 // The following can only be done because we use a private DC (using "CS_OWNDC")\r
614 // (Is that true???)\r
615 // Set the mapping to draw the character so it fits in the viewport...\r
616                 hdc = GetDC(hWnd);\r
617                 GetClientRect(hWnd, &rc1);\r
618                 GetClientRect(hStatusBar, &rc2);\r
619                 rc1.bottom -= rc2.bottom;\r
620                 SetMapMode(hdc, MM_ISOTROPIC);\r
621                 SetWindowExtEx(hdc, rc1.right, rc1.bottom, NULL);\r
622                 SetViewportExtEx(hdc, rc1.right, -rc1.bottom, NULL);\r
623                 SetViewportOrgEx(hdc, 0, rc1.bottom, NULL);\r
624                 ReleaseDC(hWnd, hdc);\r
625                 break;\r
626 \r
627         case WM_CLOSE:\r
628 \r
629                 if (SaveChanges())\r
630                 {\r
631                         wpM.length = wpC.length = sizeof(WINDOWPLACEMENT);\r
632                         GetWindowPlacement(hMainWnd, &wpM);\r
633                         GetWindowPlacement(hCharWnd, &wpC);\r
634 \r
635                         if (!IsWindowVisible(hCharWnd))         // Needed because Windows lies about visibility\r
636                                 wpC.showCmd = SW_HIDE;\r
637 \r
638                         hdc = GetDC(hWnd);\r
639                         GetViewportOrgEx(hdc, &ptVPM);\r
640                         ReleaseDC(hWnd, hdc);\r
641 \r
642                         DestroyWindow(hWnd);\r
643                 }\r
644 \r
645                 break;\r
646 \r
647         case WM_DESTROY:\r
648 \r
649                 PostQuitMessage(0);\r
650                 break;\r
651 \r
652         case WM_NCLBUTTONDOWN:\r
653 \r
654                 if (wParam == HTCAPTION)\r
655                 {\r
656                         NCMouseDown = true;\r
657                         GetWindowRect(hMainWnd, &rc1);\r
658                         GetWindowRect(hCharWnd, &rc2);\r
659                         ptWinOffset.x = rc2.left - rc1.left;\r
660                         ptWinOffset.y = rc2.top - rc1.top;\r
661                 }\r
662                     \r
663                 // Let Windows do its thing with this msg, or weird things will happen...\r
664 \r
665                 DefWindowProc(hWnd, msgID, wParam, lParam);\r
666                 NCMouseDown = false;\r
667                 break;\r
668 \r
669         case WM_WINDOWPOSCHANGING:\r
670 \r
671                 if (NCMouseDown)\r
672                 {\r
673                         WINDOWPOS * wp = (WINDOWPOS *)lParam;\r
674 \r
675                         if (wp->hwnd == hMainWnd && !(wp->flags & SWP_NOMOVE))\r
676                                 SetWindowPos(hCharWnd, 0, wp->x + ptWinOffset.x, wp->y + ptWinOffset.y,\r
677                                                 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);\r
678                 }\r
679 \r
680                 return DefWindowProc(hWnd, msgID, wParam, lParam);      // Seems this is needed... Bleah!\r
681 \r
682         case WM_PAINT:\r
683         {\r
684                 hdc = BeginPaint(hWnd, &ps);\r
685 \r
686 // Scrolling can be done by using OffsetViewportOrgEx\r
687 // Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform)\r
688 // you'd use: % = ViewportExt / WindowExt\r
689 // But it makes the window look like crap: fuggetuboutit.\r
690 // Instead, we have to scale EVERYTHING by hand. Crap!\r
691 \r
692                 // Apparently, you *must* save the individual object types (pen, brush, etc.)\r
693 \r
694                 HGDIOBJ oldPen = SelectObject(hdc, hBluePen1),\r
695                         oldBrush = SelectObject(hdc, hNullBrush);\r
696 \r
697             // Draw coordinate axes\r
698 \r
699                 MoveToEx(hdc, 0, -32000, NULL);\r
700                 LineTo(hdc, 0, 32000);\r
701                 MoveToEx(hdc, -32000, 0, NULL);\r
702                 LineTo(hdc, 32000, 0);\r
703 \r
704             // Draw points\r
705 \r
706                 for(int i=0; i<pts.GetNumPoints(); i++)\r
707                 {\r
708                         if (i == ptHighlight)\r
709                         {\r
710                                 SelectObject(hdc, hRedPen1);\r
711 \r
712                                 if (pts.GetOnCurve(i))\r
713                                 {\r
714                                         DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 7);\r
715                                         DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 9);\r
716                                 }\r
717                                 else\r
718                                 {\r
719                                         DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 7);\r
720                                         DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 9);\r
721                                 }\r
722                         }\r
723                         else if ((i == ptHighlight || i == ptNextHighlight) && currentTool == TOOLAddPt)\r
724                         {\r
725                                 SelectObject(hdc, hGreenPen1);\r
726 \r
727                                 if (pts.GetOnCurve(i))\r
728                                 {\r
729                                         DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 7);\r
730                                         DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 9);\r
731                                 }\r
732                                 else\r
733                                 {\r
734                                         DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 7);\r
735                                         DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 9);\r
736                                 }\r
737                         }\r
738                         else\r
739                         {\r
740                                 SelectObject(hdc, hBlackPen1);\r
741 \r
742                                 if (pts.GetOnCurve(i))\r
743                                         DrawSquareDot(hdc, pts.GetX(i), pts.GetY(i));\r
744                                 else\r
745                                         DrawRoundDot(hdc, pts.GetX(i), pts.GetY(i));\r
746                         }\r
747 \r
748                         if (currentTool == TOOLDelPt && i == ptHighlight)\r
749                         {\r
750                                 SelectObject(hdc, hRedPen1);\r
751                                 MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL);\r
752                                 LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5);\r
753                                 LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness!\r
754                                 MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL);\r
755                                 LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5);\r
756                                 LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!!\r
757                         }\r
758                 }\r
759 \r
760                 SelectObject(hdc, hBlackPen1);\r
761 \r
762                 // Draw curve formed by points\r
763 \r
764                 for(int poly=0; poly<pts.GetNumPolys(); poly++)\r
765                 {\r
766                         if (pts.GetNumPoints(poly) > 2)\r
767                         {\r
768                                 // Initial move...\r
769                                 // If it's not on curve, then move to it, otherwise move to last point...\r
770         \r
771                                 if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1))\r
772                                         MoveToEx(hdc, pts.GetX(poly, pts.GetNumPoints(poly) - 1), pts.GetY(poly, pts.GetNumPoints(poly) - 1), NULL);\r
773                                 else\r
774                                         MoveToEx(hdc, pts.GetX(poly, 0), pts.GetY(poly, 0), NULL);\r
775         \r
776                                 for(int i=0; i<pts.GetNumPoints(poly); i++)\r
777                                 {\r
778                                         if (pts.GetOnCurve(poly, i))\r
779                                                 LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));\r
780                                         else\r
781                                         {\r
782                                                 uint32 prev = pts.GetPrev(poly, i), next = pts.GetNext(poly, i);\r
783                                                 float px = pts.GetX(poly, prev), py = pts.GetY(poly, prev),\r
784                                                         nx = pts.GetX(poly, next), ny = pts.GetY(poly, next);\r
785         \r
786                                                 if (!pts.GetOnCurve(poly, prev))\r
787                                                         px = (px + pts.GetX(poly, i)) / 2.0f,\r
788                                                         py = (py + pts.GetY(poly, i)) / 2.0f;\r
789         \r
790                                                 if (!pts.GetOnCurve(poly, next))\r
791                                                         nx = (nx + pts.GetX(poly, i)) / 2.0f,\r
792                                                         ny = (ny + pts.GetY(poly, i)) / 2.0f;\r
793         \r
794                                                 Bezier(hdc, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));\r
795         \r
796                                                 if (pts.GetOnCurve(poly, next))\r
797                                                         i++;                                    // Following point is on curve, so move past it\r
798                                         }\r
799                                 }\r
800                         }\r
801                 }\r
802 \r
803                 SelectObject(hdc, oldPen);                              // Restore the stuff we disrupted...\r
804                 SelectObject(hdc, oldBrush);\r
805                 EndPaint(hWnd, &ps);\r
806                 break;\r
807         }\r
808         case WM_SIZE:\r
809 \r
810                 // Apparently this is needed since these windows don't update themselves.\r
811                 SendMessage(hStatusBar, msgID, wParam, lParam);\r
812                 SendMessage(hToolBar, msgID, wParam, lParam);\r
813 \r
814                 // This is needed to make the 2nd status pane visible\r
815                 GetClientRect(hWnd, &rc1);\r
816                 pt.x = rc1.right - zoomWndWidth, pt.y = -1;\r
817                 SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&pt);\r
818                 break;\r
819 \r
820         case WM_RBUTTONDOWN:\r
821 \r
822                 GetCursorPos(&pt);\r
823                 SetWindowPos(hToolPalWnd, 0, pt.x, pt.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);\r
824                 SetFocus(hToolPalWnd);\r
825                 SetCapture(hToolPalWnd);                                // Ensure tool palette gets RButtonUp\r
826                 SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));        // Tool pallete has "regular" cursor\r
827                 break;\r
828 \r
829         case WM_LBUTTONDOWN:\r
830 \r
831                 mouseDown = true;\r
832 \r
833                 if (currentTool == TOOLScroll || currentTool == TOOLZoom)\r
834                         SetCapture(hWnd);                                       // Make sure we capture the mouse when in scroll/zoom mode\r
835                 else if (currentTool == TOOLAddPt)              // "Add Point" tool\r
836                 {\r
837                         if (pts.GetNumPoints() > 0)\r
838                         {\r
839 //Do we really need to put a cap on this???\r
840 //Maybe...\r
841 //                              if (pts.GetNumPoints() < 16)\r
842 //                              {\r
843                                 pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;\r
844                                 hdc = GetDC(hWnd);\r
845                                 DPtoLP(hdc, &pt, 1);\r
846                                 pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true));\r
847                                 ptHighlight = ptNextHighlight;\r
848                                 ReleaseDC(hWnd, hdc);\r
849                                 InvalidateRect(hWnd, NULL, TRUE);\r
850 //                              }\r
851                         }\r
852                 }\r
853                 else if (currentTool == TOOLAddPoly)    // "Add Poly" tool\r
854                 {\r
855 #ifdef DEBUGFOO\r
856 wsprintf(strBuf, "Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());\r
857 WriteLogMsg(strBuf);\r
858 #endif\r
859                         if (polyFirstPoint)\r
860                         {\r
861                                 polyFirstPoint = false;\r
862                                 pts.AddNewPolyAtEnd();\r
863                         }\r
864 \r
865 //Do we really need to put a cap on this???\r
866 //Maybe...\r
867 //                      if (pts.GetNumPoints() < 16)\r
868 //                      {\r
869                         pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;\r
870                         hdc = GetDC(hWnd);\r
871                         DPtoLP(hdc, &pt, 1);\r
872                         ReleaseDC(hWnd, hdc);\r
873                         // Append a point to the end of the structure\r
874                         pts += IPoint(pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true));\r
875 ptHighlight = pts.GetNumPoints() - 1;\r
876                         InvalidateRect(hWnd, NULL, TRUE);\r
877 //                      }\r
878 #ifdef DEBUGFOO\r
879 wsprintf(strBuf, " --> [# polys: %u, # points: %u]\xD\xA", pts.GetNumPolys(), pts.GetNumPoints());\r
880 WriteLogMsg(strBuf);\r
881 #endif\r
882                 }\r
883                 else if (currentTool == TOOLSelect || currentTool == TOOLPolySelect)\r
884                 {\r
885                         if (pts.GetNumPoints() > 0)\r
886                         {\r
887                                 pt.x = pts.GetX(ptHighlight), pt.y = pts.GetY(ptHighlight);\r
888                                 hdc = GetDC(hWnd);\r
889                                 LPtoDP(hdc, &pt, 1);\r
890                                 ClientToScreen(hWnd, &pt);\r
891                                 SetCursorPos(pt.x, pt.y);\r
892                                 ReleaseDC(hWnd, hdc);\r
893 \r
894                                 if (wParam & (MK_SHIFT | MK_CONTROL))\r
895                                         pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight));\r
896                         }\r
897                 }\r
898                 else if (currentTool == TOOLDelPt)\r
899                 {\r
900                         if (pts.GetNumPoints() > 0)\r
901 //Or could use:\r
902 //                      if (ptHighlight != -1)\r
903                         {\r
904 //This assumes that WM_MOUSEMOVE happens before this!\r
905 //The above commented out line should take care of this contingency... !!! FIX !!!\r
906                                 pts.DeletePoint(ptHighlight);\r
907                                 InvalidateRect(hWnd, NULL, TRUE);\r
908                         }\r
909                 }\r
910 \r
911                 break;\r
912 \r
913         case WM_LBUTTONUP:\r
914 \r
915                 mouseDown = false;\r
916 \r
917                 if (currentTool == TOOLScroll || currentTool == TOOLZoom)\r
918                         ReleaseCapture();\r
919 \r
920                 break;\r
921 \r
922         case WM_MOUSEMOVE:\r
923 \r
924                 SetCursor(hCur[currentTool]);\r
925 \r
926             // Extract current point from lParam/calc offset from previous point\r
927 \r
928                 pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;\r
929                 ptOffset.x = pt.x - ptPrevious.x,\r
930                 ptOffset.y = pt.y - ptPrevious.y;\r
931 \r
932                 if (mouseDown)\r
933                 {\r
934                         if (currentTool == TOOLScroll)\r
935                         {\r
936                                 // NOTE: OffsetViewportOrg operates in DEVICE UNITS...\r
937 \r
938                                 hdc = GetDC(hWnd);\r
939                                 OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL);\r
940                                 ReleaseDC(hWnd, hdc);\r
941 \r
942 // this shows that it works, so the logic above must be faulty...\r
943 // And it is. It should convert the coords first, then do the subtraction to figure the offset...\r
944 // Above: DONE\r
945 // Then multiply it by the scaling factor. Whee!\r
946 \r
947                                 InvalidateRect(hWnd, NULL, TRUE);\r
948 //                              SendMessage(hWnd, WM_PAINT, NULL, NULL);\r
949                         }\r
950                         else if (currentTool == TOOLAddPt || currentTool == TOOLAddPoly || currentTool == TOOLSelect)\r
951                         {\r
952                                 if (currentTool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.\r
953                                 {\r
954                                         POINT pt2;\r
955                                         pt2.x = pt.x, pt2.y = pt.y;\r
956                                         // Should also set onCurve here as well, depending on keystate\r
957 //Or should we?\r
958                                         hdc = GetDC(hWnd);\r
959                                         DPtoLP(hdc, &pt2, 1);\r
960                                         pts.SetXY(ptHighlight, pt2.x, pt2.y);\r
961                                         ReleaseDC(hWnd, hdc);\r
962                                         InvalidateRect(hWnd, NULL, TRUE);\r
963                                 }\r
964                         }\r
965                         else if (currentTool == TOOLPolySelect)\r
966                         {\r
967                                 if (pts.GetNumPoints() > 0)\r
968                                 {\r
969                                         POINT pt2;\r
970                                         pt2.x = pt.x, pt2.y = pt.y;\r
971                                         // Should also set onCurve here as well, depending on keystate\r
972 //Or should we?\r
973                                         hdc = GetDC(hWnd);\r
974                                         DPtoLP(hdc, &pt2, 1);\r
975                                         pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));\r
976                                         ReleaseDC(hWnd, hdc);\r
977                                         InvalidateRect(hWnd, NULL, TRUE);\r
978                                 }\r
979                         }\r
980                 }\r
981                 else\r
982                 {\r
983                         if (currentTool == TOOLSelect || currentTool == TOOLDelPt || currentTool == TOOLAddPt\r
984                                 || currentTool == TOOLPolySelect)// || currentTool == TOOLAddPoly)\r
985                         {\r
986                                 POINT pt2;\r
987                                 pt2.x = pt.x, pt2.y = pt.y;\r
988                                 hdc = GetDC(hWnd);\r
989                                 DPtoLP(hdc, &pt2, 1);\r
990                                 ReleaseDC(hWnd, hdc);\r
991 \r
992                                 double closest = 1.0e+99;\r
993 \r
994                                 for(int i=0; i<pts.GetNumPoints(); i++)\r
995                                 {\r
996                                         double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))\r
997                                                 + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));\r
998 \r
999                                         if (dist < closest)\r
1000                                                 closest = dist, ptHighlight = i;\r
1001                                 }\r
1002 \r
1003                                 if (ptHighlight != oldPtHighlight)\r
1004                                 {\r
1005                                         oldPtHighlight = ptHighlight;\r
1006                                         InvalidateRect(hWnd, NULL, TRUE);\r
1007                                 }\r
1008 \r
1009                                 // What follows here looks like voodoo, but is really simple. What we do is\r
1010                                 // check to see if the mouse point has a perpendicular intersection with any of\r
1011                                 // the line segments. If it does, calculate the length of the perpendicular\r
1012                                 // and choose the smallest length. If there is no perpendicular, then choose the\r
1013                                 // length of line connecting the closer of either the first endpoint or the\r
1014                                 // second and choose the smallest of those.\r
1015 \r
1016                                 // There is one bit of math that looks like voodoo to me ATM--will explain once\r
1017                                 // I understand it better (the calculation of the length of the perpendicular).\r
1018 \r
1019                                 if (pts.GetNumPoints() > 1 && currentTool == TOOLAddPt)\r
1020                                 {\r
1021                                         double smallest = 1.0e+99;\r
1022 \r
1023                                         for(int i=0; i<pts.GetNumPoints(); i++)\r
1024                                         {\r
1025                                                 int32 p1x = pts.GetX(i), p1y = pts.GetY(i),\r
1026                                                         p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));\r
1027 \r
1028                                                 vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x, pt2.y, 0, p1x, p1y, 0),\r
1029                                                         v2(pt2.x, pt2.y, 0, p2x, p2y, 0);\r
1030                                                 double pp = ls.dot(v1) / ls.length(), dist;\r
1031 // Geometric interpretation:\r
1032 // pp is the paremeterized point on the vector ls where the perpendicular intersects ls.\r
1033 // If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,\r
1034 // then the perpendicular lies beyond the 2nd endpoint.\r
1035 \r
1036                                                 if (pp < 0.0)\r
1037                                                         dist = v1.length();\r
1038                                                 else if (pp > ls.length())\r
1039                                                         dist = v2.length();\r
1040                                                 else                                    // distance = ?Det?(ls, v1) / |ls|\r
1041                                                         dist = abs((ls.x * v1.y - v1.x * ls.y) / ls.length());\r
1042 \r
1043 //The answer to the above looks like it might be found here:\r
1044 //\r
1045 //If the segment endpoints are s and e, and the point is p, then the test for the perpendicular\r
1046 //intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and\r
1047 //{e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is\r
1048 //computed by first computing the area of the triangle the three points form, then dividing by the\r
1049 //length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the\r
1050 //triangle formed by three points is the determinant of the following matrix:\r
1051 //\r
1052 //sx sy 1\r
1053 //ex ey 1\r
1054 //px py 1\r
1055 //\r
1056 //(???) By translating the start point to the origin, this can be rewritten as:\r
1057 //By subtracting row 1 from all rows, you get the following:\r
1058 //\r
1059 //0         0         0\r
1060 //(ex - sx) (ey - sy) 0\r
1061 //(px - sx) (py - sy) 0\r
1062 //\r
1063 //which greatly simplifies the calculation of the determinant.\r
1064 \r
1065                                                 if (dist < smallest)\r
1066                                                         smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i;\r
1067                                         }\r
1068 \r
1069                                         if (ptNextHighlight != oldPtNextHighlight)\r
1070                                         {\r
1071                                                 oldPtNextHighlight = ptNextHighlight;\r
1072                                                 InvalidateRect(hWnd, NULL, TRUE);\r
1073                                         }\r
1074                                 }\r
1075                         }\r
1076                 }\r
1077 \r
1078                 ptPrevious.x = pt.x, ptPrevious.y = pt.y;\r
1079 \r
1080                 break;\r
1081 \r
1082         case WM_NOTIFY:\r
1083 \r
1084                 if (((NMHDR *)lParam)->code == TTN_NEEDTEXT)\r
1085                 {\r
1086                         LoadString(hInst, ((TOOLTIPTEXT *)lParam)->hdr.idFrom + 0x80, toolTipTxt, 16);\r
1087                         ((TOOLTIPTEXT *)lParam)->lpszText = toolTipTxt;\r
1088                 }\r
1089 \r
1090                 break;\r
1091 \r
1092         case WM_MENUSELECT:\r
1093         {\r
1094                 statusBarTxt[0] = 0;                                    // Clear status bar text\r
1095                 uint16 flags = wParam >> 16;                    // Extract flags\r
1096 \r
1097                 if (!(flags & MFT_SEPARATOR))\r
1098                 {\r
1099                         uint16 id = wParam & 0xFFFF;\r
1100 \r
1101                         if (flags & MF_POPUP)\r
1102                         {\r
1103                                 if (flags & MF_SYSMENU)\r
1104                                         id = IDS_SYSMENU;\r
1105                                 else\r
1106                                         id = IDM_FILEMENU + wParam;\r
1107                         }\r
1108 \r
1109                         LoadString(hInst, id, statusBarTxt, 64);\r
1110                 }\r
1111 \r
1112                 SendMessage(hStatusBar, SB_SETTEXT, 0 + SBT_NOBORDERS, (LPARAM)statusBarTxt);\r
1113                 break;\r
1114         }\r
1115         case WM_COMMAND:\r
1116         {\r
1117                 uint16 cmd = wParam & 0xFFFF;\r
1118 \r
1119                 if (cmd == IDM_NEW)\r
1120                 {\r
1121 //                    call   CmdIDM_NEW\r
1122                 }\r
1123                 else if (cmd == IDM_OPEN)\r
1124                 {\r
1125 //                    call   SaveChanges\r
1126 //                    .IF (eax)\r
1127 //                      movmov ofn.hwndOwner, eax, hMainWnd\r
1128 //                      mov    ofn.Flags, OFN_PATHMUSTEXIST + OFN_FILEMUSTEXIST\r
1129 //                      invoke GetOpenFileName, ADDR ofn\r
1130 //                      .IF (eax)\r
1131 ////////\r
1132 //jmp @F\r
1133 //szDMsg1a      BYTE    "Could not open the file (GetOpenFileName)...", 0\r
1134 //szDMsg1b      BYTE    "Open error!", 0\r
1135 //szDMsg1c      BYTE    "About to attempt to open file...", 0\r
1136 //@@:\r
1137 ////invoke MessageBox, hWnd, ADDR szDMsg1a, ADDR szDMsg1b, MB_ICONERROR or MB_OK\r
1138 //invoke MessageBox, hMainWnd, ADDR szDMsg1c, ADDR szFile, MB_ICONERROR or MB_OK\r
1139 //                        invoke LoadTTF, ADDR szFile\r
1140 //\r
1141 //////\r
1142 //                        // <<< FILE OPEN CODE HERE >>>\r
1143 //                        or     fFileStatus, NAMEDbit\r
1144 //                        and    fFileStatus, NOT CHANGEDbit\r
1145 //                        call   NewWindowName\r
1146 //                        mov    eax, TRUE      // return TRUE\r
1147 //                        jmp    Return\r
1148 //                        //��������������������������������������\r
1149 //OpenError:              invoke GetLastError\r
1150 //                        // <<< FILE OPEN ERROR CODE HERE >>>\r
1151 //                      .ENDIF\r
1152 //                      zero   eax      // return FALSE\r
1153 //                    .ENDIF\r
1154                 }\r
1155                 else if (cmd == IDM_SAVEAS)\r
1156                 {\r
1157 //                    and    fFileStatus, NOT NAMEDbit\r
1158 //                    call   CmdIDM_SAVE\r
1159                 }\r
1160                 else if (cmd == IDM_SAVE)\r
1161                 {\r
1162 //                    call   CmdIDM_SAVE\r
1163                 }\r
1164                 else if (cmd == IDM_ABOUT)\r
1165                         DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ABOUT), hMainWnd, AboutProc, NULL);\r
1166                 else if (cmd == IDM_EXIT)\r
1167                         SendMessage(hWnd, WM_CLOSE, 0, 0);\r
1168                 else if (cmd == ID_TBCHARWIN)\r
1169                 {\r
1170                         ShowWindow(hCharWnd, (IsWindowVisible(hCharWnd) ? SW_HIDE : SW_SHOWNOACTIVATE));\r
1171 \r
1172 #ifdef DEBUGFOO\r
1173 wpC.length = sizeof(WINDOWPLACEMENT);\r
1174 GetWindowPlacement(hCharWnd, &wpC);\r
1175 wsprintf(strBuf, "Char window showCmd = %08X...\n", wpC.showCmd);\r
1176 WriteLogMsg(strBuf);\r
1177 #endif\r
1178                 }\r
1179                 else\r
1180                         return DefWindowProc(hWnd, msgID, wParam, lParam);\r
1181 \r
1182                 break;\r
1183         }\r
1184         default:\r
1185                 return DefWindowProc(hWnd, msgID, wParam, lParam);\r
1186         }\r
1187 \r
1188         return 0;\r
1189 }\r
1190 \r
1191 //\r
1192 // Initialize TTF data\r
1193 //\r
1194 void CreateNewDoc(void)\r
1195 {\r
1196 }\r
1197 \r
1198 //\r
1199 // Save changes to document before quitting\r
1200 //\r
1201 bool SaveChanges(void)\r
1202 {\r
1203         return true;\r
1204 }\r
1205 \r
1206 \r
1207 \r
1208 //\r
1209 // ABOUT Dialog WndProc\r
1210 //\r
1211 BOOL CALLBACK AboutProc(HWND hDlg, UINT msgID, WPARAM wParam, LPARAM lParam)\r
1212 {\r
1213         switch (msgID)\r
1214         {\r
1215         case WM_INITDIALOG:\r
1216 \r
1217                 MiscCenterWnd(hDlg, hMainWnd);\r
1218                 break;\r
1219 \r
1220         case WM_COMMAND:\r
1221 \r
1222                 if (wParam == IDOK || wParam == IDCANCEL)\r
1223                         EndDialog(hDlg, TRUE);\r
1224 \r
1225                 break;\r
1226 \r
1227         default:\r
1228                 return FALSE;\r
1229         }\r
1230 \r
1231         return TRUE;\r
1232 }\r
1233 \r
1234 //\r
1235 // Character Window WndProc\r
1236 //\r
1237 WndProcCW       PROC  STDCALL, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM\r
1238 \r
1239                 mov    eax, uMsg                // pickup our message\r
1240                 .IF (eax == WM_PAINT)\r
1241                   mov    eax, 0                 // Non-sense... (placeholder!)\r
1242 // Scan conversion etc. goes here...\r
1243                 .ELSEIF (eax == WM_LBUTTONDOWN)\r
1244                   invoke SetCapture, hCharWnd\r
1245                 .ELSEIF (eax == WM_LBUTTONUP)\r
1246                   invoke ReleaseCapture\r
1247                   invoke SetFocus, hMainWnd     // Make sure the main wnd keeps focus!\r
1248                 .ELSEIF (eax == WM_NCLBUTTONDOWN)\r
1249                   invoke DefWindowProc, hWnd, uMsg, wParam, lParam // Let it do its thing\r
1250                   invoke SetFocus, hMainWnd     // Make sure the main wnd keeps focus!\r
1251                 .ELSE\r
1252 DefProc:          invoke DefWindowProc, hWnd, uMsg, wParam, lParam\r
1253                 .ENDIF\r
1254                 ret\r
1255 \r
1256 WndProcCW       ENDP\r
1257 \r
1258 //\r
1259 // Character Window WndProc\r
1260 //\r
1261 LRESULT CALLBACK WndProcCW(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)\r
1262 {\r
1263         switch (msgID)\r
1264         {\r
1265         default:\r
1266                 return DefWindowProc(hWnd, msgID, wParam, lParam);\r
1267         }\r
1268 \r
1269         return 0;\r
1270 }\r
1271 \r
1272 \r
1273 // Function prototypes\r
1274 \r
1275 int32 FindSelectedTool(void);\r
1276 \r
1277 //\r
1278 // Tool Palette WndProc\r
1279 //\r
1280 LRESULT CALLBACK WndProcTP(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)\r
1281 {\r
1282         PAINTSTRUCT ps;\r
1283         HDC hdc;\r
1284         POINT pt;\r
1285         static uint32 prevTool = -1;\r
1286 \r
1287         switch (msgID)\r
1288         {\r
1289         case WM_PAINT:\r
1290         {\r
1291                 hdc = BeginPaint(hWnd, &ps);\r
1292                 HDC newDC = CreateCompatibleDC(NULL);\r
1293                 SelectObject(newDC, hBMToolPal1);\r
1294                 BitBlt(hdc, 0, 0, sizeTPBM.x, sizeTPBM.y, newDC, 0, 0, SRCCOPY);\r
1295                 DeleteDC(newDC);\r
1296 \r
1297 // This is crappy. Find some way to tighten this up!\r
1298                 int32 tool = FindSelectedTool();\r
1299 \r
1300                 if (tool != -1)\r
1301                 {\r
1302                         newDC = CreateCompatibleDC(NULL);\r
1303                         SelectObject(newDC, hBMToolPal1);\r
1304                     //need ul corner of bitmap, ul corner of dest, width/height\r
1305                         pt.x = sizeStamp.x * (tool & 0x03), pt.y = sizeStamp.y * (tool >> 2);\r
1306                         BitBlt(hdc, pt.x, pt.y, sizeStamp.x, sizeStamp.y, newDC, pt.x, pt.y, NOTSRCCOPY);\r
1307                         DeleteDC(newDC);\r
1308                 }\r
1309 \r
1310                 EndPaint(hWnd, &ps);\r
1311                 break;\r
1312         }\r
1313         case WM_MOUSEMOVE:\r
1314         {\r
1315                 int32 tool = FindSelectedTool();\r
1316 \r
1317                 if (tool != prevTool)\r
1318                 {\r
1319                         prevTool = tool;\r
1320                         InvalidateRect(hWnd, NULL, FALSE);\r
1321                 }\r
1322 \r
1323                 break;\r
1324         }\r
1325         case WM_RBUTTONUP:\r
1326         {\r
1327                 int32 tool = FindSelectedTool(), oldTool = currentTool;\r
1328 \r
1329                 if (tool != -1)\r
1330                         currentTool = tool;\r
1331 \r
1332                 if (currentTool != TOOLSelect && currentTool != TOOLDelPt && currentTool != TOOLAddPt\r
1333                         && currentTool != TOOLPolySelect)\r
1334                         ptHighlight = -1;\r
1335 \r
1336                 if (currentTool != oldTool)\r
1337                         InvalidateRect(hMainWnd, NULL, TRUE);\r
1338 \r
1339                 if (currentTool == TOOLAddPoly)\r
1340 #ifdef DEBUGFOO\r
1341 {\r
1342 #endif\r
1343                         polyFirstPoint = true;\r
1344 #ifdef DEBUGFOO\r
1345 wsprintf(strBuf, "--> Selected poly tool, polyFirstPoint is %s\n", polyFirstPoint ? "true" : "false");\r
1346 WriteLogMsg(strBuf);\r
1347 }\r
1348 #endif\r
1349 \r
1350                 ReleaseCapture();\r
1351                 ShowWindow(hToolPalWnd, SW_HIDE);\r
1352                 SetFocus(hMainWnd);                                             // Make sure the main wnd keeps focus!\r
1353 \r
1354                 break;\r
1355         }\r
1356         default:\r
1357                 return DefWindowProc(hWnd, msgID, wParam, lParam);\r
1358         }\r
1359 \r
1360         return 0;\r
1361 }\r
1362 \r
1363 //\r
1364 // Find which tool we're pointing at\r
1365 // Use: xcoord = mouse.x / (bmsize.x/4), ycoord = mouse.y / (bmsize.y/2)\r
1366 //\r
1367 int32 FindSelectedTool(void)\r
1368 {\r
1369         POINT pt;\r
1370                 \r
1371         GetCursorPos(&pt);\r
1372         ScreenToClient(hToolPalWnd, &pt);\r
1373 \r
1374         uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y, tool = -1;\r
1375 \r
1376         if (x < 4 && y < 2)\r
1377 //      {\r
1378                 tool = (y * 4) + x;\r
1379 \r
1380 //              if (tool == 7)\r
1381 //                      tool = -1;                                                      // 7 has no tool...\r
1382 //      }\r
1383 \r
1384         return tool;\r
1385 }\r
1386 \r
1387 \r
1388 //\r
1389 // Misc center window\r
1390 //\r
1391 void MiscCenterWnd(HWND hChild, HWND hParent)\r
1392 {\r
1393         RECT parent, child;\r
1394 \r
1395         if (!GetWindowRect(hParent, &parent) || !GetWindowRect(hChild, &child))\r
1396                 return;\r
1397 \r
1398         int32 x = parent.left + (((parent.right - parent.left) - (child.right - child.left)) / 2),\r
1399                 y = parent.top + (((parent.bottom - parent.top) - (child.bottom - child.top)) / 2);\r
1400 \r
1401         if (x < 0)\r
1402                 x = 0;\r
1403         else if (x > GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left))\r
1404                 x = GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left);\r
1405 \r
1406         if (y < 0)\r
1407                 y = 0;\r
1408         else if (y > GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top))\r
1409                 y = GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top);\r
1410 \r
1411         SetWindowPos(hChild, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\r
1412 }\r
1413 \r
1414 //\r
1415 // Allow only one instance\r
1416 //\r
1417 bool OnlyOneInstance(void)\r
1418 {\r
1419         HWND window = FindWindow(className, NULL);\r
1420 \r
1421         if (window == NULL)\r
1422                 return true;\r
1423 \r
1424         ShowWindow(window, SW_SHOWNORMAL);\r
1425         SetWindowPos(window, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);\r
1426 \r
1427         return false;\r
1428 }\r
1429 \r
1430 //\r
1431 // Load/Allocate all resources\r
1432 //\r
1433 bool LoadResources(void)\r
1434 {\r
1435         hCur[0] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR1));\r
1436         hCur[1] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR2));\r
1437         hCur[2] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR3));\r
1438         hCur[3] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR4));\r
1439         hCur[4] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR5));\r
1440         hCur[5] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR6));\r
1441         hCur[6] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR7));\r
1442         hCur[7] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR8));\r
1443 \r
1444         BITMAP bm;\r
1445 \r
1446         hBMToolPal1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_TOOLPAL1));\r
1447         GetObject(hBMToolPal1, sizeof(bm), &bm);\r
1448 \r
1449         // Set up sizes\r
1450 \r
1451         sizeTPBM.x = bm.bmWidth, sizeTPBM.y = bm.bmHeight;\r
1452         sizeStamp.x = bm.bmWidth / 4, sizeStamp.y = bm.bmHeight / 2;\r
1453 \r
1454         hBluePen1 = CreatePen(PS_DOT, 1, 0x00FF0000);\r
1455         hRedPen1 = CreatePen(PS_SOLID, 1, 0x000000FF);\r
1456         hGreenPen1 = CreatePen(PS_SOLID, 1, 0x0000AF00);\r
1457         hBlackPen1 = CreatePen(PS_SOLID, 1, 0x00000000);\r
1458 \r
1459         LOGBRUSH lb = { BS_NULL, 0, 0 };\r
1460 \r
1461         hNullBrush = CreateBrushIndirect(&lb);\r
1462 \r
1463         return true;\r
1464 }\r
1465 \r
1466 //\r
1467 // Deallocate all resources\r
1468 //\r
1469 void DeallocateResources(void)\r
1470 {\r
1471         DeleteObject(hBMToolPal1);\r
1472         DeleteObject(hBluePen1);\r
1473         DeleteObject(hRedPen1);\r
1474         DeleteObject(hGreenPen1);\r
1475         DeleteObject(hBlackPen1);\r
1476         DeleteObject(hNullBrush);\r
1477 }\r
1478 \r
1479 //\r
1480 // Save all application specific data, so we can pick up where we last left off...\r
1481 //\r
1482 void SaveAppState(void)\r
1483 {\r
1484         SetINIInt("Main", "flags", wpM.flags);\r
1485         SetINIInt("Main", "showCmd", wpM.showCmd);\r
1486         SetINIInt("Main", "x1", wpM.rcNormalPosition.left);\r
1487         SetINIInt("Main", "y1", wpM.rcNormalPosition.top);\r
1488         SetINIInt("Main", "x2", wpM.rcNormalPosition.right);\r
1489         SetINIInt("Main", "y2", wpM.rcNormalPosition.bottom);\r
1490 \r
1491         SetINIInt("Main", "vpx", ptVPM.x);\r
1492         SetINIInt("Main", "vpy", ptVPM.y);\r
1493 \r
1494         SetINIInt("Char", "flags", wpC.flags);\r
1495         SetINIInt("Char", "showCmd", wpC.showCmd);\r
1496         SetINIInt("Char", "x1", wpC.rcNormalPosition.left);\r
1497         SetINIInt("Char", "y1", wpC.rcNormalPosition.top);\r
1498         SetINIInt("Char", "x2", wpC.rcNormalPosition.right);\r
1499         SetINIInt("Char", "y2", wpC.rcNormalPosition.bottom);\r
1500 \r
1501         // Need to write out currently opened font, character looking at, other misc. crap\r
1502 //      SetINIString("Main", "currentFile", pDoc->GetPathName());\r
1503 //      SetINIInt("Main", "currentChar", pDoc->character_num);\r
1504 }\r
1505 \r
1506 //\r
1507 // Restore all application specific data previously saved\r
1508 //\r
1509 bool RestoreAppState(void)\r
1510 {\r
1511         InitINIFile();\r
1512 \r
1513         WINDOWPLACEMENT wp;\r
1514         wp.length = sizeof(WINDOWPLACEMENT);\r
1515         GetWindowPlacement(hMainWnd, &wp);\r
1516 \r
1517         wp.flags = GetINIInt("Main", "flags", wp.flags);\r
1518         wp.showCmd = GetINIInt("Main", "showCmd", wp.showCmd);\r
1519         wp.rcNormalPosition.left = GetINIInt("Main", "x1", wp.rcNormalPosition.left);\r
1520         wp.rcNormalPosition.top = GetINIInt("Main", "y1", wp.rcNormalPosition.top);\r
1521         wp.rcNormalPosition.right = GetINIInt("Main", "x2", wp.rcNormalPosition.right);\r
1522         wp.rcNormalPosition.bottom = GetINIInt("Main", "y2", wp.rcNormalPosition.bottom);\r
1523 \r
1524         SetWindowPlacement(hMainWnd, &wp);\r
1525 \r
1526         HDC hdc;\r
1527         POINT pt;\r
1528         hdc = GetDC(hMainWnd);\r
1529         GetViewportOrgEx(hdc, &pt);\r
1530 \r
1531         pt.x = GetINIInt("Main", "vpx", pt.x);\r
1532         pt.y = GetINIInt("Main", "vpy", pt.y);\r
1533 \r
1534         SetViewportOrgEx(hdc, pt.x, pt.y, NULL);\r
1535         ReleaseDC(hMainWnd, hdc);\r
1536 \r
1537         GetWindowPlacement(hCharWnd, &wp);\r
1538 \r
1539         wp.flags = GetINIInt("Char", "flags", wp.flags);\r
1540         wp.showCmd = GetINIInt("Char", "showCmd", wp.showCmd);\r
1541         wp.rcNormalPosition.left = GetINIInt("Char", "x1", wp.rcNormalPosition.left);\r
1542         wp.rcNormalPosition.top = GetINIInt("Char", "y1", wp.rcNormalPosition.top);\r
1543         wp.rcNormalPosition.right = GetINIInt("Char", "x2", wp.rcNormalPosition.right);\r
1544         wp.rcNormalPosition.bottom = GetINIInt("Char", "y2", wp.rcNormalPosition.bottom);\r
1545 \r
1546         SetWindowPlacement(hCharWnd, &wp);\r
1547 \r
1548         if (wp.showCmd == SW_HIDE)\r
1549                 SendMessage(hToolBar, TB_SETSTATE, ID_TBCHARWIN, MAKELONG(TBSTATE_ENABLED, 0));\r
1550 \r
1551 //  CString lastFile = theApplicationObject.GetProfileString(version, "currentFile", "");\r
1552 //  int lastChar = theApplicationObject.GetProfileInt(version, "currentChar", 0);\r
1553 //  if (lastFile.GetLength())\r
1554 //  {\r
1555 //    // Attempt to restore the last session by open the last file used, etc...\r
1556 //    if (!pDoc->m_myFont.Load(lastFile))\r
1557 //    {\r
1558 //      // Err, make sure you can support any allegations you make below, buddy!\r
1559 //      AfxMessageBox("The last file opened with TTF Edit\n\rseems to have been moved or deleted.");\r
1560 //    }\r
1561 //    else\r
1562 //    {\r
1563 //      pDoc->m_myFont.SetGlyph(lastChar);  // Set TTF object to last used char\r
1564 //      pDoc->character_num = lastChar;\r
1565 //      pDoc->SetPathName(lastFile);\r
1566 //\r
1567 //      BYTE name[512];\r
1568 //      pDoc->m_myFont.GetCharName(lastChar, name);\r
1569 //      m_wndOwned.SetWindowText((char *)name);\r
1570 //    }\r
1571 //  }\r
1572 \r
1573         return true;\r
1574 }\r
1575 \r
1576 //\r
1577 // Initialization\r
1578 //\r
1579 bool Initialization(void)\r
1580 {\r
1581         WNDCLASSEX wcex;\r
1582 \r
1583         if (!LoadResources())\r
1584                 return false;\r
1585 \r
1586         RtlFillMemory(&wcex, sizeof(WNDCLASSEX), 0);\r
1587         wcex.cbSize = sizeof(WNDCLASSEX);\r
1588         wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;\r
1589         wcex.lpfnWndProc = WndProc;\r
1590         wcex.hInstance = hInst;\r
1591         wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON));\r
1592         wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);\r
1593         wcex.lpszMenuName = MAKEINTRESOURCE(IDM_MENU);\r
1594         wcex.lpszClassName = className;\r
1595         wcex.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, NULL);\r
1596 \r
1597         if (!RegisterClassEx(&wcex))\r
1598                 return false;\r
1599 \r
1600         hMainWnd = CreateWindowEx(NULL, className, className, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,\r
1601                 0, 0, 0x1A0, 0x180, NULL, NULL, hInst, NULL);\r
1602 \r
1603         if (!hMainWnd)\r
1604                 return false;\r
1605 \r
1606         ShowWindow(hMainWnd, nCmdShow);\r
1607         UpdateWindow(hMainWnd);\r
1608 \r
1609         // Character window creation\r
1610 \r
1611         wcex.lpfnWndProc = WndProcCW;\r
1612         wcex.lpszMenuName = NULL;\r
1613         wcex.lpszClassName = CNCharWin;\r
1614         wcex.hCursor = LoadCursor(NULL, IDC_ARROW);     // Owned windows have "regular" cursors\r
1615 \r
1616         if (!RegisterClassEx(&wcex))\r
1617                 return false;\r
1618 \r
1619         hCharWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW, CNCharWin,\r
1620                 curCharName, WS_POPUP | WS_CAPTION | WS_VISIBLE | WS_THICKFRAME,\r
1621                 100, 100, 120, 120, hMainWnd, NULL, hInst, NULL);\r
1622 \r
1623         if (!hCharWnd)\r
1624                 return false;\r
1625 \r
1626         ShowWindow(hCharWnd, SW_SHOWNORMAL);\r
1627         UpdateWindow(hCharWnd);\r
1628         SetFocus(hMainWnd);                                                     // Make sure main wnd has focus!\r
1629 \r
1630         // Tool palette window creation\r
1631 \r
1632         wcex.lpfnWndProc = WndProcTP;\r
1633         wcex.lpszClassName = CNToolPal;\r
1634 \r
1635         if (!RegisterClassEx(&wcex))\r
1636                 return false;\r
1637 \r
1638         hToolPalWnd = CreateWindowEx(WS_EX_WINDOWEDGE, CNToolPal, NULL, WS_POPUP,\r
1639                 0, 0, sizeTPBM.x, sizeTPBM.y, hMainWnd, NULL, hInst, NULL);\r
1640 \r
1641         if (!hToolPalWnd)\r
1642                 return false;\r
1643 \r
1644 // Note: A better way to handle this would be to have a sub that registers ALL\r
1645 //       classes beforehand and passes a TRUE/FALSE back depending on whether or not\r
1646 //       all the classes were able to be registered or not, THEN create the windows\r
1647 //       and controls...\r
1648 \r
1649         RestoreAppState();                                                      // Restore app related stuff\r
1650 \r
1651         return true;\r
1652 }\r
1653 \r
1654 #endif\r