*******************************************************************************
*
* Initialization for Fast text caching routines...
*
* (C)  Copyright Apple Computer, Inc. 1989, 1992
* All rights reserved.
*
* by Jim Mensch
* 2/7/89
*
*******************************************************************************
*
* Modification History:
*
* Version 1.0	mensch 2/7/89
*
* 15 Mar 89	Steven Glass
*
* A little clean up so it can be used in both the patch and the ROM.
*
* 3-Feb-92	Dave Lyons
*
* Fixed bug where the FastFont message ($0023) was not getting deleted when
* we disposed of the FastFont handle (because it had been purged).
*
* Minor optimizations.
*
*******************************************************************************
	EJECT

	MACRO
	bcsl &A
	bcc  @dontTake
	brl  &A
@dontTake
	MEND


FastFontMsgRecord	Record 0
Next	ds.L 1
Type	ds.w 1
Indicator	ds.w 1
Handle	ds.L 1
Size	equ Handle+4
	ENDR



*******************************************************************************
*
DoFastSetup	PROC export
*
* This routine does all the necessary setup to use a fast system font.
*
* First it looks for the FastFont in memory.  It is kept in a handle which
* is kept in a new message.
*
* If the message exists, then we look at the font handle.  It may have
* been purged.  A purged handle means that we have to start over as
* if the handle was not there at all.
*
* If the message does not exist or the font has been purged, then
* we look for the font on disk.  If it's there we get memory for it
* and read it in.
*
* Finally we create the message for the fast font so that the next
* time it can be there.
*
*
* Inputs:	Stack:  Room for result
*	a-reg   QuickDraw's DPage
*
* Outputs:	Stack:  Handle
*	a-reg   QuickDraw's DPage
*
* External Refs:
*	none
*
* Entry Points:
*	none
*
*******************************************************************************
	DefineStack
deref1	long
tempPort	long
tempHandle	long
RefNum	word
FileSize	word
;
SaveDPage	word
QDDPage	word
RTL1	block 3
Result	long

SizeOfFrame	equ SaveDPage-deRef1

;
; Equates for the fastfont record
;
o_FFAscent	equ 0
o_FFDescent	equ o_FFAscent+2
o_FFMaxWidth	equ o_FFDescent+2
o_Leading	equ o_FFMaxWidth+2
o_FFrowBytes	equ o_Leading+2
o_oldFontHandle	equ o_FFRowBytes+2
o_StrikeSize	equ o_oldFontHandle+4
o_FFSizeofVars	equ o_StrikeSize+4
o_FFWidthTable	equ o_FFSizeofVars
o_FFOffsetTable	equ o_FFWidthTable+256
o_FFEndOfTables	equ o_FFOffsetTable+512
;
; MessageCenterEquates
FFHandleMessage	equ 35	; message number that will contain our fastfont handle
FFMessageSize	equ 8	; it will be 8 bytes long just in case..
FFMessageIndicator	equ $A5E7	; just a byte that indicates the message is ok..
FFID	equ $4404	; memory ID we use to create handle here.



	pha
	phd
	tcd	; switch in qddpage for a moment to clear handle
	ldx #512	; first thing we do is zero out the old fastfontptr
	stz <FastRomFont,x
	stz <FastRomFont+2,x
	tsc	; get the stack pointer

	sec
	sbc #SizeOfFrame
	tcd	; create the stack frame...
	tcs
;
; Now that the stack frame is set up, create the offscreen buffers that we are
; going to use. Ask for a block the size of shaston 8 first!
;
	stz Result
	stz Result+2

	jsr GetMessage	; first see if the fastfont is in memory already
	bcs @NotLoaded	; if carry set, the fastfont ain't here yet..

	sta Result
	txa
	ora #$8000
	sta Result+2
	ldx #0
	brl @okEnd
@NotLoaded

