
.data
szOper01       db  '+-*,.[]()<>="',0
FontPrint      LOGFONT <-10,0,0,0,600,FALSE,FALSE,FALSE,0,0,0,0,0,'Courier New'>

.data?
InchesOn       dd  ?
PageSize       dd  ?
hHead          dd  ?
PrtHeading     dd  ?
PrtColor       dd  ?
PH             dd  ?
hWordMem       dd  ?
SizeWordMem    dd  ?
rpWordFree     dd  ?

;---------- [Structures] ----------
WORDINFO struct
      Len            dd ?              ; Length of word
      rpCurrent      dd ?              ; Relative pointer to current
      rpPrev         dd ?              ; Relative pointer to previous
      rpNext         dd ?              ; Relative pointer to next
      Color          dd ?              ; Color (high byte is font 0-3)
      WordFlag       dd ?              ; Word flag
WORDINFO ends

psd            PAGESETUPDLG <>

.code

;===================================================
; Load syntax keywords PROCEDURE
;===================================================
LoadKeyWords PROC uses ebx esi edi nColor:DWORD, lpWords
LOCAL    WordFlag:DWORD

         mov     esi, lpWords
         mov     edi, hWordMem
      .if !esi
            mov     ecx, SizeWordMem
            xor     eax, eax
            rep     stosb
            mov     rpWordFree, 256*4

      .else

NxtWrd:
            mov     WordFlag, 0
            mov     eax, SizeWordMem
            sub     eax, rpWordFree
         .if eax < 256
               add     SizeWordMem, MAXWORDMEM
            INVOKE     GetProcessHeap
            INVOKE     HeapReAlloc, eax, HEAP_NO_SERIALIZE or HEAP_ZERO_MEMORY, edi, SizeWordMem
            .if eax
                  mov     hWordMem, eax
                  mov     edi, eax
            .endif
         .endif
           movzx    eax, byte ptr [esi]
         .if eax
            .if eax == ','
                  inc     esi
                  jmp     NxtWrd
            .endif
            .if al >= 'a' && al <= 'z'
                  and     al, 5Fh
            .endif
               mov     edx, [edi+eax*4]
               mov     ecx, rpWordFree
               mov     [edi+eax*4], ecx

NxtChar:
               xor     eax, eax
               mov     al, [esi]
               inc     esi
            .if al == ',' || !al
               .if !al
                     dec     esi
               .endif
                  mov     byte ptr [edi+ecx+sizeof WORDINFO], 0
                  mov     eax, ecx
                  mov     ecx, rpWordFree
                  mov     [edi+ecx].WORDINFO.rpCurrent, ecx
                  mov     [edi+ecx].WORDINFO.rpNext, ecx
                  sub     eax, ecx
                  mov     [edi+ecx].WORDINFO.Len, eax
                  add     eax, sizeof WORDINFO+1
                  add     rpWordFree, eax
                  add     [edi+ecx].WORDINFO.rpNext, eax
                  mov     [edi+ecx].WORDINFO.rpPrev, edx
                  mov     eax, nColor
                  mov     [edi+ecx].WORDINFO.Color, eax
                  mov     eax, WordFlag
                  mov     [edi+ecx].WORDINFO.WordFlag, eax
                  jmp     NxtWrd
            .endif
            .if al >= 'a' && al <= 'z'
                  and     al, 5Fh
            .endif
            .if al == '-'
                  mov     WordFlag, 1
            .elseif al == '+'
                  mov     WordFlag, 2
            .else
                  mov     [edi+ecx+sizeof WORDINFO], al
                  inc     ecx
            .endif
               jmp     NxtChar
         .endif
      .endif
         ret

LoadKeyWords ENDP

