*******************************************************************************
*
* Print Record Spy
*
* (C)  Copyright Apple Computer, Inc. 1988-1990
* All rights reserved.
*
* Developer Technical Support Apple II Sample Code
*
* by Keith Rollin
* based on a story by Scott 'ZZ' Zimmerman
*
* This program lets the avid and interested user examine the various
* fields of the Print Record used by the Print Manager.  Menu items let you
* call Print Manager routines, and this program will display the values from
* the resulting print record in a window. It also keeps track of past values
* of the print record, and notes the fields that have changed by displaying
* them in Boldface. A second window displays the past values so you can
* compare them with the changed values side by side.
*
*******************************************************************************
	eject
	
**********************************************************************
*                                                                    *
*     This program and its derivatives are licensed only for         *
*     use on Apple computers.                                        *
*                                                                    *
*     Works based on this program must contain and                   *
*     conspicuously display this notice.                             *
*                                                                    *
*     This software is provided for your evaluation and to           *
*     assist you in developing software for the Apple IIGS           *
*     computer.                                                      *
*                                                                    *
*     DISCLAIMER OF WARRANTY                                         *
*                                                                    *
*     THE SOFTWARE IS PROVIDED "AS IS" WITHOUT                       *
*     WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,               *
*     WITH RESPECT TO ITS MERCHANTABILITY OR ITS FITNESS             *
*     FOR ANY PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO             *
*     THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH            *
*     YOU.  SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU (AND            *
*     NOT APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE)               *
*     ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING,             *
*     REPAIR OR CORRECTION.                                          *
*                                                                    *
*     Apple does not warrant that the functions                      *
*     contained in the Software will meet your requirements          *
*     or that the operation of the Software will be                  *
*     uninterrupted or error free or that defects in the             *
*     Software will be corrected.                                    *
*                                                                    *
*     SOME STATES DO NOT ALLOW THE EXCLUSION                         *
*     OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY              *
*     NOT APPLY TO YOU.  THIS WARRANTY GIVES YOU SPECIFIC            *
*     LEGAL RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS                *
*     WHICH VARY FROM STATE TO STATE.                                *
*                                                                    *
*                                                                    *
**********************************************************************
	eject
	
	case   on
	PRINT  NOGEN,NOHDR
	STRING ASIS

	PRINT PUSH,OFF
	INCLUDE 'M16.Util'
	INCLUDE 'M16.ProDOS'
	INCLUDE 'M16.MiscTool'
	INCLUDE 'M16.QUICKDRAW'
	INCLUDE 'M16.QDAux'
	INCLUDE 'E16.Quickdraw'
	INCLUDE 'M16.MEMORY'
	INCLUDE 'E16.Memory'
	INCLUDE 'M16.EVENT'
	INCLUDE 'M16.LOCATOR'
	INCLUDE 'M16.Menu'
	INCLUDE 'M16.Control'
	INCLUDE 'M16.Window'
	INCLUDE 'E16.Window'
	INCLUDE 'M16.Dialog'
	INCLUDE 'E16.Dialog'
	INCLUDE 'M16.LineEdit'
	INCLUDE 'M16.IntMath'
	INCLUDE 'M16.Scrap'
	INCLUDE 'M16.Desk'
	INCLUDE 'M16.font'
	INCLUDE 'M16.LIST'
	INCLUDE 'M16.Texttool'
	INCLUDE 'M16.Print'
	INCLUDE 'E16.Print'
	PRINT POP

*******************************************************************************
*
*    Equates used in this program.
*
*******************************************************************************
DPHandle	equ 0	; Handle to Tool Direct Page area
DPPointer	equ DPHandle+4	; Pointer to Tool Direct Page area
deref	equ DPPointer+4	; Temprary Handle dereference area
Temp1	equ deref+4
Temp2	equ Temp1+4

ScreenMode	equ mode640
ScreenWidth	equ 640


	EJECT
*******************************************************************************
*
Main	PROC
*
* Description:	This is the main routine. It calls routines to Initialize
*	the tools, initialize application specific data, run the
*	main EventLoop, close the application, and close the tools.
*	Then it calls the ProDOS Quit command.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:
	import InitTools
	import InitApp
	import EventLoop
	import CloseApp
	import CloseTools
	import QuitParms
*
* Entry Points:	NONE
*
*******************************************************************************

	jsr InitTools
	jsr InitApp

	_ShowCursor

	jsr EventLoop
	jsr CloseApp
	jsr CloseTools

	_Quit QuitParms

	ENDP

	EJECT
