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
AlertPrintError(VOID)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
GetPrintingRect(IN HDC hdc,IN LPCRECT pMargins)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
GetSelectionTextLength(HWND hWnd)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
GetSelectionText(HWND hWnd,LPTSTR lpString,INT nMaxCount)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/help-in-notepad-4d68c388-2ff2-0e7f-b706-35fb2ab88a8c
122 */
123 static VOID
DrawHeaderOrFooter(HDC hDC,LPRECT pRect,LPCTSTR pszFormat,INT nPageNo,const SYSTEMTIME * pstNow)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
DoPrintBody(PPRINT_DATA pData,DWORD PageCount,BOOL bSkipPage)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
DoPrintPage(PPRINT_DATA pData,DWORD PageCount)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
DoCreatePrintFonts(LPPRINTDLG pPrinter,PPRINT_DATA pPrintData)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
DoPrintDocument(PPRINT_DATA printData)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
PrintThreadFunc(LPVOID arg)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
DIALOG_Printing_DialogProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)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
DIALOG_FilePrint(VOID)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 */
DIALOG_PAGESETUP_Hook(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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 */
DIALOG_FilePageSetup(VOID)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