;===================================================
; Print heading PROCEDURE
;===================================================
PrintHeading PROC uses ebx hdlg:DWORD, wMsg, wParam, lParam
LOCAL    Clear[256]:BYTE, szBuff[256]:BYTE

      .if wMsg == WM_INITDIALOG
            and     w5, 0
         INVOKE     GetDlgItem, hdlg, 301                              ; Get handle PrtHeading
         .if PrtHeading == 1
            INVOKE     SendMessage, eax, BM_SETCHECK, BST_CHECKED, 0   ; Sets PrtHeading to checked
         .else
            INVOKE     SendMessage, eax, BM_SETCHECK, BST_UNCHECKED, 0 ; Sets PrtHeading to unchecked
         .endif
         INVOKE     GetDlgItem, hdlg, 302                              ; Get handle PrtColor
         .if PrtColor == 1
            INVOKE     SendMessage, eax, BM_SETCHECK, BST_CHECKED, 0   ; Sets PrtColor to checked
         .else
            INVOKE     SendMessage, eax, BM_SETCHECK, BST_UNCHECKED, 0 ; Sets PrtColor to unchecked
         .endif
         .if PH
               mov     eax, 401
               add     eax, PH
               dec     eax
            INVOKE     GetDlgItem, hdlg, eax                           ; Get handle Heading Type
            INVOKE     SendMessage, eax, BM_SETCHECK, BST_CHECKED, 0   ; Sets Heading Type to checked
         .endif
         INVOKE     GetDlgItem, hdlg, IDOK
            mov     h42, eax
;         INVOKE     SetWindowLong, h42, GWL_WNDPROC, ControlButt
;            mov     SubControl, eax
         INVOKE     GetDlgItem, hdlg, IDCANCEL
            mov     h43, eax
;         INVOKE     SetWindowLong, h43, GWL_WNDPROC, ControlButt
;            mov     SubControl, eax

      .elseif wMsg == WM_CTLCOLORDLG || wMsg == WM_CTLCOLORSTATIC
         INVOKE     SetBkColor, wParam, Color.DialogBC
         INVOKE     SetTextColor, wParam, 00000000h
         .if hBR
            INVOKE     DeleteObject, hBR
         .endif
         INVOKE     CreateSolidBrush, Color.DialogBC
            mov     hBR, eax
            ret

      .elseif wMsg == WM_CTLCOLOREDIT
         INVOKE     SetBkColor, wParam, 00000000h   ; Background color is black
         INVOKE     SetTextColor, wParam, 00ffff00h ; Text color of edit box is lt blue
         INVOKE     GetStockObject, BLACK_BRUSH     ; Select the black brush for background
            ret

      .elseif wMsg == WM_DRAWITEM
         INVOKE     DrawButt, lParam

      .elseif wMsg == WM_COMMAND
            mov     eax, wParam
           cwde
            mov     ebx, wParam
            shr     ebx, 16

         .if ebx == BN_CLICKED
            INVOKE     GetFocus
            INVOKE     GetDlgCtrlID, eax
         .endif

         .if eax == IDCANCEL
               mov     w5, 44
               jmp     CancelIt

         .elseif eax == IDOK
            INVOKE     FillBuffer, addr Clear, sizeof Clear, ' ', 1
               mov     PH, 0
               and     PrtHeading, 0
               and     PrtColor, 0
            INVOKE     IsDlgButtonChecked, hdlg, 301
               mov     PrtHeading, eax
            INVOKE     IsDlgButtonChecked, hdlg, 302
               mov     PrtColor, eax
               mov     ebx, hHead
            INVOKE     lstrcpy, ebx, addr Clear
            INVOKE     GetDlgItemText, hdlg, 501, addr szBuff, lengthof szBuff
            INVOKE     IsDlgButtonChecked, hdlg, 401
            .if eax
                  mov     PH, 1
            .endif
            INVOKE     IsDlgButtonChecked, hdlg, 402
            .if eax
                  mov     PH, 2
            .endif
            INVOKE     IsDlgButtonChecked, hdlg, 403
            .if eax
                  mov     PH, 3
            .endif
            INVOKE     lstrlen, addr szBuff
            .if eax || PH > 0
                  mov     ebx, hHead
               .if eax
                  INVOKE     lstrcpy, ebx, addr szBuff
               .elseif PH == 1
                  INVOKE     lstrcpy, ebx, addr Clear
               .elseif PH == 2
                  INVOKE     lstrcpy, ebx, addr FileName
               .elseif PH == 3
                  INVOKE     lstrcpy, ebx, addr PathName
               .endif
            .endif
               jmp     CancelIt
         .endif
      .elseif wMsg == WM_CLOSE
            mov     w5, 44
            jmp     CancelIt
      .endif
         jmp     DlgDone

