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