mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-02-06 14:29:53 +00:00
0ba83392d4
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.
2339 lines
95 KiB
Plaintext
2339 lines
95 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.s @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.s @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.s @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.
|
|
;
|
|
|
|
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
|
|
|
|
; 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
|
|
|
|
;____________________________________________________________________________________________________
|
|
; <53> SetDeanBitIfResourceWillBeLoaded
|
|
;
|
|
; This routine checks to see if the resource reference entry already contains a handle
|
|
; or not. If it does, DeanBit is cleared. If there is no handle (ie, the resource will
|
|
; be loaded this time) set DeanBit. This allows people to determine whether they loaded
|
|
; a resource, or if someone else did.
|
|
;
|
|
|
|
SetDeanBitIfResourceWillBeLoaded PatchProc jCheckLoad
|
|
tst.l RHndl(a2) ; See if a master pointer has already been allocated
|
|
bz.s @setDeanBit
|
|
bclr #kDeanBit,kBrianBits ; A master pointer has already been allocated
|
|
bra.s @goLoadTheResource
|
|
@setDeanBit
|
|
bset #kDeanBit,kBrianBits ; WeÕll be loading the resource right now
|
|
@goLoadTheResource
|
|
jmpOld ; Load the resource
|
|
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 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
|
|
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 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
|
|
_BlockMove ; 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
|