1 /*
2 * PROJECT: ReactOS VGA Font Editor
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Dialog for editing a glyph
5 * COPYRIGHT: Copyright 2008 Colin Finck (colin@reactos.org)
6 */
7
8 #include "precomp.h"
9
10 static VOID
AddToolboxButton(IN HWND hToolbar,IN INT iBitmap,IN INT idCommand,IN BYTE fsState)11 AddToolboxButton(IN HWND hToolbar, IN INT iBitmap, IN INT idCommand, IN BYTE fsState)
12 {
13 TBBUTTON tbb = {0,};
14
15 tbb.fsState = fsState;
16 tbb.fsStyle = BTNS_CHECKGROUP;
17 tbb.iBitmap = iBitmap;
18 tbb.idCommand = idCommand;
19
20 SendMessageW( hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb );
21 }
22
23 static VOID
InitToolbox(IN PEDIT_GLYPH_INFO Info)24 InitToolbox(IN PEDIT_GLYPH_INFO Info)
25 {
26 HWND hToolbar;
27 INT iBitmap;
28 TBADDBITMAP tbab;
29
30 hToolbar = GetDlgItem(Info->hSelf, IDC_EDIT_GLYPH_TOOLBOX);
31
32 // Identify the used Common Controls version
33 SendMessageW(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
34
35 // Set the button size to 24x24
36 SendMessageW( hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(24, 24) );
37 SendMessageW( hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24, 24) );
38
39 // Add the Toolbox bitmaps
40 tbab.hInst = hInstance;
41 tbab.nID = IDB_EDIT_GLYPH_TOOLBOX;
42 iBitmap = (INT)SendMessageW(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
43
44 AddToolboxButton(hToolbar, iBitmap + TOOLBOX_PEN, ID_TOOLBOX_PEN, TBSTATE_ENABLED | TBSTATE_CHECKED);
45 }
46
47 static VOID
GetBitRect(IN PEDIT_GLYPH_INFO Info,IN UINT uRow,IN UINT uColumn,OUT LPRECT BitRect)48 GetBitRect(IN PEDIT_GLYPH_INFO Info, IN UINT uRow, IN UINT uColumn, OUT LPRECT BitRect)
49 {
50 BitRect->left = uColumn * Info->lEditSpacing + 1;
51 BitRect->top = uRow * Info->lEditSpacing + 1;
52 BitRect->right = BitRect->left + Info->lEditSpacing - 1;
53 BitRect->bottom = BitRect->top + Info->lEditSpacing - 1;
54 }
55
56 static VOID
SetPixelBit(IN PEDIT_GLYPH_INFO Info,IN UINT uRow,IN UINT uColumn,IN BOOL uBit)57 SetPixelBit(IN PEDIT_GLYPH_INFO Info, IN UINT uRow, IN UINT uColumn, IN BOOL uBit)
58 {
59 // Set the bit in the bitfield
60 if(uBit)
61 Info->CharacterBits[uRow] |= 1 << (7 - uColumn);
62 else
63 Info->CharacterBits[uRow] &= ~( 1 << (7 - uColumn) );
64
65 // Redraw everything
66 InvalidateRect(Info->hEdit, NULL, FALSE);
67 InvalidateRect(Info->hPreview, NULL, FALSE);
68 }
69
70 static BOOL
EditGlyphCommand(IN INT idCommand,IN PEDIT_GLYPH_INFO Info)71 EditGlyphCommand(IN INT idCommand, IN PEDIT_GLYPH_INFO Info)
72 {
73 switch(idCommand)
74 {
75 case IDOK:
76 {
77 RECT rect;
78 UINT uColumn;
79 UINT uRow;
80
81 RtlCopyMemory( Info->FontWndInfo->Font->Bits + Info->uCharacter * 8, Info->CharacterBits, sizeof(Info->CharacterBits) );
82
83 GetCharacterPosition(Info->uCharacter, &uRow, &uColumn);
84 GetCharacterRect(uRow, uColumn, &rect);
85 InvalidateRect(Info->FontWndInfo->hFontBoxesWnd, &rect, FALSE);
86
87 Info->FontWndInfo->OpenInfo->bModified = TRUE;
88
89 // Fall through
90 }
91
92 // This is the equivalent of WM_DESTROY for dialogs
93 case IDCANCEL:
94 EndDialog(Info->hSelf, 0);
95
96 // Remove the window from the linked list
97 if(Info->PrevEditGlyphWnd)
98 Info->PrevEditGlyphWnd->NextEditGlyphWnd = Info->NextEditGlyphWnd;
99 else
100 Info->FontWndInfo->FirstEditGlyphWnd = Info->NextEditGlyphWnd;
101
102 if(Info->NextEditGlyphWnd)
103 Info->NextEditGlyphWnd->PrevEditGlyphWnd = Info->PrevEditGlyphWnd;
104 else
105 Info->FontWndInfo->LastEditGlyphWnd = Info->PrevEditGlyphWnd;
106
107 SetWindowLongPtrW(Info->hSelf, GWLP_USERDATA, 0);
108 SetWindowLongPtrW(Info->hEdit, GWLP_USERDATA, 0);
109 SetWindowLongPtrW(Info->hPreview, GWLP_USERDATA, 0 );
110
111 HeapFree(hProcessHeap, 0, Info);
112 return TRUE;
113 }
114
115 return FALSE;
116 }
117
118 INT_PTR CALLBACK
EditGlyphDlgProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)119 EditGlyphDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
120 {
121 PEDIT_GLYPH_INFO Info;
122
123 Info = (PEDIT_GLYPH_INFO) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
124
125 if(Info || uMsg == WM_INITDIALOG)
126 {
127 switch(uMsg)
128 {
129 case WM_COMMAND:
130 return EditGlyphCommand( LOWORD(wParam), Info );
131
132 case WM_INITDIALOG:
133 Info = (PEDIT_GLYPH_INFO) lParam;
134 Info->hSelf = hwnd;
135 Info->hEdit = GetDlgItem(hwnd, IDC_EDIT_GLYPH_EDIT);
136 Info->hPreview = GetDlgItem(hwnd, IDC_EDIT_GLYPH_PREVIEW);
137
138 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)Info);
139 SetWindowLongPtrW(Info->hEdit, GWLP_USERDATA, (LONG_PTR)Info);
140 SetWindowLongPtrW(Info->hPreview, GWLP_USERDATA, (LONG_PTR)Info);
141
142 InitToolbox(Info);
143
144 return TRUE;
145 }
146 }
147
148 return FALSE;
149 }
150
151 static LRESULT CALLBACK
EditGlyphEditWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)152 EditGlyphEditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
153 {
154 PEDIT_GLYPH_INFO Info;
155
156 Info = (PEDIT_GLYPH_INFO) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
157
158 if(Info)
159 {
160 switch(uMsg)
161 {
162 case WM_CREATE:
163 return 0;
164
165 case WM_LBUTTONDOWN:
166 SetPixelBit(Info, GET_Y_LPARAM(lParam) / Info->lEditSpacing, GET_X_LPARAM(lParam) / Info->lEditSpacing, 1);
167 return 0;
168
169 case WM_RBUTTONDOWN:
170 SetPixelBit(Info, GET_Y_LPARAM(lParam) / Info->lEditSpacing, GET_X_LPARAM(lParam) / Info->lEditSpacing, 0);
171 return 0;
172
173 case WM_PAINT:
174 {
175 BOOL bBit;
176 HPEN hOldPen;
177 HPEN hPen;
178 PAINTSTRUCT ps;
179 RECT rect;
180 UINT i;
181 UINT j;
182
183 BeginPaint(hwnd, &ps);
184
185 // Draw the grid
186 GetClientRect(hwnd, &rect);
187 Info->lEditSpacing = rect.right / 8;
188
189 hPen = CreatePen( PS_SOLID, 1, RGB(128, 128, 128) );
190 hOldPen = SelectObject(ps.hdc, hPen);
191
192 for(i = 1; i < 8; i++)
193 {
194 MoveToEx(ps.hdc, i * Info->lEditSpacing, 0, NULL);
195 LineTo (ps.hdc, i * Info->lEditSpacing, rect.right);
196
197 MoveToEx(ps.hdc, 0, i * Info->lEditSpacing, NULL);
198 LineTo (ps.hdc, rect.right, i * Info->lEditSpacing);
199 }
200
201 SelectObject(ps.hdc, hOldPen);
202 DeleteObject(hPen);
203
204 // Draw all bits
205 for(i = 0; i < 8; i++)
206 {
207 for(j = 0; j < 8; j++)
208 {
209 bBit = (BOOL) (Info->CharacterBits[i] << j & 0x80);
210
211 GetBitRect(Info, i, j, &rect);
212 FillRect( ps.hdc, &rect, (HBRUSH) GetStockObject(bBit ? BLACK_BRUSH : WHITE_BRUSH) );
213 }
214 }
215
216 // Draw the bounding rectangle
217 SelectObject( ps.hdc, GetStockObject(NULL_BRUSH) );
218 Rectangle(ps.hdc, 0, 0, rect.right, rect.right);
219
220 EndPaint(hwnd, &ps);
221 return 0;
222 }
223 }
224 }
225
226 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
227 }
228
229 static LRESULT CALLBACK
EditGlyphPreviewWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)230 EditGlyphPreviewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
231 {
232 PEDIT_GLYPH_INFO Info;
233
234 Info = (PEDIT_GLYPH_INFO) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
235
236 if(Info)
237 {
238 switch(uMsg)
239 {
240 case WM_CREATE:
241 return 0;
242
243 case WM_PAINT:
244 {
245 BOOL bBit;
246 INT iLeft;
247 INT iTop;
248 PAINTSTRUCT ps;
249 RECT rect;
250 UINT i;
251 UINT j;
252
253 BeginPaint(hwnd, &ps);
254
255 // Draw the bounding rectangle
256 GetClientRect(hwnd, &rect);
257 Rectangle(ps.hdc, 0, 0, rect.right, rect.bottom);
258
259 // Draw all bits
260 iLeft = rect.right / 2 - 8 / 2;
261 iTop = rect.bottom / 2 - 8 / 2;
262
263 for(i = 0; i < 8; i++)
264 {
265 for(j = 0; j < 8; j++)
266 {
267 bBit = (BOOL) (Info->CharacterBits[i] << j & 0x80);
268 SetPixel( ps.hdc, j + iLeft, i + iTop, (bBit ? 0 : 0xFFFFFF) );
269 }
270 }
271
272 EndPaint(hwnd, &ps);
273
274 return 0;
275 }
276 }
277 }
278
279 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
280 }
281
282 BOOL
InitEditGlyphWndClasses(VOID)283 InitEditGlyphWndClasses(VOID)
284 {
285 WNDCLASSW wc = {0,};
286
287 wc.lpfnWndProc = EditGlyphEditWndProc;
288 wc.hInstance = hInstance;
289 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
290 wc.lpszClassName = EDIT_GLYPH_EDIT_CLASSW;
291
292 if( !RegisterClassW(&wc) )
293 return FALSE;
294
295 wc.lpfnWndProc = EditGlyphPreviewWndProc;
296 wc.lpszClassName = EDIT_GLYPH_PREVIEW_CLASSW;
297
298 return RegisterClassW(&wc) != 0;
299 }
300
301 VOID
UnInitEditGlyphWndClasses(VOID)302 UnInitEditGlyphWndClasses(VOID)
303 {
304 UnregisterClassW(EDIT_GLYPH_EDIT_CLASSW, hInstance);
305 UnregisterClassW(EDIT_GLYPH_PREVIEW_CLASSW, hInstance);
306 }
307