iglobal
	szRichLib32			db "Riched32.dll",0
	szRichLib20			db "RICHED20.DLL",0
	szEditClass32		db "RICHEDIT", 0
	szEditClass20		db "RichEdit20a", 0
	szWinSpoolDRV		db "Winspool.drv", 0
	szWinSpoolDLL		db "Winspool.dll", 0
	szOpenPrinterA		db 'OpenPrinterA', 0
	szClosePrinter		db 'ClosePrinter', 0
	szDocumentProperties	db 'DocumentPropertiesA', 0
	REAppName			db 'RichEdit', 0
	REClassName			db 'REClass', 0
	j_page_break		db '*page', 0
	pbPointers			rd 40
	_windows			db	"windows", 0
	_Device				db	"Device", 0
	_Blank				db	" ", 0
	_DocTitle			db	"Bill Out Report", 0
endg

uglobal
	hPrinter			dd ?
	hDevmodeOut			dd ?
	hWndEdit			dd ?
	hLibRE				dd ?
	hFile				dd ?
	tempH				dd ?
	dcPrint				dd ?
	RTFHandle			dd ?
	tempP				dd ?
	pDevmodeOut			dd ?
	hSpoolLib			dd ?
	pOpenPrinterA		dd ?
	pClosePrinter		dd ?
	pDocumentProperties	dd ?
	pPrintDriver		dd ?
	pPrintPort			dd ?
	bLOrP				dd ?
	rtf_length			dd ?
	NumRtfBytes			dd ?
	NumOfCopies			dd ?
	set_props			dd ?
	
	pPrintInfo			rb	80
	sizeof.pPrintInfo = $ - pPrintInfo
	pRect				RECT
	DOC					DOCINFO
	LF					LOGFONT 
	FR					FORMATRANGE
	editstream			EDITSTREAM						; For EM_STREAMIN/EM_STREAMOUT
	m_psd				PAGESETUPDLG
	m_Paper             SIZEL							; in BASE_DPI
	m_MinMargin         RECT							; минимальные размеры полей 
	m_Margin            RECT							; текущие размеры полей
	gtl					GETTEXTLENGTHEX
	ft					FINDTEXTEX
endg

macro	ClearFR
{
	push	edi
	mov		ecx, sizeof.FORMATRANGE
	lea		edi, [FR]
	mov		eax, 0
	rep		stosb
	pop		edi

}

macro	Clearft
{
	push	edi
	mov		ecx, sizeof.FINDTEXTEX
	lea		edi, [ft]
	mov		eax, 0
	rep		stosb
	pop		edi

}

macro	RestoreFR
{
	m2m		[FR.rcPage.left], [temp_FR.rcPage.left]
	m2m		[FR.rcPage.top], [temp_FR.rcPage.top]
	m2m		[FR.rcPage.right], [temp_FR.rcPage.right]
	m2m		[FR.rcPage.bottom], [temp_FR.rcPage.bottom]
	m2m		[FR.rc.left], [temp_FR.rc.left]
	m2m		[FR.rc.top], [temp_FR.rc.top]
	m2m		[FR.rc.right], [temp_FR.rc.right]
	m2m		[FR.rc.bottom], [temp_FR.rc.bottom]
}


DOCINFO	struct
  cbSize        dd       ?
  lpszDocName   dd       ?
  lpszOutput    dd       ?
  lpszDatatype  dd       ?
  fwType        dd       ?
DOCINFO	ends

CHARRANGE	struct
  cpMin  dd      ?
  cpMax  dd      ?
CHARRANGE	ends

FORMATRANGE	struct
  hdc           dd      ?
  hdcTarget     dd      ?
  rc            RECT
  rcPage        RECT
  chrg          CHARRANGE
FORMATRANGE	ends

EDITSTREAM	struct
  dwCookie      dd      ?
  dwError       dd      ?
  pfnCallback   dd      ?
EDITSTREAM	ends

SIZEL	struct
  x  dd      ?
  y  dd      ?
SIZEL	ends

