mac-rom/Toolbox/ResourceMgr/ResourceMgrExtensions.a

2385 lines
96 KiB
Plaintext

;
; File: ResourceMgrExtensions.a
;
; Contains: Extensions to Resource Manager: partial resources & resource overrides
;
; Written by: by Brian B. McGhie, Darin Adler, and Dean Yu
;
; Copyright: © 1989-1994 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM24> 1/25/94 kc Back out last change till we can figure out why it is causing up
; problems on TNT.
; <SM23> 12/21/93 SAM Changed InsertOverrideMap to copy the PSN of the base map into
; the override map instead of always marking the overrride map as
; a system map.
; <SM22> 10/29/93 SAM Roll in <MC3> from cm900ftjesus.
; <MC3> 10/29/93 ECH #1119916: When looking for ID conflicts, look for both FONT and NFNT
; of the same ID.
; <SM21> 9/16/93 SAM <MC2> Added a call to MarkFileAsOwnedByTheSystem in
; InsertOverrideMap to set the map's owner PSn to kSystemProcess
; so the mod made in <SM19> will not break all non-font overriden
; resources.
; <SM20> 9/10/93 pdw Deleting the ENDWITH that corresponds to a WITH that was deleted
; earlier.
; <SM19> 9/9/93 SAM (DTY) Added MarkFileAsOwnedByTheSystem. Changed IsThisASystemResourceMap
; to return true ifF the PSN is equal to kSystemProcess. Changed
; OpenResFileUnderSystemMap to call MarkFileAsOwnedByTheSystem if the
; file is a font file (which sets its creator PSN to kSystemProcess).
; <SM18> 5/30/93 SAM Made IsthisASystemResourceMap return false if the process mgr is
; not running.
; <SM17> 5/27/93 SAM In IsThisASystemResource, no longer return true if the process
; serial number is 0.
; <SM16> 5/24/93 BT The size of an empty map in MakeOverrideMap should be 32, not
; 30. Andy Nicholas found this and Dean Yu verified it. So there.
; <SM15> 5/14/93 kc Roll in change from Reality that fixes a bug in ReleaseTheFont
; that was leaving all of the fonts locked down in the system
; heap.
; <SM14> 4/16/93 kc Change call to AddNewRef to AddNewRefWithoutUpdate so that
; MakeOverrideMap doesn't set the mapChanged bit. This fixes
; #1069183.
; <SM13> 12/4/92 RB Removed kFakeResourceOverrideMapRefNum
; <SM12> 12/1/92 RB In MakeOverrideMap, set the TwoDeepBit attribute.
; <SM11> 12/1/92 RB In MakeOverrideMap, registers were not being exchanged correctly
; unless the resources had a name.
; <SM10> 11/10/92 RB Renamed CheckGrow@1 to CheckGrowAt1, since Flashport don't like
; it.
; <SM9> 11/5/92 SWC Changed PackMacs.a->Packages.a.
; <SM8> 9/17/92 FM Update from Reality:
; <61> 9/2/92 DTY The FOND structure has been changed to a record.
; <SM7> 7/27/92 FM Update from reality. Moved DirID related patches on OpenResFile
; and CreteResFile to ResourceMgrPatches.a
; <60> 7/20/92 DTY #1035813: In IsThisASystemResourceMap, look in the parallel FCB
; array ourselves instead of going through the file system.
; <59> 6/23/92 DTY Get rid of extraneous Import in InsertMapUnderSystemMap.
; <58> 6/23/92 DTY #1033397: In InsertOverrideMap, flush emLastMapOverridden in
; case this map is being overridden again.
; <57> 6/15/92 DTY #1032647 <csd>: When renumbering NFNT, FONT, and sfnt resources,
; remember what each resource was originally numbered, and what it
; was renumbered too so that multiple FONDs in the same file will
; continue to reference them.
; <56> 6/12/92 DTY #1032065: If the font file being closed by
; CloseResFileUnderSystemMap is the file that the last used font
; came from, invalidate the emLastFont global.
; <55> 6/5/92 DTY #1031210: In OpenResFileUnderSystemMap, if there are no files
; underneath the system map yet, donÕt set the twoDeep bit in the
; new map. Additionally, in CloseResFileUnderSystemMap, if the map
; being closed does not have the two deep bit set, clear it from
; the map above it.
; <54> 6/4/92 DTY #1031494: In MakeOverrideMap, put the new override map handle
; into TopMapHndl so that itÕs actually in the resource chain
; somewhere.
; <53> 5/26/92 DTY #1027036 <jmg>: <46> Revisited. The check to see if a resource
; is loaded or not doesnÕt take into account purged resources. The
; cool new way to see if a master pointer has already been
; allocated for a resource is to patch CheckLoad, and set a bit
; (DeanBit) in BrianBits if the resource reference entry contains
; a master pointer. ResolveIDConflicts now checks this bit to
; determine whether or not it was the one that loaded a resource.
; <52> 5/21/92 DTY #1030292: 'FOND' resources are left locked in memory during
; ResolveIDConflicts because a flag is being used by three
; routines at the same time. Save and restore this flag around
; each use so that the previous value is preserved.
; <51> 5/18/92 DTY #¥BLT: Intialize hasSystemMode(a6) in OpenResFileUnderSystemMap
; before using it, dummy.
; <50> 5/15/92 DTY The bug number for <48> was 1028722
; <49> 5/15/92 hsK (Really DTY.) Thinking in C while program in Pascal style assembly is
; dangerous. Pop off the parameters in IsThisAFontFileInTheFontsFolder.
; <48> 5/14/92 DTY #1029722: Add CloseResFileUnderSystemMap.
; <47> 5/8/92 DTY #1029162: Let the caller pass in the desired permission to
; OpenResFileUnderSystemMap.
; <46> 4/22/92 DTY #1027036: Whenever we fetch a font from the main resource chain,
; see if it was already loaded. If it was, donÕt call
; ReleaseTheFont on it so we donÕt screw up people who have the
; handle cached. Like the Finder.
; <45> 4/21/92 DTY #1018901,<gbm>: Provide a new selector, GetNextFOND, which
; provides an API to get the next 'FOND' resource of the same
; family in the resource chain. This was needed because with the
; Fonts folder, a font family can be split across several files,
; and a single 'FOND' may not contain all the information about
; all the available fonts of that family.
; <44> 4/10/92 DTY BLT: Change <42> had a typo, so the override bits were being set
; off of A0 instead of A1. This prevented Gibblies from staying
; resident.
; <43> 4/6/92 DTY #1026612: Fixes from Fonts folder code review: Use _EqualString
; instead of _IUMagString.
; <42> 3/30/92 DTY #1025140,<FM>: Changed several occurances of three bset
; instructions into one or instruction. Changed an add to a move
; in ResolveIDConflicts since thatÕs what it was doing anyway.
; <41> 3/25/92 DTY #1024844: InsertOverrideMap on a map that already has an
; override map is broken. Instead of trying to do everything in
; one loop, be less tricky and remove the override map in one
; loop, and insert it in a second loop.
; <40> 3/24/92 DTY #1022599: Return some errors in InsertOverrideMap. nilHandleErr
; is returned if either parameter is a nil handle, and paramErr is
; returned if the same handle is passed twice.
; <39> 3/17/92 DTY #1024085: IsThisASystemResource returns an error for ROM resources,
; because 1 is an invalid file reference number. If the map handle
; is the ROM map handle, then skip the call to
; _GetParallelFCBFromRefNum.
; <38> 3/16/92 DTY #1024587: Do some sanity checking on the map handles passed to
; Get/SetOverrideAttributes.
; <37> 3/11/92 DTY #1024124: Initialize scriptBase before using it. Initialize the
; family number hint to be 256 instead of 0. This is the first
; valid family number in the range reserved for renumbered fonts.
; Took this opportunity to rename ÒhintÓ to ÒfamilyHintÓ in the
; stack frame.
; <36> 3/11/92 DTY #1024123: In the routine FindNewFamilyNumber, a FOND handle will
; be disposed twice if the original number is hit while searching
; for a new resource ID.
; <35> 2/21/92 DTY #1022628: Do a sanity check on the handles passed to
; InsertOverrideMap. (Check to see if either one is nil, or if
; the same handle was passed twice.)
; <34> 2/12/92 DTY In OpenResFileUnderSystemMap, check to see if the file being
; opened is a font file. (I knew I called _GetCatInfo for a
; reason!) If it is, bump the count in emOpenFontFiles. If this
; goes past our artificial limit of 128 font files, donÕt open any
; more font files.
; <33> 1/30/92 DTY Set the preventFileFromBeingClosedBit on override maps and font
; maps.
; <32> 1/29/92 DTY OK, weÕve got the real reason for what happened with that last
; change. It turns out that the mInMemoryAttrs byte was destined
; for use in another way than what I assumed, so these bits do get
; written out to the disk, which is why we saw them set when a
; resource file was being opened. Anyway, now that we know the
; real reason, IÕm taking out the last change, and adding a patch
; to vNewMap in ResourceOverridePatches.a which does the same
; thing, but more thoroughly.
; <31> 1/28/92 DTY With pvh Ð The ultimate in skanky band-aids to get past a
; project milestone: Installer copies the resource fork of
; existing font suitcases with _PBRead and _PBWrite. This copies
; the in memory attribute fields in the resource map header onto
; disk. If any resource override bits are on in the source
; resource map, these get written out to disk, so when the target
; file is subsequently opened, these bits are set in the map
; header, leading to some surprising behaviours. Like failed live
; installs. Anyway, add some code to _HOpenResFile which strips
; these bits off of newly opened files. This change should be
; taken out as soon as a better way of solving this problem is
; found; itÕs just too skanky for words. (And this is coming from
; Dean and Pete, the two skankiest INIT writers on this side of
; Stevens Creek Blvd.)
; <30> 1/25/92 csd When renumbering fonts, make sure that the changed FOND resource
; actually gets written back out to the right file.
; <29> 1/22/92 DTY Using A5 to point to a resource map, then calling _UniqueID is
; incredibly bad! (And I thought I could get away with it.) WeÕll
; have to keep the loner resource map in the stack frame for lack
; of a better place to put it.
; <28> 1/22/92 DTY _WriteResource requires that the resource handle actually be in
; memory. So instead of loading a font resource in just to change
; the ID, call _UpdateResFile to write out the map.
; <27> 1/19/92 DTY Tons oÕ weekend fun in ResolveIDConflicts: DonÕt call
; FindNewFamilyNumber to map to an existing ID if the IDs in the
; two chains match. FindNewFamilyNumber now determines whether to
; map or renumber depending on a word on the stack instead of
; seeing if existingFamilyID is set. This makes renumbering to
; the system font work. Also release each 'FOND' as weÕre
; finished with it. This means writing each change out as itÕs
; made instead of doing a massive _UpdateResFile at the end.
; <26> 1/14/92 DTY Save and restore TopMapHndl in ResolveIDConflicts. This guy
; blocked build (15). Ooops.
; <25> 1/8/92 RB Added the resource manager extensions to the ROM build, Some
; PatchProcs and ComeFromPatches are ignored at link time. Renamed
; StdExit ROMBind to RStdExit to avoid a conflict with ScriptMgr.
; <24> 1/3/92 DTY In _ResolveIDConflicts, if the current font family number does
; not conflict with any existing font families, see if the font
; family already exists with another number. Also change the
; family ID in the 'FOND' resource itself if the 'FOND' is
; renumbered.
; <23> 12/17/91 DTY Add _ResolveIDConflicts, which makes sure that there will be no
; matching font IDÕs.
; <22> 12/16/91 DTY In SetOverrideAttributes, instead of merging the flags into the
; memory attributes, just set the attributes to be the flags that
; are passed in, preserving the decompression bit, of course.
; This should make opening font suitcases (finally) work.
; <21> 12/14/91 DTY The System process number is 1, not 0. (WeÕll keep checking for
; 0 as well, since that makes things a lot simpler.)
; <20> 12/11/91 DTY Better IsThisASystemResourceMap call. Instead of looking at the
; map attribute bits to determine if a resource map is a system
; resource map, look at the PSN of the process that opened the
; file. If it was opened in system mode, then consider the file a
; system resource map. This means that the Process ManagerÕs
; patch on CheckLoad to make sure that system resources load in
; the system heap will work for Gibblies, the System file, and
; fonts files, too, which, in turn means that the SetSysHeap
; procedure can go away.
; <19> 12/11/91 DTY The file opened by _OpenResFileUnderSystemMap should not be made
; the current resource map. Save and restore CurMap in this
; routine.
; <18> 12/6/91 DTY Add routine _OpenResFileUnderSystemMap. Given an FSSpec, it will
; open a file and place it underneath the System resource map in
; the resource chain. This is done in system mode, if possible,
; since the Finder uses this routine to add fonts to the resource
; chain.
; <17> 12/4/91 DTY SignedByte values are in the high byte after allÉ
; <16> 12/2/91 DTY Bail out of setting the system heap bit on the fonts if there
; are no resources in the map.
; <15> 11/26/91 DTY Values from Get/SetOverrideAttributes should be returned in the
; low byte of SignedByte parameters.
; <14> 11/20/91 DTY Move CurMap down if TopMapHndl is being moved in
; InsertOverrideMap.
; <13> 11/20/91 JSM #1016311 - add a come-from patch on _SetEOF inside of CheckGrow
; to check for 16 megabyte resource fork limit when calling
; AddResource, ChangedResource, SetResInfo, and SetResourceSize.
; <12> 11/15/91 DTY An rts at the end of InsertFontMap would help. If TopMapHndl is
; being moved, make the next map down the top map as well as the
; current map.
; <11> 11/5/91 DTY Add MakeOverrideMap, SetOverrideAttributes,
; GetOverrideAttributes, SetScanOverride, and InsertFontMap
; routines.
; <10> 11/1/91 DTY Make GetMap return resFNotFound if the map that was passed
; wasnÕt found. Also added code for _IsThisASystemResourceMap.
; <9> 10/23/91 DTY Everybody in the world wants to close files from TopMapHndl down
; to SysMapHndl, which is a really bad thing if there are override
; maps for the System file. Provide a routine which returns a
; handle to the resource map that people should stop closing files
; at. (The resource file that is returned shouldnÕt be closed.)
; <8> 12/7/90 dba <gbm> make ResourceDispatch use DispatchHelper
; <7> 11/8/90 csd & dba & stearno : Changed the sense of the test after NewPtr to
; branch on non-zero for failure.
; <6> 11/1/90 csd & dba; Change the jsrROM for OpenResFile to be a jsrOld so we
; donÕt nuke the other patch to OpenResFile. The other ...ROM
; calls in this file need to be checked, too.
; <5> 10/17/90 stb & bbm & stearno. fix bug for very low memory situation in
; SetResourceSize
; <4> 7/11/90 JSM Initialize D0 with DirID from extended low memory area in
; NewCreate, too.
; <3> 7/5/90 DTY Initialize D0 with DirID from extended low memory area in
; NewOpenRF.
; <2> 7/3/90 DTY Updated to use LinkedPatchMacros. Changed NewCreate & NewOpenRF
; into come-from patches.
; <1.9> 12/4/89 dba RestRegs is not our friend; make the sucker work again without
; SaveRegs
; <1.8> 12/4/89 BBM NewPtr can move the resource map making a2 pointer invalid
; <1.7> 10/11/89 dba non-come-from patches caused problems for Personal AppleShare;
; fix by not patching if call is asynchronous; some day I will
; make them come-from again
; <1.6> 9/26/89 dba no longer use come-from patches since MultiFinder patches OpenRF
; <1.5> 9/18/89 BBM SaveRegs, SpaceAt, CheckGrow@1 had the wrong offsets on Esprit.
; <1.4> 9/5/89 dba fixed CreateResFile; sorry, Nick!
; <1.3> 8/30/89 dba got rid of SEEKs in Bind (and messed up the bind section rather
; badly); reorganized the code, using more PROCs and better
; labels; use RefHandle instead of HandleScan for reporting
; errors; got rid of the Resource Manager global and used a more
; traditional dispatching scheme; added HOpenResFile and
; HCreateResFile; got rid of obsolete AddReference and
; RmveReference traps; added to-do items
; <1.2> 8/7/89 EMT Use inc.sum.d rather than individual includes for speed and
; accuracy.
; <1.1> 7/6/89 CCH Added Binding macros for Portable, and fixed one for Aurora.
; <1.0> 6/29/89 bbm Adding for the first time.
; 5/30/89 fixed bugs in setsize, thanks to bo3b
; 5/2/89 made to work on all machines
;
; To Do:
; fix copy code in SetResourceSize so it copies just valid data instead of the whole space
; get rid of extra seeks, etc.
; potential bug, if size we need to set to is odd, it probably wonÕt work
; potential bug, if size is increased and it is the one just before
; the map, and there are no resources after the map, then
; the dataSize in the map header is not updated.
; move into ROM source
; handle all the cases where the resource is currently in RAM
; for ReadPartialResource, read from RAM
; for WritePartialResource, write to RAM and write that out to disk (as in WriteResource)
; for SetResourceSize, change handle size in RAM and write it out to disk if needed
; allow WritePartialResource to extend the size of the resource
load 'StandardEqu.d'
include 'Folders.a'
include 'Packages.a'
include 'LinkedPatchMacros.a'
include 'FileMgrPrivate.a'
include 'FontPrivate.a'
include 'MFPrivate.a'
include 'Processes.a'
include 'ResourceMgrPriv.a'
machine mc68020
IF (&TYPE('debugResolveIDConflicts') = 'UNDEFINED') THEN
debugResolveIDConflicts EQU 0
ENDIF
StdZEntry ROMBind (Plus,$13F4E),(SE,$0E558),(II,$12E90),(IIci,$1B700),(Portable,$144E8)
Std1Entry ROMBind (Plus,$13F52),(SE,$0E55C),(II,$12E94),(IIci,$1B704),(Portable,$144EC)
RStdExit ROMBind (Plus,$1400C),(SE,$0E616),(II,$12F4E),(IIci,$1B7C4),(Portable,$145A6)
RREntry6 ROMBind (Plus,$141FC),(SE,$0E810),(II,$1314A),(IIci,$1B9C6),(Portable,$147A2)
RdData ROMBind (Plus,$1424A),(SE,$0E85E),(II,$13198),(IIci,$1BA14),(Portable,$147F0)
WrData ROMBind (Plus,$14254),(SE,$0E868),(II,$131A2),(IIci,$1BA1E),(Portable,$147FA)
SaveRegs ROMBind (Plus,$14268),(SE,$0E87C),(II,$131B6),(IIci,$1BA32),(Portable,$1480E)
SpaceAt ROMBind (Plus,$142B4),(SE,$0E8C8),(II,$13202),(IIci,$1BA7E),(Portable,$1485A)
CheckGrowAt1 ROMBind (Plus,$1435C),(SE,$0E970),(II,$132AA),(IIci,$1BB26),(Portable,$14902)
RefHandle ROMBind (Plus,$14570),(SE,$0EB94),(II,$134CE),(IIci,$1BD4A),(Portable,$14B26)
AddNewRefWithoutUpdate ROMBind (Plus,$14622),(SE,$0EC84),(II,$135BE),(IIci,$1BE3A),(Portable,$14C16)
AddName ROMBind (Plus,$1477A),(SE,$0ED9C),(II,$136D6),(IIci,$1BF52),(Portable,$14D2E)
AfterSetEOFInCheckGrow ROMBind (Plus,$1436C),(SE,$0E980),(II,$132BA),(IIci,$1BB36),(Portable,$14912)
ROMs Plus,SE,II,IIci,Portable
kOSDispatchTrap equ $A88F
kUnimplementedTrap equ $A89F
kMaxOpenFontFiles equ 128 ; <34>
;____________________________________________________________________________________________________
; ResourceDispatch
ResourceDispatch BeginDispatcher _ResourceDispatch
DispatchSelectors CloseResFileUnderSystemMap = selectCloseResFileUnderSystemMap
DispatchSelectors ResolveIDConflicts = selectResolveIDConflicts
DispatchSelectors OpenResFileUnderSystemMap = selectOpenResFileUnderSystemMap
DispatchSelectors IsThisASystemResourceMap = selectIsThisASystemResourceMap
DispatchSelectors GetMap = selectGetMap
DispatchSelectors ReadPartialResource = selectReadPartialResource
DispatchSelectors WritePartialResource = selectWritePartialResource
DispatchSelectors SetResourceSize = selectSetResourceSize
DispatchSelectors MakeOverrideMap = selectMakeOverrideMap
DispatchSelectors InsertOverrideMap = selectInsertOverrideMap
DispatchSelectors GetOverrideMap = selectGetOverrideMap
DispatchSelectors SetScanOverride = selectSetScanOverride
DispatchSelectors GetOverrideAttributes = selectGetOverrideAttributes
DispatchSelectors SetOverrideAttributes = selectSetOverrideAttributes
DispatchSelectors GetNextFOND = selectGetNextFOND
EndDispatcher
;____________________________________________________________________________________________________
; <23> ResolveIDConflicts(refNum: Integer): Boolean;
;
; This routine ensures that any font resource IDs in the resource map specified by
; refNum do not match that of any font resources already in the resource chain. If
; conflicts are found, the conflicting font is renumbered. The changes are written
; out to disk. A boolean value is returned specifying whether or not a conflict was
; found. 'FOND' conflicts are resolved by picking a new random family number, with
; checks to ensure the new number is unique.
;
; A sketch of the ID resolution algorithm follows:
;
; Take resource map out of chain
; For each 'FOND' in resource map
; Get id and name
; Swap chain
; Look for name in main chain <24>
; If name exists, and the IDs are different, set ID of 'FOND' to existing ID <24>
; Else <24>
; Look for id in main chain
; Get name of 'FOND' in main chain
; If names match, leave alone,
; Else
; Find unique ID in main chain
; Swap chain
; Make sure ID is not duplicated in resource map
; Renumber
; End
; End
; End
; For each entry in FAT
; Get 'FONT' or 'NFNT' resource
; Make sure ID is unique in both chains
; If ID is not unique, get a unique one
; Remember original ID and new ID in a table for other 'FOND's <57>
; End
; End
; Insert resource map back in chain
; Flush 'FOND' candidate cache <27>
;
; Register conventions
;
; A4 - Handle to current 'FOND' resource
; A3 - Pointer into font association table
; D7 - _GetIndResource index
; D6 - RefNum of top resource map in main chain
; D5 - Upper bound of resource IDs for this script
; D4 - Lower bound of resource IDs for this script
;
ConflictStackFrame Record {A6Link},Decr
hadConflict ds.w 1 ; Boolean result
paramBegin equ *
refNum ds.w 1 ; RefNum of resource map to resolve
paramSize equ paramBegin - *
retAddr ds.l 1
A6Link ds.l 1
mapToRenumber ds.l 1 ; <29> Map that has just been inserted, and contains the fonts to renumber.
mapAbove ds.l 1 ; Map above this one in chain
mapBelow ds.l 1 ; Map below it in chain
mainChain ds.l 1 ; Main resource chain
currentTopMap ds.l 1 ; <26> Real top of resource chain.
currentMap ds.w 1 ; Real CurMap
resLoadState ds.w 1 ; Real ResLoad
resType ds.l 1 ; Type of resource
resID ds.w 1 ; ID of resource
resName ds.b 256 ; Name of resource
mainResType ds.l 1 ; Type of resource in main chain
mainResID ds.w 1 ; ID of resource in main chain
mainResName ds.b 256 ; Name of resource in main chain
scriptBase ds.w 1 ; Base family ID for script
familyHint ds.w 1 ; <37> Hint for family number
fontHint ds.w 1 ; Hint for font resource number
existingFamilyID ds.w 1 ; <24> ID for existing family
fontAlreadyLoaded ds.w 1 ; <46> Set to non-zero if someone else loaded the 'FONT' resource.
newFONDAlreadyLoaded ds.w 1 ; <52> Set to non-zero if the 'FOND' being renumbered is already in memory.
fromToTable ds.l 1 ; <56> List of original/new ID pairs for renumbered fonts.
localSize equ *
EndR
ResolveIDConflicts Proc Export
Import FindNewFamilyNumber
Import ValidateFontResourceIDs
Import ReleaseTheFont
With ConflictStackFrame
link a6,#localSize
movem.l a1-a4/d3-d7,-(sp)
clr.w hadConflict(a6) ; Assume no conflict
clr.w scriptBase(a6) ; <37> Initialize font number hint based on a script number
clr.l fromToTable(a6) ; <57> Initialize from-to table
move.w #256,familyHint(a6) ; <37> Initialize the id hinting field to be the lowest valid font id in the range reserved for renumbered fonts.
moveq #0,d7 ; Initialize index for _GetIndResource
move.l TopMapHndl,currentTopMap(a6) ; <26>
move.w CurMap,currentMap(a6)
move.b ResLoad,resLoadState(a6)
sf ResLoad ; <27> DonÕt load subsequent font resources
;
; Find the resource map in the chain and remove it
;
move.w refNum(a6),d0
moveq #0,a0 ; Map above
moveq #0,a1 ; Map below
move.l TopMapHndl,mapToRenumber(a6) ; <29> Start with top map in chain
@findMap
move.l mapToRenumber(a6),a2 ; <29>
move.l (a2),a2 ; <29> Get map pointer
move.l mNext(a2),a1 ; Remember map below
cmp.w mRefNum(a2),d0 ; Is this the right map?
beq.s @removeMapFromChain ; Yes. Go on
move.l mapToRenumber(a6),a0 ; <29> Remember map above
move.l a1,mapToRenumber(a6) ; Try next map
bz @exitResolve ; Hope Claris doesnÕt sueÉ
bra.s @findMap
;
; Remove the map from the chain
;
@removeMapFromChain
move.l a0,mapAbove(a6) ; Save mapAbove
move.l a1,mapBelow(a6) ; Save mapBelow
move.l a0,d0 ; Check to see if this is the first map
bnz.s @notTopMap
move.l a1,TopMapHndl ; New top resource map
bra.s @rejoin
@notTopMap
move.l (a0),a0 ; Pointer to map above
move.l a1,mNext(a0) ; Point around this map
@rejoin
clr.l mNext(a2) ; Now itÕs out of the chain
move.l TopMapHndl,a0 ; Get TopMapHndl now that resource map is out of chain
move.l a0,mainChain(a6) ; Save the main resource chain
move.l (a0),a0
move.w mRefNum(a0),d6 ; Remember itÕs reference number
;
; Loop through all the 'FOND' resources
;
move.l mapToRenumber(a6),TopMapHndl ; <29> Work with the lone resource map
move.w refNum(a6),CurMap ; Set up CurMap, too
@getNextFontFamily
addq #1,d7 ; Bump index
subq #4,sp
move.l #'FOND',-(sp) ; Look for font families
move.w d7,-(sp) ; Current index
_GetIndResource
move.l (sp)+,d0 ; Get handle to 'FOND'
bz @replaceMapInChain ; If no more resources, weÕre done
;
; Get the name and ID of the resource
;
@getFontFamilyName
move.l d0,a4 ; Save the resource handle
btst #kDeanBit,kBrianBits ; <53> See if we loaded the resource
seq newFONDAlreadyLoaded(a6) ; <52> <53> Set to true if the 'FOND' that is being renumbered is already in memory.
move.l a4,-(sp) ; <27>
_LoadResource ; <27> Use _LoadResource instead of dinking around with ResLoad
move.l a4,-(sp)
pea resID(a6)
pea resType(a6)
pea resName(a6)
_GetResInfo ; Get some information about the FOND
;
; <24> See if this family name exists with another ID in the main resource chain
;
move.l mainChain(a6),TopMapHndl ; Look in the main resource chain
move.w d6,CurMap
subq #4,sp
move.l #'FOND',-(sp)
pea resName(a6)
_GetNamedResource ; Look for font family by name
move.l (sp)+,d0
bz.s @lookForSameID ; This font family isnÕt around. Check for conflicts with other families
move.l d0,a0 ; <46>
btst #kDeanBit,kBrianBits ; <53> See if we loaded the resource
seq fontAlreadyLoaded(a6) ; <46> <53> Set our flag accordingly.
;
; <24> This font family already exists in the resource chain. Check the family number to
; make sure the two IDs match. If not, renumber the font family that is being placed
; in the Fonts Folder to the family ID of the family thatÕs already there.
;
move.l d0,-(sp) ; Push a second copy of the resource handle for call to ReleaseTheFont
move.l d0,-(sp)
pea mainResID(a6)
pea mainResType(a6)
pea mainResName(a6)
_GetResInfo ; Get info about font family in main chain
move.w mainResID(a6),d0 ; <27>
cmp.w resID(a6),d0 ; <27> See if the IDs match.
beq.s @newFamilyIDMatchesExistingOne ; <27> They do. DonÕt have to renumber.
move.w mainResID(a6),existingFamilyID(a6) ; <24> Change to this ID without using hinting.
move.w #1,-(sp) ; <27> Pass the fact that weÕre renumber to an existing ID as a parameter in case weÕre renumbering to the System font.
bsr FindNewFamilyNumber
@newFamilyIDMatchesExistingOne
move.l mainChain(a6),TopMapHndl ; Look in the main resource chain
move.w d6,CurMap
bsr ReleaseTheFont ; Done with the 'FOND' from the main chain
bra.s @checkFontResources
;
; Look for a font family with the same ID in the main resource chain
;
@lookForSameID
subq #4,sp
move.l #'FOND',-(sp)
move.w resID(a6),-(sp) ; Look for the same resource ID
_GetResource
move.l (sp)+,d0 ; Get the resource handle
bz.s @checkFontResources ; This ID doesnÕt exist. Validate other font resources.
move.l d0,a0 ; <46>
btst #kDeanBit,kBrianBits ; <53> See if we loaded the resource
seq fontAlreadyLoaded(a6) ; <46> <53> Set our flag accordingly.
;
; Found an ID match. Get the name to see if itÕs the same family.
;
@gotSameID
move.l d0,-(sp) ; Push a copy of the 'FOND' for ReleaseTheFont.
move.l d0,-(sp)
pea mainResID(a6)
pea mainResType(a6)
pea mainResName(a6)
_GetResInfo ; Get info about font family in main chain
bsr ReleaseTheFont ; Done with the 'FOND' from the main chain
;
; Compare the resource names of the two font family resources
;
@compareFamilyNames
lea resName(a6),a0
lea mainResName(a6),a1
moveq #0,d0
move.b (a0)+,d0 ; Get length of a name
swap d0 ; <43> Length of first string in high word
move.b (a1)+,d0 ; <43> Get length of the other name
_CmpString ; <43> Call _EqualString
tst.l d0 ; <43> Check result
bz.s @checkFontResources ; Yes. The two are of the same family
;
; The IDs match, but the family names are different. Give this 'FOND' a new resource ID.
;
clr.w -(sp) ; <27> Renumber to a non existent number.
bsr FindNewFamilyNumber ; Get a new family number
;
; The family number is ok. (Whether it was resolved, or it was fine in the first place.)
; Check the 'FONT', 'NFNT', and 'sfnt' resource IDs in this font family for conflicts.
;
@checkFontResources
bsr ValidateFontResourceIDs
;
; Everything checks out. Get the next font family.
;
move.l mapToRenumber(a6),TopMapHndl ; <27> <29> Work with the lone resource map
move.w refNum(a6),CurMap ; <27> Set up CurMap, too
move.l a4,-(sp) ; <27> All done with this 'FOND'. Release it.
move.w newFONDAlreadyLoaded(a6),fontAlreadyLoaded(a6) ; <52> Decided whether or not to leave the renumbered 'FOND' in memory.
bsr ReleaseTheFont ; <27>
bra.s @getNextFontFamily ; All done. Get the next font family
;
; Insert the map back into the chain
;
@replaceMapInChain
move.l mapToRenumber(a6),a1 ; <29>
move.l mapAbove(a6),d0 ; Get map above
bnz.s @notTopMapReplace
move.l a1,TopMapHndl ; <29> Put it back on top
bra.s @rejoinReplace
@notTopMapReplace
move.l d0,a0
move.l (a0),a0 ; Pointer to map above
move.l a1,mNext(a0) ; <29> Restore chain above map
@rejoinReplace
move.l (a1),a0 ; <29> Pointer to map
move.l mapBelow(a6),mNext(a0) ; Restore chain underneath map
;
; Flush the 'FOND' candidate list in case anything in the cache was unloaded during the
; renumber. (The handle in the candidate list wonÕt do us much good nowÉ)
;
move.l fromToTable(a6),d0 ; <57>
bz.s @noFromToTable ; <57> No from-to table was created.
move.l d0,a0 ; <57>
_DisposeHandle ; <57> Dispose the from to table for this file.
@noFromToTable
tst.w hadConflict(a6) ; <27> DonÕt flush if no renumbering happened.
bz.s @exitResolve ; <27>
move.l ExpandMem,a1 ; <27>
move.l ExpandMemRec.emSplineKey(a1),a1 ; <27> Get handle to TrueType globals
move.l (a1),a1 ; <27> Point to it.
lea splineKeyRec.fondCache(a1),a1 ; <27> Point to candidate cache
move.l (a1),d0 ; <27> <28>
bz.s @nextCandidate ; <28>
move.l d0,a0 ; <28>
_DisposeHandle ; <27> Get rid of this cached entry
@nextCandidate ; <28>
clr.l (a1)+ ; <27>
move.l (a1),d0 ; <27> Nail the next one too
bz.s @updateResourceMap ; <28>
move.l d0,a0 ; <28>
_DisposeHandle ; <27>
clr.l (a1) ; <27>
@updateResourceMap
move.w refNum(a6),-(sp) ; <28>
_UpdateResFile ; <28> Update the resource map to catch any font renumbering.
@exitResolve
move.l currentTopMap(a6),TopMapHndl ; <26>
move.w currentMap(a6),CurMap
move.b resLoadState(a6),ResLoad
movem.l (sp)+,a1-a4/d3-d7
unlk a6
move.l (sp)+,a0
addq #paramSize,sp
jmp (a0)
EndProc
;
; Find a new font family number for the 'FOND' resource. The new ID will be in the
; range based on the script system the font family belongs to.
;
FindNewFamilyNumber Proc Export
Import ReleaseTheFont
With ConflictStackFrame
move.w fontAlreadyLoaded(a6),-(sp) ; <52> Save ResolveIDConflictÕs value of this flag before this routine uses it.
tst.w 6(sp) ; <27> <52> See if weÕre looking for a unique number, or if weÕre mapping to an existing ID.
bnz @renumberToExistingFamilyNumber ; <24>
move.w resID(a6),d5 ; Get the resource ID of the 'FOND'
andi.w #$FF00,d5 ; Get the lower bound of the range for the script this font belongs to
move.w d5,d4 ; Save it off
addi.w #$1FF,d5 ; Figure out the upper bound
tst.w d4 ; Check lower bound
bnz.s @notRomanFont
move.w #256,d4 ; Start numbering Roman fonts at 256
move.w #1023,d5 ; Roman fonts have an reserved range for duplication
@notRomanFont
cmp.w scriptBase(a6),d4 ; Check to make sure that the ID hint is valid for this script system
beq.s @hintIsValid
move.w d4,scriptBase(a6) ; New script base
move.w d4,familyHint(a6) ; <37> New family ID hint
@hintIsValid
;
; All the ranges are set up. Find a new resource ID in this range that is unique in both
; the main chain and this resource map.
;
move.w familyHint(a6),d3 ; <37> Get ID hint
@findUniqueNumber
subq #4,sp
move.l #'FOND',-(sp)
move.w d3,-(sp) ; See if this ID is used
_GetResource ; Look for it in the main chain
move.l (sp)+,d0
bz.s @gotFreeID ; <46> This ID is not used
move.l d0,a0 ; <46>
btst #kDeanBit,kBrianBits ; <53> See if we loaded the resource
seq fontAlreadyLoaded(a6) ; <46> <53> And set our marker accordingly
bra.s @tryAnotherNumber ; <46> And look for another ID
;
; This ID is free in the main chain. Double check in the resource map to make sure itÕs
; not taken.
;
@gotFreeID
move.l mapToRenumber(a6),TopMapHndl ; <29> Work with the loner
move.w refNum(a6),CurMap
subq #4,sp
move.l #'FOND',-(sp)
move.w d3,-(sp) ; See if this ID is used
_GetResource ; Look for it in the resource map
move.l (sp)+,d0 ; Is it taken?
bz.s @foundFreeID ; No. Go ahead and use it
clr.w fontAlreadyLoaded(a6) ; <46> We want to unload the 'FOND' from the loner file
@tryAnotherNumber
move.l d0,-(sp)
bsr ReleaseTheFont ; DonÕt keep it hanging around
@gotOriginalID ; <36>
addq #1,d3
cmp.w d5,d3 ; Check against the upper bound
bhi.s @exit ; No free IDs left! (Wow!)
cmp.w resID(a6),d3 ; Check against the original ID
beq.s @gotOriginalID ; <36> If it is, try another one
move.l mainChain(a6),TopMapHndl ; Set up to look in the main chain
move.w d6,CurMap
bra.s @findUniqueNumber ; Try this one for size
;
; <24> The font family exists with another number. Renumber the 'FOND' in the new font
; file to this number.
;
@renumberToExistingFamilyNumber
move.l mapToRenumber(a6),TopMapHndl ; <29> Work with the loner
move.w refNum(a6),CurMap
move.w existingFamilyID(a6),d3 ; <27> Get ID to renumber to.
;
; Got an ID which is not used by another font family. Set up the hint for next time,
; and renumber this 'FOND' resource.
;
@foundFreeID
move.l (a4),a0 ; <24>
move.w d3,ffFamID(a0) ; <24> Save new family ID in 'FOND' resource
move.l a4,-(sp) ; Handle to 'FOND' resource
move.w d3,-(sp) ; New resource ID
clr.l -(sp) ; Leave the name alone
_SetResInfo ; Change the ID
move.l a4,-(sp) ; <24>
_ChangedResource ; <24> Mark 'FOND' as changed
move.l a4,-(sp) ; <27>
_WriteResource ; <27> Write out the changes now so the FOND can be unloaded.
tst.w 4(sp) ; <24> Are we renumbering to an existing family?
bnz.s @existingFamilyExit ; <24> Yes. DonÕt mess with the hint.
addq #1,d3
move.w d3,familyHint(a6) ; <37> For fonts of the same script, start looking here next time around
@existingFamilyExit
st hadConflict(a6) ; Report a conflict occured
@exit
move.w (sp)+,fontAlreadyLoaded(a6) ; <52> Restore ResolveIDConflictÕs value
move.l (sp)+,a0 ; Get return address
addq #2,sp ; Pop parameter
jmp (a0) ; Return to caller
EndProc
;
; Make sure 'sfnt', 'NFNT', and 'FONT' resource IDs donÕt conflict.
;
ValidateFontResourceIDs Proc Export
Import FontResourceType
Import ReleaseTheFont
Import FindIDInFromToList ; <57>
Import NewFromToEntry ; <57>
With ConflictStackFrame
move.w fontAlreadyLoaded(a6),-(sp) ; <52> Save ResolveIDConflictÕs value of this flag
move.l mapToRenumber(a6),TopMapHndl ; <29> Make sure weÕre reading out of the right map
move.w refNum(a6),CurMap
tst.l (a4) ; See if the 'FOND' needs to be loaded
bnz.s @isLoaded
move.l a4,-(sp)
_LoadResource ; Load in the 'FOND' now
@isLoaded
move.l a4,a0 ; We donÕt need to save the handle state since the resource will be released shortly
_HLock ; Lock it down while weÕre working with it
;
; Make sure the resource ID of each entry in the font association table is unique
;
move.l (a4),a3
lea FontFamilyRecord.FONDAssoc(a3),a3 ; Get a pointer to the association table
move.w (a3)+,d4 ; Get number of entries in this table
bmi @exit ; Empty font
clr.w fontHint(a6) ; Start afresh for every 'FOND'
; Calculate the size weÕll need in a from-to list for this 'FOND'
moveq #0,d2 ; <57>
move.w d4,d2 ; <57> Get the number of association table entries
addq #1,d2 ; <57> FAT counts are zero based.
asl.l #2,d2 ; <57> Convert entry count into table size: 4 bytes per entry (2 for from ID, 2 for to ID).
; See if a new from-to list needs to be created.
move.l fromToTable(a6),d1 ; <57> Is there a from-to list already?
bnz.s @resizeExistingFromToList ; <57> Yes. Resize it so thereÕs enough space for all the association entries in this 'FOND'.
; Create a new from-to list.
move.l d2,d0 ; <57> Create a handle of the size we calculated earlier
addq #2,d0 ; <57> Allocate an extra word for the number of entries in the from-to table
_NewHandle ,Sys,Clear ; <57> Create the handle
bnz @noFontsRenumbered ; <57> If we couldnÕt allocate the table, donÕt renumber any fonts.
move.l a0,fromToTable(a6) ; <57> Keep a handle on the list
move.l (a0),a0 ; <57>
move.w #-1,(a0) ; <57> Initialize the count.
bra.s @checkNextFont ; <57> And go check out some fonts
; Resize the existing from-to list to be able to fit from-to entries from this 'FOND'.
@resizeExistingFromToList
move.l d1,a0 ; <57> Get the handle to the from-to list
_GetHandleSize ; <57> Get the size of the current from-to list
add.l d2,d0 ; <57> Add in the size weÕll need
_SetHandleSize ; <57> Grow the handle
bnz @noFontsRenumbered ; <57> Bail if the handle couldnÕt grow
@checkNextFont
move.w (a3),d0 ; Get the size
;
; Get the resource type for this entry. If we successfully get a type, then we assume that
; this is the first time weÕve encountered this font resource, and we donÕt have an entry
; for it in our from-to table, so look for any conflicts.
;
@getFontResourceType
move.l mapToRenumber(a6),TopMapHndl ; <29> Make sure weÕre reading out of the right map
move.w refNum(a6),CurMap
subq #4,sp
move.w 4(a3),-(sp) ; Resource ID
bsr FontResourceType ; Figure out resource type for this entry
move.l (sp)+,d3 ; Get the type. The handle comes back in A2.
bnz @checkForConflicts ; <57> If we have a type, go see if the ID conflicts with anything
;
; Not taking that last branch means that we couldnÕt find a font resource with the ID
; specified in the font association table. This means that either the 'FOND' is corrupt,
; or that the font resource got renumbered because it is referenced in another 'FOND' in
; this file. Call FindIDInFromToList to determine if this font resource has already been
; renumbered.
;
subq #2,sp ; <57>
move.w 4(a3),-(sp) ; <57> Pass the ID to look for
bsr FindIDInFromToList ; <57> Go find the ID
move.w (sp)+,d2 ; <57> FindIDInFromList will return the ID to renumber to, or -1 if this ID wasnÕt in the table
cmpi.w #-1,d2 ; <57> Did we get back a -1?
bne @changeFATEntry ; <57> This font was already renumbered. Just change the font association table entry.
bra @nextTableEntry ; <57> A -1 means that this ID isnÕt in our list, so this 'FOND' entry is probably bad.
;
; See if the ID conflicts with a font resource in the main chain.
;
@checkForConflicts
move.l mainChain(a6),TopMapHndl
move.w d6,CurMap ; Looking for unique IDs in main chain
subq #4,sp
move.l d3,-(sp) ; Look for this resource type in the main chain
move.w 4(a3),-(sp) ; Look for this ID.
_GetResource ; Does it exist?
move.l (sp)+,d0
bne.s @conflictOccured ; This number is used
cmpi.l #'FONT',d3 ; <mc3> If it is a FONT, also check for NFNT conflicts
beq.s @checkForNFNTs ; <mc3>
cmpi.l #'NFNT',d3 ; <mc3> If it is a NFNT, also check for FONT conflicts
beq.s @checkForFONTs ; <mc3>
bra @nextTableEntry ; <mc3> If it is a sfnt or other, go on to the next one.
@checkForFONTs
subq #4,sp ; <mc3>
move.l #'FONT',-(sp) ; <mc3> Look for FONT type in the main chain
move.w 4(a3),-(sp) ; <mc3> Look for this ID.
_GetResource ; <mc3> Does it exist?
move.l (sp)+,d0 ; <mc3>
bz @nextTableEntry ; <mc3> This number is fine
bra.s @conflictOccured
@checkForNFNTs
subq #4,sp ; <mc3>
move.l #'NFNT',-(sp) ; <mc3> Look for NFNT type in the main chain
move.w 4(a3),-(sp) ; <mc3> Look for this ID.
_GetResource ; <mc3> Does it exist?
move.l (sp)+,d0 ; <mc3>
bz @nextTableEntry ; <mc3> This number is fine
@conflictOccured
move.l d0,a0 ; <46>
btst #kDeanBit,kBrianBits ; <53> See if we loaded the resource
seq fontAlreadyLoaded(a6) ; <46> <53> And set our marker accordingly
;
; If it does, find a unique ID.
;
@getUniqueID
move.l d0,-(sp)
bsr ReleaseTheFont ; Release the font from the main chain first
move.l mainChain(a6),TopMapHndl
move.w d6,CurMap ; Looking for unique IDs in main chain
subq #2,sp
move.l d3,-(sp)
_UniqueID ; Get a new ID
move.w (sp)+,d2 ; Get the ID
;
; Make sure this ID is not used in the resource map.
;
cmpi.l #'FONT',D3
beq.s @isFONT
cmpi.l #'NFNT',D3
beq.s @isNFNT
bra.s @isNeither
@isNFNT subq #4,SP
move.l #'FONT',-(SP)
move D2,-(SP)
_GetResource
move.l (SP)+,D0
beq.s @isNeither
bra.s @getUniqueID
@isFONT subq #4,SP
move.l #'NFNT',-(SP)
move D2,-(SP)
_GetResource
move.l (SP)+,D0
bne.s @getUniqueID
@isNeither
move.l mapToRenumber(a6),TopMapHndl ; <29> Make sure weÕre reading out of the right map
move.w refNum(a6),CurMap
subq #4,sp
move.l d3,-(sp) ; Push the resource type
move.w d2,-(sp)
_GetResource ; Try to get a similar resource
move.l (sp)+,d0 ; Check it out
bnz.s @getUniqueID ; Try again
cmpi.l #'FONT',D3
beq.s @isFONT2
cmpi.l #'NFNT',D3
beq.s @isNFNT2
bra.s @@isNeither
@isNFNT2 subq #4,SP
move.l #'FONT',-(SP)
move D2,-(SP)
_GetResource
move.l (SP)+,D0
beq.s @@isNeither
bra @getUniqueID
@isFONT2 subq #4,SP
move.l #'NFNT',-(SP)
move D2,-(SP)
_GetResource
move.l (SP)+,D0
beq.s @@isNeither
bra @getUniqueID
@@isNeither
; We have a unique ID. Put it and the original in the from-to list.
move.w d2,-(sp) ; <57> Pass new ID
move.w 4(a3),-(sp) ; <57> Pass original ID
bsr NewFromToEntry ; <57> Put it in the list
;
; Change the font resourceÕs ID number.
;
move.l a2,-(sp) ; Be prepared to change the resource ID
move.w d2,-(sp)
clr.l -(sp) ; Keep the old name, if any.
_SetResInfo ; Set the new ID
@changeFATEntry
move.w d2,4(a3) ; Save the new ID in the association table
st hadConflict(a6) ; <27> Report that a conflict was fixed.
;
; Work on the next entry now.
;
@nextTableEntry
lea FAssocSiz(a3),a3 ; Next entry
dbra d4,@checkNextFont ; Go again
@exit
tst.w hadConflict(a6) ; <28> If a font resource was renumbered, the 'FOND' needs to be written out too.
bz.s @noFontsRenumbered ; <28>
move.l mapToRenumber(a6),TopMapHndl ; <30> Make sure weÕre working with the right map
move.w refNum(a6),CurMap ; <30>
move.l a4,-(sp)
_ChangedResource ; Mark the 'FOND' as being changed.
move.l a4,-(sp) ; <27>
_WriteResource ; <27> Write out the changes now so the FOND can be unloaded.
@noFontsRenumbered
move.w (sp)+,fontAlreadyLoaded(a6) ; <52> Restore ResolveIDConflictÕs setting
rts
EndProc
; Given a resource ID, look for it in the from-to list. If the ID is there, pass back
; the ID the font should be renumbered to.
FindIDInFromToList Proc Export ; <57>
With ConflictStackFrame ; <57>
move.l (sp)+,a0 ; <57>
move.w (sp)+,d0 ; <57> Get the resource ID
move.l a0,-(sp) ; <57> Push the return address back on the stack
move.l fromToTable(a6),a0 ; <57>
move.l (a0),a0 ; <57> Get pointer to from-to list
move.w (a0)+,d1 ; <57> Get number of entries
bmi.s @noFromID ; <57> If the list is empty, just bail
; Scan the list for the given ID
@searchFromToList
cmp.w (a0)+,d0 ; <57> Does this from number match?
beq.s @gotMatchInList ; <57> Yep. Return the corresponding to value
addq #2,a0 ; <57> Skip to the next entry
dbra d1,@searchFromToList ; <57> Try it
@noFromID
moveq #-1,d0 ; <57> No match. Return #-1
bra.s @returnToValue ; <57>
; Got a match. Return the following to value
@gotMatchInList
move.w (a0)+,d0 ; <57> Get the to value
@returnToValue
move.w d0,4(sp) ; <57> Put the result on the stack
rts
EndProc
; Given an original ID and a new ID, save it at the end of the from-to list
NewFromToEntry Proc Export ; <57>
With ConflictStackFrame ; <57>
move.l (sp)+,a0 ; <57>
move.l (sp)+,d1 ; <57> Get from-to pair. (From in high word, to in low word)
move.l a0,-(sp) ; <57> Put return address back on stack
move.l fromToTable(a6),a0 ; <57>
move.l (a0),a0 ; <57> Get pointer to from-to list
moveq #0,d0 ; <57>
move.w (a0),d0 ; <57> Get the current number of entries in the list
addq #1,d0 ; <57> Bump the count
move.w d0,(a0)+ ; <57> Save the new count, and point to the first entry
asl.l #2,d0 ; <57> Multiply to get the offset to the new entry
move.l d1,0(a0,d0.w) ; <57> Save the from-to pair
rts ; <57>
EndProc
;
; For an entry in the font association table, determine whether the entry refers to a
; 'sfnt', 'FONT' or 'NFNT' resource, and return the correct type. The type is returned on the
; stack, and the handle to the resource is returned in A2.
;
FontResourceType Proc Export
move.l (sp)+,a0 ; Get return address
move.w (sp)+,d2 ; Get resource ID
move.l a0,-(sp) ; Save return address again
lea FontResourceTypes,a2 ; Get type list table
@getFontResource
move.l (a2)+,d3 ; Get a type
bz.s @noFontResource
subq #4,sp
move.l d3,-(sp) ; Resource type
move.w d2,-(sp) ; Resource ID
_GetResource ; Get the font resource
move.l (sp)+,d0
bnz.s @gotFontResource ; Got a font
bra.s @getFontResource ; Otherwise, try again
;
; No font resource with the specified ID could be found.
;
@noFontResource
moveq #0,d0 ; DonÕt return a handle
moveq #0,d3 ; DonÕt return a type
@gotFontResource
move.l d0,a2 ; Return handle to font resource in A2
move.l d3,4(sp) ; Return type on stack
rts
FontResourceTypes
String AsIs
dc.l 'sfnt','NFNT','FONT',0
EndProc
;
; The Process Manager doesnÕt let fonts get released, but I know what IÕm doing.
; Instead of calling _ReleaseResource, call _DetachResource then _DisposeHandle
; to free up the memory used up by the font.
;
ReleaseTheFont Proc Export
With ConflictStackFrame
move.l (sp)+,d1 ; Save the return address
tst.b fontAlreadyLoaded(a6) ; <46> See if we loaded the font <SM15>
bz.s @weLoadedTheFont ; <46> If we did, then unload it
addq #4,sp ; <46> If it was already loaded when we got our hands on it, leave it alone.
clr.w fontAlreadyLoaded(a6) ; <46> And clear this flag for the next time.
bra.s @exitReleaseTheFont ; <46>
@weLoadedTheFont
move.l (sp),a1 ; Get a copy of the resource handle
_DetachResource ; Detach it to fake out the Process Manager
move.l a1,a0
_DisposeHandle ; Dispose it like a normal handle
@exitReleaseTheFont
move.l d1,a0
jmp (a0) ; Return to the caller
EndProc
;____________________________________________________________________________________________________
; <48> CloseResFileUnderSystemMap(refNum: Integer);
;
; This routine closes files that were opened with the OpenResFileUnderSystemMap call.
; If the file is a font file in the Fonts Folder, it will decrement the count of open
; font files accordingly.
;
CloseResFileUnderSystemMap Proc Export
Import IsThisAFontFileInTheFontsFolder
StackFrame Record {A6Link},Decr
paramBegin equ *
refNum ds.w 1
paramSize equ paramBegin - *
retAddr ds.l 1
A6Link ds.l 1
folderVRefNum ds.w 1
folderDirID ds.l 1
localSize equ *
EndR
With StackFrame
link a6,#localSize
movem.l d6/a3/a4,-(sp)
; First, check to see if this is a real file in the resource chain. Since the map handle
; will be needed later, let _GetMap do all the work.
move.w refNum(a6),d6
subq #4,sp
move.w d6,-(sp)
_GetMap ; Get resource map for this file
move.l (sp)+,d0 ; Got one?
bz @exitCloseResFileUnderSystemMap ; No. Get out.
; Get a pointer to this fileÕs FCB.
move.l d0,a3 ; Save resource map handle
move.l FCBsPtr,a4 ; Get pointer to FCB array
add.w d6,a4 ; Address of FCB for file to be closed.
; See if this file is a font file
move.l fcbFType(a4),-(sp) ; Get this fileÕs type
move.l fcbDirID(a4),-(sp) ; And the folder itÕs in.
bsr IsThisAFontFileInTheFontsFolder ; See if this is a font file
bz.s @validateTwoDeepBit ; ItÕs not. Close it.
; This file is in the Fonts folder. Decrement the count of open font files.
move.l ExpandMem,a0
sub.w #1,ExpandMemRec.emOpenFontFiles(a0)
; <56> See if the last used font came from this file. If it did, invalidate that global
; as well.
move.l ExpandMemRec.emSplineKey(a0),a0 ; <56> Why on earth did I ever put
move.l (a0),a0 ; <56> this stupid thing in the
cmp.w splineKeyRec.lastFontMap(a0),d6 ; <56> TrueType globals?
bne.s @validateTwoDeepBit ; <56>
clr.w splineKeyRec.lastFontMap(a0) ; <56> The last font came from this file. Reset the global.
; Prepare to close the file
; <55> First, check the two deep bit on this map. If itÕs not set, clear it on the map above
; it in the resource chain.
@validateTwoDeepBit
move.l (a3),a0 ; <55>
btst #twoDeepBit,mInMemoryAttr(a0) ; <55> Is the two deep bit set on the map weÕre closing?
bnz.s @closeTheFile ; <55> If not, donÕt bother with this part
move.l SysMapHndl,d0 ; <55> Start from the system map (since this IS CloseResFileUnderSystemMap).
@findMapAbove
move.l d0,a1 ; <55>
move.l (a1),a0 ; <55>
move.l mNext(a0),d0 ; <55>
bz.s @exitCloseResFileUnderSystemMap ; <55> If the end of the chain is reached before finding the map, just exit.
cmp.l a3,d0 ; <55> Is the map weÕre closing the next one?
bne.s @findMapAbove ; <55> Nope. Try again.
bclr #twoDeepBit,mInMemoryAttr(a0) ; <55> Clear the twoDeep bit on this map.
; Now close the file
@closeTheFile
move.l ExpandMem,a0
tst.w ExpandMemRec.emProcessMgrExists(a0) ; See if Process Manager is around so _BeginSystemMode exists
bz.s @noBeginSystemMode ; ItÕs not. DonÕt call BeginSystemMode
subq #2,sp
_BeginSystemMode ; The file was opened in system mode, so it needs to be closed that way.
addq #2,sp
@noBeginSystemMode
move.l (a3),a0
bclr #preventFileFromBeingClosedBit,mInMemoryAttr(a0) ; Make sure this file can be closed
move.w d6,-(sp)
_CloseResFile ; Really close the file now
move.l ExpandMem,a0
tst.w ExpandMemRec.emProcessMgrExists(a0) ; See if Process Manager is around so _BeginSystemMode exists
bz.s @exitCloseResFileUnderSystemMap ; ItÕs not. DonÕt call EndSystemMode
subq #2,sp
_EndSystemMode
addq #2,sp
@exitCloseResFileUnderSystemMap
movem.l (sp)+,d6/a3/a4
unlk a6
move.l (sp)+,a0
add.w #paramSize,sp
jmp (a0)
EndProc
;____________________________________________________________________________________________________
; <18> OpenResFileUnderSystemMap(fileSpec: FSSpec; permission: SignedByte): Integer;
;
; This routine opens opens the resource file specified by fileSpec, and
; inserts it into the resource chain underneath the System resource map.
; The file is opened in System mode (if _BeginSystemMode and _EndSystemMode
; are implemented) to ensure that these files are not closed when the process
; which made this call quits. If the file is successfully opened, the file
; reference number is returned, or -1 if the file was not opened.
;
OpenResFileUnderSystemMap Proc Export
Import InsertMapUnderSystemMap
Import IsThisAFontFileInTheFontsFolder
Import MarkFileAsOwnedByTheSystem
StackFrame Record {A6Link},Decr
fileRefNum ds.w 1
paramBegin equ *
fileSpec ds.l 1 ; Pointer to file spec
permission ds.w 1 ; <47> File permission.
paramSize equ paramBegin - *
retAddr ds.l 1
A6Link ds.l 1
catInfoRec ds.b ioHFQElSiz ; Parameter block for _GetCatInfo call
currentZone ds.l 1 ; Current zone
realCurMap ds.w 1 ; Current resource map
openingFontFile ds.w 1 ; <34> Non zero if this file is a font file
localSize equ *
EndR
With StackFrame
link a6,#localSize
movem.l a3-a4,-(sp)
move.w CurMap,realCurMap(a6) ; <19> Save CurMap
move.w #-1,fileRefNum(a6) ; Be pessimistic and assume weÕll fail
clr.w openingFontFile(a6) ; <34> Assume itÕs not a font file.
; Get the file type and creator of this file.
move.l fileSpec(a6),a1 ; Get file spec
lea catInfoRec(a6),a0 ; Get the parameter block
clr.l ioCompletion(a0)
pea FSSpec.name(a1) ; Push address of the file name
move.l (sp)+,ioNamePtr(a0) ; And stash the pointer
move.w FSSpec.vRefNum(a1),ioVRefNum(a0)
move.l FSSpec.parID(a1),ioDirID(a0)
clr.w ioFDirIndex(a0) ; DonÕt use indexing
_GetCatInfo ; Get information about a file
move.w d0,ResErr ; Save error, if any
bnz @exit ; Leave if there was an error
; <34> If this file is a font file, see how many font files are already opened before
; trying to open this font file.
move.l ioFlUsrWds+fdType(a0),-(sp) ; <34> Get the file type
move.l ioFlParID(a0),-(sp) ; <48> Pass the parent folder
bsr IsThisAFontFileInTheFontsFolder ; <48> Make sure this is a font file
bz.s @notFontFile ; <48>
; This file is a font file in the fonts folder. See if we can open any more. If not,
; return too many files open.
st openingFontFile(a6) ; <34>
move.l ExpandMem,a0 ; <34>
cmpi.w #kMaxOpenFontFiles,ExpandMemRec.emOpenFontFiles(a0) ; <34> Already at the maximum?
blt.s @canOpenMoreFonts ; <34> No, we can open some more.
move.w #tmfoErr,ResErr ; <34> Return too many files open otherwise.
bra @exit ; <34> Go away.
@canOpenMoreFonts
@notFontFile
move.l TheZone,currentZone(a6) ; Save the current zone
move.l SysZone,TheZone ; Make sure map is opened in the system heap
move.l TopMapHndl,a3 ; Remember current top resource map
subq #2,sp
move.l fileSpec(a6),-(sp) ; Pass file descriptor
move.b permission(a6),-(sp) ; <47> Pass desired permission
_FSpOpenResFile ; Try to open the file
move.w (sp)+,d0
move.w d0,fileRefNum(a6) ; Return the fileRefNum
bmi.s @restoreHeap ; File wasnÕt opened
cmp.l TopMapHndl,a3 ; See if top resource map has changed
bne.s @insertMap ; If it has, file is newly opened
move.w #opWrErr,ResErr ; If file already opened, donÕt let it be moved.
bra.s @restoreHeap
; The file has been opened. Move itÕs resource map down underneath the system file.
@insertMap
move.l TopMapHndl,-(sp) ; FileÕs resource map is at the top of the chain
bsr InsertMapUnderSystemMap ; Insert it.
; If this was a font file, bump the open font file counter.
tst.w openingFontFile(a6) ; <34> Is this a font file?
bz.s @markFileOwner ; <34>
move.l ExpandMem,a0 ; <34> This was a font file
add.w #1,ExpandMemRec.emOpenFontFiles(a0)
@markFileOwner
move.w fileRefNum(a6),d0
bsr MarkFileAsOwnedByTheSystem ; <62<mc2>> Do this instead of opening in system mode
@restoreHeap
move.l currentZone(a6),TheZone ; Restore the current heap
@exit
move.w realCurMap(a6),CurMap ; <19> Restore CurMap
movem.l (sp)+,a3-a4
unlk a6
move.w ResErr,d0 ; Keep ResErr in D0
move.l (sp)+,a0 ; Get return address
addq #paramSize,sp ; Pop parameters
jmp (a0) ; Return to caller
EndProc
;
; <48> This routine checks to see if a file is a font file in the Fonts folder.
; The fileÕs type and parent folder is passed to this routine on the stack.
;
IsThisAFontFileInTheFontsFolder Proc Export
StackFrame Record {A6Link},Decr
paramBegin equ * ; <49>
fileType ds.l 1 ; FileÕs type
parentID ds.l 1 ; FileÕs parent folder
paramSize equ paramBegin - * ; <49>
retAddr ds.l 1
A6Link ds.l 1
folderVRefNum ds.w 1 ; Volume with Fonts Folder
folderDirID ds.l 1 ; Fonts folder directory ID
localSize equ *
EndR
With StackFrame
link a6,#localSize
move.l fileType(a6),d1
lea fileTypeTable,a1 ; <34>
@fileTypeLoop ; <34>
move.l (a1)+,d0 ; <34>
bz.s @exitFontFile ; <34> No more font file types
cmp.l d1,d0 ; <34> Is it a font file?
bne.s @fileTypeLoop ; <34> Nope, try again.
; This is a font file. See if itÕs in the Fonts folder.
subq #2,sp
move.w #kOnSystemDisk,-(sp) ; Look on the System disk
move.l #kFontsFolderType,-(sp) ; Look for the Fonts Folder
move.b #kDontCreateFolder,-(sp) ; DonÕt create it if itÕs not there
pea folderVRefNum(a6)
pea folderDirID(a6)
_FindFolder ; Let _FindFolder do itÕs thing.
tst.w (sp)+ ; Error?
bz @gotFontFolder ; If thereÕs no Fonts folder,
moveq #0,d0 ; this file canÕt be in it.
bra.s @exitFontFile
@gotFontFolder
move.l parentID(a6),d0
cmp.l folderDirID(a6),d0 ; Is the file in the Fonts folder?
bne.s @exitFontFile ; No
moveq #1,d0 ; Set to true if this is a font file
@exitFontFile
unlk a6
move.l (sp)+,a0 ; <49>
addq #paramSize,sp ; <49> Pop parameters
jmp (a0) ; <49>
String Asis ; <34>
fileTypeTable ; <34>
dc.b 'ffil', 'tfil', 'FFIL' ; <34>
dc.l 0 ; <34>
String Pascal ; <34>
EndProc
;
; This routine places a resource map underneath the System file in the resource chain.
;
InsertMapUnderSystemMap Proc Export
move.l 4(sp),d0 ; Handle to font map to insert
move.l d0,a1
move.l (a1),a1
move.l d1,-(sp) ; <55> Dean learns his lesson and saves registers now
ori.b #kDontCountOrIndexDuplicatesMask + \
kTwoDeepMask + \
kPreventFileFromBeingClosedMask,mInMemoryAttr(a1) ; <42>
cmp.l TopMapHndl,d0 ; Moving the top map?
bne.s @notTopMap ; Nope.
move.l mNext(a1),a0 ; Move TopMapHndl down one level
move.l a0,TopMapHndl
@notTopMap
move.l SysMapHndl,a0
move.l (a0),a0
move.l mNext(a0),d1 ; <55> Get the map below the system map
bnz.s @linkInNewMap ; <55> If there is a map, leave the two deep bit set on the new map
@clearTwoDeepBit
bclr #twoDeepBit,mInMemoryAttr(a1) ; <55> If there is no map, clear the two deep bit on the new map.
@linkInNewMap
move.l d1,mNext(a1) ; <55> Put what was below the System file underneath the font
move.l d0,16(a0) ; And put the font after the system file
move.l (sp)+,d1 ; <55>
moveq #0,d0
move.w d0,ResErr ; Never have errors
move.l (sp)+,a0 ; Get return address
addq #4,sp ; Pop parameter
jmp (a0)
EndProc
;____________________________________________________________________________________________________
; IsThisASystemResourceMap(resourceMap: Handle): Boolean;
;
; Given a resource map handle, this routine determines if itÕs the resource map
; resource map was opened the by the system. This is the ensure that fonts in the
; Fonts folder and Gibbly resources are loaded in the System heap.
;
IsThisASystemResourceMap Proc Export
Import GetPSNFromParallelFCB
move.l (sp)+,a0 ; Get return address
move.l (sp)+,d1 ; Get resourceMap
clr.w (sp) ; Default return value
move.l a0,-(sp) ; Put return address back on the stack
clr.w ResErr
tst.l d1 ; Validate resource handle
bnz.s @notNilHandle
move.w #resFNotFound,ResErr ; Stash error
bra.s @exit
@notNilHandle
cmp.l ROMMapHndl,d1 ; <39> Are we looking at the ROM map?
beq.s @isSystemResource ; <39> If so, skip all this and say itÕs a system resource.
move.l d1,a0
move.l (a0),a0
move.w mRefNum(a0),d0 ; Get the file reference number of this map
bsr.l GetPSNFromParallelFCB ; <60> Get the parallel FCB info
; I really should use EqualProcess, but the Process Manager might not be around yetÉ
move.l (a0)+,d0 ; Get high long of PSN
bnz.s @exit ; If not zero, it canÕt be kSystemProcess
cmpi.l #kSystemProcess,(a0) ; <62><mc2> Check low word of PSN.
bne.s @exit
@isSystemResource
move.w #-1,4(sp) ; This is a system resource map
@exit
move.w ResErr,d0
rts
EndProc
; <60> GetPSNFromParallelFCB
;
; This is a copy of the ParallelFCBFromRefNum routine in FileMgrPatches.a. Originally,
; IsThisASystemResourceMap called the file system to get the parallel FCB information
; for a given file. Because this routine is called by GetResource patches, and because
; GetResource is almost always being called, the caused the disk to never spin down on
; the portables, because a file system call was always being queued. This caused
; battery life to go way down with Cube-E. To alleviate this, look at the parallel
; FCB structure ourselves without using the file system. This has problems in itself,
; as we might be making this call when the FCB array is in flux, but those PowerBook
; people are picky about how long they can play Tetris on the airplaneÉ
GetPSNFromParallelFCB Proc Export
movea.l FSVarsPtr,A0
btst.b #3,FSVars.fsFlags(A0)
beq.s @dontHitFS
sub #$32,SP
movea.l SP,A0
cmp #$3,D0
bne.s @L0
moveq.l #$2,D0
@L0 move D0,$18(A0)
moveq.l #$50,D0
_HFSDispatch
cmp #$0,D0
bne.s @L1
movea.l $1C(A0),A0
bra.s @L2
@L1 lea.l 0,A0
@L2 dc.w $defc, $0032
;add #$32,SP ; can't seem to make this look right!
rts
@dontHitFS
andi.l #$FFFF, d0 ; only the low word is passed.
divu.w FSFCBLen,d0 ; convert refnum to an index
movea.l FSVarsPtr,a0 ; get address of HFS variable area
movea.l FSVars.fcbPBuf(a0),a0 ; get address of parallel array
mulu.w cbPBufULen(a0),d0 ; convert file index to parallel array offset
lea fcbPBufData(a0,d0.l),a0 ; a0 -> parallel array element for file
rts
EndProc
; MarkFileAsOwnedByTheSystem
;
; If a file is considered to be a Òsystem fileÓ if the PSN of the process that opened
; the file is kSystemProcess. Under 7.1, we also considered files with a PSN of 0
; to be a system file. This caused problems for extensions that opened files and
; wanted to load resources into their own heap instead of the system heap. In 7.2
; and later, this is no longer the case, so we need to explicitly set the PSN in the
; parallel FCB array to kSystemProcess for font files and override maps. This is what
; this routine does.
;
; Input: D0 Reference number of file to mark
;
MarkFileAsOwnedByTheSystem Proc Export
Import GetPSNFromParallelFCB
move.l a0,-(sp) ; Preserve A0
bsr.l GetPSNFromParallelFCB
clr.l (a0)+ ; Clear high word of PSN
move.l #kSystemProcess,(a0) ; Set the low word
move.l (sp)+,a0 ; Restore A0
rts
EndProc
;_______________________________________________________________________________
; GetMap(refNum: Integer): Handle;
;
; GetMap is a routine that returns the resource map handle of the file specified
; by the reference number on the stack.
;
GetMap Proc Export
GetMapStack Record {A6Link},Decr
mapHandle ds.l 1
paramBegin equ *
mapRefNum ds.w 1
paramSize equ paramBegin - *
retAddr ds.l 1
A6Link ds.l 1
EndR
With GetMapStack
link a6,#0
move.l a1,-(sp)
clr.l mapHandle(a6)
move.w mapRefNum(a6),d0 ; Get current resFile refnum.
bne.s @notSysMap ; If not zero, use standard resource
move.w SysMap,d0 ; Otherwise use refnum of system map
@notSysMap
move.l TopMapHndl,a0 ; Get top map handle
@mapLoop
move.l (a0),a1 ; Dereference
cmp.w MRefNum(a1),d0 ; Is it the right resource map?
beq.s @gotMapHandle ; Yeah, get out.
move.l MNext(a1),d1 ; Get handle to the next map.
beq.s @mapNotFound ; If the handle was nil, not found
move.l d1,a0
bra.s @mapLoop
@gotMapHandle
move.l a0,mapHandle(a6)
bra.s @exitGetMap
@mapNotFound
move.w #resFNotFound,ResErr ; Return an error if the map wasnÕt found
@exitGetMap
move.l (sp)+,a1
unlk a6
move.l (sp)+,a0
addq #paramSize,sp
move.w ResErr,d0
jmp (a0)
EndProc
;____________________________________________________________________________________________________
; ReadPartialResource(theResource:Handle; offset:LongInt; buffer:Ptr; count:LongInt);
ReadPartialResource Proc Export
jsrROM Std1Entry
move.l 20(a6),a1 ; get a copy of the handle into a1
jsrROM RefHandle
bne.s Exit
jsrROM RREntry6 ; set up regs for a read/write (donÕt change attrs)
addq.l #4,d2 ; skip over the length longint
add.l 16(a6),d2 ; add in offset inside this resource
move.l 12(a6),d1 ; get pointer to buffer
move.l 8(a6),d0 ; get amount of data to read
jsrROM RdData ; go read it
Exit
moveq #16,d0 ; pop off 16 bytes of parameters
jmpROM RStdExit ; and exit <25> rb
EndProc
;____________________________________________________________________________________________________
; WritePartialResource(theResource:Handle; offset:LongInt; buffer:Ptr; count:LongInt);
WritePartialResource Proc Export
jsrROM Std1Entry
move.l 20(a6),a1 ; get a copy of the handle into a1
jsrROM RefHandle
bne.s Exit
move.l (a4),a0
tst.b MAttr(a0) ; check if map is read-only
bmi.s MapIsReadOnly ; if high bit is set, map is read-only
jsrROM RREntry6 ; set up regs for a read/write (donÕt change attrs)
addq.l #4,d2 ; skip over the length longint
add.l 16(a6),d2 ; add in offset inside this resource
move.l 12(a6),d1 ; get pointer to buffer
move.l 8(a6),d0 ; get amount of data to write
jsrROM WrData ; go Write it
bra.s Exit ; and exit
MapIsReadOnly
move.w #mapReadErr,ResErr
Exit
moveq #16,d0 ; pop off 16 bytes of parameters
jmpROM RStdExit ; and exit <25> rb
EndProc
;____________________________________________________________________________________________________
; SetResourceSize(theResource:Handle; theSize:LongInt);
; This attempts to set the size of the resource in the resource file.
; If the request is to grow the size of the resource, we first try to grow it in place without
; moving it. This requires enough free space in the file following the resource to extend it
; by the additional amount. If it cannot be sized in place, we extend the file by theSize, then
; move the resource data from the current place in the file to the new room at the end of the file.
SetResourceSize Proc Export
sizeParam equ 8
handleParam equ 12
kMinResourceBuffer equ 2048 ; per BryanÕs request
jsrROM Std1Entry
move.l handleParam(a6),a1 ; get a copy of the resource handle into a1
jsrROM RefHandle ; now a2 is res map entry and a4 points to map
bne Exit
move.l (a4),a0
tst.b MAttr(a0) ; check if map is read-only
bmi SetResSizeMapIsReadOnly ; if high bit is set, map is read-only
move.l sizeParam(a6),d0 ; get the size into d0
cmp.l Lo3Bytes,d0 ; check if making resource larger than 16 megabytes
bge TooBig
; Check if room in current location
jsrROM SpaceAt ; returns size of resource on disk plus the free space after it
move.l sizeParam(a6),d7 ; the new size of resource
addq.l #4,d7 ; 4 bytes for the size field
cmp.l d7,d0 ; size available ³ size needed?
bge WriteSize ; if so just go change size on disk
move.l d0,d7 ; else save current disk space size for later
move.l sizeParam(a6),d1 ; check if disk full
addq.l #4,d1 ; b3b: 4 bytes for the size field.
pea @return ; put return address where CheckGrow expects it
jsrROM SaveRegs ; save registers exactly like CheckGrow does
move.l d2,-(sp)
jmpROM CheckGrowAt1 ; jump into the middle of CheckGrow <SM10> rb
; this tries to add (size + size field) to the file size
; by setting LEOF to LEOF + d1
@return
bne Exit ; give up
; Now with CheckGrowAt1 we have set the file length at the new size, all <SM10> rb
; we need to do is copy the resource from the old location to the new.
; Check for the biggest block available w/o purging. If itÕs smaller than kMinResourceBuffer bytes,
; try a NewPtr of kMinResourceBuffer. This will cause purging. <5>
sub.l (a4),a2 ; turn entry pointer into offset in map because right
; now itÕs a deref'd handle. WeÕll add it back after
; we move memory with the NewPtr <1.9>,<5>
_MaxBlock ; how big a buffer can we get?
cmp.l #kMinResourceBuffer,d0 ; is it at least kMinResourceBuffer? <5>
blo.s @useMinimum ; no, go try to grab it with NewPtr <5>
bra.s @keepGoing ; <5>
@useMinimum
clr.l d0
move.w #kMinResourceBuffer,d0 ; see if we can get the buffer bytes by purging <5>
move.l d0,d4 ; size of buffer <5>
bra.s @getABuffer
@keepGoing ; d0 ³ kMinResourceBuffer <5>
cmp.l d0,d7 ; MaxBlock ³ size needed?
bge.s @gotSmaller ; get min(maxBlock,resourceSize)
move.l d7,d0 ; use just this much
@gotSmaller
move.l d0,d4 ; d4 is size of buffer used later in CopyMore
@getABuffer ; <5>
_NewPtr ; grab a buffer. this works because d0 ² MaxBlock
bnz TooBig ; nope, time to give up <7>
move.l a0,a3 ; save for later use in CopyMore
add.l (a4),a2 ; turn offset in map back into entry pointer <1.9>
; because a2 was a deref'ed handle and we called
; NewPtr. We changed it into an offset, then restored
; it from the handle after memory moved.
move.l (a4),a0 ; point at map
move.l ResMapOffset(a0),d5
add.l MapSize(a0),d5
move.l ResDataOffset(a0),d3
add.l DataSize(a0),d3
cmp.l d3,d5
bge.s @4
move.l d3,d5 ; new offset to the end of data or map, which is
; where the new resource goes. Remember that we
; just extended the end of the file by theSize,
; and that new space starts at d5
@4
sub.l ResDataOffset(a0),d5
move.l d5,-(sp) ; save for later (new offset)
clr.l d3 ; offset index inside old resource data
; b3b: Register usage:
; a0: map pointer
; a1:
; a2:
; a3: ptr to buffer
; a4: map handle
; d3: local offset into current resource, in chunks
; d4: chunk size (size of buffer)
; d5: relative offset in file to the next ResData; doesnÕt include file header.
; d7: resource size to copy, however many bytes left to copy.
CopyMore
cmp.l d4,d7
bge.s @moreLeft ; do a single buffer
move.l d7,d4 ; or, do the rest of the resource
@moreLeft
sub.l d4,d7 ; keep track of the number of bytes left to do
;-------
; read into (a3)
; b3b: a0: pointer to res map, from RREntry6.
; a1: handle to resource
; d2: location of resource in file, offset. Out of reference list for this resource.
;-------
jsrROM RREntry6 ; set up for a read/write (donÕt change attrs)
add.l d3,d2 ; add in offset inside this resource
move.l a3,d1 ; get pointer to buffer
move.l d4,d0 ; get amount of data to read
jsrROM RdData ; go read it
; write out to end of file
jsrROM RREntry6 ; set up regs for a read/write (donÕt change attrs)
move.l ResDataOffset(a0),d2 ; a0 already points to map ;;;(b3b)
add.l d5,d2 ; add in offset to new resource
move.l a3,d1 ; get pointer to buffer
move.l d4,d0 ; get amount of data to write
jsrROM WrData ; go write it
add.l d4,d3 ; update offset index
add.l d4,d5 ; update offset index
move.l d7,d0 ; check if there are more bytes to read
bne.s CopyMore ; if so, loop back
move.l (sp),d5 ; update the new size of the data in the map.
add.l sizeParam(a6),d5
add.l #4,d5
move.l d5,DataSize(a0) ; b3b, size is right in d5, use a move not an add.
; put new offset into current map
; assume (sp) has the new offset, that needs to be popped
move.b RAttr(a2),d0 ; save attributes
and.b #rcbMask,d0 ; clear changed bit
move.l (sp)+,RLocn(a2) ; store new file offset.
move.b d0,RAttr(a2) ; restore attributes
move.l a3,a0 ; dispose of buffer
_DisposPtr
; WARNING, WARNING, WARNING, WARNING, WARNING!
; Should we at this point purge the resource (since a memory copy is invalid)?
WriteSize
; update the size on disk and exit
move.l (a4),a0 ; deref map handle again
ori.b #MCCMask,MAttr(a0) ; and tell them the map has changed, needs compaction
jsrROM RREntry6 ; set up regs for a read (donÕt change attrs)
lea sizeParam(a6),a0 ; point to size
move.l a0,d1
moveq #4,d0 ; get the size
jsrROM WrData ; go Write new size out
bra.s Exit
SetResSizeMapIsReadOnly
move.w #mapReadErr,ResErr
bra.s Exit ; and exit
TooBig
move.w #addRefFailed,ResErr ; signal error
Exit
moveq #8,d0 ; pop off 8 bytes of parameters
jmpROM RStdExit ; and exit <25> rb
EndProc
;____________________________________________________________________________________________________
; MakeOverrideMap(mapToOverride: Handle);
;
; MakeOverrideMap creates a new resource map and fills it with references to ROM resources
; specified in a 'rovm' resource, then inserts it in front of the mapToOverride.
;
MakeOverrideMap Proc Export
jsrROM Std1Entry
move.l a5,-(sp)
move.l ROMMapHndl,a5 ; Keep ROM resource map in A5
move.w CurMap,-(sp) ; I officially apologize to the AppleTalk guys
move.w #1,CurMap ; for sliming them about doing this. I see what theyÕre up to now.
subq #4,sp ; make space for handle
move.l #'rovm',-(sp) ; push 'rovm' for _Get1Resource
clr.w -(sp) ; Always look for 'rovm' 0
move.w #mapTrue,ROMMapInsert ; Get the 'rovm' from ROM
_Get1Resource ; get rovm resource (must be locked) <6>
move.l (sp)+,d0 ; save handle to the list
bz @noResourceOverrideMap ; no resource override map, so get out of here
move.l d0,-(sp) ; save handle for ReleaseResource later
moveq #32,d0 ; Space for header, map info, and type count
_NewHandle ,Sys,Clear ; Create a new map
move.l a0,a4 ; Keep handle to new map in A4
move.l (a0),a0
move.l #dataFirstRes,(a0)+ ; Fill out info for an empty resource map
move.l #dataFirstRes,(a0)+ ;
clr.l (a0)+
move.l #30,(a0)+ ; Map size
move.l TopMapHndl,(a0)+ ; Put it at the top of the chain for now
move.l a4,TopMapHndl ; <54> Put the map in the chain.
move.w #kFakeResourceOverrideMapRefNum,(a0)+ ; A fake reference number for this map since it didnÕt come from a file
bset #mapReadOnly,(a0)+
clr.b (a0)+ ; Clear the attributes
move.w #mNames+2,(a0)+ ; Type list always comes right after map header
move.w #mNames+4,(a0)+ ; Point to after resource map for name list
move.w #-1,(a0)+ ; Nothing in the resource map
clr.w (a0) ; No names in the map
move.l (a4),a1 ; get map pointer in a1 <SM12> rb
bset #twoDeepBit,mInMemoryAttr(a1) ; mark for extended search <SM12> rb
bset #overrideNextMapBit,mInMemoryAttr(a1) ; mark as an override map <SM14> rb
move.l (sp),a1 ; get rovm resource handle
move.l (a1),a1 ; get rovm resource pointer
move.w (a1)+,d1 ; count-1 of items in list
@forEachResourceInList
subq #4,sp ; make space for handle
move.l (a1)+,d3
move.l d3,-(sp) ; push type onto stack
move.w (a1)+,d2
move.w d2,-(sp) ; push id onto stack
move.w #mapFalse,ROMMapInsert ; link in ROM map w/ResLoad false
_Get1Resource
move.l (sp)+,d0 ; get that resource
bz.s @nextResourceInList ; if no resource, advance to the next one
;
; Make space in the override map for a reference to this resource
;
movem.l d0/a1,-(sp) ; push handle for RmveResource later
move.l (a4),a3 ; AddNewRef wants a pointer to the map in A3
move.l a3,a2
add.w mTypes(a2),a2 ; Point to the types list
jsrROM AddNewRefWithoutUpdate ; Call Resource Manager to make a new resource reference in override map
movem.l (sp)+,d0/a1 ; Refresh resource handle
move.l d0,-(sp) ; Save copy for RmveResource
subq #4,sp ; make space for map entry offset
move.l d0,-(sp) ; push resource handle onto stack
move.w #mapFalse,ROMMapInsert ; link in ROM map w/ResLoad false
st ResOneDeep ; since there is no one-deep version of RsrcMapEntry
_RsrcMapEntry ; ignore errors from RsrcMapEntry
move.l (sp)+,a0 ; get map entry offset
add.l (a5),a0 ; make the map offset into a pointer
exg a2,a1 ; Swap reference entry and 'rovm' pointer
move.l #RESize,d0
_BlockMoveData ; Copy reference data
clr.b RAttr(a0) ; clear the attributes for the resource (protected, etc.)
;
; If this resource has a name, add the name to the override map
;
exg a1,a2 ; Get entry pointer back in A2 <SM11> rb
move.w rNameOff(a0),d0 ; Get offset to resource name
bmi.s @noName ; If negative, this resource has no name
move.l (a5),a0 ; Dereference ROM map handle
add.w MNames(a0),a0 ; Get to resource name list
add.l d0,a0 ; A0 now points to the name for this resource
jsrROM AddName ; Let the Resource Manager do the hard part
;
; The reference has been copied from the ROM map to the override map. Delete the resource
; reference from the ROM map.
;
@noName
move.w #mapFalse,ROMMapInsert ; link in ROM map w/ResLoad false
_RmveResource ; ignore errors from RmveResource
@nextResourceInList
dbra d1,@forEachResourceInList ; loop through the resources
_ReleaseResource ; Release the 'rovm' resource
move.l a4,-(sp)
move.l 8(a6),-(sp)
_InsertOverrideMap ; The resources in the override map have been set up. Insert it.
@noResourceOverrideMap
move.w (sp)+,CurMap ; Restore the current resource map
move.l (sp)+,a5 ; Restore A5
moveq #4,d0 ; Take 4 bytes off the stack
jmpROM RStdExit ; <25> rb
EndProc
;____________________________________________________________________________________________________
; InsertOverrideMap(overrideMap, mapToOverride: Handle);
;
; Given a handle to a resource map, InsertOverrideMap places it before mapToOverride in
; the resource chain, and sets the overrideNextMap and twoDeep bits on the new override
; map. It also sets the dontCountOrIndexDuplicatesBit on mapToOverride. If mapToOverride
; already has an override map, InsertOverrideMap works on the highest override map in
; place. Doing so takes the burden off of the caller to make sure all the bits are set
; up properly.
InsertOverrideMap Proc Export
Import MarkFileAsOwnedByTheSystem ; <mc2>
jsrROM StdZEntry ; Make sure nothing is inserted before the ROM map
move.w #nilHandleErr,ResErr ; <40> Assume nil handle
lea 8(a6),a0 ; <35> Get address of mapToOverride
movem.l (a0)+,d6/d7 ; <35> Get both parameters.
tst.l d6 ; <35> Is mapToOverride nil?
bz @exitInsertOverrideMap ; <35> Yep. Bail out.
tst.l d7 ; <35> Is overrideMap nil?
bz @exitInsertOverrideMap ; <35> Yes.
move.w #paramErr,ResErr ; <40> ItÕs not a nil handle problem. Assume we have the same handle twice.
cmp.l d6,d7 ; <35> Make sure theyÕre not the same handle
beq @exitInsertOverrideMap ; <35> Bail if they are.
; Find the override map in the chain and remove it
move.w #mapReadErr,ResErr ; <41> Set up ResErr in case we need to bail out
moveq #0,a0 ; <41> Map above override map
moveq #0,a1 ; <41> Map below override map
move.l TopMapHndl,a2 ; <41> Start looking from the top of the chain
@findOverrideMap
move.l (a2),a3 ; <41> Get map pointer
move.l mNext(a3),a1 ; <41> Remember map below
cmp.l a2,d7 ; <41> Is this overrideMap?
beq.s @removeOverrideMapFromChain ; <41> Yes. Take it out of the chain
move.l a2,a0 ; <41> Remember potential map above override
move.l a1,d0 ; <41> Check to make sure there is a next map
bz @exitInsertOverrideMap ; <41> Exit if override map is not in the resouce chain
move.l a1,a2 ; <41> Try next map
bra.s @findOverrideMap ; <41>
; Remove the override map from the chain
@removeOverrideMapFromChain
move.l a0,d0 ; <41> Check to see if this is the first map
bnz.s @notTopMap ; <41>
move.l a1,TopMapHndl ; <41>New top resource map
bra.s @findMapToOverrideInChain ; <41>
@notTopMap
move.l (a0),a0 ; <41> Pointer to map above override map
move.l a1,mNext(a0) ; <41> Point around this map
; Find the map to override in the resource chain
@findMapToOverrideInChain
subq #4,sp ; <41>
move.l d6,-(sp) ; <41> Get any override maps already in place above mapToOverride
_GetOverrideMap ; <41>
move.l (sp)+,d6 ; <41>
bz.s @exitInsertOverrideMap ; <41> mapToOverride isnÕt in the chain. Bail.
moveq #0,a0 ; <41> Map above mapToOverride
move.l TopMapHndl,a2 ; <41> Start from the top again
@findMapToOverride
move.l (a2),a3 ; <41>
move.l mNext(a3),a1 ; <41> Get next map down
cmp.l a2,d6 ; <41> Is this mapToOverride?
beq.s @reinsertOverrideMap ; <41> Yes. Go put overrideMap above it.
move.l a2,a0 ; <41> Remember this in case the next map is mapToOverride
move.l a1,a2 ; <41> _GetOverrideMap implicitly made sure that mapToOverride is in the chain, so we can just loop blindly.
bra.s @findMapToOverride ; <41>
; Put overrideMap back in chain above mapToOverride (or one of its override maps)
@reinsertOverrideMap
move.l d7,a2 ; <41> We kept overrideMap in d7 for a reason.
move.l (a2),a1 ; <41>
move.l d6,mNext(a1) ; <41> Link mapToOverride after overrideMap
move.l a0,d0 ; <41> See whether overrideMap should become the top map
bnz.s @overrideMapIsNotTopMap ; <41> ItÕs not
move.l d7,TopMapHndl ; <41> Make overrideMap the top map
bra.s @setBits ; <41> Go set the bits to make this an override map
@overrideMapIsNotTopMap
move.l (a0),a0 ; <41>
move.l a2,mNext(a0) ; <41> Link overrideMap after map that used to be above mapToOverride.
; Set the attribute bits
@setBits
ori.b #kOverrideNextMapMask + \
kTwoDeepMask + \
kPreventFileFromBeingClosedMask,mInMemoryAttr(a1) ; <42> <44>
move.l d6,a0 ; Get mapToOverride
move.l (a0),a0
bset #dontCountOrIndexDuplicatesBit,mInMemoryAttr(a0) ; And ignore duplicates in this map now
clr.w ResErr ; No error if we got this far
; <62><mc2> Mark override map as being owned by the system
move.w mRefNum(a1),d0 ; Get file reference number
bsr MarkFileAsOwnedByTheSystem
; Clear emLastMapOverridden to force a resynchronization of the override maps.
move.l ExpandMem,a0 ; <58>
clr.w ExpandMemRec.emLastMapOverridden(a0) ; <58> Clearing this field forces SyncTopOverrideMap to resynch everything.
@exitInsertOverrideMap
moveq #8,d0
jmpROM RStdExit ; <25> rb
EndProc
;____________________________________________________________________________________________________
; GetOverrideMap(resourceMap: Handle): Handle;
;
; Given a resource map, GetOverrideMap finds the first override map for it. If there are
; no override maps for this resource map, the handle to this resource map is returned. If
; resourceMap isnÕt found, nil is returned.
;
; This routine is allowed to trash D1 & D2 because itÕs already been trashed by DispatchHelper.
; ItÕs up to you to save these registers yourself when you call this routine.
GetOverrideMap Proc Export
move.l (sp)+,a0
move.l (sp)+,d2 ; Get map to find overrides for
move.l a0,-(sp) ; Save return address
clr.w ResErr ; Clear out error result
moveq #0,d1 ; Reset TopOverrideMap
move.l TopMapHndl,d0 ; Start from the top
@getOverrideLoop
cmp.l d2,d0
beq.s @gotToBaseMap ; Return if base map is found
move.l d0,a0
move.l (a0),a0
btst #overrideNextMapBit,mInMemoryAttr(a0) ; Is this an override map?
beq.s @notOverrideMap ; No
tst.l d1 ; Already have an override map?
bne.s @overrideCommon ; Yes. Use that one
move.l d0,d1 ; Remember this override map
bra.s @overrideCommon
@notOverrideMap
moveq #0,d1 ; Reset override map
@overrideCommon
move.l mNext(a0),d0
bne.s @getOverrideLoop ; Keep searching until the end of the chain is reached
move.w #resFNotFound,ResErr ; End of chain, and map wasnÕt found. Error out
bra.s @gotOverrideMap
@gotToBaseMap
move.l d1,d0 ; Is there an override map for this resource map?
bne.s @gotOverrideMap ; Yes
move.l d2,d0 ; Otherwise, return the map handle itself
@gotOverrideMap
move.l d0,4(sp) ; Return the handle
move.w ResErr,d0 ; Try to be like other Resource Manager routines and return the error in D0
rts
EndProc
;____________________________________________________________________________________________________
; SetScanOverride(scanOverrideMap: Boolean);
;
; This routine sets the expanded low memory global emScanOverrideMaps to the value passed
; in the parameter. Passing FALSE will cause override maps not to be searched during
; subsequent Resource Manager calls. Passing TRUE will allow override maps to be searched.
; Only programs such as ResEdit and Installer which mess around a lot with resource maps
; should turn overriding off.
SetScanOverride Proc Export
move.l (sp)+,a0
move.b (sp)+,d0
move.l a0,-(sp)
move.l ExpandMem,a0
move.b d0,ExpandMemRec.emScanOverrideMaps(a0) ; Set the value in expand mem
moveq #0,d0
move.l d0,a0
move.w d0,ResErr ; This routine is too simple to have an error
rts
EndProc
;____________________________________________________________________________________________________
; GetOverrideAttributes(resourceMap: Handle): SignedByte;
;
; GetOverrideAttributes returns the current setting of the override bits in the memory
; attributes of the resource map.
;
GetOverrideAttributes Proc Export
jsrROM StdZEntry
move.l 8(a6),d0 ; Get the resource map handle
bnz.s @notNilHandle ; <38>
move.w #nilHandleErr,ResErr ; <38> Report a nil handle
bra.s @exitGetOverrideAttributes ; <38>
@notNilHandle ; <38>
move.l d0,a0 ; <38>
move.l (a0),a0
move.b mInMemoryAttr(a0),d0 ; Get the memory attributes
andi.b #kAllOverrideAttributesMask,d0 ; <42> Only return override attributes
move.b d0,12(a6) ; And pass the value back
@exitGetOverrideAttributes ; <38>
moveq #4,d0
jmpROM RStdExit ; Go home <25> rb
EndProc
;____________________________________________________________________________________________________
; SetOverrideAttributes(resourceMap: Handle; attributeBits: SignedByte);
;
; SetOverrideAttributes sets the override attribute bits specified in the attributeBits
; mask.
;
SetOverrideAttributes Proc Export
jsrROM StdZEntry
move.l 10(a6),d0 ; Get the resource map handle
bnz.s @notNilHandle ; <38>
move.w #nilHandleErr,ResErr ; <38> Report a nil handle
bra.s @exitSetOverrideAttributes ; <38>
@notNilHandle ; <38>
move.l d0,a0 ; <38>
move.b 8(a6),d0 ; Get the attributes
move.l (a0),a0
move.b mInMemoryAttr(a0),d1 ; <22> Get current attributes
andi.b #1,d1 ; <22> Save compression bit
or.b d0,d1 ; <22> Merge in the new attributes
move.b d1,mInMemoryAttr(a0) ; <22> Make these the new attributes
@exitSetOverrideAttributes ; <38>
moveq #6,d0
jmpROM RStdExit ; <25> rb
EndProc
;____________________________________________________________________________________________________
; <45>
;
; Function GetNextFOND(fondHandle: Handle): Handle;
;
; This function will find the next 'FOND' resource in the resource chain that has the
; same ID as the 'FOND' resource that is passed in. Since we allows font families to
; be split across several files now, we need to provide developers a way of getting
; all the font information for a font family. GetNextFOND will return NIL if there
; are no more 'FOND' resources in the chain after the one passed in. If the handle
; passed in is not a 'FOND' resource, resNotFound will be returned. (Since we couldnÕt
; find a 'FOND' with this handle.)
;
GetNextFOND Proc Export
GetNextFONDFrame Record {A6Link},Decr
nextFOND ds.l 1 ; Handle to next 'FOND' resource
fondHandle ds.l 1 ; Current 'FOND' resource
retAddr ds.l 1
A6Link ds.l 1
currentResFile ds.w 1 ; Current resource map
familyID ds.w 1 ; Resource ID of font family
familyType ds.l 1 ; We know what it is, but the Resource Manager is stupid
familyName ds.b 256 ; Space for resource name
localSize equ *
EndR
link a6,#GetNextFONDFrame.localSize
move.l a4,-(sp)
clr.l GetNextFONDFrame.nextFOND(a6) ; Assume weÕre not going to find anything
move.l GetNextFONDFrame.fondHandle(a6),a4 ; Keep the handle in a safe register
; Make sure the handle that was passed in was really a 'FOND' resource
move.l a4,-(sp) ; The current 'FOND' resource
pea GetNextFONDFrame.familyID(a6)
pea GetNextFONDFrame.familyType(a6)
pea GetNextFONDFrame.familyName(a6)
_GetResInfo
tst.w ResErr ; Did an error come back from GetResInfo?
bnz.s @exitGetNextFOND ; Bummers. Bail out.
cmp.l #'FOND',GetNextFONDFrame.familyType(a6) ; Was it really a 'FOND'?
beq.s @validFONDHAndle ; ItÕs ok. Go find the file it came from
move.w #resNotFound,ResErr ; Act like we didnÕt find the handle
bra.s @exitGetNextFOND ; It wasnÕt a 'FOND'. Go home.
; This is really a 'FOND' resource. Find out which resource map it came from.
@validFONDHandle
subq #2,sp
_CurResFile ; Remember the current resource map
subq #6,sp ; Space for HomeResFile and GetMap results
move.l a4,-(sp) ; Find out which file this resource came from
_HomeResFile
_GetMap ; Get the resource map handle
move.l (sp)+,d0 ; Make sure we really got one
bz.s @mapNotInChain ; If not, bail.
; We have a handle the resource map that this 'FOND' came from. Look for the next 'FOND'
; of the same ID starting at the next resource map down. However, if the overrideNextMap
; bit is set, donÕt stop at the next map, and look for a map without this bit set.
@findNonOverrideMap
move.l d0,a0
move.l (a0),a0
move.l a0,d0 ; Get map into a data register
btst #overrideNextMapBit,d0 ; Is this map an override map?
bz.s @notOverrideMap ; No. ItÕs ok to use the next map after this
move.l mNext(a0),d0 ; Get the next map
bz.s @mapNotInChain ; If not, then bail
bra.s @findNonOverrideMap ; Check this map for the override bit
@notOverrideMap
move.l mNext(a0),d0 ; Get the next map
bz.s @mapNotInChain ; End of the resource chain. There are no more 'FOND's.
move.l d0,a0
move.l (a0),a0
move.w mRefNum(a0),-(sp) ; Get the reference number for this resource file
_UseResFile ; Make the next map down the current resource map
; Look for the next 'FOND' for the same family.
subq #4,sp
move.l #'FOND',-(sp) ; Look for a 'FOND'
move.w GetNextFONDFrame.familyID(a6),-(sp) ; with the same ID.
_GetResource ; Go for it.
move.l (sp)+,d0 ; Did we get one?
bnz.s @gotNextFOND ; Yes.
move.w #resNotFound,ResErr ; Report an error, unlike GetResource
bra.s @mapNotInChain ; Restore the real current resource map and exit
; Got the next 'FOND' resource.
@gotNextFOND
move.l d0,GetNextFONDFrame.nextFOND(a6) ; Return it to the caller.
@mapNotInChain
_UseResFile ; Restore the previous current resource map
@exitGetNextFOND
move.l (sp)+,a4
unlk a6
move.l (sp)+,(sp)
move.w ResErr,d0 ; For compatibilityÕs sake
moveq #0,a0
rts ; Return
EndProc
End