CancelIt:
      .if hBR
         INVOKE     DeleteObject, hBR
      .endif
         and     hWndDlg, 0
      INVOKE     EndDialog, hdlg, wParam
         mov     eax, TRUE             ; Return
         jmp     DlgRet                ; with TRUE

DlgDone:
         mov     eax, FALSE            ; Return with FALSE

DlgRet:
         ret
PrintHeading ENDP

;===================================================
; Page Setup Dialog PROCEDURE
;===================================================
DoPageSU PROC
LOCAL    w1:DWORD, w2

         mov     psd.lStructSize, sizeof psd
        push     hWnd
         pop     psd.hwndOwner
        push     hInst
         pop     psd.hInstance ; or PSD_DISABLEPAPER
         mov     psd.Flags, PSD_MARGINS or PSD_INTHOUSANDTHSOFINCHES or PSD_DISABLEPRINTER
      INVOKE     PageSetupDlg, addr psd
         cmp     eax,0
          jz     NSU

NSU:
         ret
DoPageSU ENDP

;===================================================
; Syntax highlighting PROCEDURE
;===================================================
Syntax PROC uses ebx esi edi, hDC:DWORD, PtrX, PtrY, ptH, TabWth, lpStr
LOCAL    rect:RECT
LOCAL    len:DWORD, WordLen, WordColor

      INVOKE     lstrlen, lpStr
         mov     len, eax
        call     HiliteComment
      INVOKE     lstrlen, lpStr
         mov     len, eax
      INVOKE     SetTextColor, hDC, 00ffff00h
         mov     al, '"'
        call     HiliteString
         mov     al, "'"
        call     HiliteString

      INVOKE     SetTextColor, hDC, 00800080h
         mov     al, "'"
        call     HiliteOper
         mov     esi, offset szOper01

LoopOpr:
         mov     al, [esi]
      .if al
           call     HiliteOper
            inc     esi
            jmp     LoopOpr
      .endif