GETTEXTLENGTHEX	struct
  flags          dd      ?
  codepage       dd      ?
GETTEXTLENGTHEX	ends

FINDTEXTEX	struct
  chrg          CHARRANGE
  lpstrText     dd      ?
  chrgText      CHARRANGE <>
FINDTEXTEX	ends

;POINTL  equ  POINT
CCHDEVICENAME		equ 32
CCHFORMNAME			equ 32

DEVMODE	struct
  dmDeviceName      db   CCHDEVICENAME dup (?)		;0
  dmSpecVersion     dw      ?						;32
  dmDriverVersion   dw      ?						;34
  dmSize            dw      ?						;36
  dmDriverExtra     dw      ?						;38
  dmFields          dd      ?						;+40
  union												;+44
     struct
        dmOrientation dw ?
        dmPaperSize dw ?
        dmPaperLength dw ?
        dmPaperWidth dw ?
     ends
      dmPosition POINT
  ends
  dmScale           dw      ?						;52
  dmCopies          dw      ?						;+54
  dmDefaultSource   dw      ?						;56
  dmPrintQuality    dw      ?						;58
  dmColor           dw      ?						;60
  dmDuplex          dw      ?						;62
  dmYResolution     dw      ?						;64
  dmTTOption        dw      ?						;66
  dmCollate         dw      ?						;+68
  dmFormName        db CCHFORMNAME dup (?)
  dmLogPixels       dw      ?
  dmBitsPerPel      dd      ?
  dmPelsWidth       dd      ?
  dmPelsHeight      dd      ?
  dmDisplayFlags    dd      ?
  dmDisplayFrequency  dd      ?
  dmICMMethod       dd ?
  dmICMIntent       dd ?
  dmMediaType       dd ?
  dmDitherType      dd ?
  dmReserved1       dd ?
  dmReserved2       dd ?
DEVMODE	ends

DEVMODE.dmFields		fix dword [edx+40]
DEVMODE.dmOrientation	fix word [edx+44]
DEVMODE.dmCopies		fix word [edx+54]
DEVMODE.dmCollate		fix word [edx+68]

;Equtes
LandScape			equ	0
Portrait			equ	1
PrintRep			equ	0
BASE_DPI			equ	1440
ES_SAVESEL			equ 00008000h
DM_COLLATE			equ 8000h
DMCOLLATE_TRUE		equ 1
DM_COPY				equ 2
DM_COPIES			equ 100h
DM_OUT_BUFFER		equ DM_COPY
DM_ORIENTATION		equ 1h
DMORIENT_LANDSCAPE	equ 2
DM_MODIFY			equ 8
DM_IN_BUFFER		equ DM_MODIFY

LOGPIXELSX			equ 88
LOGPIXELSY			equ 90

PHYSICALWIDTH		equ 110
PHYSICALHEIGHT		equ 111
PHYSICALOFFSETX		equ 112
PHYSICALOFFSETY		equ 113

HORZRES				equ 8
VERTRES				equ 10

EM_STREAMIN			equ WM_USER + 73
EM_FORMATRANGE		equ WM_USER + 57
EM_FINDTEXTEX		equ WM_USER + 79
EM_GETTEXTLENGTHEX	equ WM_USER + 95

SF_RTF				equ 0002h
GTL_PRECISE			equ 2
CP_ACP				equ 0