;
; Open the File
;
	lda #0
	pha	; room for refnum
	pha
	PushLong #FFPath
	pha
	tsc
	pea 00
	inc a
	pha
	pea $0010	;OPEN
	jsl >$E100B0
	tax
	pla	; save the refnum
	ply
	ply
	ply
	ply	; discard the crap
	bcsl @QuickExit
	sta refNum

;
; Get the file size
;
	pha	; space for eof
	pha
	pei refNum	; the ref num
	tsc	; pointer to param block
	pea 00
	inc a
	pha
	pea $19	;GET_EOF
	jsl >$E100B0
	pla
	pla
	plx
	sta FileSize	; save this here
	bcs @QuickError	; Close file and get out on error

;
; Now get memory for the file
;

	ldx #attrLocked+attrNoSpec	; start it out locked.
	jsr GetALittleMem
	bcsl @QuickError		; close file and get out  on error

	sta deRef1
	sta Result
	txa
	ora #$8000
	sta deRef1+2
	sta Result+2

;
; Deref the handle in place (Pointer goes to deRef1).
;
	ldy #2	; Deref handle and put pointer in deref1
	lda [deref1],y
	tax
	lda [deref1]
	sta deref1
	stx deref1+2

;
; Read the data
;
	lda #0
	pha
	pha
	pha
	pei FileSize
	pei deref1+2
	pei deref1
	pei refnum
	tsc
	pea 00
	inc a
	pha
	pea $0012	;READ
	jsl >$E100B0
	plx
	plx
	plx
	plx
	plx
	plx
	plx

;
; Come here if error occurs after open.
;
@QuickError	php	; save the read status, it's important

;
; Close the file.
;
	pei refnum
	tsc
	pea 00
	inc a
	pha
	pea $0014	;CLOSE
	jsl >$E100B0
	pla

;
; Now see if everything worked or not.
;
	plp
	ldx #-1
	bcs @ErrOut	; carry set means it did not work

;
; Put the handle to the real system font into place.  Make this stuff work right!
;
	ldy #o_oldFontHandle
	lda #SystemFont
	sta [deref1],y
	lda #^SystemFont
	ldy #o_oldFontHandle+2
	sta [Deref1],y

;
; Unlock the fast font handle
;
	ldy #4
	lda [Result],y
;;;	and #$7FFF
*** opt 3-Feb-92 DAL
	asl a
	lsr a
*** end 3-Feb-92
	sta [Result],y

	jsr sendMessage	; if we get this far, post our little message...
	ldx #0

@ErrOut
;;;	cpx #0	; if x is zero we are safe
	txa	;opt 3-Feb-92 DAL
	beq @okend
	lda Result+2	; it was not zero so kill the allocated handle
	and #$00FF
	tax

	lda Result
	jsr KillIt

@QuickExit		; finally!

@okEnd	tdc
	clc
	adc #SizeOfFrame
	tcs
	pld
	pla
	txa
	cmp #1
	rtl

;
; FastFontMessageStuff
; This section will contain routines that operate with the message center to add/change
; the fastfont message that it finds.
;
;
GetMessage
;
; This routine will be called to get the fastfont handle from the message center
; if it exists.  It will set the carry if no message exists yet, if the carry is
; clear then <A> and <x> will contain the fastfont handle to use,
; <A> high word <X> low word
;
	stz <deref1
	stz <deref1+2

	lda #FastFontMsgRecord.size
	ldx #attrLocked
	jsr GetALittleMem
	bcs @NoMessage
	sta <Deref1	; save the handle for a second...
	stx <Deref1+2


	pea 2	; get a message
	pea FFHandleMessage	; type of message to get
	phx
	pha
	_MessageCenter	; get the proper message
	bcc @GotMessage	; if no error then continue
@NoFastFont
*** added 3-Feb-92 DAL -- If the handle was bad or purged, kill the message!
*** Otherwise the next time we fetch the message it will contain somebody
*** else's handle, and we'll try to use that for FastFont!  Ouch.
	pea 3	;delete message
	pea FFHandleMessage
	phx
	phx	;ignored
	_MessageCenter