;---------- [Begin the word search
         mov     esi, lpStr
      INVOKE     lstrlen, esi
         mov     ecx, eax
      .while ecx > 0
            mov     al, byte ptr [esi]
         .if al != ' ' && al != VK_TAB && al
              push     ecx
               and     WordColor, 0
              call     FindWord
            .if WordLen

;---------- [Hilight the word
               pushad
                  mov     ebx, PtrX
               .if esi != lpStr
                     mov     ecx, esi
                     sub     ecx, lpStr
                  INVOKE     GetTabbedTextExtent, hDC, lpStr, ecx, 1, addr TabWth
                     and     eax, 0FFFFh
                     add     ebx, eax
               .endif
               INVOKE     SetTextColor, hDC, WordColor
               INVOKE     TabbedTextOut, hDC, ebx, PtrY, esi, WordLen, 1, addr TabWth, PtrX
                popad
                  mov     edx, WordLen
            .else
                  mov     edx, 1
            .endif
               pop     ecx
               sub     ecx, edx
               add     esi, edx
         .else
            dec     ecx
            inc     esi
         .endif
      .endw
         ret

;---------- [
FindWord:
         xor     ecx, ecx
        call     GetWordLen
         mov     WordLen, ecx
      .if ecx
           call     TestWord
         .if !ecx
               mov     eax, 00008000h
         .endif
      .else
            mov     eax, 00008000h
      .endif
         mov     WordColor, eax
        retn

;---------- [
GetWordLen:
     push     esi
         xor     ecx, ecx
         dec     ecx

NormalChar:
         inc     ecx
       movzx     eax, byte ptr [esi]
      .if eax >= 'a' && eax <= 'z' || eax >= 'A' && eax <= 'Z'
            inc     esi
            jmp     NormalChar
      .endif
         pop     esi
        retn

;---------- [
TestWord:
        push      ebx
       movzx      eax, byte ptr [esi]
      .if eax >= 'a' && eax <= 'z'
            and     eax, 5fh
      .endif
         mov     ebx, hWordMem
         mov     edx, [ebx+eax*4]

TestWord1:
      .if edx
            cmp     ecx, [ebx+edx].WORDINFO.Len
             je     MatchedLen
            mov     edx, [ebx+edx].WORDINFO.rpPrev
            jmp     TestWord1

MatchedLen:
           call     CmpWord
         .if !ZERO?
               mov     edx, [ebx+edx].WORDINFO.rpPrev
               jmp     TestWord1
         .endif
            mov     eax, [ebx+edx].WORDINFO.Color
      .else
            xor     ecx, ecx
      .endif
         pop     ebx
        retn

;---------- [
CmpWord:
        push     ecx
        push     ebx
        push     esi
         lea     ebx, [ebx+edx+sizeof WORDINFO]
         lea     esi, [esi]
         jmp     CmpWord1

DoAgain:
         mov     al, [esi+ecx]
      .if al >= 'a' && al <= 'z'
            and     al, 5fh
      .endif
         cmp     al, [ebx+ecx]
         jne     GetOut

CmpWord1:
         dec     ecx
         jne     DoAgain

GetOut:
         pop     esi
         pop     ebx
         pop     ecx
        retn

;_______________________________________________________________
ChkSpaceTab:
         inc     esi
         inc     eax
         cmp     byte ptr [esi], ' '
          je     SpaceTab
         cmp     byte ptr [esi], VK_TAB
          je     SpaceTab
         cmp     byte ptr [esi], 0
         jne     ChkSpaceTab
SpaceTab:
         pop     esi
        retn

HiliteComment:
         mov     ecx, len
         mov     edi, lpStr
         mov     al, ';'
       repne     scasb
         jne     NoComment
         dec     edi
      INVOKE     SetTextColor, hDC, 000000ffh ;PrnColors[4]
         mov     ebx, PtrX
      .if edi != lpStr
            mov     ecx, edi
            sub     ecx, lpStr
         INVOKE     GetTabbedTextExtent, hDC, lpStr, ecx, 1, addr TabWth
            and     eax, 0FFFFh
            add     ebx, eax
      .endif
      INVOKE     lstrlen, edi
         mov     ecx, eax
      INVOKE     TabbedTextOut, hDC, ebx, PtrY, edi, ecx, 1, addr TabWth, PtrX
         mov     byte ptr [edi], 0
NoComment:
        retn

HiliteString:
         mov     ecx, len
         mov     edi, lpStr
ChkString:
       repne     scasb
         jne     NoString
        push     eax
        push     ecx
        push     edi
        push     eax
        push     ecx
         mov     ebx, PtrX
      .if edi != lpStr
            mov     ecx, edi
            sub     ecx, lpStr
         INVOKE     GetTabbedTextExtent, hDC, lpStr, ecx, 1, addr TabWth
            and     eax, 0FFFFh
            add     ebx, eax
      .endif
         pop     ecx
         pop     eax
        push     edi
       repne     scasb
         pop     ecx
         jne     NotFound
         dec     edi

NotFound:
         sub     ecx, edi
         neg     ecx
         pop     edi
        push     ecx
      INVOKE     TabbedTextOut, hDC, ebx, PtrY, edi, ecx, 1, addr TabWth, PtrX
         pop     ecx
         mov     al, ' '
         rep     stosb
         pop     ecx
         pop     eax
       repne     scasb
         jne     NoString
          or     ecx, ecx
         jne     ChkString
NoString:
        retn

HiliteOper:
         mov     ecx, len
         mov     edi, lpStr

ChkOper:
       repne     scasb
         jne     NoOper
         dec     edi
        push     eax
        push     ecx
         mov     ebx, PtrX
      .if edi != lpStr
            mov     ecx, edi
            sub     ecx, lpStr
         INVOKE     GetTabbedTextExtent, hDC, lpStr, ecx, 1, addr TabWth
            and     eax, 0FFFFh
            add     ebx, eax
      .endif
      INVOKE     TabbedTextOut, hDC, ebx, PtrY, edi, 1, 1, addr TabWth, PtrX
         mov     byte ptr [edi], ' '
         pop     ecx
         pop     eax
         inc     edi
          or     ecx, ecx
         jne     ChkOper

NoOper:
        retn

Syntax ENDP

;===================================================
; Convert to pixels PROCEDURE
;===================================================
ConvToPix PROC PixelsPerIn:DWORD, VarSize

         mov     eax, PixelsPerIn
      .if InchesOn
           imul     eax, 10

      .else
           imul     eax, 1000
            xor     edx, edx
            mov     ecx, 254
            div     ecx
      .endif
         mov     ecx, eax
         mov     eax, VarSize
        imul     eax, ecx
         xor     edx, edx
         mov     ecx, 10000
         div     ecx
         ret

ConvToPix ENDP

;===================================================
; Print document PROCEDURE
;===================================================
Print PROC uses ebx esi
LOCAL    tm:TEXTMETRIC
LOCAL    pd:PRINTDLG
LOCAL    doci:DOCINFO
LOCAL    pt:POINT
LOCAL    sz:SIZEL
LOCAL    tr:TEXTRANGE
LOCAL    rect:RECT
LOCAL    hFontHead:DWORD, hFontPrt:DWORD, PtrX, PtrY, PaperX, PaperY, mL, mT, mR, mB, CurLine
LOCAL    LinesLeft:DWORD, TabWth, hRgn, PageNum, OffSetX, OffSetY, AvgCharWth, MaxLine, hDC
LOCAL    szBuff0[256]:BYTE, szBuff1[256]:BYTE, TimeBuff[32]:BYTE
LOCAL    PrtBuff[1024*2]:BYTE, PrtWrap[1024*2]:BYTE

      INVOKE     DialogBoxParam, hInst, IDD_PRTHEAD, hWnd, addr PrintHeading, 0
      .if w5 == 44              ; Cancel dialog
            ret
      .endif

;---------- [Zero out the structures] ----------
      INVOKE     RtlZeroMemory, addr pd, sizeof pd
      INVOKE     RtlZeroMemory, addr doci, sizeof doci

jmp     Past
;---------- [Checking for LF at the end of file
      INVOKE     SendMessage, hREdit, WM_GETTEXTLENGTH, 0, 0
         mov     cr.cpMin, eax
         mov     cr.cpMax, eax
         mov     tr.chrg.cpMin, eax
         mov     tr.chrg.cpMax, eax
         sub     tr.chrg.cpMin, 2
         lea     eax, szBuff0
         mov     tr.lpstrText, eax
      INVOKE     SendMessage, hREdit, EM_GETTEXTRANGE, 0, addr tr
      .if byte ptr szBuff0 == 0ah || byte ptr szBuff0+1 == 0ah
      .else
         INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
         INVOKE     SendMessage, hREdit, EM_REPLACESEL, FALSE, addr szCRLF
      .endif
Past:

;      INVOKE     CreateFontIndirect, addr FontPrint
;         mov     hFontPrt, eax
      INVOKE     GetDC, hREdit
         mov     hDC, eax

;---------- [Get page size
      INVOKE     lstrcpy, addr lf.lfFaceName, addr FontPrint.lfFaceName
      INVOKE     GetDeviceCaps, hDC, LOGPIXELSY
         mov     ecx, FontPrint.lfHeight
         neg     ecx
         mul     ecx
         xor     edx, edx
         mov     ecx, 72
         div     ecx
         neg     eax
         mov     lf.lfHeight, eax
         mov     eax, FontPrint.lfWeight
         mov     lf.lfWeight, eax
      INVOKE     CreateFontIndirect, addr lf
         mov     hFontPrt, eax


      INVOKE     SelectObject, hDC, hFontPrt
      INVOKE     GetDeviceCaps, hDC, LOGPIXELSY
        imul     eax, 10
        push     eax
      INVOKE     GetTextMetrics, hDC, addr tm
         pop     eax
         xor     edx, edx
         mov     ecx, tm.tmHeight
;         add     ecx, tm.tmInternalLeading
;         add     ecx, tm.tmExternalLeading
         div     ecx
      .if edx
              inc     eax
      .endif
         mov     PageSize, eax
      INVOKE     ReleaseDC, hREdit, hDC
      INVOKE     DeleteObject, hFontPrt

      INVOKE     GetUserDefaultLCID
         mov     edx, eax
      INVOKE     GetLocaleInfo, edx, LOCALE_IMEASURE, addr szBuff0, sizeof szBuff0
         mov     InchesOn, 1
      .if byte ptr szBuff0 != '1'
            mov     InchesOn, 0
      .endif

      INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
         mov     pd.lStructSize,  sizeof pd
       MOVmd     pd.hwndOwner, hWnd
       MOVmd     pd.hInstance, hInst
         mov     eax, cr.cpMin
      .if eax != cr.cpMax
            mov     eax, PD_RETURNDC or PD_SELECTION
      .else
         INVOKE     SendMessage, hREdit, EM_GETLINECOUNT, 0, 0
            mov     ecx, PageSize
            xor     edx, edx
            div     ecx
         .if edx
               inc     eax
         .endif
            mov     pd.nMinPage, 1
            mov     pd.nMaxPage, ax
            mov     pd.nFromPage, 1
            mov     pd.nToPage, ax
            mov     eax, PD_RETURNDC or PD_NOSELECTION or PD_ALLPAGES
      .endif
         mov     pd.Flags, eax
      INVOKE     PrintDlg, addr pd
      .if eax
         .if PH != 1
            INVOKE     GetDateFormat, NULL, NULL, NULL, offset DatePict, addr TimeBuff, 12
               mov     dword ptr TimeBuff[10], '    '
            INVOKE     GetTimeFormat, NULL, TIME_FORCE24HOURFORMAT, NULL, offset TimePict, addr TimeBuff[12], 12
               mov     dword ptr szBuff0, 00202020h
            INVOKE     lstrcat, addr TimeBuff, addr szBuff0
         .endif

         INVOKE     GetDeviceCaps, pd.hDC, PHYSICALOFFSETX ; = device units left/right margin
            mov     OffSetX, eax
         INVOKE     GetDeviceCaps, pd.hDC, PHYSICALOFFSETY ; = device units top/bottom margin
            mov     OffSetY, eax
         INVOKE     GetDeviceCaps, pd.hDC, LOGPIXELSX
            mov     ebx, eax
         INVOKE     ConvToPix, ebx, psd.ptPaperSize.x
            mov     PaperX, eax
         INVOKE     ConvToPix, ebx, psd.rtMargin.left
            mov     mL, eax
         INVOKE     ConvToPix, ebx, psd.rtMargin.right
            mov     mR, eax
         INVOKE     GetDeviceCaps, pd.hDC, LOGPIXELSY
            mov     ebx, eax
         INVOKE     ConvToPix, ebx, psd.ptPaperSize.y
            mov     PaperY, eax
         INVOKE     ConvToPix, ebx, psd.rtMargin.top
            mov     mT, eax
         INVOKE     ConvToPix, ebx, psd.rtMargin.bottom
            mov     mB, eax
            mov     eax, OffSetX
            mov     ecx, OffSetY
            sub     mL, eax
            sub     mT, ecx
            add     mR, eax
            add     mB, ecx
;         INVOKE     RtlZeroMemory, addr lf, sizeof lf
         INVOKE     lstrcpy, addr lf.lfFaceName, addr FontPrint.lfFaceName
         INVOKE     GetDeviceCaps, pd.hDC, LOGPIXELSY
            mov     ecx, FontPrint.lfHeight
            neg     ecx
            mul     ecx
            xor     edx, edx
            mov     ecx, 72
            div     ecx
            neg     eax
            mov     lf.lfHeight, eax
            mov     eax, FontPrint.lfWeight
            mov     lf.lfWeight, eax
         INVOKE     CreateFontIndirect, addr lf
            mov     hFontPrt, eax

         INVOKE     lstrcpy, addr lf.lfFaceName, addr FontTah
            mov     lf.lfHeight, 52
            mov     lf.lfWeight, 600
         INVOKE     CreateFontIndirect, addr lf
            mov     hFontHead, eax

            mov     doci.cbSize, sizeof doci
            mov     doci.lpszDocName, offset AppName
            mov     eax, pd.Flags
            and     eax, PD_PRINTTOFILE
         .if eax
               mov     eax, 'ELIF'
               mov     dword ptr szBuff0, eax
               mov     eax, ':'
               mov     dword ptr szBuff0+4, eax
               lea     eax, szBuff0
               mov     doci.lpszOutput, eax
         .else
               mov     doci.lpszOutput, NULL
         .endif
            mov     doci.lpszDatatype, NULL
            mov     doci.fwType, NULL
         INVOKE     StartDoc, pd.hDC, addr doci
            mov     eax, pd.Flags
            and     eax, PD_SELECTION
         .if eax
            INVOKE     SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMin
               mov     CurLine, eax
               mov     ecx, PageSize
               xor     edx, edx
               div     ecx
               mov     PageNum, 0 ;eax
            INVOKE     SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMax
               sub     eax, CurLine
               mov     LinesLeft, eax
               mov     pd.nToPage, -1
         .else
             movzx     eax, pd.nFromPage
               dec     eax
               mov     PageNum, eax
              imul     eax, PageSize
               mov     CurLine, eax
            INVOKE     SendMessage, hREdit, EM_GETLINECOUNT, 0, 0
                or     eax, eax
                je     AllDone
               mov     LinesLeft, eax
         .endif

            mov     eax, mL
            mov     rect.left, eax
            mov     eax, PaperX
            sub     eax, mR
            mov     rect.right, eax
            mov     eax, mT
            mov     rect.top, eax
            mov     eax, PaperY
            sub     eax, mB
            mov     rect.bottom, eax
         INVOKE     CreateRectRgn, rect.left, rect.top, rect.right, rect.bottom
            mov     hRgn, eax

NextPage:
            inc     PageNum
            mov     eax, PageNum
         .if ax > pd.nToPage
               jmp     AllDone
         .endif
         INVOKE     StartPage, pd.hDC
            mov     eax, mT
            mov     PtrY, eax
         INVOKE     SelectObject, pd.hDC, hFontPrt
         INVOKE     SelectObject, pd.hDC, hRgn

;---------- [Get average character width and max line
            mov     eax, 'W i.'
            mov     dword ptr szBuff0, eax
         INVOKE     GetTextExtentPoint32, pd.hDC, addr szBuff0, 4, addr pt
            mov     eax, pt.x
            shr     eax, 2
            mov     AvgCharWth, eax
            xor     edx, edx
            mov     eax, rect.right
            mov     ecx, AvgCharWth
            div     ecx
            dec     eax
            mov     MaxLine, eax

;---------- [Get tab width
            mov     eax, 'WWWW'
            mov     dword ptr szBuff0, eax
         INVOKE     GetTextExtentPoint32, pd.hDC, addr szBuff0, 4, addr pt
            mov     eax, pt.x
            shr     eax, 2
           imul     eax, TAB
            mov     TabWth, eax
           push     pt.y

;---------- [Page number
         .if PrtHeading
            INVOKE     SelectObject, pd.hDC, hFontHead
               mov     eax, 'gaP('
               mov     dword ptr szBuff0, eax
               mov     word ptr szBuff0[4], ' e'
            INVOKE     BaseAscii, PageNum, addr szBuff0[6], 0, 10, 0, 1, 1
            INVOKE     lstrcat, addr szBuff0, addr szPerR
            .if PH != 1
               INVOKE     lstrcpy, addr PrtBuff, addr TimeBuff
               INVOKE     lstrcat, addr PrtBuff, addr szBuff0

            .else
               INVOKE     lstrcpy, addr PrtBuff, addr szBuff0
            .endif
            INVOKE     lstrlen, hHead
               mov     ebx, eax
               mov     eax, mL
               mov     PtrX, eax
            .if PrtColor
               INVOKE     SetTextColor, pd.hDC, 00ff0000h
            .endif
            INVOKE     TextOut, pd.hDC, PtrX, PtrY, hHead, ebx
            INVOKE     lstrlen, addr PrtBuff
               mov     ebx, eax
            INVOKE     GetTextExtentPoint32, pd.hDC, addr PrtBuff, ebx, addr pt
               mov     eax, PaperX
               sub     eax, mR
               sub     eax, pt.x
               mov     PtrX, eax
              push     pt.x
            .if PrtColor
               INVOKE     SetTextColor, pd.hDC, 00ffff00h
            .endif
;            INVOKE     TextOut, pd.hDC, PtrX, PtrY, addr PrtBuff, ebx
            INVOKE     TextOut, pd.hDC, PtrX, PtrY, addr TimeBuff, ebx

            INVOKE     lstrlen, addr szBuff0
               mov     ebx, eax
            INVOKE     GetTextExtentPoint32, pd.hDC, addr szBuff0, ebx, addr pt
               pop     ecx
               mov     eax, pt.x
               add     PtrX, ecx
               sub     PtrX, eax
            .if PrtColor
               INVOKE     SetTextColor, pd.hDC, 00000000h
            .endif
            INVOKE     TextOut, pd.hDC, PtrX, PtrY, addr szBuff0, ebx

               mov     eax, pt.y
               add     PtrY, eax
               shr     eax, 1
               add     PtrY, eax
            INVOKE     SelectObject, pd.hDC, hFontPrt
         .endif
            pop     pt.y

NextLine:
            mov     eax, PtrY
            add     eax, pt.y
            cmp     eax, rect.bottom
            jnb     EndOfPage
            mov     eax, mL
            mov     PtrX, eax
         INVOKE     SendMessage, hREdit, EM_LINEINDEX, CurLine, 0
            mov     tr.chrg.cpMin, eax
         INVOKE     SendMessage, hREdit, EM_LINELENGTH, eax, 0
            add     eax, tr.chrg.cpMin
            mov     tr.chrg.cpMax, eax
            inc     CurLine
            lea     eax, PrtBuff
            mov     tr.lpstrText, eax
         INVOKE     SendMessage, hREdit, EM_GETTEXTRANGE, 0, addr tr
         .if LinesLeft == 1 && byte ptr PrtBuff == 0dh
               jmp     EndOfLine
         .endif
             or     eax, eax
             je     EndOfLine
         .if PrtColor
            INVOKE     SetTextColor, pd.hDC, 00008000h ;PrnColors[16]
         .endif

LoopLine:
            xor     esi, esi
         INVOKE     lstrlen, addr PrtBuff
            mov     ebx, eax
         .if ebx >= MaxLine
               mov     ebx, MaxLine
            INVOKE     lstrcpy, addr PrtWrap, addr PrtBuff[ebx]
               mov     esi, 1
         .endif
         INVOKE     TabbedTextOut, pd.hDC, PtrX, PtrY, addr PrtBuff, ebx, 1, addr TabWth, PtrX
         .if PrtColor
            INVOKE     Syntax, pd.hDC, PtrX, PtrY, pt.y, TabWth, addr PrtBuff
         .endif

EndOfLine:
               mov     eax, pt.y
               add     PtrY, eax
         .if esi
            INVOKE     lstrcpy, addr PrtBuff, addr PrtWrap
               jmp     LoopLine
         .endif
            dec     LinesLeft
             je     EndOfPage
            jmp     NextLine

EndOfPage:
         INVOKE     EndPage, pd.hDC
         .if LinesLeft
               jmp     NextPage
         .endif

AllDone:
         INVOKE     EndDoc, pd.hDC
         INVOKE     DeleteDC, pd.hDC
         INVOKE     DeleteObject, hFontHead
         INVOKE     DeleteObject, hFontPrt
         INVOKE     DeleteObject, hRgn
      .endif
         ret

Print ENDP
