1 /* 2 * PROJECT: ReactOS Notepad 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Providing a Windows-compatible simple text editor for ReactOS 5 * COPYRIGHT: Copyright 1998,99 Marcel Baur <mbaur@g26.ethz.ch> 6 * Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr> 7 * Copyright 2002 Andriy Palamarchuk 8 * Copyright 2020-2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 9 */ 10 11 #include "notepad.h" 12 13 #include <strsafe.h> 14 #include <assert.h> 15 16 static VOID AlertPrintError(VOID) 17 { 18 TCHAR szUntitled[MAX_STRING_LEN]; 19 20 LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, _countof(szUntitled)); 21 22 DIALOG_StringMsgBox(Globals.hMainWnd, STRING_PRINTERROR, 23 Globals.szFileName[0] ? Globals.szFileName : szUntitled, 24 MB_ICONEXCLAMATION | MB_OK); 25 } 26 27 static RECT 28 GetPrintingRect(IN HDC hdc, IN LPCRECT pMargins) 29 { 30 INT iLogPixelsX = GetDeviceCaps(hdc, LOGPIXELSX); 31 INT iLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); 32 INT iHorzRes = GetDeviceCaps(hdc, HORZRES); /* in pixels */ 33 INT iVertRes = GetDeviceCaps(hdc, VERTRES); /* in pixels */ 34 RECT rcPrintRect, rcPhysical; 35 36 #define CONVERT_X(x) MulDiv((x), iLogPixelsX, 2540) /* 100th millimeters to pixels */ 37 #define CONVERT_Y(y) MulDiv((y), iLogPixelsY, 2540) /* 100th millimeters to pixels */ 38 SetRect(&rcPrintRect, 39 CONVERT_X(pMargins->left), CONVERT_Y(pMargins->top), 40 iHorzRes - CONVERT_X(pMargins->right), 41 iVertRes - CONVERT_Y(pMargins->bottom)); 42 43 rcPhysical.left = GetDeviceCaps(hdc, PHYSICALOFFSETX); 44 rcPhysical.right = rcPhysical.left + GetDeviceCaps(hdc, PHYSICALWIDTH); 45 rcPhysical.top = GetDeviceCaps(hdc, PHYSICALOFFSETY); 46 rcPhysical.bottom = rcPhysical.top + GetDeviceCaps(hdc, PHYSICALHEIGHT); 47 48 /* Adjust the margin */ 49 rcPrintRect.left = max(rcPrintRect.left, rcPhysical.left); 50 rcPrintRect.top = max(rcPrintRect.top, rcPhysical.top); 51 rcPrintRect.right = min(rcPrintRect.right, rcPhysical.right); 52 rcPrintRect.bottom = min(rcPrintRect.bottom, rcPhysical.bottom); 53 54 return rcPrintRect; 55 } 56 57 static INT GetSelectionTextLength(HWND hWnd) 58 { 59 DWORD dwStart = 0, dwEnd = 0; 60 SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); 61 return dwEnd - dwStart; 62 } 63 64 static INT GetSelectionText(HWND hWnd, LPTSTR lpString, INT nMaxCount) 65 { 66 DWORD dwStart = 0, dwEnd = 0; 67 INT cchText = GetWindowTextLength(hWnd); 68 LPTSTR pszText; 69 HLOCAL hLocal; 70 HRESULT hr; 71 72 SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); 73 if (!lpString || dwStart == dwEnd || cchText == 0) 74 return 0; 75 76 hLocal = (HLOCAL)SendMessage(hWnd, EM_GETHANDLE, 0, 0); 77 pszText = (LPTSTR)LocalLock(hLocal); 78 if (!pszText) 79 return 0; 80 81 hr = StringCchCopyN(lpString, nMaxCount, pszText + dwStart, dwEnd - dwStart); 82 LocalUnlock(hLocal); 83 84 switch (hr) 85 { 86 case S_OK: 87 return dwEnd - dwStart; 88 89 case STRSAFE_E_INSUFFICIENT_BUFFER: 90 return nMaxCount - 1; 91 92 default: 93 return 0; 94 } 95 } 96 97 typedef struct 98 { 99 PRINTDLG printer; 100 HWND hwndDlg; 101 INT status; 102 INT currentPage; 103 RECT printRect; 104 SYSTEMTIME stNow; 105 HFONT hHeaderFont; 106 HFONT hBodyFont; 107 LPTSTR pszText; 108 DWORD ich; 109 DWORD cchText; 110 INT cyHeader; 111 INT cySpacing; 112 INT cyFooter; 113 } PRINT_DATA, *PPRINT_DATA; 114 115 /* Convert the points into pixels */ 116 #define X_POINTS_TO_PIXELS(hDC, points) MulDiv((points), GetDeviceCaps((hDC), LOGPIXELSX), 72) 117 #define Y_POINTS_TO_PIXELS(hDC, points) MulDiv((points), GetDeviceCaps((hDC), LOGPIXELSY), 72) 118 119 /* 120 * See also: 121 * https://support.microsoft.com/en-us/windows/changing-header-and-footer-commands-in-notepad-c1b0e27b-497d-c478-c4c1-0da491cac148 122 */ 123 static VOID 124 DrawHeaderOrFooter(HDC hDC, LPRECT pRect, LPCTSTR pszFormat, INT nPageNo, const SYSTEMTIME *pstNow) 125 { 126 TCHAR szText[256], szField[128]; 127 const TCHAR *pchFormat; 128 UINT uAlign = DT_CENTER, uFlags = DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX; 129 HGDIOBJ hOldPen, hOldBrush; 130 131 /* Draw a rectangle */ 132 hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN)); 133 hOldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH)); 134 Rectangle(hDC, pRect->left, pRect->top, pRect->right, pRect->bottom); 135 SelectObject(hDC, hOldBrush); 136 SelectObject(hDC, hOldPen); 137 138 InflateRect(pRect, -X_POINTS_TO_PIXELS(hDC, 3), 0); /* Shrink 3pt */ 139 140 szText[0] = 0; 141 142 for (pchFormat = pszFormat; *pchFormat; ++pchFormat) 143 { 144 if (*pchFormat != _T('&')) 145 { 146 StringCchCatN(szText, _countof(szText), pchFormat, 1); 147 continue; 148 } 149 150 ++pchFormat; 151 if (*pchFormat == 0) 152 break; 153 154 switch (_totupper(*pchFormat)) /* Make it uppercase */ 155 { 156 case _T('&'): /* Found double ampersand */ 157 StringCchCat(szText, _countof(szText), TEXT("&")); 158 break; 159 160 case _T('L'): /* Left */ 161 DrawText(hDC, szText, -1, pRect, uAlign | uFlags); 162 szText[0] = 0; 163 uAlign = DT_LEFT; 164 break; 165 166 case _T('C'): /* Center */ 167 DrawText(hDC, szText, -1, pRect, uAlign | uFlags); 168 szText[0] = 0; 169 uAlign = DT_CENTER; 170 break; 171 172 case _T('R'): /* Right */ 173 DrawText(hDC, szText, -1, pRect, uAlign | uFlags); 174 szText[0] = 0; 175 uAlign = DT_RIGHT; 176 break; 177 178 case _T('D'): /* Date */ 179 GetDateFormat(LOCALE_USER_DEFAULT, 0, pstNow, NULL, 180 szField, (INT)_countof(szField)); 181 StringCchCat(szText, _countof(szText), szField); 182 break; 183 184 case _T('T'): /* Time */ 185 GetTimeFormat(LOCALE_USER_DEFAULT, 0, pstNow, NULL, 186 szField, (INT)_countof(szField)); 187 StringCchCat(szText, _countof(szText), szField); 188 break; 189 190 case _T('F'): /* Filename */ 191 StringCchCat(szText, _countof(szText), Globals.szFileTitle); 192 break; 193 194 case _T('P'): /* Page number */ 195 StringCchPrintf(szField, _countof(szField), TEXT("%u"), nPageNo); 196 StringCchCat(szText, _countof(szText), szField); 197 break; 198 199 default: /* Otherwise */ 200 szField[0] = _T('&'); 201 szField[1] = *pchFormat; 202 szField[2] = 0; 203 StringCchCat(szText, _countof(szText), szField); 204 break; 205 } 206 } 207 208 DrawText(hDC, szText, -1, pRect, uAlign | uFlags); 209 } 210 211 static BOOL DoPrintBody(PPRINT_DATA pData, DWORD PageCount, BOOL bSkipPage) 212 { 213 LPPRINTDLG pPrinter = &pData->printer; 214 RECT printRect = pData->printRect; 215 INT xLeft = printRect.left, yTop = printRect.top + pData->cyHeader + pData->cySpacing; 216 INT xStart, tabWidth; 217 DWORD ichStart; 218 SIZE charMetrics; 219 TEXTMETRIC tmText; 220 221 /* Calculate a tab width */ 222 #define TAB_STOP 8 223 GetTextMetrics(pPrinter->hDC, &tmText); 224 tabWidth = TAB_STOP * tmText.tmAveCharWidth; 225 226 #define DO_FLUSH() do { \ 227 if (ichStart < pData->ich && !bSkipPage) { \ 228 TextOut(pPrinter->hDC, xStart, yTop, &pData->pszText[ichStart], pData->ich - ichStart); \ 229 } \ 230 ichStart = pData->ich; \ 231 xStart = xLeft; \ 232 if (pData->status == STRING_PRINTCANCELING) return FALSE; \ 233 } while (0) 234 235 /* The drawing-body loop */ 236 for (ichStart = pData->ich, xStart = xLeft; pData->ich < pData->cchText; ) 237 { 238 TCHAR ch = pData->pszText[pData->ich]; 239 240 if (ch == _T('\r')) 241 { 242 DO_FLUSH(); 243 244 pData->ich++; /* Next char */ 245 ichStart = pData->ich; 246 continue; 247 } 248 249 if (ch == _T('\n')) 250 { 251 DO_FLUSH(); 252 253 /* Next line */ 254 yTop += tmText.tmHeight; 255 xLeft = xStart = printRect.left; 256 } 257 else 258 { 259 if (ch == _T('\t')) 260 { 261 INT nStepWidth = tabWidth - ((xLeft - printRect.left) % tabWidth); 262 263 DO_FLUSH(); 264 265 /* Go to the next tab stop */ 266 xLeft += nStepWidth; 267 xStart = xLeft; 268 } 269 else /* Normal char */ 270 { 271 GetTextExtentPoint32(pPrinter->hDC, &ch, 1, &charMetrics); 272 xLeft += charMetrics.cx; 273 } 274 275 /* Insert a line break if the next position reached the right edge */ 276 if (xLeft + charMetrics.cx >= printRect.right) 277 { 278 if (ch != _T('\t')) 279 DO_FLUSH(); 280 281 /* Next line */ 282 yTop += tmText.tmHeight; 283 xLeft = xStart = printRect.left; 284 } 285 } 286 287 pData->ich++; /* Next char */ 288 if (ch == _T('\t') || ch == _T('\n')) 289 ichStart = pData->ich; 290 291 if (yTop + tmText.tmHeight >= printRect.bottom - pData->cyFooter) 292 break; /* The next line reached the body bottom */ 293 } 294 295 DO_FLUSH(); 296 return TRUE; 297 } 298 299 static BOOL DoPrintPage(PPRINT_DATA pData, DWORD PageCount) 300 { 301 LPPRINTDLG pPrinter = &pData->printer; 302 BOOL bSkipPage, ret; 303 HFONT hOldFont; 304 305 /* Should we skip this page? */ 306 bSkipPage = !(pPrinter->Flags & PD_SELECTION) && 307 (pPrinter->Flags & PD_PAGENUMS) && 308 !(pPrinter->nFromPage <= PageCount && PageCount <= pPrinter->nToPage); 309 310 /* The prologue of a page */ 311 if (!bSkipPage) 312 { 313 if (StartPage(pPrinter->hDC) <= 0) 314 { 315 pData->status = STRING_PRINTFAILED; 316 return FALSE; 317 } 318 319 if (pData->cyHeader > 0) 320 { 321 /* Draw the page header */ 322 RECT rc = pData->printRect; 323 rc.bottom = rc.top + pData->cyHeader; 324 325 hOldFont = SelectObject(pPrinter->hDC, pData->hHeaderFont); 326 DrawHeaderOrFooter(pPrinter->hDC, &rc, Globals.szHeader, PageCount, &pData->stNow); 327 SelectObject(pPrinter->hDC, hOldFont); /* De-select the font */ 328 } 329 } 330 331 hOldFont = SelectObject(pPrinter->hDC, pData->hBodyFont); 332 ret = DoPrintBody(pData, PageCount, bSkipPage); 333 SelectObject(pPrinter->hDC, hOldFont); 334 if (!ret) 335 return FALSE; /* Canceled */ 336 337 /* The epilogue of a page */ 338 if (!bSkipPage) 339 { 340 if (pData->cyFooter > 0) 341 { 342 /* Draw the page footer */ 343 RECT rc = pData->printRect; 344 rc.top = rc.bottom - pData->cyFooter; 345 346 hOldFont = SelectObject(pPrinter->hDC, pData->hHeaderFont); 347 DrawHeaderOrFooter(pPrinter->hDC, &rc, Globals.szFooter, PageCount, &pData->stNow); 348 SelectObject(pPrinter->hDC, hOldFont); 349 } 350 351 if (EndPage(pPrinter->hDC) <= 0) 352 { 353 pData->status = STRING_PRINTFAILED; 354 return FALSE; 355 } 356 } 357 358 return TRUE; 359 } 360 361 #define BODY_FONT_SIZE 10 /* 10pt */ 362 #define HEADER_FONT_SIZE 9 /* 9pt */ 363 #define SPACING_HEIGHT 4 /* 4pt */ 364 #define PRINTING_MESSAGE (WM_USER + 100) 365 366 static BOOL DoCreatePrintFonts(LPPRINTDLG pPrinter, PPRINT_DATA pPrintData) 367 { 368 LOGFONT lfBody, lfHeader; 369 370 /* Create the main text font for printing */ 371 lfBody = Globals.lfFont; 372 lfBody.lfHeight = -Y_POINTS_TO_PIXELS(pPrinter->hDC, BODY_FONT_SIZE); 373 pPrintData->hBodyFont = CreateFontIndirect(&lfBody); 374 if (pPrintData->hBodyFont == NULL) 375 return FALSE; 376 377 /* Create the header/footer font */ 378 lfHeader = Globals.lfFont; 379 lfHeader.lfHeight = -Y_POINTS_TO_PIXELS(pPrinter->hDC, HEADER_FONT_SIZE); 380 lfHeader.lfWeight = FW_BOLD; 381 pPrintData->hHeaderFont = CreateFontIndirect(&lfHeader); 382 if (pPrintData->hHeaderFont == NULL) 383 return FALSE; 384 385 return TRUE; 386 } 387 388 static BOOL DoPrintDocument(PPRINT_DATA printData) 389 { 390 DOCINFO docInfo; 391 LPPRINTDLG pPrinter = &printData->printer; 392 DWORD CopyCount, PageCount; 393 TEXTMETRIC tmHeader; 394 BOOL ret = FALSE; 395 HFONT hOldFont; 396 397 GetLocalTime(&printData->stNow); 398 399 printData->printRect = GetPrintingRect(pPrinter->hDC, &Globals.lMargins); 400 401 if (!DoCreatePrintFonts(pPrinter, printData)) 402 { 403 printData->status = STRING_PRINTFAILED; 404 goto Quit; 405 } 406 407 if (pPrinter->Flags & PD_SELECTION) 408 printData->cchText = GetSelectionTextLength(Globals.hEdit); 409 else 410 printData->cchText = GetWindowTextLength(Globals.hEdit); 411 412 /* Allocate a buffer for the text */ 413 printData->pszText = HeapAlloc(GetProcessHeap(), 0, (printData->cchText + 1) * sizeof(TCHAR)); 414 if (!printData->pszText) 415 { 416 printData->status = STRING_PRINTFAILED; 417 goto Quit; 418 } 419 420 if (pPrinter->Flags & PD_SELECTION) 421 GetSelectionText(Globals.hEdit, printData->pszText, printData->cchText + 1); 422 else 423 GetWindowText(Globals.hEdit, printData->pszText, printData->cchText + 1); 424 425 /* Start a document */ 426 ZeroMemory(&docInfo, sizeof(docInfo)); 427 docInfo.cbSize = sizeof(DOCINFO); 428 docInfo.lpszDocName = Globals.szFileTitle; 429 if (StartDoc(pPrinter->hDC, &docInfo) <= 0) 430 { 431 printData->status = STRING_PRINTFAILED; 432 goto Quit; 433 } 434 435 /* Calculate the header and footer heights */ 436 hOldFont = SelectObject(pPrinter->hDC, printData->hHeaderFont); 437 GetTextMetrics(pPrinter->hDC, &tmHeader); 438 printData->cyHeader = printData->cyFooter = 2 * tmHeader.tmHeight; 439 printData->cySpacing = Y_POINTS_TO_PIXELS(pPrinter->hDC, SPACING_HEIGHT); 440 SelectObject(pPrinter->hDC, hOldFont); /* De-select the font */ 441 if (!Globals.szHeader[0]) 442 printData->cyHeader = printData->cySpacing = 0; 443 if (!Globals.szFooter[0]) 444 printData->cyFooter = 0; 445 446 /* The printing-copies loop */ 447 for (CopyCount = 1; CopyCount <= pPrinter->nCopies; ++CopyCount) 448 { 449 /* The printing-pages loop */ 450 for (PageCount = 1, printData->ich = 0; printData->ich < printData->cchText; ++PageCount) 451 { 452 printData->currentPage = PageCount; 453 PostMessage(printData->hwndDlg, PRINTING_MESSAGE, 0, 0); 454 455 if (!DoPrintPage(printData, PageCount)) 456 { 457 AbortDoc(pPrinter->hDC); /* Cancel printing */ 458 goto Quit; 459 } 460 } 461 } 462 463 if (EndDoc(pPrinter->hDC) <= 0) 464 { 465 printData->status = STRING_PRINTFAILED; 466 goto Quit; 467 } 468 469 ret = TRUE; 470 printData->status = STRING_PRINTCOMPLETE; 471 472 Quit: 473 DeleteObject(printData->hHeaderFont); 474 DeleteObject(printData->hBodyFont); 475 if (printData->pszText) 476 HeapFree(GetProcessHeap(), 0, printData->pszText); 477 if (printData->status == STRING_PRINTCANCELING) 478 printData->status = STRING_PRINTCANCELED; 479 PostMessage(printData->hwndDlg, PRINTING_MESSAGE, 0, 0); 480 return ret; 481 } 482 483 static DWORD WINAPI PrintThreadFunc(LPVOID arg) 484 { 485 PPRINT_DATA pData = arg; 486 pData->currentPage = 1; 487 pData->status = STRING_NOWPRINTING; 488 PostMessage(pData->hwndDlg, PRINTING_MESSAGE, 0, 0); 489 return DoPrintDocument(pData); 490 } 491 492 static INT_PTR CALLBACK 493 DIALOG_Printing_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 494 { 495 TCHAR szText[MAX_STRING_LEN]; 496 static TCHAR s_szPage[64]; 497 static PPRINT_DATA s_pData = NULL; 498 static HANDLE s_hThread = NULL; 499 500 switch (uMsg) 501 { 502 case WM_INITDIALOG: 503 s_pData = (PPRINT_DATA)lParam; 504 s_pData->hwndDlg = hwnd; 505 SetDlgItemText(hwnd, IDC_PRINTING_FILENAME, Globals.szFileTitle); 506 GetDlgItemText(hwnd, IDC_PRINTING_PAGE, s_szPage, _countof(s_szPage)); 507 SetDlgItemText(hwnd, IDC_PRINTING_PAGE, NULL); 508 509 s_hThread = CreateThread(NULL, 0, PrintThreadFunc, s_pData, 0, NULL); 510 if (!s_hThread) 511 { 512 s_pData->status = STRING_PRINTFAILED; 513 EndDialog(hwnd, IDABORT); 514 } 515 return TRUE; 516 517 case PRINTING_MESSAGE: 518 switch (s_pData->status) 519 { 520 case STRING_NOWPRINTING: 521 case STRING_PRINTCANCELING: 522 StringCchPrintf(szText, _countof(szText), s_szPage, s_pData->currentPage); 523 SetDlgItemText(hwnd, IDC_PRINTING_PAGE, szText); 524 525 LoadString(Globals.hInstance, s_pData->status, szText, _countof(szText)); 526 SetDlgItemText(hwnd, IDC_PRINTING_STATUS, szText); 527 break; 528 529 case STRING_PRINTCOMPLETE: 530 case STRING_PRINTCANCELED: 531 case STRING_PRINTFAILED: 532 LoadString(Globals.hInstance, s_pData->status, szText, _countof(szText)); 533 SetDlgItemText(hwnd, IDC_PRINTING_STATUS, szText); 534 535 if (s_pData->status == STRING_PRINTCOMPLETE) 536 EndDialog(hwnd, IDOK); 537 else if (s_pData->status == STRING_PRINTFAILED) 538 EndDialog(hwnd, IDABORT); 539 else 540 EndDialog(hwnd, IDCANCEL); 541 break; 542 } 543 break; 544 545 case WM_COMMAND: 546 if (LOWORD(wParam) == IDCANCEL && s_pData->status == STRING_NOWPRINTING) 547 { 548 EnableWindow(GetDlgItem(hwnd, IDCANCEL), FALSE); 549 s_pData->status = STRING_PRINTCANCELING; 550 PostMessage(hwnd, PRINTING_MESSAGE, 0, 0); 551 } 552 break; 553 554 case WM_DESTROY: 555 if (s_hThread) 556 CloseHandle(s_hThread); 557 DeleteDC(s_pData->printer.hDC); 558 s_pData = LocalFree(s_pData); 559 break; 560 } 561 562 return 0; 563 } 564 565 VOID DIALOG_FilePrint(VOID) 566 { 567 BOOL ret; 568 LPPRINTDLG printer; 569 PPRINT_DATA printData = LocalAlloc(LPTR, sizeof(PRINT_DATA)); 570 if (!printData) 571 { 572 ShowLastError(); 573 return; 574 } 575 576 printer = &printData->printer; 577 printer->lStructSize = sizeof(PRINTDLG); 578 printer->hwndOwner = Globals.hMainWnd; 579 printer->Flags = PD_RETURNDC | PD_SELECTION; 580 581 /* Disable the selection radio button if there is no text selected */ 582 if (!GetSelectionTextLength(Globals.hEdit)) 583 printer->Flags |= PD_NOSELECTION; 584 585 printer->nFromPage = 1; 586 printer->nToPage = MAXWORD; 587 printer->nMinPage = 1; 588 printer->nMaxPage = MAXWORD; 589 590 printer->hDevMode = Globals.hDevMode; 591 printer->hDevNames = Globals.hDevNames; 592 593 ret = PrintDlg(printer); 594 /* NOTE: Even if PrintDlg returns FALSE, hDevMode and hDevNames may have changed. */ 595 Globals.hDevMode = printer->hDevMode; 596 Globals.hDevNames = printer->hDevNames; 597 598 if (!ret) 599 { 600 LocalFree(printData); 601 return; /* The user canceled printing */ 602 } 603 assert(printer->hDC != NULL); 604 605 /* Ensure that each logical unit maps to one pixel */ 606 SetMapMode(printer->hDC, MM_TEXT); 607 608 if (DialogBoxParam(Globals.hInstance, 609 MAKEINTRESOURCE(DIALOG_PRINTING), 610 Globals.hMainWnd, 611 DIALOG_Printing_DialogProc, 612 (LPARAM)printer) == IDABORT) 613 { 614 AlertPrintError(); 615 } 616 } 617 618 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 619 * DIALOG_PAGESETUP_Hook 620 */ 621 static UINT_PTR CALLBACK DIALOG_PAGESETUP_Hook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 622 { 623 switch (uMsg) 624 { 625 case WM_INITDIALOG: 626 /* fetch last user input prior to display dialog */ 627 SetDlgItemText(hDlg, 0x141, Globals.szHeader); 628 SetDlgItemText(hDlg, 0x143, Globals.szFooter); 629 break; 630 631 case WM_COMMAND: 632 { 633 if (HIWORD(wParam) == BN_CLICKED) 634 { 635 switch (LOWORD(wParam)) 636 { 637 case IDOK: 638 /* save user input and close dialog */ 639 GetDlgItemText(hDlg, 0x141, Globals.szHeader, _countof(Globals.szHeader)); 640 GetDlgItemText(hDlg, 0x143, Globals.szFooter, _countof(Globals.szFooter)); 641 return FALSE; 642 643 case IDCANCEL: 644 /* discard user input and close dialog */ 645 return FALSE; 646 647 case IDHELP: 648 { 649 /* FIXME: Bring this to work */ 650 static const TCHAR sorry[] = _T("Sorry, no help available"); 651 static const TCHAR help[] = _T("Help"); 652 MessageBox(Globals.hMainWnd, sorry, help, MB_ICONEXCLAMATION); 653 return TRUE; 654 } 655 656 default: 657 break; 658 } 659 } 660 break; 661 } 662 } 663 664 return FALSE; 665 } 666 667 /*********************************************************************** 668 * DIALOG_FilePageSetup 669 */ 670 VOID DIALOG_FilePageSetup(VOID) 671 { 672 PAGESETUPDLG page; 673 674 ZeroMemory(&page, sizeof(page)); 675 page.lStructSize = sizeof(page); 676 page.hwndOwner = Globals.hMainWnd; 677 page.Flags = PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPHOOK | PSD_MARGINS; 678 page.hInstance = Globals.hInstance; 679 page.rtMargin = Globals.lMargins; 680 page.hDevMode = Globals.hDevMode; 681 page.hDevNames = Globals.hDevNames; 682 page.lpPageSetupTemplateName = MAKEINTRESOURCE(DIALOG_PAGESETUP); 683 page.lpfnPageSetupHook = DIALOG_PAGESETUP_Hook; 684 685 PageSetupDlg(&page); 686 687 /* NOTE: Even if PageSetupDlg returns FALSE, the following members may have changed */ 688 Globals.hDevMode = page.hDevMode; 689 Globals.hDevNames = page.hDevNames; 690 Globals.lMargins = page.rtMargin; 691 } 692