- Move around definitions to make the code a bit more modular
[reactos.git] / reactos / base / applications / charmap / map.c
1 #include <precomp.h>
2
3 static const TCHAR szMapWndClass[] = TEXT("FontMapWnd");
4 static const TCHAR szLrgCellWndClass[] = TEXT("LrgCellWnd");
5
6 static VOID
7 TagFontToCell(PCELL pCell,
8 TCHAR ch)
9 {
10 pCell->ch = ch;
11 }
12
13
14 static VOID
15 SetGrid(PMAP infoPtr)
16 {
17 INT x, y;
18
19 for (y = 0; y < YCELLS; y++)
20 for (x = 0; x < XCELLS; x++)
21 {
22 infoPtr->Cells[y][x].CellExt.left = x * infoPtr->CellSize.cx + 1;
23 infoPtr->Cells[y][x].CellExt.top = y * infoPtr->CellSize.cy + 1;
24 infoPtr->Cells[y][x].CellExt.right = (x + 1) * infoPtr->CellSize.cx + 2;
25 infoPtr->Cells[y][x].CellExt.bottom = (y + 1) * infoPtr->CellSize.cy + 2;
26
27 CopyRect(&infoPtr->Cells[y][x].CellInt,
28 &infoPtr->Cells[y][x].CellExt);
29
30 InflateRect(&infoPtr->Cells[y][x].CellInt,
31 -1,
32 -1);
33 }
34 }
35
36 static VOID
37 DrawActiveCell(PMAP infoPtr,
38 HDC hdc)
39 {
40 Rectangle(hdc,
41 infoPtr->pActiveCell->CellInt.left,
42 infoPtr->pActiveCell->CellInt.top,
43 infoPtr->pActiveCell->CellInt.right,
44 infoPtr->pActiveCell->CellInt.bottom);
45
46 }
47
48
49 static VOID
50 DrawGrid(PMAP infoPtr,
51 HDC hdc)
52 {
53 INT x, y;
54
55 for (y = 0; y < YCELLS; y++)
56 for (x = 0; x < XCELLS; x++)
57 {
58 Rectangle(hdc,
59 infoPtr->Cells[y][x].CellExt.left,
60 infoPtr->Cells[y][x].CellExt.top,
61 infoPtr->Cells[y][x].CellExt.right,
62 infoPtr->Cells[y][x].CellExt.bottom);
63 }
64
65 if (infoPtr->pActiveCell)
66 DrawActiveCell(infoPtr,
67 hdc);
68 }
69
70
71 static VOID
72 FillGrid(PMAP infoPtr,
73 HDC hdc)
74 {
75 //GLYPHSET gs;
76 HFONT hOldFont;
77 TCHAR ch;
78 INT x, y;
79
80 hOldFont = SelectObject(hdc,
81 infoPtr->hFont);
82
83 for (y = 0; y < YCELLS; y++)
84 for (x = 0; x < XCELLS; x++)
85 {
86 ch = (TCHAR)((256 * infoPtr->iPage) + (XCELLS * y) + x);
87
88 TagFontToCell(&infoPtr->Cells[y][x], ch);
89
90 DrawText(hdc,
91 &ch,
92 1,
93 &infoPtr->Cells[y][x].CellInt,
94 DT_CENTER | DT_VCENTER | DT_SINGLELINE);
95 }
96
97 SelectObject(hdc,
98 hOldFont);
99 }
100
101
102 static BOOL
103 CreateLargeCell(PMAP infoPtr)
104 {
105 RECT rLarge;
106
107 CopyRect(&rLarge,
108 &infoPtr->pActiveCell->CellExt);
109
110 MapWindowPoints(infoPtr->hMapWnd,
111 infoPtr->hParent,
112 (LPPOINT)&rLarge,
113 2);
114
115 InflateRect(&rLarge,
116 XLARGE - XCELLS,
117 YLARGE - YCELLS);
118
119 infoPtr->hLrgWnd = CreateWindowEx(0,
120 szLrgCellWndClass,
121 NULL,
122 WS_CHILDWINDOW | WS_VISIBLE,
123 rLarge.left,
124 rLarge.top,
125 rLarge.right - rLarge.left,
126 rLarge.bottom - rLarge.top,
127 infoPtr->hParent,
128 NULL,
129 hInstance,
130 infoPtr);
131 if (!infoPtr->hLrgWnd)
132 return FALSE;
133
134 return TRUE;
135 }
136
137
138 static VOID
139 MoveLargeCell(PMAP infoPtr)
140 {
141 RECT rLarge;
142
143 CopyRect(&rLarge,
144 &infoPtr->pActiveCell->CellExt);
145
146 MapWindowPoints(infoPtr->hMapWnd,
147 infoPtr->hParent,
148 (LPPOINT)&rLarge,
149 2);
150
151 InflateRect(&rLarge,
152 XLARGE - XCELLS,
153 YLARGE - YCELLS);
154
155 MoveWindow(infoPtr->hLrgWnd,
156 rLarge.left,
157 rLarge.top,
158 rLarge.right - rLarge.left,
159 rLarge.bottom - rLarge.top,
160 TRUE);
161
162 InvalidateRect(infoPtr->hLrgWnd,
163 NULL,
164 TRUE);
165 }
166
167
168 static VOID
169 SetFont(PMAP infoPtr,
170 LPTSTR lpFontName)
171 {
172 HDC hdc;
173
174 if (infoPtr->hFont)
175 DeleteObject(infoPtr->hFont);
176
177 ZeroMemory(&infoPtr->CurrentFont,
178 sizeof(LOGFONT));
179
180 hdc = GetDC(infoPtr->hMapWnd);
181 infoPtr->CurrentFont.lfHeight = GetDeviceCaps(hdc,
182 LOGPIXELSY) / 5;
183 ReleaseDC(infoPtr->hMapWnd, hdc);
184
185 infoPtr->CurrentFont.lfCharSet = DEFAULT_CHARSET;
186 lstrcpy(infoPtr->CurrentFont.lfFaceName,
187 lpFontName);
188
189 infoPtr->hFont = CreateFontIndirect(&infoPtr->CurrentFont);
190
191 InvalidateRect(infoPtr->hMapWnd,
192 NULL,
193 TRUE);
194 }
195
196
197 static VOID
198 OnClick(PMAP infoPtr,
199 WORD ptx,
200 WORD pty)
201 {
202 POINT pt;
203 INT x, y;
204
205 pt.x = ptx;
206 pt.y = pty;
207
208 for (x = 0; x < XCELLS; x++)
209 for (y = 0; y < YCELLS; y++)
210 {
211 if (PtInRect(&infoPtr->Cells[y][x].CellInt,
212 pt))
213 {
214 /* if the cell is not already active */
215 if (!infoPtr->Cells[y][x].bActive)
216 {
217 /* set previous active cell to inactive */
218 if (infoPtr->pActiveCell)
219 {
220 /* invalidate normal cells, required when
221 * moving a small active cell via keyboard */
222 if (!infoPtr->pActiveCell->bLarge)
223 {
224 InvalidateRect(infoPtr->hMapWnd,
225 &infoPtr->pActiveCell->CellInt,
226 TRUE);
227 }
228
229 infoPtr->pActiveCell->bActive = FALSE;
230 infoPtr->pActiveCell->bLarge = FALSE;
231 }
232
233 /* set new cell to active */
234 infoPtr->pActiveCell = &infoPtr->Cells[y][x];
235 infoPtr->pActiveCell->bActive = TRUE;
236 infoPtr->pActiveCell->bLarge = TRUE;
237 if (infoPtr->hLrgWnd)
238 MoveLargeCell(infoPtr);
239 else
240 CreateLargeCell(infoPtr);
241 }
242 else
243 {
244 /* flick between large and small */
245 if (infoPtr->pActiveCell->bLarge)
246 {
247 DestroyWindow(infoPtr->hLrgWnd);
248 infoPtr->hLrgWnd = NULL;
249 }
250 else
251 {
252 CreateLargeCell(infoPtr);
253 }
254
255 infoPtr->pActiveCell->bLarge = (infoPtr->pActiveCell->bLarge) ? FALSE : TRUE;
256 }
257
258 break;
259 }
260 }
261 }
262
263
264 static BOOL
265 OnCreate(PMAP infoPtr,
266 HWND hwnd,
267 HWND hParent)
268 {
269 RECT rc;
270 BOOL Ret = FALSE;
271
272 infoPtr = HeapAlloc(GetProcessHeap(),
273 0,
274 sizeof(MAP));
275 if (infoPtr)
276 {
277 SetLastError(0);
278 SetWindowLongPtr(hwnd,
279 0,
280 (DWORD_PTR)infoPtr);
281 if (GetLastError() == 0)
282 {
283 ZeroMemory(infoPtr,
284 sizeof(MAP));
285
286 infoPtr->hMapWnd = hwnd;
287 infoPtr->hParent = hParent;
288
289 GetClientRect(hwnd, &rc);
290 infoPtr->ClientSize.cx = rc.right;
291 infoPtr->ClientSize.cy = rc.bottom;
292 infoPtr->CellSize.cx = infoPtr->ClientSize.cx / XCELLS;
293 infoPtr->CellSize.cy = infoPtr->ClientSize.cy / YCELLS;
294
295 infoPtr->pActiveCell = NULL;
296
297 SetGrid(infoPtr);
298
299 SetScrollRange(hwnd, SB_VERT, 0, 255, FALSE);
300 SetScrollPos(hwnd, SB_VERT, 0, TRUE);
301
302 Ret = TRUE;
303 }
304 }
305
306 return Ret;
307 }
308
309
310 static VOID
311 OnVScroll(PMAP infoPtr,
312 INT Value,
313 INT Pos)
314 {
315 switch (Value)
316 {
317 case SB_LINEUP:
318 infoPtr->iPage -= 1;
319 break;
320
321 case SB_LINEDOWN:
322 infoPtr->iPage += 1;
323 break;
324
325 case SB_PAGEUP:
326 infoPtr->iPage -= 16;
327 break;
328
329 case SB_PAGEDOWN:
330 infoPtr->iPage += 16;
331 break;
332
333 case SB_THUMBPOSITION:
334 infoPtr->iPage = Pos;
335 break;
336
337 default:
338 break;
339 }
340
341 infoPtr->iPage = max(0,
342 min(infoPtr->iPage,
343 255));
344
345 SetScrollPos(infoPtr->hMapWnd,
346 SB_VERT,
347 infoPtr->iPage,
348 TRUE);
349
350 InvalidateRect(infoPtr->hMapWnd,
351 NULL,
352 TRUE);
353 }
354
355
356 static VOID
357 OnPaint(PMAP infoPtr,
358 WPARAM wParam)
359 {
360 PAINTSTRUCT ps;
361 HDC hdc;
362
363
364 if (wParam != 0)
365 {
366 if (!GetUpdateRect(infoPtr->hMapWnd,
367 &ps.rcPaint,
368 TRUE))
369 {
370 return;
371 }
372 hdc = (HDC)wParam;
373 }
374 else
375 {
376 hdc = BeginPaint(infoPtr->hMapWnd,
377 &ps);
378 if (hdc == NULL)
379 {
380 return;
381 }
382 }
383
384 DrawGrid(infoPtr,
385 hdc);
386
387 FillGrid(infoPtr,
388 hdc);
389
390 if (wParam == 0)
391 {
392 EndPaint(infoPtr->hMapWnd,
393 &ps);
394 }
395 }
396
397
398 LRESULT CALLBACK
399 MapWndProc(HWND hwnd,
400 UINT uMsg,
401 WPARAM wParam,
402 LPARAM lParam)
403 {
404 PMAP infoPtr;
405 LRESULT Ret = 0;
406
407 infoPtr = (PMAP)GetWindowLongPtr(hwnd,
408 0);
409
410 switch (uMsg)
411 {
412 case WM_CREATE:
413 {
414 if (!OnCreate(infoPtr,
415 hwnd,
416 ((LPCREATESTRUCTW)lParam)->hwndParent))
417 {
418 return (LRESULT)-1;
419 }
420
421 break;
422 }
423
424 case WM_LBUTTONDOWN:
425 {
426 OnClick(infoPtr,
427 LOWORD(lParam),
428 HIWORD(lParam));
429
430 break;
431 }
432
433 case WM_VSCROLL:
434 {
435 OnVScroll(infoPtr,
436 LOWORD(wParam),
437 HIWORD(wParam));
438
439 break;
440 }
441
442 case FM_SETFONT:
443 {
444 LPTSTR lpFontName = (LPTSTR)lParam;
445
446 SetFont(infoPtr,
447 lpFontName);
448
449 HeapFree(GetProcessHeap(),
450 0,
451 lpFontName);
452
453 break;
454 }
455
456 case WM_PAINT:
457 {
458 OnPaint(infoPtr,
459 wParam);
460 break;
461 }
462
463 case WM_DESTROY:
464 {
465 DeleteObject(infoPtr->hFont);
466 HeapFree(GetProcessHeap(),
467 0,
468 infoPtr);
469 SetWindowLongPtr(hwnd,
470 0,
471 (DWORD_PTR)NULL);
472 break;
473 }
474
475 default:
476 {
477 Ret = DefWindowProc(hwnd,
478 uMsg,
479 wParam,
480 lParam);
481 break;
482 }
483 }
484
485 return Ret;
486 }
487
488 BOOL
489 RegisterMapClasses(HINSTANCE hInstance)
490 {
491 WNDCLASS wc = {0};
492
493 //wc.style = CS_DBLCLKS;
494 wc.lpfnWndProc = MapWndProc;
495 wc.cbWndExtra = sizeof(PMAP);
496 wc.hInstance = hInstance;
497 wc.hCursor = LoadCursor(NULL,
498 (LPTSTR)IDC_ARROW);
499 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
500 wc.lpszClassName = szMapWndClass;
501
502 if (RegisterClass(&wc))
503 {
504 wc.lpfnWndProc = LrgCellWndProc;
505 wc.cbWndExtra = 0;
506 wc.lpszClassName = szLrgCellWndClass;
507
508 return RegisterClass(&wc) != 0;
509 }
510
511 return FALSE;
512 }
513
514 VOID
515 UnregisterMapClasses(HINSTANCE hInstance)
516 {
517 UnregisterClass(szMapWndClass,
518 hInstance);
519
520 UnregisterClass(szLrgCellWndClass,
521 hInstance);
522 }