2 * PROJECT: ReactOS VGA Font Editor
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Implements the MDI child window for a font
5 * COPYRIGHT: Copyright 2008 Colin Finck (colin@reactos.org)
10 static const WCHAR szFontWndClass
[] = L
"VGAFontEditFontWndClass";
13 InitFont(IN PFONT_WND_INFO Info
)
15 Info
->Font
= (PBITMAP_FONT
) HeapAlloc( hProcessHeap
, 0, sizeof(BITMAP_FONT
) );
17 if(Info
->OpenInfo
->bCreateNew
)
19 ZeroMemory( Info
->Font
, sizeof(BITMAP_FONT
) );
29 hFile
= CreateFileW(Info
->OpenInfo
->pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
31 if(hFile
== INVALID_HANDLE_VALUE
)
33 LocalizedError( IDS_OPENERROR
, GetLastError() );
37 // Let's first check the file size to determine the file type
38 dwTemp
= GetFileSize(hFile
, NULL
);
43 // It should be a binary font file
44 Info
->OpenInfo
->bBinaryFileOpened
= TRUE
;
46 if( ReadFile(hFile
, Info
->Font
, sizeof(BITMAP_FONT
), &dwTemp
, NULL
) )
49 LocalizedError( IDS_READERROR
, GetLastError() );
57 // Probably it's a PSFv1 file, check the header to make sure
58 if( !ReadFile(hFile
, &Header
, sizeof(PSF1_HEADER
) , &dwTemp
, NULL
) )
60 LocalizedError( IDS_READERROR
, GetLastError() );
65 if(Header
.uMagic
[0] == PSF1_MAGIC0
&& Header
.uMagic
[1] == PSF1_MAGIC1
)
67 // Yes, it is a PSFv1 file.
68 // Check the mode and character size. We only support 8x8 fonts with no special mode.
69 if(Header
.uCharSize
== 8 && Header
.uMode
== 0)
71 // Perfect! The file pointer is already set correctly, so we can just read the font bitmap now.
72 if( ReadFile(hFile
, Info
->Font
, sizeof(BITMAP_FONT
), &dwTemp
, NULL
) )
75 LocalizedError( IDS_READERROR
, GetLastError() );
78 LocalizedError(IDS_UNSUPPORTEDPSF
);
83 // Fall through if the magic numbers aren't there
88 LocalizedError(IDS_UNSUPPORTEDFORMAT
);
96 static LRESULT CALLBACK
97 FontWndProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
101 Info
= (PFONT_WND_INFO
) GetWindowLongW(hwnd
, GWLP_USERDATA
);
103 if(Info
|| uMsg
== WM_CREATE
)
107 case WM_CHILDACTIVATE
:
108 Info
->MainWndInfo
->CurrentFontWnd
= Info
;
109 SetToolbarFileButtonState(Info
->MainWndInfo
, TRUE
);
110 SetPasteButtonState(Info
->MainWndInfo
);
114 Info
= (PFONT_WND_INFO
)( ( (LPMDICREATESTRUCT
) ( (LPCREATESTRUCT
)lParam
)->lpCreateParams
)->lParam
);
117 SetWindowLongW(hwnd
, GWLP_USERDATA
, (LONG
)Info
);
119 CreateFontBoxesWindow(Info
);
123 case WM_USER_APPCLOSE
:
125 // The user has to close all open edit dialogs first
126 if(Info
->FirstEditGlyphWnd
)
130 AllocAndLoadString(&pszMessage
, IDS_CLOSEEDIT
);
131 MessageBoxW(hwnd
, pszMessage
, szAppName
, MB_OK
| MB_ICONEXCLAMATION
);
132 HeapFree(hProcessHeap
, 0, pszMessage
);
137 // Prompt if the current file has been modified
138 if(Info
->OpenInfo
->bModified
)
142 WCHAR szFile
[MAX_PATH
];
144 GetWindowTextW(hwnd
, szFile
, MAX_PATH
);
145 LoadAndFormatString(IDS_SAVEPROMPT
, &pszPrompt
, szFile
);
147 nMsgBoxResult
= MessageBoxW(hwnd
, pszPrompt
, szAppName
, MB_YESNOCANCEL
| MB_ICONQUESTION
);
148 LocalFree(pszPrompt
);
150 switch(nMsgBoxResult
)
153 DoFileSave(Info
->MainWndInfo
, FALSE
);
157 // 0 = Stop the process of closing the windows (same value for both WM_CLOSE and WM_USER_APPCLOSE)
160 // IDNO is handled automatically
164 // If there is another child, it will undo the following actions through its WM_CHILDACTIVATE handler.
165 // Otherwise CurrentFontWnd will stay NULL, so the main window knows that no more childs are opened.
166 Info
->MainWndInfo
->CurrentFontWnd
= NULL
;
167 SetToolbarFileButtonState(Info
->MainWndInfo
, FALSE
);
168 SetPasteButtonState(Info
->MainWndInfo
);
170 if(uMsg
== WM_USER_APPCLOSE
)
172 // First do the tasks we would do for a normal WM_CLOSE message, then return the value for WM_USER_APPCLOSE
173 // Anything other than 0 indicates that the application shall continue closing the windows
174 DefMDIChildProcW(hwnd
, WM_CLOSE
, 0, 0);
180 // Remove the window from the linked list
181 if(Info
->PrevFontWnd
)
182 Info
->PrevFontWnd
->NextFontWnd
= Info
->NextFontWnd
;
184 Info
->MainWndInfo
->FirstFontWnd
= Info
->NextFontWnd
;
186 if(Info
->NextFontWnd
)
187 Info
->NextFontWnd
->PrevFontWnd
= Info
->PrevFontWnd
;
189 Info
->MainWndInfo
->LastFontWnd
= Info
->PrevFontWnd
;
193 HeapFree(hProcessHeap
, 0, Info
->Font
);
195 if(Info
->OpenInfo
->pszFileName
)
196 HeapFree(hProcessHeap
, 0, Info
->OpenInfo
->pszFileName
);
198 HeapFree(hProcessHeap
, 0, Info
->OpenInfo
);
199 HeapFree(hProcessHeap
, 0, Info
);
201 SetWindowLongW(hwnd
, GWLP_USERDATA
, 0);
205 // Set the keyboard focus to the FontBoxes window every time the Font window gets the focus
206 SetFocus(Info
->hFontBoxesWnd
);
211 INT nHeight
= HIWORD(lParam
);
212 INT nWidth
= LOWORD(lParam
);
216 // This ugly workaround is necessary for not setting either the Height or the Width of the window with SetWindowPos
217 GetWindowRect(Info
->hFontBoxesWnd
, &WndRect
);
220 ScreenToClient(hwnd
, &pt
);
222 if(nHeight
< FONT_BOXES_WND_HEIGHT
)
226 // Set the vertical scroll bar
227 si
.cbSize
= sizeof(si
);
228 si
.fMask
= SIF_RANGE
| SIF_PAGE
;
230 si
.nMax
= FONT_BOXES_WND_HEIGHT
;
232 SetScrollInfo(hwnd
, SB_VERT
, &si
, TRUE
);
236 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
238 // Store the new y coordinate in pt.y as well (needed for the SetWindowPos call for setting a new x coordinate)
239 pt
.y
= nHeight
/ 2 - FONT_BOXES_WND_HEIGHT
/ 2;
240 SetWindowPos(Info
->hFontBoxesWnd
,
246 SWP_NOSIZE
| SWP_NOZORDER
);
249 if(nWidth
< FONT_BOXES_WND_WIDTH
)
253 // Set the horizontal scroll bar
254 si
.cbSize
= sizeof(si
);
255 si
.fMask
= SIF_RANGE
| SIF_PAGE
;
257 si
.nMax
= FONT_BOXES_WND_WIDTH
;
259 SetScrollInfo(hwnd
, SB_HORZ
, &si
, TRUE
);
263 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
265 SetWindowPos(Info
->hFontBoxesWnd
,
267 nWidth
/ 2 - FONT_BOXES_WND_WIDTH
/ 2,
271 SWP_NOSIZE
| SWP_NOZORDER
);
274 // We have to call DefMDIChildProcW here as well, otherwise we won't get the Minimize/Maximize/Close buttons for a maximized MDI child.
285 if(uMsg
== WM_HSCROLL
)
290 si
.cbSize
= sizeof(si
);
292 GetScrollInfo(hwnd
, nBar
, &si
);
296 switch( LOWORD(wParam
) )
298 // Constant is the same as SB_LEFT for WM_HSCROLL
303 // Constant is the same as SB_RIGHT for WM_HSCROLL
308 // Constant is the same as SB_LINELEFT for WM_HSCROLL
313 // Constant is the same as SB_LINERIGHT for WM_HSCROLL
318 // Constant is the same as SB_PAGELEFT for WM_HSCROLL
323 // Constant is the same as SB_PAGERIGHT for WM_HSCROLL
329 si
.nPos
= si
.nTrackPos
;
334 SetScrollInfo(hwnd
, nBar
, &si
, TRUE
);
335 GetScrollInfo(hwnd
, nBar
, &si
);
337 if(si
.nPos
!= nOrgPos
)
339 // This ugly workaround is necessary for not setting the x coordinate
343 GetWindowRect(Info
->hFontBoxesWnd
, &WndRect
);
346 ScreenToClient(hwnd
, &pt
);
348 if(uMsg
== WM_HSCROLL
)
349 SetWindowPos(Info
->hFontBoxesWnd
, NULL
, -si
.nPos
, pt
.y
, 0, 0, SWP_NOZORDER
| SWP_NOSIZE
);
351 SetWindowPos(Info
->hFontBoxesWnd
, NULL
, pt
.x
, -si
.nPos
, 0, 0, SWP_NOZORDER
| SWP_NOSIZE
);
359 return DefMDIChildProcW(hwnd
, uMsg
, wParam
, lParam
);
363 CreateFontWindow(IN PMAIN_WND_INFO MainWndInfo
, IN PFONT_OPEN_INFO OpenInfo
)
368 Info
= (PFONT_WND_INFO
) HeapAlloc( hProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(FONT_WND_INFO
) );
372 Info
->MainWndInfo
= MainWndInfo
;
373 Info
->OpenInfo
= OpenInfo
;
377 PWSTR pszWindowTitle
;
379 if(OpenInfo
->pszFileName
)
380 pszWindowTitle
= wcsrchr(OpenInfo
->pszFileName
, '\\') + 1;
382 LoadAndFormatString(IDS_DOCNAME
, &pszWindowTitle
, ++MainWndInfo
->uDocumentCounter
);
384 hFontWnd
= CreateMDIWindowW( szFontWndClass
,
391 MainWndInfo
->hMdiClient
,
395 if(!OpenInfo
->pszFileName
)
396 LocalFree(pszWindowTitle
);
400 // Add the new window to the linked list
401 Info
->PrevFontWnd
= Info
->MainWndInfo
->LastFontWnd
;
403 if(Info
->MainWndInfo
->LastFontWnd
)
404 Info
->MainWndInfo
->LastFontWnd
->NextFontWnd
= Info
;
406 Info
->MainWndInfo
->FirstFontWnd
= Info
;
408 Info
->MainWndInfo
->LastFontWnd
= Info
;
414 HeapFree(hProcessHeap
, 0, Info
);
421 InitFontWndClass(VOID
)
425 wc
.lpfnWndProc
= FontWndProc
;
426 wc
.hInstance
= hInstance
;
427 wc
.hCursor
= LoadCursor( NULL
, IDC_ARROW
);
428 wc
.hIcon
= LoadIconW( hInstance
, MAKEINTRESOURCEW(IDI_DOC
) );
429 wc
.hbrBackground
= (HBRUSH
)( COLOR_BTNFACE
+ 1 );
430 wc
.lpszClassName
= szFontWndClass
;
432 return RegisterClassW(&wc
) != 0;
436 UnInitFontWndClass(VOID
)
438 UnregisterClassW(szFontWndClass
, hInstance
);