*******************************************************************************
*
Globals	Record
*
* Description:	Holder of all of our data.
*
*
* Inputs:	N/A
*
* Outputs:	N/A
*
* External Refs:
	import PrUpdate
	import PrOldUpdate
*
* Entry Points:
	export QuitParms	; used by Main
*
*******************************************************************************
*
* Standard global data
*
*******************************************************************************

TitleString	str 'Print Record Spy - Shows effects of Print Manager calls'
AutString	str 'By Keith Rollin Apple DTS -- Version: 3.0'
VersString	str 'Copyright (c) 1988-1990 Apple Computer'

MenuHeight	ds.B 2	; Stored height of menu bar
MyID	ds.B 2	; Application ID
MyDP	ds.B 2	; My direct page storage

QuitFlag	ds.W 1
QuitParms	dc.L 0	; Pathname of next app
	dc.W $00	; flags

EventRecord
EventWhat	ds.B 2
EventMessage	ds.B 4
EventWhen	ds.B 4
EventWhere	ds.B 4
EventModifiers	ds.B 2
TaskData	ds.B 4
TaskMask	dC.L $0000FFFF

	EJECT
*******************************************************************************
*
* Application specific global data
*
*******************************************************************************

; This is a list of pointers to the text that is used to create our menus. It
; is used by InitApp to find all of the menu templates and use them to create
; our menubar. This loop loads MenuPtrLen-4 into an index, gets the
; corresponding menu template pointer in this table, and uses that in a
; NewMenu call. It then decrements the index by 4, and repeats the procees
; until the index is negative.

MenuPtr	dc.l AppMenu
	dc.l FileMenu
	dc.l EditMenu
MenuPtrLen	equ *-MenuPtr


; Menu list: menu items should be numbered consecutivly starting from 250.
; As a convention, use 256 as about and 257 as Quit.

AppMenu	dc.B '$$@\XN1',$0D
	dc.B '--About Print Record Spy...\VN256',$0D
	dc.B '.'
FileMenu	dc.B '$$  File  \N2',$0D
	dc.B '--Choose Printer\N258',$00
	dc.B '--Page Setup\N259',$00
	dc.B '--Job Dialog\N260',$00
	dc.B '--PrDefault\N261',$00
	dc.B '--PrValidate\VN262',$00
	dc.B '--Quit\N257*Qq',$0D
	dc.B '.'
EditMenu	dc.B '$$  Edit  \N3',$00
	dc.B '--Undo\N250*ZzVD',$00
	dc.B '--Cut\N251*XxD',$00
	dc.B '--Copy\N252*CcD',$00
	dc.B '--Paste\N253*VvD',$00
	dc.B '--Clear\N254D',$00
	dc.b '.'

;
; Parameters lists for my two windows
;
wTitle1	str '  Current Settings  '
MyWindow	dc.W WindEnd-MyWindow ; size of paramBlock
	dc.W fVis+fTitle+fBScroll+fRScroll+fGrow+fMove+fZoom
	dc.L wTitle1	; no title bar, no title...
	dc.L 0	; RefCon
	dc.W 30,60,185,580	; zoomed rect
	dc.L 0	; color table = default
	dc.W 0,0	; scroll bar XY origin
	dc.W 155,520	; scroll max.
	dc.W 155,520	; Max Height/Width.
	dc.W 40,40	; scroll values
	dc.W 0,0	; page values (default)
	dc.L 0	; no info bar RefCon
	dc.W 0	; info bar height (none)
	dc.L 0	; Frame defproc, NIL=standard
	dc.L 0	; no info bar def proc
	dc.L PrUpdate	; auto updates
	dc.W 30,10,185,290	; bounds rect.
	dc.L $FFFFFFFF	; plane= on top.
	dc.L 0	; NIL storage pointer
WindEnd	equ *

