2 * PROJECT: ReactOS VGA Font Editor
3 * LICENSE: GNU General Public License Version 2.0 or any later version
4 * FILE: devutils/vgafontedit/fontboxeswnd.c
5 * PURPOSE: Implements the window showing the character boxes for a font
6 * COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
11 static const WCHAR szFontBoxesWndClass
[] = L
"VGAFontEditFontBoxesWndClass";
14 DrawCharacterPixel(IN PAINTSTRUCT
*ps
, IN UINT uCharacter
, IN UCHAR uRow
, IN UCHAR uColumn
, IN UCHAR uBit
, IN COLORREF clBackground
)
19 x
= (uCharacter
% 16) * (CHARACTER_BOX_WIDTH
+ CHARACTER_BOX_PADDING
) + 24 + uColumn
;
20 y
= (uCharacter
/ 16) * (CHARACTER_BOX_HEIGHT
+ CHARACTER_BOX_PADDING
)+ 1 + CHARACTER_INFO_BOX_HEIGHT
+ 2 + uRow
;
22 SetPixel( ps
->hdc
, x
, y
, (uBit
? 0 : clBackground
) );
26 GetCharacterRect(IN UINT uFontRow
, IN UINT uFontColumn
, OUT LPRECT CharacterRect
)
28 CharacterRect
->left
= uFontColumn
* (CHARACTER_BOX_WIDTH
+ CHARACTER_BOX_PADDING
);
29 CharacterRect
->top
= uFontRow
* (CHARACTER_BOX_HEIGHT
+ CHARACTER_BOX_PADDING
);
30 CharacterRect
->right
= CharacterRect
->left
+ CHARACTER_BOX_WIDTH
;
31 CharacterRect
->bottom
= CharacterRect
->top
+ CHARACTER_BOX_HEIGHT
;
35 GetCharacterPosition(IN UINT uCharacter
, OUT PUINT uFontRow
, OUT PUINT uFontColumn
)
37 *uFontRow
= uCharacter
/ 16;
38 *uFontColumn
= uCharacter
% 16;
42 FontBoxesHitTest(IN UINT xPos
, IN UINT yPos
, OUT LPRECT CharacterRect
)
47 uFontColumn
= xPos
/ (CHARACTER_BOX_WIDTH
+ CHARACTER_BOX_PADDING
);
48 uFontRow
= yPos
/ (CHARACTER_BOX_HEIGHT
+ CHARACTER_BOX_PADDING
);
49 GetCharacterRect(uFontRow
, uFontColumn
, CharacterRect
);
51 if(xPos
> (UINT
)CharacterRect
->right
|| yPos
> (UINT
)CharacterRect
->bottom
)
52 // The user clicked on separator space, so return HITTEST_SEPARATOR
53 return HITTEST_SEPARATOR
;
55 // Return the character number
56 return (uFontRow
* 16 + uFontColumn
);
60 SetSelectedCharacter(IN PFONT_WND_INFO Info
, IN UINT uNewCharacter
, OPTIONAL IN LPRECT NewCharacterRect
)
62 LPRECT pCharacterRect
;
63 RECT OldCharacterRect
;
67 // Remove the selection of the old character
68 GetCharacterPosition(Info
->uSelectedCharacter
, &uFontRow
, &uFontColumn
);
69 GetCharacterRect(uFontRow
, uFontColumn
, &OldCharacterRect
);
70 InvalidateRect(Info
->hFontBoxesWnd
, &OldCharacterRect
, FALSE
);
72 // You may pass the RECT of the new character, otherwise we'll allocate memory for one and get it ourselves
74 pCharacterRect
= NewCharacterRect
;
77 GetCharacterPosition(uNewCharacter
, &uFontRow
, &uFontColumn
);
78 pCharacterRect
= (LPRECT
) HeapAlloc( hProcessHeap
, 0, sizeof(RECT
) );
79 GetCharacterRect(uFontRow
, uFontColumn
, pCharacterRect
);
82 // Select the new character
83 Info
->uSelectedCharacter
= uNewCharacter
;
84 InvalidateRect(Info
->hFontBoxesWnd
, pCharacterRect
, FALSE
);
87 HeapFree(hProcessHeap
, 0, pCharacterRect
);
91 DrawProc(IN PFONT_WND_INFO Info
, IN PAINTSTRUCT
* ps
)
93 COLORREF clBackground
;
107 UCHAR uCharacterColumn
;
113 hBoxDC
= CreateCompatibleDC(NULL
);
114 SelectObject(hBoxDC
, Info
->MainWndInfo
->hBoxBmp
);
116 hFont
= CreateFontW(13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L
"Tahoma");
117 hOldFont
= SelectObject(ps
->hdc
, hFont
);
119 SetBkMode( ps
->hdc
, TRANSPARENT
);
121 // What ranges do we have to draw?
122 uStartRow
= ps
->rcPaint
.top
/ (CHARACTER_BOX_HEIGHT
+ CHARACTER_BOX_PADDING
);
123 uEndRow
= ps
->rcPaint
.bottom
/ (CHARACTER_BOX_HEIGHT
+ CHARACTER_BOX_PADDING
);
124 uStartColumn
= ps
->rcPaint
.left
/ (CHARACTER_BOX_WIDTH
+ CHARACTER_BOX_PADDING
);
125 uEndColumn
= ps
->rcPaint
.right
/ (CHARACTER_BOX_WIDTH
+ CHARACTER_BOX_PADDING
);
127 for(uFontRow
= uStartRow
; uFontRow
<= uEndRow
; uFontRow
++)
129 for(uFontColumn
= uStartColumn
; uFontColumn
<= uEndColumn
; uFontColumn
++)
131 GetCharacterRect(uFontRow
, uFontColumn
, &CharacterRect
);
132 uCharacter
= uFontRow
* 16 + uFontColumn
;
134 // Draw the Character Info Box (header)
139 CHARACTER_INFO_BOX_HEIGHT
,
145 // Draw the header text
146 wsprintfW(szInfoText
, L
"%02u = %02X", uCharacter
, uCharacter
);
147 DrawTextW( ps
->hdc
, szInfoText
, -1, &CharacterRect
, DT_CENTER
);
149 // Draw the Character Bitmap Box (rectangle with the actual character)
150 if(Info
->uSelectedCharacter
== uCharacter
)
152 clBackground
= RGB(255, 255, 0);
153 hBrush
= CreateSolidBrush(clBackground
);
154 hOldBrush
= SelectObject(ps
->hdc
, hBrush
);
158 clBackground
= RGB(255, 255, 255);
159 SelectObject( ps
->hdc
, GetStockObject(WHITE_BRUSH
) );
164 CharacterRect
.top
+ CHARACTER_INFO_BOX_HEIGHT
,
166 CharacterRect
.bottom
);
168 // Draw the actual character into the box
169 for(uCharacterRow
= 0; uCharacterRow
< 8; uCharacterRow
++)
171 for(uCharacterColumn
= 0; uCharacterColumn
< 8; uCharacterColumn
++)
173 uBit
= Info
->Font
->Bits
[uCharacter
* 8 + uCharacterRow
] << uCharacterColumn
& 0x80;
174 DrawCharacterPixel(ps
, uCharacter
, uCharacterRow
, uCharacterColumn
, uBit
, clBackground
);
180 SelectObject(ps
->hdc
, hOldFont
);
182 SelectObject(ps
->hdc
, hOldBrush
);
183 DeleteObject(hBrush
);
188 EditCurrentGlyph(PFONT_WND_INFO FontWndInfo
)
190 PEDIT_GLYPH_INFO EditGlyphInfo
;
192 // Has the window for this character already been opened?
193 EditGlyphInfo
= FontWndInfo
->FirstEditGlyphWnd
;
197 if(EditGlyphInfo
->uCharacter
== FontWndInfo
->uSelectedCharacter
)
199 // Yes, it has. Bring it to the front.
200 SetFocus(EditGlyphInfo
->hSelf
);
204 EditGlyphInfo
= EditGlyphInfo
->NextEditGlyphWnd
;
207 // No. Then create a new one
208 EditGlyphInfo
= (PEDIT_GLYPH_INFO
) HeapAlloc( hProcessHeap
, 0, sizeof(EDIT_GLYPH_INFO
) );
209 EditGlyphInfo
->FontWndInfo
= FontWndInfo
;
210 EditGlyphInfo
->uCharacter
= FontWndInfo
->uSelectedCharacter
;
211 RtlCopyMemory( EditGlyphInfo
->CharacterBits
, FontWndInfo
->Font
->Bits
+ FontWndInfo
->uSelectedCharacter
* 8, sizeof(EditGlyphInfo
->CharacterBits
) );
213 // Add the new window to the linked list
214 EditGlyphInfo
->PrevEditGlyphWnd
= FontWndInfo
->LastEditGlyphWnd
;
215 EditGlyphInfo
->NextEditGlyphWnd
= NULL
;
217 if(FontWndInfo
->LastEditGlyphWnd
)
218 FontWndInfo
->LastEditGlyphWnd
->NextEditGlyphWnd
= EditGlyphInfo
;
220 FontWndInfo
->FirstEditGlyphWnd
= EditGlyphInfo
;
222 FontWndInfo
->LastEditGlyphWnd
= EditGlyphInfo
;
224 // Open the window as a modeless dialog, so people can edit several characters at the same time.
225 EditGlyphInfo
->hSelf
= CreateDialogParamW(hInstance
, MAKEINTRESOURCEW(IDD_EDITGLYPH
), FontWndInfo
->hSelf
, EditGlyphDlgProc
, (LPARAM
)EditGlyphInfo
);
226 ShowWindow(EditGlyphInfo
->hSelf
, SW_SHOW
);
230 CreateFontBoxesWindow(IN PFONT_WND_INFO FontWndInfo
)
232 FontWndInfo
->hFontBoxesWnd
= CreateWindowExW(0,
235 WS_CHILD
| WS_VISIBLE
,
246 static LRESULT CALLBACK
247 FontBoxesWndProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
251 Info
= (PFONT_WND_INFO
) GetWindowLongW(hwnd
, GWLP_USERDATA
);
253 if(Info
|| uMsg
== WM_CREATE
)
258 Info
= (PFONT_WND_INFO
)( ( (LPCREATESTRUCT
)lParam
)->lpCreateParams
);
259 SetWindowLongW(hwnd
, GWLP_USERDATA
, (LONG
)Info
);
261 // Set a fixed window size
262 SetWindowPos(hwnd
, NULL
, 0, 0, FONT_BOXES_WND_WIDTH
, FONT_BOXES_WND_HEIGHT
, SWP_NOZORDER
| SWP_NOMOVE
);
267 SetWindowLongW(hwnd
, GWLP_USERDATA
, 0);
274 if(Info
->uSelectedCharacter
< 239)
275 SetSelectedCharacter(Info
, Info
->uSelectedCharacter
+ 16, NULL
);
279 if(Info
->uSelectedCharacter
)
280 SetSelectedCharacter(Info
, Info
->uSelectedCharacter
- 1, NULL
);
284 EditCurrentGlyph(Info
);
288 if(Info
->uSelectedCharacter
< 255)
289 SetSelectedCharacter(Info
, Info
->uSelectedCharacter
+ 1, NULL
);
293 if(Info
->uSelectedCharacter
> 15)
294 SetSelectedCharacter(Info
, Info
->uSelectedCharacter
- 16, NULL
);
300 case WM_LBUTTONDBLCLK
:
302 EditCurrentGlyph(Info
);
311 iRet
= FontBoxesHitTest( GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
), &CharacterRect
);
314 SetSelectedCharacter( Info
, (UINT
)iRet
, &CharacterRect
);
323 BeginPaint(hwnd
, &ps
);
332 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
336 InitFontBoxesWndClass(VOID
)
340 wc
.lpfnWndProc
= FontBoxesWndProc
;
341 wc
.hInstance
= hInstance
;
342 wc
.hCursor
= LoadCursor( NULL
, IDC_ARROW
);
343 wc
.hbrBackground
= (HBRUSH
)( COLOR_BTNFACE
+ 1 );
344 wc
.lpszClassName
= szFontBoxesWndClass
;
345 wc
.style
= CS_DBLCLKS
;
347 return RegisterClassW(&wc
) != 0;
351 UnInitFontBoxesWndClass(VOID
)
353 UnregisterClassW(szFontBoxesWndClass
, hInstance
);