2 * PROJECT: ReactOS Character Map
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/charmap/map.c
5 * PURPOSE: class implementation for painting glyph region
6 * COPYRIGHT: Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
14 static const WCHAR szMapWndClass
[] = L
"FontMapWnd";
15 static const WCHAR szLrgCellWndClass
[] = L
"LrgCellWnd";
19 TagFontToCell(PCELL pCell
,
32 for (y
= 0; y
< YCELLS
; y
++)
33 for (x
= 0; x
< XCELLS
; x
++)
35 infoPtr
->Cells
[y
][x
].CellExt
.left
= x
* infoPtr
->CellSize
.cx
+ 1;
36 infoPtr
->Cells
[y
][x
].CellExt
.top
= y
* infoPtr
->CellSize
.cy
+ 1;
37 infoPtr
->Cells
[y
][x
].CellExt
.right
= (x
+ 1) * infoPtr
->CellSize
.cx
+ 2;
38 infoPtr
->Cells
[y
][x
].CellExt
.bottom
= (y
+ 1) * infoPtr
->CellSize
.cy
+ 2;
40 CopyRect(&infoPtr
->Cells
[y
][x
].CellInt
,
41 &infoPtr
->Cells
[y
][x
].CellExt
);
43 InflateRect(&infoPtr
->Cells
[y
][x
].CellInt
,
51 DrawActiveCell(PMAP infoPtr
,
55 infoPtr
->pActiveCell
->CellInt
.left
,
56 infoPtr
->pActiveCell
->CellInt
.top
,
57 infoPtr
->pActiveCell
->CellInt
.right
,
58 infoPtr
->pActiveCell
->CellInt
.bottom
);
65 DrawGrid(PMAP infoPtr
,
72 for (y
= 0; y
< YCELLS
; y
++)
73 for (x
= 0; x
< XCELLS
; x
++)
75 Cell
= &infoPtr
->Cells
[y
][x
];
77 if (!IntersectRect(&rc
,
88 Cell
->CellExt
.bottom
);
90 if (infoPtr
->pActiveCell
== Cell
)
92 DrawActiveCell(infoPtr
, ps
->hdc
);
100 FillGrid(PMAP infoPtr
,
109 hOldFont
= SelectObject(ps
->hdc
,
112 for (y
= 0; y
< YCELLS
; y
++)
113 for (x
= 0; x
< XCELLS
; x
++)
115 Cell
= &infoPtr
->Cells
[y
][x
];
117 if (!IntersectRect(&rc
,
124 ch
= (WCHAR
)((XCELLS
* (y
+ infoPtr
->iYStart
)) + x
);
126 TagFontToCell(Cell
, ch
);
132 DT_CENTER
| DT_VCENTER
| DT_SINGLELINE
);
135 SelectObject(ps
->hdc
,
142 CreateLargeCell(PMAP infoPtr
)
147 &infoPtr
->pActiveCell
->CellExt
);
149 MapWindowPoints(infoPtr
->hMapWnd
,
158 infoPtr
->hLrgWnd
= CreateWindowExW(0,
161 WS_CHILDWINDOW
| WS_VISIBLE
,
164 rLarge
.right
- rLarge
.left
,
165 rLarge
.bottom
- rLarge
.top
,
170 if (!infoPtr
->hLrgWnd
)
179 MoveLargeCell(PMAP infoPtr
)
184 &infoPtr
->pActiveCell
->CellExt
);
186 MapWindowPoints(infoPtr
->hMapWnd
,
195 MoveWindow(infoPtr
->hLrgWnd
,
198 rLarge
.right
- rLarge
.left
,
199 rLarge
.bottom
- rLarge
.top
,
202 InvalidateRect(infoPtr
->hLrgWnd
,
210 SetFont(PMAP infoPtr
,
215 /* Destroy Zoom window, since it was created with older font */
216 DestroyWindow(infoPtr
->hLrgWnd
);
217 infoPtr
->hLrgWnd
= NULL
;
220 DeleteObject(infoPtr
->hFont
);
222 ZeroMemory(&infoPtr
->CurrentFont
,
225 hdc
= GetDC(infoPtr
->hMapWnd
);
226 infoPtr
->CurrentFont
.lfHeight
= GetDeviceCaps(hdc
,
228 ReleaseDC(infoPtr
->hMapWnd
, hdc
);
230 infoPtr
->CurrentFont
.lfCharSet
= DEFAULT_CHARSET
;
231 wcsncpy(infoPtr
->CurrentFont
.lfFaceName
,
233 sizeof(infoPtr
->CurrentFont
.lfFaceName
) / sizeof(infoPtr
->CurrentFont
.lfFaceName
[0]));
235 infoPtr
->hFont
= CreateFontIndirectW(&infoPtr
->CurrentFont
);
237 InvalidateRect(infoPtr
->hMapWnd
,
241 /* Test if zoom window must be reopened */
242 if (infoPtr
->pActiveCell
!= NULL
&&
243 infoPtr
->pActiveCell
->bLarge
)
245 CreateLargeCell(infoPtr
);
252 NotifyParentOfSelection(PMAP infoPtr
,
258 if (infoPtr
->hParent
!= NULL
)
260 DWORD dwIdc
= GetWindowLongPtr(infoPtr
->hMapWnd
, GWLP_ID
);
262 * Push directly into the event queue instead of waiting
263 * the parent to be unlocked.
264 * High word of LPARAM is still available for future needs...
266 Ret
= PostMessage(infoPtr
->hParent
,
268 MAKELPARAM((WORD
)dwIdc
, (WORD
)code
),
278 OnClick(PMAP infoPtr
,
288 for (x
= 0; x
< XCELLS
; x
++)
289 for (y
= 0; y
< YCELLS
; y
++)
291 if (PtInRect(&infoPtr
->Cells
[y
][x
].CellInt
,
294 /* if the cell is not already active */
295 if (!infoPtr
->Cells
[y
][x
].bActive
)
297 /* set previous active cell to inactive */
298 if (infoPtr
->pActiveCell
)
300 /* invalidate normal cells, required when
301 * moving a small active cell via keyboard */
302 if (!infoPtr
->pActiveCell
->bLarge
)
304 InvalidateRect(infoPtr
->hMapWnd
,
305 &infoPtr
->pActiveCell
->CellInt
,
309 infoPtr
->pActiveCell
->bActive
= FALSE
;
310 infoPtr
->pActiveCell
->bLarge
= FALSE
;
313 /* set new cell to active */
314 infoPtr
->pActiveCell
= &infoPtr
->Cells
[y
][x
];
315 infoPtr
->pActiveCell
->bActive
= TRUE
;
316 infoPtr
->pActiveCell
->bLarge
= TRUE
;
317 if (infoPtr
->hLrgWnd
)
318 MoveLargeCell(infoPtr
);
320 CreateLargeCell(infoPtr
);
324 /* flick between large and small */
325 if (infoPtr
->pActiveCell
->bLarge
)
327 DestroyWindow(infoPtr
->hLrgWnd
);
328 infoPtr
->hLrgWnd
= NULL
;
332 CreateLargeCell(infoPtr
);
335 infoPtr
->pActiveCell
->bLarge
= (infoPtr
->pActiveCell
->bLarge
) ? FALSE
: TRUE
;
346 OnCreate(PMAP infoPtr
,
353 infoPtr
= HeapAlloc(GetProcessHeap(),
359 SetWindowLongPtrW(hwnd
,
362 if (GetLastError() == 0)
367 infoPtr
->hMapWnd
= hwnd
;
368 infoPtr
->hParent
= hParent
;
370 GetClientRect(hwnd
, &rc
);
371 infoPtr
->ClientSize
.cx
= rc
.right
;
372 infoPtr
->ClientSize
.cy
= rc
.bottom
;
373 infoPtr
->CellSize
.cx
= infoPtr
->ClientSize
.cx
/ XCELLS
;
374 infoPtr
->CellSize
.cy
= infoPtr
->ClientSize
.cy
/ YCELLS
;
376 infoPtr
->pActiveCell
= NULL
;
380 SetScrollRange(hwnd
, SB_VERT
, 0, 255, FALSE
);
381 SetScrollPos(hwnd
, SB_VERT
, 0, TRUE
);
393 OnVScroll(PMAP infoPtr
,
397 INT iYDiff
, iOldYStart
= infoPtr
->iYStart
;
402 infoPtr
->iYStart
-= 1;
406 infoPtr
->iYStart
+= 1;
410 infoPtr
->iYStart
-= YCELLS
;
414 infoPtr
->iYStart
+= YCELLS
;
418 infoPtr
->iYStart
= Pos
;
425 infoPtr
->iYStart
= max(0,
426 min(infoPtr
->iYStart
, 255*16));
428 iYDiff
= iOldYStart
- infoPtr
->iYStart
;
431 if (infoPtr
->hLrgWnd
!= NULL
)
433 ShowWindow(infoPtr
->hLrgWnd
, SW_HIDE
);
436 SetScrollPos(infoPtr
->hMapWnd
,
441 if (abs(iYDiff
) < YCELLS
)
444 GetClientRect(infoPtr
->hMapWnd
, &rect
);
447 ScrollWindowEx(infoPtr
->hMapWnd
,
449 iYDiff
* infoPtr
->CellSize
.cy
,
458 InvalidateRect(infoPtr
->hMapWnd
,
463 if (infoPtr
->hLrgWnd
!= NULL
)
465 ShowWindow(infoPtr
->hLrgWnd
, SW_SHOW
);
473 OnPaint(PMAP infoPtr
,
482 if (!GetUpdateRect(infoPtr
->hMapWnd
,
492 hdc
= BeginPaint(infoPtr
->hMapWnd
,
500 DrawGrid(infoPtr
, &ps
);
502 FillGrid(infoPtr
, &ps
);
506 EndPaint(infoPtr
->hMapWnd
,
514 MapWndProc(HWND hwnd
,
522 infoPtr
= (PMAP
)GetWindowLongPtrW(hwnd
,
529 if (!OnCreate(infoPtr
,
531 ((LPCREATESTRUCTW
)lParam
)->hwndParent
))
548 case WM_LBUTTONDBLCLK
:
550 NotifyParentOfSelection(infoPtr
,
552 infoPtr
->pActiveCell
->ch
);
568 SetFont(infoPtr
, (LPWSTR
)lParam
);
573 if (!infoPtr
->pActiveCell
) return 0;
574 return infoPtr
->pActiveCell
->ch
;
578 return (LRESULT
)infoPtr
->hFont
;
589 DeleteObject(infoPtr
->hFont
);
590 HeapFree(GetProcessHeap(),
593 SetWindowLongPtrW(hwnd
,
601 Ret
= DefWindowProcW(hwnd
,
614 RegisterMapClasses(HINSTANCE hInstance
)
618 wc
.style
= CS_DBLCLKS
;
619 wc
.lpfnWndProc
= MapWndProc
;
620 wc
.cbWndExtra
= sizeof(PMAP
);
621 wc
.hInstance
= hInstance
;
622 wc
.hCursor
= LoadCursorW(NULL
,
624 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
625 wc
.lpszClassName
= szMapWndClass
;
627 if (RegisterClassW(&wc
))
629 wc
.lpfnWndProc
= LrgCellWndProc
;
631 wc
.lpszClassName
= szLrgCellWndClass
;
633 return RegisterClassW(&wc
) != 0;
640 UnregisterMapClasses(HINSTANCE hInstance
)
642 UnregisterClassW(szMapWndClass
,
645 UnregisterClassW(szLrgCellWndClass
,