3e2539cad838b6b9e066b42732b1719d9ba0fc84
[reactos.git] / reactos / base / applications / fontview / fontview.c
1 /*
2 * fontview
3 *
4 * fontview.c
5 *
6 * Copyright (C) 2007 Timo Kreuzer <timo <dot> kreuzer <at> reactos <dot> org>
7 * Copyright (C) 2016-2017 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #include "precomp.h"
25
26 #include <winnls.h>
27 #include <shellapi.h>
28 #include <windowsx.h>
29
30 #include "fontview.h"
31 #include "resource.h"
32
33 HINSTANCE g_hInstance;
34 INT g_FontIndex = 0;
35 INT g_NumFonts = 0;
36 LOGFONTW g_LogFonts[64];
37 LPCWSTR g_fileName;
38 WCHAR g_FontTitle[1024] = L"";
39
40 static const WCHAR g_szFontViewClassName[] = L"FontViewWClass";
41
42 /* GetFontResourceInfoW is undocumented */
43 BOOL WINAPI GetFontResourceInfoW(LPCWSTR lpFileName, DWORD *pdwBufSize, void* lpBuffer, DWORD dwType);
44
45 DWORD
46 FormatString(
47 DWORD dwFlags,
48 HINSTANCE hInstance,
49 DWORD dwStringId,
50 DWORD dwLanguageId,
51 LPWSTR lpBuffer,
52 DWORD nSize,
53 va_list* Arguments
54 )
55 {
56 DWORD dwRet;
57 int len;
58 WCHAR Buffer[1000];
59
60 len = LoadStringW(hInstance, dwStringId, (LPWSTR)Buffer, 1000);
61
62 if (len)
63 {
64 dwFlags |= FORMAT_MESSAGE_FROM_STRING;
65 dwFlags &= ~(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM);
66 dwRet = FormatMessageW(dwFlags, Buffer, 0, dwLanguageId, lpBuffer, nSize, Arguments);
67 return dwRet;
68 }
69 return 0;
70 }
71
72 static void
73 ErrorMsgBox(HWND hParent, DWORD dwMessageId, ...)
74 {
75 HLOCAL hMemCaption = NULL;
76 HLOCAL hMemText = NULL;
77 va_list args;
78
79 va_start(args, dwMessageId);
80 FormatString(FORMAT_MESSAGE_ALLOCATE_BUFFER,
81 NULL, dwMessageId, 0, (LPWSTR)&hMemText, 0, &args);
82 va_end(args);
83
84 FormatString(FORMAT_MESSAGE_ALLOCATE_BUFFER,
85 NULL, IDS_ERROR, 0, (LPWSTR)&hMemCaption, 0, NULL);
86
87 MessageBoxW(hParent, hMemText, hMemCaption, MB_ICONERROR);
88
89 LocalFree(hMemCaption);
90 LocalFree(hMemText);
91 }
92
93 int WINAPI
94 WinMain (HINSTANCE hThisInstance,
95 HINSTANCE hPrevInstance,
96 LPSTR lpCmdLine,
97 int nCmdShow)
98 {
99 int argc;
100 INT i;
101 WCHAR** argv;
102 WCHAR szFileName[MAX_PATH] = L"";
103 DWORD dwSize;
104 HWND hMainWnd;
105 MSG msg;
106 WNDCLASSEXW wincl;
107 LPCWSTR fileName;
108
109 switch (GetUserDefaultUILanguage())
110 {
111 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
112 SetProcessDefaultLayout(LAYOUT_RTL);
113 break;
114
115 default:
116 break;
117 }
118
119 g_hInstance = hThisInstance;
120
121 /* Get unicode command line */
122 argv = CommandLineToArgvW(GetCommandLineW(), &argc);
123 if (argc < 2)
124 {
125 OPENFILENAMEW fontOpen;
126 WCHAR filter[MAX_PATH*2], dialogTitle[MAX_PATH];
127
128 LoadStringW(NULL, IDS_OPEN, dialogTitle, ARRAYSIZE(dialogTitle));
129 LoadStringW(NULL, IDS_FILTER_LIST, filter, ARRAYSIZE(filter));
130
131 /* Clears out any values of fontOpen before we use it */
132 ZeroMemory(&fontOpen, sizeof(fontOpen));
133
134 /* Sets up the open dialog box */
135 fontOpen.lStructSize = sizeof(fontOpen);
136 fontOpen.hwndOwner = NULL;
137 fontOpen.lpstrFilter = filter;
138 fontOpen.lpstrFile = szFileName;
139 fontOpen.lpstrTitle = dialogTitle;
140 fontOpen.nMaxFile = MAX_PATH;
141 fontOpen.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
142 fontOpen.lpstrDefExt = L"ttf";
143
144 /* Opens up the Open File dialog box in order to chose a font file. */
145 if(GetOpenFileNameW(&fontOpen))
146 {
147 fileName = fontOpen.lpstrFile;
148 g_fileName = fileName;
149 } else {
150 /* If the user decides to close out of the open dialog effectively
151 exiting the program altogether */
152 return 0;
153 }
154 }
155 else
156 {
157 /* Try to add the font resource from command line */
158 fileName = argv[1];
159 g_fileName = fileName;
160 }
161
162 if (!AddFontResourceW(fileName))
163 {
164 ErrorMsgBox(0, IDS_ERROR_NOFONT, fileName);
165 return -1;
166 }
167
168 /* Get the font name */
169 dwSize = sizeof(g_LogFonts);
170 ZeroMemory(g_LogFonts, sizeof(g_LogFonts));
171 if (!GetFontResourceInfoW(fileName, &dwSize, g_LogFonts, 2))
172 {
173 ErrorMsgBox(0, IDS_ERROR_NOFONT, fileName);
174 return -1;
175 }
176 g_NumFonts = 0;
177 for (i = 0; i < ARRAYSIZE(g_LogFonts); ++i)
178 {
179 if (g_LogFonts[i].lfFaceName[0] == 0)
180 break;
181
182 ++g_NumFonts;
183 }
184 if (g_NumFonts == 0)
185 {
186 ErrorMsgBox(0, IDS_ERROR_NOFONT, fileName);
187 return -1;
188 }
189
190 /* get font title */
191 dwSize = sizeof(g_FontTitle);
192 ZeroMemory(g_FontTitle, sizeof(g_FontTitle));
193 GetFontResourceInfoW(fileName, &dwSize, g_FontTitle, 1);
194
195 if (!Display_InitClass(hThisInstance))
196 {
197 ErrorMsgBox(0, IDS_ERROR_NOCLASS);
198 return -1;
199 }
200
201 /* The main window class */
202 wincl.cbSize = sizeof (WNDCLASSEXW);
203 wincl.style = CS_DBLCLKS;
204 wincl.lpfnWndProc = MainWndProc;
205 wincl.cbClsExtra = 0;
206 wincl.cbWndExtra = 0;
207 wincl.hInstance = hThisInstance;
208 wincl.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_TT));
209 wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
210 wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
211 wincl.lpszMenuName = NULL;
212 wincl.lpszClassName = g_szFontViewClassName;
213 wincl.hIconSm = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_TT));
214
215 /* Register the window class, and if it fails quit the program */
216 if (!RegisterClassExW (&wincl))
217 {
218 ErrorMsgBox(0, IDS_ERROR_NOCLASS);
219 return 0;
220 }
221
222 /* The class is registered, let's create the main window */
223 hMainWnd = CreateWindowExW(
224 0, /* Extended possibilities for variation */
225 g_szFontViewClassName, /* Classname */
226 g_FontTitle, /* Title Text */
227 WS_OVERLAPPEDWINDOW, /* default window */
228 CW_USEDEFAULT, /* Windows decides the position */
229 CW_USEDEFAULT, /* where the window ends up on the screen */
230 544, /* The programs width */
231 375, /* and height in pixels */
232 HWND_DESKTOP, /* The window is a child-window to desktop */
233 NULL, /* No menu */
234 hThisInstance, /* Program Instance handler */
235 NULL /* No Window Creation data */
236 );
237 ShowWindow(hMainWnd, nCmdShow);
238
239 /* Main message loop */
240 while (GetMessage (&msg, NULL, 0, 0))
241 {
242 if (IsDialogMessage(hMainWnd, &msg))
243 continue;
244 TranslateMessage(&msg);
245 DispatchMessage(&msg);
246 }
247
248 RemoveFontResourceW(argv[1]);
249
250 return (int)msg.wParam;
251 }
252
253 static LRESULT
254 MainWnd_OnCreate(HWND hwnd)
255 {
256 WCHAR szQuit[MAX_BUTTONNAME];
257 WCHAR szPrint[MAX_BUTTONNAME];
258 WCHAR szString[MAX_STRING];
259 WCHAR szPrevious[MAX_STRING];
260 WCHAR szNext[MAX_STRING];
261 HWND hDisplay, hButtonInstall, hButtonPrint, hButtonPrev, hButtonNext;
262
263 /* create the display window */
264 hDisplay = CreateWindowExW(
265 0, /* Extended style */
266 g_szFontDisplayClassName, /* Classname */
267 L"", /* Title text */
268 WS_CHILD | WS_VSCROLL, /* Window style */
269 0, /* X-pos */
270 HEADER_SIZE, /* Y-Pos */
271 550, /* Width */
272 370-HEADER_SIZE, /* Height */
273 hwnd, /* Parent */
274 (HMENU)IDC_DISPLAY, /* Identifier */
275 g_hInstance, /* Program Instance handler */
276 NULL /* Window Creation data */
277 );
278
279 LoadStringW(g_hInstance, IDS_STRING, szString, MAX_STRING);
280 SendMessage(hDisplay, FVM_SETSTRING, 0, (LPARAM)szString);
281
282 /* Create the install button */
283 LoadStringW(g_hInstance, IDS_INSTALL, szQuit, MAX_BUTTONNAME);
284 hButtonInstall = CreateWindowExW(
285 0, /* Extended style */
286 L"button", /* Classname */
287 szQuit, /* Title text */
288 WS_CHILD | WS_VISIBLE, /* Window style */
289 BUTTON_POS_X, /* X-pos */
290 BUTTON_POS_Y, /* Y-Pos */
291 BUTTON_WIDTH, /* Width */
292 BUTTON_HEIGHT, /* Height */
293 hwnd, /* Parent */
294 (HMENU)IDC_INSTALL, /* Identifier */
295 g_hInstance, /* Program Instance handler */
296 NULL /* Window Creation data */
297 );
298 SendMessage(hButtonInstall, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
299
300 /* Create the print button */
301 LoadStringW(g_hInstance, IDS_PRINT, szPrint, MAX_BUTTONNAME);
302 hButtonPrint = CreateWindowExW(
303 0, /* Extended style */
304 L"button", /* Classname */
305 szPrint, /* Title text */
306 WS_CHILD | WS_VISIBLE, /* Window style */
307 450, /* X-pos */
308 BUTTON_POS_Y, /* Y-Pos */
309 BUTTON_WIDTH, /* Width */
310 BUTTON_HEIGHT, /* Height */
311 hwnd, /* Parent */
312 (HMENU)IDC_PRINT, /* Identifier */
313 g_hInstance, /* Program Instance handler */
314 NULL /* Window Creation data */
315 );
316 SendMessage(hButtonPrint, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
317
318 /* Create the previous button */
319 LoadStringW(g_hInstance, IDS_PREVIOUS, szPrevious, MAX_BUTTONNAME);
320 hButtonPrev = CreateWindowExW(
321 0, /* Extended style */
322 L"button", /* Classname */
323 szPrevious, /* Title text */
324 WS_CHILD | WS_VISIBLE, /* Window style */
325 450, /* X-pos */
326 BUTTON_POS_Y, /* Y-Pos */
327 BUTTON_WIDTH, /* Width */
328 BUTTON_HEIGHT, /* Height */
329 hwnd, /* Parent */
330 (HMENU)IDC_PREV, /* Identifier */
331 g_hInstance, /* Program Instance handler */
332 NULL /* Window Creation data */
333 );
334 SendMessage(hButtonPrev, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
335
336 /* Create the next button */
337 LoadStringW(g_hInstance, IDS_NEXT, szNext, MAX_BUTTONNAME);
338 hButtonNext = CreateWindowExW(
339 0, /* Extended style */
340 L"button", /* Classname */
341 szNext, /* Title text */
342 WS_CHILD | WS_VISIBLE, /* Window style */
343 450, /* X-pos */
344 BUTTON_POS_Y, /* Y-Pos */
345 BUTTON_WIDTH, /* Width */
346 BUTTON_HEIGHT, /* Height */
347 hwnd, /* Parent */
348 (HMENU)IDC_NEXT, /* Identifier */
349 g_hInstance, /* Program Instance handler */
350 NULL /* Window Creation data */
351 );
352 SendMessage(hButtonNext, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
353
354 EnableWindow(hButtonPrev, FALSE);
355 if (g_NumFonts <= 1)
356 EnableWindow(hButtonNext, FALSE);
357
358 /* Init the display window with the font name */
359 g_FontIndex = 0;
360 SendMessage(hDisplay, FVM_SETTYPEFACE, 0, (LPARAM)&g_LogFonts[g_FontIndex]);
361 ShowWindow(hDisplay, SW_SHOWNORMAL);
362
363 return 0;
364 }
365
366 static LRESULT
367 MainWnd_OnSize(HWND hwnd)
368 {
369 RECT rc;
370 HWND hInstall, hPrint, hPrev, hNext, hDisplay;
371 HDWP hDWP;
372
373 GetClientRect(hwnd, &rc);
374
375 hDWP = BeginDeferWindowPos(5);
376
377 hInstall = GetDlgItem(hwnd, IDC_INSTALL);
378 if (hDWP)
379 hDWP = DeferWindowPos(hDWP, hInstall, NULL, BUTTON_POS_X, BUTTON_POS_Y, BUTTON_WIDTH, BUTTON_HEIGHT, SWP_NOZORDER);
380
381 hPrint = GetDlgItem(hwnd, IDC_PRINT);
382 if (hDWP)
383 hDWP = DeferWindowPos(hDWP, hPrint, NULL, BUTTON_POS_X + BUTTON_WIDTH + BUTTON_PADDING, BUTTON_POS_Y, BUTTON_WIDTH, BUTTON_HEIGHT, SWP_NOZORDER);
384
385 hPrev = GetDlgItem(hwnd, IDC_PREV);
386 if (hDWP)
387 hDWP = DeferWindowPos(hDWP, hPrev, NULL, rc.right - (BUTTON_WIDTH * 2 + BUTTON_PADDING + BUTTON_POS_X), BUTTON_POS_Y, BUTTON_WIDTH, BUTTON_HEIGHT, SWP_NOZORDER);
388
389 hNext = GetDlgItem(hwnd, IDC_NEXT);
390 if (hDWP)
391 hDWP = DeferWindowPos(hDWP, hNext, NULL, rc.right - (BUTTON_WIDTH + BUTTON_POS_X), BUTTON_POS_Y, BUTTON_WIDTH, BUTTON_HEIGHT, SWP_NOZORDER);
392
393 hDisplay = GetDlgItem(hwnd, IDC_DISPLAY);
394 if (hDWP)
395 hDWP = DeferWindowPos(hDWP, hDisplay, NULL, 0, HEADER_SIZE, rc.right, rc.bottom - HEADER_SIZE, SWP_NOZORDER);
396
397 EndDeferWindowPos(hDWP);
398
399 InvalidateRect(hwnd, NULL, TRUE);
400
401 return 0;
402 }
403
404 static LRESULT
405 MainWnd_OnPaint(HWND hwnd)
406 {
407 HDC hDC;
408 PAINTSTRUCT ps;
409 RECT rc;
410
411 hDC = BeginPaint(hwnd, &ps);
412 GetClientRect(hwnd, &rc);
413 rc.top = HEADER_SIZE - 2;
414 rc.bottom = HEADER_SIZE;
415 FillRect(hDC, &rc, GetStockObject(GRAY_BRUSH));
416 EndPaint(hwnd, &ps);
417 return 0;
418 }
419
420 static LRESULT
421 MainWnd_OnInstall(HWND hwnd)
422 {
423 DWORD fontExists;
424
425 /* First, we have to find out if the font still exists. */
426 fontExists = GetFileAttributes((LPCSTR)g_fileName);
427 if (fontExists != 0xFFFFFFFF) /* If the file does not exist */
428 {
429 ErrorMsgBox(0, IDS_ERROR_NOFONT, g_fileName);
430 return -1;
431 }
432
433 //CopyFile(g_fileName, NULL, TRUE);
434
435 MessageBox(hwnd, TEXT("This function is unimplemented"), TEXT("Unimplemented"), MB_OK);
436
437 return 0;
438 }
439
440 static LRESULT
441 MainWnd_OnPrev(HWND hwnd)
442 {
443 HWND hDisplay;
444 if (g_FontIndex > 0)
445 {
446 --g_FontIndex;
447 EnableWindow(GetDlgItem(hwnd, IDC_NEXT), TRUE);
448 if (g_FontIndex == 0)
449 EnableWindow(GetDlgItem(hwnd, IDC_PREV), FALSE);
450
451 hDisplay = GetDlgItem(hwnd, IDC_DISPLAY);
452 SendMessage(hDisplay, FVM_SETTYPEFACE, 0, (LPARAM)&g_LogFonts[g_FontIndex]);
453 InvalidateRect(hDisplay, NULL, TRUE);
454 }
455 return 0;
456 }
457
458 static LRESULT
459 MainWnd_OnNext(HWND hwnd)
460 {
461 HWND hDisplay;
462 if (g_FontIndex + 1 < g_NumFonts)
463 {
464 ++g_FontIndex;
465 EnableWindow(GetDlgItem(hwnd, IDC_PREV), TRUE);
466 if (g_FontIndex == g_NumFonts - 1)
467 EnableWindow(GetDlgItem(hwnd, IDC_NEXT), FALSE);
468
469 hDisplay = GetDlgItem(hwnd, IDC_DISPLAY);
470 SendMessage(hDisplay, FVM_SETTYPEFACE, 0, (LPARAM)&g_LogFonts[g_FontIndex]);
471 InvalidateRect(hDisplay, NULL, TRUE);
472 }
473 return 0;
474 }
475
476 LRESULT CALLBACK
477 MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
478 {
479 switch (message)
480 {
481 case WM_CREATE:
482 return MainWnd_OnCreate(hwnd);
483
484 case WM_PAINT:
485 return MainWnd_OnPaint(hwnd);
486
487 case WM_SIZE:
488 return MainWnd_OnSize(hwnd);
489
490 case WM_COMMAND:
491 switch(LOWORD(wParam))
492 {
493 case IDC_INSTALL:
494 return MainWnd_OnInstall(hwnd);
495
496 case IDC_PRINT:
497 return Display_OnPrint(hwnd);
498
499 case IDC_PREV:
500 return MainWnd_OnPrev(hwnd);
501
502 case IDC_NEXT:
503 return MainWnd_OnNext(hwnd);
504 }
505 break;
506
507 case WM_DESTROY:
508 PostQuitMessage (0); /* send a WM_QUIT to the message queue */
509 break;
510
511 default: /* for messages that we don't deal with */
512 return DefWindowProcW(hwnd, message, wParam, lParam);
513 }
514
515 return 0;
516 }
517
518 /* EOF */