align 16
PrintRTF	proc	pFileName:DWORD, bLandOrPor:DWORD, PrintViewPrompt:DWORD, NumCopies:DWORD
;Designed to print an RTF file using pFileName: pointer to filename string and 
;	bLandOrPor: binary Landscape(0) or Portrait(1)
;Richedit window created as child of main window
;Default Printer Info obtained and modified if necessary
;File printed with page breaks simulated!
	local wc:WNDCLASSEX
	local msg:MSG
	local hwnd:DWORD

	m2m		[RTFHandle], [pFileName]
	m2m		[bLOrP], [bLandOrPor]
	m2m		[NumOfCopies], [NumCopies]

	mov		[wc.cbSize], sizeof.WNDCLASSEX
	mov		[wc.style], CS_HREDRAW or CS_VREDRAW
	mov		[wc.lpfnWndProc], REProc
	mov		[wc.cbClsExtra], NULL
	mov 	[wc.cbWndExtra], NULL
	push 	[gIst]
	pop		[wc.hInstance]
	mov		[wc.hbrBackground], COLOR_BTNFACE + 1
	mov		[wc.lpszMenuName], NULL
	mov		[wc.lpszClassName], REClassName
	
	invoke	LoadIcon, NULL, IDI_APPLICATION
	mov		[wc.hIcon], eax
	mov		[wc.hIconSm], eax
	
	invoke	LoadCursor, NULL, IDC_ARROW
	mov		[wc.hCursor], eax
	
	invoke	RegisterClassEx, addr wc
	invoke	CreateWindowEx, NULL, REClassName, REAppName,\
			WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,\
			CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,\
			[gIst], NULL
	mov		[hwnd], eax
	invoke	ShowWindow, [hwnd], SW_SHOWMAXIMIZED
	invoke	UpdateWindow, [hwnd]

	invoke	LoadLibrary, szRichLib32
	mov		[hLibRE], eax
	or		eax, eax
	jnz		@F
step_back:
	invoke	LoadLibrary, szRichLib20
	mov		[hLibRE], eax
	invoke	CreateWindowEx, WS_EX_CLIENTEDGE, szEditClass20, NULL, \
			WS_MAXIMIZE or WS_CHILDWINDOW or ES_MULTILINE or \
			ES_SAVESEL or WS_VSCROLL or WS_HSCROLL or ES_AUTOHSCROLL or \
			ES_AUTOVSCROLL or ES_NOHIDESEL,\
			0, 0, CW_USEDEFAULT, CW_USEDEFAULT, [hwnd], NULL, [gIst], NULL
	jmp		save_edHandle
@@:
	invoke	CreateWindowEx, WS_EX_CLIENTEDGE, szEditClass32, NULL, \
			WS_MAXIMIZE or WS_CHILDWINDOW or ES_MULTILINE or \
			ES_SAVESEL or WS_VSCROLL or WS_HSCROLL or ES_AUTOHSCROLL or \
			ES_AUTOVSCROLL or ES_NOHIDESEL,\
			0, 0, CW_USEDEFAULT, CW_USEDEFAULT, [hwnd], NULL, [gIst],NULL
	test	eax, eax
	jz		step_back
save_edHandle:
	mov		[hWndEdit], eax	    

	invoke	SetFocus, [hWndEdit]
	invoke	ShowWindow, [hWndEdit], SW_SHOWMAXIMIZED

	.while TRUE
		invoke	GetMessage, addr msg, NULL, 0, 0
		.if eax, e, 0
			jmp	@f
		.endif
		invoke	TranslateMessage, addr msg
		invoke	DispatchMessage, addr msg
	.endw

@@:	
	ret

PrintRTF endp

align 16
REProc proc uses esi, hWin, uMsg, wParam, lParam
local	rtf_len:DWORD
	.if	[uMsg], e, WM_DESTROY
		invoke	PostQuitMessage, NULL
	.elseif [uMsg], e, WM_CREATE
		invoke	SetTimer, [hWin], 4321, 100, NULL
	.elseif [uMsg], e, WM_TIMER
;int 3
		invoke	KillTimer, [hWin], 4321
		call	GetPrinterInfo
		call	GetPageInfo
		call	ChangeBP
		call	DisplayRTFFile
		call	PrintFile
		call	UnChangeBP
	.elseif	[uMsg], e, WM_SIZE
		mov		eax, [lParam]
		mov 	edx, eax
		and 	eax, 0ffffh
		shr 	edx, 16
		invoke	MoveWindow, [hWndEdit], 0, 26, eax, edx, TRUE
	.else
		invoke	DefWindowProc, [hWin], [uMsg], [wParam], [lParam]		
		jmp		.dir_out
	.endif
	
	xor eax,eax
.dir_out:
	ret
REProc endp

