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 wcscpy(infoPtr
->CurrentFont
.lfFaceName
,
234 infoPtr
->hFont
= CreateFontIndirectW(&infoPtr
->CurrentFont
);
236 InvalidateRect(infoPtr
->hMapWnd
,
240 /* Test if zoom window must be reopened */
241 if (infoPtr
->pActiveCell
!= NULL
&&
242 infoPtr
->pActiveCell
->bLarge
)
244 CreateLargeCell(infoPtr
);
251 NotifyParentOfSelection(PMAP infoPtr
,
257 if (infoPtr
->hParent
!= NULL
)
259 DWORD dwIdc
= GetWindowLongPtr(infoPtr
->hMapWnd
, GWLP_ID
);
261 * Push directly into the event queue instead of waiting
262 * the parent to be unlocked.
263 * High word of LPARAM is still available for future needs...
265 Ret
= PostMessage(infoPtr
->hParent
,
267 MAKELPARAM((WORD
)dwIdc
, (WORD
)code
),
277 OnClick(PMAP infoPtr
,
287 for (x
= 0; x
< XCELLS
; x
++)
288 for (y
= 0; y
< YCELLS
; y
++)
290 if (PtInRect(&infoPtr
->Cells
[y
][x
].CellInt
,
293 /* if the cell is not already active */
294 if (!infoPtr
->Cells
[y
][x
].bActive
)
296 /* set previous active cell to inactive */
297 if (infoPtr
->pActiveCell
)
299 /* invalidate normal cells, required when
300 * moving a small active cell via keyboard */
301 if (!infoPtr
->pActiveCell
->bLarge
)
303 InvalidateRect(infoPtr
->hMapWnd
,
304 &infoPtr
->pActiveCell
->CellInt
,
308 infoPtr
->pActiveCell
->bActive
= FALSE
;
309 infoPtr
->pActiveCell
->bLarge
= FALSE
;
312 /* set new cell to active */
313 infoPtr
->pActiveCell
= &infoPtr
->Cells
[y
][x
];
314 infoPtr
->pActiveCell
->bActive
= TRUE
;
315 infoPtr
->pActiveCell
->bLarge
= TRUE
;
316 if (infoPtr
->hLrgWnd
)
317 MoveLargeCell(infoPtr
);
319 CreateLargeCell(infoPtr
);
323 /* flick between large and small */
324 if (infoPtr
->pActiveCell
->bLarge
)
326 DestroyWindow(infoPtr
->hLrgWnd
);
327 infoPtr
->hLrgWnd
= NULL
;
331 CreateLargeCell(infoPtr
);
334 infoPtr
->pActiveCell
->bLarge
= (infoPtr
->pActiveCell
->bLarge
) ? FALSE
: TRUE
;
345 OnCreate(PMAP infoPtr
,
352 infoPtr
= HeapAlloc(GetProcessHeap(),
358 SetWindowLongPtrW(hwnd
,
361 if (GetLastError() == 0)
366 infoPtr
->hMapWnd
= hwnd
;
367 infoPtr
->hParent
= hParent
;
369 GetClientRect(hwnd
, &rc
);
370 infoPtr
->ClientSize
.cx
= rc
.right
;
371 infoPtr
->ClientSize
.cy
= rc
.bottom
;
372 infoPtr
->CellSize
.cx
= infoPtr
->ClientSize
.cx
/ XCELLS
;
373 infoPtr
->CellSize
.cy
= infoPtr
->ClientSize
.cy
/ YCELLS
;
375 infoPtr
->pActiveCell
= NULL
;
379 SetScrollRange(hwnd
, SB_VERT
, 0, 255, FALSE
);
380 SetScrollPos(hwnd
, SB_VERT
, 0, TRUE
);
392 OnVScroll(PMAP infoPtr
,
396 INT iYDiff
, iOldYStart
= infoPtr
->iYStart
;
401 infoPtr
->iYStart
-= 1;
405 infoPtr
->iYStart
+= 1;
409 infoPtr
->iYStart
-= YCELLS
;
413 infoPtr
->iYStart
+= YCELLS
;
417 infoPtr
->iYStart
= Pos
;
424 infoPtr
->iYStart
= max(0,
425 min(infoPtr
->iYStart
, 255*16));
427 iYDiff
= iOldYStart
- infoPtr
->iYStart
;
430 if (infoPtr
->hLrgWnd
!= NULL
)
432 ShowWindow(infoPtr
->hLrgWnd
, SW_HIDE
);
435 SetScrollPos(infoPtr
->hMapWnd
,
440 if (abs(iYDiff
) < YCELLS
)
443 GetClientRect(infoPtr
->hMapWnd
, &rect
);
446 ScrollWindowEx(infoPtr
->hMapWnd
,
448 iYDiff
* infoPtr
->CellSize
.cy
,
457 InvalidateRect(infoPtr
->hMapWnd
,
462 if (infoPtr
->hLrgWnd
!= NULL
)
464 ShowWindow(infoPtr
->hLrgWnd
, SW_SHOW
);
472 OnPaint(PMAP infoPtr
,
481 if (!GetUpdateRect(infoPtr
->hMapWnd
,
491 hdc
= BeginPaint(infoPtr
->hMapWnd
,
499 DrawGrid(infoPtr
, &ps
);
501 FillGrid(infoPtr
, &ps
);
505 EndPaint(infoPtr
->hMapWnd
,
513 MapWndProc(HWND hwnd
,
521 infoPtr
= (PMAP
)GetWindowLongPtrW(hwnd
,
528 if (!OnCreate(infoPtr
,
530 ((LPCREATESTRUCTW
)lParam
)->hwndParent
))
547 case WM_LBUTTONDBLCLK
:
549 NotifyParentOfSelection(infoPtr
,
551 infoPtr
->pActiveCell
->ch
);
567 SetFont(infoPtr
, (LPWSTR
)lParam
);
572 if (!infoPtr
->pActiveCell
) return 0;
573 return infoPtr
->pActiveCell
->ch
;
577 return (LRESULT
)infoPtr
->hFont
;
588 DeleteObject(infoPtr
->hFont
);
589 HeapFree(GetProcessHeap(),
592 SetWindowLongPtrW(hwnd
,
600 Ret
= DefWindowProcW(hwnd
,
613 RegisterMapClasses(HINSTANCE hInstance
)
617 wc
.style
= CS_DBLCLKS
;
618 wc
.lpfnWndProc
= MapWndProc
;
619 wc
.cbWndExtra
= sizeof(PMAP
);
620 wc
.hInstance
= hInstance
;
621 wc
.hCursor
= LoadCursorW(NULL
,
623 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
624 wc
.lpszClassName
= szMapWndClass
;
626 if (RegisterClassW(&wc
))
628 wc
.lpfnWndProc
= LrgCellWndProc
;
630 wc
.lpszClassName
= szLrgCellWndClass
;
632 return RegisterClassW(&wc
) != 0;
639 UnregisterMapClasses(HINSTANCE hInstance
)
641 UnregisterClassW(szMapWndClass
,
644 UnregisterClassW(szLrgCellWndClass
,