wTitle2	str '  Previous Settings  '
MyWindow2	dc.W WindEnd2-MyWindow2 ; size of paramBlock
	dc.W fVis+fTitle+fBScroll+fRScroll+fGrow+fMove+fZoom
	dc.L wTitle2	; no title bar, no title...
	dc.L 0	; RefCon
	dc.W 30,60,185,580	; zoomed rect
	dc.L 0	; color table = default
	dc.W 0,0	; scroll bar XY origin
	dc.W 155,520	; scroll max.
	dc.W 155,520	; Max Height/Width.
	dc.W 40,40	; scroll values
	dc.W 0,0	; page values (default).
	dc.L 0	; no info bar RefCon
	dc.W 0	; info bar height (none)
	dc.L 0	; Frame defproc, NIL=standard
	dc.L 0	; no info bar def proc
	dc.L PrOldUpdate	; auto updates
	dc.W 30,330,185,610	; bounds rect.
	dc.L $FFFFFFFF	; plane= on top.
	dc.L 0	; NIL storage pointer
WindEnd2	equ *


WindPointer	ds.B 4
WindPointer2	ds.B 4

BigRect	dc.w 0,0,200,640
PrintRecord	ds.b 4
OldRecord	ds.b 4
PrinterPort	ds.b 4


; Big hunkin' chunk of data that I use to print the strings. These are
; their X/Y coordinates.

Position	dc.w 10,10	; Print Record
	dc.w 270,10	; Printer Information
	dc.w 270,70	; Job SubRecord
	dc.w 10,80	; Style SubRecord
	dc.w 20,20	; prVersion
	dc.w 20,30	; prInfo
	dc.w 20,40	; rPaper
	dc.w 20,50	; prStl
	dc.w 20,60	; prJob
	dc.w 280,20	; iDev
	dc.w 280,30	; iVRes
	dc.w 280,40	; iHRes
	dc.w 280,50	; rPage
	dc.w 20,90	; wDev
	dc.w 20,100	; feed
	dc.w 20,110	; paperType
	dc.w 20,120	; crWidth/vSizing
	dc.w 20,130	; reduction
	dc.w 280,80	; iFstPage
	dc.w 280,90	; iLstPage
	dc.w 280,100	; iCopies
	dc.w 280,110	; bJDocLoop
	dc.w 280,120	; pIdleProc
	dc.w 280,130	; pFileName
	dc.w 280,140	; iFileVol
	dc.w 280,150	; bFileVers


; Big hunkin' chunk of data that I use to print the record's values.
; The Low word is the offset into the print record that I'm interested
; in. The high word contains the length of the field that I'm printing. If
; it's Zero, then no values get printed at all. For instance, some
; strings don't get any values printed after them.

ValueOffsets	dc.l $00000000	; Print Record
	dc.l $00000000	; Printer Information
	dc.l $00000000	; Job SubRecord
	dc.l $00000000	; Style SubRecord
	dc.l $00010000	; prVersion
	dc.l $00000000	; prInfo
	dc.l $00080010	; rPaper
	dc.l $00000000	; prStl
	dc.l $00000000	; prJob
	dc.l $00020002	; iDev
	dc.l $00020004	; iVRes
	dc.l $00020006	; iHRes
	dc.l $00080008	; rPage
	dc.l $00020018	; wDev
	dc.l $00020020	; feed
	dc.l $00020022	; paperType
	dc.l $00020024	; crWidth/vSizing
	dc.l $00020026	; reduction
	dc.l $00020050	; iFstPage
	dc.l $00020052	; iLstPage
	dc.l $00020054	; iCopies
	dc.l $00010056	; bJDocLoop
	dc.l $00040059	; pIdleProc
	dc.l $0004005D	; pFileName
	dc.l $00020051	; iFileVol
	dc.l $00010053	; bFileVers


; Table of pointers to all of my strings. A loop is used to go through
; this and print them all out.

TitleTable	dc.l Title1,Title2,Title3,Title4
	dc.l Title5,Title6,Title7,Title8
	dc.l Title9,Title10,Title11,Title12
	dc.l Title13,Title14,Title15,Title16
	dc.l Title17,Title18,Title19,Title20
	dc.l Title21,Title22,Title23,Title24
	dc.l Title25,Title26


; Da Strings! NOTE: Title17x is special cased in the window printing
; routine, so it isn't included in the above table.