align 16
StreamInProc proc uses edi, HFile, pBuffer, NumBytes, pBytesRead

	invoke	ReadFile, [HFile], [pBuffer], [NumBytes], [pBytesRead], 0

	xor		eax,1
	ret
StreamInProc endp

align 16
GetPrinterInfo	proc
;Get Library and routines for the printer functions
	invoke	LoadLibrary, szWinSpoolDRV		;Win9x
	mov		[hSpoolLib], eax
	or		eax, eax 
	jnz		@F
	invoke	LoadLibrary, szWinSpoolDLL		;NT
	mov		[hSpoolLib], eax
@@: 
	invoke	GetProcAddress, [hSpoolLib], szOpenPrinterA 
	mov		[pOpenPrinterA], eax
	invoke	GetProcAddress, [hSpoolLib], szClosePrinter 
	mov		[pClosePrinter], eax
	invoke	GetProcAddress, [hSpoolLib], szDocumentProperties 
	mov		[pDocumentProperties], eax
;Get default printer info
	invoke	GetProfileString, _windows, _Device, _Blank, \
			pPrintInfo, sizeof.pPrintInfo
	lea		esi, [pPrintInfo]
	dec		esi
check_com:
	inc		esi
	cmp		byte [esi], ','
	jnz		check_com
	mov		byte [esi], 0
	inc		esi
	mov		[pPrintDriver], esi
	dec		esi
get_driver:
	inc		esi
	cmp		byte [esi], ','
	jnz		get_driver
	mov		byte [esi], 0
	inc		esi
	mov		[pPrintPort], esi

;OpenPrinter
	push	NULL
	push	hPrinter
	push	pPrintInfo
	call	[pOpenPrinterA]						;Open printer

	push	0
	push	NULL
	push	NULL
	push	pPrintInfo
	push	[hPrinter]
	push	[hLibRE]
	call	[pDocumentProperties]				;Get size of DEVMODE struc

	invoke	GlobalAlloc, GMEM_MOVEABLE, eax	;Allocate moveable memory for DEVMODE
	mov		[hDevmodeOut], eax				;Save handle
	invoke	GlobalLock, eax
	mov		[pDevmodeOut], eax

	push	DM_OUT_BUFFER
	push	NULL
	push	[pDevmodeOut]
	push	pPrintInfo
	push	[hPrinter]
	push	[hLibRE]
	call	[pDocumentProperties]

	mov		[set_props], 0
	.if	[bLOrP], e, 0						;Landscape mode
		mov		edx, [pDevmodeOut]
		or		DEVMODE.dmFields, DM_ORIENTATION
		mov		DEVMODE.dmOrientation, DMORIENT_LANDSCAPE
		mov		edx, [pDevmodeOut]
		movzx	eax, DEVMODE.dmOrientation
		mov		[set_props], 1
	.endif
	.if	[NumOfCopies], a, 1
		mov		edx, [pDevmodeOut]
		or		DEVMODE.dmFields, DM_COPIES
		mov		DEVMODE.dmCopies, 2
		or		DEVMODE.dmFields, DM_COLLATE
		mov		DEVMODE.dmCollate, DMCOLLATE_TRUE
		mov		[set_props], 1
	.endif
	.if	[set_props], ne, 0
		push	DM_OUT_BUFFER or DM_IN_BUFFER
		push	[pDevmodeOut]
		push	[pDevmodeOut]
		push	pPrintInfo
		push	[hPrinter]
		push	[hLibRE]
		call	[pDocumentProperties]
	.endif
	invoke	CreateDC, [pPrintDriver], pPrintInfo, NULL, [pDevmodeOut]
	mov		[dcPrint], eax
;ClosePrinter
	push	[hPrinter]
	call	[pClosePrinter]

	invoke	GlobalUnlock, [pDevmodeOut]
	invoke	GlobalFree, [hDevmodeOut]
	
	ret

GetPrinterInfo endp