*** end 3-Feb-92

	lda deRef1
	ldx deRef1+2
	jsr KillIt

@NoMessage	sec	; indicate no message yet
	rts	; and return

@GotMessage
	ldy #2	; deref the message
	lda [deref1]
	sta <tempPort	; dereference the message to get its contents
	lda [deref1],y
	sta TempPort+2

	ldy #FastFontMsgRecord.Indicator
	lda [tempPort],y		; now check the signature...
	cmp #FFMessageIndicator
	bne @NoFastFont		; if not proper, then someone else used my message


;
; At this time, we have a valid message, lets test it to see if it still has
; a good handle in it!
;
	ldy #FastFontMsgRecord.Handle+2	; recover the handle
	lda [tempPort],y
	and #$00FF		; strip off high bit.
	tax
	dey
	dey
	lda [TempPort],y
	sta tempPort
	stx tempPort+2

;
; Is this a valid handle?
;
	pei tempPort+2
	pei tempPort
	_Checkhandle
	bcs @NoFastFont
;
; test to see if the handle is purged...
;
	lda [tempPort]
	ldy #2
	ora [tempPort],y
	bne @NotPurged

;
; It was purged so kill the orphan.
;
	lda TempPort
	ldx TempPort+2
	jsr KillIt
	bra @NoFastFont	; tell the app we did not have a fastfont
@NotPurged


;
; If we get this far, then we have a proper message with the proper fastfont stuff in it
;
	pea 0		; set the purge level to 0
;;;	PushLong <tempPort
*** opt 3-Feb-92 DAL
	pei <tempPort+2
	pei <tempPort
*** end 3-Feb-92
	_SetPurge		; set it as nonpurgeable...

;
; Get rid of temporary handle.
;
	lda deRef1
	ldx deRef1+2
	jsr KillIt

	lda TempPort		; Return the handle in a & x
	ldx TempPort+2

IgnoreError	clc		; clear the carry
	rts		; and return



;-----------------------------------------------------------
;
; SendMessage puts a fast font message record in the
; the message center.
;
SendMessage

; First allocate room for our message
	stz <tempHandle
	stz <tempHandle+2

	lda #FastFontMsgRecord.Size
	ldx #attrLocked		; locked for now
	jsr GetALittleMem
	bcs IgnoreError		; if no error continue

	sta <tempHandle		; save the handle for a second...
	stx <tempHandle+2
	ldy #2		; deref it.
	lda [tempHandle]
	sta tempPort
	lda [tempHandle],y
	sta tempPort+2

	ldy #FastFontMsgRecord.Indicator	; put our values in it
	lda #FFMessageIndicator
	sta [tempPort],y
	lda <Result
	ldy #FastFontMsgRecord.Handle
	sta [tempPort],y
	iny
	iny
	lda <Result+2
	sta [tempPort],y
;
; now that we have a message send it...
;
	pea 1	; add a message
	pea FFHandleMessage	; type of message to get
	pei TempHandle+2
	pei TempHandle
	_MessageCenter	; get the proper message
@NoMessage


;
; Get rid of temporary handle
;
	lda tempHandle
	ldx tempHandle+2
	jsr KillIt

	clc	; indicate no message yet
	rts	; and return

FFPath	str '*/System/Fonts/FastFont'


;-----------------------------------------------------------
;
; Disposes the handle passed in a & x.
;
KillIt

	phx
	pha
	_DisposeHandle
	rts

;-----------------------------------------------------------
;
; This is a little internal routine to call the memory manager
; and get a handle of size (a-reg) and attributes(x-reg).
;
GetALittleMem	pha
	pha
	pea 0
	pha
	pea FFID	; user id
	phx	; desired attributes
	pha
	pha
	_NewHandle
	pla
	plx
	rts

	EndP
