https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3b0791547f8857110352e1837e8cfbc2c7a93a46

commit 3b0791547f8857110352e1837e8cfbc2c7a93a46
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sun Mar 12 07:51:53 2023 +0900
Commit:     Katayama Hirofumi MZ <[email protected]>
CommitDate: Sun Mar 12 07:51:53 2023 +0900

    [NOTEPAD] Move the printing code to the newly added printing.c
    
    CORE-18837
---
 base/applications/notepad/CMakeLists.txt |   1 +
 base/applications/notepad/dialog.c       | 677 ------------------------------
 base/applications/notepad/printing.c     | 688 +++++++++++++++++++++++++++++++
 3 files changed, 689 insertions(+), 677 deletions(-)

diff --git a/base/applications/notepad/CMakeLists.txt 
b/base/applications/notepad/CMakeLists.txt
index aa1aae6034a..f9a534a70e5 100644
--- a/base/applications/notepad/CMakeLists.txt
+++ b/base/applications/notepad/CMakeLists.txt
@@ -2,6 +2,7 @@
 list(APPEND SOURCE
     dialog.c
     main.c
+    printing.c
     settings.c
     text.c
     notepad.h)
diff --git a/base/applications/notepad/dialog.c 
b/base/applications/notepad/dialog.c
index 3bd835a5011..5c78dadc39a 100644
--- a/base/applications/notepad/dialog.c
+++ b/base/applications/notepad/dialog.c
@@ -55,8 +55,6 @@ static UINT EncToStrId[] = {
     STRING_UTF8_BOM
 };
 
-static UINT_PTR CALLBACK DIALOG_PAGESETUP_Hook(HWND hDlg, UINT msg, WPARAM 
wParam, LPARAM lParam);
-
 VOID ShowLastError(VOID)
 {
     DWORD error = GetLastError();
@@ -209,17 +207,6 @@ static int AlertFileNotSaved(LPCTSTR szFileName)
                                MB_ICONQUESTION | MB_YESNOCANCEL);
 }
 
-static void AlertPrintError(void)
-{
-    TCHAR szUntitled[MAX_STRING_LEN];
-
-    LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, 
ARRAY_SIZE(szUntitled));
-
-    DIALOG_StringMsgBox(Globals.hMainWnd, STRING_PRINTERROR,
-                        Globals.szFileName[0] ? Globals.szFileName : 
szUntitled,
-                        MB_ICONEXCLAMATION | MB_OK);
-}
-
 /**
  * Returns:
  *   TRUE  - if file exists
@@ -240,76 +227,6 @@ BOOL HasFileExtension(LPCTSTR szFilename)
     return _tcsrchr(szFilename, _T('.')) != NULL;
 }
 
-int GetSelectionTextLength(HWND hWnd)
-{
-    DWORD dwStart = 0, dwEnd = 0;
-    SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
-    return dwEnd - dwStart;
-}
-
-int GetSelectionText(HWND hWnd, LPTSTR lpString, int nMaxCount)
-{
-    DWORD dwStart = 0, dwEnd = 0;
-    INT cchText = GetWindowTextLength(hWnd);
-    LPTSTR pszText;
-    HLOCAL hLocal;
-    HRESULT hr;
-
-    SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
-    if (!lpString || dwStart == dwEnd || cchText == 0)
-        return 0;
-
-    hLocal = (HLOCAL)SendMessage(hWnd, EM_GETHANDLE, 0, 0);
-    pszText = (LPTSTR)LocalLock(hLocal);
-    if (!pszText)
-        return 0;
-
-    hr = StringCchCopyN(lpString, nMaxCount, pszText + dwStart, dwEnd - 
dwStart);
-    LocalUnlock(hLocal);
-
-    switch (hr)
-    {
-        case S_OK:
-            return dwEnd - dwStart;
-
-        case STRSAFE_E_INSUFFICIENT_BUFFER:
-            return nMaxCount - 1;
-
-        default:
-            return 0;
-    }
-}
-
-static RECT
-GetPrintingRect(IN HDC hdc, IN LPCRECT pMargins)
-{
-    INT iLogPixelsX = GetDeviceCaps(hdc, LOGPIXELSX);
-    INT iLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
-    INT iHorzRes = GetDeviceCaps(hdc, HORZRES); /* in pixels */
-    INT iVertRes = GetDeviceCaps(hdc, VERTRES); /* in pixels */
-    RECT rcPrintRect, rcPhysical;
-
-#define CONVERT_X(x) MulDiv((x), iLogPixelsX, 2540) /* 100th millimeters to 
pixels */
-#define CONVERT_Y(y) MulDiv((y), iLogPixelsY, 2540) /* 100th millimeters to 
pixels */
-    SetRect(&rcPrintRect,
-            CONVERT_X(pMargins->left), CONVERT_Y(pMargins->top),
-            iHorzRes - CONVERT_X(pMargins->right),
-            iVertRes - CONVERT_Y(pMargins->bottom));
-
-    rcPhysical.left = GetDeviceCaps(hdc, PHYSICALOFFSETX);
-    rcPhysical.right = rcPhysical.left + GetDeviceCaps(hdc, PHYSICALWIDTH);
-    rcPhysical.top = GetDeviceCaps(hdc, PHYSICALOFFSETY);
-    rcPhysical.bottom = rcPhysical.top + GetDeviceCaps(hdc, PHYSICALHEIGHT);
-
-    /* Adjust the margin */
-    rcPrintRect.left = max(rcPrintRect.left, rcPhysical.left);
-    rcPrintRect.top = max(rcPrintRect.top, rcPhysical.top);
-    rcPrintRect.right = min(rcPrintRect.right, rcPhysical.right);
-    rcPrintRect.bottom = min(rcPrintRect.bottom, rcPhysical.bottom);
-
-    return rcPrintRect;
-}
-
 static BOOL DoSaveFile(VOID)
 {
     BOOL bRet = FALSE;
@@ -619,527 +536,6 @@ BOOL DIALOG_FileSaveAs(VOID)
     }
 }
 
