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