align 16
GetPageInfo	proc
;To modify RichEdit Window to match Printer we need:
;	LineWidth = LeftMargin - RightMargin
;	LeftMargin = LeftMarginWidth - LeftOffset	=	.5" - 
local	dpix	:DWORD
local	dpiy	:DWORD
local	var		:DWORD
local	paper	:POINT 
local	margin	:RECT  
local	minmargin	:RECT

	mov		[m_psd.rtMargin.left], 500       ; 1.00 дюйма
	mov		[m_psd.rtMargin.right], 500      ; 1.00 дюйма
	mov		[m_psd.rtMargin.top], 500         ; 0.75 дюйм
	mov		[m_psd.rtMargin.bottom], 500      ; 0.75 дюйм

	invoke	GetDeviceCaps, [dcPrint], LOGPIXELSX
	mov		[dpix], eax
	invoke	GetDeviceCaps, [dcPrint], LOGPIXELSY
	mov		[dpiy], eax

	invoke	GetDeviceCaps, [dcPrint], PHYSICALWIDTH
	stdcall	IntMul, eax, 1000
	stdcall	IntDiv, eax, [dpix]   
	mov		[m_psd.ptPaperSize.x], eax

	invoke	GetDeviceCaps, [dcPrint], PHYSICALHEIGHT
	stdcall	IntMul, eax, 1000       
	stdcall	IntDiv, eax, [dpiy]   
	mov		[m_psd.ptPaperSize.y], eax

	invoke	GetDeviceCaps, [dcPrint], PHYSICALOFFSETX
	stdcall	IntMul, eax, 1000
	stdcall	IntDiv, eax, [dpix]   
	mov		[m_psd.rtMinMargin.left], eax

	invoke	GetDeviceCaps, [dcPrint], PHYSICALOFFSETY
	stdcall	IntMul, eax, 1000
	stdcall	IntDiv, eax, [dpiy]   
	mov		[m_psd.rtMinMargin.top], eax

	invoke	GetDeviceCaps, [dcPrint], HORZRES
	stdcall	IntMul, eax, 1000
	stdcall	IntDiv, eax, [dpix]    

	m2m		[var], [m_psd.ptPaperSize.x]    ; m_psd.rtMinMargin.right = ebx - edx - eax
	mov		edx, [m_psd.rtMinMargin.left]

	sub		[var], edx
	sub		[var], eax
	m2m		[m_psd.rtMinMargin.right], [var]

	invoke	GetDeviceCaps, [dcPrint], VERTRES
	stdcall	IntMul, eax, 1000
	stdcall	IntDiv, eax, [dpiy]    

	m2m		[var], [m_psd.ptPaperSize.y]    ; m_psd.rtMinMargin.bottom = ebx - edx - eax
	mov		edx, [m_psd.rtMinMargin.top]

	sub		[var], edx
	sub		[var], eax   

	m2m		[m_psd.rtMinMargin.bottom], [var]
    m2m		[paper.x], [m_psd.ptPaperSize.x]    
    m2m		[paper.y], [m_psd.ptPaperSize.y]       

    invoke	CopyRect, addr margin, m_psd.rtMargin
    invoke	CopyRect, addr minmargin, m_psd.rtMinMargin

    mov		eax, [paper.x]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000
    mov		[m_Paper.x], eax
    
    mov		eax, [paper.y]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_Paper.y], eax
    
    mov		eax, [margin.left]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_Margin.left], eax
 
    mov		eax, [margin.right]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_Margin.right], eax
    
    mov		eax, [margin.top]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_Margin.top], eax
 
    mov		eax, [margin.bottom]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_Margin.bottom], eax
    
    mov		eax, [minmargin.left]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_MinMargin.left], eax
 
    mov		eax, [minmargin.right]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_MinMargin.right], eax
    
    mov		eax, [minmargin.top]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_MinMargin.top], eax
 
    mov		eax, [minmargin.bottom]
    stdcall	IntMul, eax, BASE_DPI   
    stdcall	IntDiv, eax, 1000    
    mov		[m_MinMargin.bottom], eax        
	
	ret

GetPageInfo endp