-/* Convert the points into pixels */
-#define X_POINTS_TO_PIXELS(hDC, points) MulDiv((points), GetDeviceCaps((hDC), 
LOGPIXELSX), 72)
-#define Y_POINTS_TO_PIXELS(hDC, points) MulDiv((points), GetDeviceCaps((hDC), 
LOGPIXELSY), 72)
-
-/*
- * See also:
- * 
https://support.microsoft.com/en-us/windows/changing-header-and-footer-commands-in-notepad-c1b0e27b-497d-c478-c4c1-0da491cac148
- */
-static VOID
-DrawHeaderOrFooter(HDC hDC, LPRECT pRect, LPCTSTR pszFormat, INT nPageNo, 
const SYSTEMTIME *pstNow)
-{
-    TCHAR szText[256], szField[128];
-    const TCHAR *pchFormat;
-    UINT uAlign = DT_CENTER, uFlags = DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX;
-    HGDIOBJ hOldPen, hOldBrush;
-
-    /* Draw a rectangle */
-    hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
-    hOldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH));
-    Rectangle(hDC, pRect->left, pRect->top, pRect->right, pRect->bottom);
-    SelectObject(hDC, hOldBrush);
-    SelectObject(hDC, hOldPen);
-
-    InflateRect(pRect, -X_POINTS_TO_PIXELS(hDC, 3), 0); /* Shrink 3pt */
-
-    szText[0] = 0;
-
-    for (pchFormat = pszFormat; *pchFormat; ++pchFormat)
-    {
-        if (*pchFormat != _T('&'))
-        {
-            StringCchCatN(szText, ARRAY_SIZE(szText), pchFormat, 1);
-            continue;
-        }
-
-        ++pchFormat;
-        if (*pchFormat == 0)
-            break;
-
-        switch (_totupper(*pchFormat)) /* Make it uppercase */
-        {
-            case _T('&'): /* Found double ampersand */
-                StringCchCat(szText, ARRAY_SIZE(szText), TEXT("&"));
-                break;
-
-            case _T('L'): /* Left */
-                DrawText(hDC, szText, -1, pRect, uAlign | uFlags);
-                szText[0] = 0;
-                uAlign = DT_LEFT;
-                break;
-
-            case _T('C'): /* Center */
-                DrawText(hDC, szText, -1, pRect, uAlign | uFlags);
-                szText[0] = 0;
-                uAlign = DT_CENTER;
-                break;
-
-            case _T('R'): /* Right */
-                DrawText(hDC, szText, -1, pRect, uAlign | uFlags);
-                szText[0] = 0;
-                uAlign = DT_RIGHT;
-                break;
-
-            case _T('D'): /* Date */
-                GetDateFormat(LOCALE_USER_DEFAULT, 0, pstNow, NULL,
-                              szField, (INT)ARRAY_SIZE(szField));
-                StringCchCat(szText, ARRAY_SIZE(szText), szField);
-                break;
-
-            case _T('T'): /* Time */
-                GetTimeFormat(LOCALE_USER_DEFAULT, 0, pstNow, NULL,
-                              szField, (INT)ARRAY_SIZE(szField));
-                StringCchCat(szText, ARRAY_SIZE(szText), szField);
-                break;
-
-            case _T('F'): /* Filename */
-                StringCchCat(szText, ARRAY_SIZE(szText), Globals.szFileTitle);
-                break;
-
-            case _T('P'): /* Page number */
-                StringCchPrintf(szField, ARRAY_SIZE(szField), TEXT("%u"), 
nPageNo);
-                StringCchCat(szText, ARRAY_SIZE(szText), szField);
-                break;
-
-            default: /* Otherwise */
-                szField[0] = _T('&');
-                szField[1] = *pchFormat;
-                szField[2] = 0;
-                StringCchCat(szText, ARRAY_SIZE(szText), szField);
-                break;
-        }
-    }
-
-    DrawText(hDC, szText, -1, pRect, uAlign | uFlags);
-}
-
-typedef struct
-{
-    PRINTDLG printer;
-    HWND hwndDlg;
-    INT status;
-    INT currentPage;
-    RECT printRect;
-    SYSTEMTIME stNow;
-    HFONT hHeaderFont;
-    HFONT hBodyFont;
-    LPTSTR pszText;
-    DWORD ich;
-    DWORD cchText;
-    INT cyHeader;
-    INT cySpacing;
-    INT cyFooter;
-} PRINT_DATA, *PPRINT_DATA;
-
-static BOOL DoPrintBody(PPRINT_DATA pData, DWORD PageCount, BOOL bSkipPage)
-{
-    LPPRINTDLG pPrinter = &pData->printer;
-    RECT printRect = pData->printRect;
-    INT xLeft = printRect.left, yTop = printRect.top + pData->cyHeader + 
pData->cySpacing;
-    INT xStart, tabWidth;
-    DWORD ichStart;
-    SIZE charMetrics;
-    TEXTMETRIC tmText;
-
-    /* Calculate a tab width */
-#define TAB_STOP 8
-    GetTextMetrics(pPrinter->hDC, &tmText);
-    tabWidth = TAB_STOP * tmText.tmAveCharWidth;
-
-#define DO_FLUSH() do { \
-    if (ichStart < pData->ich && !bSkipPage) { \
-        TextOut(pPrinter->hDC, xStart, yTop, &pData->pszText[ichStart], 
pData->ich - ichStart); \
-    } \
-    ichStart = pData->ich; \
-    xStart = xLeft; \
-    if (pData->status == STRING_PRINTCANCELING) return FALSE; \
-} while (0)
-
-    /* The drawing-body loop */
-    for (ichStart = pData->ich, xStart = xLeft; pData->ich < pData->cchText; )
-    {
-        TCHAR ch = pData->pszText[pData->ich];
-
-        if (ch == _T('\r'))
-        {
-            DO_FLUSH();
-
-            pData->ich++; /* Next char */
-            ichStart = pData->ich;
-            continue;
-        }
-
-        if (ch == _T('\n'))
-        {
-            DO_FLUSH();
-
-            /* Next line */
-            yTop += tmText.tmHeight;
-            xLeft = xStart = printRect.left;
-        }
-        else
-        {
-            if (ch == _T('\t'))
-            {
-                INT nStepWidth = tabWidth - ((xLeft - printRect.left) % 
tabWidth);
-
-                DO_FLUSH();
-
-                /* Go to the next tab stop */
-                xLeft += nStepWidth;
-                xStart = xLeft;
-            }
-            else /* Normal char */
-            {
-                GetTextExtentPoint32(pPrinter->hDC, &ch, 1, &charMetrics);
-                xLeft += charMetrics.cx;
-            }
-
-            /* Insert a line break if the next position reached the right edge 
*/
-            if (xLeft + charMetrics.cx >= printRect.right)
-            {
-                if (ch != _T('\t'))
-                    DO_FLUSH();
-
-                /* Next line */
-                yTop += tmText.tmHeight;
-                xLeft = xStart = printRect.left;
-            }
-        }
-
-        pData->ich++; /* Next char */
-        if (ch == _T('\t') || ch == _T('\n'))
-            ichStart = pData->ich;
-
-        if (yTop + tmText.tmHeight >= printRect.bottom - pData->cyFooter)
-            break; /* The next line reached the body bottom */
-    }
-
-    DO_FLUSH();
-    return TRUE;
-}
-
-static BOOL DoPrintPage(PPRINT_DATA pData, DWORD PageCount)
-{
-    LPPRINTDLG pPrinter = &pData->printer;
-    BOOL bSkipPage, ret;
-    HFONT hOldFont;
-
-    /* Should we skip this page? */
-    bSkipPage = !(pPrinter->Flags & PD_SELECTION) &&
-                (pPrinter->Flags & PD_PAGENUMS) &&
-                !(pPrinter->nFromPage <= PageCount && PageCount <= 
pPrinter->nToPage);
-
-    /* The prologue of a page */
-    if (!bSkipPage)
-    {
-        if (StartPage(pPrinter->hDC) <= 0)
-        {
-            pData->status = STRING_PRINTFAILED;
-            return FALSE;
-        }
-
-        if (pData->cyHeader > 0)
-        {
-            /* Draw the page header */
-            RECT rc = pData->printRect;
-            rc.bottom = rc.top + pData->cyHeader;
-
-            hOldFont = SelectObject(pPrinter->hDC, pData->hHeaderFont);
-            DrawHeaderOrFooter(pPrinter->hDC, &rc, Globals.szHeader, 
PageCount, &pData->stNow);
-            SelectObject(pPrinter->hDC, hOldFont); /* De-select the font */
-        }
-    }
-
-    hOldFont = SelectObject(pPrinter->hDC, pData->hBodyFont);
-    ret = DoPrintBody(pData, PageCount, bSkipPage);
-    SelectObject(pPrinter->hDC, hOldFont);
-    if (!ret)
-        return FALSE; /* Canceled */
-
-    /* The epilogue of a page */
-    if (!bSkipPage)
-    {
-        if (pData->cyFooter > 0)
-        {
-            /* Draw the page footer */
-            RECT rc = pData->printRect;
-            rc.top = rc.bottom - pData->cyFooter;
-
-            hOldFont = SelectObject(pPrinter->hDC, pData->hHeaderFont);
-            DrawHeaderOrFooter(pPrinter->hDC, &rc, Globals.szFooter, 
PageCount, &pData->stNow);
-            SelectObject(pPrinter->hDC, hOldFont);
-        }
-
-        if (EndPage(pPrinter->hDC) <= 0)
-        {
-            pData->status = STRING_PRINTFAILED;
-            return FALSE;
-        }
-    }
-
-    return TRUE;
-}
-
-#define BODY_FONT_SIZE      10 /* 10pt */
-#define HEADER_FONT_SIZE    9  /* 9pt */
-#define SPACING_HEIGHT      4  /* 4pt */
-#define PRINTING_MESSAGE (WM_USER + 100)
-
-static BOOL DoCreatePrintFonts(LPPRINTDLG pPrinter, PPRINT_DATA pPrintData)
-{
-    LOGFONT lfBody, lfHeader;
-
-    /* Create the main text font for printing */
-    lfBody = Globals.lfFont;
-    lfBody.lfHeight = -Y_POINTS_TO_PIXELS(pPrinter->hDC, BODY_FONT_SIZE);
-    pPrintData->hBodyFont = CreateFontIndirect(&lfBody);
-    if (pPrintData->hBodyFont == NULL)
-        return FALSE;
-
-    /* Create the header/footer font */
-    lfHeader = Globals.lfFont;
-    lfHeader.lfHeight = -Y_POINTS_TO_PIXELS(pPrinter->hDC, HEADER_FONT_SIZE);
-    lfHeader.lfWeight = FW_BOLD;
-    pPrintData->hHeaderFont = CreateFontIndirect(&lfHeader);
-    if (pPrintData->hHeaderFont == NULL)
-        return FALSE;
-
-    return TRUE;
-}
-
-static BOOL DoPrintDocument(PPRINT_DATA printData)
-{
-    DOCINFO docInfo;
-    LPPRINTDLG pPrinter = &printData->printer;
-    DWORD CopyCount, PageCount;
-    TEXTMETRIC tmHeader;
-    BOOL ret = FALSE;
-    HFONT hOldFont;
-
-    GetLocalTime(&printData->stNow);
-
-    printData->printRect = GetPrintingRect(pPrinter->hDC, &Globals.lMargins);
-
-    if (!DoCreatePrintFonts(pPrinter, printData))
-    {
-        printData->status = STRING_PRINTFAILED;
-        goto Quit;
-    }
-
-    if (pPrinter->Flags & PD_SELECTION)
-        printData->cchText = GetSelectionTextLength(Globals.hEdit);
-    else
-        printData->cchText = GetWindowTextLength(Globals.hEdit);
-
-    /* Allocate a buffer for the text */
-    printData->pszText = HeapAlloc(GetProcessHeap(), 0, (printData->cchText + 
1) * sizeof(TCHAR));
-    if (!printData->pszText)
-    {
-        printData->status = STRING_PRINTFAILED;
-        goto Quit;
-    }
-
-    if (pPrinter->Flags & PD_SELECTION)
-        GetSelectionText(Globals.hEdit, printData->pszText, printData->cchText 
+ 1);
-    else
-        GetWindowText(Globals.hEdit, printData->pszText, printData->cchText + 
1);
-
-    /* Start a document */
-    ZeroMemory(&docInfo, sizeof(docInfo));
-    docInfo.cbSize = sizeof(DOCINFO);
-    docInfo.lpszDocName = Globals.szFileTitle;
-    if (StartDoc(pPrinter->hDC, &docInfo) <= 0)
-    {
-        printData->status = STRING_PRINTFAILED;
-        goto Quit;
-    }
-
-    /* Calculate the header and footer heights */
-    hOldFont = SelectObject(pPrinter->hDC, printData->hHeaderFont);
-    GetTextMetrics(pPrinter->hDC, &tmHeader);
-    printData->cyHeader = printData->cyFooter = 2 * tmHeader.tmHeight;
-    printData->cySpacing = Y_POINTS_TO_PIXELS(pPrinter->hDC, SPACING_HEIGHT);
-    SelectObject(pPrinter->hDC, hOldFont); /* De-select the font */
-    if (!Globals.szHeader[0])
-        printData->cyHeader = printData->cySpacing = 0;
-    if (!Globals.szFooter[0])
-        printData->cyFooter = 0;
-
-    /* The printing-copies loop */
-    for (CopyCount = 1; CopyCount <= pPrinter->nCopies; ++CopyCount)
-    {
-        /* The printing-pages loop */
-        for (PageCount = 1, printData->ich = 0; printData->ich < 
printData->cchText; ++PageCount)
-        {
-            printData->currentPage = PageCount;
-            PostMessage(printData->hwndDlg, PRINTING_MESSAGE, 0, 0);
-
-            if (!DoPrintPage(printData, PageCount))
-            {
-                AbortDoc(pPrinter->hDC); /* Cancel printing */
-                goto Quit;
-            }
-        }
-    }
-
-    if (EndDoc(pPrinter->hDC) <= 0)
-    {
-        printData->status = STRING_PRINTFAILED;
-        goto Quit;
-    }
-
-    ret = TRUE;
-    printData->status = STRING_PRINTCOMPLETE;
-
-Quit:
-    DeleteObject(printData->hHeaderFont);
-    DeleteObject(printData->hBodyFont);
-    if (printData->pszText)
-        HeapFree(GetProcessHeap(), 0, printData->pszText);
-    if (printData->status == STRING_PRINTCANCELING)
-        printData->status = STRING_PRINTCANCELED;
-    PostMessage(printData->hwndDlg, PRINTING_MESSAGE, 0, 0);
-    return ret;
-}
-
-static DWORD WINAPI PrintThreadFunc(LPVOID arg)
-{
-    PPRINT_DATA pData = arg;
-    pData->currentPage = 1;
-    pData->status = STRING_NOWPRINTING;
-    PostMessage(pData->hwndDlg, PRINTING_MESSAGE, 0, 0);
-    return DoPrintDocument(pData);
-}
-
-static INT_PTR CALLBACK
-DIALOG_Printing_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-    TCHAR szText[MAX_STRING_LEN];
-    static TCHAR s_szPage[64];
-    static PPRINT_DATA s_pData = NULL;
-    static HANDLE s_hThread = NULL;
-
-    switch (uMsg)
-    {
-        case WM_INITDIALOG:
-            s_pData = (PPRINT_DATA)lParam;
-            s_pData->hwndDlg = hwnd;
-            SetDlgItemText(hwnd, IDC_PRINTING_FILENAME, Globals.szFileTitle);
-            GetDlgItemText(hwnd, IDC_PRINTING_PAGE, s_szPage, 
ARRAY_SIZE(s_szPage));
-            SetDlgItemText(hwnd, IDC_PRINTING_PAGE, NULL);
-
-            s_hThread = CreateThread(NULL, 0, PrintThreadFunc, s_pData, 0, 
NULL);
-            if (!s_hThread)
-            {
-                s_pData->status = STRING_PRINTFAILED;
-                EndDialog(hwnd, IDABORT);
-            }
-            return TRUE;
-
-        case PRINTING_MESSAGE:
-            switch (s_pData->status)
-            {
-                case STRING_NOWPRINTING:
-                case STRING_PRINTCANCELING:
-                    StringCchPrintf(szText, ARRAY_SIZE(szText), s_szPage, 
s_pData->currentPage);
-                    SetDlgItemText(hwnd, IDC_PRINTING_PAGE, szText);
-
-                    LoadString(Globals.hInstance, s_pData->status, szText, 
ARRAY_SIZE(szText));
-                    SetDlgItemText(hwnd, IDC_PRINTING_STATUS, szText);
-                    break;
-
-                case STRING_PRINTCOMPLETE:
-                case STRING_PRINTCANCELED:
-                case STRING_PRINTFAILED:
-                    LoadString(Globals.hInstance, s_pData->status, szText, 
ARRAY_SIZE(szText));
-                    SetDlgItemText(hwnd, IDC_PRINTING_STATUS, szText);
-
-                    if (s_pData->status == STRING_PRINTCOMPLETE)
-                        EndDialog(hwnd, IDOK);
-                    else if (s_pData->status == STRING_PRINTFAILED)
-                        EndDialog(hwnd, IDABORT);
-                    else
-                        EndDialog(hwnd, IDCANCEL);
-                    break;
-            }
-            break;
-
-        case WM_COMMAND:
-            if (LOWORD(wParam) == IDCANCEL && s_pData->status == 
STRING_NOWPRINTING)
-            {
-                EnableWindow(GetDlgItem(hwnd, IDCANCEL), FALSE);
-                s_pData->status = STRING_PRINTCANCELING;
-                PostMessage(hwnd, PRINTING_MESSAGE, 0, 0);
-            }
-            break;
-
-        case WM_DESTROY:
-            if (s_hThread)
-                CloseHandle(s_hThread);
-            DeleteDC(s_pData->printer.hDC);
-            s_pData = LocalFree(s_pData);
-            break;
-    }
-
-    return 0;
-}
-
-VOID DIALOG_FilePrint(VOID)
-{
-    BOOL ret;
-    LPPRINTDLG printer;
-    PPRINT_DATA printData = LocalAlloc(LPTR, sizeof(PRINT_DATA));
-    if (!printData)
-    {
-        ShowLastError();
-        return;
-    }
-
-    printer = &printData->printer;
-    printer->lStructSize = sizeof(PRINTDLG);
-    printer->hwndOwner = Globals.hMainWnd;
-    printer->Flags = PD_RETURNDC | PD_SELECTION;
-
-    /* Disable the selection radio button if there is no text selected */
-    if (!GetSelectionTextLength(Globals.hEdit))
-        printer->Flags |= PD_NOSELECTION;
-
-    printer->nFromPage = 1;
-    printer->nToPage = MAXWORD;
-    printer->nMinPage = 1;
-    printer->nMaxPage = MAXWORD;
-
-    printer->hDevMode = Globals.hDevMode;
-    printer->hDevNames = Globals.hDevNames;
-
-    ret = PrintDlg(printer);
-    /* NOTE: Even if PrintDlg returns FALSE, hDevMode and hDevNames may have 
changed. */
-    Globals.hDevMode = printer->hDevMode;
-    Globals.hDevNames = printer->hDevNames;
-
-    if (!ret)
-    {
-        LocalFree(printData);
-        return; /* The user canceled printing */
-    }
-    assert(printer->hDC != NULL);
-
-    /* Ensure that each logical unit maps to one pixel */
-    SetMapMode(printer->hDC, MM_TEXT);
-
-    if (DialogBoxParam(Globals.hInstance,
-                       MAKEINTRESOURCE(DIALOG_PRINTING),
-                       Globals.hMainWnd,
-                       DIALOG_Printing_DialogProc,
-                       (LPARAM)printer) == IDABORT)
-    {
-        AlertPrintError();
-    }
-}
-
 VOID DIALOG_FileExit(VOID)
 {
     PostMessage(Globals.hMainWnd, WM_CLOSE, 0, 0);
@@ -1525,76 +921,3 @@ VOID DIALOG_HelpAboutNotepad(VOID)
     ShellAbout(Globals.hMainWnd, szNotepad, szNotepadAuthors, notepadIcon);
     DestroyIcon(notepadIcon);
 }
