mac-rom/Toolbox/ScriptMgr/RomanUtil.a

913 lines
38 KiB
Plaintext
Raw Normal View History

;
; File: RomanUtil.a
;
; Contains: Character drawing and measurement routines for the Roman script. These routines
; support the Roman script through the ScriptUtil trap.
;
; Written by: JDT Joe Ternasky
; KWK Ken Krugler
; MED Mark Davis
; LDC Lee Collins
; PKE Peter Edberg
; SMB Sue Bartalo
;
; Copyright: <09> 1986-1992 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM4> 11/6/92 SWC Changed PackMacs.a->Packages.a.
; <20> 5/31/92 FM Deleted ParseTable and CharType from this file. They were
; conditionalized forRom. They are no longer needed now that the
; rom build includes ScriptMgrExtensions.a.
; <19> 4/29/92 FM Get rid of conditionals: romanDoSimpleScripts,
; smgrSys7Extensions, smgrROMVers
; <18> 4/22/92 PKE #1027368,<FM>: Make Roman CharType handle the direction bit too
; (so one-byte extension can just call the Roman one, and we will
; use the same format for all one-byte tables). For System builds,
; move it to ptch 27 since we patch it out completely.
; <17> 4/14/92 PKE #1026778,<yds>: To make FindWord not depend on having script
; code passed in d2 (script code will not be in d2 when it is
; called from one-byte extension), change Roman dispatcher to
; replace selector on stack with ScriptRecord pointer, and get
; script code from new scriptID field of ScriptRecord instead of
; from d2. Do this for CharType & Transliterate too. Remove some
; code conditionalized for pre-7.0.
; <16> 4/8/92 PKE #1026515,<cv>: Roman FindWord should not require that itl2 be in
; new format in order to handle custom break tables (passed by
; pointer). Thanks to Hani Abdelazim for noticing this and
; supplying fix.
; <15> 2/13/92 PKE #1021419, Cube-E: Make Roman dispatcher handle nil entries in
; dispatcher table.
; <14> 12/17/91 PKE #1018346: Fix bug introduced in <13>. Call IUGetScriptItl with
; script code passed from ScriptMgr dispatcher, so it works for
; simple scripts too (don't assume script is smRoman).
; <13> 10/8/91 PKE For Cube-E (and Bruges): When getting tables from 'itl2', use
; IUGetScriptItl instead of using IUGetIntl with IntlForce off.
; Part of fix for bug #1013149. Include IntlUtilsPriv.a. Clean up
; some conditionals and remove code that is conditionalized out.
; <12> 7/23/90 PKE For 7.0, move romanDispTable (table of offsets used to
; initialize dispatch table) to end of ScriptMgrInit.a, so it gets
; cut back. Use smgrSixPack instead of $606.
; <11> 5/29/90 PKE NEEDED FOR SIXPACK DISK: Moved ParseTable to ptch 27 so we can
; fix an old unbalanced stack bug in both RAM and ROM versions.
; Stuff a dummy ParseTable vector here; it will be updated by ptch
; 27. All these changes are flagged with <11>.
; <10> 4/10/90 PKE Used smgrSysVers, smgrROMVers, smgrSys7Extensions symbols
; instead of SysVers, buildLevel, and some forRom symbols. Deleted
; conditionalized definitions of SysVers and Scripts604. Started
; organizing for ROMification of 7.0 extensions. Included
; VisibleLength in main proc and exported label; included
; FindScriptRun if it<69>s here. Renamed Roman versions of GetScript
; and SetScript to rGetScript, rSetScript.
; <9> 3/27/90 PKE Missed a couple of places where I should use romanKeepSelector
; conditional.
; <8> 3/26/90 PKE Needed more complicated conditionals around BitBucket and
; BitBucketReg in romanTable.
; <7> 3/21/90 EMT Removed unnecessary ROM85 references and oldMacTweek code.
; <6> 3/21/90 SMB For 7.0, we moved FindScriptRun to ptch 27.
; <5> 3/19/90 PKE Use new feature conditionals smgrUseStdExit,
; smgrUseDispTablePtr, and romanKeepSelector. Rearranged
; RomanScript dispatcher so we can use these conditionals. Deleted
; obsolete definition: if forRom undefined, then forRom equ 0.
; <4> 2/22/90 PKE For 7.0, move Char2Pixel, DrawJust, MeasureJust, and FixSpExtra
; code to ptch 27 (ScriptMgrExtTail.a) so we can make changes in
; ROM too. Used dummy vector for Char2Pixel, DrawJust, MeasureJust
; in RomanUtil table here; ptch 27 will stuff real vector.
; <3> 1/30/90 PKE NEEDED FOR 6.0.5: Changed conditionals so some ROM and System 7
; bug fixes also go in System 6.0.5. (1) Fix for VisibleLength
; when called with a null string. (2) Fix divide by zero problem
; in FixSpExtra.
; <2> 1/11/90 PKE For 7.0, moved PortionText, Pixel2Char to ptch 27 because we
; completely patch out the ROM versions of these routines. Used a
; dummy vector for these routines in RomanUtil table here - ptch
; 27 will stuff the real vector. Also use dummy vectors for Kanji
; private routines and new 7.0 routines - ptch 27 will update the
; vectors for the new routines. Updated header to BBS format and
; fixed up tabs throughout.
; <1> 12/18/89 CCH Adding for the first time into BBS. Changed include 'inc.sum.a'
; to load 'StandardEqu.d'. Updated file name references.
; (BBS versions above, EASE versions below)
; <2.4> 8/26/89 PKE Cleaned up conditionals, changing newItl2Tables to buildLevel >=
; 1. Deleted obsolete itlr stuff (never got built).
; <2.3> 8/24/89 PKE NEEDED FOR 6.0.4 SCRIPTS BUILD, 6.0.5: Conditionalize (2.1).
; Remove some gratuitous conditionals. NOTE: May have to add back
; load 'nEqu.d' when we roll this over to Fiction for SS-6.0.4
; (Scripts) build.
; <2.2> 8/22/89 SES Removed references to nFiles.
; <2.1> 8/21/89 PKE NEEDED FOR 6.0.4 SCRIPTS BUILD, 6.0.5: Change CharType/
; Transliterate/ FindWord to save IntlForce flag then clear it
; before IUGetIntl call, restoring it afterward. This is so we get
; the itl2 tables for the correct script (instead of the tables
; for the system script).
; <2.0> 8/21/89 PKE NEEDED FOR 6.0.4!!: Fix me-too problem with pointer to unlocked
; handle in Transliterate; affects Roman system (this problem
; looks familiar; did I dream that I already fixed this one?).
; <1.9> 6/30/89 PKE NEEDED FOR AURORA AND 6.0.4: Clean up register usage in
; CharType; add some comments (stuff from code review).
; <1.8> 6/23/89 PKE Skip definition of buildLevel (done in ScriptPriv.a).
; <1.7> 6/5/89 PKE Add more error checking after IUGetIntl calls and set related
; error return values (for CharType, Transliterate, FindWord).
; <1.6> 5/30/89 PKE (ROM & 7.0 only) Fix bug in which VisibleLength returns 1 for
; null string (BRC #44640).
; <1.5> 4/26/89 PKE (ROM & 7.0 only) Change RomanUtil to use dispatch tables in RAM,
; accessed through pointer/limits in ScriptRecord.
; <1.4> 3/13/89 PKE Fixed CharType trashing of a2/a3, Transliterate trashing of a4
; (a consequence of the itl2 changes). Oops.
; <1.3> 2/21/89 PKE Replaced with RomProj version, which already had system and Rom
; sources merged.
; (EASE ROMproj history below)
; <1.6> 2/21/89 PKE Get CharType/Transliterate/FindWord tables from itl2, not itlR;
; do this for all new Systems and ROMs. Get rid of itlR. Use
; include 'inc.sum.a' (not inc.sum.src.a), not load 'inc.sum.d'.
; <1.5> 2/14/89 PKE Updated to use MPW 3.0 final ScriptEqu.a equate names
; <1.4> 2/3/89 PKE Merged with current system sources (CCH's 01/16/1989 merge of
; 6.0.3 and 7.0 sources, done in RES.sys:smgr)
; <1.3> 12/1/88 PKE MED fixed divide by zero in FixSpExtra.
; <1.2> 11/14/88 PKE Synchronize EASE and Projector
; <1.1> 11/11/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; (old EASE ROMproj history below)
; <1.6> 10/27/88 LDC Mods by Carl Hewitt and Brian McGhie in the process of putting
; Script Manager in ROM
; (EASE Sysproj history below)
; <1.2> 2/14/89 PKE Updated to use MPW 3.0 final ScriptEqu.a equate names
; <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)
; 4/26/89 pke Export romanTable<6C>
; 2/21/89 pke For ROM and all systems, get CharType/Transliterate/FindWord
; tables from itl2, not itlR or code. Include MED's FixSpExtra fix
; in Sys $700 as well as ROM (it was previously left out of Sys
; $700 for testing source merge). Also change conditionals so that
; if we don't do the new itl2 stuff, we will get the FindWord
; tables from itlR in Sys $700 as well as in the ROM version. Use
; include 'inc.sum.a' (not inc.sum.src.a), not load 'inc.sum.d'.
; 2/2/89 pke Merged system sources and ROM sources
; 11/7/88 med Fixed FixSpExtra divide by zero.
; 10/18/88 ldc Moved word wrap and break tables to itlr.a
; 10/12/88 ldc Removed check for old roms, use inc.sum.src.a
; 7/18/88 ldc Fixed word table to handle character extensions
; 6/15/88 ldc Moved tables for CharType and upper/lower casing to itlr.a.
; Added GetItlr routine to get pointer to itlr.a
; 6/7/88 ldc Added BRA's to StdUnlink and StdExit for romification
; changes above are for ROM or buildLevel >= 2
; 6/6/88 med fixed <20> bug
; 3/21/88 med Minor fix in PortionText intercharacter spacing.
; 3/21/88 med Moved VisibleLength in here
; 1/7/88 med Moved PortionText, FindScriptRun in
; 8/20/87 med Added <letter><number> to words
; 8/20/87 med Removed $a0 from list of blanks
; 8/2/87 med Fixed bug with non-breaking space in FindWord
; 7/31/87 med Fixed CR in middle of blanks in FindWord
; 7/24/87 med Changed CharType table so blank characters have smPunctBlank
; 6/8/87 med Fixed FixSpExtra: add small value to compensate for QD bug, make
; the spExtra value additive.
; 3/6/87 med Added smScriptFlags field and dispatch
; 12/28/86 jdt Removed bug in FixSpExtra where dbra count was trashed.
; 12/25/86 jdt Modified the FixSpExtra routine for performance. It now assumes
; that space characters will outnumber non-space characters, and
; checks for the case where slop is zero.
; 12/22/86 jdt Changed stack frames to include argument sizes. Moved several
; magic numbers into equates. Space improvements in RomanScript,
; CharType, Translit, FindWord, GetScript/SetScript, and
; HiliteText. Speed improvements in Pixel2Char. Added constant for
; last script verb.
; 12/8/86 jdt Modified the dispatch so the ParseTable call is not faked. Added
; Mark's speedup for dispatch (-smGetScript).
; 12/5/86 jdt Cleaned up stack frames and comments. Now use SpaceExtra trap in
; FixSpExtra.
; 11/20/86 jdt Replaced standard equates load.
; 11/16/86 KWK Added ParseTable routine.
; 10/24/86 jdt New ironsides dispatcher can fake falls for unimplemented
; selectors. Yanked extra storage argument from Pixel2Char.
; 10/23/86 jdt Added new storage argument to Pixel2Char.
; 10/7/86 JDT Error check after GetHandleSize should be a long test.
; 9/14/86 JDT Frenzied reorganization to cover up an embarassing assumption
; concerning spExtra. Don't believe anything you hear about it.
; 9/6/86 JDT New GetScript/SetScript interfaces. Added Font2Script stub.
; Installed smScriptMunged verb in table and incremented it in
; SetScript.
; 9/4/86 JDT Added nil FontScript, IntlScript, and KeyScript routines.
; 9/1/86 JDT Fixed bug in simple GetScript routine.
; 8/28/86 JDT Removed Roman KeyHook routine.
; 8/21/86 JDT Broke into script manager and roman utilities files.
;___________________________________________________________________________________________________
; To Do (old):
; Fix bug in Pixel2Char when checking for stack space.
; Speed improvements to FixSpExtra.
; Packing of character type and transliteration tables.
;___________________________________________________________________________________________________
load 'standardequ.d'
include 'ScriptPriv.a'
include 'IntlUtilsPriv.a' ; for IUGetScriptItl <13>
include 'Packages.a' ; To get _IUGetIntl <02/21/89 pke><08/26/89 pke>
import StdUnlink, StdExit ; <6/7/88ldc> for rom
proc
blanks on
string asis
import BitBucket ; <6/7/88ldc> for rom
export RomanPrint
export RomanName
export RomanScript
export rGetScript, rSetScript, CharByte ; <10>
export Translit, FindWord
export HiliteText
export VisibleLength ; <10>
; ----------------------------------------------------------------------------
; function: RomanPrint
; input: d0.l Printer GrafPort.
; d1.w Printer number.
; warning: This routine is register based.
; This routine preserves all registers.
;
; The print action routine for Roman does absolutely nothing, as you might
; expect.
; ----------------------------------------------------------------------------
RomanPrint
rts ; return to the caller.
RomanName
string Pascal
dc.b 'Roman'
align 2
string asis
; ----------------------------------------------------------------------------
; function: RomanScript
; input: (sp).l Routine selector, arguments length, result length.
; warning: This routine is a dispatcher and does not return directly.
; This routine follows Pascal register conventions.
;
; This is the ScriptUtil entry for the Roman Script. The entry uses a
; dispatch table to find the routine offset for this selector. If the
; call is not implemented, we remove the arguments, clear the result, and
; return directly.
;
; Now we assume that the ScriptRecord pointer is in A0 when this is called. <17>
; We will replace the selector on the stack with this value, so that routines
; have access to script-specific information (since they may be called for
; non-Roman scripts). Till now, no Roman routines have depended on having
; any particular value in the selector space.
; Note 1: starting in Bruges, some routines assumed that the script code was in
; the high word of d2; changing to depend on having a ScriptRecord pointer in
; A0 makes an easier interface when Roman routines are called directly by the
; one-byte extension. In both cases, we hope that RomanScript is only called
; by the ScriptMgr or the one-byte extension.
; Note 2: We still want to use the Roman ScriptRecord for dispatching, NOT
; the ScriptRecord whose pointer is in A0.
; ----------------------------------------------------------------------------
RomanScript
with SMgrRecord,ScriptRecord
move.l 4(sp),d0 ; get selector
GetSMgrCore a1 ; set up ptr to SMgrRecord <17>
move.l smgrEntry+(smRoman*4)(a1),a1 ; now set up ptr to Roman ScriptRecord <17>
cmp.w scriptDispHigh(a1),d0 ; selector past max script sys call? <17>
bhi BitBucket ; clean up stack and fake the call <6/7/88ldc>
sub.w scriptDispLow(a1),d0 ; make word offset from table start <17>
add.w d0,d0 ; make a long offset
move.l scriptDispTable(a1),a1 ; get table ptr <17>
move.l 0(a1,d0.w),d0 ; get routine vector from table <15><17>
beq BitBucket ; if nil, bail <15>
move.l a0,4(sp) ; replace selector with ScriptRecord ptr <17>
move.l d0,a0 ; copy vector <15>
jmp (a0) ; now jump to it
endwith ;SMgrRecord,ScriptRecord
; ----------------------------------------------------------------------------
; function: GetScript(script, verb: Integer): LongInt;
; input: (sp).w Script code.
; (sp).w Verb value.
; (sp).l Param pointer.
; output: (sp).l Result, OSErr.
; warning: This routine follows Pascal register conventions.
;
; GetScript reads values from the script entry and returns them.
; ----------------------------------------------------------------------------
; now handled in ScriptUtil
rGetScript ; <10>
rSetScript ; <10>
;<6/7/88ldc> BitBucket removes the return address and selector
bra BitBucket ; clean stack and return
; ----------------------------------------------------------------------------
; function: CharByte(textBuf: Ptr; textOffset: Integer): Integer;
; input: (sp).l Text pointer.
; (sp).w Text offset.
; output: (sp).w Result, character type.
; warning: This routine follows Pascal register conventions.
;
; Return the single byte character result for all characters. Since RIS
; only supports single byte characters, this routine is trivial.
; ----------------------------------------------------------------------------
;<6/7/88ldc> cbArgs equ *-4 = only discount the size of the return, not the
; obsolete a6link
; Cleaned up the conditionalized structure <5>
cbRecord record {return},decr ; used to be {a6link}
result ds.w 1 ; result.
cbArgs equ *-4 ; size of arguments.
textBuf ds.l 1 ; text buffer pointer.
textOffset ds.w 1 ; text buffer offset.
scriptRecPtr ds.l 1 ; Scriptrecord ptr <5><17>
return ds.l 1 ; return address.
;;a6link ds.l 1 ; old a6 register.
;;cbLocals equ * ; size of local variables.
endr
CharByte
with cbRecord
move.w #0,result(sp) ; clear result (stack based!!!)
move.w #cbArgs,d0 ; args to clear
bra StdExit ; exit without unlink
endWith
; ----------------------------------------------------------------------------
; function: Translit(srcHandle,dstHandle: Handle;
; target: Integer; srcMask: Longint): OSErr;
; input: (sp).l Source handle.
; (sp).l Destination handle.
; (sp).w Target.
; (sp).l Source mask.
; output: (sp).w Result, OSErr.
; warning: This routine follows Pascal register conventions.
;
; Transliterate is used only to uppercase or lowercase text under RIS. If
; the target and source masks are legal, the destination handle is sized to
; match the source handle.
; ----------------------------------------------------------------------------
tlRecord record {a6link},decr
result ds.w 1 ; function result.
tlArgs equ *-8 ; size of arguments.
srcHandle ds.l 1 ; srcHandle.
dstHandle ds.l 1 ; dstHandle.
target ds.w 1 ; target.
srcMask ds.l 1 ; srcMask.
scriptRecPtr ds.l 1 ; ScriptRecord pointer <5><17>
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
tlLocals equ * ; size of local variables.
endr
sourceOn equ $0003 ; source bits on.
modifierMask equ $C000 ; case modifiers
transRegs reg d3/a2-a4 ; save regs <03/13/89 pke><08/26/89 pke><10>
; Link the stack and save the registers.
; Note: d2 hi word has a value passed from dispatcher; save it till IUGetScriptItl call <14>
Translit
with tlRecord
link a6,#tlLocals ; link the stack.
movem.l transRegs,-(sp) ; save the registers.
; Assume the error result and check the target, modifiers, and source mask.
; If any of them is wrong, return immediately.
move.l #-1,d0 ; assume error result.
move.l srcMask(a6),d1 ; get the source mask.
and.w #sourceOn,d1 ; isolate ascii and native.
beq transDone ; transliteration not available. <02/21/89 pke><08/26/89 pke><10>
move.w target(a6),d1 ; get the target and modifiers.
move.w d1,d2 ; copy the target and modifiers.
sub.b #1,d1 ; if target not native or ascii,
bgt transDone ; transliteration not available. <02/21/89 pke><08/26/89 pke><10>
sub.b #-2-1,d1 ; check also for general target, -2,-1
blt transDone ; bail if not <02/21/89 pke><08/26/89 pke><10>
move.w #modifierMask,d3 ; now case modifiers
and.w d3,d2 ; remove the target.
cmp.w d3,d2 ; if both modifiers are on,
beq transDone ; transliteration not available. <02/21/89 pke><08/26/89 pke><10>
; Change the size of the destination handle to be the same as the source
; handle. If an error occurs, return immediately.
move.l srcHandle(a6),a1 ; get source handle.
move.l dstHandle(a6),a2 ; get destination handle.
move.l a1,a0 ; get source handle.
_GetHandleSize ; find out how large it is.
tst.l d0 ; if an error occurred,
blt transDone ; return the error code.
move.l d0,d1 ; save the length.
move.l a2,a0 ; get destination handle.
_SetHandleSize ; make it the same length.
tst.w d0 ; if an error occurred,
blt transDone ; return the error code.
; Convert the handles into pointers and determine which of the translation
; tables to use from the target modifiers. If the modifier is to upper
; case, use the upperCase table. If the modifier is to lower case, use
; the lowerCase table. If the modifiers specify neither upper nor lower
; case, so a block move from the source to the destination.
; <02/21/89 pke><08/26/89 pke><10>
movem.l a1/d1-d2,-(sp) ;*save around IUGetIntl <skip a0/d0, 06/05/89 pke>
; skip save/clear of IntlForce <13>
clr.l -(sp) ; space for returned handle
move.w #2,-(sp) ; select itl2
;; clr.w d2 ; sysFlag=0; script code in hi word <14>
;; swap d2 ; put where they belong <14>
move.l scriptRecPtr(a6),a0 ; ScriptRecord ptr (maybe nonRoman) <17>
moveq #0,d2 ; sysFlag=0 in hi word <17>
move.b ScriptRecord.scriptID(a0),d2 ; script code in low word <17>
move.l d2,-(sp) ; two arguments: script code, sysFlag=0 <13><14>
_IUGetScriptItl ; may trash a0,a1,d0-d2 <13>
move.l (sp)+,a4 ; store itl2 handle
; skip restore of IntlForce <13>
movem.l (sp)+,a1/d1-d2 ;*
; move following two dereferences here, after IUGetIntl <2.0> <08/20/89 pke>
move.l (a1),a1 ; get source pointer.
move.l (a2),a2 ; get destination pointer.
moveq #-1,d0 ; assume error result <06/05/89 pke>
move.l a4,d3 ; nil handle? <06/05/89 pke>
beq transDone ; bail if so <06/05/89 pke>
move.l (a4),a4 ; dereference
btst.b #0,itl2FlagsOffset+1(a4) ; extended itl2 tables?
beq.s transDone ; no, bail (special return code?)
clr.l d3 ; wordize <12/16/87med> <move here 06/05/89 pke>
move.l a4,a0 ; copy
clr.l d0 ; <move here 06/05/89 pke>
move.w classArrayOffset(a4),d0 ; longize
add.l d0,a0 ;
move.l a4,a3 ;
move.w upperListOffset(a4),d0 ;
add.l d0,a3 ;
clr.l d0 ; quick fix: do this in case we branch
cmp.w #smTransUpper,d2 ; if mask is transUpper,
beq.s @TransNext ; transliterate to upper case.
move.l a4, a3 ; start from itlr ptr <6/16/88ldc>
move.w lowerListOffset(a4),d0 ;
add.l d0,a3 ;
clr.l d0 ;
cmp.w #smTransLower,d2 ; if mask is transLower,
beq.s @TransNext ; transliterate to lower case.
move.l a1,a0 ; copy the source to the
move.l a2,a1 ; destination without changing
move.l d1,d0 ; the characters.
_BlockMove ;
bra.s transNoErr ; return error code.
@TransLoop
move.b (a1)+,d0 ; get the character.
move.b 0(a0,d0.w),d3 ; get class <12/16/87med>
add.b 0(a3,d3.w),d0 ; delta <12/16/87med>
move.b d0,(a2)+ ; get the transliteration. <12/16/87med>
@TransNext
dbra d1,@TransLoop ; do the next character.
; Return the noErr code.
transNoErr
move.l #noErr,d0 ; return noErr.
; We're all through translating. Store the result code, clean up the
; stack and return to the caller.
transDone
move.w d0,result(a6) ; store the result.
movem.l (sp)+,transRegs ; restore the registers.
; Unlink the stack and return to the caller.
move.w #tlArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endwith
; ----------------------------------------------------------------------------
; function: FindWord(textPtr: Ptr; textLength, offset: Integer;
; leftSide: Boolean; breaks: BreakTable;
; Var offsets: OffsetTable);
; input: (sp).l Text pointer.
; (sp).w Text length.
; (sp).w Text offset.
; (sp).w LeftSide flag.
; (sp).l Table of types and tuples.
; (sp).l Table of offsets.
; warning: This routine follows Pascal register conventions.
;
; Mark decided what he wants to do with this routine, and it is impressive.
; The basic idea is that we are passed a text selection (pointer, length,
; offset, and leftSide flag) and are to find the word selected.
; We return the offsets that mark the endpoints of the word. The return
; offsets are given in an offset table.
; The break table pointer allows the user to override the standard table
; used by the routine. If this parameter is 0, the standard table is used.
; If it is -1, a second table is used for word-wrap type selections. Any
; other value is interpreted as a pointer to new table, which is then used
; by the routine. This table has a specific format, as detailed below.
; ----------------------------------------------------------------------------
fwRecord record {a6link},decr
fwArgs equ *-8 ; size of arguments.
pointer ds.l 1 ; Text pointer.
length ds.w 1 ; Text length.
offset ds.w 1 ; First offset.
left ds.w 1 ; LeftSide flag.
option ds.l 1 ; Optional tuple table.
table ds.l 1 ; array of offsets.
scriptRecPtr ds.l 1 ; ScriptRecord pointer <5><17>
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
fwLocals equ * ; size of local variables.
endr
tupleOffset equ 256 ; breakTable offset to tuples.
; Link the stack and save the registers.
;
; register usage:
; d3.w Left offset.
; d4.w Center offset.
; d5.w Right offset.
; d6.w Current tuple under consideration.
; d7.w Text length.
; a0.l Tuple table copy.
; a1.l Type table pointer.
; a2.l Block record pointer.
; a3.l Text pointer.
; a4.l Tuple table pointer.
; Note: d2 hi word has a value passed from dispatcher; save it till IUGetScriptItl call <14>
FindWord
with fwRecord
link a6,#fwLocals ; link the stack.
movem.l d3-d7/a2-a4,-(sp) ; save the registers.
; Load the registers with the basic parameters.
move.l table(a6),a2 ; get offset array.
move.l pointer(a6),a3 ; get text pointer.
move.w offset(a6),d4 ; get first offset.
move.w length(a6),d7 ; get text length.
; Find the word that has the offset in it and return its limits. First,
; determine the starting offset based on the text offset, length, and
; leftSide flag.
tst.b left(a6) ; if leftSide is false,
bne.s @1 ; subtract one from
sub.w #1,d4 ; the offset.
@1 move.l #0,d3 ; left is zero.
move.l d3,d5 ; right is zero.
tst.w d4 ; if offset < 0,
blt storeOffsets ; return to caller.
move.l d7,d3 ; left is length.
move.l d7,d5 ; right is length.
cmp.w d7,d4 ; if offset >= length,
bge storeOffsets ; return to caller.
; Next, prime all of the registers for the search in both directions. We
; determine here which god-forsaken table the user wants.
FoundOffset
MOVE.L option(A6),D0 ; check for 0 <16>
BEQ.S @UseDefault ; if default word select table, go get it <16>
CMP.L #-1,D0 ; check for -1 <16>
BEQ.S @UseDefault ; if default word wrap table, go get it <16>
MOVE.L D0,A1 ; have pointer to custom table <16>
BRA.S @LoadOffsets ; continue with it <16>
@UseDefault
;; clr.w d2 ; sysFlag=0; script code in hi word <14>
;; swap d2 ; put where they belong <14>
move.l scriptRecPtr(a6),a0 ; ScriptRecord ptr (maybe nonRoman) <17>
moveq #0,d2 ; sysFlag=0 in hi word <17>
move.b ScriptRecord.scriptID(a0),d2 ; script code in low word <17>
clr.l -(sp) ; space for returned handle
move.w #2,-(sp) ; select itl2
move.l d2,-(sp) ; two arguments: script code, sysFlag=0 <13><14>
_IUGetScriptItl ; may trash a0,a1,d0-d2 <13>
move.l (sp)+,a0 ; store itl2 handle
move.l a0,d0 ; nil handle?
beq.s storeOffsets ; bail if so
move.l (a0),a0 ; dereference
btst.b #0,itl2FlagsOffset+1(a0) ; extended itl2 tables?
beq.s storeOffsets ; no, bail (what should we return?)
move.l a0,a1 ; copy
clr.l d0 ; for longizing
move.w wordTableOffset(a0),d0 ; longize
add.l d0,a1 ; get offset
move.l option(a6),d0 ; optional table = 0?
beq.s @LoadOffsets ; yes -> use standard table.
move.l a0,a1 ; copy again
clr.l d0 ; clear again for longizing
move.w wrapTableOffset(a0),d0 ; longize
add.l d0,a1 ;
; we now check for breaks <20> 0 or -1 above, <16>
; don't need to do it here anymore
@LoadOffsets
lea tupleOffset(a1),a4 ; tuples follow char types.
move.w d4,d3 ; start left at center.
move.w d4,d5 ; start right at center - 2.
sub.w #2,d5 ;
; First, check the center tuple to see if we have a word at all. Second,
; search to the right until we come to the end of a word. Third, search
; to the left until we come to the beginning of a word.
FindOffsets
clr.l d6 ; clear the tuple.
bsr.s FindRight ; get left character.
bsr.s FindRight ; get center character.
bsr.s FindRight ; get right character.
bsr.s TupleCenter ; legal center tuple?
bne.s StoreOffsets ; no -> return center.
move.w d6,-(sp) ; save center tuple.
@1 bsr.s FindRight ; get the next character.
bsr.s TupleRight ; if the tuple is good,
beq.s @1 ; continue to the right.
move.w (sp)+,d6 ; fetch center tuple.
sub.w #1,d3 ; left is center - 1.
@2 bsr.s FindLeft ; get the next character.
bsr.s TupleLeft ; if the tuple is good,
beq.s @2 ; continue on the left.
; Adjust the offsets to return the correct string. The right is one past
; its break, and the left is two before its break.
sub.w #1,d5 ; bring right back one.
add.w #2,d3 ; bring left forward two.
; Save the offsets in the offset table. Be sure to clear the two extra
; offset pairs. Restore the registers and return to the caller.
StoreOffsets
move.w d3,(a2)+ ; store the left offset.
move.w d5,(a2)+ ; store the right offset.
clr.l (a2)+ ; clear the second pair.
clr.l (a2) ; clear the third pair.
movem.l (sp)+,d3-d7/a2-a4 ; restore the registers.
; Unlink the stack and return to the caller.
move.w #fwArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
; The following routines are used by the FindWord routine to build and
; categorize the character tuples.
highMask equ $7fff ; mask off high bit.
rightMask equ $ffe0 ; clear right character.
leftMask equ $03ff ; clear left character.
bothMask equ $03e0 ; clear right and left.
nonBreak equ $0020 ; non-breaking center.
; ----------------------------------------------------------------------------
; Increment the right offset and get the next character. Shift its type
; into the current tuple on the right side.
; Note that a right offset which is less than zero or greater than the
; length shifts a wildcard character into the tuple.
FindRight
move.l #0,d0 ; type is wildcard.
add.w #1,d5 ; offset < 0?
blt.s @0 ; yes -> enter a wildcard.
cmp.w d7,d5 ; offset >= length?
bge.s @0 ; yes -> enter a invalid.
move.b 0(a3,d5.w),d0 ; get the character.
move.b 0(a1,d0.w),d0 ; get the character type.
@0 lsl.w #5,d6 ; shift the tuple left.
and.w #highMask,d6 ; clear high bit.
or.b d0,d6 ; or in the character.
rts ; return to the caller.
; Decrement the left offset and get the next character. Shift its type
; into the current tuple on the left side.
; Note that a left offset which is less than zero or greater than the
; length shifts a wildcard character into the tuple.
FindLeft
move.l #0,d0 ; type is wildcard.
sub.w #1,d3 ; left offset < 0?
blt.s @0 ; yes -> enter a wildcard.
cmp.w d7,d3 ; left offset >= length?
bge.s @0 ; yes -> enter a wildcard.
move.b 0(a3,d3.w),d0 ; get the character.
move.b 0(a1,d0),d0 ; get the character type.
@0 and.w #rightMask,d6 ; clear the bottom five bits.
add.w d6,d6 ; place a zero at bit 5.
or.w d0,d6 ; insert new type.
ror.w #6,d6 ; rotate right 6 bits.
rts ; return to the caller.
; ----------------------------------------------------------------------------
; Determine whether a tuple exists or not in the tuple table. The current
; tuple is in d6, and registers d0-d2 and a0 are free for our use. We
; return 'eq' in the cc's if the tuple was found, 'ne' otherwise.
rightAlone equ $001F ; right character
leftAlone equ $7C00 ; left character
rightNB equ $0001 ; non-breaking on right
leftNB equ $0400 ; ditto on left
TupleCenter
bsr.s TupleRight ; try right side <8/2/87med>
beq.s VanillaReturn ; done? <8/2/87med>
move.w d6,d1 ; copy the tuple.
bra.s CommonLeft ; join into left
TupleRight
move.w d6,d1 ; copy the tuple.
bsr.s TupleExacting ; legal tuple?
beq.s VanillaReturn ; yes -> accept immediatly.
andi.w #rightMask,d1 ; right character is wild.
bsr.s TupleExacting ; legal tuple?
beq.s VanillaReturn ; yes -> accept <8/2/87med>
and.w #leftAlone,d1 ; get left char <8/2/87med>
cmp.w #leftNB,d1 ; = non-break? <8/2/87med>
bra.s TestCenter ; check center=wild
TupleLeft
move.w d6,d1 ; copy the tuple.
bsr.s TupleExacting ; legal tuple?
beq.s VanillaReturn ; yes -> accept immediatly.
CommonLeft
andi.w #leftMask,d1 ; left character is wild.
bsr.s TupleExacting ; legal tuple?
beq.s VanillaReturn ; yes -> return immediately. <8/2/87med>
and.w #rightAlone,d1 ; get left char <8/2/87med>
cmp.w #rightNB,d1 ; = non-break? <8/2/87med>
TestCenter
bne.s NonBreaking ; not R or L break, skip center test
move.w d6,d1 ; refresh tuple <8/2/87med>
and.w #bothMask,d1 ; wild center? <8/2/87med>
seq d1 ; reverse CCR <8/2/87med>
tst.b d1 ; cause EQ = center <20> 0 <8/2/87med>
rts ; return to the caller. <8/2/87med>
NonBreaking
move.w d6,d1 ; refresh tuple <8/2/87med>
andi.w #bothMask,d1 ; non-breaking?
cmp.w #nonBreak,d1 ; yes -> accept.
VanillaReturn ; branched Return <8/2/87med>
rts ; return to the caller.
; ----------------------------------------------------------------------------
TupleExacting
move.l a4,a0 ; copy tuple table address.
move.w (a0)+,d0 ; get tuple table length.
@1 cmp.w (a0)+,d1 ; if this is the tuple,
dbeq d0,@1 ; exit the loop.
rts ; return to caller.
endwith
; ----------------------------------------------------------------------------
; function: HiliteText(textPtr: Ptr; textLength, firstOffset,
; secondOffset: Integer; Var offsets: OffsetTable);
; input: (sp).l Text pointer.
; (sp).w Text length.
; (sp).w First offset.
; (sp).w Second offset.
; (sp).l Table of offsets].
; warning: This routine follows Pascal register conventions.
;
; Given two offsets into a text string, this routine returns the part of
; the string that is to be highlighted. For RIS, this is just the original
; offsets.
; ----------------------------------------------------------------------------
htRecord record {a6link},decr
htArgs equ *-8 ; size of arguments.
pointer ds.l 1 ; Text pointer.
length ds.w 1 ; Text length.
first ds.w 1 ; First offset.
second ds.w 1 ; Second offset.
table ds.l 1 ; array of offsets.
scriptRecPtr ds.l 1 ; ScriptRecord pointer <5><17>
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
htLocals equ * ; size of local variables.
endr
HiliteText
with htRecord
link a6,#htLocals ; link the stack.
; Store the default values into the offset table. The first pair is
; the first and second offsets pinned between 0 and the length of the
; string. Note that the following relationship should hold true:
;
; 0 <= firstOffset <= secondOffset <= length
move.l table(a6),a0 ; load table pointer.
move.w length(a6),d1 ; load length.
move.w first(a6),d0 ; load first offset.
bsr.s Normalize ; 0 <= offset <= length.
move.w second(a6),d0 ; load second offset.
bsr.s Normalize ; 0 <= offset <= length.
move.l #0,(a0)+ ; clear second pair.
move.l #0,(a0)+ ; clear third pair.
; Unlink the stack and return to the caller.
move.w #htArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
; Force the offset to be between 0 and the length of the text.
Normalize
bge.s @1 ; >0 -> skip this.
move.l #0,d0 ; set it to zero.
@1 cmp.w d1,d0 ; offset <= length?
ble.s @2 ; yes -> skip this.
move.w d1,d0 ; set it to length.
@2 move.w d0,(a0)+ ; store normal offset.
rts ; return to the caller.
endWith
;____________________________________________________________
; PROCEDURE VisibleLength (
; textPtr : Ptr;
; textLen : Longint
; ): Longint;
;____________________________________________________________
VisibleLengthFrame record {oldA6},decrement
resultSize equ 4
result ds.l 1
argSize equ *-8
textPtr ds.l 1
textLen ds.l 1
scriptRecPtr ds.l 1 ; ScriptRecord pointer <5><17>
return ds.l 1
oldA6 ds.l 1
localFrame equ *
endR
VisibleLength ; <10>
with VisibleLengthFrame
link a6,#localFrame
; init
move.l textPtr(a6),a0 ; ptr to text
move.l a0,d2 ; save for comparison
move.l textLen(a6),d0 ; len
ble.s @StripDone0 ; exit <05/30/89 pke><3><10>
add.l d0,a0 ; get to end
@StripLoop
move.b -(a0),d1 ; get character
beq.s @StripContinue ; null?: continue
cmp.b #32,d1 ; space?
bhi.s @StripDone ; no, and cant be white
beq.s @StripContinue ; white, keep looping
cmp.b #$0D,d1 ; CR?
beq.s @StripContinue ; white, keep looping
cmp.b #$09,d1 ; HT?
bne.s @StripDone ; no, and cant be white
@StripContinue
cmp.w a0,d2 ; at start?
bne.s @StripLoop ; no, continue
clr.l d2 ; no visible text
bra.s @StripExit ; finished
@StripDone
addq.l #1,a0 ; retract one
@StripDone0
sub.l a0,d2 ; subtract current position
neg.l d2 ; fix sign
@StripExit
move.l d2,result(a6) ; return result
CheckA6
; Unlink the stack and return to the caller.
move.w #argSize,d0 ; for std exit
bra StdUnlink ; StdUnlink
endProc
;____________________________________________________________
end