align 16
DisplayRTFFile	proc
local	FSize:DWORD
;Stream RTF File into RichEdit Window
	invoke	CreateFile, [RTFHandle], \
			GENERIC_READ, FILE_SHARE_READ, NULL,\
			OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL
	mov		[hFile], eax
	mov		[editstream.dwCookie], eax
	mov		[editstream.pfnCallback], StreamInProc
	invoke	GetFileSize, [hFile], NULL
	shl		eax, 1
	mov		[FSize], eax

	invoke	SendMessage, [hWndEdit], EM_LIMITTEXT, addr FSize, 0
	invoke	SendMessage, [hWndEdit], EM_STREAMIN, SF_RTF, editstream
	invoke	SendMessage, [hWndEdit], EM_SETMODIFY, FALSE, 0
	invoke	CloseHandle, [hFile]

	ret
DisplayRTFFile	endp

align 16
FormatScreenLikePrinter	proc
;Calculate Line Width to make screen text display show like printer output
;		m_psd.rtMinMargin.left = LeftOffset
;		500 = LeftMarginWidth 0.5"
;		500 = RightMarginWidth 0.5"
;		LeftMargin = LeftMarginWidth - LeftOffset
;		RightMargin = (Printer.Width - RightMarginWidth) - LeftOffset
;Calculate the line width
;LineWidth = RightMargin - LeftMargin
;			 Printer.Width - RightMarginWidth - LeftMarginWidth
		mov		eax, [m_psd.ptPaperSize.x]	;Printer.Width

		sub		eax, 500					;RightMarginWidth
		sub		eax, 500					;LeftMarginWidth

		invoke	SendMessage, [hWndEdit], EM_SETTARGETDEVICE, [dcPrint], eax

	ret
FormatScreenLikePrinter	endp

align 16
PrintFile	proc
local	temp_FR:FORMATRANGE
;Clear EM_FORMATRANGE process
	ClearFR
	Clearft
	invoke	SendMessage, [hWndEdit], EM_FORMATRANGE, 0, 0

;Setup FR FORMATRANGE structure
	m2m		[FR.hdc], [dcPrint]			;format for the printer
	m2m		[FR.hdcTarget], [dcPrint]

	m2m		[FR.rc.left], [m_Margin.left]

	m2m		[FR.rc.top], [m_Margin.top]

	mov		eax, [m_Paper.x]
	sub		eax, [m_Margin.right]
	mov		[FR.rc.right], eax

	mov		eax, [m_Paper.y]
	sub		eax, [m_Margin.bottom]
	mov		[FR.rc.bottom], eax

	mov		[FR.rcPage.left], 0
	mov		[FR.rcPage.top], 0
	m2m		[FR.rcPage.right], [m_Paper.x]
	m2m		[FR.rcPage.bottom], [m_Paper.y]

;Save page dimensions to temp file
	m2m		[temp_FR.rcPage.left], [FR.rcPage.left]
	m2m		[temp_FR.rcPage.top], [FR.rcPage.top]
	m2m		[temp_FR.rcPage.right], [FR.rcPage.right]
	m2m		[temp_FR.rcPage.bottom], [FR.rcPage.bottom]
	m2m		[temp_FR.rc.left], [FR.rc.left]
	m2m		[temp_FR.rc.top], [FR.rc.top]
	m2m		[temp_FR.rc.right], [FR.rc.right]
	m2m		[temp_FR.rc.bottom], [FR.rc.bottom]
;Setup EM_GETTEXTLENGTH structure
	mov		[gtl.flags], GTL_PRECISE
	mov		[gtl.codepage], CP_ACP
	invoke	SendMessage, [hWndEdit], EM_GETTEXTLENGTHEX, gtl, 0
	mov		[rtf_length], eax
;PrintDec rtf_length
	mov		[FR.chrg.cpMin], 0		;Format from beginning of RichEdit content
	mov		[FR.chrg.cpMax], -1		;Format to end of content
	mov		[ft.chrg.cpMin], 0		;Beginning range of EM_FINDTEXTEX, start at beginning
	m2m		[ft.chrg.cpMax], -1		;FINDTEXT to end of content
