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