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 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 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 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 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 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 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 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 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 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 302 UnInitEditGlyphWndClasses(VOID) 303 { 304 UnregisterClassW(EDIT_GLYPH_EDIT_CLASSW, hInstance); 305 UnregisterClassW(EDIT_GLYPH_PREVIEW_CLASSW, hInstance); 306 } 307