;Text EM_FINDTEXTEX will search for
	mov		[ft.lpstrText], j_page_break
;Zero out EM_FINDTEXTEX results
	mov		[ft.chrgText.cpMin], 0
	mov		[ft.chrgText.cpMax], 0

	mov		[DOC.cbSize], sizeof.DOCINFO
	mov		[DOC.lpszDocName], _DocTitle
	mov		[DOC.lpszOutput], NULL
	mov		[DOC.lpszDatatype], NULL
	mov		[DOC.fwType], NULL


	invoke	StartDoc, [dcPrint], DOC
	invoke	StartPage, [dcPrint]
	invoke	SendMessage, [hWndEdit], EM_FINDTEXTEX, FR_DOWN, ft		;try to find first page break
	.if	eax, e, -1													;no page break found
		mov		[FR.chrg.cpMin], 0									;start at beginning of content
		mov		[FR.chrg.cpMax], -1									;process to end of content
		invoke	SendMessage, [hWndEdit], EM_FORMATRANGE, TRUE, FR	;first page
		RestoreFR
		mov		[FR.chrg.cpMin], eax									;prepare for next page
		mov		[FR.chrg.cpMax], -1
		.while	eax, b, [rtf_length]									;more pages to process
			invoke	EndPage, [dcPrint]
			invoke	StartPage, [dcPrint]
			invoke	SendMessage, [hWndEdit], EM_FORMATRANGE, TRUE, FR
			RestoreFR
			mov		[FR.chrg.cpMin], eax								;prepare for next page
			mov		[FR.chrg.cpMax], -1								;process to end of content
		.endw
		invoke	EndPage, [dcPrint]
	.else															;process page breaks
;int 3
		mov		[FR.chrg.cpMin], 0									;start at beginning of content
		m2m		[FR.chrg.cpMax], [ft.chrgText.cpMin]				;process to beginning of found text
		invoke	SendMessage, [hWndEdit], EM_FORMATRANGE, TRUE, FR	;process first page
		RestoreFR
		.while	eax, b, [rtf_length]									;more content to process
;Excessive Content of first page may cause page break to fall over to following page
			.while	eax, b, [FR.chrg.cpMax]							;page break not on previous EM_FORMATed page
				mov		[FR.chrg.cpMin], eax						;start next page right after last page
				m2m		[FR.chrg.cpMax], [ft.chrgText.cpMin]		;process to beginning of found text
				invoke	EndPage, [dcPrint]
				invoke	StartPage, [dcPrint]
				invoke	SendMessage, [hWndEdit], EM_FORMATRANGE, TRUE, FR
				RestoreFR
;Print content until we reach the next page break
			.endw
			invoke	EndPage, [dcPrint]
			invoke	StartPage, [dcPrint]
;Print content after page break, first check if there is another  page break, if not format the rest
			m2m	[FR.chrg.cpMin], [ft.chrgText.cpMax]					;start next page after last char of found text
			m2m	[ft.chrg.cpMin], [ft.chrgText.cpMax]					;start next search after last char of found text
			mov [ft.chrg.cpMax], -1										;search to end of content
			mov	[ft.chrgText.cpMin], 0
			mov	[ft.chrgText.cpMax], 0
			invoke	SendMessage, [hWndEdit], EM_FINDTEXTEX, FR_DOWN, ft		;try to find page break
			.if	eax, e, -1													;no more page breaks
				m2m		[FR.chrg.cpMax], -1
				mov		eax, [FR.chrg.cpMin]
				.while	eax, b, [rtf_length]									;more pages to process
					invoke	SendMessage, [hWndEdit], EM_FORMATRANGE, TRUE, FR
					RestoreFR
					push	eax
					invoke	EndPage, [dcPrint]
					pop		eax
					.if	eax, b, [rtf_length]
						invoke	StartPage, [dcPrint]
						mov		[FR.chrg.cpMin], eax							;prepare for next page
						mov		[FR.chrg.cpMax], -1								;process to end of content
					.endif
				.endw
			.else									;prepare for next page break
				m2m		[FR.chrg.cpMax], [ft.chrgText.cpMin]					;process to beginning of found text
				invoke	SendMessage, [hWndEdit], EM_FORMATRANGE, TRUE, FR
				RestoreFR
			.endif
		.endw
		invoke	EndPage, [dcPrint]
	.endif
	
	invoke	EndDoc, [dcPrint]
	invoke	SendMessage, [hWndEdit], EM_FORMATRANGE, 0, 0
	invoke	DeleteDC, [dcPrint]
		
