boot3/Toolbox/Printing/PrintGlue.a
Elliot Nunn 5b0f0cc134 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 10:02:57 +08:00

766 lines
31 KiB
Plaintext

;
; File: PrintGlue.a
;
; Contains: This code is the printing glue for 128K ROM printing
;
; Copyright: © 1985-1993 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM4> 6/28/93 kc Roll in Ludwig.
; <LW2> 6/25/93 fau (with mal and chp): If the PDEF is 32 bytes or less, go flush
; the cache, in case the developer is using the PDEF as a stub and
; stuffing their own code.
; <SM3> 11/5/92 SWC Changed PrEqu.a->Printing.a and
; PrintCallsEqu.a->PrintTrapsEqu.a.
; <SM1> 6/15/92 CSS Take out forRom and CubeE conditionals because the forRomed code is old
; and this is CubeE. The net effect of which is to make printing work
; on SuperMario!!!!!
; <17> 12/16/91 IH Fix 1018177 in theFuture. Search for symbol "PURGEALIAS". Do
; not release the print driver alias and make it non-purgable
; before calling ResolveAlias.
; <16> 11/27/91 DTY DonÕt save LastSPExtra around _HOpenResFile any more now that
; _HOpenResFile checks to see if the font caches should be
; flushed.
; <15> 10/4/91 gbm #1013134,#1013156: Work around a case where the font caches
; would get flushed repeatedly during printing
; <14> 3/6/91 NB Bug: NB-3. Reviewed by csd. An earlier fix to error handling
; caused the error to not be overwritten if it was already set.
; However, since PrOpen doesn't reset the error to noErr at
; startup, any printing error that stays in low-mem after closing
; the printing manager prevents subsequent printing calls. Now
; PrOpen (actually PrOpenDrvr) will reset the error to noErr
; before opening the driver.
; <13> 3/5/91 PN Fix the warning by putting back the END statement at the end
; <12> 3/1/91 NB If the resource for the alias is not found, then we would
; normally return resNotFound. The glue used to return fnfErr
; whenever it couldn't open the driver and applications have coded
; for that error. Rather than add an error code, we map
; resNotFound to fnfErr and save the user some grief. We also put
; PrError into D0 at exit. This is needed because PrLoadDriver
; returns the error in D0.
; <11> 2/21/91 NB Bug: NB-2. Reviewed by dba. Fixed a bug in PrLoadDriver in which
; it was overwriting the error. This would occasionally cause a
; cancel request from the user (iUsrAbort) to be replaced with
; noErr. Now it preserves the error if the error is already set.
; <10> 8/9/90 CCH Added System 6 print glue back in, conditionalized for ROM only.
; <8> 8/1/90 gbm fix Darin ÒBoneHeadÓ AdlerÕs ÒoptimizationÓ
; <7> 7/23/90 dba change this into a linked patch
; <6> 7/20/90 gbm get rid of the warning
; <5> 5/18/90 PP Pass address of ÒfromFileÓ correctly to ResolveAlias call.
; <4> 4/17/90 NB Removed GetResource error messages when the alias is not present.
; Fixed a bad cleanup condition (called ReleaseResource on a nil
; handle on an error (no harm, though)).
; <3> 4/10/90 NB Missed a TST.W D0. Without which, the condition codes for the
; BNE.S which followed weren't always right. This caused
; occasionally stack explosions.
; 4/9/90 Nik Added call to PrLoadDriver. This loads in the driver based on
; the 'alis' -8192 resource in the system file, rather than on the
; system printer string. OpenResFile and .Print also make this
; call, instead of doing it themselves.
; <1.2> 9/20/89 CCH Rolled in System version from System sources.
; <1.3> 8/28/89 SES Removed references to nFiles.
; <1.2> 8/4/89 NMB Restored to 6.0 version of PrGlue. Ginsu is no longer in the 7.0
; builds of the system (sigh). The glue is now a ptch, rather than
; part of Rom7xFix.a, at least....
; <1.1> 5/8/89 NMB Gutted the whole thing and replaced it with a new glue which
; supports the new printing manager (Ginsu)
; <1.0> 11/16/88 CCH Added to EASE.
; 2/22/87 Jay 1). Restore curMap before jumping into the print code. This used
; to be done after comming back from the print code. The reason
; for this fix is that by leaving curMap pointing to us we might
; kick the application out of the resource search path. What if we
; need a resource out of the application file while we are inside
; the print code? 2). Also, under PrintOpen, Move PrintVars+iPrErr
; to d0 instead of testing it. This is because if PrDrvrOpen
; failed then it puts the error is in low memory but D0 (which is
; also the error) gets written over on the way out from
; PrDrvrOpen. PrintOpen tests low memory and if it is an error,
; goes to LLOut which puts D0 in low memory! D0 at this point is
; bad and the application does not get the correct error code. 3).
; Save curMap in a3 before getting the PDEF resource the first
; time.
; 2/13/87 Jay 1). Fixed a BAD bug with stack corruption on error exit if the
; printer resource file does not exist in the system folder. - In
; OpenRF, return _OpenRFPerm error in d0 - Removed ResErr check
; after OpenRF call under OpenPrRF. The error is already in d0. -
; Under OpenPrRF, if we have an error from OpenRF, put that error
; in low memory and branch to GlueAbort. It used to bne to LLOut.
; - Cleaned up GlueOut to eliminate call to _BlockMove. 2). Don't
; close the driver during PrClose. Close the resource file only.
; This is to eliminate the overhead of going thru .Print
; everytime. NOTE: The old PrLink used to leave the driver open.
; It must have been changed when PrLink was changed to PrGlue (I
; think!). - Removed call to _PrDrvrClose from PrintClose.
; 12/23/86 Jay If the GetResource call to get a PDEF fails, don't give up. The
; printer resfile may not be in the resource search path. Save and
; restore the user resource map around the GetResource (for PDEF)
; call. Get the printer resfile refnum from the low memory print
; var ($944+$E) or open the printer resource file to get it. After
; opening the printer resource file, save the refnum in low
; memory. The code to get the printer resfile refnum is now in a
; procedure called OpenRF. Check the print error after _PrDrvrOpen
; call in PrintOpen.
; 11/7/86 Jay Fixed bugs in PrDrvrDCE and PrDrvrVers. Put the result on the
; stack at (sp) instead of at 12(a6). Then, jump to GlueOut
; instead of LLOut. Changed Bra.s at PrOCerr to Bra.
; 11/7/86 Jay Fixed bug in PurgePr and NoPurgePr. Check the lower byte of
; flags to see if the driver is RAM based.
; 8/1/86 David Added PrGeneral call
; 9/17/85 Leo Converted to Ira's New Assembler
; 9/10/85 Leo New trap files, added GoSetVol Changed this file to PrintGlue.a
; no include files
; 8/17/85 Leo Integrated PrScreen, went to single Trap and selector.
; 8/6/85 Leo Added calls to SetVol/GetVol
; 7/16/85 Leo Fixed bug with stripping return values Removed PrCfgDialog Fixed
; values in PrGlueTable
; 7/13/85 Leo from old PrLink
;
; This code is the printing glue for 128K ROM printing
; calls. In this ROM, there is a single trap for printing,
; which is this code. This code takes the selctor, which
; is the last parameter to every printing call, and
; dispatches to the correct routine.
;
; There are two types of printing routines: those related
; to the high-level (PrOpenPage, etc.) interface, and
; those related to the low-level (driver calls) interface.
; The low-level interface calls are also referred to as
; 'non-link' routines throughout the comments, for reasons
; which totally escape me.
;
; The high-level interfaces are handled as one block,
; collectively referred to as PrGlue. These routines
; simply fetch the appropriate PDEF resource from the
; current printer resource file, and jsr to a certain
; offset into the resource. Which PDEF to use and
; how far into the PDEF to Jsr to are recorded in
; PrGlueTable, along with useful information like
; the number of bytes of parameters and return value
; there are for each entry. This information is used
; to allow PrGlue to build a stack frame for the routine
; and call the PDEF, after which it copies the return
; information back up on the stack and returns.
;
; The non-link routines are mostly calls on the
; .Print driver. They get themselves a iopb and
; make the call, or twiddle some aspect of the
; driver. The routines that fool with the DCE
; of the driver or the handle to the driver itself
; get the DCE by making a Status call on the
; driver, and pulling the DCEPtr out of the CSParam
; area of the iopb.
;
; PrOpen and PrClose are high-level routines that
; do not dispatch to a PDEF. They are responsible
; for opening/closing the current printer resource file.
; They also Open/Close the .Print driver.
;
; These routines are called with a final parameter,
; in addition to the ones listed in Inside Mac.
; As the last parameter, they take a longword
; full of information. The format of this long
; is like so:
;
; 31 23 15 7 0
; +--------+--------+--------+--------+
; |xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
; +--------+--------+--------+--------+
; Bits 31-27: Selector for the various routines in the glue
; Bits 26-24: Number of bytes of function result for this routine
; (must be either 0, 2, or 4)
; Bits 23-16: ID of PDEF to call for high level routines
; Bits 15-08: The number of bytes of parameters
; to this routine
; Bit 07: 1 if the PDEF should be unlocked after
; the call (high level routines)
; Bits 06-00: The offset into the PDEF to Jsr to
; (high level routines)
; 31 23 15 7 0
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | | | | | | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | | | | | |
; | Result Bytes | | Unlock Flag |
;Routine Selector PDEF ID Parameter Bytes PDEF Offset
;
;
; Routine Selector value
; ------- -------- -----
; (high-level routines)
; PrOpenDoc 0
; PrCloseDoc 1
; PrOpenPage 2
; PrClosePage 3
; PrintDefault 4
; PrStlDialog 5
; PrJobDialog 6
; PrStlInit 7
; PrJobInit 8
; PrDlgMain 9
; PrValidate 10
; PrJobMerge 11
; PrPicFile 12
; PrHack 13
; PrGeneral 14
; (low-level and 'non-link' routines)
; PrDrvrOpen 16
; PrDrvrClose 17
; PrDrvrDCE 18
; PrDrvrVers 19
; PrCtlCall 20
; PrPurge 21
; PrNoPurge 22
; PrError 23
; PrSetError 24
; PrOpen 25
; PrClose 26
;
LOAD 'StandardEqu.d'
INCLUDE 'Printing.a'
INCLUDE 'PrPrivate.a'
INCLUDE 'PrintTrapsEqu.a'
INCLUDE 'Folders.a'
INCLUDE 'Aliases.a'
INCLUDE 'LinkedPatchMacros.a'
MACHINE MC68020 ; needed for cache flush <LW2> fau
;************************************************************************************************
;* _MDebugStr takes a string for a parameter and calls DebugStr with it.
;*
;* Example: _MDebugStr 'In PrOpen'
;************************************************************************************************
MACRO
_MDebugStr &dbgStr
PEA @dbgAddr
_DebugStr
BRA.S @pastDbgAddr
@dbgAddr DC.B &dbgStr
ALIGN 2
@pastDbgAddr
ENDM
PrGlue PatchProc $A8FD,(Plus,SE,II,Portable,IIci)
;
; A few constants regarding selector values:
PrDocLimit EQU 3 ; Highest selector for doc loop routine
PDEFLimit EQU 15 ; Highest selector for high-level (PDEF-calling)
; routines
;
; PrGlue Entry points are below. The idea of this entry setup is to allow PrGlue
; to determine what entry point was used in very little code space. The Bsr.s
; pushes the return address on the stack, which PrGlue then uses to derive which
; entry point was used. The key is that the entry points here are arranged in
; the same order as the table PrGlueTable, below.
;
; Constants: Offsets into the PrGlue information
Selectr EQU 8+0 ; Selector for routine invoked (Most significant 5 bits)
FuncByt EQU 8+0 ; Bytes of function result (Least significant 3 bits)
PDEFId EQU 8+1 ; ID of the PDEF to call (8 bits)
ParmByt EQU 8+2 ; Bytes of parameters (8 bits)
CodeOfs EQU 8+3 ; Offset into the PDEF of the code for this function (7 bits)
;
; Parameters to the Glue:
longAt EQU 8 ; Offset from a6 of longWord o'info
;
; PrGlue itself
Link a6,#0 ; Stack frame, no local variables
Movem.l a3-a4,-(sp) ; Save the regs we will use to hold info across
; the call to the actual print routine
; Get selector in d1
Moveq #0,d1
Move.b Selectr(a6),d1 ; Get the byte containing it
Lsr.b #3,d1 ; Move selector over
Beq.s OpenDocOnly ; PrOpenDoc has a bunch of special case code, so don't
; get the ID the way we do it normally
; If it's a low-level call, dispatch to that stuff
Tst.b Selectr(a6) ; Test the selector: high-level or low-level?
Bmi LowLevel ; Send the low-level calls off to thier corner
; Get Id of PDEF that this call will be dispatched to in d2
Moveq #0,d2 ; Preset for PDEFId in d2
Move.b PDEFId(a6),d2 ; Get PDEF Id from Glue Parameter.
Bne.s GetPDEF ; If that's nonzero, it's the id. If it's zero,
; the id should be gotten from printing globals
Moveq #3,d2 ; Mask for PrintLoop type from Globals. This
; is also the PDEF Id to use
And.b PrintVars+bDocLoop,d2 ; Get that info into d2
Bra.s GetPDEF ; ...and go to it
OpenDocOnly
; For OpenDoc, we get the print loop type, which is the PDEF Id, from
; the print record passed by the caller as a parameter.
Move.l 20(a6),a0 ; Get handle to print record
Move.l (a0),a0 ; Deref Handle
Moveq #3,d2 ; Mask for doc loop type
And.b PrJob+bJDocLoop(a0),d2 ; Mask off them bits
Andi.b #$FC,PrintVars+bDocLoop ; Clear out those two bits in PrintVars
Or.b d2,PrintVars+bDocLoop ; and put the new bits in
;
; Get that PDEF
GetPDEF
Move.w CurMap, a3 ; <22Feb87> JNP save user's resfile refnum in a3
Clr.l -(sp) ; Room for the GetResource result
Move.l #'PDEF',-(sp) ; Type
Move d2,-(sp) ; id
_GetResource
Move.l (sp)+,d0
Tst.l d0 ; Test the result of GetResource
Bne.s GotPDEF ; we have the PDEF
; CurMap may be set to point to the user's res file. We need to set it to point to our resfile.
; Check the low memory global iPrRefNum. If it is $FFFF (i.e is not used and is initialised)
; then open the printer resource file to get our refnum. Otherwise use the refnum stored in the
; low memory global to call _UseResFile. Check the result of this call, if it failed then open
; the printer resource file to get our ref num.
Cmpi.w #$FFFF, iPrRefNum ; is our refnum in low memory?
Beq.s OpenPrRF ; no, open the printer resource file
Move.w iPrRefNum, -(sp) ; Try _UseResFile on this refnum
_UseResFile
Tst.w ResErr ; Did it work?
Bne.s GetRsrc ; Yes, so get the PDEF
OpenPrRF
MOVE.W D2, -(SP) ; save D2 across the call to FetchDriver
Bsr FetchDriver ; Open our res file
MOVE.W (SP)+, D2 ; restore D2 as soon as possible
Tst.w d0 ; success?
Beq.s Continue ; <13Feb87> JNP yes, continue
Move.w d0, PrintVars+iPrErr ; <13Feb87> JNP no, set error and get out.
Bra GlueAbort ; <13Feb87> JNP
Continue ; <13Feb87> JNP
Move.w iPrRefNum, -(sp)
_UseResFile ; our resfile is opened, now let's use it.
GetRsrc
Clr.l -(sp) ; Room for the GetResource result
Move.l #'PDEF',-(sp) ; Type
Move d2,-(sp) ; id
_GetResource ; get that PDEF
Move.l (sp)+,d0
Tst.l d0 ; Test the result of GetResource
Bne.s GotPDEF
; Can't get the resource... set PrError, and jump down to the return point
Move.w a3, -(sp) ; User's res file refnum
_UseResFile ; Restore user's Resource map. Refnum is on the stack.
Move.w #resNotFound,PrintVars+iPrErr
Bra GlueAbort
;
GotPDEF
Move.l d0,a4 ; Transfer the handle to an a-reg
Move.l a4,a0 ; Lock that baby down
; Some programmers are pretty slimy and load a PDEF that is empty. They then <LW2> fau
; stuff some code into it. However, since HLOCK does not flush the cache anymore, <LW2> fau
; the code that they stuff into it might not get written back to memory. To solve this, <LW2> fau
; we check here whether the PDEF resource size is less than, say, 32 bytes. If so, we <LW2> fau
; assume that they have already loaded the PDEF and modified it, so we flush the cache <LW2> fau
; for them. <LW2> fau
_GetHandleSize ; How big is our PDEF Handle <LW2> fau
cmp.l #32,D0 ; Is it "small" <LW2> fau
bhi.s @RealPDEF ; no, don't flush the cache <LW2> fau
jsr ([jCacheFlush]) ; else, flush the caches. <LW2> fau
@RealPDEF ; <LW2> fau
_HLock
;<22Feb87> JNP Restore curMap before jumping into the print code.
Move.w a3, -(sp) ; <22Feb87> JNP user's resfile refnum
_UseResFile ; <22Feb87> JNP Restore user's Resource map.
; Copy the parameters and return value of the routine down onto the stack again
Lea 12(a6),a0 ; Start of old parameters
Moveq #7,d0 ; Get bytes of param + bytes of return value in d0
and.b FuncByt(a6),d0 ; Together, these are the number of bytes to copy
Add.b ParmByt(a6),d0
Sub.w d0,sp ; We know the thing isn't actually more than a word wide
Move.l sp,a1 ; Beginning of destination
_BlockMove ; Note: Leaves d0 = 0
; Call the routine. The offset into the PDEF to jump to is given by the glue parameter
Move.b CodeOfs(a6),d0 ; Get offset (note high part of d0 is still 0)
Andi.b #$7F,d0 ; Mask off the unlock bit that is stored there
Move.l (a4),a0 ; Deref PDEF handle
Jsr 0(a0,d0) ; Call the routine
; Unlock the PDEF if the unlock bit from PrGlueTable is set
Move.b CodeOfs(a6),d0 ; The unlock bit is the high-order bit of this byte, so...
Bpl.s NoUnlock
Move.l a4,a0
_HUnlock ; make it float again
NoUnlock
Bra GlueOut
;
; All the low-level routines are implemented here
LowLevel
; Allocate and set up for .Print call a iopb on
; the stack
Sub.w #IOQElSize,sp ; Get an iopb
Lea PrintName,a0 ; Address of .Print string
Move.l a0,ioFileName(sp) ; Put in iopb
Move.w #iPrDrvrRef,ioRefNum(sp); Put refNum in iopb
Clr.b ioPermssn(sp) ; Always a good idea
Move.l sp,a0 ; Put pointer in a0
; The selector is in d1. We're gonna do a jump table on
; it. After the jump table, everybody should branch
; back to LLOut.
Moveq #0,d0 ; Since LLOut uses d0 as a return code,
; let's make sure it's something reasonable
Bclr #4,d1 ; We don't want the high bit
Add.w d1,d1 ; Shift selector left one
Move.w LLJump(d1),d1 ; Get jump table entry
Jmp LLJump(d1) ; Go to correct entry
LLJump
DC.W DrvrPrOpen-LLJump ; PrDrvrOpen 16
DC.W DrvrPrClose-LLJump ; PrDrvrClose 17
DC.W DrvrDCE-LLJump ; PrDrvrDCE 18
DC.W DrvrVers-LLJump ; PrDrvrVers 19
DC.W CtlCall-LLJump ; PrCtlCall 20
DC.W PurgePr-LLJump ; PrPurge 21
DC.W NoPurgePr-LLJump ; PrNoPurge 22
DC.W GetError-LLJump ; PrError 23
DC.W SetError-LLJump ; PrSetError 24
DC.W PrintOpen-LLJump ; PrOpen 25
DC.W PrintClose-LLJump ; PrClose 26
DC.W LoadDriver-LLJump ; Load Driver 27
DC.W LLBadParam-LLJump ; not implemented 28
DC.W LLBadParam-LLJump ; not implemented 29
DC.W LLBadParam-LLJump ; not implemented 30
DC.W LLBadParam-LLJump ; not implemented 31
LLBadParam
Move.w #paramErr,PrintVars+iPrErr ; Yes, say params in error
GlueAbort
Moveq #0,d1 ; Get the number of bytes of parameter to this entry in d1
Move.b ParmByt(a6),d1 ; Get from the glue parameter, source of all knowledge...
Bra PrExit
LoadDriver
BSR FetchDriver ; error in D0
; LLOut is the exit point for this routine. It takes the error in D0 and sets
; iPrErr with it. We only want that to happen under two circumstances:
; [1] when the error is uninitialized and
; [2] when the error is noErr.
; If the error is already set, we want to leave it alone. This code manages
; that change. <11>
MOVE.W PrintVars+iPrErr, D1 ; get the error in D1 (faster than low-mem access)
CMPI.W #-1, D1 ; is error uninitialized?
BEQ LLOut ; Yes, use D0 to set it.
TST.W D1 ; Otherwise, is an error pending?
BZ LLOut ; no, so set the error from D0 in LLOut
MOVE.W D1, D0 ; otherwise, refresh the D0 error for exit
BRA LLOut ; LLOut will therefore not reset the error.
PrintOpen
_PrDrvrOpen ; Open the .Print driver
Move.w PrintVars+iPrErr, d0 ; <22Feb87> JNP Move the error into d0
BNE.S PrOCerr ;abort if error.
ST -(SP) ;Mark call "open", by setting a byte true on stack (NB, 3/23/90)
BRA.S PrOCcom
PrintClose
;<13Feb87> JNP removed call to _PrDrvrClose
; DON'T check for an answer ; just keep slogging through
SF -(SP) ;Mark Call "close" by setting stack byte false. <NB: 3/23/90>
PrOCcom
Bsr FetchDriver ; Open the printer resource file, error in D0
MOVE.B (SP)+, D1 ; get the flag byte in D1. Always clean up stack!
Tst.w D0
Bne.s PrOCerr ; Error! get out
; Test result of OpenResFile
Move.w iPrRefNum, d0 ; get the refnum in d0
Tst.w ResErr
Bne.s @26
;Now return for opens, or close the resfile with the id
;found above if closing.
TST.B D1 ;Open Call?
BNZ.S @26 ;Yes: Go home
MOVE.W D0,-(SP) ;No: CloseResFile. Push the refnum param
_CloseResFile
@26
Move.w ResErr,d0
PrOCerr
Bra LLOut
DrvrPrOpen
CLR.W PrintVars+iPrErr ; force error to noErr at startup for a clean beginning
_Open ; Do the open
Bra.s LLOut ; and out
DrvrPrClose
_Close ; Do the close
Bra.s LLOut ; and out
DrvrDCE ;
Bsr.s GetDCEHandle ; Get DCE handle in a0
add.w #IOQELSize-4, sp ; Leave room for the DCEHandle
Move.l a0, (sp) ; Move the handle to the stack,
; Glueout will pick up the value and adjust the stack
Bra.s GlueOut ; get out
DrvrVers ;
Bsr.s GetDCEHandle ; Get DCE handle in a0
Move.l (a0),a0 ; Deref it
Moveq #0, d0
Move.b DCtlQueue+1(a0),d0 ; Get the version byte
add.w #IOQELSize-2, sp ; Leave room for one word
Move.w d0, (sp) ; Move the version# to the stack,
; Glueout will pick up the value and adjust the stack
Bra.s GlueOut ; Get out
CtlCall
Move.l 12(a6),csParam+8(a0) ; lParam3
Move.l 16(a6),CSParam+4(A0) ; lParam2
Move.l 20(a6),CSParam(A0) ; lParam1
Move.w 24(a6),CSCode(A0) ; iWhichCtl
_Control
Bra.s LLOut ; and out
PurgePr
Bsr.s GetDCEHandle ; Get DCE handle in a0
Move.l (a0),a0 ; Deref DCE handle
Btst #dRAMBased,dCtlFlags+1(a0); Is this a RAM-based driver?
Beq.s LLOut ; No? Well then it's not gonna purge
Move.l DCtlDriver(a0),a0 ; Get driver handle
_HPurge ; make purgeable
Bra.s LLOut
NoPurgePr
Bsr.s GetDCEHandle ; Get DCE handle in a0
Move.l (a0),a0 ; Deref DCE handle
Btst #dRAMBased,dCtlFlags+1(a0); Is this a RAM-based driver?
Beq.s LLOut ; No? Well then it's won't purge anyway
Move.l DCtlDriver(a0),a0 ; Get driver handle
_HNoPurge ; make non purgeable
Bra.s LLOut
GetDCEHandle
Move.w #1,csCode(a0) ; The old get-the-DCE status call
_Status
Move.l csParam(a0),a0 ; Get DCE Handle
Rts
GetError
add.w #IOQElSize-2,sp ; Strip parameter block except for one word
Move.w PrintVars+iPrErr,(sp) ; Get error code
Bra.s GlueOut
SetError
Move.w 12(a6),d0 ; Set the error code in register
;
; LLOut: All the low-level routines return here, with
; their error code in d0.
LLOut
Add.w #IOQElSize,sp ; Strip parameter block
Move.w d0,PrintVars+iPrErr ; Set return code
GlueOut
;
; Get the number of bytes of parameter to this entry in d1
Moveq #0,d1
Move.b ParmByt(a6),d1 ; Get from the table, source of all knowledge...
; Copy the function value, if any, back up to the caller's stack frame
Moveq #7,d0 ; We're going for # bytes function value in d0
and.b FuncByt(a6),d0 ; Got 'em
Beq.s NoRetVal
Move.l sp,a0 ; The function left its result on top of stack
Lea 12(a6,d1),a1 ; The place we want to go is after the original params
Lsr.w #1, d0 ; <13Feb87> JNP
Bra.s @1 ; <13Feb87> JNP
@2 Move.w (sp)+, (a1)+ ; <13Feb87> JNP
@1 Dbf d0, @2 ; <13Feb87> JNP
NoRetVal
Move.w PrintVars+iPrErr, d0 ; Leave function result in D0 <12> NB
PrExit
;
; Unwind our stack frame and strip the params (# bytes params still in d1)
Movem.l (sp)+,a3-a4
Unlk a6
Move.l (sp)+,a0 ; Return address
Adda.l d1,sp ; Strip params
Addq #4,sp ; Strip glue parameter
Jmp (a0) ; ...and we're out
;
; Subroutines for PrGlue
;
kStartupDisk EQU -1
;************************************************************************
; FindSpecialFolder - find the dirID of a special folder
; <12jan90 fjs, 3/22/90 used a stack frame: nb>
;
; in: d0 = foldertype (ie 'extn')
; out: d0 = dirID (or 0 if an error occurred) ( this is a lie --sad & ich )
;************************************************************************
FSFStackFrame RECORD 0,decr
vRefNum DS.W 1
dirID DS.L 1
kFSFSize EQU *
ENDR
FindSpecialFolder
WITH FSFStackFrame
LINK A6, #kFSFSize
SUBQ.W #2, SP ; space for error
MOVE.W #kStartupDisk, -(SP) ; this volume
MOVE.L D0, -(SP) ; folder type (input)
SF -(SP) ; don't create
PEA vRefNum(A6) ; ptr to the output vRefNum
PEA dirID(A6) ; ptr to output dirID
_FindFolder
MOVE.W (SP)+, D0 ; fetch error
BNZ.S @bail ; oh, well. Unlink and out.
MOVE.L dirID(A6), D0 ; if no error, copy dirID into output reg.
@bail UNLK A6
RTS
ENDWITH
;************************************************************************
; FetchDriver: open the system printer's resource file:
; We do this by resolving the alias written into the system file by
; the chooser. This alias maps from the system file to the driver.
; We canonify the system file, and then call ResolveAlias to create
; a canonified representation of the driver. That representation
; contains the information needed by HOpenResFile, which we then call.
; Any error is returned in D0.
;************************************************************************
FetchDriver
;************************************************************************
; CanonSysFile: Canonify the system file
;
; sysFileCanon(A6) contains the output CanonSpec if the routine succeeds.
; If an error occurs, the entire routine is abandoned, with the error in D0.
;
; pascal OSErr CanonifyFile(short vRefNum,
; long dirID,
; const Str255 *fileName,
; CanonicalFileSpec *canonicalFile);
;************************************************************************
SpecRec RECORD 0,decr
sysFileSpec DS.B FSSpec.size
driverSpec DS.B FSSpec.size
aliasHandle DS.L 1
wasChanged DS.B 1
if theFuture then ; PURGEALIAS
aliasState DS.B 1 ; State of the alias
endif ; PURGEALIAS
ALIGN 2
kSpecSize EQU * - SpecRec
ENDR
kAliasID EQU -8192 ; System Printer alias's resID
WITH SpecRec
LINK A6, #kSpecSize
MOVE.L #kSystemFolderType, D0 ; get this folder's dirID
BSR.S FindSpecialFolder ; if cond code < 0, then we have an error
BMI @Bail ; if failure, exit routine, error in D0
; create a file spec for the system file
MOVE.W #kStartupDisk, sysFileSpec + FSSpec.vRefNum(A6) ; VRefNum of startup disk
MOVE.L D0, sysFileSpec + FSSpec.parID(A6) ; dirID from FetchSpecialFolder
MOVEQ #0, D0 ; clear out D0 for BlockMove
LEA SysResName, A0 ; Copy system file's name
MOVE.B (A0), D0 ; which is this long
ADDQ.B #1, D0 ; plus that length byte!
LEA sysFileSpec + FSSpec.name(A6), A1 ; to the FSSpec
_BlockMove
; ResolveDriver: Resolve the alias using the system file's FSSpec.
SUBQ #4, SP ; allocate space for GetResource
MOVE.L #rAliasType, -(SP) ; get this type
MOVE.W #kAliasID, -(SP) ; get this ID
_GetResource ; fetch, boy!
MOVE.L (SP)+, D0 ; this is the handle
MOVE.L D0, aliasHandle(A6) ; save it across all these calls
BNZ.S @ResolveIt ; got one. Off we go...
; This is a new problem for the glue. If the resource for the alias is not found, then
; we would normally return resNotFound. The glue used to return fnfErr whenever it couldn't
; open the driver and applications have coded for that error. Rather than add an error
; code, we map resNotFound to fnfErr and save the user some grief.
@failedGetRes
MOVE.W ResErr, D0 ; copy error into output var
BNZ.S @Bail ; and exit if non-zero
MOVE.W #fnfErr, D0 ; else, return fnfErr so apps alert the user correctly
BRA.S @Bail ; and exit.
@ResolveIt
if theFuture then ; PURGEALIAS
Move.l aliasHandle(A6),A0
_HGetState
Move.b D0,aliasState(A6) ; Save the Alias state.
_HNoPurge ; Make the alias non-purgeable
endif ; PURGEALIAS
SUBQ.W #2, SP ; space for error
PEA sysFileSpec(A6) ; first parameter
MOVE.L D0, -(SP) ; the alias handle
PEA driverSpec(A6) ; ptr to driverSpec
PEA wasChanged(A6) ; ptr to output boolean (ignored)
_ResolveAlias
MOVE.W (SP)+, D0 ; got the error here.
BNZ.S @Cleanup
TST.B wasChanged(A6) ; check if the alias needs updating
BZ.S @CallHOpenRes ; Nope, keep going
MOVE.L aliasHandle(A6), -(SP) ; Now set the resource changed
_ChangedResource
TST.W ResErr
BNZ.S @Cleanup ; exit on error
CLR.W -(SP) ; Update the system file
_UpdateResFile ; (refnum = 0)
TST.W ResErr
BNZ.S @Cleanup ; exit on error
@CallHOpenRes
SUBQ.W #2, SP ; space for function result
MOVE.W driverSpec + FSSpec.vRefNum(A6), -(SP) ; parameter 1: vRefNum
MOVE.L driverSpec + FSSpec.parID(A6), -(SP) ; parameter 2: parent ID
PEA driverSpec + FSSpec.name(A6) ; parameter 3: ptr to fileName
MOVE.B #fsCurPerm, -(SP) ; set permission to "current"
_HOpenResFile
MOVE.W (SP)+, D0 ; grab function result
MOVE.W D0, iPrRefNum ; If it worked, then set the refnum
MOVE.W ResErr, d0 ; set the error in D0
@Cleanup
if theFuture then ; PURGEALIAS
Move.l aliasHandle(A6),A0
Move.b aliasState(A6),D0 ; Restore the alias state.
_HSetState
endif
MOVE.L aliasHandle(A6), -(SP) ; release the alias resource
_ReleaseResource
@Bail UNLK A6 ; error in D0.
RTS
ENDWITH
; Name of the .Print driver
STRING PASCAL
PrintName DC.B '.Print'
ALIGN
ENDPROC
END