mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-02-05 23:30:14 +00:00
2414 lines
88 KiB
Plaintext
2414 lines
88 KiB
Plaintext
|
;
|
|||
|
; File: ScriptMgrExtensions.a
|
|||
|
;
|
|||
|
; Contains: Extensions to the Script Manager that were formerly in ScriptMgrExtTail.a.
|
|||
|
;
|
|||
|
; Written by: FM Fred Monroe
|
|||
|
; JSM Jeff Miller
|
|||
|
; PKE Peter Edberg
|
|||
|
; HA Hani Abdelazim
|
|||
|
;
|
|||
|
; Copyright: <09> 1992-1993 by Apple Computer, Inc. All rights reserved.
|
|||
|
;
|
|||
|
; Change History (most recent first):
|
|||
|
;
|
|||
|
; <SM8> 5/21/93 CSS Update fixes from Reality per P. Edberg's review:
|
|||
|
; <12> 4/2/93 ngk Fix bug with gestalt routine. It was returning a long instead of
|
|||
|
; a short. This is bad with Pascal calling conventions.
|
|||
|
; <SM7> 11/19/92 RB When looking for the standard Chicago font, look in ROM first.
|
|||
|
; <SM6> 11/6/92 SWC Changed PackMacs.a->Packages.a.
|
|||
|
; <SM5> 10/27/92 CSS Changed short branch to word branch.
|
|||
|
; <10> 7/6/92 HA ##1034403 <PKE>: Fixed bug in StyledLineBreak, now I made sure
|
|||
|
; to return the correct offset when the (text buffer ends with a
|
|||
|
; carriage return) AND (textStart parameter is > 0 ) AND the whole
|
|||
|
; text fits in the line pixel width) .
|
|||
|
; <9> 6/22/92 PKE #1032408 <amw>: <+ csd>: Move check for presence of bidi &
|
|||
|
; 2-byte scripts to be after call to ScriptAvail vector.
|
|||
|
; <8> 6/17/92 HA #1029756,<PKE>: #1032724 <YS> : Fixed CharType to return correct
|
|||
|
; results when offset is > 256. #1029756 <PKE> moved here the new
|
|||
|
; StyledLineBreak (and FindCarriage) from ScriptMgrUtilText.a, so
|
|||
|
; the new routine will be included in ptch 27.
|
|||
|
; <7> 6/5/92 PKE #1031797 <csd>: Add option-space to prevent enabling of all
|
|||
|
; scripts except primary & roman
|
|||
|
; <6> 5/31/92 FM Add entry point StdExit for call by the ROM build. There was a
|
|||
|
; duplicate of this code in another file. The only difference was
|
|||
|
; this added label.
|
|||
|
; <5> 5/18/92 PKE #1028382,<jh>: InitScripts should not enable a script if it has
|
|||
|
; no fonts. If the specified system font is not present but other
|
|||
|
; fonts in the script range are, use one of them.
|
|||
|
; <4> 5/14/92 PKE #1029395,<bbm>: Move glue for generic FindScriptRun from Roman
|
|||
|
; script to Script Mgr dispatcher so scripts get it for free; we
|
|||
|
; only come to romanFindScriptRun if a new-format table does not
|
|||
|
; exist. Move new FindScriptTable record to ScriptPriv.a, where it
|
|||
|
; belongs.
|
|||
|
; <3> 5/8/92 PKE #1029395,<KST>: Fix FindScriptRun for non-Roman simple scripts
|
|||
|
; to handle "shared" characters (space, punctuation) contextually.
|
|||
|
; Also fix it to get the correct itl2.
|
|||
|
; <2> 4/28/92 JSM Move almost all resident code from ScriptMgrExtTail.a here.
|
|||
|
; Slightly modified the LwrString routine by changing the name of
|
|||
|
; the entry point to NewLwrString so we could keep the weird
|
|||
|
; come-from patch back in ScriptMgrExtTail.a where it belongs.
|
|||
|
; This file has no conditionals (yay!).
|
|||
|
; <1> 4/28/92 JSM first checked in
|
|||
|
;
|
|||
|
|
|||
|
blanks on
|
|||
|
string asis
|
|||
|
|
|||
|
LOAD 'StandardEqu.d'
|
|||
|
include 'ScriptPriv.a'
|
|||
|
include 'Packages.a'
|
|||
|
include 'IntlUtilsPriv.a'
|
|||
|
include 'GestaltEqu.a'
|
|||
|
|
|||
|
; ----------------------------------------------------------------------- <1.4>
|
|||
|
; Gestalt function
|
|||
|
;
|
|||
|
|
|||
|
proc
|
|||
|
import StdUnlink
|
|||
|
export gestaltScriptMgr,gestaltSMgrTable
|
|||
|
|
|||
|
;____________________________________________________________
|
|||
|
; The following Gestalt Function is an interface between the Gestalt mechanism
|
|||
|
; and the Script Manager's GetEnvirons routine. Currently, it only supports two
|
|||
|
; Gestalt selectors: gestaltScriptMgrVersion and gestaltScriptCount.
|
|||
|
;
|
|||
|
; Routine gestaltScriptMgr (
|
|||
|
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
|||
|
; VAR gestaltResult: Longint;
|
|||
|
; ): OSErr; = Integer;
|
|||
|
;
|
|||
|
; <08/05/89 pke> New today
|
|||
|
;____________________________________________________________
|
|||
|
|
|||
|
gestaltSMgrFrame record {oldA6},decrement
|
|||
|
result ds.w 1 ; OSErr
|
|||
|
argSize equ *-8
|
|||
|
gestaltSelector ds.l 1 ; packed array [1..4] of char
|
|||
|
gestaltResult ds.l 1 ; addr of longint result
|
|||
|
return ds.l 1
|
|||
|
oldA6 ds.l 1
|
|||
|
localFrame equ *
|
|||
|
endR
|
|||
|
;____________________________________________________________
|
|||
|
|
|||
|
gestaltScriptMgr
|
|||
|
|
|||
|
with gestaltSMgrFrame
|
|||
|
link a6,#localFrame
|
|||
|
|
|||
|
; initialize loop, set up default return values
|
|||
|
move.l gestaltSelector(a6),d0 ; selector value
|
|||
|
move.w #gestaltUndefSelectorErr,result(a6) ; assume unknown selector <12>
|
|||
|
lea gestaltSMgrTable,a1
|
|||
|
|
|||
|
; loop to find Gestalt selector in table
|
|||
|
@gestaltLoop
|
|||
|
move.l (a1)+,d1 ; get next table entry
|
|||
|
beq.s @gestaltDone ; end of list, quit
|
|||
|
move.w (a1)+,d2 ; now get GetEnvirons verb
|
|||
|
cmp.l d0,d1 ; is selector correct?
|
|||
|
bne.s @gestaltLoop ; no, get next one
|
|||
|
|
|||
|
; ok, we found the Gestalt selector. Now call GetEnvirons with correct verb
|
|||
|
clr.l -(sp) ; space for result
|
|||
|
move.w d2,-(sp) ; push verb
|
|||
|
_GetEnvirons
|
|||
|
move.l gestaltResult(a6),a0 ; addr for result
|
|||
|
move.l (sp)+,(a0) ; pop result into Gestalt
|
|||
|
move.w #noErr,result(a6) ; return no error
|
|||
|
; all done
|
|||
|
@gestaltDone
|
|||
|
|
|||
|
move.w #argSize, d0 ; for StdUnlink
|
|||
|
bra StdUnlink ; standard exit
|
|||
|
endWith
|
|||
|
|
|||
|
; Table for converting between gestalt selectors and GetEnvirons verbs. Each pair
|
|||
|
; consists of a long with the gestalt selector, followed by a word with the
|
|||
|
; GetEnvirons verb. This table and the equate files where the Gestalt selectors
|
|||
|
; are defined are the only things that need to change to add new Gestalt selectors
|
|||
|
; for the Script Manager.
|
|||
|
|
|||
|
gestaltSMgrTable
|
|||
|
dc.l gestaltScriptMgrVersion
|
|||
|
dc.w smVersion
|
|||
|
|
|||
|
dc.l gestaltScriptCount
|
|||
|
dc.w smEnabled
|
|||
|
|
|||
|
dc.l 0 ; terminator
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
|
|||
|
; ---------------------------------------------------------------------------- <45>
|
|||
|
; function: PrintAction
|
|||
|
; input: d0.l Printer GrafPort.
|
|||
|
; d1.w Printer number.
|
|||
|
; warning: This routine is register based.
|
|||
|
;
|
|||
|
; The script manager print action routine calls the print action routines
|
|||
|
; of each script that is currently installed. These private print action
|
|||
|
; routines should preserve all of the registers.
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
proc
|
|||
|
export PrintAction
|
|||
|
|
|||
|
; Save the registers and load a pointer to the list of script entries in the
|
|||
|
; script manager globals. Load the script manager count so we will step
|
|||
|
; through all of the scripts.
|
|||
|
;
|
|||
|
; register usage:
|
|||
|
; a4.l Script Manager globals, script entry table.
|
|||
|
; a3.l Script Interface System entry pointer.
|
|||
|
; d4.l Count of script entries.
|
|||
|
|
|||
|
PrintAction
|
|||
|
with smgrRecord,scriptRecord ;
|
|||
|
movem.l a0-a6/d0-d7,-(sp) ; save all registers.
|
|||
|
GetSMgrCore a4 ; load SMgr pointer.
|
|||
|
lea smgrEntry(a4),a4 ; load entry table address.
|
|||
|
move.w #smgrCount,d4 ; get the count.
|
|||
|
bra.s @2 ; enter loop at bottom.
|
|||
|
|
|||
|
; Check the next script system to see if it is installed. If so, load call
|
|||
|
; the printer action routine. A pointer to the routine is kept in the
|
|||
|
; script entry record.
|
|||
|
|
|||
|
@1 move.l (a4)+,d3 ; entry pointer = nil?
|
|||
|
beq.s @2 ; yes -> try the next script.
|
|||
|
move.l d3,a3 ; load entry pointer.
|
|||
|
tst.b scriptEnabled(a3) ; script disabled?
|
|||
|
beq.s @2 ; yes -> try the next script.
|
|||
|
move.l scriptPrint(a3),d3 ; action pointer = nil?
|
|||
|
beq.s @2 ; yes -> try the next script.
|
|||
|
move.l a3,a0 ; pass ScriptRecord pointer to script <45>
|
|||
|
move.l d3,a3 ; load action pointer.
|
|||
|
movem.l a4/d0-d4,-(sp) ; save used registers.
|
|||
|
jsr (a3) ; call the routine.
|
|||
|
movem.l (sp)+,a4/d0-d4 ; restore used registers.
|
|||
|
@2 dbra d4,@1 ; try the next one.
|
|||
|
|
|||
|
; Restore the registers and return to the caller.
|
|||
|
|
|||
|
movem.l (sp)+,a0-a6/d0-d7 ; restore all registers.
|
|||
|
rts ; return to the caller.
|
|||
|
endwith ;smgrRecord,scriptRecord
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
; ---------------------------------------------------------------------------- <8>
|
|||
|
; Function FindScriptRun (
|
|||
|
; textPtr: Ptr;
|
|||
|
; textLen: Longint;
|
|||
|
; var lenUsed: Longint
|
|||
|
; ): Integer;
|
|||
|
;
|
|||
|
; Find a block of text. Very simple for Roman!
|
|||
|
; Modified to use itl2 tables for simple scripts (single-byte,non-Roman)
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
proc
|
|||
|
export FindScriptRun
|
|||
|
|
|||
|
FScript record {oldA6},decr
|
|||
|
Result ds.w 1 ; result of the function
|
|||
|
ParamStart equ *
|
|||
|
TextPtr ds.l 1 ; Pointer
|
|||
|
Length ds.l 1 ; length of the text
|
|||
|
LenUsedPtr ds.l 1 ; Length use
|
|||
|
scriptRecPtr ds.l 1 ; Scriptrecord ptr
|
|||
|
ParamEnd equ *
|
|||
|
Return ds.l 1 ;
|
|||
|
oldA6 ds.l 1
|
|||
|
FScriptFrame equ *
|
|||
|
endr
|
|||
|
|
|||
|
FindScriptRun
|
|||
|
WITH ScriptRecord,FScript ; <3>
|
|||
|
link a6,#FScriptFrame ; now link always <3>
|
|||
|
clr.w Result(a6) ; initialize to script Roman, variant zero <3>
|
|||
|
|
|||
|
move.l Length(a6),d1 ; check length <3>
|
|||
|
bpl.s @goodLength ; if negative, <3>
|
|||
|
moveq #0,d1 ; fix it <3>
|
|||
|
@goodLength
|
|||
|
move.l LenUsedPtr(a6),a0 ; LenUsedPtr is the address <3>
|
|||
|
move.l d1,(a0) ; initialize lenUsed to textLen <3>
|
|||
|
|
|||
|
move.l scriptRecPtr(a6),a0 ; get script pointer <3>
|
|||
|
moveq #0,d0 ; for word-izing <3>
|
|||
|
move.b scriptID(a0),d0 ; what script are we really handling? <3>
|
|||
|
beq @doneRoman ; if Roman, done, go unlink & return <3>
|
|||
|
|
|||
|
move.b d0,Result(a6) ; initialize to real script, variant 0 <3>
|
|||
|
tst.l d1 ; any length? <3>
|
|||
|
beq @doneRoman ; if not, bail now <3>
|
|||
|
|
|||
|
; Now use GetScriptItl <3>
|
|||
|
subq #4,sp ; make room for the itl handle.
|
|||
|
move.w #2,-(sp) ; push 'which' argument => itl2.
|
|||
|
move.w d0,-(sp) ; push ScriptCode
|
|||
|
move.w #-1,-(sp) ; push sysFlag as TRUE
|
|||
|
_IUGetScriptItl ; get itl handle
|
|||
|
move.l (sp)+,d0 ; pop handle (null if err)
|
|||
|
beq.s @doneRoman ; bail if none
|
|||
|
|
|||
|
move.l d0,a1 ; get handle
|
|||
|
move.l (a1),a1 ; get pointer
|
|||
|
move.w findScriptTableOffset(a1),d0 ; get offset to table
|
|||
|
beq.s @doneRoman ; bail if no table
|
|||
|
tst.w findScriptTableLen(a1) ; check table length
|
|||
|
beq.s @doneRoman ; bail if null
|
|||
|
add.w d0,a1 ; make pointer to table
|
|||
|
|
|||
|
; Now we assume old format; new format would have been picked up by glue in <4>
|
|||
|
; Script Mgr dispatcher.
|
|||
|
|
|||
|
@oldFormat
|
|||
|
move.l a2,-(sp) ; <3>
|
|||
|
|
|||
|
move.l Length(a6),d0 ; text length to d0
|
|||
|
|
|||
|
move.l a1,a2 ; working table ptr in a1, saved in a2 <31++><3>
|
|||
|
move.l TextPtr(a6),a0 ; text pointer to a0
|
|||
|
move.b (a0)+,d1 ; get character
|
|||
|
bra.s @JmpIn1
|
|||
|
|
|||
|
; get initial script!
|
|||
|
@InitScriptLoop
|
|||
|
addq #1,a1
|
|||
|
@JmpIn1
|
|||
|
cmp.b (a1)+,d1
|
|||
|
bhi.s @InitScriptLoop ; not in this script range <31>
|
|||
|
move.b (a1),d2 ; save initial script of this text
|
|||
|
move.b d2,result(a6) ; and return it to caller in hi byte of word ; sub 1 to zero base for the dbne below
|
|||
|
|
|||
|
; a2 = ptr to FindScriptTable
|
|||
|
; a0 = textPtr
|
|||
|
; d0.l = textLen
|
|||
|
; d2 = script of the first byte of the textPtr
|
|||
|
|
|||
|
; now search for script run boundary
|
|||
|
@TextLoop
|
|||
|
sub.l #1,d0 ; update textLen beyond processed char <31+>
|
|||
|
beq.s @noMoreText ; <31+>
|
|||
|
move.l a2,a1 ; reset ptr to FindScriptTable <31++>
|
|||
|
move.b (a0)+,d1 ; get character
|
|||
|
bra.s @JmpIn2
|
|||
|
@RangeLoop
|
|||
|
addq #1,a1
|
|||
|
@JmpIn2
|
|||
|
cmp.b (a1)+,d1 ; cmp to char range & incr to script #
|
|||
|
bhi.s @RangeLoop ; not in this script range <31>
|
|||
|
|
|||
|
; found range of character
|
|||
|
cmp.b (a1),d2 ; are the scripts the same <31+>
|
|||
|
beq.s @TextLoop ; yep, so branch (can't use dbne since d0 is long) <31+>
|
|||
|
|
|||
|
@noMoreText
|
|||
|
; found a script boundary
|
|||
|
move.l LenUsedPtr(a6),a0 ; LenUsedPtr is the address
|
|||
|
sub.l d0,(a0) ; contains initial length
|
|||
|
@done
|
|||
|
move.l (sp)+,a2 ; <3>
|
|||
|
|
|||
|
@doneRoman
|
|||
|
unlk a6
|
|||
|
move.l (sp)+,a1 ; get return address
|
|||
|
add.w #ParamStart-ParamEnd,sp ; remove parameters from stack
|
|||
|
jmp (a1) ; return
|
|||
|
|
|||
|
endwith ;ScriptRecord,FScript
|
|||
|
endproc
|
|||
|
|
|||
|
; ---------------------------------------------------------------------------- <18>
|
|||
|
; function: ParseTable(tablePtr: Ptr): Boolean;
|
|||
|
; input: (sp).l Pointer to parse table.
|
|||
|
; output: (sp).w Table validity flag.
|
|||
|
; warning: This routine follows pascal register conventions.
|
|||
|
;
|
|||
|
; ParseTable fills the given table with values for parsing characters in the
|
|||
|
; Roman script.
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
proc ; <18>
|
|||
|
export ParseTable ; <18>
|
|||
|
import StdUnlink ; <18>
|
|||
|
|
|||
|
ptRecord record {oldA6},decr
|
|||
|
result ds.w 1 ; validity flag.
|
|||
|
ptArgs equ *-8 ; size of args. BUG FIX: Moved this AFTER result. <18>
|
|||
|
table ds.l 1 ; parse table pointer.
|
|||
|
selector ds.l 1 ; selector
|
|||
|
return ds.l 1 ; return address.
|
|||
|
oldA6 ds.l 1 ; old link address.
|
|||
|
ptLocals equ * ; size of local variables.
|
|||
|
endr
|
|||
|
|
|||
|
; Link the stack and set the result to true. Since Roman characters are all
|
|||
|
; one byte long, all we have to do is clear the parse table.
|
|||
|
|
|||
|
ParseTable
|
|||
|
with ptRecord
|
|||
|
link a6,#ptLocals ; set up stack frame.
|
|||
|
move.w #$0100,result(a6) ; set result to true.
|
|||
|
move.l table(a6),a0 ; load table pointer.
|
|||
|
move.w #256-1,d0 ; load table length - 1.
|
|||
|
@0 clr.b (a0)+ ; clear a byte in the table.
|
|||
|
dbra d0,@0 ; do the next entry.
|
|||
|
|
|||
|
; Unlink the stack and return to the caller.
|
|||
|
|
|||
|
move.w #ptArgs,d0 ; for std exit
|
|||
|
bra StdUnlink ; StdUnlink
|
|||
|
endWith
|
|||
|
|
|||
|
endproc ; <18>
|
|||
|
|
|||
|
;------------------------------------------------------------------------ <14>
|
|||
|
; FUNCTION InitScripts: OSErr;
|
|||
|
;------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; InitScripts routine calls FixSMgrWorld and then handles new
|
|||
|
; initializations that must be done after script systems are installed
|
|||
|
; and enabled.
|
|||
|
;
|
|||
|
; These initializations set up the emItlSysCache sort cache (with entries <15>
|
|||
|
; for each script in correct sorting order), and the emScriptMap and
|
|||
|
; emLangMap tables that map script (lang) to sorting position and default
|
|||
|
; lang (script).
|
|||
|
;
|
|||
|
; KillOldFixWorldVec is just an rts whose address we can stuff in the
|
|||
|
; old sVectFixSMgrWorld vector to render it inactive.
|
|||
|
;
|
|||
|
|
|||
|
proc
|
|||
|
export InitScripts, KillOldFixWorldVec
|
|||
|
import StdUnlink
|
|||
|
|
|||
|
disabCacheReq equ -2 ; disable cache request in CurFMInput <26>
|
|||
|
|
|||
|
isFrame record {a6link},decr
|
|||
|
result ds.w 1 ; OSErr result code.
|
|||
|
isArgs equ *-8 ; size of arguments.
|
|||
|
selector ds.l 1 ; selector
|
|||
|
return ds.l 1 ; return address.
|
|||
|
a6link ds.l 1 ; old a6
|
|||
|
saveItlcSysFlag ds.w 1 ; save sysflags from itlc <7>
|
|||
|
saveOldISOkeybd ds.b 1 ; Mac Plus ISO keybd flag <7>
|
|||
|
disabAuxScripts ds.b 1 ; T to enable only system & Roman script <7>
|
|||
|
isLocals equ *
|
|||
|
endr
|
|||
|
|
|||
|
isRegs reg d3-d7/a2-a4 ; save all regs
|
|||
|
|
|||
|
InitScripts
|
|||
|
with SMgrRecord,isFrame,ExpandMemRec ;
|
|||
|
link a6,#isLocals ; link the stack.
|
|||
|
movem.l isRegs,-(sp) ; save regs
|
|||
|
|
|||
|
; ---------------------------------------------------------------------------- <26>
|
|||
|
; The first batch of stuff is mostly a copy of the old FixSMgrWorld routine,
|
|||
|
; enhanced to (1) get the RegionCode from itlc, (2) copy and check the extended
|
|||
|
; itlb font and style info if present. It no longer detaches the itlc.
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
FixSMgrWorld
|
|||
|
|
|||
|
with smgrRecord ;
|
|||
|
GetSmgrCore a4 ; get script manager core.
|
|||
|
|
|||
|
; Install the keyboard swapping table from the system file. If we get a nil
|
|||
|
; handle back, we store the nil value in the script manager globals anyway.
|
|||
|
; This effectively disables keyboard swapping.
|
|||
|
|
|||
|
sub.l #4,sp ; make room for handle.
|
|||
|
move.l #'KSWP',-(sp) ; push KSWP type.
|
|||
|
move.w #0,-(sp) ; push KSWP id number.
|
|||
|
_GetResource ; get the KSWP resource.
|
|||
|
move.l (sp)+,smgrKeySwap(a4) ; store handle in SMgr globals.
|
|||
|
|
|||
|
; Load the configuration resource and set the system and
|
|||
|
; keyboard script numbers in the script manager globals.
|
|||
|
; Moved this after enabling all installed scripts. <37>
|
|||
|
; Moved back here <7>
|
|||
|
|
|||
|
; Currently we don't touch the following fields in SMgrRecord, which
|
|||
|
; are set from itlc only in ScriptMgrInit.a; should we reset them here?
|
|||
|
; smgrFontForce from itlcFontForce
|
|||
|
; smgrIntlForce from itlcIntlForce
|
|||
|
; smgrGenFlags from itlcFlags high byte
|
|||
|
|
|||
|
clr.w saveItlcSysFlag(a6) ; set to 0 if we can't get 'itlc' <7>
|
|||
|
clr.b saveOldISOkeybd(a6) ; set to 0 if we can't get 'itlc' <7>
|
|||
|
|
|||
|
with itlcRecord
|
|||
|
sub.w #4,sp ; make room for handle.
|
|||
|
move.l #'itlc',-(sp) ; push conf type.
|
|||
|
move.w #0,-(sp) ; push conf number.
|
|||
|
_GetResource ; load the resource.
|
|||
|
move.l (sp)+,d0 ; handle = nil?
|
|||
|
beq.s @doneItlc ; yes -> skip this.
|
|||
|
move.l d0,a0 ; load conf handle.
|
|||
|
move.l (a0),a0 ; load conf pointer.
|
|||
|
|
|||
|
move.w itlcSystem(a0),d1 ; load system code.
|
|||
|
move.w d1,smgrSysScript(a4) ; set system script.
|
|||
|
move.w d1,smgrKeyScript(a4) ; set key script.
|
|||
|
|
|||
|
move.w itlcRegionCode(a0),d1 ; get preferred region code. <26>
|
|||
|
move.w d1,smgrRegionCode(a4) ; save in globals <26>
|
|||
|
|
|||
|
move.w itlcSysFlags(a0),saveItlcSysFlag(a6) ; save system flags <7>
|
|||
|
move.b itlcOldKybd(a0),saveOldISOkeybd(a6) ; save Mac Plus ISO flag <7>
|
|||
|
|
|||
|
endWith ;itlcRecord
|
|||
|
@doneItlc
|
|||
|
|
|||
|
; Check for Option-space to prevent enabling of scripts other than system <7>
|
|||
|
; script & Roman
|
|||
|
; Masks for word at KeyMap+6:
|
|||
|
ClearCapsLock equ $FFFD ; and with this to ignore CapsLock <7>
|
|||
|
NormalOptSpace equ $0204 ; bits set for Opt & Space on reg kybd <7>
|
|||
|
MacPlusISOOptSp equ $1004 ; bits set for Opt & Space on Mac+ ISO <7>
|
|||
|
|
|||
|
move.w KeyMap+6,d0 ; get state of modifiers, space, etc <7>
|
|||
|
and.w #ClearCapsLock,d0 ; ignore Caps Lock <7>
|
|||
|
move.w #NormalOptSpace,d1 ; setup desired bit state <7>
|
|||
|
cmp.b #3,KbdType ; is it a 128K/512K-type mini keyboard? <7>
|
|||
|
bne.s @doCompare ; if not, we're ready to check bits <7>
|
|||
|
tst.b saveOldISOkeybd(a6) ; is it the ISO version? <7>
|
|||
|
beq.s @doCompare ; if not, we're ready to check bits <7>
|
|||
|
move.w #MacPlusISOOptSp,d1 ; else desired bit state is different <7>
|
|||
|
@doCompare ; <7>
|
|||
|
cmp.w d1,d0 ; Do we have Opt-Space & nothing else? <7>
|
|||
|
seq disabAuxScripts(a6) ; if so, set disable flag <7>
|
|||
|
|
|||
|
|
|||
|
; Fetch the script bundle for each installed script and copy the bundle
|
|||
|
; information into the script entry. If we cannot find a bundle for a
|
|||
|
; script, it is disabled. Notice that at least one bundle must be found
|
|||
|
; for an installed script in order for the script manager to be enabled.
|
|||
|
|
|||
|
with ScriptRecord
|
|||
|
sf smgrEnabled(a4) ; clear the enabled counter.
|
|||
|
move.w #smgrCount-1,d3 ; forall entries.
|
|||
|
@scriptLoop
|
|||
|
move.w d3,d0 ; copy index.
|
|||
|
lsl.w #2,d0 ; long word offset.
|
|||
|
move.l smgrEntry(a4,d0.w),d0 ; script installed?
|
|||
|
beq @nextScript ; no -> try next entry.
|
|||
|
|
|||
|
move.l d0,a3 ; load script entry.
|
|||
|
sf scriptEnabled(a3) ; disable this entry.
|
|||
|
|
|||
|
; check for disabling key combo <7>
|
|||
|
tst.w d3 ; is it Roman? <7>
|
|||
|
beq.s @dontDisable ; if so, don't disable <7>
|
|||
|
cmp.w smgrSysScript(a4),d3 ; is it system? <7>
|
|||
|
beq.s @dontDisable ; if so, don't disable <7>
|
|||
|
tst.b disabAuxScripts(a6) ; are we disabling others? <7>
|
|||
|
bne @nextScript ; if so, we're outta here <7>
|
|||
|
@dontDisable
|
|||
|
|
|||
|
sub.l #4,sp ; make room for handle.
|
|||
|
move.l #'itlb',-(sp) ; push bundle type.
|
|||
|
move.w d3,-(sp) ; push bundle number.
|
|||
|
_GetResource ; load the resource.
|
|||
|
move.l (sp)+,d0 ; handle = nil?
|
|||
|
beq @nextScript ; yes -> try next entry.
|
|||
|
|
|||
|
with ItlbRecord
|
|||
|
move.l d0,a2 ; load bundle handle.
|
|||
|
move.l (a2),a0 ; load bundle pointer.
|
|||
|
lea scriptBundle(a3),a1 ; load script pointer.
|
|||
|
move.l #itlbSize,d0 ; load size of bundle.
|
|||
|
_BlockMove ; copy bundle into script.
|
|||
|
endwith ;ItlbRecord
|
|||
|
|
|||
|
move.b d3,scriptID(a3) ; put script code in ScriptRecord <52>
|
|||
|
|
|||
|
; Now see if we have an extended bundle, and if so, copy font info <26>
|
|||
|
|
|||
|
with ItlbExtRecord
|
|||
|
subq #4,sp ; space for SizeRsrc result
|
|||
|
move.l a2,-(sp) ; push 'itlb' handle
|
|||
|
_SizeRsrc
|
|||
|
cmp.l #itlbExtSize,(sp)+ ; is itlb size big enough
|
|||
|
blt @doneExtItlb ; skip if too small or res err
|
|||
|
move.l (a2),a0 ; get itlb pointer
|
|||
|
move.l itlbMonoFond(a0),scriptMonoFondSize(a3) ; set the mono font.
|
|||
|
move.l itlbPrefFond(a0),scriptPrefFondSize(a3) ; set the font.
|
|||
|
move.l itlbSmallFond(a0),scriptSmallFondSize(a3) ; set the font.
|
|||
|
move.l itlbSysFond(a0),scriptSysFondSize(a3) ; set the font.
|
|||
|
move.l itlbAppFond(a0),scriptAppFondSize(a3) ; set the font.
|
|||
|
move.l itlbHelpFond(a0),scriptHelpFondSize(a3) ; set the font.
|
|||
|
move.b itlbValidStyles(a0),scriptValidStyles(a3) ; set valid styles
|
|||
|
move.b itlbAliasStyle(a0),scriptAliasStyle(a3) ; set alias style
|
|||
|
endwith ;ItlbExtRecord
|
|||
|
|
|||
|
; Done with bundle, now do some checking. <26>
|
|||
|
; First, if this is Roman, do some funky testing for sys fond ID.
|
|||
|
; If Chicago $3FFF is present, it becomes the Roman sys font.
|
|||
|
; If not, try the itlb value. If this also isn't present, assume
|
|||
|
; 0 is the Roman sys FOND ID.
|
|||
|
|
|||
|
clr.b ResLoad ; don't bother loading fonts (move here) <5>
|
|||
|
tst.w d3 ; is this Roman?
|
|||
|
bne.s @nonRoman ; if not, different check <5>
|
|||
|
|
|||
|
move.w #RomanSysFond,d4 ; assume fond $3FFF exists
|
|||
|
bsr.s @returnIfNotFound ; set if found, return if not <5>
|
|||
|
|
|||
|
move.w scriptSysFondSize(a3),d4 ; try itlb value <5>
|
|||
|
bsr.s @returnIfNotFound ; set if found, return if not <5>
|
|||
|
|
|||
|
clr.w d4 ; otherwise, reset to 0
|
|||
|
bra.s @setSysFondId ; <5>
|
|||
|
|
|||
|
@nonRoman
|
|||
|
; check that itlb system font ID is there <5>
|
|||
|
move.w scriptSysFondSize(a3),d4 ; try itlb value
|
|||
|
bsr.s @returnIfNotFound ; set if found, return if not
|
|||
|
|
|||
|
; if not, try itlb app font ID <5>
|
|||
|
move.w scriptAppFondSize(a3),d4 ; try itlb value
|
|||
|
bsr.s @returnIfNotFound ; set if found, return if not
|
|||
|
|
|||
|
; specified font not there; use first font in range <5>
|
|||
|
subq #4,sp ; space for result
|
|||
|
move.w d3,-(sp) ; push ScriptCode (explicit code works at this point in boot)
|
|||
|
_ScriptToRange ; map it
|
|||
|
move.l (sp)+,d4 ; min in high word, max in low
|
|||
|
move.w d4,d5
|
|||
|
swap d4 ; min in d4.w, max in d5.w
|
|||
|
@fontLoop
|
|||
|
bsr.s @returnIfNotFound ; set if found, return if not
|
|||
|
addq.w #1,d4
|
|||
|
cmp.w d5,d4 ; past end of range?
|
|||
|
ble.s @fontLoop ; if not, check next
|
|||
|
bra.s @nextScript ; else no fonts found, don't enable
|
|||
|
|
|||
|
; this routine expects FOND ID in d4. If found, it pops return addr and <5>
|
|||
|
; falls through to set system font to the value in d4. Otherwise, it
|
|||
|
; returns to the caller.
|
|||
|
@returnIfNotFound
|
|||
|
subq #4,sp ; space for return value
|
|||
|
move.l #'FOND',-(sp) ; push type
|
|||
|
move.w d4,-(sp) ; push next id in range
|
|||
|
MOVE.W #MapTrue,RomMapInsert ; look in ROM first <SM7> rb
|
|||
|
_GetResource
|
|||
|
tst.l (sp)+ ; was it there?
|
|||
|
bne.s @popRetnAndSetSysFondId ; if yes, go reset
|
|||
|
rts
|
|||
|
@popRetnAndSetSysFondId
|
|||
|
addq #4,sp ; discard return addr
|
|||
|
|
|||
|
@setSysFondId ; <5>
|
|||
|
move.w d4,scriptSysFondSize(a3) ; reset the system font. <5>
|
|||
|
|
|||
|
|
|||
|
; now check non-sys fonts and copy font IDs to old fields <26>
|
|||
|
|
|||
|
move.w scriptSysFondSize(a3),scriptSysFond(a3) ; copy sys fond to old field
|
|||
|
lea scriptAppFondSize(a3),a0
|
|||
|
bsr FixFond ; resets to sys fond if bad
|
|||
|
move.w scriptAppFondSize(a3),scriptAppFond(a3) ; copy app fond to old field
|
|||
|
lea scriptMonoFondSize(a3),a0 ; top word is fond id
|
|||
|
bsr FixFond ; resets to sys fond if bad
|
|||
|
lea scriptPrefFondSize(a3),a0 ; top word is fond id
|
|||
|
bsr FixFond ; resets to sys fond if bad
|
|||
|
lea scriptSmallFondSize(a3),a0 ; top word is fond id
|
|||
|
bsr FixFond ; resets to sys fond if bad
|
|||
|
lea scriptHelpFondSize(a3),a0 ; top word is fond id
|
|||
|
bsr FixFond ; resets to sys fond if bad
|
|||
|
|
|||
|
@doneExtItlb
|
|||
|
|
|||
|
st scriptEnabled(a3) ; enable this entry.
|
|||
|
add.b #1,smgrEnabled(a4) ; enable the script manager.
|
|||
|
|
|||
|
; moved scriptRedraw check down after call to ScriptAvail <9>
|
|||
|
|
|||
|
@nextScript
|
|||
|
move.b #1,ResLoad ; reset ResLoad (move here) <5>
|
|||
|
dbra d3,@scriptLoop ; do the next entry.
|
|||
|
endWith ;ScriptRecord
|
|||
|
|
|||
|
; (Load the configuration resource and set the system and
|
|||
|
; keyboard script numbers in the script manager globals.)
|
|||
|
; Moved this here from above, so we can make decisions based on <37>
|
|||
|
; enabled scripts. <37>
|
|||
|
; Moved back above to get keyboard flag earlier, but keep decisions <7>
|
|||
|
; here.
|
|||
|
;
|
|||
|
|
|||
|
moveq #0,d0 ; assume L->R <37>
|
|||
|
tst.w saveItlcSysFlag(a6) ; check system flags <37><7>
|
|||
|
bpl.s @doneSysFlags ; if config is L->R, don't change <37>
|
|||
|
cmpi.w #1,smgrEnabled(a4) ; how many scripts? <37>
|
|||
|
ble.s @doneSysFlags ; if Roman only, don't change <37>
|
|||
|
moveq #-1,d0 ; else R->L <37>
|
|||
|
@doneSysFlags ; <37>
|
|||
|
move.w d0,TESysJust ; set direction <37>
|
|||
|
|
|||
|
; If the current system script is not installed, or is installed but not
|
|||
|
; enabled, default the system and key scripts to Roman.
|
|||
|
|
|||
|
with scriptRecord
|
|||
|
move.w smgrSysScript(a4),d3 ; load system script code.
|
|||
|
move.w d3,d0 ; copy system script code.
|
|||
|
lsl.w #2,d0 ; code is long word index.
|
|||
|
move.l smgrEntry(a4,d0.w),d0 ; system script installed?
|
|||
|
beq.s @useRoman ; no -> use Roman.
|
|||
|
move.l d0,a3 ; load system script entry.
|
|||
|
tst.b scriptEnabled(a3) ; system script enabled?
|
|||
|
bne.s @doneCheckSysScript ; yes -> keep system script.
|
|||
|
@useRoman
|
|||
|
move.l #smRoman,d3 ; script is Roman.
|
|||
|
move.l smgrEntry(a4),a3 ; load Roman script entry.
|
|||
|
move.w d3,smgrSysScript(a4) ; reset system script.
|
|||
|
move.w d3,smgrKeyScript(a4) ; reset keyboard script.
|
|||
|
endWith ;scriptRecord
|
|||
|
@doneCheckSysScript
|
|||
|
|
|||
|
; Set the system font according to the system script. If the application
|
|||
|
; font is not in the system script's range, then reset it as well.
|
|||
|
; Note that we expect the system script code in d3 and its entry in a3.
|
|||
|
; Also, we have SMgrRecord pointer in a4.
|
|||
|
|
|||
|
with scriptRecord
|
|||
|
|
|||
|
; Now we just set it ; <41>
|
|||
|
|
|||
|
move.w scriptSysFond(a3),d0 ; get desired system font. <41>
|
|||
|
cmp.w SysFontFam,d0 ; already set up? <41>
|
|||
|
beq.s @SkipSFontSet ; yes -> skip resetting. <41>
|
|||
|
move.w d0,SysFontFam ; set desired system font. <41>
|
|||
|
move.w #disabCacheReq,CurFMInput ; disable cache request <41>
|
|||
|
@SkipSFontSet
|
|||
|
|
|||
|
move.w scriptAppFond(a3),d0 ; get desired application font. <41>
|
|||
|
cmp.w ApFontID,d0 ; already set up? <41>
|
|||
|
beq.s @SkipAFontSet ; yes -> skip resetting. <41>
|
|||
|
move.w d0,ApFontID ; set desired application font. <41>
|
|||
|
move.w #disabCacheReq,CurFMInput ; disable cache request <41>
|
|||
|
@SkipAFontSet
|
|||
|
|
|||
|
; Load the keyboard character table for the new system script. If this fails,
|
|||
|
; we are left with the current KCHR resource in the cache.
|
|||
|
|
|||
|
move.w smgrKeyScript(a4),-(sp) ; push current keyboard script. <16jun87 jdt>
|
|||
|
_KeyScript ; load appropriate KCHR. <16jun87 jdt>
|
|||
|
|
|||
|
; Save the new boot driver number. This prevents us from executing all of
|
|||
|
; the above code during a vanilla-launch.
|
|||
|
|
|||
|
move.w BootDrive,smgrSysRef(a4) ; save vRefNum in globals.
|
|||
|
|
|||
|
endWith ; ScriptRecord
|
|||
|
endWith ; SMgrRecord ; <x3.1>
|
|||
|
|
|||
|
EndFixSMgrWorld
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
; Set up regs we'll need
|
|||
|
move.l IntlSpec,a3 ; SMgrRecord ptr
|
|||
|
move.l ExpandMem,a4 ; ExpandMemRec ptr
|
|||
|
|
|||
|
; Initialize ItlSysCache
|
|||
|
with NewItlCacheRec
|
|||
|
moveq #0,d0 ; for wordizing smgrEnabled
|
|||
|
move.b smgrEnabled(a3),d0 ; how many scripts installed?
|
|||
|
move.w d0,d3 ; save copy
|
|||
|
mulu.w #newItlCacheRecSize,d0 ; one record per script
|
|||
|
addq.l #2,d0 ; space for record count
|
|||
|
_NewPtr sys,clear ; make a0 point to new space
|
|||
|
bne @doneInitScripts ; bail if error (errcode in d0)
|
|||
|
move.l a0,emItlSysCachePtr(a4) ; save pointer
|
|||
|
move.w d3,(a0)+ ; put in record count
|
|||
|
move.l a0,a2 ; save for later use
|
|||
|
endwith ;NewItlCacheRec
|
|||
|
|
|||
|
; Get 'itlm' resource
|
|||
|
subq #4,sp ; space for returned handle
|
|||
|
move.l #'itlm',-(sp) ; resource type
|
|||
|
clr.w -(sp) ; resource ID
|
|||
|
_GetResource
|
|||
|
move.l (sp)+,d7 ; check handle, save in d7
|
|||
|
beq @resError ; special handling for rmgr errs
|
|||
|
move.l d7,a0 ; copy handle
|
|||
|
move.l (a0),d6 ; dereference, save in d6
|
|||
|
_HLock ; "can't have error here"
|
|||
|
|
|||
|
; Next, put script codes in emItlSysCache in proper sort order
|
|||
|
with ItlmHeaderRec,ScriptRecord,NewItlCacheRec
|
|||
|
move.l d6,a1 ; copy pointer
|
|||
|
add.l scriptDataOffset(a1),a1 ; point to scriptData table
|
|||
|
addq #4,a1 ; skip to num entries
|
|||
|
move.w (a1)+,d3 ; get num entries in 'itlm' table
|
|||
|
; have emItlSysCachePtr in a2 from above
|
|||
|
move.w smgrSysScript(a3),d2 ; get system script
|
|||
|
move.w d2,(a2) ; system script always comes first
|
|||
|
lsl.w #2,d2 ; make it a long offset
|
|||
|
move.l smgrEntry(a3,d2.w),a0 ; get scriptRecord ptr for sys script
|
|||
|
st scriptInItlm(a0) ; remember that script has 'itlm' entry
|
|||
|
bra.s @nextEntry ; test for d3=0, decrement it for dbra
|
|||
|
@sysCacheLoop
|
|||
|
move.w (a1)+,d2 ; get next script code in 'itlm'
|
|||
|
addq #2,a1 ; skip default lang value
|
|||
|
cmp.w smgrSysScript(a3),d2 ; is it system script?
|
|||
|
beq.s @nextEntry ; if so, we handled it above
|
|||
|
move.w d2,d1 ; copy for shift
|
|||
|
lsl.w #2,d1 ; make a long offset
|
|||
|
move.l smgrEntry(a3,d1.w),d0 ; get scriptRecord ptr
|
|||
|
beq.s @nextEntry ; if none, script not installed
|
|||
|
move.l d0,a0
|
|||
|
tst.b scriptEnabled(a0) ; is script enabled?
|
|||
|
beq.s @nextEntry ; if not, really give up.
|
|||
|
st scriptInItlm(a0) ; remember that script has 'itlm' entry
|
|||
|
add.w #newItlCacheRecSize,a2 ; now go to next emItlSysCache entry
|
|||
|
move.w d2,(a2) ; put script code in emItlSysCache entry
|
|||
|
@nextEntry
|
|||
|
dbra d3,@sysCacheLoop
|
|||
|
|
|||
|
; Now, go through installed & enabled scripts and add any that were not in 'itlm'.
|
|||
|
move.w #smgrCount-1,d3 ; for all possible scripts<74>
|
|||
|
moveq #0,d2 ; current script
|
|||
|
move.w #0,d4 ; keep track of max script code for<6F>
|
|||
|
; <20>inst. & enab. scripts
|
|||
|
lea smgrEntry(a3),a1 ; pointer to current entry in SMgrRecord
|
|||
|
@scriptLoop
|
|||
|
move.l (a1)+,d0 ; get scriptRecord ptr
|
|||
|
beq.s @nextScript ; if none, script not installed
|
|||
|
move.l d0,a0
|
|||
|
tst.b scriptEnabled(a0) ; is script enabled?
|
|||
|
beq.s @nextScript ; if not, really give up.
|
|||
|
move.w d2,d4 ; keep max inst & enab script code so far
|
|||
|
tst.b scriptInItlm(a0) ; have we already put this in emItlSysCache?
|
|||
|
bne.s @nextScript ; skip if so
|
|||
|
add.w #newItlCacheRecSize,a2 ; otherwise go to next emItlSysCache entry
|
|||
|
move.w d2,(a2) ; put script code in emItlSysCache entry
|
|||
|
@nextScript
|
|||
|
addq.w #1,d2 ; next script
|
|||
|
dbra d3,@scriptLoop
|
|||
|
endwith ;ItlmHeaderRec,ScriptRecord,NewItlCacheRec
|
|||
|
|
|||
|
; Now emItlSysCache is set up, and d4 has max script code for an installed & enabled
|
|||
|
; script.
|
|||
|
|
|||
|
; Next, allocate space for scriptData and fill it header entries
|
|||
|
with ItlmHeaderRec,NewItlCacheRec
|
|||
|
move.l d6,a1 ; copy pointer
|
|||
|
add.l scriptDataOffset(a1),a1 ; point to scriptData table
|
|||
|
move.w (a1)+,d5 ; get max script for table
|
|||
|
cmp.w d4,d5 ; is it big enough?
|
|||
|
bge.s @bigEnough ; if so, ok so far
|
|||
|
move.w d4,d5 ; if not, make it big enough
|
|||
|
@bigEnough
|
|||
|
lea emScriptMapPtr(a4),a2 ; say where to save ptr
|
|||
|
|
|||
|
; Allocate map table, put pointer in ExpandMem, copy header from itlm,
|
|||
|
; advance pointer, set some registers with values from header, and fill in
|
|||
|
; default values.
|
|||
|
;
|
|||
|
; Scripts with real entries will replace the default values. Scripts that
|
|||
|
; are not installed and enabled are sorted after everything else in order
|
|||
|
; of script number, by adding a base value to their script code. They get
|
|||
|
; the default lang code.
|
|||
|
|
|||
|
bsr SetHdrAndDefaults
|
|||
|
bne @unlockThenDone ; bail if can't allocate space
|
|||
|
|
|||
|
; Now fill in sort positions obtained from sort order in emItlSysCache
|
|||
|
moveq #0,d2 ; sort position count
|
|||
|
move.l emItlSysCachePtr(a4),a0 ; get emItlSysCache ptr
|
|||
|
move.w (a0)+,d3 ; get count of enab scripts
|
|||
|
bra.s @nextSort
|
|||
|
@sortLoop
|
|||
|
move.w (a0),d1 ; get next script code, in order
|
|||
|
lsl.w #2,d1 ; make a long offset
|
|||
|
move.w d2,0(a2,d1.w) ; set data in table
|
|||
|
addq.w #1,d2 ; next sort position
|
|||
|
add.w #newItlCacheRecSize,a0 ; now go to next emItlSysCache entry
|
|||
|
@nextSort
|
|||
|
dbra d3,@sortLoop
|
|||
|
|
|||
|
; And fill in lang codes obtained from 'itlm'.
|
|||
|
bra.s @nextScriptLang
|
|||
|
@scriptLangLoop
|
|||
|
move.w (a1)+,d1 ; get script code
|
|||
|
move.w (a1)+,d2 ; get lang code
|
|||
|
cmp.w d5,d1 ; too big?
|
|||
|
bgt.s @nextScriptLang ; skip if so
|
|||
|
lsl.w #2,d1 ; make a long offset
|
|||
|
move.w d2,2(a2,d1.w) ; stuff lang code
|
|||
|
@nextScriptLang
|
|||
|
dbra d4,@scriptLangLoop
|
|||
|
endwith ;ItlmHeaderRec,NewItlCacheRec
|
|||
|
|
|||
|
; Almost done: allocate space for langData and fill in header info.
|
|||
|
with ItlmHeaderRec
|
|||
|
move.l d6,a1 ; copy pointer
|
|||
|
add.l langDataOffset(a1),a1 ; point to langData table
|
|||
|
move.w (a1)+,d5 ; get max lang for table
|
|||
|
lea emLangMapPtr(a4),a2 ; say where to save ptr
|
|||
|
|
|||
|
; Allocate map table, put pointer in ExpandMem, copy header from itlm,
|
|||
|
; advance pointer, set some registers with values from header, and fill in
|
|||
|
; default values.
|
|||
|
;
|
|||
|
; Langs with real entries will replace the default values. Langs that
|
|||
|
; are not in 'itlm' are sorted after everything else in order of lang
|
|||
|
; code, by adding a base value to their lang code. They get the default
|
|||
|
; script code.
|
|||
|
|
|||
|
bsr SetHdrAndDefaults
|
|||
|
bne @unlockThenDone ; bail if can't allocate space
|
|||
|
|
|||
|
; Now just fill in sort positions obtained from 'itlm'. This is much
|
|||
|
; simpler than what we did with script codes.
|
|||
|
|
|||
|
moveq #0,d3 ; sort position
|
|||
|
bra.s @nextLang
|
|||
|
@langLoop
|
|||
|
move.l (a1)+,d2 ; get lang code & script
|
|||
|
swap d2 ; get lang code
|
|||
|
cmp.w d5,d2 ; too big?
|
|||
|
bgt.s @nextLang ; skip if so
|
|||
|
move.w d2,d1
|
|||
|
lsl.w #2,d1 ; make a long offset
|
|||
|
move.w d3,d2 ; stuff sort position
|
|||
|
swap d2 ; put everything in its place
|
|||
|
move.l d2,(a2,d1.w) ; stuff lang code
|
|||
|
addq.w #1,d3 ; update sort position count
|
|||
|
@nextLang
|
|||
|
dbra d4,@langLoop
|
|||
|
endwith ;ItlmHeaderRec
|
|||
|
|
|||
|
; Now go through all installed & enabled scripts, loading the 'itl2' and <26>
|
|||
|
; 'itl4' resource IDs & handles into the system itl cache, and calling the
|
|||
|
; script<70>s scriptAvail vector if non-zero.
|
|||
|
; At this point, a4 still points to ExpandMemRec, a3 points to SMgrRecord.
|
|||
|
|
|||
|
with ScriptRecord
|
|||
|
move.l emItlSysCachePtr(a4),a4 ; get emItlSysCache ptr
|
|||
|
move.w (a4)+,d7 ; number of enabled scripts
|
|||
|
bra.s @nextCopy ; dbra, so decrement d7
|
|||
|
@copyLoop
|
|||
|
move.w (a4)+,d6 ; get script code
|
|||
|
move.w d6,d0 ; copy it
|
|||
|
lsl.w #2,d0 ; make it a long offset
|
|||
|
move.l smgrEntry(a3,d0.w),a2 ; and get scriptRecord ptr
|
|||
|
; we already know script is enabled
|
|||
|
;; sub #8,sp ; space for 2 GetResource results <55>
|
|||
|
|
|||
|
with ItlbRecord
|
|||
|
move.w scriptBundle.itlbSort(a2),d0 ; get itl2 ID
|
|||
|
move.w d0,(a4)+ ; save ID in cache
|
|||
|
;; move.l #'itl2',-(sp) ; push type <55>
|
|||
|
;; move.w d0,-(sp) ; push ID <55>
|
|||
|
;; _GetResource ; <55>
|
|||
|
;; move.l (sp)+,(a4)+ ; save handle in cache (even if 0) <55>
|
|||
|
clr.l (a4)+ ; don't save a handle <55>
|
|||
|
|
|||
|
move.w scriptBundle.itlbToken(a2),d0 ; get itl4 ID
|
|||
|
move.w d0,(a4)+ ; save ID in cache
|
|||
|
;; move.l #'itl4',-(sp) ; push type <55>
|
|||
|
;; move.w d0,-(sp) ; push ID <55>
|
|||
|
;; _GetResource ; <55>
|
|||
|
;; move.l (sp)+,(a4)+ ; save handle in cache (even if 0) <55>
|
|||
|
clr.l (a4)+ ; don't save a handle <55>
|
|||
|
endwith ;ItlbRecord
|
|||
|
|
|||
|
; now call ScriptAvail
|
|||
|
|
|||
|
move.l scriptAvail(a2),d0 ; check script's Avail vector
|
|||
|
beq.s @checkRedraw ; if none, finish up this script <9>
|
|||
|
move.l d0,a0 ; otherwise<73>
|
|||
|
move.w d6,-(sp) ; <20>push script code<64>
|
|||
|
jsr (a0) ; <20>and call script<70>s Avail routine
|
|||
|
|
|||
|
; Set smgrBidirect and smgrDoubleByte if appropriate (moved here from above) <37><9>
|
|||
|
@checkRedraw ; <9>
|
|||
|
tst.b scriptRedraw(a2) ; what kind of script is it? <37><9>*
|
|||
|
beq.s @doneCheckRedraw ; if redraw char, L->R 1-byte, done <37><9>
|
|||
|
bpl.s @setDouble ; if redraw word, 2-byte <37><9>
|
|||
|
st smgrBidirect(a3) ; else redraw line, bidi sys <37><9>*
|
|||
|
bra.s @doneCheckRedraw ; <37><9>
|
|||
|
@setDouble ; <37><9>
|
|||
|
st smgrDoubleByte(a3) ; <37><9>*
|
|||
|
@doneCheckRedraw ; <37><9>
|
|||
|
|
|||
|
@nextCopy
|
|||
|
dbra d7,@copyLoop ; loop for all enabled scripts
|
|||
|
endwith ;ScriptRecord
|
|||
|
|
|||
|
; If we got to here, no errors
|
|||
|
moveq #0,d0 ; return noErr
|
|||
|
|
|||
|
; Set result and return
|
|||
|
@doneInitScripts
|
|||
|
move.w d0,result(a6) ; return error code or noErr
|
|||
|
movem.l (sp)+,isRegs ; restore regs
|
|||
|
move.w #isArgs,d0 ; for StdUnlink
|
|||
|
bra StdUnlink ; standard exit
|
|||
|
|
|||
|
@resError
|
|||
|
move.w ResErr,d0 ; get current resource err code
|
|||
|
bne.s @doneInitScripts
|
|||
|
move.w #resNotFound,d0 ; some errs leave ResErr as 0
|
|||
|
bra.s @doneInitScripts
|
|||
|
@unlockThenDone
|
|||
|
move.w d0,d6 ; save errcode across HUnlock
|
|||
|
move.l d7,a0 ; get handle
|
|||
|
_HUnlock
|
|||
|
move.w d6,d0 ; restore errcode
|
|||
|
bra.s @doneInitScripts
|
|||
|
endwith ;SMgrRecord,isFrame,ExpandMemRec
|
|||
|
|
|||
|
;--------
|
|||
|
; This utility routine allocates a block of memory for scriptMap or langMap,
|
|||
|
; copies header information from the 'itlm' resource, fills in the table with
|
|||
|
; default values, and sets up various registers.
|
|||
|
;
|
|||
|
; At entry:
|
|||
|
; d5 max script or lang value for map table. WILL NOT BE CHANGED.
|
|||
|
; a2 pointer to ExpandMemRec field for map table ptr. WILL BE REPLACED.
|
|||
|
; a1 pointer to beginning of scriptData or langData table in 'itlm'.
|
|||
|
; WILL BE ADVANCED PAST HEADER.
|
|||
|
;
|
|||
|
; At exit:
|
|||
|
; d0 OSErr
|
|||
|
; a1 pointer to scriptData or langdata data (past header).
|
|||
|
; a2 pointer to map table data (past header, which has been filled in).
|
|||
|
; d4 num entries in 'itlm' table
|
|||
|
;
|
|||
|
; Besides the above, uses: a0,d3,d2,d1
|
|||
|
;--------
|
|||
|
|
|||
|
SetHdrAndDefaults
|
|||
|
move.w d5,d0
|
|||
|
addq.w #2,d0 ; add script 0 and header entry
|
|||
|
lsl.w #2,d0 ; get size (one long per entry)
|
|||
|
_NewPtr sys,clear ; OS trap, saves a1,d1-d2
|
|||
|
bne.s @exit ; bail if error (errcode in d0)
|
|||
|
move.l a0,(a2) ; save ptr
|
|||
|
move.w (a1)+,d3 ; get default lang/script code
|
|||
|
move.w (a1)+,d4 ; get num entries in 'itlm' table
|
|||
|
move.w d5,(a0)+
|
|||
|
move.w d3,(a0)+
|
|||
|
move.l a0,a2 ; save pointer to data to fill in
|
|||
|
|
|||
|
; Fill in default values for everything.
|
|||
|
move.w d5,d2
|
|||
|
clr.w d0 ; current script/lang code
|
|||
|
move.w #$1000,d1 ; base sort pos for bad scripts/langs
|
|||
|
@initLoop
|
|||
|
move.b d0,d1 ; make base + script/lang
|
|||
|
move.w d1,(a0)+ ; and put it in table
|
|||
|
move.w d3,(a0)+ ; put in default lang/script code
|
|||
|
addq.w #1,d0 ; next script/lang code
|
|||
|
dbra d2,@initLoop
|
|||
|
|
|||
|
moveq #0,d0 ; no error
|
|||
|
@exit
|
|||
|
rts
|
|||
|
|
|||
|
; -----------------------------------------------------------------------------
|
|||
|
; Utility routine to check for FOND & reset if bad
|
|||
|
; Input (a0): fond id
|
|||
|
; a3: ptr to script globals <47>
|
|||
|
;
|
|||
|
; Don't manipulate ResLoad here, now done at higher level <5>
|
|||
|
; -----------------------------------------------------------------------------
|
|||
|
FixFond
|
|||
|
with ScriptRecord
|
|||
|
movem.l a2,-(sp) ; don't trash a2 <47>
|
|||
|
move.l a0,a2 ; remember pointer to fond id in a2 <47>
|
|||
|
subq #4,sp ; return room
|
|||
|
move.l #'FOND',-(sp) ; see if this FOND exists
|
|||
|
move.w (a2),-(sp) ; id, get the id from a2 pointer <47>
|
|||
|
MOVE.W #MapTrue,RomMapInsert ; look in ROM first <SM7> rb
|
|||
|
_GetResource
|
|||
|
tst.l (sp)+ ; was it there?
|
|||
|
bne.s @fixFondDone ; yes, ok
|
|||
|
move.w scriptSysFond(a3),(a2) ; reset to system fond, changed to used a3 as pointer to script globals <47>
|
|||
|
@fixFondDone
|
|||
|
movem.l (sp)+,a2 ; restore a2
|
|||
|
rts
|
|||
|
endwith
|
|||
|
|
|||
|
; -----------------------------------------------------------------------------
|
|||
|
; Convenient rts; this address will be stuffed in obsolete vectors
|
|||
|
|
|||
|
KillOldFixWorldVec
|
|||
|
rts
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
;------------------------------------------------------------------------ <32>
|
|||
|
; FUNCTION ReInitScripts: OSErr;
|
|||
|
;------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; ReInitScripts frees all of the structures set up by InitScripts, then
|
|||
|
; redoes the parts of installation that must be performed with a new
|
|||
|
; system file: setting fields from itlc, setting up a KCHR, and then
|
|||
|
; calling InitScripts again.
|
|||
|
;
|
|||
|
|
|||
|
proc
|
|||
|
export ReInitScripts
|
|||
|
import StdUnlink
|
|||
|
|
|||
|
risFrame record {a6link},decr
|
|||
|
result ds.w 1 ; OSErr result code.
|
|||
|
risArgs equ *-8 ; size of arguments.
|
|||
|
selector ds.l 1 ; selector
|
|||
|
return ds.l 1 ; return address.
|
|||
|
a6link ds.l 1 ; old a6
|
|||
|
risLocals equ *
|
|||
|
endr
|
|||
|
|
|||
|
risRegs reg d3-d7/a2-a4 ; save all regs
|
|||
|
|
|||
|
ReInitScripts
|
|||
|
with risFrame,ExpandMemRec
|
|||
|
link a6,#risLocals ; link the stack.
|
|||
|
movem.l risRegs,-(sp) ; save regs
|
|||
|
|
|||
|
; dispose of caches whose size depended on resources in old system file
|
|||
|
|
|||
|
move.l ExpandMem,a1 ; ExpandMemRec ptr
|
|||
|
moveq #0,d1
|
|||
|
|
|||
|
move.l emItlSysCachePtr(a1),a0
|
|||
|
_DisposPtr
|
|||
|
move.l d1,emItlSysCachePtr(a1)
|
|||
|
|
|||
|
move.l emScriptMapPtr(a1),a0
|
|||
|
_DisposPtr
|
|||
|
move.l d1,emScriptMapPtr(a1)
|
|||
|
|
|||
|
move.l emLangMapPtr(a1),a0
|
|||
|
_DisposPtr
|
|||
|
move.l d1,emLangMapPtr(a1)
|
|||
|
|
|||
|
; Call _InitScripts and get any errors from it
|
|||
|
|
|||
|
subq #2,sp ; make room for OSErr result
|
|||
|
_InitScripts ;
|
|||
|
move.w (sp)+,d0 ; get result in d0
|
|||
|
|
|||
|
; Set result and return
|
|||
|
@doneReInitScripts
|
|||
|
move.w d0,result(a6) ; return error code or noErr
|
|||
|
movem.l (sp)+,risRegs ; restore regs
|
|||
|
move.w #risArgs,d0 ; for StdUnlink
|
|||
|
bra StdUnlink ; standard exit
|
|||
|
endwith ;risFrame,ExpandMemRec
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
;------------------------------------------------------------------------ <16>
|
|||
|
; FUNCTION AddScriptFonts: OSErr;
|
|||
|
;------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; AddScriptFonts loops through all enabled script systems, checks the
|
|||
|
; script's AddFonts vector, and calls the routine at that vector (if
|
|||
|
; non-zero) to load additional fonts over the network (or do other
|
|||
|
; post-initialization).
|
|||
|
;
|
|||
|
|
|||
|
proc
|
|||
|
export AddScriptFonts
|
|||
|
import StdUnlink
|
|||
|
|
|||
|
asfFrame record {a6link},decr
|
|||
|
result ds.w 1 ; OSErr result code.
|
|||
|
asfArgs equ *-8 ; size of arguments.
|
|||
|
selector ds.l 1 ; selector
|
|||
|
return ds.l 1 ; return address.
|
|||
|
a6link ds.l 1 ; old a6
|
|||
|
asfLocals equ *
|
|||
|
endr
|
|||
|
|
|||
|
asRegs reg a2-a3/d3 ; regs to save
|
|||
|
|
|||
|
AddScriptFonts
|
|||
|
with asfFrame,ExpandMemRec,NewItlCacheRec,SMgrRecord,ScriptRecord
|
|||
|
link a6,#asfLocals ; link the stack.
|
|||
|
movem.l asRegs,-(sp) ; save regs
|
|||
|
|
|||
|
move.l IntlSpec,a3 ; GetSMgrRecord pointer
|
|||
|
move.l ExpandMem,a2 ; get ExpandMemRec ptr
|
|||
|
move.l emItlSysCachePtr(a2),a2 ; get sys itl cache ptr
|
|||
|
move.w (a2)+,d3 ; get count of enabled scripts
|
|||
|
bra.s @nextAddFont ; enter loop at end
|
|||
|
@addFontLoop
|
|||
|
move.w (a2)+,d1 ; get next script code
|
|||
|
add #newItlCacheRecSize-2,a2 ; advance to next cache entry
|
|||
|
move.w d1,d0 ; copy script code
|
|||
|
lsl.w #2,d0 ; make a long offset
|
|||
|
move.l smgrEntry(a3,d0.w),a0 ; get ScriptRecord ptr, know it's enabled
|
|||
|
move.l scriptAddFonts(a0),d0 ; check script's AddFonts vector
|
|||
|
beq.s @nextAddFont ; if none, skip to next script
|
|||
|
move.l d0,a0 ; otherwise<73>
|
|||
|
move.w d1,-(sp) ; <20>push script code<64>
|
|||
|
jsr (a0) ; <20>and call script<70>s AddFonts routine
|
|||
|
@nextAddFont
|
|||
|
dbra d3,@addFontLoop
|
|||
|
|
|||
|
move.w #noErr,result(a6) ; return noErr
|
|||
|
movem.l (sp)+,asRegs ; restore regs
|
|||
|
move.w #asfArgs,d0 ; for StdUnlink
|
|||
|
bra StdUnlink ; standard exit
|
|||
|
endwith ;asfFrame,ExpandMemRec,NewItlCacheRec,SMgrRecord,ScriptRecord
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
;------------------------------------------------------------------------ <27>
|
|||
|
; FUNCTION InitScriptApp: OSErr;
|
|||
|
;------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; InitScriptApp initializes the application-specific Script Mgr globals,
|
|||
|
; which are allocated in the app heap.
|
|||
|
; So far, these just contain the application itl2/4 cache and some reserved
|
|||
|
; fields. The code to initialize the cache was moved from InternationalPACK.a.
|
|||
|
;
|
|||
|
|
|||
|
proc
|
|||
|
export InitScriptApp
|
|||
|
import StdUnlink
|
|||
|
|
|||
|
isaFrame record {a6link},decr
|
|||
|
result ds.w 1 ; OSErr result code.
|
|||
|
isaArgs equ *-8 ; size of arguments.
|
|||
|
selector ds.l 1 ; selector
|
|||
|
return ds.l 1 ; return address.
|
|||
|
a6link ds.l 1 ; old a6
|
|||
|
isaLocals equ *
|
|||
|
endr
|
|||
|
|
|||
|
isaRegs reg a2 ; regs to save
|
|||
|
|
|||
|
InitScriptApp
|
|||
|
with isaFrame,ExpandMemRec,SMgrAppRecord
|
|||
|
link a6,#isaLocals ; link the stack.
|
|||
|
movem.l isaRegs,-(sp) ; save regs
|
|||
|
|
|||
|
; Create app-specific script globals, initialize itl cache part from
|
|||
|
; sys itl cache. This code mostly moved from International PACK.a.
|
|||
|
|
|||
|
move.l ExpandMem,a2
|
|||
|
move.l emItlSysCachePtr(a2),a0 ; get pointer to sys itl cache
|
|||
|
_GetPtrSize
|
|||
|
tst.l d0 ; error?
|
|||
|
bmi.s @isaExit ; if so, no app script globals
|
|||
|
move.l d0,d2 ; save length
|
|||
|
add.l #smgrAppRsvdSize,d0 ; add space for other global fields
|
|||
|
_NewHandle ,CLEAR ; make global space in app heap <28>
|
|||
|
bmi.s @isaExit ; if error, no app script globals
|
|||
|
move.l a0,a1 ; save new handle in a1<61>
|
|||
|
move.l a1,emScriptAppGlobals(a2) ; <20>and in ExpandMemRec field
|
|||
|
_HNoPurge ; and make it non-purgeable
|
|||
|
move.l emItlSysCachePtr(a2),a0 ; get pointer to sys itl cache
|
|||
|
move.l (a1),a1 ; get pointer to new globals
|
|||
|
lea smgrAppCacheCount(a1),a1 ; point to base of cache area
|
|||
|
move.l d2,d0 ; get length of cache part
|
|||
|
_BlockMove ; copy sys cache to app cache
|
|||
|
; what to do about errors here?
|
|||
|
@isaExit
|
|||
|
move.w #noErr,result(a6) ; return noErr
|
|||
|
movem.l (sp)+,isaRegs ; restore regs
|
|||
|
move.w #isaArgs,d0 ; for StdUnlink
|
|||
|
bra StdUnlink ; standard exit
|
|||
|
endwith ;isaFrame,ExpandMemRec,SMgrAppRecord
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
;------------------------------------------------------------------------ <27>
|
|||
|
; FUNCTION CleanupScriptApp: OSErr;
|
|||
|
;------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; CleanupScriptApp cleans up the application-specific Script Mgr globals.
|
|||
|
;
|
|||
|
|
|||
|
proc
|
|||
|
export CleanupScriptApp
|
|||
|
import StdUnlink
|
|||
|
|
|||
|
csaFrame record {a6link},decr
|
|||
|
result ds.w 1 ; OSErr result code.
|
|||
|
csaArgs equ *-8 ; size of arguments.
|
|||
|
selector ds.l 1 ; selector
|
|||
|
return ds.l 1 ; return address.
|
|||
|
a6link ds.l 1 ; old a6
|
|||
|
csaLocals equ *
|
|||
|
endr
|
|||
|
|
|||
|
;csaRegs reg a2-a3/d3 ; regs to save
|
|||
|
|
|||
|
CleanupScriptApp
|
|||
|
with csaFrame,ExpandMemRec
|
|||
|
link a6,#csaLocals ; link the stack.
|
|||
|
; movem.l csaRegs,-(sp) ; save regs
|
|||
|
|
|||
|
; If app script globals exist, dispose of them
|
|||
|
move.l ExpandMem,a0 ; get ptr to ExpandMemRec
|
|||
|
move.l emScriptAppGlobals(a0),a0 ; get handle to app<70>s script globals
|
|||
|
move.l a0,d0 ; is it 0 (couldn<64>t allocate)?
|
|||
|
beq.s @csaExit ; if so, nothing to do
|
|||
|
addq.l #1,d0 ; is it -1 (Process Mgr didn<64>t set field)?
|
|||
|
beq.s @csaExit ; if so, nothing to do
|
|||
|
_DisposHandle
|
|||
|
move.l ExpandMem,a0 ; get ptr to ExpandMemRec <29>
|
|||
|
clr.l emScriptAppGlobals(a0) ; clear out so we don't try to use it <29>
|
|||
|
|
|||
|
@csaExit
|
|||
|
move.w #noErr,result(a6) ; return noErr
|
|||
|
; movem.l (sp)+,csaRegs ; restore regs
|
|||
|
move.w #csaArgs,d0 ; for StdUnlink
|
|||
|
bra StdUnlink ; standard exit
|
|||
|
endwith ;csaFrame,ExpandMemRec
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
;------------------------------------------------------------------------------- <24>
|
|||
|
; FUNCTION IsCmdChar(keyEvent: EventRecord; testChar: CHAR): BOOLEAN;
|
|||
|
;
|
|||
|
; This function tests if Command is being pressed in conjunction with another
|
|||
|
; key (or keys) that could generate testChar for some combination of Command up
|
|||
|
; or down and Shift up or down. This accomodates European keyboards that may
|
|||
|
; have testChar as a Shifted character, and non-Roman keyboards that will ONLY
|
|||
|
; generate testChar if Command is down. It is most useful for testing for
|
|||
|
; Command-period.
|
|||
|
;
|
|||
|
; The caller passes in the event record, which is assumed by the function to be
|
|||
|
; an event record for a key-down or auto-key event with the Command key down.
|
|||
|
; The caller also passes in the character to be tested for (e.g. '.'). The
|
|||
|
; function returns TRUE if the test char is produced with the current modifier
|
|||
|
; keys, or if it would be produced by changing the current modifier key bits in
|
|||
|
; the following ways:
|
|||
|
; 1. turning the Command bit off
|
|||
|
; 2. toggling the Shift bit
|
|||
|
; 3. both of the above
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
|
|||
|
proc
|
|||
|
export IsCmdChar
|
|||
|
export DoKeyTrans ; <37>
|
|||
|
|
|||
|
keyUpMask equ $80 ; or mask to set key up bit in keycode
|
|||
|
cmdOffMask equ $FEFF ; and mask to clear CmdKey bit in keycode
|
|||
|
cmdOnMask equ $0100 ; or mask to set CmdKey bit in keycode
|
|||
|
shiftToggleMask equ $0200 ; xor mask to toggle ShiftKey bit in keycode
|
|||
|
|
|||
|
iccFrame record {a6link},decr
|
|||
|
result ds.w 1 ; Boolean result
|
|||
|
iccArgStart equ *
|
|||
|
eventRecPtr ds.l 1 ; Pointer to event record
|
|||
|
testChar ds.w 1 ; Char parameter to test for
|
|||
|
selector ds.l 1 ; Script Mgr selector
|
|||
|
iccArgEnd equ *
|
|||
|
return ds.l 1 ; return address
|
|||
|
a6link ds.l 1 ; link register
|
|||
|
iccLocals equ *
|
|||
|
iccArgSize equ iccArgStart-iccArgEnd
|
|||
|
endr
|
|||
|
|
|||
|
iccRegs reg a2/d3-d4 ; regs to save <37>
|
|||
|
; Local regs:
|
|||
|
; a2.l KCHRPtr
|
|||
|
; d3.w keycode
|
|||
|
; d4.w testChar
|
|||
|
|
|||
|
IsCmdChar
|
|||
|
with iccFrame
|
|||
|
LINK A6,#iccLocals ;
|
|||
|
movem.l iccRegs,-(sp) ; save regs <37>
|
|||
|
|
|||
|
move.w testChar(a6),d4 ; save testChar <37>
|
|||
|
|
|||
|
;...............................................................................
|
|||
|
; Set up KeyTrans parameters keycode and KCHRPtr
|
|||
|
;...............................................................................
|
|||
|
|
|||
|
move.l eventRecPtr(a6),a0 ; get ptr to event record
|
|||
|
move.w evtMeta(a0),d3 ; get modifier keys in hi byte of word <37>
|
|||
|
move.b evtMessage+2(a0),d3 ; get virtual key code in lo byte <37>
|
|||
|
or.b #keyUpMask,d3 ; Set key up bit. This will make <37>
|
|||
|
; KeyTrans skip dead key processing.
|
|||
|
|
|||
|
with ExpandMemRec
|
|||
|
MOVE.L ExpandMem,A0 ; Pointer to ExpandMemRec
|
|||
|
MOVE.L emKeyCache(A0),a2 ; Save pointer to KCHR resource <37>
|
|||
|
endwith
|
|||
|
|
|||
|
;...............................................................................
|
|||
|
; Call KeyTrans with various modifier key settings
|
|||
|
;...............................................................................
|
|||
|
ST result(A6) ; Assume we have a match
|
|||
|
BSR.S DoKeyTrans ; First, call with real modifiers
|
|||
|
BEQ.S DoneTest ; If that gave us a match, hooray
|
|||
|
AND.W #cmdOffMask,d3 ; Turn off Command and try again <37>
|
|||
|
BSR.S DoKeyTrans ; I can't stand the suspense
|
|||
|
BEQ.S DoneTest ; Do we have a match yet?
|
|||
|
MOVE.W #shiftToggleMask,D0 ; Because of weird 68000 EOR inst.
|
|||
|
EOR.W D0,d3 ; Toggle the Shift bit and try again <37>
|
|||
|
BSR.S DoKeyTrans ; Read all about it<69>
|
|||
|
BEQ.S DoneTest ; Are we home yet?
|
|||
|
OR.W #cmdOnMask,d3 ; Turn on Command and try once more <37>
|
|||
|
BSR.S DoKeyTrans ; Almost done<6E>
|
|||
|
SZ result(A6) ; Our final result
|
|||
|
|
|||
|
;...............................................................................
|
|||
|
; Clean up and exit
|
|||
|
;...............................................................................
|
|||
|
DoneTest
|
|||
|
movem.l (sp)+,iccRegs ; restore regs <37>
|
|||
|
UNLK A6 ;
|
|||
|
MOVE.L (SP)+,A0 ; pop return address
|
|||
|
ADD.L #iccArgSize,SP ; clean up parameter space
|
|||
|
JMP (A0) ; return to caller
|
|||
|
|
|||
|
;...............................................................................
|
|||
|
; Subroutine for calling KeyTrans. Returns with condition codes set
|
|||
|
; to indicate result: Z set if match, clear if no match.
|
|||
|
;
|
|||
|
; Assumes the following registers are set up: <37>
|
|||
|
; a2.l KCHRPtr
|
|||
|
; d3.w keycode
|
|||
|
; d4.w testChar
|
|||
|
;...............................................................................
|
|||
|
DoKeyTrans
|
|||
|
SUBQ.L #4, SP ; Make room for KeyTrans result
|
|||
|
MOVE.L a2,-(SP) ; Push pointer to KCHR resource <37>
|
|||
|
MOVE.W d3,-(SP) ; Push keycode (w/o modifiers) <37>
|
|||
|
PEA TestDead ; Push address of dead key state
|
|||
|
_KeyTrans
|
|||
|
CMP.W (SP)+,D4 ; compare testChar with first char <37>
|
|||
|
BEQ.S @FixStackReturn ; if equal, clean up stack & return
|
|||
|
CMP.W (SP)+,D4 ; compare testChar with second char <37>
|
|||
|
RTS ; return Z set or clear, indicates result
|
|||
|
@FixStackReturn
|
|||
|
ADDA.W #2,SP ; fix stack w/o changing cond codes
|
|||
|
RTS ; return with Z set.
|
|||
|
|
|||
|
TestDead dc.l 0 ; storage for dead state
|
|||
|
endwith
|
|||
|
endproc
|
|||
|
|
|||
|
;------------------------------------------------------------------------------- <33>
|
|||
|
; FUNCTION FindCharInSet(textPtr: Ptr; textLen: LongInt; charSet: StringPtr;
|
|||
|
; table: CharByteTable): LongInt;
|
|||
|
;
|
|||
|
; The textPtr and textLen parameters specify a string to be searched for any
|
|||
|
; of the characters in charSet. If any are found, the offset where the
|
|||
|
; character was found is returned; otherwise, the function returns -1.
|
|||
|
;
|
|||
|
; The table parameter is obtained from the Script Mgr ParseTable routine.
|
|||
|
; The caller must set the txFont of the port to a font in the script being
|
|||
|
; handled, then call ParseTable to get the table.
|
|||
|
;
|
|||
|
; This routine is used by Dialog Mgr and Finder (and Help Mgr?).
|
|||
|
; Written by Kevin S. MacDonell.
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
|
|||
|
proc
|
|||
|
export FindCharInSet
|
|||
|
|
|||
|
FCISFrame RECORD {A6Link},decr
|
|||
|
fcisresult DS.L 1
|
|||
|
txtPtr DS.L 1
|
|||
|
txtLen DS.L 1
|
|||
|
charSetPtr DS.L 1
|
|||
|
tblPtr DS.L 1
|
|||
|
selector DS.L 1 ; Script Mgr selector <36>
|
|||
|
fcisparamSz EQU fcisresult-*
|
|||
|
ReturnAddr DS.L 1
|
|||
|
A6Link DS.L 1
|
|||
|
ENDR
|
|||
|
|
|||
|
fcisSaveReg REG D2-D7/A2-A4
|
|||
|
; Register conventions for this routine
|
|||
|
; D0 - The char from the text buffer we are looking at
|
|||
|
; D1 - The char from the charset we are looking at
|
|||
|
; D2 - length of character in charset
|
|||
|
; D3 - offset into charset
|
|||
|
; D4 - offset into text
|
|||
|
; D5 - subrange counter (bytes into char from charset)
|
|||
|
; D6 - The # of BYTES in the charset (because there may be double-byte chars in it)
|
|||
|
; D7 - The text length in bytes (not chars, we assume caller does not know this)
|
|||
|
|
|||
|
; A4/D4 - txtPtr and offset
|
|||
|
; A3/D3 - charSetPtr and offset
|
|||
|
; A2 - tblPtr
|
|||
|
; A1 - subrange pointer into charset
|
|||
|
; A0 - subrange pointer into text
|
|||
|
|
|||
|
FindCharInSet
|
|||
|
WITH FCISFrame
|
|||
|
link a6,#0
|
|||
|
movem.l fcisSaveReg,-(sp)
|
|||
|
|
|||
|
moveq #-1,d7
|
|||
|
move.l d7,fcisresult(a6) ; Assume we won<6F>t find anything
|
|||
|
|
|||
|
move.l txtLen(a6),d7 ; Get the length of the text to search
|
|||
|
ble.s @done ; don<6F>t bother if it<69>s bogus
|
|||
|
|
|||
|
move.l charSetPtr(a6),a3 ; Get base of string
|
|||
|
moveq #0,d6 ; Clear high part
|
|||
|
move.b (a3)+,d6 ; Get length byte and bump pointer past it
|
|||
|
beq.s @done ; If no chars to search for, bail
|
|||
|
|
|||
|
moveq #0,d0 ; Clear text byte
|
|||
|
moveq #0,d1 ; Clear charset byte
|
|||
|
moveq #0,d2 ; Clear subrange counter
|
|||
|
move.l txtPtr(a6),a4 ; Get the text ptr
|
|||
|
move.l tblPtr(a6),a2 ; Get the table ptr
|
|||
|
move.b (a3),d1 ; Preload d1 with single char to preflight special case
|
|||
|
; Since it never changes during textloop
|
|||
|
|
|||
|
; Loop thru each char in the text and compare it with each char in the charset
|
|||
|
; If we find a match, return the byte offset into the text where the match starts
|
|||
|
|
|||
|
moveq #0,d4 ; Start at offset zero into text
|
|||
|
@textLoop ; while (offsetintotext (d4) < textlen) do
|
|||
|
move.b (a4,d4.l),d0 ; Get first byte of next char in text
|
|||
|
cmp.w #1,d6 ; Is the charset only 1 byte long? (special case)
|
|||
|
beq.s @fastCompare
|
|||
|
|
|||
|
moveq #0,d3 ; Start at offset zero into charset
|
|||
|
@charsetLoop: ; while (offsetintocharset(d3) < charsetlen) do
|
|||
|
lea (a4,d4.l),a0 ; Point to current byte in text string
|
|||
|
lea (a3,d3.l),a1
|
|||
|
move.b (a1),d1 ; Get first byte of next char in charset
|
|||
|
move.b (a2,d1.l),d2 ; Get the length of this charset character
|
|||
|
move.l d2,d5 ; Copy to loop counter
|
|||
|
|
|||
|
@subcharsetloop:
|
|||
|
cmpm.b (a0)+,(a1)+ ; Did we find it?
|
|||
|
bne.s @charsetLoopNext ; Nope, check the next char in the charset
|
|||
|
dbf d5,@subcharsetloop ; Go check the next one
|
|||
|
bra.s @foundit ; If we fell out of loop, we found it!
|
|||
|
|
|||
|
@charsetLoopNext:
|
|||
|
addq.l #1,d3 ; Advance 1 byte in the char set
|
|||
|
add.l d2,d3 ; Advance more bytes if necessary, past end of char
|
|||
|
cmp.l d3,d6 ; Checked all the chars in the charset?
|
|||
|
bgt.s @charsetLoop ; no, keep going
|
|||
|
bra.s @textLoopNext ; yep, check next char in text
|
|||
|
|
|||
|
; This is the short-circuit compare loop when we are searching for a single 1-byte character
|
|||
|
@fastCompare
|
|||
|
cmp.b d0,d1 ; Did we find it?
|
|||
|
bne.s @textLoopNext
|
|||
|
|
|||
|
@foundit
|
|||
|
move.l d4,fcisresult(a6) ; Return the offset into the text where we matched
|
|||
|
bra.s @done
|
|||
|
|
|||
|
@textLoopNext
|
|||
|
addq.l #1,d4 ; Point to next character in the text
|
|||
|
move.b (a2,d0.l),d0 ; Get number of additional chars
|
|||
|
add.l d0,d4 ; And point past those
|
|||
|
cmp.l d4,d7 ; Checked all the chars in the text?
|
|||
|
bgt.s @textLoop ; keep going
|
|||
|
|
|||
|
@done
|
|||
|
movem.l (sp)+,fcisSaveReg
|
|||
|
unlk a6
|
|||
|
move.l (sp)+,a0
|
|||
|
moveq #fcisparamSz,d0
|
|||
|
add.w d0,sp
|
|||
|
jmp (a0)
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; StdUnlink, StdExit
|
|||
|
; Standard point of return for script manager routines.
|
|||
|
; Input
|
|||
|
; d0 := number of arguments passed to returning routine
|
|||
|
; sp := address of jump target routine
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
proc
|
|||
|
export StdUnlink, StdExit ; standard exit points
|
|||
|
|
|||
|
StdUnlink
|
|||
|
unlk a6 ; unlink the stack.
|
|||
|
StdExit
|
|||
|
move.l (sp)+,a0 ; pop return address.
|
|||
|
add.w d0,sp ; pop arguments.
|
|||
|
jmp (a0) ; return to the caller.
|
|||
|
endproc
|
|||
|
|
|||
|
; ----------------------------------------------------------------------- <1.8>
|
|||
|
; Patch out LwrString to handle 2-byte chars.
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; routine: LwrString
|
|||
|
; input: a0 textPtr
|
|||
|
; d0.w length
|
|||
|
; d1.w trap word; the following bits are significant in 7.0 only:
|
|||
|
; Opcode bits
|
|||
|
; 10 9 Function
|
|||
|
; -- -- --------
|
|||
|
; 0 0 convert to lower-case
|
|||
|
; 0 1 strip diacritics
|
|||
|
; 1 0 convert to upper-case
|
|||
|
; 1 1 convert to upper-case and strip diacritics
|
|||
|
; output: d0.w error
|
|||
|
; function: Change text pointed to by a0 according to opcode bits. Before 7.0, we
|
|||
|
; just assume that these bits are 0 and act accordingly.
|
|||
|
; -----------------------------------------------------------------------------
|
|||
|
; Add a new entry point for ScriptUtil. Like LwrString, but params on stack,
|
|||
|
; and two additional params: script specifies the script (so we don't need a
|
|||
|
; grafPort), and func selects which function (Upper, Lower, etc.) using the same
|
|||
|
; bits as in the OS trap word.
|
|||
|
;
|
|||
|
; PROCEDURE SCLwrString(textPtr: Ptr;len: INTEGER;script: ScriptCode;
|
|||
|
; func: INTEGER);
|
|||
|
;
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
proc
|
|||
|
export NewLwrString, SCLwrString ; <38><2>
|
|||
|
|
|||
|
lwrTrFrame record {a6link},decr
|
|||
|
return ds.l 1 ; return address
|
|||
|
a6link ds.l 1 ; link pointer
|
|||
|
sourcePtr ds.l 1 ; orig source ptr
|
|||
|
sourceLen ds.l 1 ; orig source len
|
|||
|
sourceHndl ds.l 1 ; new handle with copy of source
|
|||
|
destHndl ds.l 1 ; new handle for transliterate result
|
|||
|
errCode ds.w 1 ; err code to be returned in d0
|
|||
|
target ds.w 1 ; target for Transliterate <new in 7.0>
|
|||
|
script ds.w 1 ; script code <38>
|
|||
|
lwrTrLocals equ * ; size of locals
|
|||
|
endr
|
|||
|
|
|||
|
opcodeMask equ $0600 ; mask for opcode bits
|
|||
|
stripOnly equ $0200 ; opcode bits for strip diacritics only
|
|||
|
|
|||
|
|
|||
|
; New entry point, ScriptUtil routine <38>
|
|||
|
SCLwrString
|
|||
|
|
|||
|
move.l (sp)+,a1 ; pop return address <38>
|
|||
|
addq #4,sp ; discard selector <38>
|
|||
|
move.w (sp)+,d1 ; get func code (bits 9-10 like trap word) <38>
|
|||
|
move.w (sp)+,d2 ; get ScriptCode for later <38>
|
|||
|
move.w (sp)+,d0 ; get length where OS trap would have it<69> <38>
|
|||
|
move.l (sp)+,a0 ; and pointer where OS trap would have it. <38>
|
|||
|
move.l a1,-(sp) ; restore return address <38>
|
|||
|
|
|||
|
cmp.w #smSystemScript,d2 ; check ScriptCode <38>
|
|||
|
blt.s useFontScript ; FontScript, go get it <38>
|
|||
|
|
|||
|
with SMgrRecord,ScriptRecord ; <38>
|
|||
|
movea.l IntlSpec,a1 ; doesn't affect cc <38>
|
|||
|
bgt.s @haveRealScript ; <38>
|
|||
|
move.w smgrSysScript(a1),d2 ; get system script <38>
|
|||
|
@haveRealScript
|
|||
|
move.w d2,-(sp) ; save script code <38>
|
|||
|
lsl.w #2,d2 ; convert to long offset. <38>
|
|||
|
move.l smgrEntry(a1,d2.w),d2 ; script installed? <38>
|
|||
|
beq lwrCleanup ; no, do nothing <38>
|
|||
|
move.l d2,a1 ; load ScriptRecord pointer. <38>
|
|||
|
tst.b scriptEnabled(a1) ; script enabled? <38>
|
|||
|
beq lwrCleanup ; if so, go dispatch <38>
|
|||
|
move.w (sp)+,d2 ; restore ScriptCode <38>
|
|||
|
bra.s haveValidScript ; <38>
|
|||
|
endwith ;SMgrRecord,ScriptRecord <38>
|
|||
|
|
|||
|
; Old entry point, OS trap
|
|||
|
NewLwrString ; <2>
|
|||
|
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; NOTE: For 2-byte scripts, we need to call Transliterate. So, the first thing to
|
|||
|
; do is figure out what script we're in. We also test for length <= 0 (tests >32K).
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
useFontScript ; <38>
|
|||
|
movem.l a0/d0/d1,-(sp) ; save important registers
|
|||
|
subq.l #2,sp ; make room for return
|
|||
|
_FontScript ; find script of port, ScriptRecord in a0
|
|||
|
move.w (sp)+,d2 ; pop script into d2
|
|||
|
move.l a0,a1 ; put ScriptRecord ptr in a1 <38>
|
|||
|
movem.l (sp)+,a0/d0/d1 ; restore important registers
|
|||
|
|
|||
|
haveValidScript ; <38>
|
|||
|
; Here we have: ; <38>
|
|||
|
; a0 textPtr
|
|||
|
; d0.w len
|
|||
|
; d1.w bits 9-10 have func flags
|
|||
|
; a1 ScriptRecord ptr
|
|||
|
; d2 real script code
|
|||
|
|
|||
|
ext.l d0 ; as fast as tst.w and we need ext.l later <38> move here
|
|||
|
ble lwrRTS ; if bad length, quit <38> move here
|
|||
|
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; Here we make use of the fact that a word redraw flag of 1 (or anything >0)
|
|||
|
; indicates a 2-byte script.
|
|||
|
; Now we already have ScriptRecord ptr in a1, and we know script is enabled. <38>
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
with ScriptRecord ; <38>
|
|||
|
tst.b scriptRedraw(a1) ; is it a 2-byte script?
|
|||
|
ble not2Byte ; if not, go use normal LwrString
|
|||
|
endwith ;ScriptRecord
|
|||
|
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; OK, we need to set up for Transliterate: set up source & dest handles.
|
|||
|
; Also set target depending on opcode bits <new in 7.0>.
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
with lwrTrFrame
|
|||
|
link a6,#lwrTrLocals ; create local storage
|
|||
|
move.w d2,script(a6) ; save script code <38>
|
|||
|
; ------------
|
|||
|
; Set target depending on opcode bits <new in 7.0>.
|
|||
|
clr.w errCode(a6) ; start with no errors
|
|||
|
move.w #smTransLower+smTransAscii,target(a6) ; assume lower-casing
|
|||
|
and.w #opcodeMask,d1 ; isolate opcode bits
|
|||
|
beq.s @gotTarget ; if 00, go with lower-casing
|
|||
|
cmp.w #stripOnly,d1 ; if just stripping diacritics<63>
|
|||
|
beq lwrTrUnlk ; nothing to do in 2-byte system
|
|||
|
move.w #smTransUpper+smTransAscii,target(a6) ; else upper-casing
|
|||
|
@gotTarget
|
|||
|
; ------------
|
|||
|
move.l a0,sourcePtr(a6) ; save source ptr
|
|||
|
move.l d0,sourceLen(a6) ; save length
|
|||
|
_PtrToHand ; make new handle containing copy of text
|
|||
|
move.w d0,errCode(a6) ; save err code
|
|||
|
bne lwrTrUnlk ; if error in PtrToHand, quit <SM5> CSS
|
|||
|
move.l a0,sourceHndl(a6) ; save new source handle
|
|||
|
move.l sourceLen(a6),d0 ; get length again
|
|||
|
_NewHandle ; make new handle with random contents
|
|||
|
move.w d0,errCode(a6) ; save err code
|
|||
|
bne.s lwrTrDisp1Hndl ; if error in NewHandle, quit
|
|||
|
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; Now do Transliterate and check result: dest length should equal source length
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
move.l a0,destHndl(a6) ; save new dest handle
|
|||
|
subq.l #2,sp ; space for Transliterate error code
|
|||
|
move.l sourceHndl(a6),-(sp) ; push source handle
|
|||
|
move.l a0,-(sp) ; push dest handle (still in a0)
|
|||
|
move.w target(a6),-(sp) ; use specified target <changed in 7.0>
|
|||
|
move.l #smMaskAscii,-(sp) ; convert Roman only
|
|||
|
move.w script(a6),-(sp) ; push ScriptCode <38>
|
|||
|
_SCTransliterate ; <38>
|
|||
|
move.w (sp)+,errCode(a6) ; save error code
|
|||
|
bne.s lwrTrDisp2Hndl ; if error in Transliterate, quit
|
|||
|
move.l destHndl(a6),a0 ; now check result<6C>
|
|||
|
_GetHandleSize
|
|||
|
move.w d0,errCode(a6) ; save err code
|
|||
|
tst.l d0 ; .l, because the result is really a long
|
|||
|
blt.s lwrTrDisp2Hndl ; if error in GetHandleSize, quit
|
|||
|
move.w #-1,errCode(a6) ; assume len err; need a better err code!
|
|||
|
cmp.l sourceLen(a6),d0 ; should be same as source len
|
|||
|
bne.s lwrTrDisp2Hndl ; if not, set err and bail
|
|||
|
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; Copy result (destHndl) to original text buffer (sourcePtr).
|
|||
|
; NOTE: For large text blocks, _BlockMove might be faster than this loop.
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
move.l destHndl(a6),a0 ; get dest handle and<6E>
|
|||
|
move.l (a0),a0 ; deref it to get source ptr for this copy
|
|||
|
move.l sourcePtr(a6),a1 ; old source ptr is dest for this copy
|
|||
|
move.l sourceLen(a6),d0 ; length for copy (we know it is >= 1)
|
|||
|
subq.l #1,d0 ; set up for dbra
|
|||
|
@1 move.b (a0)+,(a1)+ ; copy a byte
|
|||
|
dbra d0,@1 ; loop till done
|
|||
|
clr.w errCode(a6) ; no errors!
|
|||
|
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; Exits - need to dispose of handles we created
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
lwrTrDisp2Hndl
|
|||
|
move.l destHndl(a6),a0 ;
|
|||
|
_DisposHandle ;
|
|||
|
lwrTrDisp1Hndl
|
|||
|
move.l sourceHndl(a6),a0 ;
|
|||
|
_DisposHandle ;
|
|||
|
lwrTrUnlk
|
|||
|
move.w errCode(a6),d0 ; set err code
|
|||
|
unlk a6 ;
|
|||
|
rts
|
|||
|
endwith
|
|||
|
|
|||
|
lwrCleanup ; <38>
|
|||
|
addq #2,sp ; discard saved script code <38>
|
|||
|
lwrRTS
|
|||
|
clr.w d0
|
|||
|
rts
|
|||
|
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
; This is not a 2-byte script, just use old LwrString.
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
not2Byte
|
|||
|
; We used to jump back into ROM here with "BackToTrap oldLwrString". Now we <38>
|
|||
|
; patch out LwrString entirely, so we add the code below.
|
|||
|
; Instead of saving/clearing IntlForce, calling GetIntl,
|
|||
|
; then restoring IntlForce, we now just call GetScriptItl.
|
|||
|
|
|||
|
move.l a2,-(sp) ; save a2 <03/05/89 pke>
|
|||
|
; actually, OS trap dispatch saves & restores a2 - strange but true <06/05/89 pke>
|
|||
|
|
|||
|
movem.l a0/d0/d1,-(sp) ;*save around IUGetScriptItl (ugly temp hack)
|
|||
|
|
|||
|
; <38>
|
|||
|
clr.l -(sp) ; space for returned handle
|
|||
|
move.w #2,-(sp) ; select itl2
|
|||
|
move.w d2,-(sp) ; push ScriptCode <38>
|
|||
|
clr.w -(sp) ; sysFlag = 0 <38>
|
|||
|
_IUGetScriptItl ; may trash a0,a1,d0-d2 <38>
|
|||
|
move.l (sp)+,a2 ; store itl2 handle
|
|||
|
; <38>
|
|||
|
|
|||
|
movem.l (sp)+,a0/d0/d1 ;*(ugly temp hack)
|
|||
|
move.l a2,d2 ; nil handle? <06/05/89 pke>
|
|||
|
beq.s @LwrError ; bail if so <06/05/89 pke>
|
|||
|
move.l (a2),a2 ; dereference
|
|||
|
btst.b #0,itl2FlagsOffset+1(a2) ; extended itl2 tables?
|
|||
|
beq.s @LwrError ; no, bail (was beq to @LwrExit) <06/05/89 pke>
|
|||
|
move.l a2,a1 ; copy pointer
|
|||
|
clr.l d2 ; for longizing
|
|||
|
move.w classArrayOffset(a2),d2 ; longize classArrayOffset
|
|||
|
add.l d2,a1 ; make classArray pointer
|
|||
|
|
|||
|
; Opword = 1010 xcdx xxxx xxxx , where c=caseBit and d=diacBit. Shift & mask
|
|||
|
; to form 0000 0000 0000 0CD0 for use as an address offset. <03/28/89 pke>
|
|||
|
lsr.w #8,d1 ; xxxx xxxx 1010 xcdx <03/28/89 pke>
|
|||
|
andi.w #$0006,d1 ; 0000 0000 0000 0cd0 <03/28/89 pke>
|
|||
|
move.w @LwrOffsetTable(d1.w),d1 ; offset into itl2 offset table <03/28/89 pke>
|
|||
|
move.w 0(a2,d1.w),d2 ; now get actual table offset <03/28/89 pke>
|
|||
|
|
|||
|
add.l d2,a2 ; make lowerList pointer
|
|||
|
|
|||
|
clr.l d1 ; wordize
|
|||
|
bra.s @LwrNext ; loop at bottom
|
|||
|
@LwrLoop
|
|||
|
move.b (a0),d1 ; char
|
|||
|
move.b 0(a1,d1.w),d1 ; class
|
|||
|
move.b 0(a2,d1.w),d1 ; delta
|
|||
|
add.b d1,(a0)+ ; add delta to make lower
|
|||
|
@LwrNext
|
|||
|
dbra d0,@LwrLoop ; until d0 = -1
|
|||
|
@LwrExit
|
|||
|
clr.l d0 ; no error
|
|||
|
@LwrExit2 ; <06/05/89 pke>
|
|||
|
move.l (sp)+,a2 ; restore a2 <03/05/89 pke>
|
|||
|
rts
|
|||
|
|
|||
|
@LwrError ; <06/05/89 pke>
|
|||
|
move.w #resNotFound,d0 ; <06/05/89 pke><07/08/89 pke>
|
|||
|
bra.s @LwrExit2 ; <06/05/89 pke>
|
|||
|
|
|||
|
@LwrOffsetTable ; <03/28/89 pke>
|
|||
|
dc.w lowerListOffset ; <03/28/89 pke>
|
|||
|
dc.w noMarkListOffset ; <03/28/89 pke><04/07/89 pke>
|
|||
|
dc.w upperListOffset ; <03/28/89 pke>
|
|||
|
dc.w upperNoMarkListOffset ; <03/28/89 pke>
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
;------------------------------------------------------------------------------- <37>
|
|||
|
; FUNCTION TestLetter(testChar: CHAR): BOOLEAN; {Pascal calling conventions}
|
|||
|
;
|
|||
|
; This function tests if a key on the main keyboard is being pressed that could
|
|||
|
; generate testChar with Command up or down (and no other modifiers). This is only
|
|||
|
; intended to test for Roman lower-case letters. It checks for the key press by
|
|||
|
; examining the low-memory Keymap area, so this is useful when we are not in an
|
|||
|
; event loop. We check with Command bit on because this forces the Roman layout
|
|||
|
; on a non-Roman keyboard.
|
|||
|
;
|
|||
|
; Example of usage from assembly language to test for Opt-e:
|
|||
|
;
|
|||
|
; btst #2,KeyMap+7 ; option key down?
|
|||
|
; beq.s @done ; no, skip check.
|
|||
|
; subq #2,sp ; make room for Boolean result
|
|||
|
; move.w #'e',-(sp) ; push 'e' as the char to test for
|
|||
|
; bsr TestLetter ; returns TRUE if key with Roman 'e' being pressed
|
|||
|
; tst.b (sp)+ ; what was the result?
|
|||
|
; bne SkipInstall ; if Opt-e, skip script install
|
|||
|
;
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
|
|||
|
proc
|
|||
|
export xTestLetter, iTestLetter
|
|||
|
import DoKeyTrans
|
|||
|
|
|||
|
clearModifiers equ $FFFF7F80 ; and mask to clear modifier bits in (KeyMap+4).L
|
|||
|
keyUpMask equ $0080 ; or mask to set key up bit in keycode
|
|||
|
cmdOnMask equ $0100 ; or mask to set CmdKey bit in keycode
|
|||
|
|
|||
|
tlFrame record {a6link},decr
|
|||
|
result ds.w 1 ; Boolean result
|
|||
|
tlArgStart equ *
|
|||
|
testChar ds.w 1 ; Char parameter to test for
|
|||
|
tlArgEnd equ *
|
|||
|
return ds.l 1 ; return address
|
|||
|
a6link ds.l 1 ; link register
|
|||
|
tlLocals equ *
|
|||
|
tlArgSize equ tlArgStart-tlArgEnd
|
|||
|
endr
|
|||
|
|
|||
|
tlRegs reg a2/d3-d4 ; regs to save
|
|||
|
; Local regs:
|
|||
|
; a2.l KCHRPtr
|
|||
|
; d3.w keycode
|
|||
|
; d4.w testChar
|
|||
|
|
|||
|
xTestLetter ; external entry <44>
|
|||
|
move.l (sp)+,(sp) ; discard selector but save return addr <44>
|
|||
|
|
|||
|
iTestLetter ; internal entry <44>
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
; Check if we have a non-modifier key down on the main keyboard (not the keypad
|
|||
|
; etc.). We look in the KeyMap bit array to see if a bit is set that indicates a
|
|||
|
; non-modifier key is pressed. KeyMap is 128 bits, so we can test 4 longs.
|
|||
|
; However, we skip the last 2 longs, because they are only for the keypad, arrow
|
|||
|
; keys or special keys on the extended keyboard.
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
CLR.W 6(SP) ; Assume result FALSE
|
|||
|
|
|||
|
MOVEQ #0,D1 ; bit offset in KeyMap
|
|||
|
MOVE.L KeyMap,D0 ; Key down in (KeyMap+0).L?
|
|||
|
BNE.S GotKey ; If so, handle it
|
|||
|
MOVEQ #32,D1 ; bit offset in KeyMap
|
|||
|
MOVE.L KeyMap+4,D0 ; Get (KeyMap+4).L
|
|||
|
AND.L #clearModifiers,D0 ; Is non-modifier key down?
|
|||
|
BEQ.S NoKey ; If not, give up
|
|||
|
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
; Here, we have a non-modifier key down on the main keyboard. At this point, D0
|
|||
|
; is guaranteed to have at least one non-zero bit. We determine the keycode
|
|||
|
; modulo 32 based on the position of this bit in D0. Then we add in the bit
|
|||
|
; offset from the beginning of KeyMap to the 32-bit block that the key down bit
|
|||
|
; was in (this value is in D1). This gives us the keycode.
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
GotKey
|
|||
|
with tlFrame
|
|||
|
LINK A6,#tlLocals
|
|||
|
movem.l tlRegs,-(sp) ; save regs
|
|||
|
|
|||
|
move.w testChar(a6),d4 ; save testChar
|
|||
|
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
; Set up KeyTrans parameter: keycode (in d3)
|
|||
|
; Note that modifiers byte will be all 0 (this is what we want)
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
|
|||
|
MOVEQ.L #31,d3 ; Loop starts testing from 31
|
|||
|
@bitLoop
|
|||
|
BTST.L d3,d0 ; Is selected bit set in D0?
|
|||
|
DBNE d3,@bitLoop ; No, try next. Guaranteed to find one.
|
|||
|
; Now d3.W contains the number of the bit that was set in D0.L.
|
|||
|
MOVE.W d3,d0 ; Copy bit number
|
|||
|
AND.W #$07,d3 ; Get bit number within byte
|
|||
|
AND.W #$F8,d0 ; Get bit offset of byte in register
|
|||
|
ADD.W #24,d3 ; Byte's bit offset in KeyMap is <20>
|
|||
|
SUB.W d0,d3 ; <20> 24 - bit offset in register
|
|||
|
; Now we have keycode mod 32 in d3.
|
|||
|
ADD.W d1,d3 ; Add in Keymap block bit offset (0 or 32).
|
|||
|
; Now we have keycode in d3.w
|
|||
|
OR.W #keyUpMask,d3 ; Set key up bit. This will make
|
|||
|
; KeyTrans skip dead key processing.
|
|||
|
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
; Get KeyTrans parameter: KCHRPtr (in a2)
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
|
|||
|
with ExpandMemRec
|
|||
|
MOVE.L ExpandMem,A0 ; Pointer to ExpandMemRec
|
|||
|
MOVE.L emKeyCache(A0),a2 ; Save pointer to KCHR resource
|
|||
|
endwith ;ExpandMemRec
|
|||
|
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
; Call KeyTrans with various modifier key settings
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
ST result(A6) ; Assume we have a match
|
|||
|
BSR DoKeyTrans ; First, call with no modifiers
|
|||
|
BEQ.S DoneTest ; If that gave us a match, hooray
|
|||
|
OR.W #cmdOnMask,d3 ; Turn on Command and try once more
|
|||
|
BSR DoKeyTrans ; Almost done<6E>
|
|||
|
SZ result(A6) ; Our final result
|
|||
|
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
; Clean up and exit
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
DoneTest
|
|||
|
movem.l (sp)+,tlRegs ; restore regs
|
|||
|
UNLK A6 ;
|
|||
|
NoKey
|
|||
|
MOVE.L (SP)+,A0 ; pop return address
|
|||
|
ADDQ.L #tlArgSize,SP ; clean up parameter space
|
|||
|
JMP (A0) ; return to caller
|
|||
|
|
|||
|
endwith ;tlFrame
|
|||
|
endproc
|
|||
|
|
|||
|
;------------------------------------------------------------------------------- <50>
|
|||
|
; GetScript/SetScript for Roman
|
|||
|
;
|
|||
|
; These do nothing but clean up the stack and return a constant value.
|
|||
|
;-------------------------------------------------------------------------------
|
|||
|
|
|||
|
proc
|
|||
|
export RomanGetScript, RomanSetScript
|
|||
|
|
|||
|
gsRecord record {return},decr
|
|||
|
result ds.l 1 ; result code.
|
|||
|
gsArgs equ *-4 ; size of arguments.
|
|||
|
script ds.w 1 ; script code.
|
|||
|
verb ds.w 1 ; verb value.
|
|||
|
selector ds.l 1 ; trap selector.
|
|||
|
return ds.l 1 ; return address.
|
|||
|
gsLocals equ * ; size of local variables.
|
|||
|
endr
|
|||
|
|
|||
|
RomanGetScript
|
|||
|
with gsRecord
|
|||
|
move.l (sp)+,a0 ; pop return address.
|
|||
|
addq #gsArgs,sp ; discard arguments.
|
|||
|
clr.l (sp) ; return value
|
|||
|
jmp (a0) ; return to the caller.
|
|||
|
endwith ;gsRecord
|
|||
|
|
|||
|
ssRecord record {return},decr
|
|||
|
result ds.w 1 ; result code.
|
|||
|
ssArgs equ *-4 ; size of arguments.
|
|||
|
script ds.w 1 ; script code.
|
|||
|
verb ds.w 1 ; verb value.
|
|||
|
param ds.l 1 ; parameter value.
|
|||
|
selector ds.l 1 ; trap selector.
|
|||
|
return ds.l 1 ; return address.
|
|||
|
ssLocals equ * ; size of local variables.
|
|||
|
endr
|
|||
|
|
|||
|
RomanSetScript
|
|||
|
with ssRecord
|
|||
|
move.l (sp)+,a0 ; pop return address.
|
|||
|
add.w #ssArgs,sp ; discard arguments.
|
|||
|
move.w #smBadVerb,(sp) ; set error code.
|
|||
|
jmp (a0) ; return to the caller.
|
|||
|
endwith ;ssRecord
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
|
|||
|
; ---------------------------------------------------------------------------- <54>
|
|||
|
; function: CharType(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 information about a character, including character type, punctuation
|
|||
|
; type, and case. For RIS, this is reduced to a simple table lookup.
|
|||
|
; ----------------------------------------------------------------------------
|
|||
|
|
|||
|
proc
|
|||
|
export CharType
|
|||
|
|
|||
|
ctRecord record {a6link},decr
|
|||
|
result ds.w 1 ; result.
|
|||
|
ctArgs equ *-8 ; size of arguments.
|
|||
|
textBuf ds.l 1 ; text buffer pointer.
|
|||
|
textOffset ds.w 1 ; text buffer offset.
|
|||
|
scriptRecPtr ds.l 1 ; Scriptrecord ptr
|
|||
|
return ds.l 1 ; return address.
|
|||
|
a6link ds.l 1 ; old a6 register.
|
|||
|
ctLocals equ * ; size of local variables.
|
|||
|
endr
|
|||
|
|
|||
|
caseBit equ 14 ; case bit index in returned word
|
|||
|
dirBit equ 13 ; dir bit index in returned word <54>
|
|||
|
charMask equ $0f ; mask for character type.
|
|||
|
punctMask equ $70 ; mask for punctuation class in itl2 (L-R scripts)
|
|||
|
rlPunctMask equ $30 ; mask for punctuation class in itl2 (R-L scripts) <54>
|
|||
|
dirBitInItl2 equ 6 ; dir bit number in Itl2 type byte <54>
|
|||
|
|
|||
|
ctRegs reg a2/a3 ;
|
|||
|
|
|||
|
|
|||
|
CharType
|
|||
|
|
|||
|
with ctRecord
|
|||
|
|
|||
|
move.l 4(sp),a0 ; ScriptRecord ptr (maybe nonRoman)
|
|||
|
moveq #0,d2 ; sysFlag=0 in hi word
|
|||
|
move.b ScriptRecord.scriptID(a0),d2 ; script code in low word
|
|||
|
|
|||
|
clr.l -(sp) ; space for returned handle
|
|||
|
move.w #2,-(sp) ; select itl2
|
|||
|
|
|||
|
move.l d2,-(sp) ; two arguments: script code, sysFlag=0
|
|||
|
_IUGetScriptItl ; may trash a0,a1,d0-d2
|
|||
|
move.l (sp)+,d0 ; store itl2 handle
|
|||
|
|
|||
|
move.l (sp)+,a0 ; pop return address.
|
|||
|
move.l (sp)+,d2 ; save scriptRecPtr in d2 <54>
|
|||
|
move.w (sp)+,d1 ; get character offset.
|
|||
|
move.l (sp)+,a1 ; get text buffer pointer.
|
|||
|
movem.l ctRegs, -(sp) ; save regs
|
|||
|
|
|||
|
tst.l d0 ; nil handle?
|
|||
|
beq.s @CharTypeExit ; if so, bail (return 0)
|
|||
|
move.l d0,a2 ; get handle in a2
|
|||
|
clr.l d0 ; for longizing & err return
|
|||
|
move.l (a2),a2 ; dereference
|
|||
|
btst.b #0,itl2FlagsOffset+1(a2) ; extended itl2 tables?
|
|||
|
beq.s @CharTypeExit ; no, bail (returns 0)
|
|||
|
move.l a2,a3 ; copy
|
|||
|
move.w classArrayOffset(a2),d0 ; longize
|
|||
|
add.l d0,a2 ;
|
|||
|
move.w typeListOffset(a3),d0 ;
|
|||
|
add.l d0,a3 ;
|
|||
|
|
|||
|
clr.l d0 ; clear character code.
|
|||
|
move.b 0(a1,d1.w),d0 ; get the character code.
|
|||
|
move.b 0(a2, d0.w),d0 ; get character class and
|
|||
|
move.b 0(a3, d0.w),d0 ; specific type
|
|||
|
|
|||
|
MOVEQ #0,D1 ; clear it, we are going to shit later <8>
|
|||
|
move.b d0,d1 ; punctuation type.
|
|||
|
bpl.s @1 ; move case bit to the
|
|||
|
bset #caseBit,d0 ; left.
|
|||
|
@1 andi.b #charMask,d0 ; isolate character type.
|
|||
|
move.l d2,a1 ; scriptRecPtr <54>
|
|||
|
tst.b ScriptRecord.scriptRight(a1) ; right-to-left script? <54>
|
|||
|
beq.s @dontSetDirBit ; if not, don't check dir bit <54>
|
|||
|
; for right-left scripts, itl2 table has 2 bits for type + 1 dir bit <54>
|
|||
|
btst #dirBitInItl2,d1 ; does byte in table indicate R-L char? <54>
|
|||
|
beq.s @dontSetDirBit ; if not, go handle punct sub-types <54>
|
|||
|
bset #dirBit,d0 ; return R-L direction <54>
|
|||
|
andi.b #rlPunctMask,d1 ; and isolate punctuation sub-type <54>
|
|||
|
bra.s @setType ; <54>
|
|||
|
@dontSetDirBit ; <54>
|
|||
|
andi.b #punctMask,d1 ; isolate punctuation sub-type.
|
|||
|
@setType ; <54>
|
|||
|
lsl.w #4,d1 ;
|
|||
|
or.w d1,d0 ; or punctuation type back
|
|||
|
|
|||
|
@CharTypeExit
|
|||
|
movem.l (sp)+,ctRegs ;
|
|||
|
|
|||
|
move.w d0,(sp) ; into character type.
|
|||
|
jmp (a0) ; return to the caller.
|
|||
|
endWith
|
|||
|
|
|||
|
endproc
|
|||
|
|
|||
|
;____________________________________________________________
|
|||
|
; Routine StyledLineBreak (
|
|||
|
; textPtr: Ptr;
|
|||
|
; textLen: Longint; {must be < 32K ;<2/14/89 pke>}
|
|||
|
; textStart: Longint;
|
|||
|
; textEnd: Longint;
|
|||
|
; flags: Longint;
|
|||
|
; var textWidth: Fixed; {on exit, set if too long}
|
|||
|
; var textOffset: Longint;
|
|||
|
; ): LineCode;
|
|||
|
;____________________________________________________________
|
|||
|
|
|||
|
|
|||
|
LineBreakFrame record {oldA6},decrement
|
|||
|
result ds.w 1
|
|||
|
argSize equ *-8
|
|||
|
textPtr ds.l 1
|
|||
|
textLen ds.l 1
|
|||
|
textStart ds.l 1
|
|||
|
textEnd ds.l 1
|
|||
|
flags ds.l 1
|
|||
|
textWidth ds.l 1
|
|||
|
textOffset ds.l 1
|
|||
|
selector ds.l 1
|
|||
|
return ds.l 1
|
|||
|
oldA6 ds.l 1
|
|||
|
offsets ds.l 3
|
|||
|
leadingEdge ds.b 1
|
|||
|
foundCR ds.b 1
|
|||
|
lineDirection ds.w 1
|
|||
|
oldBlockFlags ds.w 1 ; only a byte is used
|
|||
|
savedTextWidth DS.L 1 ; fixed value
|
|||
|
localFrame equ *
|
|||
|
endR
|
|||
|
|
|||
|
FixMinusOne equ $FFFF0000
|
|||
|
|
|||
|
HiByteFlags EQU ScriptRecord.scriptBundle.itlbFlags
|
|||
|
LoByteFlags EQU HiByteFlags+1
|
|||
|
|
|||
|
LineBreakRegs reg a2-a3/d4-d6
|
|||
|
;____________________________________________________________
|
|||
|
|
|||
|
StyledLineBreak proc EXPORT ; <8>
|
|||
|
|
|||
|
import FindCarriage
|
|||
|
import StdUnlink
|
|||
|
|
|||
|
; setup
|
|||
|
with LineBreakFrame
|
|||
|
CheckSelector
|
|||
|
link a6,#localFrame
|
|||
|
movem.l LineBreakRegs,-(sp)
|
|||
|
|
|||
|
; common args
|
|||
|
move.l textWidth(a6),a3 ; get @width
|
|||
|
move.l textPtr(a6),d5 ; pointer
|
|||
|
add.l textStart(a6),d5 ; pointer+start
|
|||
|
|
|||
|
; save environment and reset
|
|||
|
;!!! generalize for left-right
|
|||
|
move.w teSysJust,lineDirection(a6) ; save just
|
|||
|
move.w #0,teSysJust ; set to LR, disable formating of RL scripts
|
|||
|
|
|||
|
; get current script
|
|||
|
move.w #0,-(sp) ; allocate _FontScript return
|
|||
|
_FontScript ; get current script
|
|||
|
move.w (sp)+,d0 ; current script
|
|||
|
|
|||
|
; get core globals and test: inline instead of trap, for speed
|
|||
|
|
|||
|
lsl.w #2,d0 ; make script code a longword offset <1.9>
|
|||
|
GetSmgrCore a2 ; smgr core globals
|
|||
|
move.l smgrRecord.smgrEntry(a2,d0),a2 ; get the script record ptr
|
|||
|
move.b HiByteFlags(a2),oldBlockFlags(a6) ; save the high byte of the itlb flags
|
|||
|
bclr.b #smsfReverse,HiByteFlags(a2) ; set reverse block bit, disable reversing text for RL scripts
|
|||
|
|
|||
|
; quick check on length
|
|||
|
move.l textEnd(a6),d4 ; get length
|
|||
|
sub.l textStart(a6),d4 ; segment length
|
|||
|
ble @TooLong ; if zero, bail
|
|||
|
tst.l (a3) ; no width (degenerate)
|
|||
|
; changed this so we handle blanks at start of 0-width line. <06/09/89 pke><3>
|
|||
|
bmi @FixNoChars ; fix neg width
|
|||
|
|
|||
|
; first search for a carriage return, try minimum buffer for NPixel2Char
|
|||
|
|
|||
|
MOVE.L D5,A0 ; pass text ptr (TextPtr + start offset)
|
|||
|
MOVE.W D4,D0 ; pass textlength (start offset - end offset)
|
|||
|
BSR FindCarriage ; returns the offset after CR in D1
|
|||
|
MOVE.B D0,foundCR(A6) ; D0=true if a carriage return was found,save this value
|
|||
|
MOVE.W D1,D4 ; update the textlength
|
|||
|
|
|||
|
; now try to find how much of the text (D4) fits in the line pixel width
|
|||
|
|
|||
|
MOVE.L (A3),savedTextWidth(A6) ; save this value, can be changed by NP2C
|
|||
|
MOVE.W #0,-(SP) ; space for result
|
|||
|
MOVE.L D5,-(SP) ; push text ptr
|
|||
|
MOVE.L D4,-(SP) ; push text byte length
|
|||
|
MOVE.L #0,-(SP) ; 0 slop
|
|||
|
MOVE.L (A3),-(SP) ; line pixel width
|
|||
|
PEA leadingEdge(A6) ; leading Edge flag
|
|||
|
MOVE.L A3,-(SP) ; remaing with
|
|||
|
MOVE.W #smOnlyStyleRun,-(SP) ; style run position
|
|||
|
MOVE.L #$00010001,D0 ; 1/1 scaling
|
|||
|
MOVE.L D0,-(SP) ; num
|
|||
|
MOVE.L D0,-(SP) ; denum
|
|||
|
_NPixel2Char ; call trap
|
|||
|
MOVE.L #0,D6 ; longize
|
|||
|
MOVE.W (SP)+,D6 ; pop char offset
|
|||
|
|
|||
|
; if width is zero, fix leadingEdge for FindWord etc.
|
|||
|
|
|||
|
tst.l savedTextWidth(A6) ; zero width?
|
|||
|
bne.s @doneFixleadingEdge ;
|
|||
|
st leadingEdge(a6) ; if so, fix leadingEdge
|
|||
|
@doneFixleadingEdge
|
|||
|
|
|||
|
; check for position being too long
|
|||
|
|
|||
|
move.l d6,d0 ; copy un-offsetted length
|
|||
|
add.l textStart(a6),d6 ; get char offset
|
|||
|
|
|||
|
; if offset > length, return width of text
|
|||
|
|
|||
|
cmp.l d4,d0 ; position at end?
|
|||
|
blt.s @GotCharPos ; no, skip
|
|||
|
tst.b leadingEdge(a6) ; test if D4=D0 and leadingEdge is false
|
|||
|
BEQ.S @GotCharPos ; if so, skip
|
|||
|
TST.B foundCR(A6) ; was a CR found ?
|
|||
|
BEQ.S @TooLong ; the pix width is too big for the line
|
|||
|
MOVE.L D6,D1 ; update D1 with the whole offet <10>
|
|||
|
BRA @ReturnWord ; we had CR so, return a word
|
|||
|
@GotCharPos
|
|||
|
|
|||
|
; get word around char offset
|
|||
|
|
|||
|
move.l textPtr(a6),-(sp) ; ptr
|
|||
|
move.w textLen+2(a6),-(sp) ; length (mod)
|
|||
|
move.w d6,-(sp) ; offset (truncate)
|
|||
|
move.b leadingEdge(a6),-(sp) ; leadingEdge
|
|||
|
move.l MinusOne,-(sp) ; line break table
|
|||
|
pea offsets(a6) ; offset table
|
|||
|
_FindWord ; use trap
|
|||
|
|
|||
|
; test character to see if it is white-space
|
|||
|
; Mark suggests checking to see if VisibleLength would work better here<72> <06/09/89 pke>
|
|||
|
|
|||
|
move.w #0,-(sp) ; allocate return
|
|||
|
move.l textPtr(a6),-(sp) ; ptr
|
|||
|
move.w offsets(a6),-(sp) ; offset
|
|||
|
_CharType ; use trap
|
|||
|
move.w (sp)+,d0 ; get type
|
|||
|
move.l #0,d1 ; longize
|
|||
|
move.w offsets(a6),d1 ; assume second offset ***
|
|||
|
and.w #smcTypeMask+smcClassMask,d0 ; type and class
|
|||
|
cmp.w #smCharPunct+smPunctBlank,d0 ; blank?
|
|||
|
bne.s @ReturnOffset ; no, continue
|
|||
|
btst.b #smsfReverse,oldBlockFlags(a6) ; test reverse block flag
|
|||
|
sne d0 ; 0/-1 left/right
|
|||
|
cmp.b LineDirection+1(a6),d0 ; line = char? (bottom byte of line)
|
|||
|
bne.s @ReturnOffset ; yes, skip to end
|
|||
|
|
|||
|
; here, word is whitespace and direction is ok (script direction = line direction),
|
|||
|
; so return second offset.
|
|||
|
|
|||
|
MOVE.W offsets+2(A6),D1 ; set to second offset
|
|||
|
BRA.S @ReturnWord ; we broke at word boundary
|
|||
|
|
|||
|
@TooLong
|
|||
|
move.l textEnd(a6),d6 ; return width
|
|||
|
move.l #smBreakOverflow,d0 ; set type
|
|||
|
bra.s @Done ; return
|
|||
|
|
|||
|
@ReturnOffset
|
|||
|
tst.l d1 ; break at start?
|
|||
|
bne.s @ReturnWord ; yes, return char
|
|||
|
|
|||
|
move.l textOffset(a6),a0 ; get @textOffset
|
|||
|
tst.l (a0) ; was offset 0 at entry?
|
|||
|
beq.s @ReturnWord ; if so, go return zero offset
|
|||
|
|
|||
|
; have to break word, so backup until length is less.
|
|||
|
|
|||
|
; The most we have to backup is one char, and we only have to do that if
|
|||
|
; leadingEdge is false . We also need to catch the case of d6=0.
|
|||
|
|
|||
|
tst.b leadingEdge(a6) ; leadingEdge?
|
|||
|
bne.s @checkNullOffset ; if T, skip decrement
|
|||
|
sub.l #1,d6 ; decrement
|
|||
|
|
|||
|
BTST.B #smsfSingByte,LoByteFlags(A2) ; is it a single byte script ?
|
|||
|
BNE.S @checkNullOffset ; don't fall thru if single byte script
|
|||
|
|
|||
|
clr.w -(sp) ; allocate return
|
|||
|
move.l d5,-(sp) ; pass text ptr
|
|||
|
move.l d6,d0 ; cur position
|
|||
|
sub.l textStart(a6),d0 ; start of real text
|
|||
|
move.w d0,-(sp) ; count (mod!!!)
|
|||
|
_CharByte
|
|||
|
tst.w (sp)+ ; return 0=single,-1=first,1=last
|
|||
|
ble.s @checkNullOffset ; bail if -1 or 0, ok
|
|||
|
sub.l #1,d6 ; fix for 2-byte chars
|
|||
|
|
|||
|
@checkNullOffset
|
|||
|
tst.l d6 ; are we still >0?
|
|||
|
bgt.s @ReturnChar ; if so, go return a char
|
|||
|
bra.s @FixNoChars1 ; don't redo test for orig offset 0
|
|||
|
|
|||
|
@FixNoChars
|
|||
|
move.l textOffset(a6),a0 ; get @textOffset
|
|||
|
tst.l (a0) ; was offset 0 at entry?
|
|||
|
bne.s @FixNoChars1 ; if not, return 1 char
|
|||
|
moveq #0,d1 ; if so, set zero offset
|
|||
|
bra.s @ReturnWord ; and go return word break
|
|||
|
@FixNoChars1
|
|||
|
|
|||
|
; string is now zero length, make it at least 1 char
|
|||
|
|
|||
|
move.l #1,d6 ; include first char
|
|||
|
|
|||
|
BTST #smsfSingByte,LoByteFlags(A2) ; is it single byte script ?
|
|||
|
BNE.S @ReturnChar ; don't fall thru if single byte script
|
|||
|
|
|||
|
clr.w -(sp) ; allocate return
|
|||
|
move.l d5,-(sp) ; pass text ptr
|
|||
|
move.w #1,-(sp) ; offset
|
|||
|
_CharByte
|
|||
|
tst.w (sp)+ ; return 0=single,-1=first,1=last
|
|||
|
ble.s @ReturnChar ; bail if -1 or 0, ok
|
|||
|
add.l #1,d6 ; fix for 2-byte chars
|
|||
|
|
|||
|
@ReturnChar
|
|||
|
move.l #smBreakChar,d0 ; so, word too long.
|
|||
|
bra.s @Done ; exit
|
|||
|
|
|||
|
@ReturnWord
|
|||
|
moveq #0,d6 ; make long
|
|||
|
move.w d1,d6 ; set to word bound
|
|||
|
|
|||
|
move.l #smBreakWord,d0 ; break at word
|
|||
|
|
|||
|
@Done
|
|||
|
move.l textOffset(a6),a0 ; get @textOffset
|
|||
|
move.l d6,(a0) ; set to char position
|
|||
|
move.b d0,result(a6) ; set result type
|
|||
|
|
|||
|
; restore environment
|
|||
|
|
|||
|
move.b oldBlockFlags(a6),HiByteFlags(a2) ; restor the high byte of itlb flags
|
|||
|
move.w lineDirection(a6),teSysJust ; restore just
|
|||
|
|
|||
|
; cleanup
|
|||
|
movem.l (sp)+,LineBreakRegs
|
|||
|
CheckA6
|
|||
|
|
|||
|
move #argSize, d0 ; for StdUnlink
|
|||
|
bra StdUnlink ; standard exit
|
|||
|
endWith
|
|||
|
endProc
|
|||
|
|
|||
|
;____________________________________________________________
|
|||
|
; Routine FindCarriage
|
|||
|
; Input a0.l ptr
|
|||
|
; d0.w length
|
|||
|
; Output d0.b $FF/0 found/not found
|
|||
|
; d1.w offset from ptr to char after CR; =length if CR not found
|
|||
|
; Uses Pascal regs
|
|||
|
;____________________________________________________________
|
|||
|
|
|||
|
FindCarriage proc
|
|||
|
With smgrRecord, scriptRecord ; <8>
|
|||
|
|
|||
|
move.w d0,d1 ; copy for later
|
|||
|
move.b #$0D,d2 ; carriage return
|
|||
|
bra.s @CheckLength ; zero check
|
|||
|
@CarriageLoop
|
|||
|
cmp.b (a0)+,d2 ; is it?
|
|||
|
@CheckLength
|
|||
|
dbeq d0,@CarriageLoop ; keep going?
|
|||
|
beq.s @GotCarriage ; not found
|
|||
|
sf d0 ; signal caller
|
|||
|
bra.s @FindCarriageDone ; done
|
|||
|
|
|||
|
@GotCarriage
|
|||
|
; found a CR. Set up length and leftside. length is to character AFTER cr.
|
|||
|
|
|||
|
sub.w d0,d1 ; - characters left (+1) <2/14/89 pke><3>
|
|||
|
|
|||
|
st d0 ; signal caller
|
|||
|
|
|||
|
@FindCarriageDone
|
|||
|
rts
|
|||
|
endWith
|
|||
|
endProc
|
|||
|
;____________________________________________________________
|
|||
|
|
|||
|
end
|