-
-/***********************************************************************
- *           DIALOG_FilePageSetup
- */
-VOID DIALOG_FilePageSetup(void)
-{
-    PAGESETUPDLG page;
-
-    ZeroMemory(&page, sizeof(page));
-    page.lStructSize = sizeof(page);
-    page.hwndOwner = Globals.hMainWnd;
-    page.Flags = PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPHOOK | 
PSD_MARGINS;
-    page.hInstance = Globals.hInstance;
-    page.rtMargin = Globals.lMargins;
-    page.hDevMode = Globals.hDevMode;
-    page.hDevNames = Globals.hDevNames;
-    page.lpPageSetupTemplateName = MAKEINTRESOURCE(DIALOG_PAGESETUP);
-    page.lpfnPageSetupHook = DIALOG_PAGESETUP_Hook;
-
-    PageSetupDlg(&page);
-
-    /* NOTE: Even if PageSetupDlg returns FALSE, the following members may 
have changed */
-    Globals.hDevMode = page.hDevMode;
-    Globals.hDevNames = page.hDevNames;
-    Globals.lMargins = page.rtMargin;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *           DIALOG_PAGESETUP_Hook
- */
-static UINT_PTR CALLBACK DIALOG_PAGESETUP_Hook(HWND hDlg, UINT msg, WPARAM 
wParam, LPARAM lParam)
-{
-    switch (msg)
-    {
-    case WM_COMMAND:
-        if (HIWORD(wParam) == BN_CLICKED)
-        {
-            switch (LOWORD(wParam))
-            {
-            case IDOK:
-                /* save user input and close dialog */
-                GetDlgItemText(hDlg, 0x141, Globals.szHeader, 
ARRAY_SIZE(Globals.szHeader));
-                GetDlgItemText(hDlg, 0x143, Globals.szFooter, 
ARRAY_SIZE(Globals.szFooter));
-                return FALSE;
-
-            case IDCANCEL:
-                /* discard user input and close dialog */
-                return FALSE;
-
-            case IDHELP:
-                {
-                    /* FIXME: Bring this to work */
-                    static const TCHAR sorry[] = _T("Sorry, no help 
available");
-                    static const TCHAR help[] = _T("Help");
-                    MessageBox(Globals.hMainWnd, sorry, help, 
MB_ICONEXCLAMATION);
-                    return TRUE;
-                }
-
-            default:
-                break;
-            }
-        }
-        break;
-
-    case WM_INITDIALOG:
-        /* fetch last user input prior to display dialog */
-        SetDlgItemText(hDlg, 0x141, Globals.szHeader);
-        SetDlgItemText(hDlg, 0x143, Globals.szFooter);
-        break;
-    }
-
-    return FALSE;
-}
diff --git a/base/applications/notepad/printing.c 
b/base/applications/notepad/printing.c
new file mode 100644
index 00000000000..7040ec3498f
--- /dev/null
+++ b/base/applications/notepad/printing.c
@@ -0,0 +1,688 @@
+/*
+ * PROJECT:    ReactOS Notepad
+ * LICENSE:    LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:    Providing a Windows-compatible simple text editor for ReactOS
+ * COPYRIGHT:  Copyright 2020-2023 Katayama Hirofumi MZ 
<[email protected]>
+ */
+
+#include "notepad.h"
+
+#include <strsafe.h>
+#include <assert.h>
+
+static VOID AlertPrintError(VOID)
+{
+    TCHAR szUntitled[MAX_STRING_LEN];
+
+    LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, 
ARRAY_SIZE(szUntitled));
+
+    DIALOG_StringMsgBox(Globals.hMainWnd, STRING_PRINTERROR,
+                        Globals.szFileName[0] ? Globals.szFileName : 
szUntitled,
+                        MB_ICONEXCLAMATION | MB_OK);
+}
+
+static RECT
+GetPrintingRect(IN HDC hdc, IN LPCRECT pMargins)
+{
+    INT iLogPixelsX = GetDeviceCaps(hdc, LOGPIXELSX);
+    INT iLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
+    INT iHorzRes = GetDeviceCaps(hdc, HORZRES); /* in pixels */
+    INT iVertRes = GetDeviceCaps(hdc, VERTRES); /* in pixels */
+    RECT rcPrintRect, rcPhysical;
+
+#define CONVERT_X(x) MulDiv((x), iLogPixelsX, 2540) /* 100th millimeters to 
pixels */
+#define CONVERT_Y(y) MulDiv((y), iLogPixelsY, 2540) /* 100th millimeters to 
pixels */
+    SetRect(&rcPrintRect,
+            CONVERT_X(pMargins->left), CONVERT_Y(pMargins->top),
+            iHorzRes - CONVERT_X(pMargins->right),
+            iVertRes - CONVERT_Y(pMargins->bottom));
+
+    rcPhysical.left = GetDeviceCaps(hdc, PHYSICALOFFSETX);
+    rcPhysical.right = rcPhysical.left + GetDeviceCaps(hdc, PHYSICALWIDTH);
+    rcPhysical.top = GetDeviceCaps(hdc, PHYSICALOFFSETY);
+    rcPhysical.bottom = rcPhysical.top + GetDeviceCaps(hdc, PHYSICALHEIGHT);
+
+    /* Adjust the margin */
+    rcPrintRect.left = max(rcPrintRect.left, rcPhysical.left);
+    rcPrintRect.top = max(rcPrintRect.top, rcPhysical.top);
+    rcPrintRect.right = min(rcPrintRect.right, rcPhysical.right);
+    rcPrintRect.bottom = min(rcPrintRect.bottom, rcPhysical.bottom);
+
+    return rcPrintRect;
+}
+
+static INT GetSelectionTextLength(HWND hWnd)
+{
+    DWORD dwStart = 0, dwEnd = 0;
+    SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
+    return dwEnd - dwStart;
+}
+
+static INT GetSelectionText(HWND hWnd, LPTSTR lpString, INT nMaxCount)
+{
+    DWORD dwStart = 0, dwEnd = 0;
+    INT cchText = GetWindowTextLength(hWnd);
+    LPTSTR pszText;
+    HLOCAL hLocal;
+    HRESULT hr;
+
+    SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
+    if (!lpString || dwStart == dwEnd || cchText == 0)
+        return 0;
+
+    hLocal = (HLOCAL)SendMessage(hWnd, EM_GETHANDLE, 0, 0);
+    pszText = (LPTSTR)LocalLock(hLocal);
+    if (!pszText)
+        return 0;
+
+    hr = StringCchCopyN(lpString, nMaxCount, pszText + dwStart, dwEnd - 
dwStart);
+    LocalUnlock(hLocal);
+
+    switch (hr)
+    {
+        case S_OK:
+            return dwEnd - dwStart;
+
+        case STRSAFE_E_INSUFFICIENT_BUFFER:
+            return nMaxCount - 1;
+
+        default:
+            return 0;
+    }
+}
+
+typedef struct
+{
+    PRINTDLG printer;
+    HWND hwndDlg;
+    INT status;
+    INT currentPage;
+    RECT printRect;
+    SYSTEMTIME stNow;
+    HFONT hHeaderFont;
+    HFONT hBodyFont;
+    LPTSTR pszText;
+    DWORD ich;
+    DWORD cchText;
+    INT cyHeader;
+    INT cySpacing;
+    INT cyFooter;
+} PRINT_DATA, *PPRINT_DATA;
+
+/* Convert the points into pixels */
+#define X_POINTS_TO_PIXELS(hDC, points) MulDiv((points), GetDeviceCaps((hDC), 
LOGPIXELSX), 72)
+#define Y_POINTS_TO_PIXELS(hDC, points) MulDiv((points), GetDeviceCaps((hDC), 
LOGPIXELSY), 72)
+
+/*
+ * See also:
+ * 
https://support.microsoft.com/en-us/windows/changing-header-and-footer-commands-in-notepad-c1b0e27b-497d-c478-c4c1-0da491cac148
+ */
+static VOID
+DrawHeaderOrFooter(HDC hDC, LPRECT pRect, LPCTSTR pszFormat, INT nPageNo, 
const SYSTEMTIME *pstNow)
+{
+    TCHAR szText[256], szField[128];
+    const TCHAR *pchFormat;
+    UINT uAlign = DT_CENTER, uFlags = DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX;
+    HGDIOBJ hOldPen, hOldBrush;
+
+    /* Draw a rectangle */
+    hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
+    hOldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH));
+    Rectangle(hDC, pRect->left, pRect->top, pRect->right, pRect->bottom);
+    SelectObject(hDC, hOldBrush);
+    SelectObject(hDC, hOldPen);
+
+    InflateRect(pRect, -X_POINTS_TO_PIXELS(hDC, 3), 0); /* Shrink 3pt */
+
+    szText[0] = 0;
+
+    for (pchFormat = pszFormat; *pchFormat; ++pchFormat)
+    {
+        if (*pchFormat != _T('&'))
+        {
+            StringCchCatN(szText, ARRAY_SIZE(szText), pchFormat, 1);
+            continue;
+        }
+
+        ++pchFormat;
+        if (*pchFormat == 0)
+            break;
+
+        switch (_totupper(*pchFormat)) /* Make it uppercase */
+        {
+            case _T('&'): /* Found double ampersand */
+                StringCchCat(szText, ARRAY_SIZE(szText), TEXT("&"));
+                break;
+
+            case _T('L'): /* Left */
+                DrawText(hDC, szText, -1, pRect, uAlign | uFlags);
+                szText[0] = 0;
+                uAlign = DT_LEFT;
+                break;
+
+            case _T('C'): /* Center */
+                DrawText(hDC, szText, -1, pRect, uAlign | uFlags);
+                szText[0] = 0;
+                uAlign = DT_CENTER;
+                break;
+
+            case _T('R'): /* Right */
+                DrawText(hDC, szText, -1, pRect, uAlign | uFlags);
+                szText[0] = 0;
+                uAlign = DT_RIGHT;
+                break;
+
+            case _T('D'): /* Date */
+                GetDateFormat(LOCALE_USER_DEFAULT, 0, pstNow, NULL,
+                              szField, (INT)ARRAY_SIZE(szField));
+                StringCchCat(szText, ARRAY_SIZE(szText), szField);
+                break;
+
+            case _T('T'): /* Time */
+                GetTimeFormat(LOCALE_USER_DEFAULT, 0, pstNow, NULL,
+                              szField, (INT)ARRAY_SIZE(szField));
+                StringCchCat(szText, ARRAY_SIZE(szText), szField);
+                break;
+
+            case _T('F'): /* Filename */
+                StringCchCat(szText, ARRAY_SIZE(szText), Globals.szFileTitle);
+                break;
+
+            case _T('P'): /* Page number */
+                StringCchPrintf(szField, ARRAY_SIZE(szField), TEXT("%u"), 
nPageNo);
+                StringCchCat(szText, ARRAY_SIZE(szText), szField);
+                break;
+
+            default: /* Otherwise */
+                szField[0] = _T('&');
+                szField[1] = *pchFormat;
+                szField[2] = 0;
+                StringCchCat(szText, ARRAY_SIZE(szText), szField);
+                break;
+        }
+    }
+
+    DrawText(hDC, szText, -1, pRect, uAlign | uFlags);
+}
+
+static BOOL DoPrintBody(PPRINT_DATA pData, DWORD PageCount, BOOL bSkipPage)
+{
+    LPPRINTDLG pPrinter = &pData->printer;
+    RECT printRect = pData->printRect;
+    INT xLeft = printRect.left, yTop = printRect.top + pData->cyHeader + 
pData->cySpacing;
+    INT xStart, tabWidth;
+    DWORD ichStart;
+    SIZE charMetrics;
+    TEXTMETRIC tmText;
+
+    /* Calculate a tab width */
+#define TAB_STOP 8
+    GetTextMetrics(pPrinter->hDC, &tmText);
+    tabWidth = TAB_STOP * tmText.tmAveCharWidth;
+
+#define DO_FLUSH() do { \
+    if (ichStart < pData->ich && !bSkipPage) { \
+        TextOut(pPrinter->hDC, xStart, yTop, &pData->pszText[ichStart], 
pData->ich - ichStart); \
+    } \
+    ichStart = pData->ich; \
+    xStart = xLeft; \
+    if (pData->status == STRING_PRINTCANCELING) return FALSE; \
+} while (0)
+
+    /* The drawing-body loop */
+    for (ichStart = pData->ich, xStart = xLeft; pData->ich < pData->cchText; )
+    {
+        TCHAR ch = pData->pszText[pData->ich];
+
+        if (ch == _T('\r'))
+        {
+            DO_FLUSH();
+
+            pData->ich++; /* Next char */
+            ichStart = pData->ich;
+            continue;
+        }
+
+        if (ch == _T('\n'))
+        {
+            DO_FLUSH();
+
+            /* Next line */
+            yTop += tmText.tmHeight;
+            xLeft = xStart = printRect.left;
+        }
+        else
+        {
+            if (ch == _T('\t'))
+            {
+                INT nStepWidth = tabWidth - ((xLeft - printRect.left) % 
tabWidth);
+
+                DO_FLUSH();
+
+                /* Go to the next tab stop */
+                xLeft += nStepWidth;
+                xStart = xLeft;
+            }
+            else /* Normal char */
+            {
+                GetTextExtentPoint32(pPrinter->hDC, &ch, 1, &charMetrics);
+                xLeft += charMetrics.cx;
+            }
+
+            /* Insert a line break if the next position reached the right edge 
*/
+            if (xLeft + charMetrics.cx >= printRect.right)
+            {
+                if (ch != _T('\t'))
+                    DO_FLUSH();
+
+                /* Next line */
+                yTop += tmText.tmHeight;
+                xLeft = xStart = printRect.left;
+            }
+        }
+
+        pData->ich++; /* Next char */
+        if (ch == _T('\t') || ch == _T('\n'))
+            ichStart = pData->ich;
+
+        if (yTop + tmText.tmHeight >= printRect.bottom - pData->cyFooter)
+            break; /* The next line reached the body bottom */
+    }
+
+    DO_FLUSH();
+    return TRUE;
+}
+
+static BOOL DoPrintPage(PPRINT_DATA pData, DWORD PageCount)
+{
+    LPPRINTDLG pPrinter = &pData->printer;
+    BOOL bSkipPage, ret;
+    HFONT hOldFont;
+
+    /* Should we skip this page? */
+    bSkipPage = !(pPrinter->Flags & PD_SELECTION) &&
+                (pPrinter->Flags & PD_PAGENUMS) &&
+                !(pPrinter->nFromPage <= PageCount && PageCount <= 
pPrinter->nToPage);
+
+    /* The prologue of a page */
+    if (!bSkipPage)
+    {
+        if (StartPage(pPrinter->hDC) <= 0)
+        {
+            pData->status = STRING_PRINTFAILED;
+            return FALSE;
+        }
+
+        if (pData->cyHeader > 0)
+        {
+            /* Draw the page header */
+            RECT rc = pData->printRect;
+            rc.bottom = rc.top + pData->cyHeader;
+
+            hOldFont = SelectObject(pPrinter->hDC, pData->hHeaderFont);
+            DrawHeaderOrFooter(pPrinter->hDC, &rc, Globals.szHeader, 
PageCount, &pData->stNow);
+            SelectObject(pPrinter->hDC, hOldFont); /* De-select the font */
+        }
+    }
+
+    hOldFont = SelectObject(pPrinter->hDC, pData->hBodyFont);
+    ret = DoPrintBody(pData, PageCount, bSkipPage);
+    SelectObject(pPrinter->hDC, hOldFont);
+    if (!ret)
+        return FALSE; /* Canceled */
+
+    /* The epilogue of a page */
+    if (!bSkipPage)
+    {
+        if (pData->cyFooter > 0)
+        {
+            /* Draw the page footer */
+            RECT rc = pData->printRect;
+            rc.top = rc.bottom - pData->cyFooter;
+
+            hOldFont = SelectObject(pPrinter->hDC, pData->hHeaderFont);
+            DrawHeaderOrFooter(pPrinter->hDC, &rc, Globals.szFooter, 
PageCount, &pData->stNow);
+            SelectObject(pPrinter->hDC, hOldFont);
+        }
+
+        if (EndPage(pPrinter->hDC) <= 0)
+        {
+            pData->status = STRING_PRINTFAILED;
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+#define BODY_FONT_SIZE      10 /* 10pt */
+#define HEADER_FONT_SIZE    9  /* 9pt */
+#define SPACING_HEIGHT      4  /* 4pt */
+#define PRINTING_MESSAGE (WM_USER + 100)
+
+static BOOL DoCreatePrintFonts(LPPRINTDLG pPrinter, PPRINT_DATA pPrintData)
+{
+    LOGFONT lfBody, lfHeader;
+
+    /* Create the main text font for printing */
+    lfBody = Globals.lfFont;
+    lfBody.lfHeight = -Y_POINTS_TO_PIXELS(pPrinter->hDC, BODY_FONT_SIZE);
+    pPrintData->hBodyFont = CreateFontIndirect(&lfBody);
+    if (pPrintData->hBodyFont == NULL)
+        return FALSE;
+
+    /* Create the header/footer font */
+    lfHeader = Globals.lfFont;
+    lfHeader.lfHeight = -Y_POINTS_TO_PIXELS(pPrinter->hDC, HEADER_FONT_SIZE);
+    lfHeader.lfWeight = FW_BOLD;
+    pPrintData->hHeaderFont = CreateFontIndirect(&lfHeader);
+    if (pPrintData->hHeaderFont == NULL)
+        return FALSE;
+
+    return TRUE;
+}
+
+static BOOL DoPrintDocument(PPRINT_DATA printData)
+{
+    DOCINFO docInfo;
+    LPPRINTDLG pPrinter = &printData->printer;
+    DWORD CopyCount, PageCount;
+    TEXTMETRIC tmHeader;
+    BOOL ret = FALSE;
+    HFONT hOldFont;
+
+    GetLocalTime(&printData->stNow);
+
+    printData->printRect = GetPrintingRect(pPrinter->hDC, &Globals.lMargins);
+
+    if (!DoCreatePrintFonts(pPrinter, printData))
+    {
+        printData->status = STRING_PRINTFAILED;
+        goto Quit;
+    }
+
+    if (pPrinter->Flags & PD_SELECTION)
+        printData->cchText = GetSelectionTextLength(Globals.hEdit);
+    else
+        printData->cchText = GetWindowTextLength(Globals.hEdit);
+
+    /* Allocate a buffer for the text */
+    printData->pszText = HeapAlloc(GetProcessHeap(), 0, (printData->cchText + 
1) * sizeof(TCHAR));
+    if (!printData->pszText)
+    {
+        printData->status = STRING_PRINTFAILED;
+        goto Quit;
+    }
+
+    if (pPrinter->Flags & PD_SELECTION)
+        GetSelectionText(Globals.hEdit, printData->pszText, printData->cchText 
+ 1);
+    else
+        GetWindowText(Globals.hEdit, printData->pszText, printData->cchText + 
1);
+
+    /* Start a document */
+    ZeroMemory(&docInfo, sizeof(docInfo));
+    docInfo.cbSize = sizeof(DOCINFO);
+    docInfo.lpszDocName = Globals.szFileTitle;
+    if (StartDoc(pPrinter->hDC, &docInfo) <= 0)
+    {
+        printData->status = STRING_PRINTFAILED;
+        goto Quit;
+    }
+
+    /* Calculate the header and footer heights */
+    hOldFont = SelectObject(pPrinter->hDC, printData->hHeaderFont);
+    GetTextMetrics(pPrinter->hDC, &tmHeader);
+    printData->cyHeader = printData->cyFooter = 2 * tmHeader.tmHeight;
+    printData->cySpacing = Y_POINTS_TO_PIXELS(pPrinter->hDC, SPACING_HEIGHT);
+    SelectObject(pPrinter->hDC, hOldFont); /* De-select the font */
+    if (!Globals.szHeader[0])
+        printData->cyHeader = printData->cySpacing = 0;
+    if (!Globals.szFooter[0])
+        printData->cyFooter = 0;
+
+    /* The printing-copies loop */
+    for (CopyCount = 1; CopyCount <= pPrinter->nCopies; ++CopyCount)
+    {
+        /* The printing-pages loop */
+        for (PageCount = 1, printData->ich = 0; printData->ich < 
printData->cchText; ++PageCount)
+        {
+            printData->currentPage = PageCount;
+            PostMessage(printData->hwndDlg, PRINTING_MESSAGE, 0, 0);
+
+            if (!DoPrintPage(printData, PageCount))
+            {
+                AbortDoc(pPrinter->hDC); /* Cancel printing */
+                goto Quit;
+            }
+        }
+    }
+
+    if (EndDoc(pPrinter->hDC) <= 0)
+    {
+        printData->status = STRING_PRINTFAILED;
+        goto Quit;
+    }
+
+    ret = TRUE;
+    printData->status = STRING_PRINTCOMPLETE;
+
+Quit:
+    DeleteObject(printData->hHeaderFont);
+    DeleteObject(printData->hBodyFont);
+    if (printData->pszText)
+        HeapFree(GetProcessHeap(), 0, printData->pszText);
+    if (printData->status == STRING_PRINTCANCELING)
+        printData->status = STRING_PRINTCANCELED;
+    PostMessage(printData->hwndDlg, PRINTING_MESSAGE, 0, 0);
+    return ret;
+}
+
+static DWORD WINAPI PrintThreadFunc(LPVOID arg)
+{
+    PPRINT_DATA pData = arg;
+    pData->currentPage = 1;
+    pData->status = STRING_NOWPRINTING;
+    PostMessage(pData->hwndDlg, PRINTING_MESSAGE, 0, 0);
+    return DoPrintDocument(pData);
+}
+
+static INT_PTR CALLBACK
+DIALOG_Printing_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    TCHAR szText[MAX_STRING_LEN];
+    static TCHAR s_szPage[64];
+    static PPRINT_DATA s_pData = NULL;
+    static HANDLE s_hThread = NULL;
+
+    switch (uMsg)
+    {
+        case WM_INITDIALOG:
+            s_pData = (PPRINT_DATA)lParam;
+            s_pData->hwndDlg = hwnd;
+            SetDlgItemText(hwnd, IDC_PRINTING_FILENAME, Globals.szFileTitle);
+            GetDlgItemText(hwnd, IDC_PRINTING_PAGE, s_szPage, 
ARRAY_SIZE(s_szPage));
+            SetDlgItemText(hwnd, IDC_PRINTING_PAGE, NULL);
+
+            s_hThread = CreateThread(NULL, 0, PrintThreadFunc, s_pData, 0, 
NULL);
+            if (!s_hThread)
+            {
+                s_pData->status = STRING_PRINTFAILED;
+                EndDialog(hwnd, IDABORT);
+            }
+            return TRUE;
+
+        case PRINTING_MESSAGE:
+            switch (s_pData->status)
+            {
+                case STRING_NOWPRINTING:
+                case STRING_PRINTCANCELING:
+                    StringCchPrintf(szText, ARRAY_SIZE(szText), s_szPage, 
s_pData->currentPage);
+                    SetDlgItemText(hwnd, IDC_PRINTING_PAGE, szText);
+
+                    LoadString(Globals.hInstance, s_pData->status, szText, 
ARRAY_SIZE(szText));
+                    SetDlgItemText(hwnd, IDC_PRINTING_STATUS, szText);
+                    break;
+
+                case STRING_PRINTCOMPLETE:
+                case STRING_PRINTCANCELED:
+                case STRING_PRINTFAILED:
+                    LoadString(Globals.hInstance, s_pData->status, szText, 
ARRAY_SIZE(szText));
+                    SetDlgItemText(hwnd, IDC_PRINTING_STATUS, szText);
+
+                    if (s_pData->status == STRING_PRINTCOMPLETE)
+                        EndDialog(hwnd, IDOK);
+                    else if (s_pData->status == STRING_PRINTFAILED)
+                        EndDialog(hwnd, IDABORT);
+                    else
+                        EndDialog(hwnd, IDCANCEL);
+                    break;
+            }
+            break;
+
+        case WM_COMMAND:
+            if (LOWORD(wParam) == IDCANCEL && s_pData->status == 
STRING_NOWPRINTING)
+            {
+                EnableWindow(GetDlgItem(hwnd, IDCANCEL), FALSE);
+                s_pData->status = STRING_PRINTCANCELING;
+                PostMessage(hwnd, PRINTING_MESSAGE, 0, 0);
+            }
+            break;
+
+        case WM_DESTROY:
+            if (s_hThread)
+                CloseHandle(s_hThread);
+            DeleteDC(s_pData->printer.hDC);
+            s_pData = LocalFree(s_pData);
+            break;
+    }
+
+    return 0;
+}
+
+VOID DIALOG_FilePrint(VOID)
+{
+    BOOL ret;
+    LPPRINTDLG printer;
+    PPRINT_DATA printData = LocalAlloc(LPTR, sizeof(PRINT_DATA));
+    if (!printData)
+    {
+        ShowLastError();
+        return;
+    }
+
+    printer = &printData->printer;
+    printer->lStructSize = sizeof(PRINTDLG);
+    printer->hwndOwner = Globals.hMainWnd;
+    printer->Flags = PD_RETURNDC | PD_SELECTION;
+
+    /* Disable the selection radio button if there is no text selected */
+    if (!GetSelectionTextLength(Globals.hEdit))
+        printer->Flags |= PD_NOSELECTION;
+
+    printer->nFromPage = 1;
+    printer->nToPage = MAXWORD;
+    printer->nMinPage = 1;
+    printer->nMaxPage = MAXWORD;
+
+    printer->hDevMode = Globals.hDevMode;
+    printer->hDevNames = Globals.hDevNames;
+
+    ret = PrintDlg(printer);
+    /* NOTE: Even if PrintDlg returns FALSE, hDevMode and hDevNames may have 
changed. */
+    Globals.hDevMode = printer->hDevMode;
+    Globals.hDevNames = printer->hDevNames;
+
+    if (!ret)
+    {
+        LocalFree(printData);
+        return; /* The user canceled printing */
+    }
+    assert(printer->hDC != NULL);
+
+    /* Ensure that each logical unit maps to one pixel */
+    SetMapMode(printer->hDC, MM_TEXT);
+
+    if (DialogBoxParam(Globals.hInstance,
+                       MAKEINTRESOURCE(DIALOG_PRINTING),
+                       Globals.hMainWnd,
+                       DIALOG_Printing_DialogProc,
+                       (LPARAM)printer) == IDABORT)
+    {
+        AlertPrintError();
+    }
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *           DIALOG_PAGESETUP_Hook
+ */
+static UINT_PTR CALLBACK DIALOG_PAGESETUP_Hook(HWND hDlg, UINT uMsg, WPARAM 
wParam, LPARAM lParam)
+{
+    switch (uMsg)
+    {
+        case WM_INITDIALOG:
+            /* fetch last user input prior to display dialog */
+            SetDlgItemText(hDlg, 0x141, Globals.szHeader);
+            SetDlgItemText(hDlg, 0x143, Globals.szFooter);
+            break;
+
+        case WM_COMMAND:
+        {
+            if (HIWORD(wParam) == BN_CLICKED)
+            {
+                switch (LOWORD(wParam))
+                {
+                case IDOK:
+                    /* save user input and close dialog */
+                    GetDlgItemText(hDlg, 0x141, Globals.szHeader, 
ARRAY_SIZE(Globals.szHeader));
+                    GetDlgItemText(hDlg, 0x143, Globals.szFooter, 
ARRAY_SIZE(Globals.szFooter));
+                    return FALSE;
+
+                case IDCANCEL:
+                    /* discard user input and close dialog */
+                    return FALSE;
+
+                case IDHELP:
+                    {
+                        /* FIXME: Bring this to work */
+                        static const TCHAR sorry[] = _T("Sorry, no help 
available");
+                        static const TCHAR help[] = _T("Help");
+                        MessageBox(Globals.hMainWnd, sorry, help, 
MB_ICONEXCLAMATION);
+                        return TRUE;
+                    }
+
+                default:
+                    break;
+                }
+            }
+            break;
+        }
+    }
+
+    return FALSE;
+}
+
+/***********************************************************************
+ *           DIALOG_FilePageSetup
+ */
+VOID DIALOG_FilePageSetup(VOID)
+{
+    PAGESETUPDLG page;
+
+    ZeroMemory(&page, sizeof(page));
+    page.lStructSize = sizeof(page);
+    page.hwndOwner = Globals.hMainWnd;
+    page.Flags = PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPHOOK | 
PSD_MARGINS;
+    page.hInstance = Globals.hInstance;
+    page.rtMargin = Globals.lMargins;
+    page.hDevMode = Globals.hDevMode;
+    page.hDevNames = Globals.hDevNames;
+    page.lpPageSetupTemplateName = MAKEINTRESOURCE(DIALOG_PAGESETUP);
+    page.lpfnPageSetupHook = DIALOG_PAGESETUP_Hook;
+
+    PageSetupDlg(&page);
+
+    /* NOTE: Even if PageSetupDlg returns FALSE, the following members may 
have changed */
+    Globals.hDevMode = page.hDevMode;
+    Globals.hDevNames = page.hDevNames;
+    Globals.lMargins = page.rtMargin;
+}

Reply via email to