mac-rom/Toolbox/ScriptMgr/DblByteCompat.a

229 lines
8.7 KiB
Plaintext
Raw Normal View History

;
; File: DblByteCompat.a
;
; Contains: See Dan's heart-wrenching tale below<6F>
;
; Written by: Dan Quayle
;
; Copyright: <09> 1992 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM2> 11/3/92 SWC Changed ScriptEqu.a->Script.a.
; <3> 4/17/92 JSM Moved this file from {IntAIncludes}DblByteCompatPriv.a to
; {ScriptMgr}DblByteCompat.a.
; <2> 1/15/92 SMB Remove END. Moved equates, records and macros to ScriptPriv.a.
; <1> 1/14/92 SMB first checked in
;
;
;-------------------------------------------------------------------------------------
;
; So what is this nightmare??
; Once long, long ago there was going to be a new age for KanjiTalk with an elegant
; method for doing input methods. The design proceeded it was sweet and clear as a
; child's eyes. But then things started to darken, angry war clouds darkened the
; sky and the titans of Ops/Tech and Cupertino did battle once again.
;
; When the sky cleared there were many causualities, but perhaps the greatest was
; the need to support old input methods. Thus this ugly, ugly file.
;
; The deal is that we hacked together an Init that supports old input methods.
; We also decided that new input methods should be selectable from the Apple Menu
; just the way keyboards have been since 7.0.
;
; In the pre-7.0 kanjitalk you selected FEPs from a control panel just like
; you select keyboards from a control panel. The original (apparently not very clear)
; thinking was that old feps would still be selected from the old cdev. But feps
; be they old or new are much more complicated. For example, when you pick one
; you have to turn off another that might be on.
; The old cdev couldn't just handle the old ones because it has no way of knowing about
; anybody selecting the new ones
;
; So we have to put all the responsibility on the keyboard menu. Which now displays old
; and new input methods for CJK scripts and keyboards for all other scripts.
;
; There are 4 switching conditions to worry about:
; old input method -> old input method
; old input method -> new input method
; new input method -> new input method
; new input method -> old input method
;-------------------------------------------------------------------------------------
Include 'SysEqu.a'
Include 'Script.a' ; Public Script manager equates
Include 'ScriptPriv.a' ; Private Script manager equates. <1>
Include 'Traps.a'
; Moved ScriptSystemGlobals record, NewScriptSystemGlobals record, intfRecord and selectors
; and error codes for these routines to ScriptPriv.a. This file will now only contain
; code and not templates and equates.
; ----------------------------------------------------------------------------
; Routine: GetIDEntry(table: Handle; id: Integer) : LongInt;
; Input: (sp).l Handle to table.
; (sp).w ID number in entry Record to return.
; Output: (sp).l Item from table.
; Warning: This routine follows Pascal register conventions.
;
; Retreive an item from a table using the ID number.
; ----------------------------------------------------------------------------
gidRecord Record {a6link},decr
entry ds.l 1 ; entry returned from table.
handle ds.l 1 ; table handle.
id ds.w 1 ; id of entry Record to fetch.
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
gidFrame equ * ; size of local variables.
EndR
GetIDEntry Proc Export
With gidRecord,ScriptSystemGlobals,SMgrRecord
link a6,#gidFrame ; link the stack.
move.l a4,-(sp) ; save registers
GetSmgrCore a4 ; load script manager core.
move.l smgrEntry+(smJapanese*4)(a4),a4 ; load doubleTalkRecord for Japanese.
clr.w FISError(a4) ; clear the error global
; Search the table for the given ID number. If we do not find it in the
; table, set an error value and bail out.
move.l handle(a6),a0 ; Load table handle.
move.l (a0),a0 ; Load table pointer.
move.l (a0)+,d0 ; Load table length.
move.w id(a6),d1 ; Load search id number.
bra.s @1 ; enter loop at bottom.
@0 move.l (a0)+,a1 ; Load table entry.
cmp.w (a1),d1 ; same id number?
beq.s @okID ; yes -> we found it!
@1 dbra d0,@0 ; do the next entry.
clr.l entry(a6) ; clear the result.
move.w #euBadID,FISError(a4) ; set the error code.
bra.s @getIDDone ; return to the caller.
; We've found the entry, so save the entry value.
@okID
move.l a1,entry(a6) ; save the result.
; Unlink the stack, remove the arguments, and return to the caller.
@getIDDone
move.l (sp)+,a4 ; restore registers
unlk a6 ; unlink the stack.
move.l (sp)+,a0 ; pop return address.
add.w #6,sp ; pop the arguments.
jmp (a0) ; return to the caller.
EndWith
EndProc
; ----------------------------------------------------------------------------
; Routine GetKanjiUserIDIntf(id: Integer);
; Input sp.w record ID for interface routine.
; Output
; Function If this is a valid record ID, and the new interface is ready,
; deactivate the old interface and activate the new one.
; ----------------------------------------------------------------------------
uidRecord Record {a6link},decr
id ds.w 1 ; interface routine ID number.
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
trueResult ds.w 1 ; activate result.
envRec ds.b SysEnvRec.sysEnv1Size
uidFrame equ * ; size of local variables.
EndR
GetKanjiUserIDIntf Proc Export
With uidRecord,intfRecord,ScriptSystemGlobals,SMgrRecord
link a6,#uidFrame ; link the stack.
movem.l a2-a4,-(sp) ; save the registers.
GetSmgrCore a4 ; load script manager core. <2>
move.l smgrEntry+(smJapanese*4)(a4),a4 ; load doubleTalkRecord for Japanese. <2>
clr.w FISError(a4) ; clear error global
clr.w trueResult(a6) ; clear error result.
; Try to find the new user interface routine. If we cannot find it in
; the table, or it is not ready, return immediately.
@fetchNew
sub.w #4,sp ; make room for the pointer.
move.l intfArray(a4),-(sp) ; push the array handle.
move.w id(a6),-(sp) ; push record ID number.
jsr GetIDEntry ; get the entry.
move.l (sp)+,a3 ; load the record pointer.
tst.w FISError(a4) ; bad index?
bne @noNew ; yes -> bail out.
btst.b #intfFReady-8,intfFlags(a3) ; is it ready?
beq @noNew ; no -> bail out.
; Try to find the old user interface routine. If we cannot find it in
; the table, skip it entirely. Note that this is an attempt at recovery
; since the interface index should always point to a valid interface.
sub.w #4,sp ; make room for the pointer.
move.l intfArray(a4),-(sp) ; push the array handle.
move.w imMethod(a4),-(sp) ; push old Record ID number.
jsr GetIDEntry ; get the entry.
move.l (sp)+,a2 ; load the Record pointer.
tst.w FISError(a4) ; bad index?
bne.s @noOld ; yes -> skip old.
; Deactivate the old user interface and set its flags correctly.
cmp.l a2,a3 ; interface method same?
beq.s @noOld ; yes -> pretend like no old.
btst.b #intfFActive-8,intfFlags(a2) ; old intf active?
beq.s @noOld ; no -> skip deactivate.
move.w intfVol(a2),-(sp) ; push volume refNum.
pea intfFile(a2) ; push file name pointer.
IntfDeactivate ; deactivate old intf.
bclr.b #intfFActive-8,intfFlags(a2) ; clear active bit.
; Set the interface index to the passed index and activate the new user
; interface. Remember to set the flags correctly again and also set
; the saved ID number.
@noOld
move.w id(a6),imMethod(a4) ; set new intf ID.
btst.b #intfFActive-8,intfFlags(a3) ; new intf active?
bne.s @noNew ; yes -> skip activate.
;now get the boot drive so input method can find its dictionaries
lea.l envRec(a6),a0 ; get system folder's <20>volRefNum<75>.
moveq.l #1,d0 ; actually, it<69>s WDRefNum.
_SysEnvirons ; this is calling OpenWD to get it.
move.w SysEnvRec.sysVRefNum(a0),intfVol(a3) ; set new volume refnum.
clr.w FISError(a4) ; clear the error value.
move.w intfVol(a3),-(sp) ; put the volref on the stack
pea intfFile(a3) ; push file name ptr.
IntfActivate ; activate new intf.
tst.w id(a6) ; activating default?
beq.s @0 ; yup, skip error check.
clr.w id(a6) ; assume error, set default id.
move.w FISError(a4),trueResult(a6) ; save true result.
bne @fetchNew ; error -> one more try...
@0 bset.b #intfFActive-8,intfFlags(a3) ; set active bit.
move.w trueResult(a6),FISError(a4) ; set result.
; Restore the registers, unlink the stack, pop the arguments, and return
; to the caller.
@noNew
movem.l (sp)+,a2-a4 ; restore the registers.
unlk a6 ; unlink the stack.
move.l (sp)+,a0 ; Load the return address.
add.w #2,sp ; pop the arguments.
jmp (a0) ; return to the caller.
EndWith
EndProc
End