mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-29 20:49:19 +00:00
3553 lines
137 KiB
Plaintext
3553 lines
137 KiB
Plaintext
;
|
||
; File: InternationalPACK.a
|
||
;
|
||
; Contains: Date, time, and sorting routines for language-independent programs. These routines
|
||
; help maintain international parameter blocks as resources of type 'itl_' where the
|
||
; last character is a digit (0 through 4). The date and time routines translate the
|
||
; long integer "seconds" count into strings whose formats are specified in the
|
||
; parameter blocks. The magnitude string comparison routine for Roman languages was
|
||
; designed and implemented by Dr. J. Coonen. Later modifications allow the parameter
|
||
; blocks to change the sorting algorithm for non-Roman languages. For 7.0, the type
|
||
; select utilities (for keyboard navigation) are added here.
|
||
;
|
||
; Written by: AJH Andy Hertzfeld
|
||
; JTC Jerome Coonen
|
||
; MED Mark Davis
|
||
; JDT Joe Ternasky
|
||
; DRS daan strebe
|
||
; LDC Lee Collins
|
||
; PKE Peter Edberg
|
||
; ngk Nick Kledzik
|
||
; …and a cast of thousands
|
||
;
|
||
; Copyright: © 1983-1992 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <46> 10/16/92 PKE Move itl1 extension offsets into Packages.a. Include Packages.a
|
||
; instead of PackMacs.a.
|
||
; <45> 6/2/92 PKE #1028868 <smb>: Really fix problem of crashing when resource is
|
||
; not loaded: the problem was not ResLoad being false, but GetIntl
|
||
; not handling low-memory failure to load resource when GetIntl
|
||
; was called internally (with ResLoad always TRUE). Now GetIntl
|
||
; always returns NIL handle if a resource fails to load. Also
|
||
; revert to making direct calls to GetIntl pay attention to
|
||
; ResLoad (as in <43>), but handle ResLoad as a byte.
|
||
; <44> 6/1/92 DTY #1028868 <FM>: The previous change only turns on ResLoad (if
|
||
; it’s false) for calls to GetIntl made internally. This isn’t
|
||
; enough. There are some cases where an external call to GetIntl
|
||
; will fail and crash because ResLoad is false, and it’s not
|
||
; turned on before getting an ‘itl ’ resource. Get rid of the
|
||
; check to see if the call to GetIntl is made from an internal
|
||
; call, and always turn on ResLoad before getting an ‘itl ’
|
||
; resource.
|
||
; <43> 5/14/92 PKE #1028868,<bbm>: Fix crash in internal call to GetIntl (e.g. from
|
||
; MagString) if ResLoad false and itl resource purged. Fix
|
||
; GetItlTable to handle ResLoad false by returning nil handle.
|
||
; <42> 4/22/92 JSM Get rid of useNewItlCache (which was never used) and
|
||
; FixNonRomanTypeSelect (which was only used once) conditionals.
|
||
; <41> 4/22/92 PKE #1026767: (no reviewer before check-in: it is late at night,
|
||
; nobody is around, I am going out of town early tomorrow morning,
|
||
; and I have to have this in for the a7 build) Stop caching
|
||
; handles to itl2/itl4 resources, since itl2/itl4 resources can be
|
||
; changed under us; use cached IDs instead. Also, in GetIntl move
|
||
; DoneIntl and FailIntl above UnlockIt call to make sure we always
|
||
; unlock (since we may have gotten locked before making an
|
||
; internal call to GetIntl); this is a continuation of fix <40>.
|
||
; <40> 4/17/92 PKE #1027387,<DTY>: Fix <35> below - removing the check for
|
||
; emItlDirectGetIntl at the end of GetIntl caused the PACK to
|
||
; become unlocked prematurely (this is a bug in 7up too). However,
|
||
; the emItlDirectGetIntl scheme was brain-dead anyway. Instead, do
|
||
; locking/unlocking a better way: bracket all internal calls to
|
||
; other externally-callable PACK 6 routines with an
|
||
; increment/decrement of emItlDontUnlockYet (renamed from
|
||
; emItlDirectGetIntl), and have UnlockIt not unlock if
|
||
; emItlDontUnlockYet is non-zero. Also, add missing calls to
|
||
; LockIt before LoadResource in MagString, DatePString, and
|
||
; TimePString, and add missing call to UnlockIt in QuickExit from
|
||
; MagString (this last missing UnlockIt was responsible for PACK 6
|
||
; remaining locked in many cases, which was what 7up was trying to
|
||
; fix).
|
||
; <39> 4/15/92 PKE #1023781,<dty>: Fix <36> below - need to use it0 or itl1 handle,
|
||
; as appropriate; itl2 has nothing to do with dates or times!!
|
||
; Also test if intlParam handle is unloaded; if so, load it.
|
||
; <38> 4/3/92 PKE #1015311,<smb>: Fix <37> below - If you change IntlMaxID, you
|
||
; also need to add a 0 entry in CacheOffset.
|
||
; <37> 4/2/92 DTY #1015311,<SLS>: Change IntlMaxID to 5 now that we have 'itl5'
|
||
; resources.
|
||
; <36> 4/1/92 DTY #1025710,<pvh>: IUDatePString and IUTimePString will crash if
|
||
; intlParam is nil. Add checks for nil to these two routines. If
|
||
; intlParam is nil, get the default 'itl2' resource.
|
||
; <35> 1/7/92 DTY Checking emItlDirectGetIntl before calling UnlockIt causes the
|
||
; PACK to not get unlocked sometimes. Take out this check. (This
|
||
; was done as a patch by 7 Up.)
|
||
; <34> 10/16/91 PKE For Cube-E (and Bruges): Increment PACK 6 version number.
|
||
; <33> 10/8/91 PKE For Cube-E (and Bruges): Fix IUScriptOrder and IUTextOrder (by
|
||
; fixing internal routine intScriptCodeToSort) to ignore FontForce
|
||
; flag, and to sort non-enabled scripts last. Clean up some more
|
||
; conditionals.
|
||
; <32> 9/20/91 PKE Remove CubeE conditionals, since the new plan (according to
|
||
; Darin) is that everything for Cube-E goes in without
|
||
; conditionals. While I'm at it, remove some ">=$700" conditionals
|
||
; and pre-7.0-only code.
|
||
; <31> 9/15/91 PKE smb,#85675: IUSetIntl was causing crashes. It assumed that
|
||
; _HomeResFile returned the actual refNum (not 0) for the system
|
||
; file, so it failed to remove an ‘INTL’ resource before adding
|
||
; another one with the same ID. Also, it was setting the
|
||
; resChanged attribute with _SetResAttrs instead of calling
|
||
; ChangedResource.
|
||
; <30> 3/1/91 ngk pke,#77804: use secondary difference when differentiating
|
||
; between better possibilities for type selecting.
|
||
; <29> 2/21/91 PKE gbm,#82260: TypeSelect does not work if system script is
|
||
; non-Roman but Roman name is typed.
|
||
; <28> 2/21/91 ngk dho: fix bug introduced by change <27>
|
||
; <27> 2/11/91 ngk dho, #80563: Fix TypeSelect wrap around bug.
|
||
; <26> 1/10/91 PKE (fjs) Fix bugs in GetIntl that can result in a call to
|
||
; UseResFile with an invalid refNum, and a call to HLock with an
|
||
; invalid handle. Make MagPString and MagIdPString load handle
|
||
; passed to them if necessary.
|
||
; <25> 12/19/90 PKE (VL) Have app caches ignore SetScript changes to itl2 or itl4
|
||
; ID, since IUClearCache eliminates the need for this. This
|
||
; isolates each application’s cache from the effects of other
|
||
; apps. Add private ClearCacheSys routine. Protect against bad
|
||
; selectors.
|
||
; <24> 12/14/90 PKE (DC) Use itl1 extension, if present, to make IUDateString,
|
||
; IUDatePString, and IULDateString produce correct abbreviated
|
||
; date and handle calendars with >7 days or >12 months (So that
|
||
; localizers can fix bug #49924 correctly). Force IUGetIntl to
|
||
; load sys cache from System file, and make sys cache relatively
|
||
; immune to a SetScript change to itl2 or itl4 ID.
|
||
; <23> 10/21/90 gbm (with dba) Fix an assembly warning
|
||
; <22> 9/14/90 BG Removed <13>. 040s are behaving more reliably now.
|
||
; <21> 9/10/90 PKE Merge common code from TextOrder and TypeSelectCompare into
|
||
; GetScriptItl for code sharing; change it to take its ScriptCode
|
||
; and sysFlag parameters on the stack; make it accessible through
|
||
; dispatcher for internal use.
|
||
; <20> 9/6/90 PKE Change TypeSelectCompare to use only primary sorting order, and
|
||
; to use correct way of getting itl2 handles.
|
||
; <19> 8/29/90 PKE Let IUGetItlTable provide whiteSpaceList too.
|
||
; <18> 8/26/90 PKE NEEDED FOR SIXPACK: Fixed a register trashing bug introduced in
|
||
; <16> in the internal routine GetLArray. If IULDateString or
|
||
; IULTimeString were passed an intlParam value of 0, this bug
|
||
; would cause GetIntl to look for an invalid resource type;
|
||
; GetIntl wouldn’t find it, and these procedures would bail,
|
||
; returning null strings.
|
||
; <17> 8/24/90 PKE Let IUGetItlTable provide unTokenTable too.
|
||
; <16> 8/1/90 PKE NEEDED FOR SIXPACK: Change IUGetIntl to do better error
|
||
; reporting. Change all Pack6 routines that make internal GetIntl
|
||
; calls to actually check if there was an error (what a concept).
|
||
; This fixes crashes that occurred in low-memory situations,
|
||
; including BRC #70045 (string compare routines were crashing in
|
||
; two-byte systems).
|
||
; <15> 7/30/90 gbm axe branch to next instruction
|
||
; <14> 7/25/90 PKE Modify so that application itl cache is part of new
|
||
; application-specific script globals. Remove code in ClearCache
|
||
; and GetIntl that creates the cache; app-specific script globals
|
||
; are now allocated by InitScriptApp.
|
||
; <13> 7/17/90 BG Added EclipseNOPs for flakey 040s.
|
||
; <12> 7/16/90 PKE Use new names for fields in ExpandMemRec: emItlCache2Ptr is now
|
||
; emItlSysCachePtr, emItlAppCachePtr is now emItlAppCacheHndl.
|
||
; Renamed Cache2Rec to NewItlCacheRec.
|
||
; <11> 7/5/90 PKE Fixed bugs in new cache scheme (see <10>): register use bug was
|
||
; wiping out the script code used for finding the right cache
|
||
; entry, so we didn’t find a match and defaulted to system script;
|
||
; save app cache handle (!); better handling of BlockMove errs,
|
||
; etc. Changed IUClearCache to fit more nicely into this scheme.
|
||
; Reworked itl2 handle fetching for IUTextOrder and IUTextOrderSys
|
||
; to use new caching via GetScriptItl entry point; ensures that
|
||
; IUTextOrderSys uses system sorting and not app sorting.
|
||
; <10> 7/2/90 PKE Redo GetIntl’s itl2/itl4 caching to use emItlAppCachePtr so
|
||
; Process Mgr can swap cache for each application. Put in
|
||
; framework for private IUTextOrderSys routine - a new entry point
|
||
; for IUTextOrder that uses the system’s cached itl2/itl4 handles
|
||
; instead of the current application’s cached handles.
|
||
; <9> 5/8/90 PKE Changed script and language sorting routines to use new
|
||
; emScriptMap and emLangMap tables, which are set up from ‘itlm’
|
||
; resource. Use new emItlCache2 for improved caching of ‘itl2’ and
|
||
; ‘itl4’ resource handles. Changed ClearCache to work with new
|
||
; cache.
|
||
; <8> 5/3/90 ngk Fixed bug in TypeSelectNewKey of script not being set in tsr.
|
||
; <7> 5/2/90 ngk Added private TypeSelect (a.k.a. keyboard navigation) routines.
|
||
; <6> 4/10/90 PKE Conditionalized <2.3> and <3> so object compares work against
|
||
; official 6.0.x sources. Used smgrSys7Extensions instead of
|
||
; SysVers where appropriate.
|
||
; <5> 3/21/90 PKE Added private IUMagWPString interface.
|
||
; <4> 3/2/90 PKE Use new name IUNSortFrame for the extended IUSortFrame in System
|
||
; 7.0; use new name nItl4Rec for the extended Itl4Rec (used in
|
||
; GetItlTable). Updated version number. Extended langScriptTable
|
||
; to accomodate all current language codes (need to put this in a
|
||
; resource soon!!). Fixed up header and tabs.
|
||
; <3> 1/4/90 dba get rid of assembly warnings by using ALIGN statement and using
|
||
; low-memory for an empty string
|
||
; <2> 12/19/89 EMT (with dba) Cleared itl2Handle in MagWString, which is an
|
||
; undocumented call used by Microsoft.
|
||
; <1> 12/18/89 CCH Adding for the first time into BBS.
|
||
; (BBS versions above, EASE versions below)
|
||
; <2.3> 11/17/89 dba got rid of checks for 64K ROMs
|
||
; <2.2> 10/31/89 PKE Lock package before GetResource calls in new routines
|
||
; (IUTextOrder, IUGetItlTable)!! Also, in LockIt and UnlockIt,
|
||
; get handle directly from AppPacks instead of using
|
||
; RecoverHandle (takes care of problems when Pack6 is called from
|
||
; MultiFinder).
|
||
; <2.1> 10/5/89 PKE Clear ignChar flag in FetchChar; fixes bug (BRC #54591) with
|
||
; sorting of ignorable characters.
|
||
; <2.0> 9/22/89 PKE Added GetItlTable routine. Implemented the remaining special
|
||
; negative ScriptCodes and LangCode values for ScriptOrder,
|
||
; LangOrder, and TextOrder.
|
||
; <1.9> 9/18/89 PKE Rearrange parameters for IUTextOrder; use different lang code
|
||
; to signal mapping to default lang for script.
|
||
; <1.8> 9/15/89 PKE Add 7.0 functions ClearCache, MagPString, MagIdPString,
|
||
; ScriptOrder, LangOrder, and TextOrder.
|
||
; <1.7> 8/26/89 PKE Delete load 'nEqu.d'.
|
||
; <1.6> 3/10/89 PKE Add sorting support for 'ß and extended Mac character set (incl.
|
||
; fi,fl). Should revise to get project & vernier info from the same
|
||
; table at the same time.
|
||
; <1.5> 2/22/89 PKE Change GetIntl to determine the script itself if the
|
||
; smgrIntlForce flag is true, instead of calling IntlScript to do
|
||
; this. This makes GetIntl independent of the a5 world when
|
||
; smgrIntlForce is true, which is most of the time. Need to
|
||
; include ScriptEqu.priv for this.
|
||
; <1.4> 2/21/89 PKE Fix up includes: always include 'inc.sum.a'.
|
||
; <1.3> 2/14/89 PKE Updated to use MPW 3.0 final ScriptEqu.a equate names
|
||
; <1.2> 1/17/89 CCH Changed LongMonth to LongMonth1 and LongDay to LongDay1.
|
||
; <1.1> 1/16/89 CCH Merged 6.0.3 final sources into 7.0.
|
||
; <1.0> 11/16/88 CCH Added to EASE.
|
||
; (pre-EASE history below)
|
||
; 7/11/88 ldc fixed IUSetIntl stack frame values
|
||
; 6/27/88 ldc fixed IUEqualString (MagIDString) to only return 1 in place of
|
||
; -1
|
||
; 6/16/88 ldc moved NeedUnlock and DirectGetIntl to expandMem
|
||
; 6/13/88 ldc allow caller of GetLArray to select itlx
|
||
; 6/1/88 med DatePString common entry must go to LongerDate, NOT DoLongForm
|
||
;
|
||
; 3/21/88 med Do not use cache if expandMem version is not correct
|
||
; 2/5/88 med Use Cache Offsets table to avoid some calculation.
|
||
; 2/5/88 med Moved cache storage into expandmem
|
||
; 1/25/88 med Gave SetIntl a frame, to prevent spurious errors
|
||
; 1/19/88 med Skip cache if id = 0,1; since MacWrite breaks it
|
||
; 1/19/88 med We know the script manager is always there, so don't check
|
||
; 1/13/88 med Added MakeDatLString, MakeTimLString; restructured entries
|
||
; slightly
|
||
; 1/13/88 drs Fixed equates and stack frame. Produces identical code.
|
||
; 1/7/88 med Changed label 'NoCache' to 'GotNoCache': must be new name
|
||
; conflict
|
||
; 1/4/88 drs Fixed lock/unlock of Pack6
|
||
; 1/4/88 med Fixed TestMetric Offset for new dispatch
|
||
; 12/22/87 med Fixed two nasty bugs with ligatures: oeœ = œoe, and oer < and >
|
||
; œdipus
|
||
; 11/16/87 med GetIntl now takes verbs 0,1,2,4
|
||
; 5/15/87 drs Created a cache for the handle loaded from GetIntl so that
|
||
; subsequent calls could used LoadResource. Optimizations
|
||
; throughout the sorting routine. Fixed bug in FetchChar which
|
||
; updated the character pointer wrongly. Global reorganization of
|
||
; entire sort routine. Don't start initialization until strings
|
||
; are proven to be unequal and quick exit if they are equal.
|
||
;
|
||
; Changes for performance enhancements above
|
||
;
|
||
; <S132> 3/24/87 med Fixed the BMI in TestMetric, and the CLR.L in GetTheIntl to
|
||
; unlock properly.
|
||
; 3/2/87 med Used _HPurge instead of direct call. Cleared d1 in GetTheIntl.
|
||
; This routine calls GetIntl, which unlocks the package if d1 is
|
||
; set, so for safety, it should be cleared.
|
||
; 1/19/87 jdt Replaced resource type constants with literals.
|
||
; 1/5/87 jdt Minor changes to GetIntl routine for clarity. Replaced script
|
||
; manager core macro with check for _ScriptUtil trap implemented.
|
||
; Changed dispatch to use _HGetState when new ROMs are present.
|
||
; Changed d2 to d7 in MakeTimeString and removed saving of d2 in
|
||
; AppendNumCom. Added call to ExitHook in MagComString exit code.
|
||
; Removed CCR save and restore in TwoMoreChars.
|
||
; 11/25/86 jdt Changed the equate files just one more time.
|
||
; 11/18/86 MED Fixed register save/restore with MakeTimPString; Modified movem
|
||
; calls generally by using REG
|
||
; 11/13/86 MED Redid equates
|
||
; 9/18/86 JDT Modified GetIntl routine to handle switch-launch. We cannot
|
||
; assume that the script manager has been installed.
|
||
; 9/11/86 MED Save and restore d2 over appendNum call for safety.
|
||
; 9/3/86 JDT Modified GetIntl to use the ScriptUtil trap.
|
||
; 8/30/86 JDT GetIntl now uses the Script Manager to find the ITLx resources.
|
||
; 8/28/86 JDT Removed support for LocalRtn in string comparison. A4 is now a
|
||
; handle to the international parameter block that contains the
|
||
; new sorting hooks.
|
||
; 8/26/86 JDT Moved localization hooks from ITL1 to new ITL2 resource.
|
||
; 8/25/86 JDT Modified the GetIntl routine to look for ITLx resources.
|
||
; 7/29/86 MED Changed AppendNum (and AppendLongNum) to use NumToString in the
|
||
; 'approved' manner.
|
||
;
|
||
; Changes for Script Manager support above
|
||
;
|
||
; 6/10/86 MED Added: hooks in string comparison, ignore flags.
|
||
; 5/20/86 JDT Put MagWString back in, depending on the Microsoft flag.
|
||
; 5/9/86 JDT Removed Kanji routines from Pack6. They now reside in their own
|
||
; package, Pack8.
|
||
; 5/7/86 JDT Bracked all Kanji routines by calls to saveLock and checkLock,
|
||
; to preserve the (un)locked status of the package.
|
||
; 3/26/86 MED Changed inKanji to be zero if CharMode > 1
|
||
; 3/22/86 MED Added separate entry for Microsoft (WeakMag)
|
||
; 3/21/86 KWK Changed version number to use equate
|
||
; 3/10/86 MED Cleaned up extended routines
|
||
; 3/3/86 MED added:
|
||
; short form formats: added 3,4,5 for myd,dym,ydm.
|
||
; timeCycle: 128 for 0:00 AM/PM instead of 12:00 AM/PM.
|
||
; longDateFormat: first+second*4+third*16+fourth*64, where 0 =
|
||
; day, 1 = weekday, 2 = month, 3 = year.
|
||
; suppressDay: now a bitmap to suppress 0,1,2,3.
|
||
; old forms all should work as before.
|
||
; 2/19/86 MED now interleaves katakana, hiragana, kana
|
||
; 2/17/86 MED Added routines to access KIS vectors (text manipulation)
|
||
; 12/16/85 MED Added basic support for double-byte characters
|
||
;
|
||
; Changes for Kanji Interface System support above
|
||
;
|
||
; 12/30/85 JTC Fix reg save bug in SetIntl. <30Dec85 JTC>
|
||
; 12/18/85 JTC Last nanosecond changes for Mac+: Fix old JTC bug with string
|
||
; comparisons trashing D3. Have the package preserve its
|
||
; lockedness across the call. <18Dec85 JTC>
|
||
; 2/4/84 JTC fixed oe ligature problem
|
||
; 1/11/84 AJH believe it or not, there was a 12 AM bug, too...
|
||
; 1/6/84 AJH fixed short year bug
|
||
; 1/5/84 AJH made it use medium mode for day, too
|
||
; 1/4/84 AJH fixed 12 PM bug (was giving 00 PM)
|
||
; 1/3/84 AJH alternate entry points added for Random Wigginton
|
||
; 12/22/83 AJH GetIntl was staying locked...
|
||
; 11/17/83 JTC Added MagIdString compare.
|
||
; 11/12/83 AJH Fixed bug in "medium long" option
|
||
; 11/10/83 AJH Added "medium long" date option
|
||
; 11/8/83 AJH Made "GetIntl" preserve lock state
|
||
; 11/7/83 AJH Integrated Jerome's magnitude compare
|
||
; 11/3/83 AJH Added "wantSeconds" parameter to time formatting
|
||
;___________________________________________________________________________________________________
|
||
; To Do:
|
||
; • Always call LockIt at entry instead of waiting for first time that might move memory
|
||
;___________________________________________________________________________________________________
|
||
|
||
load 'StandardEqu.d'
|
||
include 'Packages.a' ; <46>
|
||
include 'ScriptPriv.a'
|
||
include 'IntlUtilsPriv.a' ; <7>
|
||
string asis
|
||
|
||
EmptyString equ Lo3Bytes ; handy empty string <3>
|
||
|
||
proc
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; Local Variable Equates.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; International Parameter Block Definitions
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
IntlMaxID equ 5 ; <37> maximum resource ID number.
|
||
|
||
; Parameter Block 0 Offsets
|
||
|
||
IntlDecPoint EQU 0 ;decimal point character
|
||
IntlThouSep EQU 1 ;thousands separator character
|
||
IntlListSep EQU 2 ;list separator character
|
||
|
||
IntlCurSym EQU 3 ;3 byte currency symbol
|
||
IntlCurFmt EQU 6 ;currency format flags
|
||
|
||
IntlDateOrder EQU 7 ;order for short form dates
|
||
IntlSDLZFlags EQU 8 ;leading zero flags for dates
|
||
IntlDSep EQU 9 ;seperator character for dates
|
||
|
||
IntlTimeMode EQU 10 ;12 or 24 hour time mode flag
|
||
IntlTLZFlags EQU 11 ;time leading zero flags
|
||
IntlAMSuffix EQU 12 ;suffix string for AM times
|
||
IntlPMSuffix EQU 16 ;suffix string for PM times
|
||
IntlTSep EQU 20 ;time separator character
|
||
Intl24Suffix EQU 21 ;suffix for 24 hr mode
|
||
|
||
IntlMetric EQU 29 ;boolean for English/Metric
|
||
|
||
; Parameter Block 1 Offsets.
|
||
; Get rid of unused ones. <24>
|
||
|
||
IntlSunday EQU 0 ;string for Sunday
|
||
|
||
IntlJanuary EQU 112 ;string for January
|
||
|
||
IntlDaySupress EQU 304 ;boolean for supressing day-of-week
|
||
IntlLongOrder EQU 305 ;boolean for selecting order
|
||
IntlLDayLZFlag EQU 306 ;boolean for day# leading zeros
|
||
IntlMonLen EQU 307 ;month length for medium date
|
||
|
||
IntlStr1 EQU 308 ;long date prefix string
|
||
IntlStr2 EQU 312 ;long date day seperator string
|
||
IntlStr3 EQU 316 ;long date month seperator string
|
||
IntlStr4 EQU 320 ;long date date seperator string
|
||
IntlStr5 EQU 324 ;long date year suffix string
|
||
|
||
; New offsets for itl1 extension. Moved to Packages.a. <24><46>
|
||
|
||
; Note: Each list above begins with a count of items,
|
||
; followed by that many variable-length pstrings.
|
||
|
||
; Since these routines are accessed as a "package", the first code is
|
||
; a dispatcher which strips the selection parameter and cases out on it.
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; Package dispatch
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
maxSelector equ 52 ; <25>
|
||
|
||
IntlUnit
|
||
bra.s RealStart ; skip over header
|
||
|
||
; Standard resource header.
|
||
|
||
dc.w 0 ; flags word.
|
||
dc.b 'PACK' ; resource type is PACK.
|
||
dc.w 6 ; resource ID number is 6.
|
||
dc.w $701 ; version number. <4><34>
|
||
|
||
; The real code starts here. We dispatch
|
||
; to the appropriate routine based on the selector parameter.
|
||
|
||
; Note!: the dispatch changed around August 87, but is not marked <1/4/88med>
|
||
|
||
RealStart
|
||
|
||
with ExpandMemRec
|
||
move.l expandMem, a0 ; get expand mem <6/16/88ldc>
|
||
clr.w emItlNeedUnlock(a0) ; clear both emItlNeedUnlock & emItlDontUnlockYet <40>
|
||
endwith ;ExpandMemRec
|
||
|
||
move.l (sp)+,a0 ; save return address.
|
||
move.w (sp)+,d0 ; pop the selector.
|
||
move.l a0,-(sp) ; restore return address.
|
||
|
||
cmp.w #maxSelector,d0 ; <25>
|
||
bhi.s @bail ; bail if selector high or negative <25>
|
||
|
||
lea IntlTable,a0 ; get jump table address.
|
||
add.w 0(a0,d0.w),a0 ; compute dispatch address.
|
||
jmp (a0) ; jump into routine.
|
||
|
||
@bail ; <25>
|
||
rts ; <25>
|
||
|
||
|
||
; import/export needed for separate type select procedures ; <7>
|
||
import TypeSelectClear, TypeSelectNewKey, TypeSelectFindItem, TypeSelectCompare ; <7>
|
||
export ScriptOrder, MagWPString, LockIt, UnLockIt, intScriptCodeToReal, GetScriptItl ; <7><20>
|
||
|
||
; Package dispatch table.
|
||
IntlTable
|
||
dc.w MakeDateString - IntlTable ; 00
|
||
dc.w MakeTimeString - IntlTable ; 02
|
||
dc.w TestMetric - IntlTable ; 04
|
||
dc.w GetIntl - IntlTable ; 06
|
||
dc.w SetIntl - IntlTable ; 08
|
||
dc.w MagString - IntlTable ; 10 and CompString
|
||
dc.w MagIdString - IntlTable ; 12 and EqualString
|
||
dc.w MakeDatPString - IntlTable ; 14
|
||
dc.w MakeTimPString - IntlTable ; 16
|
||
dc.w MagWString - IntlTable ; 18 (private interface)
|
||
dc.w MakeLDatString - IntlTable ; 20 (Script Mgr 2.0)
|
||
dc.w MakeLTimString - IntlTable ; 22 (Script Mgr 2.0)
|
||
; System 7 extensions:
|
||
dc.w ClearCache - IntlTable ; 24 <1.8>
|
||
dc.w MagPString - IntlTable ; 26 (and CompPString) <1.8>
|
||
dc.w MagIdPString - IntlTable ; 28 (and EqualPString) <1.8>
|
||
dc.w ScriptOrder - IntlTable ; 30 <1.8>
|
||
dc.w LangOrder - IntlTable ; 32 <1.8>
|
||
dc.w TextOrder - IntlTable ; 34 (and StringOrder) <1.8>
|
||
dc.w GetItlTable - IntlTable ; 36 <2.0>
|
||
dc.w MagWPString - IntlTable ; 38 (private interface) <5>
|
||
dc.w TypeSelectClear - IntlTable ; 40 (private interface) <7>
|
||
dc.w TypeSelectNewKey - IntlTable ; 42 (private interface) <7>
|
||
dc.w TypeSelectFindItem - IntlTable ; 44 (private interface) <7>
|
||
dc.w TypeSelectCompare - IntlTable ; 46 (private interface) <7>
|
||
dc.w TextOrderSys - IntlTable ; 48 (private interface) <10>
|
||
dc.w GetScriptItl - IntlTable ; 50 (private interface) <21>
|
||
dc.w ClearCacheSys - IntlTable ; 52 (private interface) <25>
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; Utility Routines
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; UnlockIt is a short utility that unlocks the package.
|
||
; Simplified <1/4/88med>
|
||
|
||
UnlockIt
|
||
with ExpandMemRec
|
||
move.l ExpandMem,a0 ; ExpandMem ptr
|
||
tst.b emItlDontUnlockYet(a0) ; are we really leaving PACK 6? <40>
|
||
bne.s @0 ; if not, don't even try to unlock <40>
|
||
tst.b emItlNeedUnlock(a0) ; did we lock it? <40>
|
||
beq.s @0 ; if not, don't unlock it
|
||
endWith ;ExpandMemRec
|
||
|
||
move.l AppPacks+(6*4),a0 ; get handle directly <2.2>
|
||
|
||
_HUnlock ; unlock the package.
|
||
@0
|
||
rts ; return to the caller.
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; LockIt is a short utility that locks the package if we locked it
|
||
; Simplified <1/4/88med>
|
||
|
||
LockIt
|
||
move.l AppPacks+(6*4),a0 ; get handle directly <2.2>
|
||
_HGetState ; get lock state new way.
|
||
tst.b d0 ; was it already locked (negative)? (d0) <1/4/88med>
|
||
blt.s @LockReturn ; yes, done
|
||
_HLock ; lock the package down.
|
||
|
||
with ExpandMemRec
|
||
move.l ExpandMem, a0 ; ExpandMem ptr <6/16/88ldc>
|
||
st emItlNeedUnlock(a0) ; remember that we locked it <6/16/88ldc><40>
|
||
endwith ;ExpandMemRec
|
||
|
||
@LockReturn
|
||
rts
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; The following are frames, equates and utilities for date and time conversions.
|
||
; They share a fair amount of common code, so the entries are a bit odd.
|
||
|
||
DateTimeFrame record {oldA61},decrement
|
||
argFrameT1 EQU *
|
||
return1 ds.l 1
|
||
argFrame1 EQU argFrameT1-*
|
||
theTime ds.l 1 ; LongInt ; 14
|
||
longFlag ds.w 1 ; BOOLEAN ; 12
|
||
result ds.l 1 ; str255 ; 8
|
||
intlParam ds.l 1 ; Handle ; 4
|
||
oldA61 ds.l 1 ; ; 0
|
||
|
||
garbage ds.b 2 ;-2
|
||
longdate ds LongDateRec
|
||
MPByte ds.w 1 ;-18
|
||
TempStr ds.b 10 ;-28
|
||
LocSiz EQU *
|
||
ENDR
|
||
|
||
WITH DateTimeFrame
|
||
DateTimeRegs reg D3-D7/A2-A4 ; common entry/exit regs <18Nov86MED>
|
||
DayInteger equ longDate.dayOfWeek
|
||
SecondInteger equ longDate.second
|
||
MinuteInteger equ longDate.minute
|
||
HourInteger equ longDate.hour
|
||
DateInteger equ longDate.day
|
||
MonthInteger equ longDate.month
|
||
YearInteger equ longDate.year
|
||
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; The following is a set of common utility routines for decimal conversion,
|
||
; string manipulation, etc.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; AppendLongNum appends a four digit number to the current string
|
||
; Note: we use this unusual method of adding zeros so that StringToNum adds the proper form.
|
||
|
||
AppendLongNum
|
||
st d1 ; leading zeros
|
||
add.w #10000,d0 ; for zeros
|
||
bra.s AppendNumCom ; go to it
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; AppendNum -- given an integer in D0, and a leading zero flag in D1, append
|
||
; its 2 low order digits to the string pointed to by A0. D0 and D1 are
|
||
; clobbered.
|
||
|
||
AppendNum
|
||
tst.b d1 ; leading zeros?
|
||
beq.s AppendNumCom ; no
|
||
add.w #100,d0 ; for zeros
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
AppendNumCom
|
||
ext.l d0 ; longize (always positive)
|
||
movem.l a0/d1,-(sp) ; save the registers.
|
||
lea TempStr(a6),a0 ; space for string
|
||
_NumToString ; put string in apStr(a6)
|
||
movem.l (sp)+,a0/d1 ; restore the registers.
|
||
lea TempStr(a6),a1 ; get string in local frame
|
||
tst.b d1 ; want leading zeros on two digit num?
|
||
beq.s @1 ; no, just add string
|
||
move.b (a1)+,d0 ; get length
|
||
subq.w #1,d0 ; subtract
|
||
move.b d0,(a1) ; set length one byte up
|
||
@1
|
||
bsr.s AppendString ; append a1 to a0
|
||
rts
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; AppendChar appends the character in D0 to the string pointed to by A0.
|
||
; It filters out NULLs (ASCII 0).
|
||
|
||
AppendChar
|
||
TST.B D0 ;is it null?
|
||
BEQ.S @1 ;if so, ignore it
|
||
|
||
MOVEQ #0,D1
|
||
MOVE.B (A0),D1 ;get current length of string
|
||
ADDQ.B #1,(A0) ;bump it by one
|
||
|
||
MOVE.B D0,1(A0,D1) ;store away the new character
|
||
@1
|
||
RTS ;return to our caller
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; AppendString appends the string pointed to by A1 to the string pointed
|
||
; to by A0.
|
||
; If a string can't be found, the NoAppend entry point is used. <24>
|
||
|
||
AppendString
|
||
MOVEQ #0,D2 ;zero high part
|
||
MOVE.B (A1)+,D2 ;get the length
|
||
AppStrLoop
|
||
MOVE.B (A1)+,D0 ;get next character
|
||
BSR.S AppendChar ;append it
|
||
SUBQ #1,D2 ;more to do?
|
||
BNE.S AppStrLoop ;loop till done
|
||
NoAppend
|
||
RTS ;all done
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; Append4 appends the four character string pointed at by A1 to the string
|
||
; pointed to by A3.
|
||
|
||
Append4
|
||
MOVE.L A3,A0 ;get result string ptr
|
||
MOVEQ #4,D2 ;4 characters to process
|
||
BRA.S AppStrLoop ;use common code
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; The following is a set of common utility routines for setting up the date time.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; GetTheDate is a utility subroutine shared by the date and time routines
|
||
; The time longInt is passed in the stack frame.
|
||
;
|
||
; It makes a3 point to the result string, sets it to null, gets itl0 handle in a4,
|
||
; and now sets Z if itl0 couldn't be loaded. <16>
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
GetTheDate
|
||
BSR.S GetTArray
|
||
MOVEQ #0,D0 ;we need INTL 0
|
||
BRA GetTheINTL ;get resource handle in A4
|
||
; and set Z if we fail <16>
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
GetTArray
|
||
MOVE.L theTime(A6),D0 ;get the time (common) <1/13/88med>
|
||
LEA YearInteger(A6),A0 ;point to word array
|
||
_Secs2Date ;convert to tractable integers
|
||
|
||
; copied from below (6.0.6 fix) <16>
|
||
MOVE.L result(A6),A3 ;get the result string
|
||
CLR.B (A3) ;start it out with length 0
|
||
RTS
|
||
|
||
; added new routine for long times <1/13/88med>
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
GetLArray
|
||
; a4 = intlParam. if nil, we load a new one.
|
||
; d0.w = itlx type from caller (0 or 1).
|
||
; Now sets Z if we can't load the itl resource. <16>
|
||
|
||
; rearrange so Z is set if we can't load handle (6.0.6 fix) <16>
|
||
move.w d0,-(sp) ;save d0 <18>
|
||
move.l theTime(A6),-(sp) ; @LongDateTime
|
||
pea longDate(A6) ;point to word array
|
||
_LongSecs2Date ;convert to tractable integers
|
||
|
||
MOVE.L result(A6),A3 ;get the result string
|
||
CLR.B (A3) ;start it out with length 0
|
||
|
||
move.w (sp)+,d0 ; restore d0 <18>
|
||
move.l a4,d1 ; nil handle?
|
||
beq GetTheIntl ; if so, get resource handle in A4 (else set Z)
|
||
rts ; else we have a good handle
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE IULDateString(theTime: Comp; longFlag:BOOLEAN; VAR result: str255; intlParam: Handle);
|
||
; MakeDatPString is an alternate for of MakeDateString added for Randy. It has
|
||
; an additional parameter, which is the INTL parameter block handle, which it
|
||
; uses instead of getting it from resources.
|
||
;<1/13/88med> Added
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
MakeLDatString
|
||
MOVE.L (SP)+,D0 ;get return address
|
||
MOVE.L (SP)+,A0 ;get parameter handle
|
||
MOVE.L D0,-(SP) ;replace return address
|
||
LINK A6,#LocSiz ;get local space <18Dec85 JTC>
|
||
MOVEM.L DateTimeRegs,-(SP) ;save work regs <18Nov86MED>
|
||
MOVE.L A0,A4 ;keep pBlock in A4
|
||
|
||
;<6/11/88ldc> need itl1 or 0 depending on long or short form
|
||
; seems like longFlag isn't really a flag, but an enumerated type
|
||
; check on this.
|
||
|
||
moveq #1, d0 ; assume itl1
|
||
tst.b longFlag(A6) ; long date form?
|
||
bne.s @elseGLA ; else just call GetLArray
|
||
moveq #0, d0 ; itl0
|
||
@elseGLA
|
||
BSR.s GetLArray ; included theTime <1/13/88med>
|
||
beq DoneMDS ; bail if we couldn't load itl0/1 <16>
|
||
bra.s DateCommon ; jump to common date routine <1/13/88med>
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE MakeDatePString(theTime: LongInt; longFlag:BOOLEAN; VAR result: str255; intlParam: Handle);
|
||
; MakeDatPString is an alternate for of MakeDateString added for Randy. It has
|
||
; an additional parameter, which is the INTL parameter block handle, which it
|
||
; uses instead of getting it from resources.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
MakeDatPString
|
||
MOVE.L (SP)+,D0 ;get return address
|
||
MOVE.L (SP)+,A0 ;get parameter handle
|
||
MOVE.L D0,-(SP) ;replace return address
|
||
|
||
LINK A6,#LocSiz ;get local space <18Dec85 JTC>
|
||
MOVEM.L DateTimeRegs,-(SP) ;save work regs <18Nov86MED>
|
||
MOVE.L A0,d0 ; Make sure there is a valid intlParam <36>
|
||
bz.s @getDefaultItl ; Handle was nil. Go get the default 'itl' resource. <36><39>
|
||
move.l d0,a4 ; <36>
|
||
tst.l (a4) ; is it loaded <39>
|
||
bne.s @gotValidHandle ; if so, done <39>
|
||
bsr LockIt ; lock ourselves down <40>
|
||
move.l a4,-(sp) ; <39>
|
||
_LoadResource ; else load it <39>
|
||
bra.s @gotValidHandle ; <36>
|
||
|
||
@getDefaultItl ; <36><39>
|
||
moveq #0,d0 ; assume 'itl0' resource <36><39>
|
||
TST.B longFlag(A6) ; long or short date? <39>
|
||
beq.s @gotWhichItl ; if short, have correct 'which' param <39>
|
||
moveq #1,d0 ; set 'itl1' resource <39>
|
||
@gotWhichItl ; <39>
|
||
bsr GetTheIntl ; <36>
|
||
beq DoneMDS ; bail if we couldn't load default itl <39>
|
||
@gotValidHandle ; <36>
|
||
BSR.s GetTArray ; included theTime <1/13/88med>
|
||
|
||
; common entry must go to LongerDate, NOT DoLongForm <6/1/88med>
|
||
DateCommon
|
||
TST.B longFlag(A6) ; long form? (1,2) <6/1/88med>
|
||
BEQ.S ShorterDate ; no (0) <6/1/88med>
|
||
BRA LongerDate ; long form, have parameter
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; table for short date order
|
||
|
||
OrderTable
|
||
dc.w 2,6,4,5,0,$8007 ;month, day, year
|
||
dc.w 4,5,2,6,0,$8007 ;day, month, year
|
||
dc.w 0,$8007,2,6,4,5 ;year, month, day
|
||
dc.w 2,6,0,$8007,4,5 ;month, year, day
|
||
dc.w 4,5,0,$8007,2,6 ;day, year, month
|
||
dc.w 0,$8007,4,5,2,6 ;year, day, month
|
||
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE MakeDateString(theTime: LongInt; longFlag:BOOLEAN; VAR result: str255);
|
||
;
|
||
; MakeDateString produces a result string from the input parameter based
|
||
; on the current settings in the international resource block. It provides
|
||
; both a long and short form of the date.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
MakeDateString
|
||
LINK A6,#LocSiz ;get space for our locals <18Dec85 JTC>
|
||
MOVEM.L DateTimeRegs,-(SP) ;save work registers
|
||
|
||
BSR GetTheDate ;get the date/time integers
|
||
beq DoneMDS ; bail if we couldn't load itl0 <16>
|
||
|
||
;;DateCommon ; moved higher <6/1/88med>
|
||
|
||
TST.B longFlag(A6) ;long or short?
|
||
BNE.S DoLongForm ;if long, go do it
|
||
|
||
; the caller is requesting a short-form date so inspect the parameters in the
|
||
; resource block and build a string for her
|
||
|
||
ShorterDate
|
||
MOVEQ #0,D0 ;clear out high part of D0
|
||
MOVE.L (A4),A0 ;get pBlock ptr
|
||
MOVE.B IntlDateOrder(A0),D0 ;get order indicator
|
||
MULU #12,D0 ;multiply by 12 for index
|
||
|
||
MOVEQ #2,D3 ;three fields to handle
|
||
LEA OrderTable(D0),A2 ;point to the order table entry
|
||
|
||
; here is the loop where we process one field at a time. The order is
|
||
; determined by the 4 byte/entry table pointed at by A2
|
||
|
||
DateLoop
|
||
MOVEQ #0,D0 ;clear out high part
|
||
MOVE.W (A2)+,D0 ;get date array index
|
||
MOVE.W (A2)+,D1 ;get flag bit index
|
||
|
||
MOVE.L (A4),A0 ;get pBlock ptr
|
||
BTST D1,IntlSDLZFlags(A0) ;test the appropriate flag bit
|
||
SNE D1 ;record the boolean
|
||
|
||
MOVE.W YearInteger(A6,D0),D0 ;get the value to append
|
||
MOVE.L A3,A0 ;get the string ptr
|
||
|
||
TST.W D1 ;is it the year command?
|
||
BPL.S @1 ;if not, skip
|
||
TST.B D1 ;long form enabled?
|
||
BNE.S LongYear1
|
||
|
||
DIVU #100,D0 ;compute year mod 100
|
||
SWAP D0 ;remainder in D0
|
||
@1
|
||
BSR AppendNum ;append it
|
||
TestLast
|
||
TST D3 ;is it the last one?
|
||
BEQ.S SkipSep ;the last one doesn't have a separator
|
||
|
||
; append the separator character
|
||
|
||
MOVE.L (A4),A0 ;get pBlock pointer
|
||
MOVE.B IntlDSep(A0),D0 ;get the separator character
|
||
MOVE.L A3,A0 ;point A0 at the result string
|
||
BSR AppendChar ;append the character in D0
|
||
|
||
; loop till we've processed all three fields
|
||
|
||
SkipSep
|
||
DBRA D3,DateLoop ;loop until finished
|
||
|
||
; all done so clean up the stack and go home
|
||
|
||
DoneMDS
|
||
BSR UnlockIt ;unlock the package
|
||
MOVEM.L (SP)+,DateTimeRegs ;restore registers <18Nov86MED>
|
||
UNLK A6 ;deallocate stck frame
|
||
MOVE.L (SP)+,A0 ;get the return address
|
||
ADD #10,SP ;strip parameters
|
||
JMP (A0) ;return to caller
|
||
|
||
; handle the case of the long year (all four digits)
|
||
|
||
LongYear1
|
||
BSR AppendLongNum
|
||
BRA.S TestLast
|
||
|
||
; handle the long form of the date. We must get the INTL 1 resource to
|
||
; get all those strings
|
||
|
||
DoLongForm
|
||
MOVEQ #1,D0 ;get INTL 1
|
||
BSR GetTheINTL ;get the resource
|
||
beq DoneMDS ; bail if we couldn't load itl0 <16>
|
||
|
||
LongerDate
|
||
MOVE.L (A4),A2 ; point to record with A2
|
||
|
||
; generalize the old formats
|
||
|
||
move.b IntlLongOrder(A2),d5 ; get the order byte
|
||
bne.s @1 ; zero, get old format?
|
||
move.b #1+0*4+2*16+3*64,d5 ; weekday,day,month,year
|
||
bra.s @2 ; continue
|
||
@1
|
||
cmp.b #$FF,d5 ; 255, get old format?
|
||
bne.s @2 ; continue
|
||
move.b #1+2*4+0*16+3*64,d5 ; weekday,month,day,year
|
||
@2
|
||
moveq #0,d6 ; longize
|
||
move.b IntlDaySupress(A2),d6 ; get suppression byte
|
||
cmp.b #$FF,d6 ; old style?
|
||
bne.s @3 ; no, skip
|
||
moveq #2,d6 ; suppress day
|
||
@3
|
||
move.w #IntlStr1,d7 ; get offset
|
||
lea 0(a2,d7),a1 ; point at first prefix
|
||
move.l a3,a0 ; point at string
|
||
bsr Append4 ; and stick it on
|
||
|
||
LongDateLoop
|
||
addq.w #4,d7 ; point to next separator
|
||
move.b d5,d0 ; get part number
|
||
and.w #3,d0 ; out of the composite
|
||
lsr.b #2,d5 ; and remove it
|
||
btst.l d0,d6 ; suppress element?
|
||
bne.s @1 ; yes, skip
|
||
add.w d0,d0 ; make word offset
|
||
lea LongDispatch,a1 ; get dispatch
|
||
add.w 0(a1,d0.w),a1 ; add offset
|
||
jsr (a1) ; call it
|
||
lea 0(a2,d7),a1 ; pass separator
|
||
bsr Append4 ; and stick it on
|
||
@1
|
||
cmp.w #IntlStr5,d7 ; at end yet?
|
||
blo.s LongDateLoop ; and loop til done
|
||
BRA.S DoneMDS ; all done!
|
||
|
||
LongDispatch
|
||
dc.w LongDay1-LongDispatch ; day
|
||
dc.w LongWeekDay-LongDispatch ; weekday
|
||
dc.w LongMonth1-LongDispatch ; month
|
||
dc.w LongYear2-LongDispatch ; year
|
||
|
||
LongDay1
|
||
MOVE.W DateInteger(A6),D0 ;get day of month
|
||
MOVE.B IntlLDayLZFlag(A2),D1 ;get leading zero supress flag
|
||
bra AppendNum ;append it and return from there
|
||
|
||
LongWeekDay
|
||
MOVE.W DayInteger(A6),D0 ; get the day of week
|
||
; support for 7.0 itl1 extension <24>
|
||
cmp.w #itl1ExtFlag,localRtn(a2) ; extended itl1?
|
||
beq.s @doExt ; if so, handle differently
|
||
cmp.w #7,d0 ; out of range or negative?
|
||
bhi.s NoAppend ; if so, bail
|
||
|
||
@doOld
|
||
SUBQ #1,D0 ; make it zero based [0..6]
|
||
ASL #4,D0 ; multiply by 16
|
||
LEA IntlSunday(A2,D0),A1 ; get string ptr
|
||
|
||
CMP.B #abbrevDate,longFlag(A6) ; is it abbreviated?
|
||
BEQ AbbrevString ; if so, go truncate it <24>
|
||
bra AppendString ; otherwise, append name and return
|
||
|
||
; support for 7.0 itl1 extension <24>
|
||
@doExt
|
||
cmp.b #abbrevDate,longFlag(A6) ; is it abbreviated?
|
||
beq.s @doExtAbbrev ; if so, deal with it.
|
||
cmp.w #7,d0 ; in range?
|
||
bls.s @doOld ; if so, use old code
|
||
|
||
; here we need extra day name
|
||
subq.w #7,d0 ; extra day number
|
||
move.l #itl1XDayOffset,d2 ; offset to extra days list
|
||
bsr GetListString ; get pointer to name in a1;
|
||
bge.s NoAppend ; if no extra day name, bail
|
||
; here we are pointing to the correct pstring
|
||
bra AppendString ; append name and return
|
||
|
||
@doExtAbbrev
|
||
; here we need abbrev day name
|
||
move.l #itl1AbDayOffset,d2 ; offset to abbrev days list
|
||
bsr.s GetListString ; get pointer to abbrev in a1;
|
||
bge.s @doOld ; if no abbrev, go truncate
|
||
; here we are pointing to the correct pstring
|
||
bra AppendString ; append name and return
|
||
|
||
LongMonth1
|
||
MOVE.W MonthInteger(A6),D0 ; get the month
|
||
; support for 7.0 itl1 extension <24>
|
||
cmp.w #itl1ExtFlag,localRtn(a2) ; extended itl1?
|
||
beq.s @doExt ; if so, handle differently
|
||
cmp.w #12,d0 ; out of range or negative?
|
||
bhi.s NoAppend ; if so, bail
|
||
|
||
@doOld
|
||
SUBQ #1,D0 ; make it zero based [0..11]
|
||
ASL #4,D0 ; multiply by 16
|
||
LEA IntlJanuary(A2,D0),A1 ; get string ptr
|
||
|
||
CMP.B #abbrevDate,longFlag(A6) ; is it abbreviated?
|
||
BEQ.S AbbrevString ; if so, go truncate it
|
||
bra AppendString ; otherwise, append name and return
|
||
|
||
; support for 7.0 itl1 extension <24>
|
||
@doExt
|
||
cmp.b #abbrevDate,longFlag(A6) ; is it abbreviated?
|
||
beq.s @doExtAbbrev ; if so, deal with it.
|
||
cmp.w #12,d0 ; in range?
|
||
bls.s @doOld ; if so, use old code
|
||
|
||
; here we need extra month name
|
||
sub.w #12,d0 ; extra month number
|
||
move.l #itl1XMonOffset,d2 ; offset to extra months list
|
||
bsr.s GetListString ; get pointer to name in a1;
|
||
bge.s NoAppend ; if no extra month name, bail
|
||
; here we are pointing to the correct pstring
|
||
bra AppendString ; append name and return
|
||
|
||
@doExtAbbrev
|
||
; here we need abbrev month name
|
||
move.l #itl1AbMonOffset,d2 ; offset to abbrev months list
|
||
bsr.s GetListString ; get pointer to abbrev in a1;
|
||
bge.s @doOld ; if no abbrev, go truncate
|
||
; here we are pointing to the correct pstring
|
||
bra AppendString ; append name and return
|
||
|
||
LongYear2
|
||
MOVE.W YearInteger(A6),D0 ;get the year
|
||
bra AppendLongNum ;append it and return from there
|
||
|
||
AbbrevString
|
||
ADDQ #1,A1 ;bump past length
|
||
MOVEQ #0,D2 ;clear high part
|
||
MOVE.B IntlMonLen(A2),D2 ;get month length
|
||
BRA AppStrLoop ;append it, return to caller
|
||
|
||
|
||
;------------------------------------------------------------------------------- <24>
|
||
; GetListString
|
||
;
|
||
; Local routine for code saving. Gets a string specified by index in d0 from
|
||
; itl1 table whose offset is in d2.l.
|
||
;
|
||
; input:
|
||
; string index [1..n] in d0
|
||
; table offset in d2
|
||
; itl1 pointer in a2
|
||
; output:
|
||
; Caller should use bge to branch if failure.
|
||
; If no failure, string pointer is in a1
|
||
; effects:
|
||
; Does not change a0 (current date string pointer)
|
||
;-------------------------------------------------------------------------------
|
||
|
||
GetListString
|
||
move.l 0(a2,d2.w),d2 ; get offset to list
|
||
beq.s @fail ; if none, bail (with nZvc)
|
||
lea 0(a2,d2.l),a1 ; make pointer to list
|
||
cmp.w (a1)+,d0 ; is our string# in the list?
|
||
bgt.s @fail ; if not, bail
|
||
subq.w #1,d0 ; set up for dbra
|
||
moveq #0,d2 ; for longizing
|
||
bra.s @endLoop
|
||
@loop
|
||
move.b (a1)+,d2 ; this pstring length
|
||
add.w d2,a1 ; skip, point to next pstring
|
||
@endLoop
|
||
dbra d0,@loop
|
||
moveq #-1,d0 ; set cond codes to Nzvc
|
||
@fail
|
||
rts
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE IULTimeString(theTime: Comp; wantSeconds: BOOLEAN; VAR result: str255; intlParam: Handle);
|
||
;
|
||
; MakeTimPString is an alternate entry point for Randy. It takes the pBlock
|
||
; handle as an additional parameter instead of getting it from resources
|
||
;<1/13/88med> Added
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
MakeLTimString
|
||
MOVE.L (SP)+,D0 ;get return address
|
||
MOVE.L (SP)+,A0 ;get pBlock handle
|
||
MOVE.L D0,-(SP) ;replace return address
|
||
|
||
LINK A6,#LocSiz ;get space for our locals <18Dec85 JTC>
|
||
MOVEM.L DateTimeRegs,-(SP) ;save work registers <18Nov86MED>
|
||
MOVE.L A0,A4 ;keep pBLock handle in A4
|
||
|
||
;<6/11/88ldc> change GetLArray so caller specifies which itlx
|
||
MOVEQ #0,D0 ;want itl0
|
||
BSR GetLArray ; included theTime <1/13/88med>
|
||
beq DoneMDS ; bail if we couldn't load itl0 <16>
|
||
BRA.s MTimeCommon ;use common code for the rest
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE MakeTimeString(theTime: LongInt; wantSeconds: BOOLEAN; VAR result: str255; intlParam: Handle);
|
||
;
|
||
; MakeTimPString is an alternate entry point for Randy. It takes the pBlock
|
||
; handle as an additional parameter instead of getting it from resources
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
MakeTimPString
|
||
MOVE.L (SP)+,D0 ;get return address
|
||
MOVE.L (SP)+,A0 ;get pBlock handle
|
||
MOVE.L D0,-(SP) ;replace return address
|
||
|
||
LINK A6,#LocSiz ;get space for our locals <18Dec85 JTC>
|
||
MOVEM.L DateTimeRegs,-(SP) ;save work registers <18Nov86MED>
|
||
MOVE.L A0,d0 ; Make sure there is a valid intlParam <36>
|
||
bz.s @getDefaultItl0 ; Handle was nil. Go get the default 'itl0' resource. <36><39>
|
||
move.l d0,a4 ; <36>
|
||
tst.l (a4) ; is it loaded <39>
|
||
bne.s @gotValidHandle ; if so, done <39>
|
||
bsr LockIt ; lock ourselves down <40>
|
||
move.l a4,-(sp) ; <39>
|
||
_LoadResource ; else load it <39>
|
||
bra.s @gotValidHandle ; <36>
|
||
|
||
@getDefaultItl0 ; <36><39>
|
||
moveq #0,d0 ; Get default 'itl0' resource if handle was nil. <36><39>
|
||
bsr GetTheIntl ; <36>
|
||
beq DoneMDS ; bail if we couldn't load default itl0 <39>
|
||
@gotValidHandle ; <36>
|
||
BSR GetTArray ;included theTime <1/13/88med>
|
||
BRA.s MTimeCommon ;use common code for the rest
|
||
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE MakeTimeString(theTime: LongInt; wantSeconds: BOOLEAN; VAR result: str255);
|
||
;
|
||
; MakeTimeString produces a result string from the input parameter based
|
||
; on the current settings in the international resource block.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
MakeTimeString
|
||
LINK A6,#LocSiz ;get space for our locals <18Dec85 JTC>
|
||
MOVEM.L DateTimeRegs,-(SP) ;save work registers <18Nov86MED>
|
||
|
||
BSR GetTheDate ;get the date/time integers
|
||
beq DoneMDS ; bail if we couldn't load itl0 <16>
|
||
|
||
; pre-process the hour integer to reflect a 12 or 24 hour time system as
|
||
; indicated in the parameter block
|
||
|
||
MTimeCommon
|
||
LEA HourInteger(A6),A2 ;point at the hour number
|
||
MOVE.W (A2),D7 ;remember it
|
||
SUB #12,D7 ;subtract 12
|
||
|
||
MOVE.L (A4),A0 ;get pointer to pBlock
|
||
MOVE.B IntlTLZFlags(A0),D4 ;get time leading zero flags
|
||
|
||
TST.B IntlTimeMode(A0) ;12 or 24 hr cycle (or special12)?
|
||
BEQ.S @1 ;skip if 24
|
||
bmi.s @11 ; normal 12 hour
|
||
tst.b d7 ; special 12 hour: is it AM?
|
||
bmi.s @1 ; yes, skip
|
||
bra.s @0 ; no, adjust for PM
|
||
|
||
@11
|
||
TST (A2) ;12 AM?
|
||
BNE.S @2 ;if not, skip
|
||
|
||
MOVE.W #12,(A2) ;12 AM, not 00 AM
|
||
BRA.S @1 ;skip the rest...
|
||
@2
|
||
TST.B D7 ;is it AM?
|
||
BMI.S @1 ;if negative, skip
|
||
BNE.S @0 ;if non-zero, go update it
|
||
|
||
MOVEQ #12,d7 ;12 PM is not 00 PM
|
||
@0
|
||
MOVE.W d7,(A2) ;update hour
|
||
|
||
; OK, set up the loop count and dive in
|
||
|
||
@1
|
||
MOVEQ #2,D3 ;3 times through the loop
|
||
|
||
TST.B longFlag(A6) ;want seconds?
|
||
BNE.S TimeLoop ;if so, we're cool
|
||
SUBQ #1,D3 ;skip the seconds
|
||
|
||
TimeLoop
|
||
MOVE.W (A2)+,D0 ;get the integer
|
||
MOVE.L A3,A0 ;point to the string
|
||
TST.B D4 ;test the current LZ flag
|
||
SMI D1 ;set D1 accordingly
|
||
BSR AppendNum ;append the number
|
||
ADD.B D4,D4 ;shift flags for next time
|
||
|
||
; now print the separator if necessary
|
||
|
||
TST D3 ;the last one?
|
||
BEQ.S @1 ;if so, skip the separator
|
||
|
||
MOVE.L (A4),A1 ;get pointer to pBlock
|
||
MOVE.B IntlTSep(A1),D0 ;get the date separator
|
||
BSR AppendChar ;append it
|
||
|
||
; loop until finished
|
||
|
||
@1
|
||
DBRA D3,TimeLoop ;loop 3 times total
|
||
|
||
; now append a trailing string based on the current hour (AM or PM, etc.)
|
||
|
||
MOVE.L (A4),A1 ;point to pBlock
|
||
TST.B IntlTimeMode(A1) ;12 or 24 hr mode?
|
||
BEQ.S Mode24 ;branch if 24 hr
|
||
|
||
LEA IntlAMSuffix(A1),A1 ;point to suffix string
|
||
ModeCommon
|
||
TST.B D7 ;AM or PM?
|
||
BMI.S AppendTrailer ;if AM, skip
|
||
ADDQ #4,A1 ;bump to PM
|
||
AppendTrailer
|
||
BSR Append4 ;append the suffix
|
||
|
||
; OK, the time string is built so restore the registers and return to the caller
|
||
|
||
BRA DoneMDS ;use common exit code
|
||
|
||
; use 24-hr trailer
|
||
|
||
Mode24
|
||
LEA Intl24Suffix(A1),A1 ;point to suffix string
|
||
BRA.S ModeCommon ;use common code
|
||
|
||
ENDWITH ;DateTimeFrame
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; FUNCTION TestMetric: BOOLEAN;
|
||
;
|
||
; TestMetric returns TRUE if the current international resource block is
|
||
; configured for metric.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
TestMetric
|
||
CLR.W 4(SP) ;assume false <fixed offset> <1/4/88med>
|
||
|
||
move.l a4,-(sp) ; save a4 <1/4/88med>
|
||
moveq.l #0,d0
|
||
BSR GetTheIntl ;get it
|
||
move.l a4,a0 ; intl handle for outside use <1/4/88med>
|
||
move.l (sp)+,a4 ; restore a4 <1/4/88med>
|
||
|
||
beq UnlockIt ; bail if GetIntl error <16>
|
||
|
||
MOVE.L (A0),A0 ;handle to pointer
|
||
|
||
TST.B IntlMetric(A0) ;is the metric flag set?
|
||
BEQ.S @1 ;if so, we're done
|
||
ADDQ.B #1,4(SP) ;return true <18Dec85 JTC> <fixed offset> <1/4/88med>
|
||
@1
|
||
BRA UnlockIt ;unlock it, return to caller <18Dec85 JTC><S132>
|
||
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE ClearCache;
|
||
;
|
||
; Clears out cache memory for resources, so apps can supply their own itl2/itl4. New. <1.8>
|
||
; New implementation for new cache structure. <9>
|
||
;
|
||
; Removed the code for handling the internal entry point ClearCacheInt - <11>
|
||
; we no longer need it, and it was wrong anyway. Rewrote to use app cache,
|
||
; creating one if necessary.
|
||
;
|
||
; No longer create app cache, since it is done in InitScriptApp <14>
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
with ExpandMemRec,SMgrAppRecord
|
||
; Add new entry point to clear the system cache <25>
|
||
ClearCacheSys ; <25>
|
||
move.l ExpandMem,a0 ; get ExpandMemRec ptr <25>
|
||
move.l emItlSysCachePtr(a0),d0 ; get cache pointer <25>
|
||
beq.s ccExit ; if 0, don't do anything <25>
|
||
move.l d0,a0 ; <25>
|
||
bra.s ClearCacheCommon ; <25>
|
||
ClearCache
|
||
move.l ExpandMem,a0 ; get ExpandMemRec ptr
|
||
move.l emScriptAppGlobals(a0),a0 ; get globals handle
|
||
move.l a0,d0 ; is it 0 (no app-specific ScriptMgr globals)?
|
||
beq.s ccExit ; if so, don't do anything
|
||
addq.l #1,d0 ; is it -1 (no Process Mgr yet, use sys cache)?
|
||
beq.s ccExit ; if so, don’t do anything
|
||
|
||
move.l (a0),a0 ; dereference - get ptr to globals
|
||
lea smgrAppCacheCount(a0),a0 ; point to record count
|
||
ClearCacheCommon ; <25>
|
||
move.w (a0)+,d0 ; get count, point to cache start
|
||
moveq #-1,d1 ; for flagging invalid IDs <41>
|
||
bra.s @enterLoop
|
||
@loop
|
||
addq #2,a0 ; skip script code
|
||
move.w d1,(a0)+ ; invalid itl2 ID <41>
|
||
clr.l (a0)+ ; nil itl2 handle <41>
|
||
move.w d1,(a0)+ ; invalid itl4 ID <41>
|
||
clr.l (a0)+ ; nil itl4 handle <41>
|
||
@enterLoop
|
||
dbra d0,@loop
|
||
ccExit
|
||
bra.s UnlockIt ; unlock it, return to caller
|
||
|
||
endwith ;ExpandMemRec,SMgrAppRecord
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE GetItlTable(script:ScriptCode; tableCode: Integer;
|
||
; VAR itlHandle: Handle; VAR offset: LongInt; VAR length: LongInt);
|
||
;
|
||
; Permits access to tables in itl2, itl4
|
||
; <2.0> new
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
gtRecord record {a6link},decr ;
|
||
gtArgs equ *-8 ; size of arguments
|
||
script ds.w 1 ; script code
|
||
table ds.w 1 ; table selector
|
||
itlHandlePtr ds.l 1 ; address of itlHandle longword
|
||
offsetPtr ds.l 1 ; address of offset longword
|
||
lengthPtr ds.l 1 ; address of length longword
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old link pointer.
|
||
gtLocals equ * ; size of local variables.
|
||
endr ;
|
||
|
||
GetItlTable
|
||
with gtRecord,SMgrRecord,ScriptRecord
|
||
link a6,#gtLocals
|
||
move.l a2,-(sp) ; save a2
|
||
|
||
; process script code, check validity
|
||
move.w script(a6),d0 ; get ScriptCode
|
||
blt.s @mapScript ; if special, go map to real script
|
||
cmp.w #smgrCount-1,d0 ; invalid?
|
||
ble.s @gotScript ; if not, we have a good script code
|
||
bra @gtError ; otherwise, bail
|
||
@mapScript
|
||
add.w #1,d0 ; is it iuSystemScript (-1)?
|
||
blt.s @getCurrent ; no, check for other codes
|
||
GetSMgrCore a0 ; get SMgrRecord pointer
|
||
move.w smgrSysScript(a0),d0 ; get system script
|
||
bra.s @gotScript
|
||
@getCurrent
|
||
add.w #1,d0 ; is it iuCurrentScript (-2)?
|
||
blt @gtError ; no, bail
|
||
subq.w #2,sp ; leave space for returned script
|
||
_FontScript ; NOT IntlScript
|
||
move.w (sp)+,d0
|
||
|
||
; OK, we have a good script code in d0, use it to get ScriptRecord
|
||
@gotScript
|
||
lsl.w #2,d0 ; make script code a long offset
|
||
GetSMgrCore a0 ; SMgrRecord pointer
|
||
move.l smgrEntry(a0,d0.w),d0 ; script's ScriptRecord pointer
|
||
beq @gtError ; bail if not installed
|
||
move.l d0,a0 ; copy
|
||
tst.b scriptEnabled(a0) ; script enabled?
|
||
beq @gtError ; bail if not
|
||
|
||
; If table selector ok, use it to locate resource info.
|
||
move.w table(a6),d1 ; get table selector
|
||
lea TableLocator,a2 ; point to locator table (1st wd is max) <17>
|
||
cmp.w (a2)+,d1 ; too big (unsigned)? <17>
|
||
bhi @gtError ; if so, bail
|
||
add.w d1,d1 ; mult by 2
|
||
move.w d1,d0 ; copy
|
||
add.w d1,d0
|
||
add.w d1,d0 ; now it is multiplied by 6
|
||
add.w d0,a2 ; now point to info for correct table
|
||
tst.w (a2)+ ; which resource?
|
||
bne.s @getitl4
|
||
|
||
; Get itl2 info
|
||
subq #4,sp ; space for returned handle
|
||
move.l #'itl2',-(sp) ; push resource type
|
||
move.w scriptBundle.itlbSort(a0),-(sp) ; push resource ID
|
||
bsr LockIt ; lock the package!! <2.2>
|
||
_GetResource
|
||
move.l (sp)+,d0 ; get itl2 handle
|
||
beq.s @gtError ; bail if nil
|
||
|
||
; OK, we're cool. Get offset and length from resource.
|
||
move.l d0,a1 ; copy resource handle
|
||
move.l (a1),d0 ; resource pointer <43>
|
||
beq.s @gtError ; bail if resource not loaded <43>
|
||
move.l d0,a0 ; copy pointer <43>
|
||
move.w (a2)+,d0 ; get offset for offset!
|
||
moveq #0,d1 ; for longizing
|
||
move.w 0(a0,d0.w),d1 ; get offset
|
||
move.w (a2)+,d0 ; get offset for length
|
||
moveq #0,d2 ; for longizing
|
||
move.w 0(a0,d0.w),d2 ; get length
|
||
bra.s @gtSetResult
|
||
|
||
; Get itl4 info
|
||
@getItl4
|
||
subq #4,sp ; space for returned handle
|
||
move.l #'itl4',-(sp) ; push resource type
|
||
move.w scriptBundle.itlbToken(a0),-(sp) ; push resource ID
|
||
bsr LockIt ; lock the package!! <2.2>
|
||
_GetResource
|
||
move.l (sp)+,d0 ; get itl2 handle
|
||
beq.s @gtError ; bail if nil
|
||
|
||
; OK, we're cool. Get offset and length from resource.
|
||
move.l d0,a1 ; copy resource handle
|
||
move.l (a1),d0 ; resource pointer <43>
|
||
beq.s @gtError ; bail if resource not loaded <43>
|
||
move.l d0,a0 ; copy pointer <43>
|
||
move.w (a2)+,d0 ; get offset for offset!
|
||
move.l 0(a0,d0.w),d1 ; get offset
|
||
move.w (a2)+,d0 ; get offset for length
|
||
moveq #0,d2 ; for longizing
|
||
move.w 0(a0,d0.w),d2 ; get length
|
||
|
||
; now we have handle in a1, offset in d1, length in d2; set result.
|
||
@gtSetResult
|
||
move.l itlHandlePtr(a6),a0
|
||
move.l a1,(a0)
|
||
move.l offsetPtr(a6),a0
|
||
move.l d1,(a0)
|
||
move.l lengthPtr(a6),a0
|
||
move.l d2,(a0)
|
||
|
||
move.l (sp)+,a2 ; restore a2
|
||
unlk a6 ; unlink stack
|
||
move.l (sp)+,a0 ; pop return addr
|
||
add.w #gtArgs,sp ; kill args
|
||
move.l a0,-(sp) ; push return addr
|
||
bra.s UnlockIt ; unlock it, return to caller
|
||
|
||
@gtError
|
||
moveq #0,a1 ; make handle nil
|
||
moveq #0,d1
|
||
moveq #0,d2
|
||
bra.s @gtSetResult
|
||
endwith ;gtRecord,SMgrRecord,ScriptRecord
|
||
|
||
TableLocator
|
||
with nItl4Rec ; <4>
|
||
dc.w iuWhiteSpaceList ; max selector <17><19>
|
||
; 0/1 for itl2/4,offset for offset,offset for length
|
||
dc.w 0,wordTableOffset,wordTableLen ; WordSelectTable
|
||
dc.w 0,wrapTableOffset,wrapTableLen ; WordWrapTable
|
||
dc.w 1,defPartsOffset,defPartsLength ; NumberPartsTable
|
||
dc.w 1,unTokenOffset,unTokenLength ; unTokenTable <17>
|
||
dc.w 1,whtSpListOffset,whtSpListLength ; whiteSpaceList <19>
|
||
endwith
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; GetTheINTL is an internal entry point for GetIntl. It expects the 'which'
|
||
; parameter in d0 and returns the resource handle in a4.
|
||
; It now also returns Z set if GetIntl failed. <16>
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
GetTheINTL
|
||
with ExpandMemRec ; <40>
|
||
sub.l #4,sp ; make room for the handle.
|
||
move.w d0,-(sp) ; push 'which' argument.
|
||
move.l ExpandMem,a4 ; ExpandMem ptr <40>
|
||
addq.b #1,emItlDontUnlockYet(a4) ; say this is internal call <40>
|
||
bsr.s GetIntl ; get the ITLx resource. <40>
|
||
subq.b #1,emItlDontUnlockYet(a4) ; end of internal call <40>
|
||
move.l (sp)+,a4 ; copy result to a4.
|
||
move.l a4,d0 ; is handle ok? set cond codes <16>
|
||
rts ; return to the caller.
|
||
endwith ;ExpandMemRec ; <40>
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; Cache memory for resources. Three records comprise the cache, one for each of
|
||
; three international resources. These records will be checked before
|
||
; performing a GetResource.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
cache record 0
|
||
theID ds.w 1
|
||
theHandle ds.l 1
|
||
endr
|
||
|
||
; offsets in expandMem. 0 means don't cache, -1 means doesn't exist <2/5/88med>
|
||
with ExpandMemRec
|
||
CacheOffset
|
||
with NewItlCacheRec
|
||
dc.b 0, 0, itl2Id, -1, itl4Id, 0 ; offsets in NewItlCacheRec <9><38>
|
||
endwith
|
||
align 2
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; FUNCTION GetIntl(which: INTEGER): Handle;
|
||
;
|
||
; GetIntl returns a handle to the international parameter block specified
|
||
; by the "which" parameter and the resource id numbers kept in the Script
|
||
; Manager globals.
|
||
; 5/15/87 <daan> Extensive revisions to cache the Intl block handle and call
|
||
; LoadResource when possible.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
|
||
giRecord record {a6link},decr ;
|
||
result ds.l 1 ; handle to intl block.
|
||
which ds.w 1 ; which argument.
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old link pointer.
|
||
state ds.w 1 ; old lock state.
|
||
|
||
sAppGlobHnd ds.l 1 ; handle to app script globals & itl cache <10><14>
|
||
sysFlag ds.w 1 ; non-zero => use sys itl cache <11>
|
||
saveRefNum ds.w 1 ; saved ref num of current resource file <24>
|
||
saveResLoad ds.b 1 ; saved value of ResLoad at entry <43><45>
|
||
ds.b 1 ; filler <45>
|
||
|
||
giLocals equ * ; size of local variables.
|
||
endr ;
|
||
|
||
|
||
GetIntl1Regs reg a3/a4/d3-d5 ; define regs <11>
|
||
|
||
|
||
with giRecord ;
|
||
GetIntl
|
||
|
||
; Link the stack and clear the result. If the 'which'
|
||
; argument is illegal, return immediately.
|
||
|
||
link a6,#giLocals ; link the stack.
|
||
movem.l GetIntl1Regs,-(sp)
|
||
clr.l result(a6) ; clear result handle.
|
||
|
||
; clr.l sAppGlobHnd(a6) ; <10><26>
|
||
clr.w sysFlag(a6) ; use app cache <11>
|
||
|
||
move.w #resNotFound,ResErr ; assume illegal 'which' arg <16>
|
||
|
||
move.w which(a6),d0 ; load 'which' argument.
|
||
cmp.w #IntlMaxID,d0 ; which > IntlMaxID?
|
||
bhi FailIntl ; yes -> bail out.
|
||
|
||
; Do not use cache if expandMem version is not correct. <3/21/88med>
|
||
; Don't bother testing anymore, it is always there in 7.0. <9>
|
||
|
||
clr.l d3 ; longize
|
||
|
||
move.b CacheOffset(d0.w),d3 ; get offset <3/21/88med>
|
||
blt FailIntl ; no resource, bail <2/5/88med>
|
||
|
||
; Get the new ITLx resource if it exists. The resource type is calculated
|
||
; by adding the 'which' parameter to the base type, ITL0. The resource id
|
||
; number is found in the script bundle of the current IntlScript.
|
||
;
|
||
; If the smgrIntlForce flag is on (which is most of the time), we know that IntlScript
|
||
; will force the script to the system script. So, if we do it here, we can avoid
|
||
; the a5 dependence of IntlScript (by doing this, however, the smgrForced and smgrDefault
|
||
; flags will not be set as they would have with IntlScript). The reason for doing this
|
||
; is to make GetIntl independent of the a5 world for most cases (i.e., when IntlForce is
|
||
; on <02/22/89 pke>.
|
||
|
||
NewIntl
|
||
subq.l #2,sp ; make room for IntlScript result <9>
|
||
|
||
with SMgrRecord,ScriptRecord ; <9>
|
||
|
||
GetSMgrCore a0 ; load script manager globals. <02/22/89 pke>
|
||
move.b smgrIntlForce(a0),d0 ; load IntlForce flag. <02/22/89 pke>
|
||
beq.s @DoIntlScr ; if 0, call IntlScript <02/22/89 pke>
|
||
move.w smgrSysScript(a0),d0 ; otherwise, use system script <02/22/89 pke>
|
||
move.w d0,(sp) ; arg for _GetScript <02/22/89 pke>
|
||
bra.s @HaveScript ; <02/22/89 pke>
|
||
@DoIntlScr ; <02/22/89 pke>
|
||
|
||
_IntlScript ; get the IntlScript code.
|
||
@HaveScript ; now script code is on stack <02/22/89 pke>
|
||
; <9>
|
||
move.w (sp)+,d0 ; get script code
|
||
move.w d0,d2 ; save in d2
|
||
GetSMgrCore a0 ; get SMgrRecord pointer
|
||
lsl.w #2,d0 ; make long offset
|
||
move.l smgrEntry(a0,d0.w),a1 ; get ScriptRecord pointer
|
||
move.w which(a6),d0 ; load 'which' argument.
|
||
add.w d0,d0 ; make word offset
|
||
move.w scriptBundle(a1,d0.w),d4 ; get resource id
|
||
|
||
endwith ;SMgrRecord,ScriptRecord ; <9>
|
||
|
||
GetIntlCommon ; code shared with GetScriptItl <11>
|
||
|
||
clr.w ResErr ; now assume no errs <16>
|
||
clr.l sAppGlobHnd(a6) ; nothing to lock/unlock <26>
|
||
move.b ResLoad,saveResLoad(a6) ; save orig value of ResLoad <43><45>
|
||
bne.s @doneSetResLoad ; if already TRUE, no need to set <43><45>
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <43><45>
|
||
tst.b emItlDontUnlockYet(a0) ; if this is external call... <43><45>
|
||
beq.s @doneSetResLoad ; ...don't change ResLoad <43><45>
|
||
st ResLoad ; else set it TRUE <43><44>
|
||
@doneSetResLoad ; <43>
|
||
|
||
; skip cache if id = 0,1; since MacWrite breaks it <1/19/88med>
|
||
|
||
tst.w d3 ; no cache?
|
||
|
||
beq GotNoCache ; bail <1/19/88med>
|
||
|
||
; Set up a4 to point to the right place. Assumes script code in d2 (not true for <9>
|
||
; all settings of conditionals! Need to fix them up some more).
|
||
; Rewrote this (down through @gotCachePtr) to use new ItlAppCache. I also <10>
|
||
; eliminated the code that cleared the new cache if someone had tried to
|
||
; clear the old one, since no developers know how to clear the old cache.
|
||
|
||
with SMgrAppRecord ; <14>
|
||
move.l Expandmem,a4
|
||
tst.w sysFlag(a6) ; use sys cache? <11>
|
||
bne.s @useSysCache ; if flag says yes, go do it <11>
|
||
move.l emScriptAppGlobals(a4),a1 ; get handle to globals <14>
|
||
move.l a1,d0 ; is it 0 (no app-specific ScriptMgr globals)?
|
||
beq.s @useSysCache ; if so, use sys cache <14>
|
||
addq.l #1,d0 ; is it -1 (no Process Mgr yet, use sys cache)?
|
||
beq.s @useSysCache ; if so, use sys cache
|
||
move.l a1,sAppGlobHnd(a6) ; save handle for lock/unlock
|
||
move.l (a1),a1 ; dereference - get ptr to globals & app cache
|
||
lea smgrAppCacheCount(a1),a1 ; point to record count <14>
|
||
bra.s @gotCachePtr
|
||
endwith ;SMgrAppRecord ; <14>
|
||
|
||
@useSysCache
|
||
move.l emItlSysCachePtr(a4),a1 ; get pointer to sys itl cache
|
||
; clr.l sAppGlobHnd(a6) ; nothing to lock/unlock <26>
|
||
move.w #-1,sysFlag(a6) ; we are now using the sys cache <26>
|
||
|
||
@gotCachePtr
|
||
with NewItlCacheRec
|
||
move.w (a1)+,d0 ; get record count, point to cache start
|
||
move.l a1,a4 ; work with copy
|
||
bra.s @endLoop ; decrement for dbra, test for 0
|
||
@loop
|
||
cmp.w (a4),d2 ; is this rec for this script
|
||
beq.s @a4SetupDone
|
||
adda.w #newItlCacheRecSize,a4 ; skip to next record
|
||
@endLoop
|
||
dbra d0,@loop
|
||
move.l a1,a4 ; oops, we failed, set to first entry
|
||
@a4SetupDone
|
||
add.w d3,a4 ; select itl2 or itl4 handle
|
||
endwith ;NewItlCacheRec
|
||
|
||
; continue on for good citizens <1/19/88med>
|
||
|
||
MOVE.W cache.theID(a4),d0 ; check cached ID <41>
|
||
cmp.w #-1,d0 ; is it -1 (invalid)? <41>
|
||
beq.s @gotID ; if so, use value in d4 from ScriptRecord <41>
|
||
move.w d0,d4 ; else use cached ID <41>
|
||
@gotID ; <41>
|
||
MOVE.L cache.theHandle(a4),d0 ; do we have a handle?
|
||
BEQ.S GotNoCache ; too bad
|
||
; skip old branch to make all caches immune to ID changes unless cleared <24><25>
|
||
|
||
IsCache
|
||
MOVEA.L d0,a0 ; get in addr reg
|
||
MOVE.L a0,result(a6) ; assume cache is ok <2/5/88med>
|
||
TST.L (a0) ; if ptr's ok, skip this nonsense
|
||
BNE DoneIntl ; don't bother unlocking <2/5/88med>
|
||
MOVE.L a0, -(sp) ; push the handle for load
|
||
BSR LockIt ; take the plunge
|
||
; <10>
|
||
move.l sAppGlobHnd(a6),d0 ; do we need to lock script app globals?
|
||
beq.s @noLock ; if not, skip
|
||
move.l d0,a0
|
||
_HLock
|
||
@noLock
|
||
_LoadResource ; load 'em up
|
||
|
||
tst.w ResErr ; any errs? <16>
|
||
beq.s UnlockIntl ; go finish up if not <16>
|
||
clr.l result(a6) ; if so, clear returned handle <16>
|
||
|
||
BRA.S UnlockIntl ; unlock
|
||
|
||
GotNoCache
|
||
SUBQ.L #4, sp ; room for getresource handle
|
||
CLR.L d0 ; clean up high word
|
||
move.w which(a6),d0 ; load 'which' argument.
|
||
add.l #'itl0',d0 ; load base type.
|
||
move.l d0,-(sp) ; push resource type.
|
||
MOVE.W d4,-(sp) ; push resource id <2/5/88med>
|
||
|
||
; Whatever resource we decided to load, go get it and return the resulting handle.
|
||
|
||
BSR LockIt
|
||
; <10>
|
||
tst.w sysFlag(a6) ; get system resources? <26>
|
||
beq.s @setupApp ; if not, do app setup <26>
|
||
move.w CurMap,saveRefNum(a6) ; save current resource file <24>
|
||
clr.w -(sp) ; use system <24>
|
||
_UseResFile ; <24>
|
||
bra.s @doneSetup ; <24>
|
||
@setupApp ; <26>
|
||
move.l sAppGlobHnd(a6),d0 ; need to lock script app globals?
|
||
beq.s @doneSetup ; if not, all done <24><26>
|
||
move.l d0,a0
|
||
_HLock
|
||
@doneSetup
|
||
_GetResource ; get the param block.
|
||
|
||
; <24>
|
||
move.l (sp)+,d0 ; did we get a handle? <24>
|
||
tst.w ResErr ; error reported? <45>
|
||
beq.s @noResErr ; if not, go check handle <45>
|
||
clr.l d0 ; if so, force handle to NIL <45>
|
||
bra.s @doneErrChk ; <45>
|
||
@noResErr ; here, no error was reported <45>
|
||
tst.l d0 ; but check if handle is NIL <45>
|
||
bne.s @doneErrChk ; if not, ResErr is OK <45>
|
||
move.w #resNotFound,ResErr ; otherwise, make it useful <16>
|
||
@doneErrChk ; <16>
|
||
|
||
tst.w d3 ; no cache?
|
||
beq.s FinishIntl ; done.
|
||
MOVE.W d4,cache.theID(a4) ; update theID (from stack) <2/5/88med>
|
||
|
||
;;; MOVE.L d0,cache.theHandle(a4) ; cache the handle (no more!!) <24><41>comment out
|
||
|
||
; Restore the state and unlock the package if necessary.
|
||
; Unlink the stack and return to the caller.
|
||
|
||
FinishIntl
|
||
; <24>
|
||
MOVE.L d0, result(a6) ; also return the handle <24>
|
||
tst.w sysFlag(a6) ; get system resources? <26>
|
||
beq.s @doneRestore ; if not, skip restore <26>
|
||
move.w saveRefNum(a6),-(sp) ; restore saved resource file <24><26>
|
||
_UseResFile ; <24><26>
|
||
@doneRestore ; <26>
|
||
|
||
UnlockIntl
|
||
; <10>
|
||
move.l sAppGlobHnd(a6),d0 ; need to unlock script app globals?
|
||
beq.s @doneAppCleanup ; if not, done app cleanup <24><26>
|
||
move.l d0,a0
|
||
_HUnlock
|
||
; Moved CurMap restore to FinishIntl <26>
|
||
@doneAppCleanup ; <26>
|
||
DoneIntl ; move above Unlock call <41>
|
||
move.b saveResLoad(a6),ResLoad ; restire orig ResLoad <43><45>
|
||
FailIntl ; move above Unlock call <41>
|
||
BSR UnlockIt
|
||
movem.l (sp)+,GetIntl1Regs
|
||
unlk a6 ; unlink the stack.
|
||
move.l (sp)+,a0 ; pop return address.
|
||
add.l #2,sp ; pop the arguments.
|
||
jmp (a0) ; return to the caller.
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; GetScriptItl <11><21>
|
||
;
|
||
; FUNCTION IUGetScriptItl(theID: INTEGER; script: ScriptCode; sysFlag: INTEGER): Handle;
|
||
;
|
||
; The following routine is a special interface to GetIntl. In addition
|
||
; to the usual 'which' parameter, it expects:
|
||
; script: ScriptCode, which may be a special negative code
|
||
; sysFlag: 0 for app cache, -1 for sys cache
|
||
;
|
||
; The following code performs the relevant operations from the initial part of
|
||
; GetIntl, modified as necessary, then rejoins GetIntl for the stuff we need.
|
||
|
||
GetScriptItl
|
||
move.l (sp)+,a0 ; pop return address <21>
|
||
move.w (sp)+,d1 ; pop sysFlag <21>
|
||
move.w (sp)+,d0 ; pop script <21>
|
||
move.l a0,-(sp) ; push return address <21>
|
||
|
||
; Now stack is set up like entry to GetIntl, so we can do the link.
|
||
; We also have script in d0, sysFlag in d1
|
||
link a6,#giLocals ; link the stack.
|
||
movem.l GetIntl1Regs,-(sp)
|
||
clr.l result(a6) ; clear result handle.
|
||
|
||
; clr.l sAppGlobHnd(a6) ; comment out <26>
|
||
move.w d1,sysFlag(a6) ; <21>
|
||
|
||
move.w #resNotFound,ResErr ; assume illegal 'which' arg <21>
|
||
|
||
move.w which(a6),d2 ; load 'which' argument. <21>
|
||
cmp.w #IntlMaxID,d2 ; which > IntlMaxID? <21>
|
||
bhi.s FailIntl ; yes -> bail out. <21>
|
||
|
||
clr.l d3 ; longize
|
||
|
||
lea CacheOffset,a0 ; point to table of offsets <21>
|
||
move.b 0(a0,d2.w),d3 ; get cache offset from table <21>
|
||
blt FailIntl ; no resource, bail <21>
|
||
|
||
; we still have ScriptCode in d0. Map it to real code, check that script <21>
|
||
; is installed and enabled, end up with script code in d2, resource ID
|
||
; in d4. Leave a4 alone.
|
||
|
||
with SMgrRecord,ScriptRecord ;
|
||
bsr intScriptCodeToReal ; map it to real script code
|
||
cmp.w #smgrCount-1,d0 ; valid?
|
||
bhi.s FailIntl ; if not, bail
|
||
move.w d0,d2 ; save in d2
|
||
lsl.w #2,d0 ; make script code a long offset
|
||
GetSMgrCore a0 ; SMgrRecord pointer
|
||
move.l smgrEntry(a0,d0.w),d0 ; ScriptRecord ptr. Script installed?
|
||
beq.s FailIntl ; if not, can't get resource ID
|
||
move.l d0,a1 ;
|
||
tst.b scriptEnabled(a1) ; script enabled?
|
||
beq.s FailIntl ; if not, bail
|
||
move.w scriptBundle.itlbSort(a1),d4 ; itl2 resource id
|
||
endwith ;SMgrRecord,ScriptRecord ;
|
||
|
||
; now we have script code in d2, cache offset in d3, resource ID in d4,
|
||
; and stack frame set up as needed. Rejoin main GetIntl code.
|
||
bra.s GetIntlCommon ; go get itl2 handle
|
||
|
||
endWith ;giRecord
|
||
endWith ;ExpandMemRec
|
||
|
||
|
||
;---------------------------------------------------------------------------------------------------------
|
||
; PROCEDURE SetIntl(resFile: INTEGER; theID: INTEGER; theBlock: Handle);
|
||
;
|
||
; SetIntl appends (or replaces) an INTL parameter block in the resource
|
||
; file specified by the "resFile" parameter.
|
||
;---------------------------------------------------------------------------------------------------------
|
||
;
|
||
siRecord record {a6link},decr ; Added frame <1/25/88med>
|
||
resFile ds.w 1 ; resource file
|
||
theId ds.w 1 ; 0,1
|
||
theBlock ds.l 1 ; handle <7/11/88ldc> change from w to l
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old link pointer.
|
||
siLocals equ * ; size of local variables.
|
||
endr ;
|
||
SetIntlRegs reg D3-D5/A3 ; <18Nov86MED>
|
||
|
||
SetIntl
|
||
with siRecord
|
||
link a6,#siLocals ; allocate <1/25/88med>
|
||
BSR LockIt
|
||
MOVEM.L SetIntlRegs,-(SP) ;save work registers <30Dec85 JTC>
|
||
; MOVE.L theBlock(SP),A0 ;get the block handle (was 24 when D1...) <18Dec85 JTC>
|
||
; MOVEM.W 24(SP),D3-D4 ;get the ID and resFile (was 28 when D1...) <18Dec85 JTC>
|
||
move.w resFile(a6),d4 ; get resource file <1/25/88med>
|
||
|
||
bne.s @doneFixRequest ;if nonzero, it is a real refNum <31>
|
||
move.w SysMap,d4 ;else map it to real refNum for System <31>
|
||
@doneFixRequest ;now we have real refNum <31>
|
||
|
||
move.w theId(a6),d3 ; get id <1/25/88med>
|
||
move.l theBlock(a6),a0 ; get the block handle <1/25/88med>
|
||
|
||
; copy the INTL parameter block into a new handle
|
||
|
||
_HandToHand ;clone the handle
|
||
MOVE.L A0,A3 ;keep the clone in A3
|
||
|
||
; remember the current resFile and make this one the current one
|
||
|
||
SUBQ #2,SP ;make room for result
|
||
_CurResFile ;remember it on the stack
|
||
|
||
MOVE.W D4,-(SP) ;push the resFile
|
||
_UseResFile ;use this one
|
||
|
||
; determine if this resource is already in the file; if it is, remove it
|
||
|
||
SUBQ #4,SP ;make room on stack
|
||
MOVE.L #'INTL',-(SP) ;push the INTL type
|
||
MOVE.W D3,-(SP) ;push the ID
|
||
_GetResource ;get the resource
|
||
MOVE.L (SP)+,D5 ;did we get it?
|
||
BEQ.S @GoAddIt ;if not, we're cool
|
||
|
||
; unfortunately, there's already one there, but it might not be in our
|
||
; particular file. Check this out using HomeResFile
|
||
|
||
SUBQ #2,SP ;make room for result
|
||
MOVE.L D5,-(SP) ;push the handle
|
||
_HomeResFile ;see where it came from
|
||
|
||
move.w (sp)+,d0 ;get the old INTL's file refNum <31>
|
||
bne.s @doneFixHome ;if nonzero, it is a real refNum <31>
|
||
move.w SysMap,d0 ;else map it to real refNum for System <31>
|
||
@doneFixHome ;now we have real refNum for old INTL <31>
|
||
cmp.w d0,d4 ;same as caller's refNum? <31>
|
||
|
||
BNE.S @GoAddIt ;if not, we're cool
|
||
|
||
; better remove the resource
|
||
|
||
MOVE.L D5,-(SP) ;push the handle
|
||
_RmveResource ;remove it
|
||
|
||
; O.K., now we can add the resource to our file
|
||
|
||
@GoAddIt
|
||
MOVE.L A3,-(SP) ;push the handle to be added
|
||
MOVE.L #'INTL',-(SP) ;push the type
|
||
MOVE.W D3,-(SP) ;push the ID
|
||
PEA EmptyString ;push NIL string for name
|
||
_AddResource
|
||
|
||
; make sure we make it purgable
|
||
|
||
MOVE.L A3,-(SP) ;push the handle
|
||
|
||
MOVE.W #resPurgeable,-(SP) ;purgeable <31>
|
||
_SetResAttrs ;set attributes <31>
|
||
MOVE.L A3,-(SP) ;push the handle again <31>
|
||
_ChangedResource ;mark it changed (the right way) <31>
|
||
|
||
; better update the resFile to make sure it gets written out
|
||
|
||
MOVE.W D4,-(SP) ;push resFile refNum
|
||
_UpdateResFile ;update it
|
||
|
||
MOVE.L A3,A0 ; pass the handle <3/2/87med>
|
||
_HPurge ; make it really purgable <3/2/87med>
|
||
; BSET #6,(A3) ;make it really purgable <3/2/87med>
|
||
|
||
; all done with SetINTL; clean up the stack and go home
|
||
|
||
_UseResFile ;restore old resFile
|
||
|
||
MOVEM.L (SP)+,SetIntlRegs ;restore work registers <30Dec85 JTC>
|
||
unlk a6 ; deallocate frame <1/25/88med>
|
||
BSR UnlockIt
|
||
MOVE.L (SP)+,A0 ;get the return address
|
||
ADDQ #8,SP ;strip parameters
|
||
JMP (A0) ;return to caller
|
||
|
||
endwith ;siRecord ; <11>
|
||
|
||
;------------------------------------------------------------------------
|
||
; Interscript sorting <1.8>
|
||
;
|
||
; FUNCTION ScriptOrder(script1, script2: ScriptCode): Integer;
|
||
;
|
||
; For now, this sorts system script first and sorts the rest in
|
||
; numerical order of script code. A script code of iuSystemScript
|
||
; is mapped to the system script.
|
||
;
|
||
; FUNCTION LangOrder(language1, language2: LangCode): Integer;
|
||
;
|
||
; This sorts languages in different scripts by the script. Languages
|
||
; in the same script are, for now, just sorted in numerical order.
|
||
;
|
||
; FUNCTION TextOrder(aPtr, bPtr: Ptr; aLen, bLen: Integer; aScript,
|
||
; bScript: ScriptCode; aLang, bLang: LangCode): Integer;
|
||
;
|
||
; This calls ScriptOrder on the scripts and returns that result if
|
||
; nonzero; otherwise it calls LangOrder on the languages and returns
|
||
; that result if nonzero; otherwise it gets the itl2 for the script,
|
||
; and calls MagPString with that itl2 handle, returning the MagPString
|
||
; result.
|
||
;------------------------------------------------------------------------
|
||
bignum equ 32767 ; largest positive int
|
||
noScriptFlag equ bignum
|
||
tableHeaderSize equ 4 ; header size in script & font map tables <9>
|
||
|
||
ScriptOrder
|
||
move.l (sp)+,a1 ; save return addr
|
||
move.w (sp)+,d2 ; get script 2
|
||
move.w (sp)+,d1 ; get script 1
|
||
move.l a1,-(sp)
|
||
bsr.s intScriptOrder
|
||
bra.s OrderExit
|
||
LangOrder
|
||
move.l (sp)+,a1 ; save return addr
|
||
move.w #noScriptFlag,d2 ; no associated script
|
||
swap d2 ; put in high word
|
||
move.w (sp)+,d2 ; get lang 2
|
||
move.w #noScriptFlag,d1 ; no associated script
|
||
swap d1 ; put in high word
|
||
move.w (sp)+,d1 ; get lang 1
|
||
move.l a1,-(sp)
|
||
bsr.s intLangOrder
|
||
OrderExit
|
||
move.w d0,4(sp) ; set result
|
||
bra.s UnlockIt ; return from UnlockIt
|
||
|
||
;---------------------------------------------------------------
|
||
; intScriptOrder
|
||
; On entry, d1 & d2 contain ScriptCode in low word
|
||
; On exit, d0.w contains order result, with cond codes N and Z set appropriately.
|
||
; Uses a0-a1,d0-d2, plus saved a2/d3-d4
|
||
;
|
||
intScriptOrder
|
||
with ExpandMemRec ; <9>
|
||
movem.l a2/d3-d4,-(sp) ; save regs <9>
|
||
cmp.w d1,d2 ; are scripts equal? <9>
|
||
beq.s commonOrderEqual ; if so, save a lot of work <9>
|
||
intScriptOrderForLangs ; entry point with regs saved <9>
|
||
move.l ExpandMem,a2 ; get ExpandMem ptr <9>
|
||
move.l emScriptMapPtr(a2),a2 ; get script map data ptr <9>
|
||
move.w d2,d4 ; save script2
|
||
move.w d1,d0 ; set up to map script1
|
||
bsr intScriptCodeToSort ; map it to sort position <9>
|
||
move.w d0,d3 ; save mapped value
|
||
move.w d4,d0 ; set up to map script2
|
||
bsr intScriptCodeToSort ; map it to sort position <9>
|
||
move.w d0,d4 ; save mapped value
|
||
|
||
; intScriptCodeToSort has mapped system script to 0 so it sorts first <9>
|
||
|
||
endwith ;ExpandMemRec
|
||
bra.s commonOrder
|
||
|
||
;---------------------------------------------------------------
|
||
; intLangOrder
|
||
; On entry, d1 & d2 contain LangCode in low word, assoc ScriptCode in high word.
|
||
; On exit, d0 contains order result, with cond codes N and Z set appropriately.
|
||
; Uses a0-a1,d0-d2, plus saved a2/d3-d4
|
||
;
|
||
intLangOrder
|
||
with ExpandMemRec ; <9>
|
||
movem.l a2/d3-d4,-(sp) ; save regs <9>
|
||
cmp.l d1,d2 ; are langs equal? <9>
|
||
beq.s commonOrderEqual ; if so, save a lot of work <9>
|
||
move.l ExpandMem,a2 ; get ExpandMem ptr <9>
|
||
move.l emLangMapPtr(a2),a2 ; get lang map data ptr <9>
|
||
move.l d2,d4 ; save lang2/script2
|
||
move.l d1,d0 ; set up to map lang1
|
||
bsr intLangCodeToScript ; map to real script code <9>
|
||
move.l d0,d3 ; save mapped value
|
||
move.l d4,d0 ; set up to map lang2
|
||
bsr intLangCodeToScript ; map to real script code <9>
|
||
|
||
; If real script codes are different, then return sorting order for
|
||
; the scripts.
|
||
cmp.w d3,d0 ; how do we look? <9>
|
||
beq.s @mapLangs ; if same, go map langs. <9>
|
||
move.w d3,d1 ; set up for intScriptOrderForLangs <9>
|
||
move.w d0,d2 ; " <9>
|
||
bra.s intScriptOrderForLangs ; <9>
|
||
|
||
; Scripts are identical. If lang codes in d0 hi are too, return 0.
|
||
@mapLangs
|
||
cmp.l d3,d0 ; look at everything.
|
||
beq.s commonOrderEqual ; if identical, save some work
|
||
|
||
bsr intLangScriptToSort ; map lang & script info to sort position <9>
|
||
move.w d0,d4 ; save it
|
||
move.l d3,d0
|
||
bsr intLangScriptToSort ; map lang & script info to sort position <9>
|
||
move.w d0,d3 ; save it
|
||
|
||
; fall through to commonOrder
|
||
endwith ;ExpandMemRec ; <9>
|
||
|
||
;---------------------------------------------------------------
|
||
; now return ordering of scripts/langs
|
||
commonOrder
|
||
moveq #-1,d0 ; assume item1 < item2
|
||
cmp.w d4,d3 ; what's the real scoop?
|
||
blt.s @2 ; if as assumed, we're done
|
||
bgt.s @1 ; if item1 > item2, deal with it
|
||
clr.w d0 ; that leaves item1 = item2
|
||
bra.s @2 ; and we're done
|
||
@1 moveq #1,d0 ; handling item1 > item2
|
||
@2 ;tst.w d0 ; not necessary
|
||
commonOrderExit
|
||
movem.l (sp)+,a2/d3-d4 ; restore temp regs
|
||
rts
|
||
commonOrderEqual ; <9>
|
||
clr.w d0 ; item1 = item2
|
||
bra.s commonOrderExit
|
||
|
||
;---------------------------------------------------------------
|
||
; Map ScriptCode value to sort position.
|
||
; At entry, d0 contains ScriptCode. a2 points to script map data table.
|
||
; At exit, d0 contains sorting position.
|
||
; Uses a0-a1,d0-d2.
|
||
; Invalid ScriptCodes are mapped to a large number.
|
||
;
|
||
|
||
intScriptCodeToSort
|
||
tst.w d0
|
||
bge.s @gotScript ; if non-negative, get sort position
|
||
|
||
addq.w #1,d0 ; is it iuSystemScript (-1)?
|
||
beq.s @doneMap ; if it is, already have result
|
||
addq.w #1,d0 ; is it iuCurrentScript (-2)?
|
||
bne.s @doErr ; no, return error result
|
||
subq #2,sp ; leave space for returned script
|
||
_RealScript ; NOT IntlScript. Change FontScript to RealScript <33>
|
||
move.w (sp)+,d0
|
||
|
||
; Now have real script code in d0.w, map it to sort position.
|
||
@gotScript
|
||
cmp.w (a2),d0 ; is our code past end of table?
|
||
bgt.s @doErr ; if so, bail
|
||
lsl.w #2,d0 ; make a long offset
|
||
move.w tableHeaderSize(a2,d0.w),d0 ; get sort position from table
|
||
@doneMap
|
||
rts
|
||
@doErr
|
||
move.w #bignum,d0 ; sort at end.
|
||
rts
|
||
|
||
;---------------------------------------------------------------
|
||
; Map ScriptCode value to real script code.
|
||
; At entry, d0 contains ScriptCode.
|
||
; At exit, d0 contains real script code.
|
||
; Uses a0-a1,d0-d2.
|
||
; Invalid ScriptCodes are mapped to a number larger than 64.
|
||
;
|
||
|
||
intScriptCodeToReal
|
||
with SMgrRecord
|
||
tst.w d0
|
||
bge.s @doneMap ; if non-negative, we-re done
|
||
|
||
addq.w #1,d0 ; is it iuSystemScript (-1)?
|
||
blt.s @getCurrent ; no, check for other codes
|
||
GetSMgrCore a0 ; get SMgrRecord pointer
|
||
move.w smgrSysScript(a0),d0 ; get system script
|
||
rts
|
||
@getCurrent
|
||
addq.w #1,d0 ; is it iuCurrentScript (-2)?
|
||
blt.s @doErr ; no, handle error
|
||
subq.w #2,sp ; leave space for returned script
|
||
_FontScript ; NOT IntlScript
|
||
move.w (sp)+,d0
|
||
rts
|
||
@doErr
|
||
move.w #bignum,d0 ; sort at end.
|
||
@doneMap
|
||
rts
|
||
endwith ;SMgrRecord
|
||
|
||
;---------------------------------------------------------------
|
||
; Map LangCode value to real script code, save info needed to get lang code.
|
||
; At entry, d0 lo contains LangCode and d0 hi contains an associated ScriptCode
|
||
; (=noScriptFlag if it is meaningless). a2 points to language data map table.
|
||
; At exit, d0 lo contains real script code. d0 hi contains a real lang code, or -1 to use
|
||
; current language for script in d0 lo, or -2 to use default lang for script in d0 lo.
|
||
; Uses a0-a1,d0-d2.
|
||
; Invalid LangCodes (or invalid associated ScriptCodes) will produce a large number for
|
||
; the real script code and 0 for the real lang code.
|
||
;
|
||
|
||
intLangCodeToScript
|
||
with SMgrRecord
|
||
tst.w d0
|
||
bge.s @realLang ; if non-negative, map lang to script <9>
|
||
|
||
add.w #1,d0 ; shift to get rid of hole at -1
|
||
beq.s @doScriptErr
|
||
|
||
asr.w #1,d0 ; C = current/default lang bit
|
||
scs -(sp) ; save bit state
|
||
|
||
cmp.w #-3,d0 ; -1,-2,-3 are valid here <9>
|
||
bgt.s @mapScript ; handle -1, -2 with intScriptCodeToReal <9>
|
||
blt.s @doScriptErrPop ; handle < -3 as err <9>
|
||
swap d0 ; set up to map specified script <9>
|
||
@mapScript ; <9>
|
||
bsr.s intScriptCodeToReal ; map to real script code <9>
|
||
cmp.w #smgrCount-1,d0 ; is script ok?
|
||
bhi.s @doScriptErrPop ; bail if not
|
||
swap d0 ; save how to get lang code
|
||
move.w #-1,d0 ; assume current lang
|
||
tst.b (sp)+ ; get current or default?
|
||
bne.s @doneLangFlag ; if current, flag is ok
|
||
move.w #-2,d0 ; set flag to be default
|
||
@doneLangFlag
|
||
swap d0 ; everything in its proper place
|
||
rts
|
||
|
||
; Map lang code to script code using table. <9>
|
||
@realLang
|
||
move.w d0,d1 ; copy lang code
|
||
swap d0 ; save real lang code in d0 hi
|
||
cmp.w (a2),d1 ; is our code past end of table?
|
||
bgt.s @doRangeErr ; if so, bail
|
||
lsl.w #2,d1 ; make lang code into long offset
|
||
move.w tableHeaderSize+2(a2,d1.w),d0 ; get real script code for lang
|
||
rts
|
||
@doRangeErr
|
||
move.w #bignum,d0 ; sort at end (move.w preserves lang code) <9>
|
||
rts
|
||
|
||
@doScriptErrPop
|
||
addq.w #2,sp ; remove flag from stack
|
||
@doScriptErr
|
||
move.l #bignum,d0 ; sort at end, arbitrary lang code <9>
|
||
rts
|
||
endwith ;SMgrRecord
|
||
|
||
;--------------------------------------------------------------- <9>
|
||
; Map lang and script info to sort position.
|
||
; At entry, d0 lo contains real script code. d0 hi contains a real lang code, or -1 to use
|
||
; current language for script in d0 lo, or -2 to use default lang for script in d0 lo.
|
||
; a2 points to language map data table.
|
||
; At exit, d0.w contains sort position.
|
||
; Uses a0-a1,d0-d2.
|
||
;
|
||
|
||
intLangScriptToSort
|
||
with SMgrRecord,ScriptRecord, ExpandMemRec
|
||
|
||
move.w d0,d1 ; save script code
|
||
swap d0 ; get lang code
|
||
tst.w d0 ; (we need cc for just low word)
|
||
bpl.s @mapLangToSort ; if positive, it is real, map it
|
||
addq.w #1,d0 ; -1 or -2?
|
||
bne.s @getDefault
|
||
|
||
GetSMgrCore a0 ; SMgrRecord pointer
|
||
move.w d1,d0 ; copy script code
|
||
lsl.w #2,d0 ; make it a long offset
|
||
move.l smgrEntry(a0,d0.w),d0 ; ScriptRecord pointer
|
||
beq.s @getDefault ; if no ScriptRecord, bail
|
||
move.l d0,a0 ; copy
|
||
tst.b scriptEnabled(a0) ; script enabled?
|
||
beq.s @getDefault ; if not, ScriptRecord not valid
|
||
move.w scriptBundle.ItlbLang(a0),d0 ; resource id
|
||
bra.s @gotLang
|
||
@getDefault
|
||
move.l ExpandMem,a0
|
||
move.l emScriptMapPtr(a0),a0 ; get script map data ptr <9>
|
||
cmp.w (a0),d1 ; is script code past end of table?
|
||
bgt.s @doErr ; if so, bail
|
||
lsl.w #2,d1 ; make script code a long offset
|
||
move.w tableHeaderSize+2(a0,d1.w),d0 ; get default lang from table
|
||
@gotLang
|
||
|
||
; Map lang code in d0.w to sort position using table.
|
||
@mapLangToSort
|
||
|
||
cmp.w (a2),d0 ; is our code past end of table?
|
||
bhi.s @doErr ; if so, bail
|
||
lsl.w #2,d0 ; make a long offset
|
||
move.w tableHeaderSize(a2,d0.w),d0 ; get sort position from table
|
||
rts
|
||
|
||
@doErr
|
||
move.w #bignum,d0 ; sort at end. <9>
|
||
rts
|
||
endwith ;SMgrRecord,ScriptRecord, ExpandMemRec
|
||
|
||
;------------------------------------------------------------------------
|
||
;
|
||
; Public routine
|
||
;
|
||
; IUTextOrder(aPtr, bPtr: Ptr; aLen, bLen: Integer;
|
||
; aScript, bScript: ScriptCode; aLang, bLang: LangCode);
|
||
;
|
||
; Private routine. <10>
|
||
; • IUTextOrderSys uses the system itl cache (instead of the app itl cache)
|
||
; to get handle for the itl2 resource.
|
||
;
|
||
; IUTextOrderSys(aPtr, bPtr: Ptr; aLen, bLen: Integer;
|
||
; aScript, bScript: ScriptCode; aLang, bLang: LangCode);
|
||
;
|
||
; Unimplemented but possible private routine. <10>
|
||
; • IUTextOrderHndl uses a specifed 'itl2' handle. We only use the handle
|
||
; to compare strings if script and language are identical, so we only need
|
||
; one handle.
|
||
;
|
||
; IUTextOrderHndl(aPtr, bPtr: Ptr; aLen, bLen: Integer;
|
||
; aScript, bScript: ScriptCode; aLang, bLang: LangCode;
|
||
; sortHandle: Handle);
|
||
;
|
||
;------------------------------------------------------------------------
|
||
|
||
toRecord record {a6link},decr ; <2.0>
|
||
result ds.w 1 ; result.
|
||
toArgs equ *-8 ; size of arguments <2.0>
|
||
aStr ds.l 1 ; aStr pointer.
|
||
bStr ds.l 1 ; bStr pointer.
|
||
aLen ds.w 1 ; aStr length
|
||
bLen ds.w 1 ; bStr length
|
||
toXtraArgs equ *-8 ; size of extra args over MagString <2.0>
|
||
aScript ds.w 1 ; aStr script
|
||
bScript ds.w 1 ; bStr script
|
||
aLang ds.w 1 ; aStr language
|
||
bLang ds.w 1 ; bStr language
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; saved a6 reg <2.0>
|
||
sysFlag ds.w 1 ; non-zero => use sys itl cache <10>
|
||
toLocals equ * ; <2.0>
|
||
endr
|
||
|
||
export TextOrder ; <30>
|
||
|
||
with toRecord
|
||
TextOrder
|
||
link a6,#toLocals ; <2.0>
|
||
clr.w sysFlag(a6) ; <10>
|
||
bra.s TextOrderCommon ; <10>
|
||
TextOrderSys ; <10>
|
||
link a6,#toLocals ; <10>
|
||
move.w #-1,sysFlag(a6) ; <10>
|
||
TextOrderCommon ; <10>
|
||
; check scripts
|
||
move.w aScript(a6),d1 ; get script1 <2.0>
|
||
move.w bScript(a6),d2 ; get script2 <2.0>
|
||
bsr.s intScriptOrder
|
||
bne.s @exit ; if so, we're done
|
||
; check languages
|
||
move.w aScript(a6),d1 ; get associated script for lang1 <2.0>
|
||
swap d1 ; put it in high byte <2.0>
|
||
move.w aLang(a6),d1 ; get lang1 <2.0>
|
||
move.w bScript(a6),d2 ; get associated script for lang2 <2.0>
|
||
swap d2 ; put it in high byte <2.0>
|
||
move.w bLang(a6),d2 ; get lang2 <2.0>
|
||
bsr.s intLangOrder
|
||
beq.s @tryText ; if not, go compare text
|
||
@exit
|
||
move.w d0,result(a6) ; otherwise, set result <2.0>
|
||
unlk a6 ; unlink stack <2.0>
|
||
move.l (sp)+,a0 ; pop return addr
|
||
add.w #toArgs,sp ; kill args
|
||
move.l a0,-(sp) ; push return addr
|
||
bra.s UnlockIt ; return from UnlockIt
|
||
|
||
; Both strings have same script and language; have to actually compare them!
|
||
; Create a stack frame for MagPString and go there. Use GetItlScript to get <21>
|
||
; itl2 handle from cache, using specified script.
|
||
|
||
@tryText
|
||
with ExpandMemRec ; <40>
|
||
sub.l #4,sp ; make room for the itl handle. <11>
|
||
move.w #2,-(sp) ; push 'which' argument for itl2. <11>
|
||
move.w aScript(a6),-(sp) ; push ScriptCode <21>
|
||
move.w sysFlag(a6),-(sp) ; push sysFlag <21>
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
addq.b #1,emItlDontUnlockYet(a0) ; say this is internal call <40>
|
||
bsr GetScriptItl ; get itl handle (does it all now) <11><21>
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
subq.b #1,emItlDontUnlockYet(a0) ; end of internal call <40>
|
||
move.l (sp)+,a1 ; pop handle into a1 (null if err) <11>
|
||
endwith ;ExpandMemRec ; <40>
|
||
|
||
@cleanUp
|
||
unlk a6 ; unlink stack <2.0>
|
||
move.l (sp)+,a0 ; temporarily pop return
|
||
addq #toXtraArgs,sp ; destroy extra args
|
||
move.l a1,-(sp) ; push itl2 Handle for MagPString
|
||
move.l a0,-(sp) ; and push return.
|
||
bra MagPString ; someone else's job now…
|
||
endwith ;toRecord
|
||
|
||
|
||
;------------------------------------------------------------------------
|
||
; FUNCTION MagString (A,B:str255; Alen,Blen:integer): integer;
|
||
; FUNCTION MagIdString(A,B:str255; Alen,Blen:integer): integer;
|
||
;
|
||
; Designed for international flavors of magnitude string comparison
|
||
; by J. Coonen 27 Oct 83.
|
||
;
|
||
;------------------------------------------------------------------------
|
||
;------------------------------------------------------------------------
|
||
; Macro: CallHook
|
||
; Input: a4.l international hooks parameter block (itl2).
|
||
; Warning: This routine trashes d0.
|
||
; This routine does not return directly.
|
||
;
|
||
; Calls one of the new hook routines from itl2 to perform special
|
||
; processing for sorting algorithm.
|
||
;------------------------------------------------------------------------
|
||
MACRO
|
||
CallHook &offset
|
||
move.w &offset(a4),d0
|
||
jsr 0(a4,d0.w) ; go and return from there.
|
||
ENDM
|
||
;------------------------------------------------------------------------
|
||
;
|
||
; In adding the Script Manager support, we call routines that trash the
|
||
; standard scratch regs, so we remap the register usage. MED
|
||
;
|
||
; d0 scratch
|
||
; d1 scratch
|
||
; d2 scratch/temporary storage for return value
|
||
; d3 end-of-strings: 2-both empty, 1-one empty, 0-neither empty
|
||
; d4 character return (now two byte)
|
||
; d5 eos (fetch)/low byte(vernier)
|
||
; d6 temporary storage
|
||
;
|
||
; a0 scratch
|
||
; a1 scratch
|
||
; a2 string data structure/deciding char (vernier)
|
||
; a3 string pointer/table ptr (vernier,proj,lig)
|
||
; a4 hook international parameter block (ITL2).
|
||
;
|
||
;------------------------------------------------------------------------
|
||
; Start code: allocate string data structures and save a4 for hook block
|
||
; resource handle (using Andy's routine).
|
||
;------------------------------------------------------------------------
|
||
; 5/15/87 <daan> Massive reorganization, renaming, and optimizing to
|
||
; squeeze as much out o' this puppy as we can. It worked.
|
||
; <1.8> Added MagPString and MagIdPString
|
||
;------------------------------------------------------------------------
|
||
|
||
with IUNSortFrame,IUStrData ; Use IUNSortFrame <4>
|
||
|
||
SortRegs reg D3-D6/A2-A4 ; <18Nov86MED>
|
||
|
||
MagWString ; <22Mar86 MED>
|
||
LINK A6,#LkSize ; <22Mar86 MED>
|
||
CLR.B WantMag(A6) ; mark weak identity compare only <22Mar86 MED>
|
||
st WeakMag(a6) ; mark as weak identity compare <22Mar86 MED>
|
||
move.w #-1, d2 ; return for less than <6/27/88ldc>
|
||
|
||
clr.l itl2Handle(a6) ; no itl2 handle supplied <2>
|
||
|
||
BRA.S ComWString ; <22Mar86 MED>
|
||
|
||
; 3 new entry points for System 7 <1.8>
|
||
MagWPString ; <5>
|
||
MOVE.L (SP)+,D0 ; get return address <5>
|
||
MOVE.L (SP)+,A0 ; get parameter handle <5>
|
||
MOVE.L D0,-(SP) ; replace return address <5>
|
||
LINK A6,#LkSize ;
|
||
CLR.B WantMag(A6) ; mark weak identity compare only
|
||
st WeakMag(a6) ; mark as weak identity compare
|
||
move.w #-1, d2 ; return for less than
|
||
move.l a0,itl2Handle(a6) ; save supplied itl2 handle <5>
|
||
BRA.S ComWString ;
|
||
|
||
MagIdPString ; <1.8>
|
||
MOVE.L (SP)+,D0 ; get return address <1.8>
|
||
MOVE.L (SP)+,A0 ; get parameter handle <1.8>
|
||
MOVE.L D0,-(SP) ; replace return address <1.8>
|
||
LINK A6,#LkSize
|
||
CLR.B WantMag(A6) ; mark weak identity compare only
|
||
move.w #1, d2 ; '<' value for EqualString
|
||
; which only returns 0 or 1
|
||
move.l a0,itl2Handle(a6) ; save supplied itl2 handle <1.8>
|
||
BRA.S ComString
|
||
MagPString ; <1.8>
|
||
MOVE.L (SP)+,D0 ; get return address <1.8>
|
||
MOVE.L (SP)+,A0 ; get parameter handle <1.8>
|
||
MOVE.L D0,-(SP) ; replace return address <1.8>
|
||
LINK A6,#LkSize
|
||
MOVE.B #1,WantMag(A6) ; true mag compare
|
||
move.w #-1, d2 ; allows -1 for '<'
|
||
move.l a0,itl2Handle(a6) ; save supplied itl2 handle <1.8>
|
||
BRA.S ComString
|
||
|
||
|
||
MagIdString
|
||
LINK A6,#LkSize
|
||
CLR.B WantMag(A6) ; mark weak identity compare only
|
||
move.w #1, d2 ; '<' value for EqualString
|
||
; which only returns 0 or 1 <6/27/88ldc>
|
||
clr.l itl2Handle(a6) ; no itl2 handle supplied <1.8>
|
||
|
||
BRA.S ComString
|
||
MagString
|
||
LINK A6,#LkSize
|
||
MOVE.B #1,WantMag(A6) ; true mag compare
|
||
move.w #-1, d2 ; allows -1 for '<' <6/27/88ldc>
|
||
|
||
clr.l itl2Handle(a6) ; no itl2 handle supplied <1.8>
|
||
|
||
ComString
|
||
sf WeakMag(a6) ; mark as strong identity compare <22Mar86 MED>
|
||
|
||
;-------------------------------------------------------------------------------
|
||
; 5/15/87 <daan> Advance pointers so far as the two strings are equal. If they
|
||
; happen to be exactly equal to the end, then so much the better; forget the
|
||
; expensive resource loading and initializations, set the status and exit.
|
||
;-------------------------------------------------------------------------------
|
||
ComWString
|
||
MOVEA.L AStrText(a6),a0 ; a string pointer
|
||
MOVEA.L BStrText(a6),a1 ; b string pointer
|
||
MOVE.W AStrLen(a6),d0 ; a length
|
||
|
||
BNE.S @1 ; remove null cases
|
||
MOVE.W BStrLen(a6),d1 ; b length
|
||
BEQ.S QuickExit ; = 0 also
|
||
MOVEQ.L #-1,d0 ; <> 0 so a < b
|
||
BRA.S QuickExit
|
||
|
||
@1 MOVE.W BStrLen(a6),d1 ; b length
|
||
BNE.S @2 ; <> 0 either
|
||
MOVEQ.L #1,d0 ; = 0 so a > b
|
||
BRA.S QuickExit
|
||
|
||
@2 CMP.W d0,d1 ; can mag(a) = mag(b)?
|
||
BNE.S NotShortEQ ; mags not trivially equal
|
||
|
||
SUBQ.W #1,d0 ; loop optimize
|
||
@3 CMPM.B (a0)+,(a1)+ ; check equality
|
||
DBNE d0,@3 ; branch if strings not exhausted
|
||
BNE.S FixLength ; didn't run out of characters
|
||
MOVEQ.L #0,d0 ; did run out; mag(a) = mag(b)
|
||
|
||
QuickExit
|
||
MOVE.W d0,result(a6) ; comparison result
|
||
bpl.s @doQuick ; check for -1 because
|
||
; IUEqualString replaces -1 with 1
|
||
|
||
; <6/27/88ldc> fix so that IUEqualString only returns 0 and 1
|
||
move.w d2, result(a6) ; d2 contains 1 if this is IUEqualString
|
||
@doQuick
|
||
bsr UnlockIt ; might have been locked by this point <40>
|
||
UNLK A6 ; clean up stack and quit
|
||
MOVEA.L (sp)+,a0
|
||
ADDA.W #ParamBytes,sp
|
||
JMP (a0)
|
||
|
||
QuickPopExit ; <16>
|
||
MOVEM.L (sp)+,SortRegs ; restore work regs <16>
|
||
moveq.l #0,d0 ; say strings are equal <16>
|
||
bra.s QuickExit ; and return <16>
|
||
|
||
FixLength
|
||
ADDQ.W #1,d0 ; repair lengths
|
||
MOVE.W d0,d1
|
||
BRA.S MainComp
|
||
|
||
NotShortEQ
|
||
SUBQ.W #1,d0 ; loop optimization
|
||
@1 CMPM.B (a0)+,(a1)+ ; check equality
|
||
BNE.S @2 ; no match
|
||
SUBQ.W #1,d1
|
||
DBEQ d0,@1 ; branch iff neither exhausted
|
||
BNE.S QuickExit ; string A ran out; d0 = -1
|
||
MOVEQ.L #1,d0 ; string B ran out; quickexit
|
||
BRA.S QuickExit
|
||
|
||
@2 ADDQ.W #1,d0 ; repair length
|
||
|
||
MainComp
|
||
SUBA.L #1,a0 ; repair addresses
|
||
SUBA.L #1,a1
|
||
MOVEM.L SortRegs,-(SP) ; use D3&A4 as temp cells <18Dec85 JTC>
|
||
MOVE.W d0,AInfo.StrCnt(A6)
|
||
MOVE.W d1,BInfo.StrCnt(A6)
|
||
MOVE.L a0,AInfo.StrPtr(A6)
|
||
MOVE.L a1,BInfo.StrPtr(A6)
|
||
CLR.L AInfo.BufChar(A6) ; nil buffer on input, false JustA, IgnChar
|
||
CLR.L BInfo.BufChar(A6) ; nil buffer on input, false JustA, IgnChar
|
||
|
||
move.l itl2Handle(a6),d0 ; <1.8><26>
|
||
beq.s @useDefault ; <26>
|
||
move.l d0,a0 ; <26>
|
||
move.l (a0),a4 ; get pointer <26>
|
||
move.l a4,d0 ; resource purged? <26>
|
||
bne.s @gotPointer ; if not, pointer ok, continue <26>
|
||
move.l a0,a4 ; copy handle <26>
|
||
bsr LockIt ; gonna move memory, lock ourselves down <40>
|
||
move.l a4,-(sp) ; <26>
|
||
_LoadResource ; load resource <26>
|
||
tst.w ResErr ; any errs? <26>
|
||
beq.s @gotHandle ; if not, handle ok, continue <26>
|
||
@useDefault ; <26>
|
||
|
||
moveq #2,d0 ; get ITL2 for hooks. <28Aug86 JDT>
|
||
bsr GetTheINTL ; puts ITL2 handle in a4.
|
||
|
||
beq QuickPopExit ; bail if can't load itl2 resource <16>
|
||
|
||
@gotHandle ; <1.8><26>
|
||
movea.l (a4),a4 ; dereference handle
|
||
@gotPointer ; <26>
|
||
|
||
; Initialize the Sorting Hooks stuff.
|
||
|
||
CLR.B WeakEq(A6) ; initialize flag
|
||
CallHook InitHook ; call InitHook routine. <28Aug86 JDT>
|
||
BRA.S MagLoop
|
||
|
||
|
||
;------------------------------------------------------------------------
|
||
; MOVED HERE FOR PROXIMITY (Formerly TwoMoreChars)
|
||
; When both strings have more characters, do a first compare for the
|
||
; easy case of equality. Otherwise, project the characters onto their
|
||
; so-called rows and compare. If their projections differ, duck soup.
|
||
; Else mark the strings as equivalent, if they haven't been so marked
|
||
; already.
|
||
;------------------------------------------------------------------------
|
||
CompareChars
|
||
CMP.W D4,D6 ; D4-B D6-A
|
||
BEQ.S MagLoop ; look no further
|
||
|
||
LEA BInfo(A6),A2 ; B data structure
|
||
BSR ProcessChar ; Mapped char in d4
|
||
|
||
LEA AInfo(A6),A2 ; A data structure
|
||
BSR ProcessChar ; Mapped char in d4
|
||
|
||
;------------------------------------------------------------------------
|
||
; After processing, if mapped characters differ, then the comparison is
|
||
; unambiguous.
|
||
;------------------------------------------------------------------------
|
||
|
||
CMP.W BInfo.MapChar(A6),D4 ; compare second char.
|
||
beq.s MappedEqual
|
||
|
||
; check for tweeking. If either char is ignorable, the string is weakly equal.
|
||
|
||
move.b AInfo.IgnChar(a6),d0 ; A ignore flag
|
||
or.b BInfo.IgnChar(a6),d0 ; B ignore flag
|
||
bne.s @1 ; at least one ignorable
|
||
CMP.W BInfo.MapChar(A6),D4 ; set status codes
|
||
bra.s MagFiniNE ; and exit
|
||
|
||
; also, fix the noFetch flags for next fetch.
|
||
; if A has an ignorable, don't fetch B's next char, and vv (unless both are ignore)
|
||
|
||
@1
|
||
move.b AInfo.IgnChar(a6),d0 ; ignorable?
|
||
move.b BInfo.IgnChar(a6),d1 ; ignorable?
|
||
not.b d0 ; reverse
|
||
move.b d0,AInfo.NoFetch(a6) ; store
|
||
not.b d1 ; reverse
|
||
move.b d1,BInfo.NoFetch(a6) ; store
|
||
|
||
;------------------------------------------------------------------------
|
||
; If the mapped characters are equal, save any necessary state.
|
||
;------------------------------------------------------------------------
|
||
MappedEqual
|
||
TST.B WeakEq(A6)
|
||
BNE.S MagLoop ; already weakly equal
|
||
|
||
ADDQ.B #1,WeakEq(A6) ; set up proper state
|
||
MOVE.W AInfo.CurChar(A6),AInfo.DecChar(A6)
|
||
MOVE.W BInfo.CurChar(A6),BInfo.DecChar(A6)
|
||
|
||
;------------------------------------------------------------------------
|
||
; Fetch a character from each string, checking for end of string, and
|
||
; make the quick check for bit equality.
|
||
;------------------------------------------------------------------------
|
||
MagLoop
|
||
LEA AInfo(A6),A2 ; string A data structure
|
||
BSR FetchChar
|
||
MOVE.W D4,D6 ; copy character
|
||
MOVE.B D5,D3 ; end of string indicator
|
||
|
||
LEA BInfo(A6),A2 ; string B data structure
|
||
BSR FetchChar
|
||
|
||
ADD.B D5,D3 ; 2-both empty 1-one empty
|
||
; 0-neither empty
|
||
BEQ.S CompareChars
|
||
SUBQ.B #2,D3
|
||
BEQ.S NoMorechars
|
||
|
||
;------------------------------------------------------------------------
|
||
; Fall through to here when just one string is exhausted.
|
||
;
|
||
; Deal specially with ignore characters.
|
||
; If we are weakly equal,
|
||
; the non-exhausted string has the ignore flag on,
|
||
; and the non-exhausted string has all ignorable characters afterward,
|
||
; then we are still weakly equal
|
||
;------------------------------------------------------------------------
|
||
|
||
move.b d5,d3 ; save status
|
||
TST.B WeakEq(A6) ; set status code
|
||
BEQ.S OneStrDone
|
||
|
||
LEA AInfo(A6),A2 ; assume string A data structure
|
||
tst.b d5 ; B exhausted?
|
||
bne.s @1 ; yes
|
||
LEA BInfo(A6),A2 ; string B data structure
|
||
@1
|
||
bra.s @3 ; map the last char
|
||
@2
|
||
BSR FetchChar ; get character
|
||
tst.b d5 ; exhausted?
|
||
bne.s CheckNoMore ; yes, check weak flags
|
||
@3
|
||
BSR ProcessChar ; map it, find if ignorable
|
||
tst.b IgnChar(a2) ; is it?
|
||
bne.s @2 ; yes, keep looping
|
||
|
||
OneStrDone
|
||
;------------------------------------------------------------------------
|
||
; Trick: since D3 is 0 if B is nonempty and 1 if B is empty,
|
||
; corresponding to A<B and A>B, respectively, just double D5 and
|
||
; compare with #1 immediate to get proper result.
|
||
; No special care required for MagIdCompare -- they're always unequal.
|
||
;------------------------------------------------------------------------
|
||
ADD.B D3,D3 ; 0-B full 2-B empty
|
||
CMPI.B #1,D3
|
||
;------------------------------------------------------------------------
|
||
; Finally, store -1,0,1 in result field according to A<B, A=B, A>B.
|
||
; If just comparing for identity, force absolute(result) into D0.
|
||
;------------------------------------------------------------------------
|
||
MagFini
|
||
BEQ.S MagFiniEQ
|
||
MagFiniNE
|
||
BCS.S @2 ; unsigned less than
|
||
@1
|
||
MOVEQ #1,D0 ; greater-than code
|
||
BRA.S MagExit
|
||
@2
|
||
tst.b WeakMag(a6) ; weak compare? <22Mar86 MED>
|
||
bne.s @25 ; yes, skip force <22Mar86 MED>
|
||
TST.B WantMag(A6)
|
||
BEQ.S @1 ; just force 1 for unequal
|
||
@25
|
||
MOVEQ #-1,D0 ; less-than code
|
||
BRA.S MagExit
|
||
MagFiniEQ
|
||
MOVEQ #0,D0 ; equal code
|
||
|
||
;------------------------------------------------------------------------
|
||
; Exit code.
|
||
;------------------------------------------------------------------------
|
||
MagExit
|
||
|
||
MOVE.W D0,result(a6) ; return result
|
||
CallHook ExitHook ; <28Aug86 JDT>
|
||
|
||
BSR UnlockIt ; unlock the package
|
||
MOVEM.L (sp)+,SortRegs ; restore work regs <18Dec85 JTC>
|
||
UNLK a6
|
||
MOVEA.L (sp)+,a0
|
||
ADDA.W #ParamBytes,sp
|
||
JMP (a0)
|
||
|
||
;------------------------------------------------------------------------
|
||
; When both strings are exhuasted simultaneously, either:
|
||
; WeakEq = 1, in which case row-relation must be arbitrated, subject
|
||
; to the JustAfter flag; or
|
||
; WeakEq = 0, in which case the strings are in fact equal.
|
||
; In the former case, if WantMag is set, then presume equality.
|
||
;------------------------------------------------------------------------
|
||
NoMoreChars
|
||
TST.B WeakEq(A6)
|
||
BEQ.S MagFiniEQ
|
||
|
||
CheckNoMore
|
||
TST.B WantMag(A6)
|
||
BEQ.S MagFiniEQ
|
||
|
||
LEA AInfo.DecChar(A6),A2 ; get deciding char
|
||
BSR.S VernierChar
|
||
MOVE.W D4,D6 ; save off
|
||
LEA BInfo.DecChar(A6),A2
|
||
BSR.S VernierChar
|
||
CMP.W D4,D6 ; compare as A-B
|
||
BNE.S MagFiniNE
|
||
|
||
;------------------------------------------------------------------------
|
||
; If both row characters are equal, decide with JustAfter flag:
|
||
; A=0 B=0 A=B
|
||
; A=0 B=1 A<B
|
||
; A=1 B=0 A>B
|
||
; A=1 B=1 A=B
|
||
; So the condition bits can be set properly just by comparing the flags!
|
||
;------------------------------------------------------------------------
|
||
MOVE.B AInfo.JustAfter(A6),D0
|
||
CMP.B BInfo.JustAfter(A6),D0
|
||
BRA.S MagFini
|
||
|
||
|
||
;------------------------------------------------------------------------
|
||
; FUNCTION VernierChar
|
||
; Input: A2 = pointer to relevant DecChar
|
||
;
|
||
; Vernier tuning of characters within rows.
|
||
; The default ordering for diacriticals is:
|
||
; acute -- '
|
||
; grave -- `
|
||
; circumflex -- ^
|
||
; umlaut -- <double dot>
|
||
; tilde -- ~
|
||
; circle -- <like the A in Angstrom>
|
||
; slash -- / <Swedish>
|
||
; cedilla -- ,
|
||
;
|
||
; The general ordering for letters is thus:
|
||
; A A' `A A^ A-umlaut A~ A-circle A/ A, a a' `a a^ ...
|
||
;
|
||
; Since most of the accented characters are correctly ordered in the
|
||
; character mapping, some simple adjustments are required. Adding $22
|
||
; to a lower-case letter forces it between its accented CAPS and accented
|
||
; lowers. The four letters requiring special treatment are:
|
||
; O-slash $AF --> $88
|
||
; A-grave $CB --> $7F
|
||
; A-tilde $CC --> $80 followed by low-order $80 to force between
|
||
; $80 and $81
|
||
; O-tilde $CD --> $86
|
||
; If the CurChar has nonzero low-order information, Vernier just maps
|
||
; to CurChar.
|
||
;------------------------------------------------------------------------
|
||
VernierChar
|
||
MOVE.B (A2)+,D4 ; hi byte of DecChar
|
||
MOVE.B (A2),D5 ; low byte
|
||
|
||
CallHook VernierHook
|
||
bne.s @9 ; skip other vernier
|
||
|
||
tst.b d5 ; special char?
|
||
bne.s @9 ; skip other vernier
|
||
|
||
|
||
LEA VernTable,A3 ; tuning table
|
||
|
||
CMP.B (A3)+,D4 ; less than lower a
|
||
BCS.S @9
|
||
CMP.B (A3)+,D4 ; greater than lower z
|
||
BHI.S @3
|
||
|
||
ADDI.B #$22,D4 ; magic translation
|
||
BRA.S @9
|
||
@3
|
||
CMP.B (A3)+,D4 ; is it in list now?
|
||
BEQ.S @8
|
||
ADDQ.L #2,A3 ; skip over hi and low
|
||
TST.B (A3)
|
||
BNE.S @3
|
||
BRA.S @9 ; no sub at all
|
||
@8
|
||
MOVE.B (A3)+,D4
|
||
MOVE.B (A3),D5
|
||
@9
|
||
LSL.W #8,D4 ; put hi and low together
|
||
OR.B D5,D4
|
||
RTS
|
||
|
||
;------------------------------------------------------------------------
|
||
; The vernier table consists of byte pairs for final tweaking.
|
||
;------------------------------------------------------------------------
|
||
VernTable
|
||
dc.b $61 ; 'a' for lower-case test
|
||
dc.b $7B ; '{' = 'z'+1 for lower-case test
|
||
dc.b $AF, $87, $00 ; O-slash ---> after O-tilde
|
||
dc.b $CB, $7E, $00 ; A` - redo to fit with stuff below <03/10/89 pke>
|
||
dc.b $CC, $80, $01 ; A-tilde ---> between A-umlaut and A-circle
|
||
dc.b $CD, $86, $00 ; O-tilde ---> after O-umlaut
|
||
dc.b $83, $70, $00 ; redo É to fit with stuff below <03/10/89 pke>
|
||
; added support for char set extensions <03/10/89 pke>
|
||
dc.b $E5, $7F, $00 ; Â
|
||
dc.b $E6, $72, $00 ; Ê
|
||
dc.b $E7, $7D, $00 ; Á
|
||
dc.b $E8, $73, $00 ; Ë
|
||
dc.b $E9, $71, $00 ; È
|
||
dc.b $EA, $80, $00 ; Í
|
||
dc.b $EB, $82, $00 ; Î
|
||
dc.b $EC, $83, $00 ; Ï
|
||
dc.b $ED, $81, $00 ; Ì
|
||
dc.b $EE, $80, $00 ; Ó
|
||
dc.b $EF, $82, $00 ; Ô
|
||
dc.b $F1, $81, $00 ; Ò
|
||
dc.b $F2, $80, $00 ; Ú
|
||
dc.b $F3, $82, $00 ; Û
|
||
dc.b $F4, $81, $00 ; Ù
|
||
dc.b $F5, $8B, $00 ; ı (change to 'i' + $22)
|
||
|
||
dc.b $00, $00 ; stop codes
|
||
align ; <3>
|
||
|
||
|
||
;------------------------------------------------------------------------
|
||
; FUNCTION FetchChar
|
||
; Input: A2 = string data structure
|
||
; Output: D4.B = next character
|
||
; D5 = nonzero iff string exhausted
|
||
; CurChar, StrPtr, IgnChar reset
|
||
;
|
||
; Note that expansion presumes that second character is not ASCII NULL.
|
||
; Note that expansion character is a byte only.
|
||
;------------------------------------------------------------------------
|
||
; 5/15/87 <daan> Reorganized, optimized, and bug-fixed.
|
||
;------------------------------------------------------------------------
|
||
FetchChar
|
||
clr.b ignChar(a2) ; reset ignChar <2.1>
|
||
|
||
MOVEQ #0,D5 ; presume string non0
|
||
tst.b NoFetch(a2) ; ignorable?
|
||
bne.s @20 ; yes, skip
|
||
MOVE.B BufChar(A2),D4 ; presume char from buf
|
||
bne.s @15 ; get a char unless one is waiting
|
||
MOVEA.L StrPtr(A2),A3
|
||
MOVE.B (A3)+,d4 ; get a character regardless
|
||
lsl.w #8,D4 ; put char in upper byte
|
||
SUBQ.W #1,StrCnt(A2) ; decrement string length (Z cleared iff ≠)
|
||
addx.w d5,d5 ; set x=1 if string len = 0
|
||
CallHook FetchHook ; call fetch hook: return d4,a3,d5
|
||
MOVE.L A3,StrPtr(A2)
|
||
move.w d4,CurChar(a2) ; save input char
|
||
rts
|
||
|
||
@15
|
||
lsl.w #8,D4 ; put char in upper byte
|
||
clr.b BufChar(A2) ; kill buffered char
|
||
move.w d4,CurChar(a2) ; save input char
|
||
rts
|
||
|
||
@20
|
||
clr.b NoFetch(a2) ; not any more, it ain't
|
||
move.w CurChar(a2),d4 ; get same char
|
||
rts
|
||
|
||
;------------------------------------------------------------------------
|
||
; After a byte is input, it is mapped to a family character (e.g. all
|
||
; A's and a's are mapped to 'A'), and expanded if one of the ligatures
|
||
; AE, ae, OE, oe. Then the Info structure is passed to the international
|
||
; routine for one last chance to tweak.
|
||
;------------------------------------------------------------------------
|
||
ProcessChar
|
||
; just fall into...
|
||
|
||
;------------------------------------------------------------------------
|
||
; FUNCTION projectChar
|
||
; Input: A2 = string data structure
|
||
; Output: D4 = Mapped character
|
||
;
|
||
; Uses table for all values.
|
||
; If the CurChar has any nonzero tail, then set MapChar := CurChar.
|
||
; Special processing for double-byte characters
|
||
;------------------------------------------------------------------------
|
||
projectChar
|
||
CLR.W MapChar(A2) ; clear hi/low halves
|
||
move.w CurChar(a2),d4 ; get current
|
||
CallHook ProjectHook ; call it
|
||
bne.s SkipProject ; skip if NE
|
||
|
||
lsr #8,d4 ; get char in lower byte
|
||
MOVE.B ProjTable(D4),D4 ; look up mapping
|
||
; then fall through to...
|
||
CMP.B LigTable(PC),D4 ; ligature iff $AE
|
||
bne.s ProjectD4 ; fix D4 and return <12/22/87med>
|
||
|
||
;------------------------------------------------------------------------
|
||
; PROCEDURE xLigature
|
||
; Input: D4 = MapChar hi byte; A2 = string data structure
|
||
;
|
||
; <03/10/89 pke> added ß, fi, fl. Need to turn this into a loop, get
|
||
; count from table, used defined constant to mark
|
||
; ligature above and in ProjTable.
|
||
;------------------------------------------------------------------------
|
||
xLigature
|
||
LEA LigTable,A3
|
||
|
||
MOVE.B CurChar(A2),D4 ; restore character
|
||
|
||
CMP.B (A3)+,D4 ; AE
|
||
BEQ.S @18
|
||
|
||
ADDQ.L #3,A3
|
||
CMP.B (A3)+,D4 ; ae
|
||
BEQ.S @18
|
||
|
||
ADDQ.L #3,A3
|
||
CMP.B (A3)+,D4 ; OE
|
||
BEQ.S @18
|
||
|
||
ADDQ.L #3,A3
|
||
CMP.B (A3)+,D4 ; oe
|
||
BEQ.S @18
|
||
|
||
ADDQ.L #3,A3
|
||
CMP.B (A3)+,D4 ; ß
|
||
BEQ.S @18
|
||
|
||
ADDQ.L #3,A3
|
||
CMP.B (A3)+,D4 ; fi
|
||
BEQ.S @18
|
||
|
||
ADDQ.L #4,A3 ; fl, by default
|
||
@18
|
||
MOVE.B (A3)+,CurChar(A2)
|
||
MOVE.B (A3)+,D4
|
||
MOVE.B (A3),BufChar(A2)
|
||
TST.B WeakEq(A6) ; only set JustAfter if not yet we <12/22/87med>
|
||
BNE.S ProjectD4 ; already weakly equal <12/22/87med>
|
||
ADDQ.B #1,JustAfter(A2)
|
||
ProjectD4
|
||
asl.w #8,d4 ; restore to high byte <12/22/87med>
|
||
SkipProject
|
||
MOVE.W D4,MapChar(A2) ; hi-order MapChar
|
||
rts
|
||
|
||
;------------------------------------------------------------------------
|
||
; Table of default ligature expansions.
|
||
;------------------------------------------------------------------------
|
||
LigTable
|
||
dc.b $AE, 'A', 'A', 'E' ; note: $AE must be first
|
||
dc.b $BE, 'a', 'A', 'e'
|
||
dc.b $CE, 'O', 'O', 'E'
|
||
dc.b $CF, 'o', 'O', 'e'
|
||
dc.b $A7, 's', 'S', 's' ; ß <03/10/89 pke>
|
||
dc.b $DE, 'f', 'F', 'i' ; fi <03/10/89 pke>
|
||
dc.b $DF, 'f', 'F', 'l' ; fl <03/10/89 pke>
|
||
|
||
;------------------------------------------------------------------------
|
||
; Table projecting all byte values into 'rows':
|
||
; -- All letters are mapped to the CAPITAL form, sans diacriticals.
|
||
; -- Non-breaking space is mapped to space.
|
||
; -- All double quotes are mapped to ASCII double quote $22.
|
||
; -- All single quotes are mapped to ASCII single quote $27
|
||
; (this doesn't include acute $AB and ASCII grave $60).
|
||
; -- All AE/OE/fi/fl/ß ligatures are mapped to ligature-AE $AE.
|
||
; -- Superscripted, underscored a and o ($BB and $BC) are symbols,
|
||
; and thus mapped to themselves rather than 'A' and 'O'.
|
||
; -- Em-dash and minus sign ($D0 and $D1) are mapped to selves rather
|
||
; than ASCII hyphen $2D.
|
||
; -- All other characters in $00 to $FF are mapped to themselves.
|
||
;------------------------------------------------------------------------
|
||
ProjTable
|
||
dc.b $00, $01, $02, $03, $04, $05, $06, $07
|
||
dc.b $08, $09, $0A, $0B, $0C, $0D, $0E, $0F
|
||
dc.b $10, $11, $12, $13, $14, $15, $16, $17
|
||
dc.b $18, $19, $1A, $1B, $1C, $1D, $1E, $1F
|
||
|
||
dc.b ' ', '!', '"', '#', '$', '%', '&', $27 ; $20
|
||
dc.b '(', ')', '*', '+', ',', '-', '.', '/'
|
||
dc.b '0', '1', '2', '3', '4', '5', '6', '7'
|
||
dc.b '8', '9', ':', ';', '<', '=', '>', '?'
|
||
|
||
dc.b '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' ; $40
|
||
dc.b 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
|
||
dc.b 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'
|
||
dc.b 'X', 'Y', 'Z', '[', '\', ']', '^', '_'
|
||
|
||
dc.b '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G' ; $60
|
||
dc.b 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
|
||
dc.b 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'
|
||
dc.b 'X', 'Y', 'Z', '{', '|', '}', '~', $7F
|
||
|
||
dc.b 'A', 'A', 'C', 'E', 'N', 'O', 'U', 'A' ; $80
|
||
dc.b 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E'
|
||
dc.b 'E', 'E', 'I', 'I', 'I', 'I', 'N', 'O'
|
||
dc.b 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U'
|
||
|
||
dc.b $A0, $A1, $A2, $A3, $A4, $A5, $A6, $AE ; ß is ligature <03/10/89 pke>
|
||
dc.b $A8, $A9, $AA, $AB, $AC, $AD, $AE, 'O'
|
||
dc.b $B0, $B1, $B2, $B3, $B4, $B5, $B6, $B7
|
||
dc.b $B8, $B9, $BA, $BB, $BC, $BD, $AE, 'O'
|
||
|
||
dc.b $C0, $C1, $C2, $C3, $C4, $C5, $C6, $22 ; note: $22 = "
|
||
dc.b $22, $C9, ' ', 'A', 'A', 'O', $AE, $AE
|
||
dc.b $D0, $D1, $22, $22, $27, $27, $D6, $D7
|
||
dc.b 'Y', 'Y', $DA, $DB, $DC, $DD, $AE, $AE ; add Ÿ & fi,fl ligatures <03/10/89 pke>
|
||
|
||
dc.b $E0, $E1, $E2, $E3, $E4, 'A', 'E', 'A' ; add Â,Ê,Á
|
||
dc.b 'E', 'E', 'I', 'I', 'I', 'I', 'O', 'O' ; add Ë,È,Í,Î,Ï,Ì,Ó,Ô <3/10/89 pke>
|
||
dc.b $F0, 'O', 'U', 'U', 'U', 'I', $F6, $F7 ; add Ò,Ú,Û,Ù,ı <03/10/89 pke>
|
||
dc.b $F8, $F9, $FA, $FB, $FC, $FD, $FE, $FF
|
||
|
||
endWith ; iuSortFrame/iuNSortFrame, IUStrData
|
||
|
||
endProc
|
||
|
||
|
||
;---------------------------------------------------------- <7>
|
||
;
|
||
; PROCEDURE TypeSelectClear(VAR tsr: TypeSelectRecord);
|
||
;
|
||
; clears/initials the tsr record.
|
||
;
|
||
;----------------------------------------------------------
|
||
TypeSelectClear PROC EXPORT
|
||
move.l (sp)+,a0 ; get return address
|
||
move.l (sp)+,a1 ; get tsr pointer
|
||
moveq #0,d0
|
||
move.l d0,TypeSelectRecord.tsrLastKeyTime(a1) ; clear timer
|
||
move.b d0,TypeSelectRecord.tsrKeyStrokes(a1) ; clear text
|
||
jmp (a0)
|
||
ENDPROC
|
||
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
;
|
||
; FUNCTION TypeSelectNewKey(theEvent: EventRecord;
|
||
; VAR tsr: TypeSelectRecord): BOOLEAN;
|
||
;
|
||
; Call this each time you get a key down event for a type select list.
|
||
; If it returns true then you should change selection to the closest
|
||
; match in tsr. It handles timeouts, and delete/clear keys.
|
||
;
|
||
;----------------------------------------------------------------------
|
||
TypeSelectNewKey PROC EXPORT
|
||
|
||
kMaxTypeDelay EQU 60 ; if auto repeat is turn off, then value to use
|
||
chClear EQU $1B ; clear key on keypad happens to have same char code as ESC
|
||
chDelete EQU $08 ; aka backspace
|
||
|
||
StackFrame RECORD {A6Link},DECR
|
||
result DS.W 1
|
||
paramSize EQU *-8 ; bytes of prameters to remove on return
|
||
theEvent DS.L 1
|
||
tsr DS.L 1
|
||
ReturnAddr DS.L 1
|
||
A6Link DS.L 1
|
||
; locals go here
|
||
ALIGN
|
||
size EQU * ; size to link
|
||
ENDR
|
||
|
||
EventRecord RECORD 0
|
||
what DS.W 1
|
||
message DS.L 1
|
||
when DS.L 1
|
||
where DS.W 2
|
||
modifiers DS.W 1
|
||
ENDR
|
||
|
||
link a6,#StackFrame.size
|
||
movem.l a3/a4,-(sp) ; save registers
|
||
move.l StackFrame.theEvent(a6),a4 ; get theEvent
|
||
move.l StackFrame.tsr(a6),a3 ; get tsr pointer
|
||
clr.b StackFrame.result(a6) ; set return to false by default
|
||
|
||
; only do somthing if event is a keydown
|
||
cmp.w #keyDwnEvt,EventRecord.what(a4)
|
||
bne @done ; if not really key down, then done
|
||
; and not a command-key
|
||
btst #cmdKey,EventRecord.modifiers(a4)
|
||
bne.s @clearTyping ; if command key down, then clear buffer?
|
||
|
||
; delete or clear key means clear buffer
|
||
move.b EventRecord.message+3(a4),d0 ; get character
|
||
cmp.b #chDelete,d0 ; is this Delete/Backspace?
|
||
bne.s @notDelete
|
||
@clearTyping move.l a3,-(sp)
|
||
bsr.s TypeSelectClear
|
||
bra.s @done
|
||
@notDelete cmp.b #chClear,d0 ; is this Clear? ### should I check keycode?
|
||
beq.s @clearTyping
|
||
|
||
; get max delay since last key stroke
|
||
move.w keyThresh,d0 ; get threshhold 'til auto-repeat
|
||
cmp.w #kMaxTypeDelay,d0
|
||
bls.s @autoRepeatOn ; if large, then it is turned off
|
||
move.w #kMaxTypeDelay,d0 ; so use resonably long delay instead
|
||
@autoRepeatOn add.l d0,d0 ; use 2x keythreshold
|
||
|
||
; check time since last keystroke
|
||
move.l EventRecord.when(a4),d1 ; get time of this key stroke
|
||
sub.l TypeSelectRecord.tsrLastKeyTime(a3),d1 ; get time since last key stroke
|
||
cmp.l d0,d1 ; see if key strokes close enough together
|
||
bls.s @checkScript ; if not reset buffer and start with this key
|
||
move.l a3,-(sp)
|
||
bsr.s TypeSelectClear
|
||
|
||
; check if keyboard script has changed
|
||
@checkScript subq #4,sp ; space for long
|
||
move.w #smKeyScript,-(sp) ; ask for current keyboard script
|
||
_GetEnvirons ; from script manager
|
||
move.l (sp)+,d0 ; get long result, script in low word
|
||
|
||
; always treat Roman keyboard like system script <29>
|
||
bne.s @doneRomanAdjust ; <29>
|
||
subq #4,sp ; space for long <29>
|
||
move.w #smSysScript,-(sp) ; ask for system script <29>
|
||
_GetEnvirons ; from script manager <29>
|
||
move.l (sp)+,d0 ; get long result, script in low word <29>
|
||
@doneRomanAdjust ; <29>
|
||
|
||
tst.b TypeSelectRecord.tsrKeyStrokes(a3) ; will this be first byte in buffer? <8>
|
||
bne.s @compareScript ; <8>
|
||
move.w d0,TypeSelectRecord.tsrScript(a3) ; if so initialize script for this string <8>
|
||
bra.s @addNewKey ; <8>
|
||
@compareScript cmp.w TypeSelectRecord.tsrScript(a3),d0 ; has keyboard script changed?
|
||
beq.s @addNewKey
|
||
move.l a3,-(sp)
|
||
bsr TypeSelectClear
|
||
|
||
; add key stroke to buffer
|
||
@addNewKey lea TypeSelectRecord.tsrKeyStrokes(a3),a0
|
||
cmp.b #63,(a0) ; check for overflow
|
||
bge.s @done
|
||
addq.b #1,(a0) ; increment string buffer
|
||
moveq #0,d0
|
||
move.b (a0),d0 ; get end index
|
||
add.l d0,a0 ; make into pointer
|
||
move.b EventRecord.message+3(a4),(a0) ; put char code into end of buffer
|
||
|
||
; record time of keystroke
|
||
move.l EventRecord.when(a4),TypeSelectRecord.tsrLastKeyTime(a3)
|
||
|
||
; return true
|
||
addq.b #1,StackFrame.result(a6) ; return boolean true
|
||
|
||
@done movem.l (sp)+,a3/a4
|
||
unlk a6
|
||
move.l (sp)+,a0
|
||
add #StackFrame.paramSize,sp
|
||
jmp (a0)
|
||
ENDPROC
|
||
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
;
|
||
; FUNCTION TypeSelectCompare(tsr: TypeSelectRecord;
|
||
; testStringScript: ScriptCode;
|
||
; testStringPtr: StringPtr): INTEGER;
|
||
;
|
||
; Used to find closest matching list item. Does correct international
|
||
; comparison of the keys strokes stored in tsr against any string.
|
||
; That is, first check for byte to byte equality, if not the same then
|
||
; call MagWPString to compare strings. <20>
|
||
; Returns -1, 0, 1 if keys strokes are before, same, or after the test string
|
||
;
|
||
;----------------------------------------------------------------------
|
||
TypeSelectCompare PROC EXPORT
|
||
IMPORT ScriptOrder, MagWPString, UnLockIt, intScriptCodeToReal, GetScriptItl ; <20>
|
||
|
||
StackFrame RECORD {A6Link},DECR
|
||
result DS.W 1
|
||
paramSize EQU *-8 ; bytes of prameters to remove on return
|
||
tsr DS.L 1
|
||
testStringScript DS.W 1 ; cached in d3.w
|
||
testStringPtr DS.L 1 ; lea testStringPtr^[1] in a3, length in d4.w
|
||
ReturnAddr DS.L 1
|
||
A6Link DS.L 1
|
||
; locals go here
|
||
; tsr.script cached in d5.w
|
||
; lea tsr.keyStrokes^[1] in a4, length in d6.w
|
||
ALIGN
|
||
size EQU * ; size to link
|
||
ENDR
|
||
|
||
|
||
link a6,#StackFrame.size
|
||
movem.l d3-d6/a2-a4,-(sp) ; save registers <20>
|
||
move.w StackFrame.testStringScript(a6),d3 ; get testStringScript
|
||
move.l StackFrame.testStringPtr(a6),a3 ; get testStringPtr
|
||
moveq #0,d4
|
||
move.b (a3)+,d4 ; a3 = test.StringPtr, d4.w = test.length
|
||
move.l StackFrame.tsr(a6),a4
|
||
move.w TypeSelectRecord.tsrScript(a4),d5 ; d5.w = tsr.script
|
||
moveq #0,d6
|
||
move.b TypeSelectRecord.tsrKeyStrokes(a4),d6 ; d6.w = tsr.length
|
||
lea TypeSelectRecord.tsrKeyStrokes+1(a4),a4 ; a4 = tsr.stringPtr
|
||
|
||
; first check the scripts, if same check strings
|
||
cmp.w d3,d5 ; compare script numbers first
|
||
beq.s @testStringsLength ; same script so compare the text
|
||
; scripts are different so use script order to find overall order
|
||
subq #2,sp ; room for result
|
||
move.w d5,-(sp)
|
||
move.w d3,-(sp)
|
||
bsr ScriptOrder ; get order for scripts
|
||
move.w (sp)+,d0 ; set CC's and we are done
|
||
bra.s @done
|
||
|
||
; check string lengths as short circuit of equality
|
||
@testStringsLength
|
||
cmp.b d4,d6 ; are strings the same length?
|
||
bne.s @doIntlCompare ; if not check sort order
|
||
|
||
; check for exactly the same bytes
|
||
move.l a3,a0
|
||
move.l a4,a1
|
||
move.w d4,d0
|
||
@nextByte cmp.b (a0)+,(a1)+ ; compare each byte
|
||
bne.s @doIntlCompare ; if one byte wrong then try I.U.
|
||
subq.w #1,d0
|
||
beq.s @done ; if all bytes same, return 0
|
||
bra.s @nextByte
|
||
|
||
; use localizable string comparison, for primary sort order only. <20>
|
||
@doIntlCompare
|
||
;; bsr LockIt ; GetScriptItl will lock if necessary <20>
|
||
|
||
; Use GetItlScript to get itl2 handle from cache, using specified script. <21>
|
||
|
||
with ExpandMemRec ; <40>
|
||
sub.l #4,sp ; make room for the itl handle.
|
||
move.w #2,-(sp) ; push 'which' argument for itl2.
|
||
move.w d3,-(sp) ; push ScriptCode <21>
|
||
move.w #-1,-(sp) ; we want system cache <21>
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
addq.b #1,emItlDontUnlockYet(a0) ; say this is internal call <40>
|
||
bsr GetScriptItl ; get itl handle
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
subq.b #1,emItlDontUnlockYet(a0) ; end of internal call <40>
|
||
move.l (sp)+,d0 ; pop handle into d0.
|
||
beq.s @done ; if err, bail (d0=0) <21>
|
||
|
||
subq #2,sp ; room for result
|
||
move.l a4,-(sp) ; aPtr
|
||
move.l a3,-(sp) ; bPtr
|
||
move.w d6,-(sp) ; aLen
|
||
move.w d4,-(sp) ; bLen
|
||
move.l d0,-(sp) ; itl2 handle
|
||
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
addq.b #1,emItlDontUnlockYet(a0) ; say this is internal call <40>
|
||
bsr MagWPString ; order comparison
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
subq.b #1,emItlDontUnlockYet(a0) ; end of internal call <40>
|
||
move.w (sp)+,d0 ; <40>
|
||
endwith ;ExpandMemRec ; <40>
|
||
|
||
; return value in d0
|
||
@done move.w d0,StackFrame.result(a6) ; return boolean
|
||
|
||
bsr UnLockIt ; moved here <40>
|
||
movem.l (sp)+,d3-d6/a2-a4 ; restore regs <20>
|
||
unlk a6
|
||
move.l (sp)+,a0
|
||
add #StackFrame.paramSize,sp
|
||
jmp (a0)
|
||
;
|
||
; set up parameters for compare string call
|
||
; (modified and moved inline, since we only need it once now) <20>
|
||
|
||
ENDPROC
|
||
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
;
|
||
; FUNCTION TypeSelectFindItem( tsr: TypeSelectRecord;
|
||
; listSize: INTEGER;
|
||
; selectMode: TSCode {INTEGER};
|
||
; getStringProc: IndexToStringProcPtr;
|
||
; yourDataPtr: Ptr): INTEGER;
|
||
;
|
||
; If your list is sorted, you can start at the beginning of the list and
|
||
; call TypeSelectCompare on each item to you find one that is ≥ and
|
||
; it is the item to select.
|
||
;
|
||
; If list is not sorted, you can call TypeSelectFindItem. It will walk the
|
||
; entire list and return the correct one to select. It calls a procedure you
|
||
; supply to get an item's script and string from its index in the list
|
||
;
|
||
; If the number of item in the list is unknown, you pass in MAXINT ($7FFF) for
|
||
; listSize and have your getStringProc return false when it is called past the
|
||
; end of the list.
|
||
;
|
||
; selectMode is a parameter to allow the user to alphabetically walk through an
|
||
; unsorted list. Normally, you would use tsNormalSelectMode for type selecting.
|
||
; If after an item is selected, the user wants to select the next alphabetical
|
||
; item, fill the tsr buffer with the string for the current selected item
|
||
; and call TypeSelectFindSelect with selectMode = tsNextSelectMode. To get the
|
||
; previous item use selectMode = tsPreviousSelectMode.
|
||
;
|
||
; tsPreviousSelectMode largest item < type select buffer
|
||
; tsNormalSelectMode smallest item ≥ type select buffer
|
||
; tsNextSelectMode smallest item > type select buffer
|
||
;
|
||
;
|
||
;TYPE
|
||
; IndexToStringProcPtr = ^FUNCTION(item: INTEGER;
|
||
; VAR itemsScript: ScriptCode;
|
||
; VAR itemsStringPtr: StringPtr;
|
||
; yourDataPtr: Ptr): BOOLEAN;
|
||
;
|
||
; If an item is not selectable (ex. grayed out items in putfile)
|
||
; your IndexToStringProcPtr should return NIL for itemsStringPtr.
|
||
;
|
||
; Selects the item which based on the selectMode. tsNormalSelectMode is
|
||
; the smallest item ≥ type select buffer.
|
||
; That is, the exact match, or if the list was sorted, the first
|
||
; file after where the type select buffer would be inserted.
|
||
;
|
||
; Works by scanning the entire list. Trying to find the closet match.
|
||
; It keeps a "best guess", The best guess is changed if another item is
|
||
; found which better matches the criteria.
|
||
;
|
||
; Uses a routine BndBranch to do bounds checking based on selectMode.
|
||
;
|
||
;----------------------------------------------------------------------
|
||
TypeSelectFindItem PROC EXPORT
|
||
IMPORT LockIt, UnLockIt
|
||
|
||
StackFrame RECORD {A6Link},DECR
|
||
result DS.W 1
|
||
paramSize EQU *-8 ; bytes of prameters to remove on return
|
||
tsr DS.L 1 ; cached in A4
|
||
listSize DS.W 1
|
||
selectMode DS.W 1
|
||
getStringProc DS.L 1
|
||
yourDataPtr DS.L 1
|
||
ReturnAddr DS.L 1
|
||
A6Link DS.L 1
|
||
; locals go here
|
||
bestGuess DS TypeSelectRecord
|
||
firstValidItem DS.W 1 ; for use as guess if wrap-around needed
|
||
lastValidItem DS.W 1 ; for use as guess if wrap-around needed
|
||
anItemScript DS.W 1 ; cached in D5
|
||
anItemStringPtr DS.L 1 ; cached in D4
|
||
; bestGuess StringPtr in D7
|
||
ALIGN
|
||
size EQU * ; size to link
|
||
ENDR
|
||
|
||
MACRO
|
||
tstBra &branchLabel
|
||
lea &branchLabel,a1
|
||
bsr BndBranch ; <27>
|
||
ENDM
|
||
|
||
link a6,#StackFrame.size
|
||
movem.l a4/d3-d7,-(sp)
|
||
move.l StackFrame.tsr(a6),a4
|
||
move.w StackFrame.selectMode(a6),d6
|
||
bsr LockIt ; lock the package!! we will be calling user code
|
||
|
||
moveq #0,d7 ; remember, we have no bestGuess
|
||
move.w d7,StackFrame.result(a6) ; zero guess index
|
||
move.w d7,StackFrame.firstValidItem(a6) ; zero out
|
||
move.w d7,StackFrame.lastValidItem(a6) ; zero out
|
||
moveq #1,d3 ; start looking at first cell
|
||
|
||
@nextCell ; get D3'th item into anItem
|
||
bsr GetStringFromIndex
|
||
beq @endOfList ; if IndexToString returns false, then done <40>
|
||
|
||
tst.l d4 ; d4 = StackFrame.anItemStringPtr(a6)
|
||
beq.s @notFound ; if stringPtr is NIL then skip this item
|
||
|
||
; save off first and last know valid items
|
||
tst.w StackFrame.firstValidItem(a6)
|
||
bne.s @firstWasFound
|
||
move.w d3,StackFrame.firstValidItem(a6) ; this is once set once
|
||
@firstWasFound move.w d3,StackFrame.lastValidItem(a6) ; this keeps getting set
|
||
|
||
; compare anItem with type select buffer
|
||
with ExpandMemRec ; <40>
|
||
subq #2,sp ; room for result
|
||
move.l a4,-(sp) ; a4 = StackFrame.tsr(a6)
|
||
move.w d5,-(sp) ; d5 = StackFrame.anItemScript(a6)
|
||
move.l d4,-(sp) ; d4 = StackFrame.anItemStringPtr(a6)
|
||
; note: there is a bug here in next- and prev-mode. It should
|
||
; be doing a comparsion that includes secondary differences.
|
||
; Currently TAB in the Finder will skip over names that do not
|
||
; differ in a linguistically relevant manner (i.e. "abc" "åbc" in English)
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
addq.b #1,emItlDontUnlockYet(a0) ; say this is internal call <40>
|
||
bsr TypeSelectCompare
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
subq.b #1,emItlDontUnlockYet(a0) ; end of internal call <40>
|
||
tstBra @notFound ; if bounds fails, try next item
|
||
|
||
; have a contender for a better guess
|
||
; see if this is first contender, then it is bestGuess
|
||
tst.l d7 ; if last bestGuess does not exist
|
||
beq.s @newBest ; then this guess is better!
|
||
|
||
; see if current cell is closer to typeSelect than bestGuess
|
||
; need to consider secondary differences when differentiating between guesses <30>
|
||
lea StackFrame.bestGuess.tsrKeyStrokes(a6),a0 ; a0 is bestguess <30>
|
||
moveq #0,d0 ; <30>
|
||
move.b (a0)+,d0 ; d0 is bestguess length<30>
|
||
move.l d4,a1 ; a1 is this item <30>
|
||
moveq #0,d1 ; <30>
|
||
move.b (a1)+,d1 ; d1 is this item length<30>
|
||
subq #2,sp ; room for result <30>
|
||
pea (a0) ; aPtr <30>
|
||
pea (a1) ; bPtr <30>
|
||
move.w d0,-(sp) ; aLen <30>
|
||
move.w d1,-(sp) ; bLen <30>
|
||
move.w StackFrame.bestGuess.tsrScript(a6),-(sp) ; aScript <30>
|
||
move.w d5,-(sp) ; bScript <30>
|
||
moveq #iuScriptDefLang,d0 ; <30>
|
||
move.w d0,-(sp) ; aLang <30>
|
||
move.w d0,-(sp) ; bLang <30>
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
addq.b #1,emItlDontUnlockYet(a0) ; say this is internal call <40>
|
||
bsr TextOrder ; compare them <30>
|
||
move.l ExpandMem,a0 ; ExpandMem ptr <40>
|
||
subq.b #1,emItlDontUnlockYet(a0) ; end of internal call <40>
|
||
; note: if the list contains duplicate names and one of those names is
|
||
; the best type select match, then TypeSelectFindItem returns
|
||
; the last list-order of the duplicates. This maybe somewhat random,
|
||
; but the API for TypeSelect does not support anyway to differentiate
|
||
; between the duplicates. If you want to do something about it, check
|
||
; for $0000 on the stack at this point.
|
||
neg.w (sp)
|
||
tstBra @notFound ; if bounds fails, then bestGuess is
|
||
; still better than anItem, so try next item
|
||
endwith ;ExpandMemRec ; <40>
|
||
|
||
@newBest bsr NewBestGuess
|
||
|
||
@notFound addq.w #1,d3 ; next cell index
|
||
cmp.w StackFrame.listSize(a6),d3
|
||
ble.s @nextCell ; keep going 'til end of list
|
||
|
||
@endOfList
|
||
; see if tsr passed in was empty. if so, choose first or last <27>
|
||
tst.b TypeSelectRecord.tsrKeyStrokes(a4) ; a4 = StackFrame.tsr(a6) <27>
|
||
beq.s @firstOrLast ; <27>
|
||
|
||
; looked at 'em all, result has best one
|
||
tst.w StackFrame.result(a6)
|
||
bne.s @foundIt
|
||
|
||
@firstOrLast ; <27>
|
||
; if result is still zero then none matched
|
||
; so tsNormalSelectMode => select last item
|
||
; tsNextSelectMode => wrap around to first
|
||
; tsPreviousSelectMode => wrap around to last
|
||
move.w StackFrame.firstValidItem(a6),d3; assume will want to find first <27>
|
||
beq.s @foundIt ; handle zero length list <27>
|
||
tst.w d6 ; d6 = StackFrame.selectMode(a6) <27>
|
||
bgt.s @startSearch ; <27><28>
|
||
moveq #tsPreviousSelectMode,d6 ; force normal to previous in order to get last item<28>
|
||
@findLast move.w StackFrame.lastValidItem(a6),d3 ; assumption wrong, start with last <27>
|
||
@startSearch bsr GetStringFromIndex ; get D3'th item into anItem <27>
|
||
beq.s @foundIt ; if IndexToString returns false, then end of list <27>
|
||
bsr.s NewBestGuess ; use first/last as initial best guess <27>
|
||
; walk entire list finding the lowest (or highest) alphabetically <27>
|
||
move.w StackFrame.firstValidItem(a6),d3; start walking list <27>
|
||
subq.w #1,d3 ; <27>
|
||
@nextWrap addq.w #1,d3 ; next cell index <27>
|
||
cmp.w StackFrame.listSize(a6),d3 ; <27>
|
||
bgt.s @foundIt ; stop at end of list <27>
|
||
bsr GetStringFromIndex ; get D3'th item into anItem <27>
|
||
beq.s @foundIt ; if IndexToString returns false, then at end of list<27>
|
||
tst.l d4 ; d4 = StackFrame.anItemStringPtr(a6) <27>
|
||
beq.s @nextWrap ; if stringPtr is NIL then skip this item <27>
|
||
; see if this cell is better than bestGuess <27>
|
||
; that is, when trying to find first, it is better if cell is less than bestGuess <27>
|
||
subq #2,sp ; room for result <27>
|
||
pea StackFrame.bestGuess(a6) ; <27>
|
||
move.w d5,-(sp) ; d5 = StackFrame.anItemScript(a6) <27>
|
||
move.l d4,-(sp) ; d4 = StackFrame.anItemStringPtr(a6) <27>
|
||
bsr TypeSelectCompare ; <27>
|
||
neg.w (sp) ; want to branch on opposite conditions <27>
|
||
tstBra @nextWrap ; if bounds fails, try next item <27>
|
||
bsr.s NewBestGuess ; this is better than guess, so use it <27>
|
||
bra.s @nextWrap ; <27>
|
||
|
||
@foundIt bsr UnLockIt ; unlock the package
|
||
movem.l (sp)+,a4/d3-d7
|
||
unlk a6
|
||
move.l (sp)+,a0
|
||
add #StackFrame.paramSize,sp
|
||
jmp (a0)
|
||
|
||
|
||
;--------------------------------------
|
||
;
|
||
; Branch according to selectMode.
|
||
;
|
||
; tsPreviousSelectMode => bra if item ≥ type select buffer
|
||
; tsNormalSelectMode => bra if item < type select buffer
|
||
; tsNextSelectMode => bra if item ≤ type select buffer
|
||
;
|
||
;
|
||
; in: 4(sp).w = compare's result
|
||
; a1 = place to branch on success
|
||
;
|
||
; if test passes
|
||
; then pops return address and jumps to a1
|
||
; else returns
|
||
;
|
||
BndBranch move.l (sp)+,a0 ; return address
|
||
move.w (sp)+,d0 ; test result on which to base branch
|
||
neg.w d0
|
||
cmp.w d0,d6 ; d6 = StackFrame.selectMode(a6)
|
||
beq.s @dontBranch
|
||
tst.w d6
|
||
bne.s @branch
|
||
tst.w d0
|
||
bgt.s @dontBranch
|
||
@branch move.l a1,a0 ; force branch
|
||
@dontBranch jmp (a0) ; return
|
||
|
||
|
||
;--------------------------------------
|
||
;
|
||
; in d3.w = cell index
|
||
;
|
||
NewBestGuess move.w d3,StackFrame.result(a6)
|
||
move.w StackFrame.anItemScript(a6),StackFrame.bestGuess.tsrScript(a6)
|
||
move.l d4,d7 ; save off last ptr
|
||
move.l d4,a0 ; source
|
||
lea StackFrame.bestGuess.tsrKeyStrokes(a6),a1 ; destination
|
||
moveq #0,d0
|
||
move.b (a0),d0 ; source string length
|
||
addq #1,d0
|
||
moveq #63,d1
|
||
cmp.b d1,d0 ; no more then 63 chars long
|
||
blt.s @1
|
||
move.b d1,d0
|
||
@1 _BlockMove
|
||
rts
|
||
|
||
|
||
;--------------------------------------
|
||
;
|
||
; in: d3.w = cell index
|
||
;
|
||
GetStringFromIndex subq #2,sp ; Boolean result
|
||
move.w d3,-(sp) ; item: INTEGER
|
||
pea StackFrame.anItemScript(a6) ; VAR itemsScript
|
||
pea StackFrame.anItemStringPtr(a6) ; VAR itemsStringPtr
|
||
move.l StackFrame.yourDataPtr(a6),-(sp) ; yourDataPtr: Ptr;
|
||
move.l StackFrame.getStringProc(a6),a0
|
||
jsr (a0)
|
||
move.l StackFrame.anItemStringPtr(a6),d4 ; d4 = StackFrame.anItemStringPtr(a6)
|
||
move.w StackFrame.anItemScript(a6),d5 ; d5 = StackFrame.anItemScript(a6)
|
||
move.b (sp)+,d0
|
||
rts
|
||
|
||
ENDPROC
|
||
|
||
end ; of file
|