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>
12 static const WCHAR szMapWndClass
[] = L
"FontMapWnd";
13 static const WCHAR szLrgCellWndClass
[] = L
"LrgCellWnd";
17 TagFontToCell(PCELL pCell
,
30 for (y
= 0; y
< YCELLS
; y
++)
31 for (x
= 0; x
< XCELLS
; x
++)
33 infoPtr
->Cells
[y
][x
].CellExt
.left
= x
* infoPtr
->CellSize
.cx
+ 1;
34 infoPtr
->Cells
[y
][x
].CellExt
.top
= y
* infoPtr
->CellSize
.cy
+ 1;
35 infoPtr
->Cells
[y
][x
].CellExt
.right
= (x
+ 1) * infoPtr
->CellSize
.cx
+ 2;
36 infoPtr
->Cells
[y
][x
].CellExt
.bottom
= (y
+ 1) * infoPtr
->CellSize
.cy
+ 2;
38 CopyRect(&infoPtr
->Cells
[y
][x
].CellInt
,
39 &infoPtr
->Cells
[y
][x
].CellExt
);
41 InflateRect(&infoPtr
->Cells
[y
][x
].CellInt
,
49 DrawActiveCell(PMAP infoPtr
,
53 infoPtr
->pActiveCell
->CellInt
.left
,
54 infoPtr
->pActiveCell
->CellInt
.top
,
55 infoPtr
->pActiveCell
->CellInt
.right
,
56 infoPtr
->pActiveCell
->CellInt
.bottom
);
63 DrawGrid(PMAP infoPtr
,
70 for (y
= 0; y
< YCELLS
; y
++)
71 for (x
= 0; x
< XCELLS
; x
++)
73 Cell
= &infoPtr
->Cells
[y
][x
];
75 if (!IntersectRect(&rc
,
86 Cell
->CellExt
.bottom
);
88 if (infoPtr
->pActiveCell
== Cell
)
90 DrawActiveCell(infoPtr
, ps
->hdc
);
98 FillGrid(PMAP infoPtr
,
107 hOldFont
= SelectObject(ps
->hdc
,
110 for (y
= 0; y
< YCELLS
; y
++)
111 for (x
= 0; x
< XCELLS
; x
++)
113 Cell
= &infoPtr
->Cells
[y
][x
];
115 if (!IntersectRect(&rc
,
122 ch
= (WCHAR
)((XCELLS
* (y
+ infoPtr
->iYStart
)) + x
);
124 TagFontToCell(Cell
, ch
);
130 DT_CENTER
| DT_VCENTER
| DT_SINGLELINE
);
133 SelectObject(ps
->hdc
,
140 CreateLargeCell(PMAP infoPtr
)
145 &infoPtr
->pActiveCell
->CellExt
);
147 MapWindowPoints(infoPtr
->hMapWnd
,
156 infoPtr
->hLrgWnd
= CreateWindowExW(0,
159 WS_CHILDWINDOW
| WS_VISIBLE
,
162 rLarge
.right
- rLarge
.left
,
163 rLarge
.bottom
- rLarge
.top
,
168 if (!infoPtr
->hLrgWnd
)
177 MoveLargeCell(PMAP infoPtr
)
182 &infoPtr
->pActiveCell
->CellExt
);
184 MapWindowPoints(infoPtr
->hMapWnd
,
193 MoveWindow(infoPtr
->hLrgWnd
,
196 rLarge
.right
- rLarge
.left
,
197 rLarge
.bottom
- rLarge
.top
,
200 InvalidateRect(infoPtr
->hLrgWnd
,
208 SetFont(PMAP infoPtr
,
213 /* Destroy Zoom window, since it was created with older font */
214 DestroyWindow(infoPtr
->hLrgWnd
);
215 infoPtr
->hLrgWnd
= NULL
;
218 DeleteObject(infoPtr
->hFont
);
220 ZeroMemory(&infoPtr
->CurrentFont
,
223 hdc
= GetDC(infoPtr
->hMapWnd
);
224 infoPtr
->CurrentFont
.lfHeight
= GetDeviceCaps(hdc
,
226 ReleaseDC(infoPtr
->hMapWnd
, hdc
);
228 infoPtr
->CurrentFont
.lfCharSet
= DEFAULT_CHARSET
;
229 wcscpy(infoPtr
->CurrentFont
.lfFaceName
,
232 infoPtr
->hFont
= CreateFontIndirectW(&infoPtr
->CurrentFont
);
234 InvalidateRect(infoPtr
->hMapWnd
,
238 /* Test if zoom window must be reopened */
239 if (infoPtr
->pActiveCell
!= NULL
&&
240 infoPtr
->pActiveCell
->bLarge
)
242 CreateLargeCell(infoPtr
);
249 NotifyParentOfSelection(PMAP infoPtr
,
255 if (infoPtr
->hParent
!= NULL
)
257 DWORD dwIdc
= GetWindowLongPtr(infoPtr
->hMapWnd
, GWLP_ID
);
259 * Push directly into the event queue instead of waiting
260 * the parent to be unlocked.
261 * High word of LPARAM is still available for future needs...
263 Ret
= PostMessage(infoPtr
->hParent
,
265 MAKELPARAM((WORD
)dwIdc
, (WORD
)code
),
275 OnClick(PMAP infoPtr
,
285 for (x
= 0; x
< XCELLS
; x
++)
286 for (y
= 0; y
< YCELLS
; y
++)
288 if (PtInRect(&infoPtr
->Cells
[y
][x
].CellInt
,
291 /* if the cell is not already active */
292 if (!infoPtr
->Cells
[y
][x
].bActive
)
294 /* set previous active cell to inactive */
295 if (infoPtr
->pActiveCell
)
297 /* invalidate normal cells, required when
298 * moving a small active cell via keyboard */
299 if (!infoPtr
->pActiveCell
->bLarge
)
301 InvalidateRect(infoPtr
->hMapWnd
,
302 &infoPtr
->pActiveCell
->CellInt
,
306 infoPtr
->pActiveCell
->bActive
= FALSE
;
307 infoPtr
->pActiveCell
->bLarge
= FALSE
;
310 /* set new cell to active */
311 infoPtr
->pActiveCell
= &infoPtr
->Cells
[y
][x
];
312 infoPtr
->pActiveCell
->bActive
= TRUE
;
313 infoPtr
->pActiveCell
->bLarge
= TRUE
;
314 if (infoPtr
->hLrgWnd
)
315 MoveLargeCell(infoPtr
);
317 CreateLargeCell(infoPtr
);
321 /* flick between large and small */
322 if (infoPtr
->pActiveCell
->bLarge
)
324 DestroyWindow(infoPtr
->hLrgWnd
);
325 infoPtr
->hLrgWnd
= NULL
;
329 CreateLargeCell(infoPtr
);
332 infoPtr
->pActiveCell
->bLarge
= (infoPtr
->pActiveCell
->bLarge
) ? FALSE
: TRUE
;
343 OnCreate(PMAP infoPtr
,
350 infoPtr
= HeapAlloc(GetProcessHeap(),
356 SetWindowLongPtrW(hwnd
,
359 if (GetLastError() == 0)
364 infoPtr
->hMapWnd
= hwnd
;
365 infoPtr
->hParent
= hParent
;
367 GetClientRect(hwnd
, &rc
);
368 infoPtr
->ClientSize
.cx
= rc
.right
;
369 infoPtr
->ClientSize
.cy
= rc
.bottom
;
370 infoPtr
->CellSize
.cx
= infoPtr
->ClientSize
.cx
/ XCELLS
;
371 infoPtr
->CellSize
.cy
= infoPtr
->ClientSize
.cy
/ YCELLS
;
373 infoPtr
->pActiveCell
= NULL
;
377 SetScrollRange(hwnd
, SB_VERT
, 0, 255, FALSE
);
378 SetScrollPos(hwnd
, SB_VERT
, 0, TRUE
);
390 OnVScroll(PMAP infoPtr
,
394 INT iYDiff
, iOldYStart
= infoPtr
->iYStart
;
399 infoPtr
->iYStart
-= 1;
403 infoPtr
->iYStart
+= 1;
407 infoPtr
->iYStart
-= YCELLS
;
411 infoPtr
->iYStart
+= YCELLS
;
415 infoPtr
->iYStart
= Pos
;
422 infoPtr
->iYStart
= max(0,
423 min(infoPtr
->iYStart
, 255*16));
425 iYDiff
= iOldYStart
- infoPtr
->iYStart
;
428 if (infoPtr
->hLrgWnd
!= NULL
)
430 ShowWindow(infoPtr
->hLrgWnd
, SW_HIDE
);
433 SetScrollPos(infoPtr
->hMapWnd
,
438 if (abs(iYDiff
) < YCELLS
)
441 GetClientRect(infoPtr
->hMapWnd
, &rect
);
444 ScrollWindowEx(infoPtr
->hMapWnd
,
446 iYDiff
* infoPtr
->CellSize
.cy
,
455 InvalidateRect(infoPtr
->hMapWnd
,
460 if (infoPtr
->hLrgWnd
!= NULL
)
462 ShowWindow(infoPtr
->hLrgWnd
, SW_SHOW
);
470 OnPaint(PMAP infoPtr
,
479 if (!GetUpdateRect(infoPtr
->hMapWnd
,
489 hdc
= BeginPaint(infoPtr
->hMapWnd
,
497 DrawGrid(infoPtr
, &ps
);
499 FillGrid(infoPtr
, &ps
);
503 EndPaint(infoPtr
->hMapWnd
,
511 MapWndProc(HWND hwnd
,
519 infoPtr
= (PMAP
)GetWindowLongPtrW(hwnd
,
526 if (!OnCreate(infoPtr
,
528 ((LPCREATESTRUCTW
)lParam
)->hwndParent
))
545 case WM_LBUTTONDBLCLK
:
547 NotifyParentOfSelection(infoPtr
,
549 infoPtr
->pActiveCell
->ch
);
565 SetFont(infoPtr
, (LPWSTR
)lParam
);
570 if (!infoPtr
->pActiveCell
) return 0;
571 return infoPtr
->pActiveCell
->ch
;
575 return (LRESULT
)infoPtr
->hFont
;
586 DeleteObject(infoPtr
->hFont
);
587 HeapFree(GetProcessHeap(),
590 SetWindowLongPtrW(hwnd
,
598 Ret
= DefWindowProcW(hwnd
,
611 RegisterMapClasses(HINSTANCE hInstance
)
615 wc
.style
= CS_DBLCLKS
;
616 wc
.lpfnWndProc
= MapWndProc
;
617 wc
.cbWndExtra
= sizeof(PMAP
);
618 wc
.hInstance
= hInstance
;
619 wc
.hCursor
= LoadCursorW(NULL
,
621 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
622 wc
.lpszClassName
= szMapWndClass
;
624 if (RegisterClassW(&wc
))
626 wc
.lpfnWndProc
= LrgCellWndProc
;
628 wc
.lpszClassName
= szLrgCellWndClass
;
630 return RegisterClassW(&wc
) != 0;
637 UnregisterMapClasses(HINSTANCE hInstance
)
639 UnregisterClassW(szMapWndClass
,
642 UnregisterClassW(szLrgCellWndClass
,