;ClosePrinter
	push	[hPrinter]
	call	[pClosePrinter]
	invoke	GlobalUnlock, [pDevmodeOut]
	invoke	GlobalFree, [hDevmodeOut]

	ret

PrintFile endp

align 16
ChangeBP	proc uses ebx edi esi
	invoke	CreateFile, [RTFHandle], \
			GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ, NULL,\
			OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL

	mov		[hFile], eax
	invoke	GetFileSize, [hFile], NULL
	mov		[rtf_length], eax

	invoke	GlobalAlloc, GMEM_MOVEABLE, eax
	mov		[tempH], eax

	invoke	GlobalLock, eax
	mov		[tempP], eax

	invoke	ReadFile, [hFile], [tempP], [rtf_length], NumRtfBytes, 0

	mov		ecx, [NumRtfBytes]
	mov		edi, [tempP]
	mov		esi, 0
	mov		ebx, 0
;	mov		eax, 'gap\'				;correct in MASM
	mov		eax, '\pag'
.FindBS:
	cmp		dword [edi], eax
	je		.got_pb
.check_a:
	inc		edi
	inc		esi
	dec		ecx
	je		.got_pb
	jmp		.FindBS
.got_pb:
	.if	ecx, ne, 0					;not done processing for page breaks
		mov	[pbPointers + ebx], esi
		mov	byte [edi], '*'

		add	ebx, 4
		add	edi, 5
		add esi, 5
		sub	ecx, 5
		je	.done_pb
		jmp	.FindBS
	.endif

.done_pb:
	invoke	SetFilePointer, [hFile], 0, 0, FILE_BEGIN

	invoke	WriteFile, [hFile], [tempP], [NumRtfBytes], NumRtfBytes, 0

	invoke	CloseHandle, [hFile]
	invoke	GlobalUnlock, [tempH]
	invoke	GlobalFree, [tempH]

	ret

ChangeBP endp

align 16
UnChangeBP	proc uses edi esi

	invoke	CreateFile, [RTFHandle], \
			GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ, NULL,\
			OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL
	mov		[hFile], eax
	invoke	GetFileSize, [hFile], NULL
	mov		[rtf_length], eax

	invoke	GlobalAlloc, GMEM_MOVEABLE, eax
	mov		[tempH], eax

	invoke	GlobalLock, eax
	mov		[tempP], eax

	invoke	ReadFile, [hFile], [tempP], [rtf_length], NumRtfBytes, 0

	mov		ecx, [NumRtfBytes]
	mov		edi, [tempP]
	mov		esi, 0
;	mov		eax, 'gap*'				;correct in MASM
	mov		eax, '*pag'
.FindBS:
	cmp		dword [edi], eax
	je		.got_pb
.check_a:
	inc		edi
	inc		esi
	dec		ecx
	je		.got_pb
	jmp		.FindBS
.got_pb:
	.if	ecx, ne, 0					;not done processing for page breaks
		mov	byte [edi], '\'
		add	edi, 5
		add esi, 5
		sub	ecx, 5
		je	.done_pb
		jmp	.FindBS
	.endif
.done_pb:
	invoke	SetFilePointer, [hFile], 0, 0, FILE_BEGIN

	invoke	WriteFile, [hFile], [tempP], [NumRtfBytes], NumRtfBytes, 0

	invoke	CloseHandle, [hFile]
	invoke	GlobalUnlock, [tempH]
	invoke	GlobalFree, [tempH]

	ret

UnChangeBP endp