Title1	str 'Print Record'
Title2	str 'Printer Information'
Title3	str 'Job SubRecord'
Title4	str 'Style SubRecord'
Title5	str 'prVersion = '
Title6	str 'prInfo = See Printer Information'
Title7	str 'rPaper = '
Title8	str 'prStl = See Style SubRecord'
Title9	str 'prJob = See Job SubRecord'
Title10	str 'iDev = '
Title11	str 'iVRes = '
Title12	str 'iHRes = '
Title13	str 'rPage = '
Title14	str 'wDev = '
Title15	str 'feed = '
Title16	str 'paperType = '
Title17	str 'crWidth = '
Title17x	str 'vSizing = '
Title18	str 'reduction = '
Title19	str 'iFstPage = '
Title20	str 'iLstPage = '
Title21	str 'iCopies = '
Title22	str 'bJDocLoop = '
Title23	str 'pIdleProc = '
Title24	str 'pFileName = '
Title25	str 'iFileVol = '
Title26	str 'bFileVers = '


ExtraString	ds.b 2

DriverChanged	str 'The Driver was changed.'
DriverDidntChange	str 'The Driver was not changed.'
Confirmed	str 'The OK Button was pressed.'
Canceled	str 'The Cancel Button was pressed.'
RecordChanged	str 'The Print Record changed.'
RecordNotChanged	str 'The Print Record didn''t change.'

	EndR

	INCLUDE 'Spy.stds.aii'

	EJECT
*******************************************************************************
*
InitApp	PROC
*
* Description:	Create my windows, and get two handles for print records
*	and initialize them.
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	stz QuitFlag

	pha	; Create the windows that will show
	pha	; the print records
	PushLong #MyWindow2
	_NewWindow
	PullLong WindPointer2

	pha	; space for result (window pointer)
	pha
	PushLong #MyWindow
	_NewWindow
	PullLong WindPointer

	PushLong WindPointer ; Set the port to one of them
	_SetPort

;
; Get a couple of handles to hold my print records
;
	pha	; space for result
	pha
	PushLong #140	; size of print record
	PushWord MyID	; put it to my name
	PushWord #attrLocked+attrNoCross
	PushLong #0	; address for attributes
	_NewHandle	; get the handle
	PullLong PrintRecord ; save the handle

	pha
	pha
	PushLong #140	; Size of print record
	PushWord MyID
	PushWord #attrLocked+attrNoCross
	PushLong #0
	_NewHandle
	PullLong OldRecord

;
; Finally, call the print manager to set default values in the
; print records
;
	PushLong PrintRecord
	_PrDefault

	PushLong OldRecord
	_PrDefault

	rts
	ENDP

	EJECT
*******************************************************************************
*
CloseApp	PROC
*
* Description:	Close down things. This disposes of all items and memory
*	that we allocated.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	PushLong PrintRecord
	_DisposeHandle

	PushLong OldRecord
	_DisposeHandle

	PushLong WindPointer
	_CloseWindow

	PushLong WindPointer2
	_CloseWindow

	rts
	ENDP

	EJECT
*******************************************************************************
*
EventLoop	PROC
*
* Description:	Main Event Loop. Handle things until user selects Quit.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:
	import MenuSelect
	import Ignore
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	pha	; Push on space for TaskMaster result
	PushWord #$FFFF	; GetNextEvent mask
	PushLong #EventRecord
	_TaskMaster

	pla	; Get TaskMaster result
	beq EventLoop	; Remove if you want to use null events
	asl A	; Turn it into an index
	tax
	jsr (TaskTable,x)	; Call appropriate event handler

	lda QuitFlag	; Quit selected?
	beq EventLoop	; no - keep looping

	rts	; yes- leave the program

TaskTable	dc.W Ignore	; 0 Null
	dc.W Ignore	; 1 MouseDown
	dc.W Ignore	; 2 MouseUp
	dc.W Ignore	; 3 KeyDown
	dc.W Ignore	; 4 undefined
	dc.W Ignore	; 5 AutoKey
	dc.W Ignore	; 6 Update
	dc.W Ignore	; 7 undefined
	dc.W Ignore	; 8 Activate
	dc.W Ignore	; 9 Switch
	dc.W Ignore	; 10 Desk accessory
	dc.W Ignore	; 11 Device driver
	dc.W Ignore	; 12 ap
	dc.W Ignore	; 13 ap
	dc.W Ignore	; 14 ap
	dc.W Ignore	; 15 ap
	dc.W Ignore	; TASK 0 indesk
	dc.W MenuSelect	; TASK 1 in menuBar
	dc.W Ignore	; TASK 2 in system window
	dc.W Ignore	; TASK 3 in content
	dc.W Ignore	; TASK 4 in Drag
	dc.W Ignore	; TASK 5 in grow
	dc.W Ignore	; TASK 6 in goaway
	dc.W Ignore	; TASK 7 in zoom
	dc.W Ignore	; TASK 8 in info bar
	dc.W Ignore	; TASK 9 in special	menu
	dc.W Ignore	; TASK 10 in NDA
	dc.W Ignore	; TASK 11 in frame
	dc.W Ignore	; TASK 12 in drop

	ENDP

	EJECT
