mirror of
https://github.com/elliotnunn/supermario.git
synced 2025-02-21 17:29:00 +00:00
2313 lines
85 KiB
Plaintext
2313 lines
85 KiB
Plaintext
;
|
||
; File: ScriptMgrROMPatch.a
|
||
;
|
||
; Contains: Patches for the IIci/Portable ROM version of the Script Manager
|
||
;
|
||
; Written by: PKE Peter Edberg
|
||
; SMB Sue Bartalo
|
||
; JH John Harvey
|
||
;
|
||
; Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <27> 6/10/92 FM Replace obsolete equate smgrVerPTCHRom with smgrVersPriv.
|
||
; <26> 4/30/92 FM Get rid of conditionals: SysVers, smgrSysVers,
|
||
; doScriptMgrStr2DatFix
|
||
; <25> 4/22/92 PKE #1027368,<FM>: Now Roman CharType is patched out entirely to
|
||
; handle the direction bit too, so it is moved to ptch 27 - delete
|
||
; it here.
|
||
; <24> 4/14/92 PKE #1026778,<yds>: To make FindWord not depend on having script
|
||
; code passed in d2 (script code will not be in d2 when it is
|
||
; called from one-byte extension), change Roman dispatcher to
|
||
; replace selector on stack with ScriptRecord pointer, and get
|
||
; script code from new scriptID field of ScriptRecord instead of
|
||
; from d2. Do this for CharType & Transliterate too.
|
||
; <23> 4/8/92 PKE #1026515,<cv>: Patch Roman FindWord to not require that itl2 be
|
||
; in new format in order to handle custom break tables (passed by
|
||
; pointer). We patch enough so we no longer need FindWord part of
|
||
; PACK 6 patch in this file, so remove it. Then the CharType part
|
||
; of the PACK 6 patch can be eliminated by just patching out the
|
||
; beginning of CharType (this way is shorter too), so do that
|
||
; also. Eliminates half of PACK 6 patch, makes it cleaner and
|
||
; faster. Finally: eliminate some pre-7.0 conditionalized code.
|
||
; <22> 3/16/92 csd #1017570,<gbm>: Removed the MoveHHi call on the itl0 and itl1
|
||
; resources to avoid System heap fragmentation.
|
||
; <21> 2/13/92 PKE #1021419, Cube-E: Make Roman dispatcher handle nil entries in
|
||
; dispatcher table.
|
||
; <20> 12/17/91 PKE #1018346: Fix bug introduced in <19>. Call IUGetScriptItl with
|
||
; script code passed from ScriptMgr dispatcher, so it works for
|
||
; simple scripts too (don't assume script is smRoman).
|
||
; <19> 10/8/91 PKE For Cube-E (and Bruges): PACK 6 patch no longer applies to
|
||
; LwrString, since we patch it out entirely. Change PACK 6 patch
|
||
; to just call IUGetScriptItl instead of forcing IntlForce off.
|
||
; Part of fix for bug #1013149. Clean up a few more conditionals.
|
||
; <18> 9/20/91 PKE Remove CubeE conditional, since the new plan (according to
|
||
; Darin) is that everything for Cube-E goes in without
|
||
; conditionals. While I'm at it, get rid of some ">= $700"
|
||
; conditionals, and get rid of some code that was only for
|
||
; pre-7.0.
|
||
; <17> 9/15/91 PKE smb, #1011961: For Bruges/Cube-E, roll in from 6.1 - Fix
|
||
; trashing of d3 by GetFormatOrder (replace ROM version of
|
||
; GetFormatOrder with version in this file).
|
||
;
|
||
; <16> 2/19/91 PKE smb,#DTS FT: ToggleDate trashes one word past the end of its
|
||
; “VAR lSecs: LongDateTime” parameter (reported by a developer).
|
||
; <15> 2/15/91 PKE JSM,#54736: Redo conditionals to move change <14> to Post 7.0.
|
||
; Object compare identical to <13>.
|
||
; <14> 1/28/91 JH PKE,#54736: Added changes to mirror changes in
|
||
; ScriptMgrUtilDate. So changes to date cache, changes in
|
||
; InitDateCache to add date separators to the cache, moved
|
||
; ValidLong, MatchString over to this file so that String2Date
|
||
; could use the new cache. And added slightly tougher requirements
|
||
; for date separators.
|
||
; <13> 12/15/90 PKE (gbm) Move ‘itlk’ loading from KeyScript into SwapKybd patch.
|
||
; Fixes bugs with some European keyboards when using Keyboard
|
||
; menu, etc.
|
||
; <12> 12/14/90 PKE (DC) Don’t install GetOSEvent patch if A/UX is running. A/UX
|
||
; folks will figure out how to handle the Script Mgr key
|
||
; combinations another way. Patch out rest of Script Mgr extension
|
||
; to GetOSEvent, and change it to use smgrKeyScriptResult to
|
||
; determine whether or not to strip event from queue (in a future
|
||
; build, this patch will be reduced in size by using a come-from
|
||
; patch in KeyScript). Patch KeyTrans to skip itlk handling if
|
||
; KeyTrans is called with a special KCHR (not the one emKeyCache
|
||
; points to). Patch internal SwapKybd routine to force it to load
|
||
; ‘KCHR’ resources from System file.
|
||
; <11> 12/5/90 BBM (JSM) Protect the come-from patches
|
||
; <10> 10/30/90 PKE (stb) Patch out GetOSEvent and change it to permit switching
|
||
; keyboards within scripts using key combos defined in 'KSWP'
|
||
; resource.
|
||
; <9> 8/7/90 PKE Just altered the previous comment to say needed for SixPack.
|
||
; <8> 8/5/90 PKE NEEDED FOR SIXPACK: Since this patch may now be installed for
|
||
; A/UX, we need to branch around the installations in here that
|
||
; shouldn’t be done for A/UX. Search for <8> to find changes.
|
||
; <7> 7/5/90 PKE NEEDED FOR SIXPACK: Rearrange InitDateCache to fix old problem:
|
||
; itl0 and itl1 may be purged before we try to use them. Patch out
|
||
; GetScript for 6.x systems to fix its handling of unimplemented
|
||
; verbs (old bug, fix needed for Sound Cdev). Removed local
|
||
; definition of smgrSixPack since it is now defined in
|
||
; ScriptPriv.a.
|
||
; <6> 6/11/90 PKE NEEDED FOR SIXPACK: Fix Script Mgr InitResources patch in ROM to
|
||
; save and restore all regs; only needed for 6.x. Changes are
|
||
; flagged with <6>. ALSO: Removed some superfluous with/endwith
|
||
; pairs.
|
||
; <5> 5/13/90 SMB Doing an ‘rts’ for NewSwapIcon since now using Keyboard Menu.
|
||
; Installing a tail patch to InitMenus to set smgrRect to 0 so
|
||
; that keyboard/script toggling in the system menu is no longer
|
||
; available.
|
||
; <4> 3/26/90 PKE Moved definition of symbols that control Script Mgr patches into
|
||
; ScriptPriv.a. Renamed symbols and added some.
|
||
; <3> 3/4/90 PKE Changed _UprText to _UpperText to match new Traps.a.
|
||
; <2> 2/28/90 PKE Moved FixRomAddresses macro to end and bsr to it; fixes problems
|
||
; that occur with BIND macros that are located after it.
|
||
; <1> 2/27/90 PKE New today, created from common patch code extracted from
|
||
; PatchIIciROM.a and PatchPortableROM.a. Relevant comments from
|
||
; those files are copied below.
|
||
;___________________________________________________________________________________________________
|
||
; Here are the relevant comments copied from PatchIIciROM.a; in body, these are marked <aX.X>
|
||
;
|
||
; <39> 2/22/90 PKE Replaced obsolete _LwrStringToUpr opword with _UprText. Removed
|
||
; setting of temporary sVectFixSpExtra vector (see <12>); we no
|
||
; longer need it.
|
||
; <12> 1/11/90 PKE Initialize Script Manager's new sVectFixSpExtra vector.
|
||
; <8.0> 11/17/89 PKE Tail patch on _GetIndADB to fix Script Mgr SwapKybd routine,
|
||
; which cleared ADB keyboard driver dead state as a word: should
|
||
; be a long.
|
||
; <7.8> 11/6/89 PKE NEEDED FOR 6.0.5!! Bug fixes for InitDateCache and String2Date
|
||
; needed for HyperCard. InitDateCache: Fixed CopyArray to use
|
||
; correct register (A4) for source pointer, and to initialize all
|
||
; relevant bytes of length register (D0). String2Date: if first
|
||
; relevant (i.e., day or month name) alpha token is a month name,
|
||
; we now search the day name list if we find another alpha token
|
||
; (fixes BRC #54946). Rearranged Cache structure to fix invalid
|
||
; use of month/day name index.
|
||
; <6.2> 9/18/89 PKE For 7.0, patch Script Manager internal routine SwapIcon to use
|
||
; new 'kscn' resource type instead of 'SICN'.
|
||
; <5.4> 8/28/89 PKE For 7.0, initialize additional Script Mgr vectors for
|
||
; SMgrCalcRect and SMgrInitFonts.
|
||
; <5.3> 8/27/89 PKE NEEDED FOR Scripts604, 6.0.5: Bump Script Manager version for
|
||
; Scripts604 or SysVers > $604, since IntlForce bug fix (4.5) is
|
||
; installed.
|
||
; <4.7> 8/21/89 PKE NEEDED FOR 6.0.4:
|
||
; • Conditionalize 4.5 for Scripts604 OR (SysVers > $604)
|
||
; <4.5> 8/21/89 PKE NEEDED FOR 6.0.4 SCRIPTS BUILD, 6.0.5: Extend Pack6 patch to fix
|
||
; a problem in LwrString,CharType,Transliterate,FindWord. These
|
||
; routines should save the IntlForce flags then clear them before
|
||
; the IUGetIntl call, restoring the flags afterward. This is so we
|
||
; get the itl2 tables for the correct script (instead of the
|
||
; tables for the system script).
|
||
; <4.3> 8/21/89 PKE NEEDED FOR 6.0.4!!: Patch Pack6 to fix me-too problem with
|
||
; pointer to unlocked handle in Transliterate; affects Roman
|
||
; system (this problem looks familiar; did I dream that I already
|
||
; fixed this one?).
|
||
;___________________________________________________________________________________________________
|
||
; To Do:
|
||
;
|
||
;___________________________________________________________________________________________________
|
||
PRINT OFF ; <14>
|
||
blanks on
|
||
string asis
|
||
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'PatchMacros.a'
|
||
include 'ScriptPriv.a' ; <a4.5><e3.8>
|
||
INCLUDE 'ApplDeskBus.a' ; <a8.0><e5.5>
|
||
INCLUDE 'PackMacs.a' ; <a4.3><e3.7>
|
||
INCLUDE 'HardwarePrivateEqu.a' ; <8>
|
||
INCLUDE 'IntlUtilsPriv.a' ; <19>
|
||
|
||
PRINT ON ; <14>
|
||
|
||
ptchID equ 39 ; per CCH.
|
||
|
||
; The following symbols are defined in ScriptPriv.a. They control whether <4>
|
||
; various Script Mgr patches are resident and installed here.
|
||
;
|
||
; doScriptMgrUseKscn
|
||
; doScriptMgrStr2DatFix
|
||
|
||
; Local symbols <15>
|
||
FixCacheAndStr2Date equ 0 ; do this for 7.1? (not 7.0.1) <15>
|
||
;FixCacheAndStr2Date equ (smgrSysVers >= $710) ; do this for 7.1? (not 7.0.1) <15>
|
||
|
||
; =============================================================================
|
||
|
||
CodeEntry Main export
|
||
Import SMgrInstallPatch ; start of init code
|
||
|
||
bra.w SMgrInstallPatch ; branch to initialization
|
||
dc.b 'ptch' ; resource type
|
||
dc.w ptchID ; resource number
|
||
dc.w smgrVersPriv ; version
|
||
|
||
EndMain
|
||
|
||
; =============================================================================
|
||
; ROM binds
|
||
; =============================================================================
|
||
|
||
ROMVersions Esprit, Aurora
|
||
|
||
; for PACK6 patch
|
||
;fromROMLwrString BIND (Aurora, $0C0B2), (Esprit, $0797A)
|
||
;fromROMCharType BIND (Aurora, $1D986), (Esprit, $1745C)
|
||
;fromROMFindWord BIND (Aurora, $1DBE0), (Esprit, $176B6)
|
||
|
||
fromROMTranslit BIND (Aurora, $1DB34), (Esprit, $1760A)
|
||
toROMTranslit BIND (Aurora, $1DB3A), (Esprit, $17610)
|
||
ROMPack6 BIND (Aurora, $262B2), (Esprit, $1E3F4)
|
||
|
||
; for SwapIcon patch
|
||
ROMAfterPushSICN BIND (Aurora, $1DF26), (Esprit, $179E8)
|
||
ROMNoList BIND (Aurora, $1DF7C), (Esprit, $17A3E)
|
||
|
||
; for InitDateCache/String2Date patch
|
||
ROMValidLong BIND (Aurora, $1EE60), (Esprit, $1895A)
|
||
ROMBlock2String BIND (Aurora, $1EEA0), (Esprit, $18996)
|
||
ROMMatchString BIND (Aurora, $1EF20), (Esprit, $18A02)
|
||
; in InitDateCache
|
||
ROMAfter2ndJSRCopyArray BIND (Aurora, $1F0E8), (Esprit, $18BC8)
|
||
ROMExit BIND (Aurora, $1F160), (Esprit, $18C40)
|
||
; in/after String2Date
|
||
ROMAfterDBNE BIND (Aurora, $1F2D6), (Esprit, $18DB4)
|
||
ROMDTComExit BIND (Aurora, $1F426), (Esprit, $18F04)
|
||
IF FixCacheAndStr2Date THEN ; <14><15>
|
||
ROMCheckRest BIND (Aurora, $1f434), (Esprit, $18F12)
|
||
ROMCvtTables BIND (Aurora, $1f51e), (Esprit,$18ffc)
|
||
ROMCheckValid BIND (Aurora, $1F506), (Esprit,$18FE4)
|
||
ROMStdUnlink BIND (Aurora, $1E310), (Esprit,$17DCA)
|
||
ENDIF ; <14>
|
||
ROMFixValue BIND (Aurora, $1F46E), (Esprit, $18F4C)
|
||
ROMDateTimeEntry BIND (Aurora, $1F47E), (Esprit, $18F5C)
|
||
|
||
; for GetIndADB patch
|
||
ROMAfterGetIndADB BIND (Aurora, $1E048), (Esprit, $17B0A)
|
||
ROMAfterClrDeadKey BIND (Aurora, $1E058), (Esprit, $17B1A)
|
||
ROM@1dbra BIND (Aurora, $1E064), (Esprit, $17B26)
|
||
|
||
; for new vector initialization
|
||
ROMSMgrCalcRect BIND (Aurora, $1E1C2), (Esprit, $17C84)
|
||
ROMSMgrInitFonts BIND (Aurora, $1E21C), (Esprit, $17CDE)
|
||
ROMCallInterface BIND (Aurora, $1E3B0), (Esprit, $17E6A)
|
||
;ROMFixSpEXtra BIND (Aurora, $1DD94), (Esprit, $1786A)
|
||
|
||
; For GetOSEvent patch
|
||
ROMOSEventAvail BIND (Aurora, $B418), (Esprit, $6420) ; <10>
|
||
ROMDequeue BIND (Aurora, $9956), (Esprit, $4D64) ; <10>
|
||
ROMFilterKey BIND (Aurora, $1E2C6), (Esprit, $17D88) ; <10>
|
||
|
||
; For KeyTrans itlk fix
|
||
;ROMKeyTrans BIND (Aurora, $AD7A), (Esprit, $5DA2) ; <12>
|
||
ROMKeyTransAfterItlk BIND (Aurora, $ADCC), (Esprit, $5DF4) ; <12>
|
||
|
||
; For SwapKybd fix
|
||
;ROMSwapKybdAfterGetKCHR BIND (Aurora, $1DFC2), (Esprit, $17A84) ; <12>
|
||
ROMSwapKybdLockKCHR BIND (Aurora, $1DFC6), (Esprit, $17A88) ; <13>
|
||
|
||
; For ToggleDate fix via come-from patch in ValidDate ; <16>
|
||
ROMValidDate BIND (Aurora, $1E7B0), (Esprit, $18260) ; <16>
|
||
ROMTogDateAfterValDate BIND (Aurora, $1EAC6), (Esprit, $1856E) ; <16>
|
||
ROMbsrCopyDateLoop BIND (Aurora, $1EB3E), (Esprit, $185E6) ; <16>
|
||
; Five pairs - return address for xValidDate, ROM addresses after blt SetNewDate: <16>
|
||
;ROMbltSetNewDate1 BIND (Aurora, $1EA2E), (Esprit, $184D6) ; <16>
|
||
ROMAfterBltSetNewDate1 BIND (Aurora, $1EA32), (Esprit, $184DA) ; <16>
|
||
ROMbltSetNewDate2 BIND (Aurora, $1EA70), (Esprit, $18518) ; <16>
|
||
ROMAfterBltSetNewDate2 BIND (Aurora, $1EA74), (Esprit, $1851C) ; <16>
|
||
;ROMbltSetNewDate3 BIND (Aurora, $1EAE4), (Esprit, $1858C) ; <16>
|
||
ROMAfterBltSetNewDate3 BIND (Aurora, $1EAE6), (Esprit, $1858E) ; <16>
|
||
ROMdbltFinerLoop4 BIND (Aurora, $1EB02), (Esprit, $185AA) ; <16>
|
||
ROMAfterBltSetNewDate4 BIND (Aurora, $1EB08), (Esprit, $185B0) ; <16>
|
||
;ROMdbltBackwardsLoop5 BIND (Aurora, $1EB28), (Esprit, $185D0) ; <16>
|
||
ROMAfterBltSetNewDate5 BIND (Aurora, $1EB2E), (Esprit, $185D6) ; <16>
|
||
|
||
; For GetFormatOrder fix <17>
|
||
ROMReverseCluster BIND (Aurora, $1F974), (Esprit, $1944A) ; <17>
|
||
ROMEndFormatOrder BIND (Aurora, $1F96C), (Esprit, $19442) ; <17>
|
||
|
||
; For Roman dispatcher change <21>
|
||
ROMBitBucket BIND (Aurora, $1E3BC), (Esprit, $17E76) ; <21>
|
||
|
||
; For Roman FindWord/CharType changes <23>
|
||
; beginning of FindWord (Aurora, $1DBA4), (Esprit, $1767A) <23>
|
||
ROMfwAfterGetIntl BIND (Aurora, $1DBE0), (Esprit, $176B6) ; <23>
|
||
ROMfwLoadOffsets BIND (Aurora, $1DC16), (Esprit, $176EC) ; <23>
|
||
ROMfwstoreOffsets BIND (Aurora, $1DC42), (Esprit, $17718) ; <23>
|
||
|
||
; =============================================================================
|
||
; Begin resident code
|
||
; =============================================================================
|
||
;____________________________________________________________________________
|
||
; Script Manager patch to Pack6, fixes problem with pointer to unlocked
|
||
; handle in Transliterate. <a4.3><e3.7>
|
||
; Also fixes another problem in LwrString, CharType, Transliterate, FindWord:
|
||
; These routines need to get itl2 tables that apply to the current font script. <a4.5><e3.8>
|
||
; No longer applies to LwrString. <19>
|
||
; No longer applies to FindWord or CharType. <23>
|
||
;
|
||
; Note: d2 hi word has a value passed from dispatcher; save it till IUGetScriptItl call <20>
|
||
|
||
ptchPack6 PROC Export
|
||
|
||
tlRecord record {a6link},decr
|
||
result ds.w 1 ; function result.
|
||
tlArgs equ *-8 ; size of arguments.
|
||
srcHandle ds.l 1 ; srcHandle.
|
||
dstHandle ds.l 1 ; dstHandle.
|
||
target ds.w 1 ; target.
|
||
srcMask ds.l 1 ; srcMask.
|
||
scriptRecPtr ds.l 1 ; ScriptRecord pointer <24>
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old a6 register.
|
||
tlLocals equ * ; size of local variables.
|
||
endr
|
||
|
||
; We can use the new protection scheme, if the first two instructions in the <11>
|
||
; patch are a bra.s followed by the jump to the old rom address.
|
||
|
||
bra.s @protection
|
||
@NoPatch
|
||
JMPBIND ROMPack6 ; nothing interesting to do
|
||
@protection
|
||
CMPBIND fromROMTranslit,(sp)
|
||
bne.s @NoPatch ; Translit is special - 2 bugs
|
||
|
||
@PatchTrans
|
||
; We get here if we came from the _IUGetIntl in Roman Transliterate (IUGetIntl is a
|
||
; macro that pushes a selector and then does a _Pack6 trap). A few instructions
|
||
; before the _IUgetIntl, we had handles in a1 and a2 which were then dereferenced
|
||
; into the same registers. We want to postpone this dereferencing till after
|
||
; _Pack6. Fortunately, the original handles are still available in Transliterate's
|
||
; a6 frame, so we can get them after the Pack6 call, dereference them again, and
|
||
; stuff them where they belong. We also need to clear the IntlForce flag around
|
||
; Pack6 if it is set.
|
||
; Now we ignore IntlForce and instead use IUGetScriptItl to be independent <19>
|
||
; of the grafPort, since we already know script is Roman.
|
||
;
|
||
; At this point the stack has 12 bytes that were intended for Pack6:
|
||
; 8(sp).L = space for returned handle
|
||
; 6(sp).W = argument, specifies which itlx
|
||
; 4(sp).W = Pack6 routine selector = #iuGetIntl
|
||
; 0(sp).L = return address
|
||
; We only care about the handle space and arg; we will call iuGetScriptItl instead.
|
||
|
||
WITH tlRecord
|
||
addq #6,sp ; kill old return address, selector <19>
|
||
|
||
;; clr.w d2 ; sysFlag=0; script code in hi word <20>
|
||
;; swap d2 ; put where they belong <20>
|
||
move.l scriptRecPtr(a6),a0 ; ScriptRecord ptr (maybe nonRoman) <24>
|
||
moveq #0,d2 ; sysFlag=0 in hi word <24>
|
||
move.b ScriptRecord.scriptID(a0),d2 ; script code in low word <24>
|
||
|
||
move.l d2,-(sp) ; two arguments: script code, sysFlag=0 <19><20>
|
||
move.w #iuGetScriptItl,-(sp) ; selector for PACK 6 <19>
|
||
JSRBIND ROMPack6
|
||
|
||
; The next two lines are what follow the _IUGetIntl in the ROM Transliterate
|
||
move.l (sp)+,a4 ;
|
||
movem.l (sp)+,a1/d1-d2 ;
|
||
; Now we expect to have pointers in a1 and a2, so set them up again (this is
|
||
; the fix) and jump back into ROM:
|
||
move.l srcHandle(a6),a1 ; get source handle.
|
||
move.l dstHandle(a6),a2 ; get destination handle.
|
||
move.l (a1),a1 ; get source pointer.
|
||
move.l (a2),a2 ; get destination pointer.
|
||
JMPBIND toROMTranslit
|
||
endwith ;tlRecord
|
||
|
||
endproc
|
||
|
||
;====================================================================== pke <a6.2><e4.7>
|
||
; This used to patch Script Manager internal routine SwapIcon to use <5>
|
||
; new 'kscn' instead of 'SICN'. Now we just eliminate it because we are
|
||
; using the new keyboard system menu.
|
||
; ----------------------------------------------------------------------------
|
||
; SwapIcon blits the key script icon in the upper right corner of the screen,
|
||
; opposite the apple symbol in the menu bar. It only draws the icon if the
|
||
; menuList is not nil.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export NewSwapIcon
|
||
|
||
NewSwapIcon ; <a6.2><e4.7>
|
||
rts ; removing since now using the Keyboard-Script Menu <5>
|
||
endproc
|
||
|
||
;_______________________________________________________________________
|
||
IF FixCacheAndStr2Date THEN ; { <14><15>
|
||
|
||
|
||
;===========================================================================
|
||
; For System 7.0 changes made where the cache record would not be bigger than the
|
||
; cache space passed in. ALso MatchString was changed to handle arrays of variable
|
||
; length pascal strings rather than just fixed length
|
||
;===============================================================================
|
||
|
||
;======================================================================
|
||
; FUNCTION MatchString (textPtr : Ptr; textLen: Integer; textMinLen: Integer;
|
||
; strArrPtr : Ptr; strArrMaxLen: Integer;
|
||
; strArrCount: Integer) : Integer; external;
|
||
; function Finds the longest match between the text and an
|
||
; initial portion of a string in the array.
|
||
; return is the number of the match (1 based), -1 if not found
|
||
;======================================================================
|
||
|
||
MatchString proc export
|
||
|
||
import StdUnlink
|
||
|
||
MatchStrFrame record {oldA6},decrement
|
||
result ds.w 1
|
||
textPtr ds.l 1
|
||
textLen ds.w 1
|
||
textMinLen ds.w 1
|
||
strArrPtr ds.l 1
|
||
strArrMaxLen ds.w 1
|
||
strArrCount ds.w 1
|
||
return ds.l 1
|
||
oldA6 ds.l 1
|
||
args equ result-return-4
|
||
endr
|
||
|
||
|
||
MatchStrRegs reg a2-a4/d3-d5
|
||
|
||
|
||
with MatchStrFrame
|
||
link a6,#Frame ; allocate
|
||
movem.l MatchStrRegs,-(sp) ; save regs
|
||
move.l textPtr(a6),a3 ; get textPtr
|
||
move.w textLen(a6),d3 ; get len
|
||
move.l strArrPtr(a6),a4 ; get string array
|
||
move.w strArrCount(a6),d5 ; get count
|
||
bra.s @EndLoop ; for dbra
|
||
@MainLoop
|
||
; if 0 we have variable length pstrings in the array and handle
|
||
; differently, see below <1-8-91jh>
|
||
move.w strArrMaxLen(a6),d4 ; get max str length
|
||
; call compare with array entry
|
||
|
||
move.l a3,a0 ; pass ptr1
|
||
move.l d3,d0 ; pass len1
|
||
clr.l d1 ; wordize
|
||
move.b (a4)+,d1 ; get length
|
||
tst.w d4 ; if d4.w=0 then we need to remember the actual string
|
||
; length for each string and now the strArrMaxLen as
|
||
; above <1-9-91, jh>
|
||
bne.s @UsingStrArrMaxLen ; valid length in d4.2 so we don't need to remember
|
||
; the real length <1-9-91, jh>
|
||
move.b d1,d4 ; remember # of characters so we can move to next string <1-8-91 jh>
|
||
@UsingStrArrMaxLen ; added label to branch to <1-9-91, jh>
|
||
move.l a4,a1 ; pass start of text
|
||
|
||
; move compare to in-line, add min length test <2/23/88med>
|
||
|
||
CMP.w D1,D0 ; word length
|
||
BGT.S @NextString ; if len actual > len template, skip
|
||
beq.s @TryCompare ; lens equal, try anyway
|
||
cmp.w textMinLen(a6),d0 ; len actual < abbrev len?
|
||
blt.s @NextString ; do next
|
||
|
||
@TryCompare
|
||
|
||
SUBQ.w #1,D0 ; word length
|
||
blt.s @NextString ; actual string is null
|
||
@CompareLoop
|
||
CMPM.B (A0)+,(A1)+
|
||
DBNE D0,@CompareLoop
|
||
beq.s @GotString ; exit <2/23/88med>
|
||
|
||
@NextString
|
||
add.w d4,a4 ; get to next string
|
||
@EndLoop
|
||
dbra d5,@MainLoop ; loop til done
|
||
|
||
bra.s @Exit ; bail with d5 = -1.
|
||
|
||
@GotString
|
||
; return number of string, 1 based
|
||
|
||
sub.w strArrCount(a6),d5 ; get difference <2/23/88med>
|
||
neg.w d5 ; now right direction <2/23/88med>
|
||
|
||
@Exit
|
||
move.w d5,result(a6)
|
||
movem.l (sp)+,MatchStrRegs ; restore regs
|
||
|
||
move.w #args, d0 ; for StdUnlink
|
||
bra StdUnlink ; standard exit
|
||
|
||
endWith
|
||
endProc
|
||
|
||
ENDIF ; } <14>
|
||
|
||
|
||
|
||
|
||
;====================================================================== pke <a7.8><e5.4>
|
||
; Patch Script Manager routines InitDateCache and String2Date for bug fixes
|
||
; needed by HyperCard.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export NewInitDateCache,NewString2Date
|
||
|
||
WhiteSpace EQU 1 ; token number for white space
|
||
AlphaToken EQU 4 ; token number for string
|
||
NumericToken EQU 5 ; token number for number
|
||
AltNumericToken equ $B ; alternate token type for numbers
|
||
NonAlphNumToken EQU 16 ; token numbers starting here correspond to non-alpha numeric tokens
|
||
NilToken EQU $7F ; token number for nil <14>
|
||
MaxTokens EQU 32 ; number of tokens for which there is space
|
||
|
||
omdy EQU 0 ; date order constants
|
||
odmy EQU 1
|
||
oymd EQU 2
|
||
|
||
Str15 EQU 16 ; length of string[15]
|
||
IF FixCacheAndStr2Date THEN ; { <14><15>
|
||
Str4 EQU 5 ; length of string[4] added for more space-efficient cache <1-8-91jh>
|
||
Str8 EQU 9 ; length of string[8] ditto <1-8-91jh>
|
||
ENDIF ; } <14>
|
||
|
||
DayMonthLen equ 15 ; length of days and months
|
||
NumDays EQU 7 ; length of various arrays
|
||
NumMonths EQU 12
|
||
DayList EQU NumDays*Str15
|
||
MonthList EQU NumMonths*Str15
|
||
NumStrBytes EQU 300
|
||
|
||
IF FixCacheAndStr2Date THEN ; { <14><15>
|
||
|
||
monthReplace EQU 0 ; offsets to CvtTable
|
||
reorder EQU 18
|
||
theYear EQU 0 ; offset to elements of arrays in CvtTable.reorder
|
||
theMonth EQU 1
|
||
theDay EQU 2
|
||
|
||
NumTimeStrings equ 4
|
||
TimeLen equ 4
|
||
|
||
|
||
;;-------BEGIN <1-8-90, jh> equates for extend itl1
|
||
; new itl1 extensions
|
||
itl1Version equ localRtn+2 ; <pke>
|
||
itl1Format equ itl1Version+2 ; <pke>
|
||
calendarcode equ itl1Format+2 ; <pke>
|
||
extraDaysOffset equ calendarcode+2
|
||
extraDaysLength equ extraDaysOffset+4
|
||
extraMonthsOffset equ extraDaysLength+4
|
||
extraMonthsLength equ extraMonthsOffset+4
|
||
abbrevDaysOffset equ extraMonthsLength+4
|
||
abbrevDaysLength equ abbrevDaysOffset+4
|
||
abbrevMonthsOffset equ abbrevDaysLength+4
|
||
abbrevMonthsLength equ abbrevMonthsOffset+4
|
||
extraSepsOffset equ abbrevMonthsLength+4
|
||
extraSepsLength equ extraSepsOffset+4
|
||
; For any of the above offsets there will be data down here in all cases this
|
||
; data will have the STR# format (i.e. word for string count followed by an
|
||
; array of pstring)
|
||
|
||
extformatkey equ $A89F
|
||
maxExtraSeps equ 10 ; count of extra seps in cache, must be at least 1!! <10>
|
||
IF maxExtraSeps<1 THEN ; <14>
|
||
aerror &concat('maxExtraSeps wrong: ',&i2s(maxExtraSeps)) ; <14>
|
||
ENDIF ; <14>
|
||
itl1stCount equ 4 ; 0..4 st's in itl1
|
||
|
||
;;-----------END <1-8-91, jh> equates for extended itl1
|
||
ENDIF ; } <14>
|
||
|
||
;========================IMPORTANT NOTE,POTENTIAL DANGER===================================
|
||
;
|
||
; The Data structure below is actually 6 bytes longer than the size of a
|
||
; DateCacheRecord. Initially, I fixed it so that the Record fit within 512 bytes
|
||
; but that change forced very large patches to String2Date and String2Time in the
|
||
; aurora and esprit ROMs.
|
||
;
|
||
; Since these patches were large and required a fair amount of change to ScriptMgrROMPatch.a
|
||
; we rethought fixing the cache so that it fit into 512 bytes and instead opted
|
||
; for keeping the fields in identical offsets.
|
||
;
|
||
; This is not as bad as it sounds (although it is bad, let there be no doubt about that)
|
||
; since the last 32 bytes of a tokenBlock are reserved and at this time (7.0 and earlier)
|
||
; are neither read from nor written to. For that reason, the fact that the declaration
|
||
; below is 6 bytes longer than the memory provided for it is only a forgiveable bit
|
||
; of forgetfulness.
|
||
;
|
||
; However, do NOT read or write any values past the itlResource field of the token block.
|
||
; And do NOT do what inside mac and the published headers say to do which is zero out
|
||
; the last 32 bytes of the token block. Doing that will TRASH memory. DON'T DO IT.
|
||
;========================================================================================
|
||
Cache RECORD 0
|
||
version ds.w 1
|
||
CurrentDate DS LongDateRec
|
||
BaseDate DS LongDateRec
|
||
theDays DS.B DayList ; <a7.8><e5.4>
|
||
theMonths DS.B MonthList ; <a7.8><e5.4>
|
||
IF FixCacheAndStr2Date THEN ; { <14><15>
|
||
theEveStr DS.B Str4 ;use new string definitions to make room for altseps
|
||
theMornStr DS.B Str4 ;
|
||
the24hrAMStr DS.B Str4 ;
|
||
the24hrPMStr DS.B Str4 ;
|
||
countAltSeps DS.W 1 ;number of separator tokens <14>
|
||
AltSeps DS.W maxExtraSeps ;contains an array of separator tokens <14>
|
||
filler DS.B 6
|
||
ELSE ; }{ <14>
|
||
theEveStr DS.B Str15
|
||
theMornStr DS.B Str15
|
||
the24hrStr DS.B Str15
|
||
ENDIF ; } <14>
|
||
theTimeSep DS.W 1
|
||
theDateSep DS.W 1
|
||
theDateOrder DS.b 1
|
||
longDateOrder ds.b 1
|
||
theAbbrLen DS.W 1
|
||
TBlock DS tokenBlock
|
||
CacheSize equ *
|
||
theTimeStrings equ theEveStr
|
||
ENDR
|
||
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; function InitDateCache(theCache: CachePtr): OSErr;
|
||
;
|
||
; InitDateCache will initialize the items in the DateCacheRecord pointed to by theCache^
|
||
; and set the initialized item to true
|
||
;
|
||
; The bug fixes are in the CopyArray subroutine <a7.8><e5.4>.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
IF FixCacheAndStr2Date THEN ; <14><15>
|
||
idcSaveRegs REG A2-A4/D3-d7 ; use d5,d6,d7 in our code to cache separators <1-10-91, jh>
|
||
ELSE ; <14>
|
||
idcSaveRegs REG A2-A4/D3/D4
|
||
ENDIF ; <14>
|
||
|
||
InitCacheRec RECORD {A6link},decr
|
||
Result DS.W 1 ; offset to function result (integer)
|
||
paramBegin EQU *
|
||
theCache DS.L 1 ; pointer to the cache record
|
||
selector ds.l 1 ; added for resource
|
||
paramEnd EQU *
|
||
return DS.L 1
|
||
A6link DS.L 1
|
||
theTokens DS.B 2*TokenRec.tokenRecSize
|
||
Intl0 DS.L 1 ; handle, not pointer
|
||
Intl1 DS.L 1 ; handle, not pointer
|
||
altSpace ds.w 1 ; use top byte
|
||
aLongDate ds LongDateTime ;
|
||
IF FixCacheAndStr2Date THEN ; <14><15>
|
||
temp4bytes ds.l 1 ;4 bytes to cache temp string <1-10-91,jh>
|
||
ENDIF ; <14>
|
||
localsize EQU *
|
||
ENDR
|
||
|
||
WITH InitCacheRec,LongDateField
|
||
|
||
parametersize EQU paramBegin - paramEnd ; size of parameter space on stack <14>
|
||
|
||
NewInitDateCache
|
||
LINK A6,#localsize ; Establish local frame and variables
|
||
MOVEM.L idcSaveRegs,-(SP) ; saved used registers
|
||
CLR.W Result(A6) ; clear function result
|
||
|
||
MOVE.L theCache(A6),A2 ; cache addr
|
||
|
||
move.b #' ',altSpace(a6) ; assume no alt space
|
||
|
||
sub.l #6,sp ; reserve returns
|
||
_IntlScript ; get the script
|
||
move.w #smScriptRight,-(sp) ; get flag
|
||
_GetScript ; get value
|
||
tst.l (sp)+ ; got it?
|
||
beq.s @NoAltSpace ; no
|
||
move.b #' '+$80,altSpace(a6) ; use alt space.
|
||
@NoAltSpace
|
||
|
||
WITH Cache
|
||
|
||
lea aLongDate(a6),a0 ; @temp
|
||
clr.l (a0)+ ; no high
|
||
move.l Time,(a0)+ ; low = current
|
||
pea aLongDate(a6) ; extended
|
||
pea CurrentDate(A2) ; get current date from system global time and convert to date
|
||
_LongSecs2Date
|
||
|
||
lea aLongDate(a6),a0 ; @temp
|
||
clr.l (a0)+ ; no high
|
||
clr.l (a0)+ ; low = current
|
||
pea aLongDate(a6) ; extended
|
||
pea BaseDate(A2) ; get base date and convert to date
|
||
_LongSecs2Date
|
||
|
||
; IUGetIntl(0): Handle
|
||
|
||
CLR.L -(SP)
|
||
CLR.W -(SP)
|
||
_IUGetIntl
|
||
MOVE.L (SP)+,Intl0(A6)
|
||
|
||
move.w ResErr,d0 ; did intl0 load in all right
|
||
BEQ.S GotIntl0Ok ; if so, go on
|
||
|
||
MOVE.W d0,Result(A6)
|
||
BRA Exit
|
||
|
||
GotIntl0Ok
|
||
|
||
MOVE.L Intl0(A6),A3
|
||
; Lock itl0 across Block2String calls (which can now move memory)
|
||
move.l a3,a0
|
||
_HLock
|
||
|
||
MOVE.L (A3),A3 ; now a3 is pointer to itl0
|
||
|
||
; Block2String(eveStr,theEveStr,4,true)
|
||
|
||
LEA eveStr(A3),A0 ; get international 0 record for evening string
|
||
LEA theEveStr(A2),A1
|
||
MOVEQ #4,D0
|
||
MOVE.B #1,D1
|
||
move.b altSpace(a6),d2 ; pass alt string
|
||
JSRBIND ROMBlock2String ; convert packed array of char into string <a7.8><e5.4>
|
||
; with no leading spaces
|
||
; Block2String(mornStr,theMornStr,4,true)
|
||
|
||
LEA mornStr(A3),A0 ; get international 0 record for morning string
|
||
LEA theMornStr(A2),A1
|
||
MOVEQ #4,D0
|
||
MOVE.B #1,D1
|
||
move.b altSpace(a6),d2 ; pass alt string
|
||
JSRBIND ROMBlock2String ; convert packed array of char into string <a7.8><e5.4>
|
||
; with no leading spaces
|
||
; Block2String(time1Stuff,the24hrStr,1,true)
|
||
IF FixCacheAndStr2Date THEN ; <14><15>
|
||
lea timeSuff(a3),A0 ; AM trailer for 24 hour time
|
||
lea the24hrAMStr(a2),a1 ; position in cache
|
||
moveq #4,d0 ; max four bytes per trailer
|
||
MOVE.B #1,D1
|
||
move.b altSpace(a6),d2 ; pass alt string <8/22/87med>
|
||
JSRBIND ROMBlock2String ; convert packed array of char into…
|
||
; …string with no leading spaces
|
||
lea timeSuff+4(a3),A0 ; PM trailer for 24 hour time
|
||
lea the24hrPMStr(a2),a1 ; position in cache
|
||
moveq #4,d0 ; max four bytes per trailer
|
||
MOVE.B #1,D1
|
||
move.b altSpace(a6),d2 ; pass alt string <8/22/87med>
|
||
JSRBIND ROMBlock2String ; convert packed array of char into…
|
||
|
||
ELSE ; <14>
|
||
|
||
LEA timeSuff(A3),A0 ; get international 0 record for 24 hour string
|
||
LEA the24hrStr(A2),A1
|
||
MOVEQ #1,D0
|
||
MOVE.B #1,D1
|
||
move.b altSpace(a6),d2 ; pass alt string
|
||
JSRBIND ROMBlock2String ; convert packed array of char into string <a7.8><e5.4>
|
||
; with no leading spaces
|
||
ENDIF ; <14>
|
||
|
||
MOVE.B timeSep(A3),theTimeSep(A2) ; get time separator from intl 0
|
||
MOVE.B dateOrder(A3),theDateOrder(A2)
|
||
MOVE.B dateSep(A3),(theTimeSep + 1)(A2)
|
||
|
||
; Now unlock itl0
|
||
move.l Intl0(A6),a0
|
||
_HUnlock
|
||
|
||
; This was moved from above to prevent itl0 and itl1 handles from being purged <7>
|
||
; before we lock them.
|
||
|
||
; IUGetIntl(1): Handle
|
||
|
||
CLR.L -(SP)
|
||
MOVE.W #1,-(SP)
|
||
_IUGetIntl
|
||
MOVE.L (SP)+,Intl1(A6)
|
||
|
||
TST.W ResErr ; did intl1 load in all right
|
||
BEQ.S GotIntl1 ; if so, go on
|
||
|
||
MOVE.W ResErr,Result(A6)
|
||
BRA Exit
|
||
|
||
GotIntl1
|
||
|
||
|
||
MOVE.L Intl1(A6),A3
|
||
|
||
; Lock itl1 across Copy Array calls; it calls Block2String, which can now move memory
|
||
move.l a3,a0
|
||
_HLock
|
||
|
||
MOVE.L (A3),A3 ; now a3 is pointer to itl1
|
||
|
||
; Get the long date order and convert
|
||
; false => dmy, true => mdy; otherwise fancy stuff
|
||
|
||
move.l #omdy,d1 ; assume false
|
||
clr.w d0 ; wordize
|
||
move.b lngDateFmt(a3),d0 ; get long format
|
||
beq.s @GotLong ; done
|
||
move.l #odmy,d1 ; assume true
|
||
cmp.b #$FF,d0 ; true?
|
||
beq.s @GotLong ; yes, got it
|
||
|
||
; if we are looking at the long date, only the day and year are important,
|
||
; since the dayOfWeek and month are both strings. Walk through the format until
|
||
; we find either one or the other
|
||
|
||
@LongFmtLoop
|
||
move.b d0,d2 ; get bottom half-nybble
|
||
and.b #3,d2 ; got it
|
||
cmp.b #longDay,d2 ; day?
|
||
beq.s @GotLong ; yes, return #odmy
|
||
cmp.b #longYear,d2 ; year?
|
||
beq.s @LongYearFirst ; go for it
|
||
lsr.b #2,d0 ; strip bottom
|
||
bne.s @LongFmtLoop ; repeat until done
|
||
@LongYearFirst
|
||
move.l #oymd,d1 ; year first (also if none found)
|
||
|
||
@GotLong
|
||
move.b d1,longDateOrder(a2) ; set it
|
||
|
||
; continue
|
||
MOVE.B abbrLen(A3),theAbbrLen(A2) ; get abbrLen
|
||
|
||
; changed order for more convenience in the later routine
|
||
lea months(a3),a4 ; source of days
|
||
LEA theMonths(A2),a1 ; destination names of the day and months
|
||
MOVE.L #(numMonths - 1),D3 ; load day and months from intl 1 rec into space
|
||
jsr CopyArray ; copy days
|
||
|
||
lea days(a3),a4 ; source of days
|
||
LEA theDays(A2),a1 ; destination names of the day and months
|
||
MOVE.L #(numDays - 1),D3 ; load day and months from intl 1 rec into space
|
||
jsr CopyArray ; copy days
|
||
|
||
|
||
IF NOT FixCacheAndStr2Date THEN ; <14><15>
|
||
|
||
; Now continue with ROM code
|
||
JMPBIND ROMAfter2ndJSRCopyArray ; <a7.8><e5.4>
|
||
Exit
|
||
JMPBIND ROMExit ; <a7.8><e5.4>
|
||
|
||
|
||
ELSE ; <14>
|
||
|
||
; Begin addition where we try to cache any valid st0 through st4 strings <14>
|
||
; and any alternative separators included in the extended itl1
|
||
; note that these separators are not cached as strings but as tokens produced by IntlTokenize
|
||
; jh, 1-8-91
|
||
; Notes on the loop:
|
||
; An itl1 has 5 fields that are declared as PACKED ARRAY[1..4] OF CHAR
|
||
; This field contain valid separators for the long date format
|
||
; This loop walks through those arrays, and converts valid separators into pascal
|
||
; strings; those strings are then converted to tokens and potentially cached in the subroutine TokenizeSepAndCache
|
||
; Register usage in the loop:
|
||
; a0-used to pass address of separator string to TokenizeSepAndCache
|
||
; a1-used briefly in the beginning to copy the date separator obtained previously from the itl0 into the cache
|
||
; a2-just like the rest of this code holds pointer to the cache
|
||
; a3-contains pointer to itl1
|
||
; a4-points at the ST arrays is
|
||
; d0-used to hold characters so they can be compared to null and space
|
||
; d1-used as a scratch register
|
||
; d3 - loop control for inner loop
|
||
; d4 - used to hold count of characters placed in temp4bytes, for that reason used to pass length of string to TokenizeSepAndCache
|
||
; d6 - loop control for outer loop
|
||
; d7 - holds available cache space
|
||
|
||
|
||
move.w #maxExtraSeps,d7 ;hold onto the maximum chars allowed
|
||
clr.w CountAltSeps(a2) ;clear the count
|
||
|
||
; get the itl resource and stash it in parameter block
|
||
WITH TBlock
|
||
clr.l -(sp) ; return handle
|
||
move.w #4,-(sp) ; get itl4
|
||
_IUGetIntl
|
||
move.l (sp)+,itlResource(a2) ; store itl resource
|
||
ENDWITH
|
||
beq @FatalError ; couldn't get it give up
|
||
|
||
lea st0(a3),a4 ;load start of 4-byte char blocks
|
||
move.l #4,d6 ; 5 ST strings to look at
|
||
|
||
@startSTLoop
|
||
clr.l d4 ; clear our offset into temp4bytes
|
||
move.w #3,d3
|
||
lea temp4bytes(a6),a1 ;get our temp string address
|
||
|
||
@char4loop
|
||
move.b (a4)+,d0
|
||
beq.s @looptotop ; yes its null so just continue
|
||
cmp.b #32,d0 ; space ?
|
||
beq.s @looptotop ; yes don't copy it, but continue
|
||
move.b d0,(a1)+
|
||
addq #1,d4 ;increment our offset
|
||
|
||
@looptotop
|
||
dbra d3,@char4loop ;loop back
|
||
|
||
tst.w d4 ; if d4 > 0 we have some sort of string
|
||
beq.s @looptoTopST ; its 0 so look at the next st[x]
|
||
|
||
;if we got a string we want to turn it into a Token here and then stick the token into
|
||
; our cache
|
||
moveq #1,d5 ; only one token permitted
|
||
|
||
;now we need to tokenize this separator and check to see if it is in the cache
|
||
lea temp4bytes(a6),A0 ; load the address of the source text into A0 which is where the subroutine expects it
|
||
bsr TokenizeSep ; branch to subroutine
|
||
bne.s @looptoTopST ; something went wrong with that one
|
||
bsr CompareAndCache ; check the token against the cache
|
||
ble.s @DoneWithItls ; if we have run out of cache, quit this
|
||
@looptoTopST
|
||
dbra d6,@startSTloop
|
||
|
||
|
||
;now we've copied the old st0-st4 separators, its time to check and see if we are
|
||
;dealing with an extended itl1 that might have some more separators added
|
||
cmp.w #extformatkey,localRtn(a3) ;is local routine $A89F ($A89F (unimplemented trap)
|
||
; is used here to flag this itl1 as an extended itl1)
|
||
bne.s @DoneWithItls ;nope, so branch around extra sep copying code
|
||
|
||
move.l extraSepsOffset(a3),d1 ;ok move the offset into d1
|
||
beq.s @DoneWithItls ;moved a 0 nothing is actually here so give it up
|
||
|
||
move.l extraSepsLength(a3),d0 ;how long is this array
|
||
ble.s @DoneWithItls ;negative or 0 means nothing is really here so get out
|
||
add.l a3,d1 ;add offset to ptr to itl1
|
||
move.l d1,a4 ;move result to a4
|
||
move.w (a4)+,d3 ;move the count of extra separators to d3,
|
||
subq #1,d3 ; set up for dbra
|
||
clr.l d4 ;clear d4 for safety
|
||
moveq #1,D5 ;D5 carrys number of token recs allowed into subroutine
|
||
@extraSepLoop
|
||
move.b (a4)+,d4 ;a4 points at the length byte, put that in d4 and increment a0 to point at actual string
|
||
move.l a4,a0 ;TokenizeSep expects source in a0
|
||
bsr TokenizeSep ; branch to subroutine
|
||
bne.s @extraSepLoop ; NE is tokenizer failed
|
||
bsr CompareAndCache ; tokenizer was OK so compare the token and potentially cache it
|
||
ble.s @DoneWithItls ; if we have run out of cache, quit this
|
||
add d4,a4 ; increment to next string
|
||
dbra d3,@extraSepLoop
|
||
|
||
@DoneWithItls
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;end addition
|
||
;jh, 1-8-91 <14>
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;end addition
|
||
|
||
; Now unlock itl1
|
||
move.l Intl1(A6),a0
|
||
_HUnlock
|
||
|
||
LEA theTimeSep(A2),A0 ;get ready for tokenize sub routine
|
||
moveq #2,d5 ;we allow two tokens
|
||
move.l #2,d4 ; length into d4
|
||
bsr TokenizeSep ;
|
||
beq.s @GotSeparators ; OK so back to the old code
|
||
|
||
@FatalError ;added label so I could branch here from new code <10>
|
||
MOVE.W #fatalDateTime,Result(A6) ; if not, exit procedure and return fatal error
|
||
BRA.S Exit
|
||
|
||
|
||
@GotSeparators
|
||
MOVE.W theTokens(A6),theTimeSep(A2)
|
||
MOVE.W (theTokens + TokenRec.tokenRecSize)(A6),theDateSep(A2) ; store date and time sep tokens
|
||
MOVE.L #MaxTokens,TBlock.tokenLength(A2) ; no more than 2 tokens, please
|
||
|
||
Exit
|
||
MOVEM.L (SP)+,idcSaveRegs ; restore registers to their original value
|
||
move.w #parametersize, d0 ; for StdUnlink
|
||
JMPBIND ROMStdUnlink ; standard exit
|
||
|
||
ENDIF ; <14>
|
||
|
||
|
||
; little subroutine for code savings
|
||
; a4 is source pointer
|
||
; a1 is dest pointer
|
||
; d3 is byte length
|
||
|
||
CopyArray
|
||
move.l a1,d4 ; dest ptr
|
||
|
||
@LOOP MOVE.L A4,A0 ; move string from intl 1 rec <a7.8><e5.4>
|
||
MOVE.L d4,A1 ; into local frame
|
||
moveq #0,d0 ; Block2String wants a long! <a7.8><e5.4>
|
||
MOVE.B (A0)+,D0 ; with length from first byte of string
|
||
MOVEQ #1,D1 ; with no local frame
|
||
move.b altSpace(a6),d2 ; pass alt string
|
||
JSRBIND ROMBlock2String ; search <a7.8><e5.4>
|
||
ADD.L #Str15,d4 ; get next string to transfer
|
||
ADD.w #Str15,A4 ; into next string in local frame <a7.8><e5.4>
|
||
DBRA D3,@LOOP
|
||
rts
|
||
|
||
|
||
IF FixCacheAndStr2Date THEN ; { <14><15>
|
||
;-----------------------------------------------------------------------------------
|
||
; TokenizeSep
|
||
; This subroutine is called to tokenize any separator we have found and store the
|
||
; resulting token in the datecache
|
||
; registers
|
||
; INPUT
|
||
; A0 - ptr to the source text
|
||
; A2 - which holds a ptr to the cache which contains a token paramblock
|
||
; D5 - number of tokens allowed
|
||
; D4 - length of source text
|
||
; TRASHED
|
||
; A1,D0,D1
|
||
; sets NE if Tokenizer fails
|
||
;-------------------------------------------------------------------------------------
|
||
|
||
TokenizeSep
|
||
; load the tokenizer parameter block for later
|
||
WITH TBlock
|
||
|
||
LEA theTokens(A6),A1 ; spaces for tokens in local frame
|
||
MOVE.L A1,tokenList(A2)
|
||
MOVE.L d5,tokenLength(A2) ; number of tokens allowed (shouldn't be more than 2)
|
||
CLR.L tokenCount(A2)
|
||
CLR.L DoString(A2) ; clear out DoString, DoAppend, DoAlphaNumeric, and DoNest
|
||
|
||
LEA leftDelims(A2),A1
|
||
MOVE.W #(decimalCode-leftDelims)/2,D0 ; load NilToken into leftDelims, rightDelims, leftComment
|
||
@LOOP0
|
||
MOVE.W #NilToken,(A1)+ ; RightComment, EscapeCode & decimal code
|
||
DBRA D0,@LOOP0
|
||
|
||
|
||
; get the address of the source from a1
|
||
|
||
MOVE.L A0,source(A2) ; inside With TBlock
|
||
MOVE.L d4,sourceLength(A2) ; d4 holds the length
|
||
|
||
ENDWITH ; TBlock
|
||
|
||
; IntlTokenize(@TBlock): signedByte;
|
||
|
||
CLR.B -(SP)
|
||
PEA TBlock(A2)
|
||
_IntlTokenize ; tokenize text
|
||
tst.b (sp)+ ; test the result and set the return bit
|
||
|
||
rts
|
||
|
||
;---------------------------------------------------------------------------------------------------
|
||
; CompareAndCache
|
||
; Once we've sucessfully tokenized one of the separators we use this routine to compare
|
||
; the new token against the stuff already in the cache
|
||
; if the new token is not there it is cached
|
||
;
|
||
; REGISTERS
|
||
; INPUT
|
||
; a2 - Ptr to cache
|
||
; d7.w - token slots available in cache
|
||
; TRASHED
|
||
; d0,d1,a1
|
||
; SETS cc AT EXIT BASED ON UPDATED d7.w
|
||
;-------------------------------------------------------------------------------------------------
|
||
CompareAndCache
|
||
WITH TBlock
|
||
|
||
; so we have a token type in theTokenRec
|
||
lea AltSeps(a2),a1 ; get destination in a1
|
||
move.w countAltSeps(a2),d0 ; number of tokens in d0
|
||
beq.s @storeToken ; none there so store it
|
||
subq #1,d0 ; for dbra
|
||
@tokenCompare ; otherwise compare token with whats in the cache
|
||
move.w (a1)+,d1
|
||
cmp.w theTokens(a6),d1 ;
|
||
beq.s @quitSubroutine ; we've already got this one so lets get on with it
|
||
; addq #2,a1 ; increment the pointer into the cache
|
||
dbra d0,@tokenCompare ; ne so look at the next one
|
||
@storeToken
|
||
move.w theTokens(A6),(a1) ; when loop completes a1 points at first empty slot
|
||
add.w #1,countAltSeps(a2) ; increment our count of separators
|
||
subq #1,d7 ; decrement our number of available token slots in cache
|
||
|
||
ENDWITH
|
||
@quitSubroutine
|
||
tst.w d7 ; set condition codes
|
||
rts
|
||
|
||
ENDIF ; moved this back inside 2 ENDWITHs <14><15>
|
||
|
||
ENDWITH ; Cache
|
||
ENDWITH
|
||
|
||
; ----------------------------------------------------------------------------
|
||
;function String2Date( textPtr: Ptr;
|
||
; textLen: longint;
|
||
; theCache: DateCachePtr;
|
||
; var lengthUsed: longint;
|
||
; var DateTime: LongDateRec): Integer;
|
||
;
|
||
; String2Date will look for a date in the text given it according to the international
|
||
; resource format. Using the Tokenizer routine it will look for a dayofWeek (which will
|
||
; be a string), a month (either a string or a number) and a day and year (both numbers).
|
||
; If the month is a number, order is decided by the ShortDate format in INTL 0; otherwise
|
||
; String2Date uses a table. Note if only two numbers are found they are assumed to be day
|
||
; and month. If one number is found it is assumed to be a date. Missing fields are
|
||
; filled in by the current date and time
|
||
;
|
||
; Register Usage
|
||
;
|
||
; A2 - Work register D3 - loop control register
|
||
; A3 - Work register D4 - MonthFound
|
||
; A4 - Cache Addr D5 - ResultNum
|
||
; D6 - AbbrLen
|
||
; D7 - NumDelimsFound
|
||
;
|
||
; The bug fixes are: … <a7.8><e5.4>
|
||
; ----------------------------------------------------------------------------
|
||
|
||
s2dSaveRegs REG D3-D7/A2-a4 ; removed a5
|
||
|
||
DateFrame RECORD {A6link},decr
|
||
Result DS.W 1 ; offset to function result (integer)
|
||
paramBegin EQU *
|
||
textPtr DS.L 1 ; offset to Date2Time's paramters
|
||
textLen DS.L 1
|
||
theCache DS.L 1 ; @DateCacheRecord
|
||
RestofText DS.L 1 ; @Longint
|
||
DateTime DS.L 1 ; @LongDateRec
|
||
selector ds.l 1 ; added for resource
|
||
paramEnd EQU *
|
||
return DS.L 1
|
||
A6link DS.L 1
|
||
theTokens DS.B MaxTokens*TokenRec.tokenRecSize ; storage for tokens found by tokenizer
|
||
theDate DS LongDateRec ; date time rec
|
||
results DS.W 3 ; three temporary results
|
||
myDateOrder DS.W 1
|
||
DayFound DS.W 1
|
||
lastItemSep DS.W 1
|
||
lastToken DS.W 1
|
||
lastTokenAddr DS.L 1
|
||
lastExToken DS.W 1
|
||
dummyLongDate ds LongDateTime
|
||
stringStorage DS.B NumStrBytes
|
||
localsize EQU *
|
||
ENDR
|
||
|
||
WITH DateFrame
|
||
With Cache,LongDateField
|
||
IF FixCacheAndStr2Date THEN ; Needed this conditional <15>
|
||
IMPORT ValidLong
|
||
ENDIF ; <15>
|
||
|
||
NewString2Date
|
||
LINK A6,#localsize ; Establish local frame and variables
|
||
MOVEM.L s2dSaveRegs,-(SP) ; saved used registers
|
||
|
||
JSRBIND ROMDateTimeEntry ; initialize & call _IntlTokenize
|
||
|
||
; Note that DateTimeEntry also does the following:
|
||
; 1. moves theCache(a6) into a4
|
||
; 2. moves TheTokens(a6) into a3
|
||
; 3. sets result(a6)
|
||
; 4. clears D7,D6; sets D5.L = -1
|
||
; 5. after IntlTokenize, sets D3= number of tokens - 1
|
||
|
||
tst.w result(a6) ; entry failed?
|
||
bne DTComExit ; bail if so
|
||
|
||
; specific stuff
|
||
|
||
MOVEQ #-1,D4 ; initialize MonthFound to -1
|
||
CLR.W DayFound(A6)
|
||
LEA CurrentDate(A4),A1 ; source
|
||
LEA theDate(A6),A0 ;
|
||
MOVE.L (A1)+,(A0)+ ; era, year
|
||
MOVE.L (A1)+,(A0)+ ; month, day
|
||
MOVE.L (A1)+,(A0)+ ; hour, minute
|
||
move.w (a1)+,(a0)+ ; second
|
||
CLR.W (A0)+ ; clear out dayOfWeek. Will either be set by user or be set
|
||
; in the course of the validity check of the date
|
||
MOVE.B theAbbrLen(A4),D6
|
||
|
||
WITH TokenRec
|
||
|
||
@TokenLoop
|
||
MOVE.W theToken(A3),D1 ; get token code from TokenRec record at (A3)
|
||
CMP.W #NonAlphNumToken,D1 ; is it a separator
|
||
BGE.S @FoundSeparator
|
||
SUB.W #WhiteSpace,D1 ; was it a white space?
|
||
BEQ @TokenLoopEnd ; ignore
|
||
SUBQ.W #(AlphaToken - WhiteSpace),D1 ; is it an alpha token?
|
||
IF FixCacheAndStr2Date THEN ; { <14><15>
|
||
beq @FoundAlpha ; <1-8-91, jh> changed to .w
|
||
SUBQ.W #(NumericToken - AlphaToken),D1 ; is it a number token?
|
||
BEQ @NumberToken ; <1-8-91, jh> changed to .w
|
||
SUBQ.W #(AltNumericToken - NumericToken),D1 ; is it a number token? <9/2/87med>
|
||
BEQ @NumberToken ; <1-8-91, jh> changed to .w <9/2/87med>
|
||
ELSE ; }{ <14>
|
||
beq.s @FoundAlpha
|
||
SUBQ.W #(NumericToken - AlphaToken),D1 ; is it a number token?
|
||
BEQ.S @NumberToken
|
||
SUBQ.W #(AltNumericToken - NumericToken),D1 ; is it a number token? <9/2/87med>
|
||
BEQ.S @NumberToken ; <9/2/87med>
|
||
ENDIF ; } <14>
|
||
BRA @TokenLoopEnd ; ignore any other characters
|
||
|
||
@FoundSeparator
|
||
TST.B D7 ; possible separator. Has a separator already been found
|
||
BEQ.S @OneDelimFound ; no, so no error yet
|
||
OR.W #TooManySeps,Result(A6) ; yes, so now we have too many separators
|
||
|
||
@OneDelimFound
|
||
IF FixCacheAndStr2Date THEN ; { <14><15>
|
||
;***********************
|
||
;begin <1-8-91 jh> changes <14>
|
||
;here we compare if any of the separators in the itl1 equal this so-called
|
||
;separator we just found
|
||
;*********************
|
||
cmp.w theDateSep(a4),d1 ; start by comparing the DateSep (which is not cached with the other stuff) with the new token
|
||
beq.s @SeparatorFound ; found it
|
||
move.w countAltSeps(a4),d0 ; d0 will be our loop counter
|
||
beq.s @SeparatorFound ; hmm, nothing cached, but didn't match DateSep we could fail completely
|
||
; but I guess will just go with the old method of having everything match
|
||
subq #1,d0 ; set up for dbra
|
||
lea AltSeps(a4),a0 ; address of alternate separators
|
||
@compareSeps
|
||
cmp.w (a0)+,d1 ; compare cached tokens with new token
|
||
beq.s @SeparatorFound ; found it branch out of loop
|
||
dbra d0,@compareSeps ; decrement and branch
|
||
;no separator match. If any of the date is there we set up for an error and kind of continue
|
||
TST.w D5 ; is this after the first number loaded? (.w)
|
||
bmi.s @firstNonAlphaInvalid ; if first non-alphanumeric isn't a valid separator we return dateTimeInvalid
|
||
or.w #SepNotIntlSep+sepNotConsistent+extraneousStrings,Result(a6)
|
||
bra.s @SeparatorFound
|
||
@firstNonAlphaInvalid
|
||
OR.W #dateTimeInvalid,Result(A6) ; date not valid, return error
|
||
BRA DTComExit
|
||
|
||
@SeparatorFound
|
||
;;********************************************
|
||
; end <1-8-91, jh> changes <14>
|
||
;;********************************************
|
||
ENDIF ; } <14>
|
||
|
||
ADDQ.B #1,D7 ; record separator found
|
||
TST.w D5 ; is this after the first number loaded? (.w) <1/5/88med>
|
||
BMI @TokenLoopEnd ; if we have not reached a number yet go on
|
||
BNE.S @CheckDateSep ; if we loaded in a number then check consistency
|
||
|
||
MOVE.W D1,lastItemSep(A6) ; otherwise update lastItemSep with just found separator
|
||
BRA @TokenLoopEnd
|
||
|
||
@CheckDateSep
|
||
CMP.W lastItemSep(A6),D1 ; are they consistent
|
||
BEQ @TokenLoopEnd ; if yes, than go on
|
||
|
||
OR.W #SepNotIntlSep+sepNotConsistent,Result(A6) ; record warning
|
||
BRA @TokenLoopEnd
|
||
|
||
@NumberToken
|
||
; check for numbers separated only by white space
|
||
tst.w d7 ; got a separator?
|
||
bne.s @1 ; yes
|
||
tst.w d5 ; first number?
|
||
blt.s @1 ; yes, skip
|
||
bne.s @0 ; have 1 number
|
||
move.w #WhiteSpace,lastItemSep(A6) ; set separator
|
||
bra.s @1 ; continue
|
||
@0
|
||
cmp.w #WhiteSpace,lastItemSep(a6) ; same?
|
||
beq.s @1 ; yes, continue
|
||
or.w #SepNotIntlSep+sepNotConsistent,Result(A6) ; record warning
|
||
@1
|
||
; end of white space check
|
||
|
||
CLR.L D7 ; clear out past separators
|
||
CMP.W #2,D5 ; make sure that results array is not full
|
||
BGE @ExtrnsToken ; if full, record warning and search <a7.8><e5.4>
|
||
; for final string (remove .s)
|
||
|
||
; ValidLong(position,textLength): longint
|
||
|
||
MOVE.L stringPosition(A3),A0
|
||
IF FixCacheAndStr2Date THEN ; <14><15>
|
||
jsr ValidLong ; call new one to get > 32768 test
|
||
ELSE ; <14>
|
||
JSRBIND ROMValidLong ; get number in text at TokenRec.position <a7.8><e5.4>
|
||
ENDIF ; <14>
|
||
|
||
IF FixCacheAndStr2Date THEN ; <14><15>
|
||
bpl.s @numberOK ; branch around error if the number is a valid long
|
||
ori.w #dateTimeInvalid,result(a6) ;bad number so or in the dateTimeInvalid error
|
||
bra DTComExit ; and branch to our exit place
|
||
@numberOK
|
||
ELSE ; <14>
|
||
|
||
BMI DTComExit
|
||
|
||
ENDIF ; <14>
|
||
|
||
JSRBIND ROMFixValue ; <a7.8><e5.4>
|
||
bra @TokenRecognized ; get next token (remove .s) <a7.8><e5.4>
|
||
|
||
@FoundAlpha
|
||
CLR.L D7 ; clear out past separators
|
||
|
||
; UprString(newTextPtr,AbbrLen) ; and make it uppercase for case insensitive search
|
||
|
||
MOVE.L stringPosition(A3),A2
|
||
ADDQ.L #1,A2
|
||
MOVE.L A2,A0
|
||
MOVE.L length(A3),D0 ; use real length
|
||
|
||
_UpperText ; _LwrString with uppercase function <a39><e11><3>
|
||
|
||
TST.W D4
|
||
BPL.S @SearchForDay ; <a7.8><e5.4>
|
||
|
||
; MatchString(newTextPtr,AbbrLen,@months,15,12): integer
|
||
|
||
CLR.W -(SP) ; attempt to find a day/month string which matches alpha token
|
||
MOVE.L A2,-(SP)
|
||
MOVE.W length+2(a3),-(SP) ; push length as integer
|
||
MOVE.W D6,-(SP) ; push minlen as integer
|
||
PEA theDays(A4) ; <a7.8><e5.4>
|
||
MOVE.W #DayMonthLen,-(SP)
|
||
MOVE.W #NumMonths+NumDays,-(SP) ; check for both at once
|
||
JSRBIND ROMMatchString ; <a7.8><e5.4>
|
||
MOVE.W (SP)+,D2 ; save in D2
|
||
BLE.S @ExtrnsToken ; checking both
|
||
|
||
; decide between days and months
|
||
|
||
sub.w #NumDays,d2 ; months?
|
||
ble.s @CheckForDay ; no, do days
|
||
|
||
; got a month
|
||
CMP.W #2,D5 ; is result array already full?
|
||
BGE.S @ExtrnsToken ; if so, then its not a needed token
|
||
|
||
ADDQ.W #1,D5 ; is in range, result is not full and string
|
||
MOVE.W D5,D1 ; did not match as a day
|
||
ADD.W D1,D1 ; double index for integer array
|
||
LEA results(A6),A1 ; ResultNum:= ResultNum + 1
|
||
MOVE.W D2,(A1,D1.W) ; results[ResultNum]:= match result
|
||
MOVE.W D5,D4 ; MonthFound:= resultNum
|
||
BRA.S @TokenRecognized
|
||
|
||
; if day not found yet, we need to see if current string matches a day <a7.8><e5.4>
|
||
@SearchForDay
|
||
TST.B DayFound(a6) ; have we found one yet?
|
||
BNE.S @ExtrnsToken ; day already found, record warning
|
||
|
||
CLR.W -(SP) ; attempt to find a day string which matches alpha token
|
||
MOVE.L A2,-(SP)
|
||
MOVE.W length+2(a3),-(SP) ; push length as integer
|
||
MOVE.W D6,-(SP) ; push minlen as integer
|
||
PEA theDays(A4)
|
||
MOVE.W #DayMonthLen,-(SP)
|
||
MOVE.W #NumDays,-(SP) ; just check days this time
|
||
JSRBIND ROMMatchString ; <a7.8><e5.4>
|
||
MOVE.W (SP)+,D2 ; save in D2
|
||
BLE.S @ExtrnsToken ; checking both
|
||
|
||
BRA.S @HaveDay
|
||
|
||
@CheckForDay
|
||
TST.B DayFound(a6) ; off of a6!
|
||
BNE.S @ExtrnsToken ; day already found, record warning
|
||
|
||
add.w #NumDays,d2 ; restore days <a7.8><e5.4>
|
||
@HaveDay ; <a7.8><e5.4>
|
||
ST DayFound(A6) ; record that day was found <a7.8><e5.4>
|
||
MOVE.W D2,theDate.dayOfWeek(A6) ; otherwise, load dayOfWeek into date time record
|
||
|
||
TST.W D5 ; is dayOfWeek between two numbers (.w)
|
||
BMI.S @NoWarning ; if no number has been found yet, go on
|
||
OR.W #fieldOrderNotIntl,Result(A6) ; record warning
|
||
@NoWarning
|
||
BRA.S @TokenRecognized
|
||
|
||
@ExtrnsToken
|
||
TST.W lastExToken(A6) ; is this the first extraneous token found?
|
||
BPL.S @TokenLoopEnd ; no, go on
|
||
|
||
MOVE.W D3,lastExToken(A6) ; a string which we don't recognize has been found
|
||
BRA.S @TokenLoopEnd ; record warning and go on
|
||
|
||
@TokenRecognized
|
||
MOVE.W D3,lastToken(A6)
|
||
MOVE.L A3,lastTokenAddr(A6) ; save loop and token addr for later use
|
||
|
||
@TokenLoopEnd
|
||
ADD.L #tokenRecSize,A3 ; add size of TokenRec record to A3 to get next token
|
||
CMP.W #2,D5 ; if the result array full (.w)
|
||
SGE D0
|
||
AND.B DayFound(A6),D0 ; and dayofWeek string been found
|
||
DBNE D3,@TokenLoop ; then stop loop, otherwise go until all tokens are looked at
|
||
|
||
|
||
|
||
JMPBIND ROMAfterDBNE
|
||
|
||
DTComExit
|
||
JMPBIND ROMDTComExit
|
||
|
||
endproc ; replaced this endproc <15>
|
||
|
||
IF FixCacheAndStr2Date THEN ; <14><15>
|
||
;======================================================================
|
||
; Function ValidLong(aStr: Str255): Longint; <2.5>
|
||
; Input stringPtr: ptr in A0
|
||
; Output theLong ($80000000 if invalid) in D0
|
||
; returns a valid longint, positive. Number sets status register
|
||
;======================================================================
|
||
|
||
|
||
ValidLong proc export
|
||
MaxInteger equ $00008000
|
||
movem.l d3/d4,-(sp)
|
||
move.l #$80000000,d0 ; assume bad
|
||
clr.l d4
|
||
move.b (A0)+,d4 ; get length
|
||
ble.s @BailValid ; bail if not there
|
||
|
||
clr.l d1 ; longize
|
||
move.b (a0)+,d1 ; new value
|
||
sub.b #'0',d1 ; adjust
|
||
subq.b #1,D4 ; adjust string length
|
||
|
||
move.l d1,d2 ; initialize total
|
||
bra.s @FastEntry ; enter loop in middle
|
||
|
||
@FastPathLoop
|
||
; multiply by 10
|
||
|
||
add.l d2,d2 ; double
|
||
move.l d2,d3 ; save copy
|
||
lsl.l #2,d2 ; now * 8
|
||
add.l d3,d2 ; now * 10, at a cost of 6+4+12+6=28 10x = 2x + 4·2x
|
||
add.l d1,d2 ; accumulate
|
||
@FastEntry
|
||
move.b (a0)+,d1 ; new value
|
||
sub.b #'0',d1 ; adjust
|
||
dbra d4,@FastPathLoop ; yes, continue
|
||
|
||
@DoneFastPath
|
||
|
||
cmp.l #MaxInteger,d2 ; is it greater than 32768?
|
||
bhi.s @BailValid ; yes, so it is too high, bail
|
||
; note that we don't compare against negative since tokenizer will treat that as a separator
|
||
|
||
move.l d2,d0 ; return result and set status register
|
||
|
||
@BailValid
|
||
tst.l d0
|
||
@Exit
|
||
movem.l (sp)+,d3/d4
|
||
rts
|
||
endProc
|
||
|
||
|
||
ENDIF ; } <14>
|
||
|
||
|
||
|
||
;====================================================================== <a8.0><e5.5>
|
||
; Tail patch on _GetIndADB to fix bug in Script Manager ResetKCHR routine
|
||
; called by SwapKybd: it clears ADB keyboard driver dead state as a word,
|
||
; should be a long.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export ptchGetIndADB
|
||
|
||
ptchGetIndADB
|
||
|
||
|
||
|
||
; We can use the new protection scheme, if the first two instructions in the <11>
|
||
; patch are a bra.s followed by the jump to the old rom address.
|
||
|
||
bra.s @protection
|
||
@JumpToRom
|
||
BackToTrap oldGetIndADB ; Jump back to the Rom
|
||
@protection
|
||
|
||
|
||
CMPBIND ROMAfterGetIndADB,OSTrapReturnAddressDepth(sp) ; From ResetKCHR?
|
||
bne.s @JumpToRom ; if not, just continue with trap
|
||
lea ptchResetKCHR,a1 ; a1 is not a param for GetIndADB
|
||
move.l a1,OSTrapReturnAddressDepth(sp) ; so trap returns to patch, not ROM
|
||
bra.s @JumpToRom ; and go back to the ROM
|
||
|
||
|
||
; When we reach the patch below, we are in ResetKCHR just after the _GetIndADB
|
||
|
||
rkRecord record {a6link},decr
|
||
rkArgs equ *-8 ; size of arguments.
|
||
pointer ds.l 1 ; new KCHR pointer.
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old a6 register.
|
||
adb ds ADBDataBlock ; ADB data structure.
|
||
oldKeyboard ds.l 1 ; old keyboard pointer
|
||
rkLocals equ * ; size of local variables.
|
||
endr
|
||
|
||
ptchResetKCHR
|
||
with rkRecord
|
||
|
||
cmp.b #kybdADBAddr,adb.origADBAddr(a6) ; is it a keyboard?
|
||
bne.s @1 ; no -> skip it.
|
||
move.l adb.dbDataAreaAddr(a6),a0 ; load data area pointer.
|
||
clr.l KybdDriverData.deadKey(a0) ; clear dead state - long! <a8.0><e5.5>
|
||
JMPBIND ROMAfterClrDeadKey ; <a8.0><e5.5>
|
||
|
||
@1 JMPBIND ROM@1dbra ; <a8.0><e5.5>
|
||
|
||
endwith
|
||
endproc
|
||
|
||
|
||
;====================================================================== <5>
|
||
; Set the smgrRect to 0 so that a mouse-down in the script icon is not
|
||
; handled by FilterMouse in GetOSEvent patch. Really undoing our patch to
|
||
; InitMenus; ugly, but necessary, if we don't want to completely patch out
|
||
; GetOSEvent.
|
||
; ----------------------------------------------------------------------------
|
||
proc
|
||
export ptchInitMenus
|
||
|
||
with smgrRecord
|
||
ptchInitMenus
|
||
move.l IntlSpec,a0
|
||
move.l sVectInitMenus(a0),a0
|
||
jsr (a0)
|
||
move.l IntlSpec,a0 ; prepare to stuff smgrRect!
|
||
lea smgrRect(a0),a0
|
||
move.l #0,(a0)+
|
||
move.l #0,(a0)
|
||
rts
|
||
|
||
endwith
|
||
endProc
|
||
|
||
|
||
;============================================================================= <10>
|
||
; GetOSEvent in the ROM ends by jumping to some Script Mgr code that checked
|
||
; events to see if they were script toggling events. Now we want to check if
|
||
; they are "keyboard changing events" - key-down or auto-key events that match
|
||
; a key combination in the 'KSWP' resource. To do this, we have to patch out
|
||
; GetOSEvent and the Script Mgr code it jumped to.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export ptchGetOSEvent
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: GetOSEvent
|
||
;
|
||
; Arguments: A0 (input) -- pointer to user event buffer (32-bit)
|
||
; D0 (input) -- type of event desired (event mask)
|
||
; D0 (output) -- 0=non-null event returned, -1=null event
|
||
; returned
|
||
;
|
||
; Function: This routine returns the next event in the system event queue.
|
||
; The returned event is dequeued, thereby freeing up the space
|
||
; which holds that queue element. If no events of the types
|
||
; enabled by the mask exist, the null event is returned.
|
||
;
|
||
; Calling sequence: MOVE.W #EventMask,D0
|
||
; LEA EventBuffer,A0
|
||
; _GetNextEvent
|
||
;
|
||
; Other: uses D0,D1,D2,A0,A1
|
||
;_______________________________________________________________________
|
||
|
||
EvtOffset EQU 6 ; event record offset from start of
|
||
; event queue element
|
||
|
||
ptchGetOSEvent
|
||
JSRBind ROMOSEventAvail ; first find the event
|
||
BNE.S @EventDone ; don't dequeue null or update events
|
||
|
||
MOVE.L A0,-(SP) ; save user's event record ptr
|
||
MOVE.L A1,A0 ; pointer to event queue element
|
||
LEA EventQueue,A1 ; A1 points to the queue
|
||
JSRBind ROMDequeue ; dequeue it (D0 destroyed)
|
||
MOVE #$FFFF,EvtNum+EvtOffset(A0) ; and release its storage
|
||
MOVE.L (SP)+,A0 ; restore user's event record ptr
|
||
; (needed by SMgrPostMunging)
|
||
MOVEQ #0,D0 ; exit with result code 0
|
||
@EventDone
|
||
; fall thru to newSMgrPostMunging
|
||
|
||
;_______________________________________________________________________
|
||
; newSMgrPostMunging
|
||
;
|
||
; Check key-down and auto-key events to see if they match a key combo
|
||
; in the 'KSWP' resource. If they do, call KeyScript with the
|
||
; corresponding verb from 'KSWP'.
|
||
;_______________________________________________________________________
|
||
|
||
modMask equ $fffb ; mask off capsLock key.
|
||
|
||
; a4.l Script Manager globals pointer.
|
||
; a3.l Keyboard globals pointer.
|
||
; a2.l Event record pointer.
|
||
|
||
newSMgrPostMunging
|
||
with SMgrRecord ; <12>
|
||
movem.l a0-a4/d0-d2,-(sp) ; save the registers.
|
||
GetSMgrCore a4 ; load SMgr globals.
|
||
move.l a0,a2 ; save the event pointer.
|
||
|
||
; If this is a keyDown event, check to see if the keyboard code and
|
||
; modifiers match any of the combinations in the keyboard swapping table.
|
||
;
|
||
; Copied this code in from ScriptMgrPatch.a.
|
||
|
||
FilterKey
|
||
cmp.w #keyDwnEvt,evtNum(a2) ; evtNum = keyDown?
|
||
beq.s @1 ; yes -> check message.
|
||
cmp.w #autoKeyEvt,evtNum(a2) ; evtNum = autoKey?
|
||
bne.s DoneEvent ; no -> bail out.
|
||
@1
|
||
move.l smgrKeySwap(a4),d0 ; swap table = nil?
|
||
beq.s DoneEvent ; yes -> skip key swapping.
|
||
move.l d0,a0 ; load swap table handle.
|
||
move.l (a0),a0 ; load swap table pointer.
|
||
move.l evtMessage(a2),d1 ; get event message
|
||
move.b evtMeta(a2),d1 ; get modifier keys.
|
||
and.w #modMask,d1 ; mask off alpha modifier.
|
||
@2
|
||
move.l (a0)+,d0 ; tuple = 0?
|
||
beq.s DoneEvent ; yes -> bail out.
|
||
cmp.w d0,d1 ; tuple = message?
|
||
bne.s @2 ; no -> try next tuple.
|
||
swap d0 ; get KeyScript verb.
|
||
|
||
; Change the current keyboard. Call KeyScript to load the new keyboard
|
||
; and to draw the keyboard icon in the menu bar. Remember to null out
|
||
; the event type and return that no events were available.
|
||
;
|
||
; Beginning with System 7, we only strip the event if it meaningful <12>
|
||
; in the current system - i.e., the KeyScript return code is true.
|
||
|
||
ScriptEvent
|
||
move.w d0,-(sp) ; push script code.
|
||
_KeyScript ; invoke the trap.
|
||
|
||
tst.b smgrKeyScriptResult(a4) ; Did KeyScript do something useful? <12>
|
||
beq.s DoneEvent ; if not, don't strip event <12>
|
||
|
||
move.w #nullEvt,evtNum(a2) ; null event type.
|
||
move.l MinusOne,(sp) ; return no event in d0.
|
||
|
||
; Restore the registers and return to the caller.
|
||
|
||
DoneEvent
|
||
movem.l (sp)+,a0-a4/d0-d2 ; restore the registers.
|
||
rts ; return to the caller.
|
||
endwith ;SMgrRecord ; <12>
|
||
|
||
endproc
|
||
|
||
|
||
;============================================================================= <12>
|
||
; Patch KeyTrans to skip the initial itlk processing if the KCHR pointer
|
||
; passed into KeyTrans is not the same as the one in emKeyCache (i.e., the
|
||
; itlk does not apply to this KCHR).
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export ptchKeyTrans
|
||
|
||
ktFrame record {a6link},decr
|
||
result ds.l 1 ; resulting ascii codes
|
||
kchrTable ds.l 1 ; KCHR table to use
|
||
codeMods ds.w 1 ; virtual key code, modifiers
|
||
deadState ds.l 1 ; dead key state pointer
|
||
return ds.l 1 ; return address
|
||
a6link ds.l 1 ; old link pointer
|
||
ktLocals equ * ; size of locals
|
||
kchrTableNoLink equ kchrTable-return ; kchrTable offset before link
|
||
endr
|
||
|
||
ptchKeyTrans
|
||
; bail if KCHR pointer is not same as in ExpandMem
|
||
with ExpandMemRec,ktFrame ;
|
||
move.l ExpandMem,a1 ;
|
||
move.l emKeyCache(a1),d1 ; Get KCHR pointer in ExpandMem
|
||
cmp.l kchrTableNoLink(sp),d1 ; same as KCHR pointer param?
|
||
bne.s @skipItlk ; if not, skip itlk handling
|
||
BackToTrap oldKeyTrans ; begin with itlk handling
|
||
@skipItlk
|
||
JmpBIND ROMKeyTransAfterItlk ; enter after itlk handling
|
||
endwith ;ExpandMemRec,ktFrame ;
|
||
|
||
endproc
|
||
|
||
|
||
;============================================================================= <12>
|
||
; Patch internal SwapKybd routine to force it to load 'KCHR' resources only
|
||
; from the System file.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export ptchSwapKybd
|
||
|
||
SwapKybdRegs reg a2/a3/d4 ; added d4 <7/25/87med>
|
||
|
||
ptchSwapKybd
|
||
with smgrRecord,scriptRecord,ExpandMemRec
|
||
link a6,#0 ; link the stack.
|
||
movem.l SwapKybdRegs,-(sp) ; save the registers.
|
||
move.l expandMem,a3 ; load expandMemPtr
|
||
move.l emKeyCache(a3),a3 ; get pointer to key cache
|
||
|
||
; Load the KCHR resource from the system file.
|
||
|
||
@LoadKybd
|
||
move.w CurMap,-(sp) ; leave cur resfile refnum on stack <12>
|
||
clr.w -(sp) ; specify system file <12>
|
||
_UseResFile ; <12>
|
||
|
||
sub.l #4,sp ; make room for handle.
|
||
move.l #'KCHR',-(sp) ; push KCHR type.
|
||
GetSMgrCore a0 ; load smgrCore pointer.
|
||
move.w smgrKeyScript(a0),d0 ; get key script code.
|
||
lsl.w #2,d0 ; convert to long offset.
|
||
move.l smgrEntry(a0,d0.w),a0 ; get key script entry.
|
||
move.w scriptBundle.itlbKeys(a0),d4 ; save KCHR id number in d4… <13>
|
||
move.w d4,-(sp) ; and push it <13>
|
||
move.w #-1,RomMapInsert ; look for KCHR in ROM and load.
|
||
_GetResource ; get the KCHR resource.
|
||
move.l (sp)+,a2 ; load handle
|
||
move.l a2,d0 ; handle = nil? <13>
|
||
|
||
; if no KCHR, restore resfile and exit <13>
|
||
bne.s @loadItlk ; no - go load itlk. Otherwise…
|
||
_UseResFile ; restore old resfile (refnum on stack)
|
||
bra.s DoneKybd ; bail, keep old KCHR & itlk.
|
||
@loadItlk
|
||
; if we already have an itlk, dispose of it <13>
|
||
GetSMgrCore a0 ;
|
||
move.l smgrCurITLK(a0),d0 ; have old handle?
|
||
beq.s @noOld ; no -> skip dispose
|
||
clr.l smgrCurITLK(a0) ; clear the handle storage
|
||
move.l d0,a0 ; copy itlk handle
|
||
_DisposHandle ; dispose of the itlk
|
||
@noOld
|
||
; load the itlk resource, detach it, and store its handle <13>
|
||
subq #4,sp ; make room for handle
|
||
move.l #'itlk',-(sp) ; push resource type
|
||
move.w d4,-(sp) ; push resource ID number
|
||
_GetResource ; load the resource
|
||
move.l (sp)+,d0 ; found the itlk resource?
|
||
beq.s @noNew ; no -> skip installation
|
||
|
||
GetSMgrCore a0 ;
|
||
move.l d0,smgrCurITLK(a0) ; save new itlk handle
|
||
move.l d0,-(sp) ; push itlk handle
|
||
_DetachResource ; detach from system file
|
||
@noNew
|
||
; restore previous resource file
|
||
_UseResFile ; restore old resfile (refnum on stack) <12><13>
|
||
JmpBIND ROMSwapKybdLockKCHR ; <12><13>
|
||
|
||
DoneKybd ; <13>
|
||
movem.l (sp)+,SwapKybdRegs ; restore the registers.
|
||
unlk a6 ; unlink the stack.
|
||
rts ; return to the caller.
|
||
endwith ;smgrRecord,scriptRecord,ExpandMemRec
|
||
|
||
endproc
|
||
|
||
|
||
;============================================================================= <16>
|
||
; Come-from after patch on ValidDate to fix bug in Toggledate. <16>
|
||
; ---------------------------------------------------------------------------- <16>
|
||
; <16>
|
||
proc ; <16>
|
||
export ptchValidDate ; <16>
|
||
; <16>
|
||
ptchValidDate ; <16>
|
||
CMPBIND ROMTogDateAfterValDate,(sp) ; coming from ROM ToggleDate? <16>
|
||
bne.s @doROMroutine ; if not, just continue <16>
|
||
lea ptchToggleDate,a0 ; get our patch address <16>
|
||
move.l a0,(sp) ; make ValidDate return to it <16>
|
||
@doROMroutine ; <16>
|
||
JMPBIND ROMValidDate ; continue with routine <16>
|
||
; <16>
|
||
; Copied from ScriptMgrUtilDate.a ; <16>
|
||
ToggleDateRec record {oldA6},decr ; <16>
|
||
resultSize equ 2 ; <16>
|
||
funcResult ds.w 1 ; <16>
|
||
argSize equ *-8 ; <16>
|
||
mySecsPtr ds.l 1 ; <16>
|
||
field ds.w 1 ; <16>
|
||
delta ds.w 1 ; <16>
|
||
ch ds.w 1 ; <16>
|
||
paramsPtr ds.l 1 ; <16>
|
||
selector ds.l 1 ; <16>
|
||
return ds.l 1 ; <16>
|
||
oldA6 ds.l 1 ; <16>
|
||
dateTime0 ds LongDateRec ; <16>
|
||
dateTime1 ds LongDateRec ; <16>
|
||
dateTime2 ds LongDateRec ; <16>
|
||
newDate ds LongDateTime ; <16>
|
||
myTogFlags ds.l 1 ; modified copy of togFlags <16>
|
||
localFrame equ * ; <16>
|
||
endr ; <16>
|
||
; <16>
|
||
ptchToggleDate ; <16>
|
||
; at this point we are near the end of internal xValidDate routine <16>
|
||
move.w (sp)+,d0 ; pop ValidDate result, set cc <16>
|
||
;; rts ; instead of returning… <16>
|
||
; …we leave return addr on stack, check which of the five possible <16>
|
||
; return addresses it is, and dispatch to the new patch (one of 5) <16>
|
||
; that corresponds to the old return address. I first tried to pop <16>
|
||
; the old return address into a register and do the CMPBIND against <16>
|
||
; the register, but the assembler optimizes this to a cmpa.w, which <16>
|
||
; breaks the FixRomAddresses macro. <16>
|
||
lea @1,a0 ; assume first patch <16>
|
||
CMPBIND ROMbltSetNewDate2,(sp) ; but check return for second <16>
|
||
blo.s @xValidDateReturn ; if before, we want first <16>
|
||
lea @2,a0 ; try second <16>
|
||
beq.s @xValidDateReturn ; if equal, we want second <16>
|
||
lea @3,a0 ; now assume third patch <16>
|
||
CMPBIND ROMdbltFinerLoop4,(sp) ; but check return for fourth <16>
|
||
blo.s @xValidDateReturn ; if before, we want third <16>
|
||
lea @4,a0 ; try fourth <16>
|
||
beq.s @xValidDateReturn ; if equal, we want fourth <16>
|
||
lea @5,a0 ; use fifth! <16>
|
||
@xValidDateReturn ; simulate return from xValidDate: <16>
|
||
addq #4,sp ; discard old return address <16>
|
||
tst.w d0 ; reset condition codes <16>
|
||
jmp (a0) ; and jump to correct patch <16>
|
||
; <16>
|
||
@1 blt.s SetNewDate ; <16>
|
||
JMPBIND ROMAfterBltSetNewDate1 ; <16>
|
||
; <16>
|
||
@2 blt.s SetNewDate ; <16>
|
||
JMPBIND ROMAfterBltSetNewDate2 ; <16>
|
||
; <16>
|
||
@3 blt.s SetNewDate ; <16>
|
||
JMPBIND ROMAfterBltSetNewDate3 ; <16>
|
||
; <16>
|
||
@FinerLoop ; <16>
|
||
sub.w #1,(a3) ; drop <16>
|
||
bsr.s xValidDate ; is it ok? <16>
|
||
@4 dblt d5,@FinerLoop ; til done <16>
|
||
blt.s SetNewDate ; yes, exit <16>
|
||
JMPBIND ROMAfterBltSetNewDate4 ; <16>
|
||
; <16>
|
||
@BackwardsLoop ; <16>
|
||
add.w d3,(a2) ; bump <16>
|
||
bsr.s xValidDate ; is it ok? <16>
|
||
@5 dblt d5,@BackwardsLoop ; yes, exit <16>
|
||
blt.s SetNewDate ; with correct date from ValidDate <16>
|
||
JMPBIND ROMAfterBltSetNewDate5 ; <16>
|
||
; <16>
|
||
; Other fragments: <16>
|
||
; <16>
|
||
; For xValidDate, we cannot just jump into ROM, because the xValidDate <16>
|
||
; return addresses will not match the expectations of the above patch. <16>
|
||
; <16>
|
||
; The fragment after the SetNewDate label contains the real fix we are making. <16>
|
||
; <16>
|
||
with ToggleDateRec ; <16>
|
||
xValidDate ; <16>
|
||
clr.w -(sp) ; allocate return <16>
|
||
pea dateTime0(a6) ; pass @datetime0 <16>
|
||
move.l myTogFlags(a6),-(sp) ; pass adjusted togFlags <16>
|
||
pea newDate(a6) ; pass @newDate <16>
|
||
_ValidDate ; call it <16>
|
||
move.w (sp)+,d0 ; pop result <16>
|
||
rts ; <16>
|
||
; <16>
|
||
SetNewDate ; <16>
|
||
lea newDate(a6),a0 ; source <16>
|
||
move.l mySecsPtr(a6),a1 ; dest <16>
|
||
move.w #4-1,d0 ; dbra word cound <fixed!> <16>
|
||
JMPBIND ROMbsrCopyDateLoop ; <16>
|
||
; <16>
|
||
endwith ;ToggleDateRec ; <16>
|
||
endproc ; <16>
|
||
|
||
;============================================================================= <17>
|
||
; Patch out GetFormatOrder entirely to fix trashing of d3. <17>
|
||
; ---------------------------------------------------------------------------- <17>
|
||
|
||
proc
|
||
export ptchFormatOrder
|
||
|
||
FormatOrderFrame record {oldA6},decrement
|
||
resultSize equ 0
|
||
argSize equ *-8
|
||
ordering ds.l 1
|
||
firstFormat ds.w 1
|
||
lastFormat ds.w 1
|
||
filler ds.b 1
|
||
lineRight ds.b 1 ; high byte from pascal <2/10/88med>
|
||
DirProc ds.l 1
|
||
dirParam ds.l 1
|
||
selector ds.l 1
|
||
return ds.l 1
|
||
oldA6 ds.l 1
|
||
localFrame equ *
|
||
endR
|
||
|
||
FormatOrderRegs reg a2-a3/d3-d6 ; Now include d3 <17>
|
||
;____________________________________________________________
|
||
|
||
ptchFormatOrder
|
||
|
||
with FormatOrderFrame
|
||
CheckSelector
|
||
|
||
link a6,#localFrame
|
||
movem.l FormatOrderRegs,-(sp)
|
||
|
||
; consistency check
|
||
|
||
move.l ordering(a6),a2 ; get ordering
|
||
move.w firstFormat(a6),d3 ; get start
|
||
move.w lastFormat(a6),d4 ; get end
|
||
cmp.w d3,d4 ; same?
|
||
|
||
ble.s @Exit ; lastFormat ≤ firstFormat, leave array alone.
|
||
|
||
@FillArray
|
||
; {fill the array with initial values, going in lineDirection order}
|
||
|
||
move.l DirProc(a6),a3 ; get dirProc
|
||
move.l #2,d5 ; set pointer increment
|
||
move.b lineRight(a6),d6 ; right-left?
|
||
beq.s @InvertLoop ; no, continue
|
||
move.w d4,d0 ; get last element
|
||
sub.w d3,d0 ; last-first
|
||
add.w d0,d0 ; for word array
|
||
add.w d0,a2 ; last element
|
||
neg.w d5 ; invert pointer increment
|
||
|
||
@InvertLoop
|
||
clr.b -(sp) ; allocate return
|
||
move.w d3,-(sp) ; pass i
|
||
move.l dirParam(a6),-(sp) ; pass dirParam
|
||
jsr (a3) ; call it
|
||
move.w d3,d1 ; set temp
|
||
cmp.b (sp)+,d6 ; get result: same as lineRight?
|
||
beq.s @1 ; yes, skip
|
||
not.w d1 ; invert
|
||
@1
|
||
move.w d1,(a2) ; set value
|
||
add.w d5,a2 ; increment array pointer
|
||
add.w #1,d3 ; i := i+1
|
||
cmp.w d3,d4 ; same?
|
||
bge.s @InvertLoop ; no, keep looping
|
||
|
||
; {walk through the array, reversing the odd direction clusters (inverted)}
|
||
@WalkArray
|
||
sub.w firstFormat(a6),d4 ; now # elements + 1
|
||
move.l #-1,d5 ; mark as no first backwards element
|
||
clr.w d3 ; i := 0
|
||
move.l ordering(a6),a2 ; get ordering
|
||
move.l a2,a3 ; for increment
|
||
@RevLoop
|
||
tst.w (a3)+ ; get value
|
||
bge.s @BadOrder ; correct order
|
||
tst.w d5 ; have first backwards element?
|
||
bge.s @RevContinue ; yes, continue
|
||
move.w d3,d5 ; mark first backwards element
|
||
bra.s @RevContinue ; continue
|
||
@BadOrder
|
||
tst.w d5 ; have first backwards element?
|
||
blt.s @RevContinue ; no, continue
|
||
JSRBIND ROMReverseCluster ; ReverseCluster(j, i - 1) <17>
|
||
move.l #-1,d5 ; mark no first backwards element.
|
||
@RevContinue
|
||
add.w #1,d3 ; inc
|
||
cmp.w d3,d4 ; at end?
|
||
bge.s @RevLoop ; no, continue
|
||
|
||
tst.w d5 ; got one?
|
||
blt.s @Exit ; no, continue
|
||
JSRBIND ROMReverseCluster ; ReverseCluster(j, limit); <17>
|
||
|
||
@Exit
|
||
; cleanup
|
||
movem.l (sp)+,FormatOrderRegs
|
||
CheckA6
|
||
JMPBIND ROMEndFormatOrder ; <17>
|
||
|
||
endproc
|
||
|
||
;============================================================================= <21>
|
||
; Replace Roman dispatcher with version that handles nil entries in
|
||
; dispatch table.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export ptchRomanScript
|
||
|
||
ptchRomanScript
|
||
with SMgrRecord,ScriptRecord
|
||
move.l 4(sp),d0 ; get selector
|
||
GetSMgrCore a1 ; set up ptr to SMgrRecord <24>
|
||
move.l smgrEntry+(smRoman*4)(a1),a1 ; now set up ptr to Roman ScriptRecord <24>
|
||
cmp.w scriptDispHigh(a1),d0 ; selector past max script sys call? <24>
|
||
bhi BitBucket ; clean up stack and fake the call <6/7/88ldc>
|
||
sub.w scriptDispLow(a1),d0 ; make word offset from table start <24>
|
||
add.w d0,d0 ; make a long offset
|
||
move.l scriptDispTable(a1),a1 ; get table ptr <24>
|
||
move.l 0(a1,d0.w),d0 ; get routine vector from table <21><24>
|
||
beq BitBucket ; if nil, bail <21>
|
||
move.l a0,4(sp) ; replace selector with ScriptRecord ptr <24>
|
||
move.l d0,a0 ; copy vector <21>
|
||
jmp (a0) ; now jump to it
|
||
endwith
|
||
|
||
BitBucket
|
||
JMPBIND ROMBitBucket ; <21>
|
||
|
||
endproc
|
||
|
||
|
||
;============================================================================= <23>
|
||
; Patch beginning of Roman FindWord so that it handles custom break tables
|
||
; without checking the itl2 resource.
|
||
; This also replaces the FindWord part of the PACK 6 patch above.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export ptchRomanFindWord
|
||
|
||
fwRecord record {a6link},decr
|
||
fwArgs equ *-8 ; size of arguments.
|
||
pointer ds.l 1 ; Text pointer.
|
||
length ds.w 1 ; Text length.
|
||
offset ds.w 1 ; First offset.
|
||
left ds.w 1 ; LeftSide flag.
|
||
option ds.l 1 ; Optional tuple table.
|
||
table ds.l 1 ; array of offsets.
|
||
scriptRecPtr ds.l 1 ; ScriptRecord pointer <24>
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old a6 register.
|
||
fwLocals equ * ; size of local variables.
|
||
endr
|
||
|
||
ptchRomanFindWord
|
||
with fwRecord
|
||
link a6,#fwLocals ; link the stack.
|
||
movem.l d3-d7/a2-a4,-(sp) ; save the registers.
|
||
|
||
; Load the registers with the basic parameters.
|
||
|
||
move.l table(a6),a2 ; get offset array.
|
||
move.l pointer(a6),a3 ; get text pointer.
|
||
move.w offset(a6),d4 ; get first offset.
|
||
move.w length(a6),d7 ; get text length.
|
||
|
||
; Find the word that has the offset in it and return its limits. First,
|
||
; determine the starting offset based on the text offset, length, and
|
||
; leftSide flag.
|
||
|
||
tst.b left(a6) ; if leftSide is false,
|
||
bne.s @1 ; subtract one from
|
||
sub.w #1,d4 ; the offset.
|
||
@1 move.l #0,d3 ; left is zero.
|
||
move.l d3,d5 ; right is zero.
|
||
tst.w d4 ; if offset < 0,
|
||
blt storeOffsets ; return to caller.
|
||
move.l d7,d3 ; left is length.
|
||
move.l d7,d5 ; right is length.
|
||
cmp.w d7,d4 ; if offset >= length,
|
||
bge storeOffsets ; return to caller.
|
||
|
||
; Next, prime all of the registers for the search in both directions. We
|
||
; determine here which god-forsaken table the user wants.
|
||
|
||
FoundOffset
|
||
MOVE.L option(A6),D0 ; check for 0 <23>
|
||
BEQ.S @UseDefault ; if default word select table, go get it <23>
|
||
CMP.L #-1,D0 ; check for -1 <23>
|
||
BEQ.S @UseDefault ; if default word wrap table, go get it <23>
|
||
MOVE.L D0,A1 ; have pointer to custom table <23>
|
||
BRA.S @LoadOffsets ; continue with it <23>
|
||
|
||
@UseDefault
|
||
;; clr.w d2 ; sysFlag=0; script code in hi word
|
||
;; swap d2 ; put where they belong
|
||
move.l scriptRecPtr(a6),a0 ; ScriptRecord ptr (maybe nonRoman) <24>
|
||
moveq #0,d2 ; sysFlag=0 in hi word <24>
|
||
move.b ScriptRecord.scriptID(a0),d2 ; script code in low word <24>
|
||
|
||
clr.l -(sp) ; space for returned handle
|
||
move.w #2,-(sp) ; select itl2
|
||
|
||
move.l d2,-(sp) ; two arguments: script code, sysFlag=0
|
||
_IUGetScriptItl ; may trash a0,a1,d0-d2
|
||
JMPBIND ROMfwAfterGetIntl ; <23>
|
||
|
||
@LoadOffsets
|
||
JMPBIND ROMfwLoadOffsets ; <23>
|
||
storeOffsets
|
||
JMPBIND ROMfwstoreOffsets ; <23>
|
||
|
||
endwith ;fwRecord
|
||
endproc
|
||
|
||
|
||
; =============================================================================
|
||
; END RESIDENT CODE
|
||
; =============================================================================
|
||
|
||
CutBackPt proc Export
|
||
|
||
; EntryTable YourTrap,YourTrapID
|
||
EntryTable 0 ; <=== Last table entry
|
||
|
||
EndProc
|
||
|
||
; =============================================================================
|
||
; BEGIN INSTALL CODE
|
||
; =============================================================================
|
||
|
||
proc
|
||
export SMgrInstallPatch
|
||
|
||
SMgrInstallPatch ; init routine
|
||
import CutBackPt,CodeEntry
|
||
|
||
; The FixRomAddresses macro has to be located after the last bind macro in the
|
||
; code, but has to be executed before any of them. So we put it at the end and
|
||
; BSR to it.
|
||
|
||
bsr DoFixRomAddresses
|
||
|
||
with SMgrRecord
|
||
movem.l d3/a2-a4,-(sp)
|
||
|
||
; =============================================================================
|
||
; Begin init code that is not excluded for A/UX (always installed)
|
||
; Initially, everything was here, since this patch file was not loaded for A/UX. <8>
|
||
; Now, if this patch is loaded for A/UX (doScriptMgrForAUX is TRUE), we need to
|
||
; create a block that is excluded for A/UX and move OS-specific installs there.
|
||
; =============================================================================
|
||
|
||
;________________________________________________________________ <a4.3><e3.7>
|
||
; Patch to Pack6 to fix Script Manager routines
|
||
;
|
||
InstToolTp ptchPack6,$1ED
|
||
|
||
;____________________________________________________________________________
|
||
; Bump Script Manager version number for IntlForce bug fix (SysVers < $700) <a5.3><e4.2>
|
||
; Set Script Manager version (SysVers >= $700) <a5.7><e4.4>
|
||
; redo using new symbol smgrVersPTCHRom <a5.9><e4.5>
|
||
|
||
GetSMgrCore a0
|
||
move.w #smgrVersPriv,smgrVersion(a0)
|
||
|
||
;____________________________________________________________________________
|
||
; Initialize additional Script Manager vectors <a5.4><e4.3>
|
||
; Add CallInterface <a5.9><e4.5>
|
||
; Moved NewSwapIcon setup below <4>
|
||
|
||
; GetSMgrCore a0 ; already set up <23>
|
||
LEABIND ROMSMgrCalcRect,a1
|
||
move.l a1,sVectSMgrCalcRect(a0)
|
||
LEABIND ROMSMgrInitFonts,a1
|
||
move.l a1,sVectSMgrInitFonts(a0)
|
||
LEABIND ROMCallInterface,a1 ; <a5.9><e4.5>
|
||
move.l a1,sVectCallInterface(a0) ; <a5.9><e4.5>
|
||
|
||
;____________________________________________________________________________
|
||
; Use NewSwapIcon <4>
|
||
|
||
import NewSwapIcon ; <a6.2><e4.7>
|
||
|
||
; GetSMgrCore a0 ; already set up
|
||
lea NewSwapIcon,a1 ; <a6.2><e4.7><a6.7><e5.4>
|
||
move.l a1,sVectSwapIcon(a0) ; <a6.2><e4.7>
|
||
|
||
;____________________________________________________________________________ <a7.8><e5.4>
|
||
; Install patches for Script Manager routines InitDateCache, String2Date
|
||
|
||
smInitDateCacheOff equ -16 ; DispTable offset for InitDateCache
|
||
smString2DateOff equ -20 ; DispTable offset for String2Date
|
||
smValidDateOff equ -56 ; DispTable offset for ValidDate <16>
|
||
smFormatOrderOff equ -08 ; DispTable offset for GetFormatOrder <17>
|
||
|
||
GetSMgrCore a1
|
||
move.l smgrDispTable(a1),a1
|
||
|
||
lea NewInitDateCache,a0
|
||
move.l a0,smInitDateCacheOff(a1)
|
||
lea NewString2Date,a0
|
||
move.l a0,smString2DateOff(a1)
|
||
|
||
lea ptchValidDate,a0 ; <16>
|
||
move.l a0,smValidDateOff(a1) ; <16>
|
||
|
||
lea ptchFormatOrder,a0 ; <17>
|
||
move.l a0,smFormatOrderOff(a1) ; <17>
|
||
|
||
;____________________________________________________________________________ <5>
|
||
; Installing tail patch to InitMenus to fix up smgrRect.
|
||
|
||
import ptchInitMenus
|
||
|
||
move.w #$130,d0 ; InitMenus trap address
|
||
_GetTrapAddress ; returns in a0
|
||
move.l IntlSpec,a1
|
||
move.l a0,sVectInitMenus(a1)
|
||
InstToolTp ptchInitMenus,$130
|
||
|
||
;____________________________________________________________________________ <12>
|
||
; Installing KeyTrans patch for itlk handling.
|
||
|
||
import ptchKeyTrans
|
||
|
||
PatchToolJump oldKeyTrans,$1C3 ; set addr for BackToTrap
|
||
InstToolTp ptchKeyTrans,$1C3
|
||
|
||
;____________________________________________________________________________ <12>
|
||
; Patch SwapKybd to force loading of KCHRs from System file.
|
||
|
||
import ptchSwapKybd
|
||
|
||
GetSMgrCore a0
|
||
lea ptchSwapKybd,a1
|
||
move.l a1,sVectSwapKybd(a0)
|
||
|
||
;____________________________________________________________________________ <21>
|
||
; Install updated Roman dispatcher.
|
||
|
||
import ptchRomanScript
|
||
|
||
with ScriptRecord
|
||
;; GetSMgrCore a0 ; already have this from above
|
||
move.l smgrEntry+(smRoman*4)(a0),a0 ; get ptr to Roman ScriptRecord <21>
|
||
lea ptchRomanScript,a1 ; get new dispatcher address <21>
|
||
move.l a1,scriptTrap(a0) ; install it <21>
|
||
endwith ;ScriptRecord
|
||
|
||
;____________________________________________________________________________ <23>
|
||
; Install patches to Roman FindWord
|
||
|
||
import ptchRomanFindWord
|
||
|
||
with ScriptRecord
|
||
GetSMgrCore a0 ; <23>
|
||
move.l smgrEntry+(smRoman*4)(a0),a0 ; get ptr to Roman ScriptRecord <23>
|
||
move.l scriptDispTable(a0),a1 ; get ptr to Roman disp table <23>
|
||
move.w scriptDispLow(a0),d0 ; get low selector handled by table <23>
|
||
add.w d0,d0 ; make long offset <23>
|
||
sub.w d0,a1 ; adjust to point where entry for selector <23>
|
||
; 0 would go if it were in the table <23>
|
||
lea ptchRomanFindWord,a0 ; <23>
|
||
move.l a0,2*smFindWord(a1) ; <23>
|
||
|
||
endwith ;ScriptRecord
|
||
|
||
; =============================================================================
|
||
; Begin init code that is excluded for A/UX (only installed if not A/UX).
|
||
; =============================================================================
|
||
|
||
; Runtime check to determine whether we are running A/UX. <8>
|
||
; If so, skip this section of patch install code.
|
||
|
||
move.w HwCfgFlags,d0 ; check ‘em the compulsive way
|
||
btst.l #hwCbAUX,d0 ; is it A/UX time?
|
||
bne EndMacOnlySection ; if so skip the mac-only patches
|
||
|
||
;____________________________________________________________________________ <a8.0><e5.5><8>
|
||
; Install Script Manager tail patch to _GetIndADB, fixes the way SwapKybd
|
||
; clears dead key state in ADB keyboard driver data structure
|
||
|
||
PatchOSJump oldGetIndADB,$78 ; set addr for BackToTrap
|
||
InstOSTp ptchGetIndADB,$78 ; …and then install patch
|
||
|
||
;____________________________________________________________________________ <10>
|
||
; Installing GetOSEvent patch for keyboard switching via key combos.
|
||
; Don't install if A/UX running. <12>
|
||
|
||
import ptchGetOSEvent
|
||
|
||
InstOSTp ptchGetOSEvent,$31
|
||
;____________________________________________________________________________
|
||
|
||
EndMacOnlySection
|
||
|
||
; =============================================================================
|
||
; end init code
|
||
; =============================================================================
|
||
|
||
@exit
|
||
movem.l (sp)+,d3/a2-a4
|
||
lea CutBackPt,a0 ; <=== Keep these two lines…
|
||
rts ; <=== in any case
|
||
@errExit
|
||
move.w #dsSysErr,d0 ; load generic error
|
||
_SysError ; system error!
|
||
bra.s @exit
|
||
|
||
endwith
|
||
|
||
DoFixRomAddresses
|
||
FixRomAddresses ; new macro
|
||
rts
|
||
|
||
endproc
|
||
|
||
END
|