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 #include <winreg.h> 30 31 #include "fontview.h" 32 #include "resource.h" 33 34 HINSTANCE g_hInstance; 35 INT g_FontIndex = 0; 36 INT g_NumFonts = 0; 37 LOGFONTW g_LogFonts[64]; 38 LPCWSTR g_fileName; 39 WCHAR g_FontTitle[1024] = L""; 40 BOOL g_FontPrint = FALSE; 41 BOOL g_DisableInstall = FALSE; 42 43 static const WCHAR g_szFontViewClassName[] = L"FontViewWClass"; 44 45 /* GetFontResourceInfoW is undocumented */ 46 BOOL WINAPI GetFontResourceInfoW(LPCWSTR lpFileName, DWORD *pdwBufSize, void* lpBuffer, DWORD dwType); 47 48 DWORD 49 FormatString( 50 DWORD dwFlags, 51 HINSTANCE hInstance, 52 DWORD dwStringId, 53 DWORD dwLanguageId, 54 LPWSTR lpBuffer, 55 DWORD nSize, 56 va_list* Arguments 57 ) 58 { 59 DWORD dwRet; 60 int len; 61 WCHAR Buffer[1000]; 62 63 len = LoadStringW(hInstance, dwStringId, (LPWSTR)Buffer, 1000); 64 65 if (len) 66 { 67 dwFlags |= FORMAT_MESSAGE_FROM_STRING; 68 dwFlags &= ~(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM); 69 dwRet = FormatMessageW(dwFlags, Buffer, 0, dwLanguageId, lpBuffer, nSize, Arguments); 70 return dwRet; 71 } 72 return 0; 73 } 74 75 static void 76 ErrorMsgBox(HWND hParent, DWORD dwMessageId, ...) 77 { 78 HLOCAL hMemCaption = NULL; 79 HLOCAL hMemText = NULL; 80 va_list args; 81 82 va_start(args, dwMessageId); 83 FormatString(FORMAT_MESSAGE_ALLOCATE_BUFFER, 84 NULL, dwMessageId, 0, (LPWSTR)&hMemText, 0, &args); 85 va_end(args); 86 87 FormatString(FORMAT_MESSAGE_ALLOCATE_BUFFER, 88 NULL, IDS_ERROR, 0, (LPWSTR)&hMemCaption, 0, NULL); 89 90 MessageBoxW(hParent, hMemText, hMemCaption, MB_ICONERROR); 91 92 LocalFree(hMemCaption); 93 LocalFree(hMemText); 94 } 95 96 int WINAPI 97 wWinMain(HINSTANCE hThisInstance, 98 HINSTANCE hPrevInstance, 99 LPWSTR lpCmdLine, 100 int nCmdShow) 101 { 102 int argc; 103 INT i; 104 WCHAR** argv; 105 WCHAR szFileName[MAX_PATH] = L""; 106 DWORD dwSize; 107 HWND hMainWnd; 108 MSG msg; 109 WNDCLASSEXW wincl; 110 LPCWSTR fileName; 111 112 switch (GetUserDefaultUILanguage()) 113 { 114 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT): 115 SetProcessDefaultLayout(LAYOUT_RTL); 116 break; 117 118 default: 119 break; 120 } 121 122 g_hInstance = hThisInstance; 123 124 /* Get unicode command line */ 125 argv = CommandLineToArgvW(GetCommandLineW(), &argc); 126 if (argc < 2) 127 { 128 OPENFILENAMEW fontOpen; 129 WCHAR filter[MAX_PATH*2], dialogTitle[MAX_PATH]; 130 131 LoadStringW(NULL, IDS_OPEN, dialogTitle, ARRAYSIZE(dialogTitle)); 132 LoadStringW(NULL, IDS_FILTER_LIST, filter, ARRAYSIZE(filter)); 133 134 /* Clears out any values of fontOpen before we use it */ 135 ZeroMemory(&fontOpen, sizeof(fontOpen)); 136 137 /* Sets up the open dialog box */ 138 fontOpen.lStructSize = sizeof(fontOpen); 139 fontOpen.hwndOwner = NULL; 140 fontOpen.lpstrFilter = filter; 141 fontOpen.lpstrFile = szFileName; 142 fontOpen.lpstrTitle = dialogTitle; 143 fontOpen.nMaxFile = MAX_PATH; 144 fontOpen.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 145 fontOpen.lpstrDefExt = L"ttf"; 146 147 /* Opens up the Open File dialog box in order to chose a font file. */ 148 if(GetOpenFileNameW(&fontOpen)) 149 { 150 fileName = fontOpen.lpstrFile; 151 g_fileName = fileName; 152 } else { 153 /* If the user decides to close out of the open dialog effectively 154 exiting the program altogether */ 155 return 0; 156 } 157 } 158 else 159 { 160 /* Try to add the font resource from command line */ 161 for (i = 1; i < argc; ++i) 162 { 163 // Treat the last argument as filename 164 if (i + 1 == argc) 165 { 166 fileName = argv[i]; 167 } 168 else if (argv[i][0] == '/' || argv[i][0] == '-') 169 { 170 switch (argv[i][1]) 171 { 172 case 'p': 173 case 'P': 174 g_FontPrint = TRUE; 175 break; 176 case 'd': 177 case 'D': 178 g_DisableInstall = TRUE; 179 break; 180 default: 181 fileName = argv[i]; 182 break; 183 } 184 } 185 else 186 { 187 fileName = argv[i]; 188 } 189 } 190 g_fileName = fileName; 191 } 192 193 if (!AddFontResourceW(fileName)) 194 { 195 ErrorMsgBox(0, IDS_ERROR_NOFONT, fileName); 196 return -1; 197 } 198 199 /* Get the font name */ 200 dwSize = sizeof(g_LogFonts); 201 ZeroMemory(g_LogFonts, sizeof(g_LogFonts)); 202 if (!GetFontResourceInfoW(fileName, &dwSize, g_LogFonts, 2)) 203 { 204 ErrorMsgBox(0, IDS_ERROR_NOFONT, fileName); 205 return -1; 206 } 207 g_NumFonts = 0; 208 for (i = 0; i < ARRAYSIZE(g_LogFonts); ++i) 209 { 210 if (g_LogFonts[i].lfFaceName[0] == 0) 211 break; 212 213 ++g_NumFonts; 214 } 215 if (g_NumFonts == 0) 216 { 217 ErrorMsgBox(0, IDS_ERROR_NOFONT, fileName); 218 return -1; 219 } 220 221 /* get font title */ 222 dwSize = sizeof(g_FontTitle); 223 ZeroMemory(g_FontTitle, sizeof(g_FontTitle)); 224 GetFontResourceInfoW(fileName, &dwSize, g_FontTitle, 1); 225 226 if (!Display_InitClass(hThisInstance)) 227 { 228 ErrorMsgBox(0, IDS_ERROR_NOCLASS); 229 return -1; 230 } 231 232 /* The main window class */ 233 wincl.cbSize = sizeof (WNDCLASSEXW); 234 wincl.style = CS_DBLCLKS; 235 wincl.lpfnWndProc = MainWndProc; 236 wincl.cbClsExtra = 0; 237 wincl.cbWndExtra = 0; 238 wincl.hInstance = hThisInstance; 239 wincl.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_TT)); 240 wincl.hCursor = LoadCursor (NULL, IDC_ARROW); 241 wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND; 242 wincl.lpszMenuName = NULL; 243 wincl.lpszClassName = g_szFontViewClassName; 244 wincl.hIconSm = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_TT)); 245 246 /* Register the window class, and if it fails quit the program */ 247 if (!RegisterClassExW (&wincl)) 248 { 249 ErrorMsgBox(0, IDS_ERROR_NOCLASS); 250 return 0; 251 } 252 253 /* The class is registered, let's create the main window */ 254 hMainWnd = CreateWindowExW( 255 0, /* Extended possibilities for variation */ 256 g_szFontViewClassName, /* Classname */ 257 g_FontTitle, /* Title Text */ 258 WS_OVERLAPPEDWINDOW, /* default window */ 259 CW_USEDEFAULT, /* Windows decides the position */ 260 CW_USEDEFAULT, /* where the window ends up on the screen */ 261 544, /* The programs width */ 262 375, /* and height in pixels */ 263 HWND_DESKTOP, /* The window is a child-window to desktop */ 264 NULL, /* No menu */ 265 hThisInstance, /* Program Instance handler */ 266 NULL /* No Window Creation data */ 267 ); 268 ShowWindow(hMainWnd, nCmdShow); 269 270 /* Main message loop */ 271 while (GetMessage (&msg, NULL, 0, 0)) 272 { 273 if (IsDialogMessage(hMainWnd, &msg)) 274 continue; 275 TranslateMessage(&msg); 276 DispatchMessage(&msg); 277 } 278 279 RemoveFontResourceW(argv[1]); 280 281 return (int)msg.wParam; 282 } 283 284 static LRESULT 285 MainWnd_OnCreate(HWND hwnd) 286 { 287 WCHAR szQuit[MAX_BUTTONNAME]; 288 WCHAR szPrint[MAX_BUTTONNAME]; 289 WCHAR szString[MAX_STRING]; 290 WCHAR szPrevious[MAX_STRING]; 291 WCHAR szNext[MAX_STRING]; 292 HWND hDisplay, hButtonInstall, hButtonPrint, hButtonPrev, hButtonNext; 293 294 /* create the display window */ 295 hDisplay = CreateWindowExW( 296 0, /* Extended style */ 297 g_szFontDisplayClassName, /* Classname */ 298 L"", /* Title text */ 299 WS_CHILD | WS_VSCROLL, /* Window style */ 300 0, /* X-pos */ 301 HEADER_SIZE, /* Y-Pos */ 302 550, /* Width */ 303 370-HEADER_SIZE, /* Height */ 304 hwnd, /* Parent */ 305 (HMENU)IDC_DISPLAY, /* Identifier */ 306 g_hInstance, /* Program Instance handler */ 307 NULL /* Window Creation data */ 308 ); 309 310 LoadStringW(g_hInstance, IDS_STRING, szString, MAX_STRING); 311 SendMessage(hDisplay, FVM_SETSTRING, 0, (LPARAM)szString); 312 313 /* Create the install button */ 314 LoadStringW(g_hInstance, IDS_INSTALL, szQuit, MAX_BUTTONNAME); 315 hButtonInstall = CreateWindowExW( 316 0, /* Extended style */ 317 L"button", /* Classname */ 318 szQuit, /* Title text */ 319 WS_CHILD | WS_VISIBLE, /* Window style */ 320 BUTTON_POS_X, /* X-pos */ 321 BUTTON_POS_Y, /* Y-Pos */ 322 BUTTON_WIDTH, /* Width */ 323 BUTTON_HEIGHT, /* Height */ 324 hwnd, /* Parent */ 325 (HMENU)IDC_INSTALL, /* Identifier */ 326 g_hInstance, /* Program Instance handler */ 327 NULL /* Window Creation data */ 328 ); 329 SendMessage(hButtonInstall, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE); 330 EnableWindow(hButtonInstall, !g_DisableInstall); 331 332 /* Create the print button */ 333 LoadStringW(g_hInstance, IDS_PRINT, szPrint, MAX_BUTTONNAME); 334 hButtonPrint = CreateWindowExW( 335 0, /* Extended style */ 336 L"button", /* Classname */ 337 szPrint, /* Title text */ 338 WS_CHILD | WS_VISIBLE, /* Window style */ 339 450, /* X-pos */ 340 BUTTON_POS_Y, /* Y-Pos */ 341 BUTTON_WIDTH, /* Width */ 342 BUTTON_HEIGHT, /* Height */ 343 hwnd, /* Parent */ 344 (HMENU)IDC_PRINT, /* Identifier */ 345 g_hInstance, /* Program Instance handler */ 346 NULL /* Window Creation data */ 347 ); 348 SendMessage(hButtonPrint, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE); 349 350 /* Create the previous button */ 351 LoadStringW(g_hInstance, IDS_PREVIOUS, szPrevious, MAX_BUTTONNAME); 352 hButtonPrev = CreateWindowExW( 353 0, /* Extended style */ 354 L"button", /* Classname */ 355 szPrevious, /* Title text */ 356 WS_CHILD | WS_VISIBLE, /* Window style */ 357 450, /* X-pos */ 358 BUTTON_POS_Y, /* Y-Pos */ 359 BUTTON_WIDTH, /* Width */ 360 BUTTON_HEIGHT, /* Height */ 361 hwnd, /* Parent */ 362 (HMENU)IDC_PREV, /* Identifier */ 363 g_hInstance, /* Program Instance handler */ 364 NULL /* Window Creation data */ 365 ); 366 SendMessage(hButtonPrev, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE); 367 368 /* Create the next button */ 369 LoadStringW(g_hInstance, IDS_NEXT, szNext, MAX_BUTTONNAME); 370 hButtonNext = CreateWindowExW( 371 0, /* Extended style */ 372 L"button", /* Classname */ 373 szNext, /* Title text */ 374 WS_CHILD | WS_VISIBLE, /* Window style */ 375 450, /* X-pos */ 376 BUTTON_POS_Y, /* Y-Pos */ 377 BUTTON_WIDTH, /* Width */ 378 BUTTON_HEIGHT, /* Height */ 379 hwnd, /* Parent */ 380 (HMENU)IDC_NEXT, /* Identifier */ 381 g_hInstance, /* Program Instance handler */ 382 NULL /* Window Creation data */ 383 ); 384 SendMessage(hButtonNext, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE); 385 386 EnableWindow(hButtonPrev, FALSE); 387 if (g_NumFonts <= 1) 388 EnableWindow(hButtonNext, FALSE); 389 390 /* Init the display window with the font name */ 391 g_FontIndex = 0; 392 SendMessage(hDisplay, FVM_SETTYPEFACE, 0, (LPARAM)&g_LogFonts[g_FontIndex]); 393 ShowWindow(hDisplay, SW_SHOWNORMAL); 394 395 if (g_FontPrint) 396 PostMessage(hwnd, WM_COMMAND, IDC_PRINT, 0); 397 398 return 0; 399 } 400 401 static LRESULT 402 MainWnd_OnSize(HWND hwnd) 403 { 404 RECT rc; 405 HWND hInstall, hPrint, hPrev, hNext, hDisplay; 406 HDWP hDWP; 407 408 GetClientRect(hwnd, &rc); 409 410 hDWP = BeginDeferWindowPos(5); 411 412 hInstall = GetDlgItem(hwnd, IDC_INSTALL); 413 if (hDWP) 414 hDWP = DeferWindowPos(hDWP, hInstall, NULL, BUTTON_POS_X, BUTTON_POS_Y, BUTTON_WIDTH, BUTTON_HEIGHT, SWP_NOZORDER); 415 416 hPrint = GetDlgItem(hwnd, IDC_PRINT); 417 if (hDWP) 418 hDWP = DeferWindowPos(hDWP, hPrint, NULL, BUTTON_POS_X + BUTTON_WIDTH + BUTTON_PADDING, BUTTON_POS_Y, BUTTON_WIDTH, BUTTON_HEIGHT, SWP_NOZORDER); 419 420 hPrev = GetDlgItem(hwnd, IDC_PREV); 421 if (hDWP) 422 hDWP = DeferWindowPos(hDWP, hPrev, NULL, rc.right - (BUTTON_WIDTH * 2 + BUTTON_PADDING + BUTTON_POS_X), BUTTON_POS_Y, BUTTON_WIDTH, BUTTON_HEIGHT, SWP_NOZORDER); 423 424 hNext = GetDlgItem(hwnd, IDC_NEXT); 425 if (hDWP) 426 hDWP = DeferWindowPos(hDWP, hNext, NULL, rc.right - (BUTTON_WIDTH + BUTTON_POS_X), BUTTON_POS_Y, BUTTON_WIDTH, BUTTON_HEIGHT, SWP_NOZORDER); 427 428 hDisplay = GetDlgItem(hwnd, IDC_DISPLAY); 429 if (hDWP) 430 hDWP = DeferWindowPos(hDWP, hDisplay, NULL, 0, HEADER_SIZE, rc.right, rc.bottom - HEADER_SIZE, SWP_NOZORDER); 431 432 EndDeferWindowPos(hDWP); 433 434 InvalidateRect(hwnd, NULL, TRUE); 435 436 return 0; 437 } 438 439 static LRESULT 440 MainWnd_OnPaint(HWND hwnd) 441 { 442 HDC hDC; 443 PAINTSTRUCT ps; 444 RECT rc; 445 446 hDC = BeginPaint(hwnd, &ps); 447 GetClientRect(hwnd, &rc); 448 rc.top = HEADER_SIZE - 2; 449 rc.bottom = HEADER_SIZE; 450 FillRect(hDC, &rc, GetStockObject(GRAY_BRUSH)); 451 EndPaint(hwnd, &ps); 452 return 0; 453 } 454 455 static LRESULT 456 MainWnd_OnInstall(HWND hwnd) 457 { 458 WCHAR szFullName[64]; 459 460 WCHAR szSrcPath[MAX_PATH]; 461 WCHAR szDestPath[MAX_PATH]; 462 PWSTR pszFileName; 463 LONG res; 464 HKEY hKey; 465 466 SendDlgItemMessage(hwnd, IDC_DISPLAY, FVM_GETFULLNAME, 64, (LPARAM)szFullName); 467 // MessageBoxW(hwnd, szFullName, L"Debug", MB_OK); 468 469 /* First, we have to find out if the font still exists */ 470 if (GetFileAttributes(g_fileName) == INVALID_FILE_ATTRIBUTES) 471 { 472 /* Fail, if the source file does not exist */ 473 ErrorMsgBox(0, IDS_ERROR_NOFONT, g_fileName); 474 return -1; 475 } 476 477 /* Build the full destination file name */ 478 GetFullPathNameW(g_fileName, MAX_PATH, szSrcPath, &pszFileName); 479 480 GetWindowsDirectoryW(szDestPath, MAX_PATH); 481 wcscat(szDestPath, L"\\Fonts\\"); 482 wcscat(szDestPath, pszFileName); 483 484 /* Debug Message */ 485 // MessageBoxW(hwnd, szDestPath, L"szDestPath", MB_OK); 486 // MessageBoxW(hwnd, pszFileName, L"pszFileExt", MB_OK); 487 488 /* Check if the file already exists */ 489 if (GetFileAttributesW(szDestPath) != INVALID_FILE_ATTRIBUTES) 490 { 491 MessageBoxW(hwnd, L"This font is already installed!", L"Already Installed", MB_OK); 492 return 0; 493 } 494 495 /* Copy the font file */ 496 if (!CopyFileW(g_fileName, szDestPath, TRUE)) 497 { 498 MessageBoxW(hwnd,L"Failed to copy the font file!", L"File Error", MB_OK); 499 return -1; 500 } 501 502 /* Open the fonts key */ 503 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 504 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", 505 0, 506 KEY_ALL_ACCESS, 507 &hKey); 508 if (res != ERROR_SUCCESS) 509 { 510 MessageBoxW(hwnd, L"Failed top open the fonts key!", L"Debug1", MB_OK); 511 return -1; 512 } 513 514 /* Register the font */ 515 res = RegSetValueExW(hKey, 516 szFullName, 517 0, 518 REG_SZ, 519 (LPBYTE)pszFileName, 520 (wcslen(pszFileName) + 1) * sizeof(WCHAR)); 521 if (res != ERROR_SUCCESS) 522 { 523 MessageBoxW(hwnd, L"Failed to register the new font!", L"Debug2", MB_OK); 524 RegCloseKey(hKey); 525 return -1; 526 } 527 528 /* Close the fonts key */ 529 RegCloseKey(hKey); 530 531 /* Broadcast WM_FONTCHANGE message */ 532 SendMessageW(HWND_BROADCAST, WM_FONTCHANGE, 0, 0); 533 534 /* if all of this goes correctly, message the user about success */ 535 MessageBoxW(hwnd, L"Font Installation Completed.", L"Success", MB_OK); 536 537 return 0; 538 } 539 540 static LRESULT 541 MainWnd_OnPrev(HWND hwnd) 542 { 543 HWND hDisplay; 544 if (g_FontIndex > 0) 545 { 546 --g_FontIndex; 547 EnableWindow(GetDlgItem(hwnd, IDC_NEXT), TRUE); 548 if (g_FontIndex == 0) 549 EnableWindow(GetDlgItem(hwnd, IDC_PREV), FALSE); 550 551 hDisplay = GetDlgItem(hwnd, IDC_DISPLAY); 552 SendMessage(hDisplay, FVM_SETTYPEFACE, 0, (LPARAM)&g_LogFonts[g_FontIndex]); 553 InvalidateRect(hDisplay, NULL, TRUE); 554 } 555 return 0; 556 } 557 558 static LRESULT 559 MainWnd_OnNext(HWND hwnd) 560 { 561 HWND hDisplay; 562 if (g_FontIndex + 1 < g_NumFonts) 563 { 564 ++g_FontIndex; 565 EnableWindow(GetDlgItem(hwnd, IDC_PREV), TRUE); 566 if (g_FontIndex == g_NumFonts - 1) 567 EnableWindow(GetDlgItem(hwnd, IDC_NEXT), FALSE); 568 569 hDisplay = GetDlgItem(hwnd, IDC_DISPLAY); 570 SendMessage(hDisplay, FVM_SETTYPEFACE, 0, (LPARAM)&g_LogFonts[g_FontIndex]); 571 InvalidateRect(hDisplay, NULL, TRUE); 572 } 573 return 0; 574 } 575 576 LRESULT CALLBACK 577 MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 578 { 579 switch (message) 580 { 581 case WM_CREATE: 582 return MainWnd_OnCreate(hwnd); 583 584 case WM_PAINT: 585 return MainWnd_OnPaint(hwnd); 586 587 case WM_SIZE: 588 return MainWnd_OnSize(hwnd); 589 590 case WM_COMMAND: 591 switch(LOWORD(wParam)) 592 { 593 case IDC_INSTALL: 594 return MainWnd_OnInstall(hwnd); 595 596 case IDC_PRINT: 597 return Display_OnPrint(hwnd); 598 599 case IDC_PREV: 600 return MainWnd_OnPrev(hwnd); 601 602 case IDC_NEXT: 603 return MainWnd_OnNext(hwnd); 604 } 605 break; 606 607 case WM_DESTROY: 608 PostQuitMessage (0); /* send a WM_QUIT to the message queue */ 609 break; 610 611 default: /* for messages that we don't deal with */ 612 return DefWindowProcW(hwnd, message, wParam, lParam); 613 } 614 615 return 0; 616 } 617 618 /* EOF */ 619