*******************************************************************************
*
MenuSelect	PROC
*
* Description:	Menu item has been selected. Call the appropriate routine
*	and unhilite the menu when it is done. Before doing so,
*	however, a check is made to see if the routine being called
*	could possibly change the state of the Print Record. If it
*	can, a copy of the current print record is made. This way
*	we can see how the routine called changed the record.
*
* Inputs:	TaskData holds menu item selected.
*
* Outputs:	NONE
*
* External Refs:
	import Ignore
	import doAbout
	import doQuit
	import doPrChoose
	import doPrPgSetup
	import doPrJobDialog
	import doPrDefault
	import doPrValidate
	import ClearOldRecord
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	lda TaskData	; See if this call can change the
	cmp #258	; print record.
	bcc Dispatch	; No - it can't. Just call the routine.

	jsr ClearOldRecord	; Yes - so make a copy of it
Dispatch
	lda TaskData	; Fet the ID of the menu item selected.
	sec	; Turn it into an index.
	sbc #250
	asl a
	tax
	jsr (MenuTable,x)	; Call the routine behind it.

	PushWord #0	; Routine done - unhilite the menubar.
	lda TaskData+2
	pha
	_HiLiteMenu

	rts

MenuTable	dc.W Ignore	; undo
	dc.W Ignore	; cut
	dc.W Ignore	; copy
	dc.W Ignore	; paste
	dc.W Ignore	; clear
	dc.W Ignore	; close
	dc.W doAbout
	dc.W doQuit
	dc.W doPrChoose
	dc.W doPrPgSetup
	dc.W doPrJobDialog
	dc.w doPrDefault
	dc.w doPrValidate
	ENDP
	EJECT
*******************************************************************************
*
Ignore	PROC
*
* Description:	Called when I want to ignore an event.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************

	rts
	ENDP

	EJECT
*******************************************************************************
*
doQuit	PROC
*
* Description:	Quit routine. Set the QuitFlag to TRUE for the EventLoop.
*
*
* Inputs:	NONE
*
* Outputs:	QuitFlag set to $FFFF
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	lda #$FFFF
	sta QuitFlag
	rts
	ENDP

	EJECT
*******************************************************************************
*
doPrChoose	PROC
*
* Description:	Called by MenuSelect to call the routine to chooose a
*	printer. Also determine whether the print driver has
*	changed. When it is done, it calls ShowChanges to mark the
*	window as 'dirty', and prints a string to say whether or
*	not the driver has changed.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:
	import ShowChanges
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	pha	; Bring up the Choose Printer dialog
	_PrChoosePrinter

	jsr ShowChanges	; Show any changes (shouldn't be any)

	pla
	beq NotChanged

	lda #DriverChanged	; if TRUE then the driver changed
	bra done
NotChanged	lda #DriverDidntChange ; if FALSE, it didn't
done	sta ExtraString

	rts
	ENDP

	EJECT
*******************************************************************************
*
doPrPgSetup	PROC
*
* Description:	Called by MenuSelect to call the routine that does the page
*	setup. Also determines whether clicked on OK or not. When
*	it is done, it calls ShowChanges to mark the window as
*	'dirty', and prints a string to say whether or not the
*	user clicked on OK.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:
	import ShowChanges
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	pha	; bring up the dialog
	PushLong PrintRecord
	_PrStlDialog

	jsr ShowChanges	; show any changes

	pla
	beq CancelPressed

	lda #Confirmed	; TRUE:  pressed OK
	bra done
CancelPressed	lda #Canceled	; FALSE:  pressed Cancel
done	sta ExtraString

	rts
	ENDP

	EJECT
*******************************************************************************
*
doPrJobDialog	PROC
*
* Description:	Called by MenuSelect to call the routine that brings up the
*	dialog that asks how many copies, page range, etc. Also
*	indcates if the user presses Cancel or OK. When it is done,
*	it calls ShowChanges to mark the window as 'dirty', and
*	prints a string to say whether or not the user clicked on
*	OK.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:
	import ShowChanges
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	pha	; Bring up the Job Dialog
	PushLong PrintRecord
	_PrJobDialog

	jsr ShowChanges	; Show any changes

	pla
	beq CancelPressed

	lda #Confirmed	; TRUE, so pressed OK
	bra done
CancelPressed	lda #Canceled	; FALSE, so pressed Cancel
done	sta ExtraString

	rts
	ENDP

	EJECT
*******************************************************************************
*
doPrDefault	PROC
*
* Description:	Called by MenuSelect to ask the Print Driver to fill in
*	default values in the Print Record. This should be when an
*	application starts up and everytime the Print Driver is
*	changed (changing Printers does not automatically set up
*	correct values in the Print Record). When that is done,
*	ShowChanges is called to mark the window as 'dirty'.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:
	import ShowChanges
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	PushLong PrintRecord
	_PrDefault

	jsr ShowChanges

	stz ExtraString	; no extra string

	rts
	ENDP

	EJECT
*******************************************************************************
*
doPrValidate	PROC
*
* Description:	Called by MenuSelect to verify that there are correct
*	values in the Print record. If there are any that it
*	suspects, it will replace them with default values. Also,
*	PrValidate returns a boolean value to indicate if it
*	actually changed anything. ShowChanges is called to mark
*	the window as 'dirty', and a message is printed to say
*	whether or not anything was changed.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:
	import ShowChanges
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	pha	; Validate the record
	PushLong PrintRecord
	_PrValidate

	jsr ShowChanges	; Show the changes

	pla
	beq NoChange

	lda #RecordChanged	; TRUE, so yes it did change
	bra done
NoChange	lda #RecordNotChanged ;FALSE, so no nothing changed
done	sta ExtraString

	rts
	ENDP

	EJECT
*******************************************************************************
*
DerefIt	PROC
*
* Description:	Utility routine that dereferences and locks a handle.
*
*
* Inputs:	A = Handle low
*	X = Handle high
*
* Outputs:	A = Pointer Low
*	X = Pointer high
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with Globals

	sta deref	; Put our handle into a Direct Page
	stx deref+2	; location so we can use it as pointer.
	ldy #4	; Get the Handle flags.
	lda [deref],y
	ora #$8000	; Set the high bit to lock this handle.
	sta [deref],y	; Store it back
	dey	; Now get the Master Pointer
	dey
	lda [deref],y
	tax	; return High Word in X
	lda [deref]	; return Low Word in A
	rts
	ENDP

	EJECT
*******************************************************************************
*
PrUpdate	Proc
*
* Description:	Update routine for the Print Record window. Loop through 26
*	strings, see if there are any Print Record fields asso-
*	ciated with them, and print them and the values out. If the
*	values have changed since the last Print Manager call, then
*	boldface the string.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

; We are called from TaskMaster, with no guarantee as to the state of
; the data bank register or the direct page. Save off the ones that
; are passed to us, and set them up the way we like them.

	phd	; save the Direct Page
	phb	; save the Data Bank Register

	phk	; set the DBR to the program bank
	plb

	lda MyDP	; set the Direct Page to the main
	tcd	; application's Direct Page

	lda PrintRecord	; deref and lock the Print Record
	ldx PrintRecord+2
	jsr DerefIt
	sta Temp1
	stx Temp1+2

	lda OldRecord	; deref and lock the Previous P.R.
	ldx OldRecord+2
	jsr DerefIt
	sta Temp2
	stx Temp2+2

	ldx #4*25	; 4 times (number of strings - 1)
loop
	stx Index	; Save the index into memory

; Determine what this string represents (whether it identifies a field that
; has a changeable value or not) and find out if it did indeed change. If
; so, then set the fontface to BoldFace. If not, then set the fontface to
; plain.
	jsr SetFontStyle

; Find out where this string is supposed to go and move there.

	ldx Index
	PushWord Position,x
	PushWord Position+2,x
	_MoveTo

;
; Prepare to print the string. This is normally just a lookup into
; a table of string pointers to get the one we want. However, we need
; to special case the name of one field, which changes depending on
; whether or not we are using a LaserWriter.

	ldx Index
	cpx #4*16	; is the crWidth/vSizing one?
	bne doNormal	; no, so just draw it

	ldy #oprInfo+oiDev	; do we have a LaserWriter?
	lda [Temp1],y
	cmp #3
	bne doNormal	; yes, so use default string

	PushLong #Title17x	; no, so substitute in Special String
	bra DrawTitle	; now print it
doNormal
	PushLong TitleTable,x ; put on the normal string
DrawTitle
	_DrawString	; print the string

	jsr PrintValues	; print the field's values

; Now see if there is an extra message to print. If so, then do it.

	lda ExtraString	; is there one?
	beq EndLoop	; No, so skip over this next part.

	PushWord #20	; move to the right place
	PushWord #150
	_MoveTo

	phk	; create a high order word out of
	phk	; our program bank register.
	pla
	and #$00FF
	pha
	PushWord ExtraString ; push on the low order word.
	_DrawString	; draw the string.

EndLoop
	ldx Index	; get our index back
	dex	; bump to the next value
	dex
	dex
	dex
	bpl loop	; keep going if still positive

	plb	; restore the DBR...
	pld	; ... and the Direct Page

	rtl	; return back to TaskMaster

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; If the item to be printed is one of the last 4, then it is a column
; title. BoldFace it and leave. If it is not a column title, then see
; if that part of the print record has changed. If so, then set the
; font style to bold and leave. Otherwise, set the font style to normal.
;

SetFontStyle
	PushWord #0	; assume normal text
	_SetTextFace

	ldx Index
	cpx #4*4	; time to Bold for column headerss?
	bge ckChange	; no, see if print record changed

	PushWord #%00001	; turn on boldfacing
	_SetTextFace

	bra done2	; and leave

ckChange
	lda ValueOffsets+2,x ; can this one change?
	beq done2	; no so don't check
	sta count	; check this many bytes

	lda ValueOffsets,x	; get location of field to check
	tay

	SHORTM	; do the checks in 8-bit mode
ckChngLoop
	lda [Temp1],y	; get the new byte
	cmp [Temp2],y	; check against the old
	bne different	; if even one's different, boldface it
	iny	; bump to next byte to check
	dec count	; have we done them all?
	bne ckChngLoop	; no, so keep going
	LONGM	; back to 16-bit mode
	bra done2	; it didn't change so leave in normal mode

different
	LONGM	; back to 16-bit mode
	PushWord #%00001	; item changed, bold it
	_SetTextFace

done2
	rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Print out the record values.
;

PrintValues	PushWord #0	; normal text
	_SetTextFace

	ldx Index
	lda ValueOffsets+2,x ; does this entry have field values
	beq done	; no so don't print anything
	sta count	; save the number of bytes to print

	lda ValueOffsets,x	; get location of bytes to print
	tay

PrintValueLoop	sty YSave	; Save this record index
	lda [Temp1],y	; get the byte
	and #$00FF	; mask off upper byte

	pha	; push the value to be converted
	PushLong #ValueString ; put the HEX string here
	PushWord #2	; length of output is 2
	_Int2Hex	; convert byte to a Hex string

	PushLong #ValueString ; now print it
	_DrawCString

	dec count	; have we done all of them?
	beq done	; yes, so leave

	pea ','	; no, so print a comma and do the next
	_DrawChar
	ldy YSave
	iny
	bra PrintValueLoop

done
	rts

Index 	ds.b 2
YSave	ds.b 2
count 	ds.b 2
OffSet	ds.b 2
ValueString	dc.b 0,0,0

	ENDP

	EJECT
*******************************************************************************
*
PrOldUpdate	Proc
*
* Description:	Update routine for the Previous record window. This is
*	almost exactly the same as PrUpdate, but does not check to
*	see if the old record has changed when it determines the
*	font style for the strings. See that routine for comments.
*
*
* Inputs:	NONE
*
* Outputs:	NONE
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	phd
	phb

	phk
	plb

	lda MyDP
	tcd

	lda PrintRecord
	ldx PrintRecord+2
	jsr DerefIt
	sta Temp1
	stx Temp1+2

	lda OldRecord
	ldx OldRecord+2
	jsr DerefIt
	sta Temp2
	stx Temp2+2

	ldx #4*25	; 4 times number of strings - 1
loop
	stx Index

	jsr SetFontStyle

	ldx Index
	lda Position,x
	pha
	lda Position+2,x
	pha
	_MoveTo

	ldx Index
	cpx #4*16	; is the crWidth/Sizing one?
	bne doNormal	; no, so just draw it

	ldy #oprInfo+oiDev	; do we have a LaserWriter?
	lda [Temp2],y
	cmp #3
	bne doNormal	; yes, so use default string

	PushLong #Title17x
	bra DrawTitle
doNormal
	lda TitleTable+2,x
	pha
	lda TitleTable,x
	pha
DrawTitle
	_DrawString

	jsr PrintValues

	ldx Index
	dex
	dex
	dex
	dex
	bpl loop

	plb
	pld

	rtl

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; If the item to be printed is one of the last 4, then it is a column
; title. BoldFace it and leave. If it is not a column title, then see
; if that part of the print record has changed. If so, then set the
; font style to italic and leave. Otherwise, set the font style to
; normal.
;

SetFontStyle
	PushWord #0	; assume normal text
	_SetTextFace

	ldx Index
	cpx #4*4	; time to go to bold?
	bge done2	; no, see if print record changed

	PushWord #%00001	; turn on boldfacing
	_SetTextFace

done2
	rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Print out the record values
;

PrintValues
	PushWord #0	; normal text
	_SetTextFace

	ldx Index
	lda ValueOffsets+2,x ; can this one change?
	beq done	; no so don't check
	sta count

	lda ValueOffsets,x
	tay

PrintValueLoop
	sty YSave	; Save this record index
	lda [Temp2],y
	and #$00FF

	pha	; push the value to be converted
	PushLong #ValueString
	PushWord #2	; length of output is 2
	_Int2Hex

	PushLong #ValueString
	_DrawCString

	dec count	; have we done all of them?
	beq done	; yes, so leave

	pea ','	; no, so print a comma and do the next
	_DrawChar
	ldy YSave
	iny
	bra PrintValueLoop

done
	rts

Index 	ds.b 2
YSave	ds.b 2
count 	ds.b 2
OffSet	ds.b 2
ValueString	dc.b 0,0,0

	ENDP

	EJECT
*******************************************************************************
*
ClearOldRecord	PROC
*
* Description:	We are about to make a call that could change the Print
*	Record! Back up the current print record into the Previous
*	Print Record.
*
*
* Inputs:	'PrintRecord' holds handle or record to back up
*	'OldRecord' holds handle to back it up to
*
* Outputs:	'OldRecord' contains copy of 'PrintRecord' contents
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	PushLong PrintRecord ; Source Handle
	PushLong OldRecord	; Destination Handle
	PushLong #140	; Length of the Source.
	_HandToHand	; Move it.

	rts
	ENDP

	EJECT
*******************************************************************************
*
ShowChanges	PROC
*
* Description:	We have made a call the could have changed the Print
*	Record. Erase the old display of the print record, and mark
*	the screen as invalid so that TaskMaster will update it
*	with the new values.
*
*
* Inputs:	NONE
*
* Outputs:	Port set to 'Current Setting' window
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with Globals

	pha	; save the old port, as we are chang-
	pha	; ing it below to erase the windows.
	_GetPort

; first erase and invalidate the Previous Print Record window

	PushLong WindPointer2
	_SetPort

	PushLong #BigRect
	_EraseRect

	PushLong #BigRect
	_InvalRect

; Then erase and invalidate the current Print Record window.

	PushLong WindPointer
	_SetPort

	PushLong #BigRect
	_EraseRect

	PushLong #BigRect
	_InvalRect

	_SetPort

	rts
	ENDP

	EJECT
*******************************************************************************
*
DisableAll	PROC
*
* Description:	Disables all menu items between 257 and 266. This includes
*	virtually everything in the File Menu. This call will
*	usually be followed by a call to re-enable one or two File
*	items.
*
*
* Inputs:	NONE
*
* Outputs:	Menu items 257-266 disabled
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	lda #257	; start with the Quit item
	sta MItemNum	; save the index around the call
Loop
	pha	; push on for DisableItem
	_DisableMItem
	inc MItemNum	; Bump to next Menu Item
	lda MItemNum
	cmp #267	; finish with the Close Doc item
	blt Loop

	rts

MItemNum	ds.b 2

	ENDP

	EJECT
*******************************************************************************
*
EnableAll	PROC
*
* Description:	Enables all menu items between 257 and 266. This includes
*	virtually everything in the File Menu.
*
*
* Inputs:	NONE
*
* Outputs:	Menu items 257-266 enabled
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	With Globals

	lda #257	; start with the Quit item
	sta MItemNum

Loop	pha
	_EnableMItem

	inc MItemNum
	lda MItemNum
	cmp #267	; finish with the Close Doc item
	blt Loop

	rts

MItemNum	ds.b 2

	ENDP

	END

