; ; File: ScriptMgrKbdMenu.a ; ; Contains: Initialization of the new Keyboard Menu in the System Menu bar. ; ; Written by: SMB Sue Bartalo ; ; Copyright: © 1990-1993 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; <43> 4/2/93 YK Initialize D0 to zero before getting a length byte into the ; lowest byte. ; <42> 3/27/93 YK Use system script font for ÔAbout KeyboardsÉÕ menu item. ; <41> 1/19/93 PKE Update include file names: PackMacs.a->Packages.a. No effect on ; objects. ; <40> 6/26/92 SMB #1033660,: When we realized that Simplified Chinese ; TSM-style IMs were not getting correctly installed as a result ; of a flag value being defined incorrectly, we discovered some ; other minor bugs: extra TSM-style IMs were getting installed ; because the inputMethodCount also reflected the old-style IM ; count. Will now use this only for the count of TSM-style IMs and ; will use CJKcount to determine if any input methods are ; installed as appropriate (in BuildKCHRTable, etc.) ; <39> 6/18/92 csd #1030826 : Fixed a bug in BuildIMTable where register d5 ; was being initialized too late. It would get used with garbage ; in it if there were no input methods installed. ; <38> 6/17/92 SMB #1030826,: Check if an old-style IM is "ready" before ; installing it and if not, am updating the KCHR count and IM ; count appropriately. Now using STR# (kKeyboardMenuItemsID) ; instead of STR# (kKeyboardMenuID) Now using intfName instead of ; intfFile for the IM name in the menu. ; <37> 5/31/92 FM Removed obsolete conditional ScriptMgrKeyboardMenu. I would ; like to remove DoCmdKeyEquivalents too but I guess I'll wait on ; that. ; <36> 5/12/92 SMB #1026017,: Removed code that error exited if 'kcs4' is not ; available. If 'kcs4' icon is not available will simply use ; 'kcs#' icon. Also, fixed stupid code in RebuildKeybdMenu that ; causes rebuilding of menu d.s. to crash when a menu isn't ; available. #1029051, 1029243, 1024274 also. ; <35> 4/8/92 SMB #1026904,: #1026904,: Must set ResLoad to true around ; call to localGetIndString for the ÔAbout KeyboardsÉÕ string. The ; resource was getting purged so was using an empty handle; also ; changed the localGetIndString code to test the dereferenced ; handle and to do a LoadResource if the handle was empty (for ; correctness). This removes the dependency on ResLoad being true. ; <34> 4/6/92 SMB #1024274,: General cleanup: remove hardcoding of "About ; KeyboardsÉ" added in <33> when the resource isn't available. Now ; getting "About KeyboardsÉ" using GetIndString; removed ; unnecessary code. Since using "oldJIMCount" for a test rather ; than for a count, now setting a bit "HaveOldJapanIMbit" in ; CJKcount instead. No longer testing for existance of component ; mgr (it exists). Fixed bug in AddMenuItem where old-style IM ; itemRsrcID was getting written to script word instead of ; language word of scriptLangRec. In AddMenuItem, need to call ; SetScript with secret script flag 'kUsingOldInputMethodVerb' ; when old-style IM becomes the default (after call to InformTSM). ; In RebuildKeybdMenu, the equ for frame size was above the local ; variable menuH, so the link instruction wasn't actually grabbing ; enough stack space. Fixed now; been around since the routines ; inception. (also, probably the writing to 0 bug: 1024274). ; <33> 2/22/92 KST Fixed 2 bugs related to "menuItemStringHdl": 1. If we can't get ; the resource, menuItemStringHdl was not cleared. 2. Need to make ; menuItemStringHdl non-purgeable because the code set ResLoad to ; false. Bad thing happened when the resource got purged. ; <32> 2/22/92 KST Rewrite code to get IconSuite from Component. Changed TSM design ; and removed "GetKeyboardIconSuite" call. Also add a field ; "oldJIMCount" in the stack frame to keep the old Japanese input ; method count. ; <31> 2/19/92 KST Fixed a bug in "MakeIMIconSuite" which trashes A3. ; <30> 2/11/92 DCL Changed the name of TSMEqu.[aph] to TextServices.[aph] for ; better read-ability. ; <29> 2/10/92 KST We now consolidate all default input methods info in one ; resource managed by TSM. So keyboard menu should get this info ; from TSM by calling GetDefaultInputMethod at boot time. ; <28> 1/30/92 JH Right before the loop which starts at label @OldIMLoop the ; intfArray handle is dereferenced and the first long is moved ; into d4. There needs to be a check to see if that first long is ; 0. So adding a beq.s to NoMoreIMs. ; <27> 1/16/92 pvh In OldIMLoop, clear D0 before using it to hold a long word value ; for _BlockMove (D0 had residual trash in the upper word byte ; causing _BlockMove to hose memory). D1 also held the bogus D0 ; value too. ; <26> 1/16/92 DTY Double check the handle to Japanese system globals to make sure ; there actually is a handle. If there is no handle, assume there ; are no old Japanese input methods. ; <25> 1/15/92 SMB Adding code to support old Input MethodsÉ want old-style ; (pre-7.0) Japanese input methods in the kbd menu. Cleanup stack ; problem in MakeKCHRIconSuite & MakeIMIconSuite. ; <24> 1/13/92 SMB Word-align menuFrame again: eliminate tempTwo field since meant ; to replace it with CJKcount in last checkin. ; <23> 1/10/92 SMB #1013637: be sure a script is enabled and not just installed. ; Now adding KCHRs for double-byte scripts when no input methods ; are available. ; <22> 12/13/91 DTY #1018116: BuildIMTable will trash the system heap when it tries ; to add information about components to the end of the installed ; items record but there were no components in the system. Bad ; form, Boss! ;) ; <21> 12/11/91 SMB Rewrite to include Input Methods as well as KCHRs. Renamed ; AuxKeyboardMenuInfo members and KCHRInstalledRec (is now ; ItemInstalledRec) with new names. Bug #1013637 fixed - don't ; show inputs in menu if their script is installed but not ; enabled. Renamed scriptRecord's scriptKCHRCount member to ; scriptInputCount. ; <20> 11/8/91 SMB #1015613 (for CubeE & Bruges) - Fix bug that shows up when an ; application has no menu bar. We really want to use the system ; menu bar (SystemMenuList) and not the current menu bar which may ; be an application's menu bar. ; <19> 2/11/91 PKE smb,#PKE-Sys-020: RebuildKeybdMenu should perform some disposing ; and rebuilding even without a Keyboard menu, so we update if ; Mover has updated the keyboard layouts. Otherwise user can't ; switch to layouts they moved in, or code will try to switch to ; layouts that have been moved out. Note: this fix also requires ; the previous bug fix in <18>. ; <18> 2/11/91 PKE smb,#PKE-Sys-021: RebuildKeybdMenu (called by Mover) trashes a2 ; and d3 (because it doesn't do proper setup and cleanup for its ; call to InitKeybdMenu). ; <17> 1/27/91 PKE stb,#PKE-Sys-016: (Whiteboard bug in 800K install, with no keybd ; icons) InitKeybdMenu error handling code was putting menuH ; handle for DisposHandle on the stack instead of in a0, thus ; messing up the stack and trashing regs across InitKeybdMenu. ; Once menuH was being put in the right place, then another ; problem had to be fixed: it was not valid if there was no menu. ; <16> 1/22/91 SMB (csd) When no kcs resources are installed, needed to pop a3 off ; the stack before an error exit (actually we just don't display a ; keyboard menu. See branches to @ErrCleanup & @StkCleanup. ; <15> 1/7/91 SMB (JDR) Need to modify to always have the Keyboard menu structures ; so the KeyScript verb "NextKeybdInScript" is meaningful (and ; functions!). Now testing smgrKbdMenuAvail in order to do the ; right thing when a menu does/doesn't exist! In RebuildKeybdMenu ; set script manager munged count to tell the Keybd CDEV to ; rebuild it's list of KCHRs. Renamed Icons.a to IconUtilsPriv.a. ; <14> 12/15/90 SMB (gbm) Modified to use the 'kcs4' icon if the 'kcs8' is missing, ; and to guarantee fetching resources from the system resource ; file. Used 'extra' byte in local frame for a new flag, ; usingGenericIcon. Modified use of ResLoad to be a byte op and ; not a word op. Fixed bug in SortKCHRs by looping in the ; outerloop through KCHRcount-1 KCHR in the buffers (instead of ; the KCHRcount-2 KCHRs). This was causing a KCHR to not be ; included in the menu but it would show in the Keybd CDEV since ; it was in the system file. ; <13> 10/30/90 SMB NEEDED for 7.0b2: restore ResLoad before calling SortKCHRs since ; _IUTextOrderSys depends on certain resources being in the system ; heap. ; <12> 9/1/90 SMB Rearranged initial conditions for displaying a menu. Bug fix: if ; only 1 KCHR then don't need to sort in SortKCHRs. ; <11> 8/10/90 SMB Removed the KeyScript call to re-enable the keyboards since ; Mover is now making the call. Added ÔAbout KeyboardsÕ support ; now. ; <10> 8/7/90 SMB Adding guts to RebuildKeybdMenu. Added call to IUTextOrderSys to ; sort the KCHRs alphabetically based on the 'itlm'. Changed ; script's default KCHR indicator to be localizable in the STR# ; resource for the kbd menu. Adding ÔAbout KeyboardsÉÕ (but ; conditionalized out until later.) Temporarily making a KeyScript ; call to re-enable the keyboards if in RebuildKeybdMenu if they ; were disabled. ; <9> 7/16/90 PKE Use new name for field in ExpandMemRec: emItlCache2Ptr is now ; emItlSysCachePtr. Renamed Cache2Rec to NewItlCacheRec. ; <8> 6/22/90 SMB Conditionalizing out more code that expects the Next Keyboard ; and Next Script menu items to exist. Using flag ; DoCmdKeyEquivalents. ; <7> 6/13/90 PKE Put in framework for private RebuildKeybdMenu routine called by ; Mover. This call lets us know that keyboards have been moved ; into or out of the System file. ; <6> 6/13/90 SMB Removing the Next Keyboard and Next Script menu items until ; their command key equivalents can be displayed in the menu. ; <5> 6/5/90 SMB Fixed odd address problem that occurred when initializing the ; menuTitleString and DisabledDashSep by adding a dummy member to ; the Strings record. Also cleaned up some inefficient code and ; initialized a register! Disabled cmd key equivalents for Next ; Keyboard and Next Script menu items. ; <4> 6/1/90 SMB Extended Keyboard Menu to display using sorted script list ; (itl2Cache), and added Next Keyboard and Next Script menu items, ; as well as disabled dividing lines between scripts. Also testing ; itlc showIcon flag to determine whether or not to display the ; keyboard menu. ; <3> 5/31/90 SMB Renaming IconUtils.a to Icons.a. ; <2> 5/13/90 SMB Adding InitKeyboardMenu guts! ; <1> 5/5/90 PKE Added a butchered version of SueÕs new file with a temporary ; stub for InitKeybdMenu routine. Sue will fill this in later. ;___________________________________________________________________________________________________ ; To Do: ; ¥ Update use of d4 (was KCHRcount, is now total menu contents count) to be a long instead of a word ; ¥ If can't get a handle to use for the name of an IM (see @GetIMInfo) need to zero-out the itemInfo ; field and set update the count correctly. May need to do better error-handling after ; _GetComponentInfo too. ; ¥ clean up componentFlags and componentFlagsMask: should the componentFlags be #$00008F00 instead? ; ¥ search for ; ¥ make RebuildKeybdMenu its own proc and move localGetIndString above it. ; ¥ Are the menuitems numbered correctly if no kbd menu is desired and the About menu ; item isn't there? Should check ScriptMgrKeyGetSet for all of this as well. ; ¥ what to do about err result from _DisposeIconSuite? already deleted menu items if a menu exists ; and possibly already deleted icon suites so these leave the menu in a bad state. ;___________________________________________________________________________________________________ load 'StandardEqu.d' ; Private.a, ScriptEqu.a, ... include 'ScriptPriv.a' include 'Packages.a' ; <10><41> include 'IconUtilsPriv.a' ; <15> include 'IntlUtilsPriv.a' ; <10> include 'MenuMgrPriv.a' ; <20> include 'TextServices.a' ; <21> <29> include 'TSMPrivate.a' ; <29> include 'Components.a' ; <21> include 'GestaltEqu.a' ; <21> string pascal proc export InitKeybdMenu export RebuildKeybdMenu ; <7> import StdUnlink ; std unlink & exit <1> ;------------------------------------------------------------------------------- ; FUNCTION InitKeybdMenu: OSErr; ;------------------------------------------------------------------------------- menuFrame record {a6link},decr result ds.w 1 ; OSErr result code. <1> menuArgs equ *-8 ; size of arguments. <1> selector ds.l 1 ; ScriptMgr selector on stack <1> return ds.l 1 ; return address. <1> a6link ds.l 1 ; old link pointer rebuildFlag ds.b 1 ; indicates rebuilding so don't call _InsertMenu <10> ds.b 1 ; unused <21><34> byteAvail ds.b 1 ; word-aligning the stack: use me <25> CJKcount ds.b 1 ; Using low 5 bits: which dbl-byte scripts have an IM: 0 => no IM, ow 1 <23> ; xxxOCCJK KCHRcount ds.w 1 ; number of KCHRs installed <10><21> TSMInputMthdCount ds.l 1 ; input method count (old & new) <21> renamed <25> renamed again (added 'TSM') <40> menuH ds.l 1 ; menuHandle ScriptOrderPtr ds.l 1 ; ptr to ordering of scripts (in emItlSysCache) ItemInstalledRecPtr ds.l 1 ; ptr to ItemInstalledRec ItemOffsetsPtr ds.l 1 ; ptr to record of offsets of ItemInstalledRec for sorting KeyboardMenuPtr ds.l 1 ; ptr to AuxKeyboardMenuInfo record menuItem ds.w 1 ; menuItem number defaultMark ds.w 1 ; marker for default KCHR in each script scriptCount ds.b 1 ; number of scripts still to process <10> usingGenericIcon ds.b 1 ; T=> using a generic icon <14> scriptLangRec ds.l 1 ; contains the script (w) & language (w) <21> compID ds.l 1 ; component identifier <21> NextItemString ds.b 256 CompDesc ds ComponentDescription ; <21> menuLocals equ * ; size of locals endr ; definitions for creating an IconSuite of small color icons for scripts. string asis kcsTable dc.l 'kcs#',Small1BitMask,'kcs4',Small4BitData,'kcs8',Small8BitData string pascal NumItemsAfterKCHRs equ 2 ; Next Keyboard and Next Script KeyboardMenuRegs reg d2-d4/a2-a4 ;*********************************************************************************************** InitKeybdMenu with menuFrame,ItemInstalledRec link a6,#menuLocals clr.w result(a6) ; initialize to return noErr ;----------------------------------------------------------------------------------- <10> ; INITIALIZATIONS ;----------------------------------------------------------------------------------- <10> movem.l KeyboardMenuRegs,-(sp) ; get # of enabled scripts <4> with SmgrRecord GetSMgrCore a2 st smgrKbdMenuAvail(a2) ; assume want menu to display <15> cmp.b #1,smgrEnabled(a2) ; > 1 script enabled? <12> bhi.s @HaveMenuStatus ; yep, display menu <12> ; otherwise, check itlc flag (smfShowIcon) to determine whether or not to show the menu <4> move.l smgrGenFlags(a2),d0 ; <5> btst.l #smfShowIcon,d0 ; bit 31 ON => show icon even if only one script <5> bne.s @HaveMenuStatus ; <15> sf smgrKbdMenuAvail(a2) ; don't want menu to display <15> clr.l menuH(a6) ; set menu handle to NIL <17> @HaveMenuStatus move.b smgrEnabled(a2),scriptCount(a6) ; save count <12> endWith ; <12> ; setup for resource fetch from the system file <14> subq.w #2,sp ; storage for current resource file <14> _CurResFile ; <14> move.w #0,-(sp) ; use system resource file <14> _UseResFile ; <14> move.b ResLoad,-(sp) ; <14> st ResLoad ; set to true <14> ; setup defaultMark for the menu move.w #KeybdDefaultMrk,defaultMark(a6) ; initialize to empty, 0x00 pea NextItemString(a6) ; ptr to Str255 <34> move.w #kKeyboardMenuItemsID,-(sp) ; strListID <34><38> move.w #DefMarkIndex,-(sp) ; string index <34> import localGetIndString ; <34> bsr localGetIndString ; making a pString (rather than a ptr to text) <34> sf ResLoad ; reset to F <14> tst.b NextItemString(a6) ; do we have a string? <34> beq.s @useDefMarker ; if empty, use default marker <32> ; fetch the localized character move.b NextItemString+1(a6),defaultMark+1(a6) ; write out the default marker byte (skip length) <34> @useDefMarker ; Test if menu already exists so know if called from RebuildKeybdMenu <10> sf rebuildFlag(a6) ; assume first time <10> ; Use the system menuBar and not the application menuBar in case appl doesn't have a menuBar (GetMHandle would fail). <20> move.l MenuList,-(sp) ; save the current menuList since it may be an apps menu <20> move.l SystemMenuList,MenuList ; <20> subq #4,sp ; result <10> move.w #kKeyboardMenuID, -(sp) ; menuID <10> _GetMHandle ; <10> move.l (sp)+,menuH(a6) ; <10> move.l (sp)+,MenuList ; restore the menuList <20> tst.l menuH(a6) ; <10> beq.s @NewMenu ; If menu already exists then called from RebuildKeybdMenu <10> st rebuildFlag(a6) ; don't do _InsertMenu <10> ;----------------------------------------------------------------------------------- ; MENU setup ;----------------------------------------------------------------------------------- @NewMenu bsr CountMenuContents ; returns d4.l = to total # of installed inputs ; Allocate ItemInstalledRec table for # of installed KCHRs and Input Methods: move.l d4,d0 ; total number of KCHRs and Input Methods <21> mulu #ItemInstalledRecSz,d0 _NewPtr ,SYS,CLEAR move.l a0,ItemInstalledRecPtr(a6) move.l a0,a4 with smgrRecord,ScriptRecord,itlbRecord,ItemInstalledRec,AuxKeyboardMenuInfo ;----------------------------------------------------------------------------------- bsr BuildIMTable ; Init the ItemInstalledRec table for input methods <21> bsr BuildKCHRTable ; Init the ItemInstalledRec table for KCHRs <21> ;----------------------------------------------------------------------------------- st ResLoad ; must be T for _IUTextOrderSys <14> bsr SortItems ; sort the Items <10> sf ResLoad ; reset to F <14> ;------------------------------------------- ; Allocate AuxKeyboardMenuInfo record for IconSuite handles for MF and other info for SystemMenu patch move.w d4,d0 ; total number of inputs add.b scriptCount(a6),d0 ; # of scripts = # of disabled (separating) lines IF DoCmdKeyEquivalents THEN ; <8> ; Allocate space for empty entry (so can index by menu item #) and entries for items ; beyond KCHRs (so that the iconSuiteH is 0). NumItemsAfterKCHRs=0 if no cmd key items ; so would only +1. Added above in disabled line count <8> add.w #(1+NumItemsAfterKCHRs),d0 ; 1=dummy entry ENDIF add.w #2,d0 ; for "About KeyboardsÉ" & disabled line items <11> mulu #AuxMenuInfoSize,d0 _NewPtr ,SYS,CLEAR move.l a0,KeyboardMenuPtr(a6) GetSmgrCore a1 ; get script manager core. move.l a0,smgrKeyboardMenuPtr(a1) ; save in Smgr Record for MF move.l a0,a2 ; in order to index by menuItem # (not 0-based), must have a dummy entry at the beginning add.w #AuxMenuInfoSize,a2 ; point past empty entry to storage for 1st menuItem. ;----------------------------------------------------------------------------------- <10> ; Make a menu nowÉ ;----------------------------------------------------------------------------------- <10> ; Test if a menu is desired: if not, must still build menu d.s. so that the command-key <15> ; equivalent, cmd-opt-space bar (to switch between keybds. in a script) works. <15> move.w #1,menuItem(a6) ; initialize earlier for bra <15> tst.b smgrKbdMenuAvail(a1) ; do we want to display a menu? <15> beq.s @BuildMenuRec ; <15> ; Do we already have a menu? (are we called from RebuildKeybdMenu?) tst.b rebuildFlag(a6) ; do we already have a menu? <21> bne.s @GotMenuH ; bra if so <21> ; Add a new menu for the Keyboard Menu subq #4,sp ; result: menuHandle move.w #kKeyboardMenuID, -(sp) ; menuID pea #'Susan' ; pString <21> _NewMenu move.l (sp)+,menuH(a6) @GotMenuH ; Add the About KeyboardsÉ menuitem followed by a disabled line <10> st ResLoad ; set to true <35> <14> pea NextItemString(a6) ; ptr to Str255 <34> move.w #kKeyboardMenuItemsID,-(sp) ; strListID <34><38> move.w #AboutKybdsIndex,-(sp) ; string index <34> import localGetIndString ; <34> bsr localGetIndString ; <34> sf ResLoad ; reset to false <35> tst.b NextItemString(a6) ; do we have the string <34> beq.s @BuildMenuRec ; no, don't add AboutKeyboardsÉ <34> ; name the menu item move.l menuH(a6),-(sp) pea NextItemString(a6) ; name of this KCHR: pString move.w menuItem(a6),-(sp) ; insert ÔafterÕ this menuItem _InsMenuItem move.l menuH(a6),-(sp) move.w #1,-(sp) ; the first item has a script code. <42> move.w #$1C,-(sp) _SetItemCmd move.l menuH(a6),-(sp) move.w #1,-(SP) move.w #smSystemScript,-(sp) ; the script code is the sytem script <42> _SetItmIcon add.w #1,menuItem(a6) add.w #AuxMenuInfoSize,a2 ; point past 1st menuItem now bsr AddDisabledLine ; separate scripts by a disabled line <8> ;--------------------------------------------------------------------------- ; Add the menu gutsÉ ;--------------------------------------------------------------------------- @BuildMenuRec ; <15> move.l ItemInstalledRecPtr(a6),a4 ; reset to first KCHRÕs info <10> move.l ItemOffsetsPtr(a6),a3 ; reset ptr move.w (a3)+,d0 ; get offset to KCHR info for this item <10> add.w d0,a4 ;------------------------------------------- ; Currently: ; a2 = ptr to AuxKeyboardMenuInfo (storage for aux menu info for each input) ; a3 = ItemOffsetsPtr ; a4 = ptr to ItemInstalledRec ; d3 = current script # ; d4 = total number of inputs ; d5 = total num of input items thus far in this script ;-------------------------------------------- ; Time to build each menu item and it's auxilliary menu information record ; For each enabled script, loop for the input items and add menu items for each one ;-------------------- ; Scripts loopÉ ;-------------------- @EnabledScriptLoop subq.b #1,scriptCount(a6) ; decr enabled script count moveq #0,d5 ; initialize script's input item count to 0 move.w ItemScript(a4),d3 ; script code ; be sure this script is enabled (bug #1013637) <21> GetSMgrCore a0 move.w d3,d0 lsl.w #2,d0 ; long word offset move.l smgrEntry(a0,d0.w),a0 ; script record of installed script ; loop until cross a script boundary in the KCHR table ;------------------------------- ; Items_within_a_script loopÉ ;------------------------------- @ScriptItemsLoop ; if script not enabled, loop for next input. (a0 set above) tst.b scriptEnabled(a0) ; script enabled? beq.s @NextInput ; bra to fetch next input item if not a valid script ; find out the type of input to build the iconsuite move.b itemInpuType(a4), itemType(a2) ; type of input <25> beq.s @KCHRinput ; bra if this is a KCHR <25> cmp.b #TSMIMitem, itemInpuType(a4) ; is this a new-style input method? <25> bne.s @OldIM ; no, is an old-style input method <34>- replaced 2 branches @NewIM ; this input type is a TSM-style IM move.l itemInfo(a4), auxItemInfo(a2) ; store the component identifier here <21> bra.s @IMIconSuite ; <25> @OldIM move.w itemResID(a4),itemRsrcID(a2) ; save id in AuxKeyboardMenuInfo record move.l #0, auxItemInfo(a2) ; NIL indicates it's not a new-style IM <25> @IMIconSuite bsr MakeIMIconSuite ; <21> bra.s @Add2Menu @KCHRinput ; this input type is a KCHR move.w itemResID(a4),itemRsrcID(a2) ; save id in AuxKeyboardMenuInfo record movem.l d2/d3,-(sp) ; save <36> move.w itemRsrcID(a2),d2 ; store the desired KCHR icon ID <36> move.w #kKeyboardMenuID,d3 ; store the default KCHR icon ID <36> sf usingGenericIcon(a6) ; initial assumption <36> bsr MakeIconSuite ; <36> movem.l (sp)+,d2/d3 ; restore <36> move.l #0, auxItemInfo(a2) ; NIL indicates it's not a new-style Input Method @Add2Menu ; create a new menuItem and save the item order w/in the script in the AuxKeyboardMenuInfo record bsr AddMenuItem ; preserves a0 ;-------------------------------------------- @NextInput ; Get next input! sub.w #1,d4 ; are we out of inputs/menuItems to add? IF NOT DoCmdKeyEquivalents THEN ; bra if done <8> beq.s @SetTitle ; <3>;temporary<6> ELSE beq @SetCmdKeyEquiv ; add Next Keyboard and Next Script <3>;temporary<6> ENDIF add.w #AuxMenuInfoSize,a2 ; point to storage for next menuItem. ; Loop on next input in this script? move.l ItemInstalledRecPtr(a6),a4 ; reset to first KCHRÕs info <10> move.w (a3)+,d0 ; get offset to KCHR info for this item add.w d0,a4 move.w ItemScript(a4),d0 cmp.w d3,d0 ; cmp to current script beq.s @ScriptItemsLoop ; get next KCHR for this script ; Crossed a script boundary IF NOT DoCmdKeyEquivalents THEN ; <8> tst.b scriptCount(a6) ; more enabled scripts? <8> beq.s @SetTitle ; donÕt add disabled line after last KCHR <8> ; if script not enabled, don't add a line. (a0 set above at @EnabledScriptLoop) <23> tst.b scriptEnabled(a0) ; script enabled? <23> beq @EnabledScriptLoop ; bra to fetch next input item if not a valid script <23> bsr AddDisabledLine ; separate scripts by a disabled line <8> ; a2 incremented for next menuitem's info <32> bra @EnabledScriptLoop ; <8> ELSE ; Not really a routine- just a place I've moved the code to get it out of the ; middle of here. Should be put back here if we want to use it. bsr AddCmdKeyMenuItems ENDIF ; <6> ;------------------------------------------------------------------------------------------ ; FINALIZATION ;------------------------------------------------------------------------------------------ ; change the title of the menu to the icon of the system scriptÕs keybd by stuffing ; the iconSuite handle into the string posn holder "Susan" @SetTitle GetSmgrCore a3 ; get script manager core. <15> tst.b smgrKbdMenuAvail(a3) ; do we want to display a menu? <15> beq.s @Cleanup ; <15> move.l menuH(a6),a0 move.l (a0),a0 ; deref ; stuff the length (5 bytes) and special byte into the name: 01 indicates a handle is following move.w #$0501, menuData(a0) ; <21> ; stuff the system script's iconSuite handle into the name move.l KeyboardMenuPtr(a6),a1 ; get item # of default script's KCHR <10><15> move.w smgrSysScript(a3),d0 ; <10> lsl.w #2,d0 ; long word offset <10> move.l smgrEntry(a3,d0.w),a3 ; script record <10> clr.w d0 ; <10> move.b ScriptKeysItemNum(a3),d0 ; <10> mulu.w #AuxMenuInfoSize,d0 ; offset into AuxMenuInfoRec <10> add.w d0,a1 ; <3><10> move.l iconSuiteH(a1),menuData+2(a0) ; now at system script entry <3> endwith ; with smgrRecord,ScriptRecord,itlbRecord,ItemInstalledRec,AuxKeyboardMenuInfo tst.b rebuildFlag(a6) ; if rebuilding donÕt insert menu <10> bne.s @CleanUp ; <10> ; insert the menu now! move.l menuH(a6),-(sp) move.w #0,-(sp) _InsertMenu @Cleanup move.b (sp)+,ResLoad ; <14> ; restore previous (current) resource file <14> _UseResFile ; current resource file ID on stack <14> move.l ItemInstalledRecPtr(a6),a0 _DisposPtr tst.w result(a6) bne.s @done ; don't overwrite with potential DisposPtr error tst.w d0 beq.s @done move.w d0,result(a6) ; will override DisposHandle error if one existed move.l ItemOffsetsPtr(a6),a0 _DisposPtr tst.w result(a6) bne.s @done ; don't overwrite with potential DisposPtr error tst.w d0 beq.s @done move.w d0,result(a6) ; will override DisposHandle error if one existed @done movem.l (sp)+,KeyboardMenuRegs move.w #menuArgs, d0 ; for StdUnlink: number of bytes to clean up bra StdUnlink ; standard exit endwith ; menuFrame,ItemInstalledRec ;formFeed ;----------------------------------------------------------------------------------- ; Utility CountMenuContents <21> ; ; ---- Input ; a6 stack frame, menuFrame ; ; ---- Output ; d4 total # of _installed_ ÔKCHRÕs, Input Methods, (menu items). ;----------------------------------------------------------------------------------- CountMenuContents with menuFrame,ItemInstalledRec,smgrRecord,scriptRecord,ScriptSystemGlobals,intfRecord moveq #0,d4 clr.b CJKcount(a6) ; initialize to no input methods available <34> move.l d4, TSMInputMthdCount(a6) ; initialize <25> <32> ; determine # of KCHR resources in the System file subq #2,sp ; result move.l #'KCHR',-(sp) ; resource type _Count1Resources ; get the number of KCHRs move.w (sp)+,d4 move.w d4,KCHRcount(a6) ; save for KCHR search <10> ;---------------------------------------------------------------------------------- ; count # of old Japanese input methods in the System <25> GetSMgrCore a0 ; get Script Mgr core <25> move.l smgrEntry+(smJapanese*4)(a0),d0 ; get handle to the Japanese system globals <25> <26><34> bz.s @GetNewIMs ; No handle, so assume no old input method. Go find some new ones. <26> move.l d0,a0 ; <26> tst.b scriptEnabled(a0) ; script enabled? <25> beq.s @GetNewIMs ; no Japanese script so get only new IMs now <25> ; get handle to table of input methods move.l intfArray(a0),a0 ; load table handle <25> move.l (a0),a0 ; load table pointer <25> move.l (a0),d0 ; get table length => # of old input methods<25> beq.s @GetNewIMs ; No old input methods. Go find some new ones. <34> add.l d0,d4 ; use reg instead of mem loc for setting d4 <32> bset.b #HaveOldJapanIMbit,CJKcount(a6) ; use bit 5 to indicate a JIM exists <34> ;---------------------------------------------------------------------------------- @GetNewIMs ; set up component description record <21> move.l #kTextService, CompDesc.componentType(a6) ; text service interface type move.l #kInputMethodService, CompDesc.componentSubType(a6) ; specific text service move.l #0, CompDesc.componentManufacturer(a6) ; get the grand total of IMs for a comparison with the compiled total of IMs <40> move.l d3,-(sp) ; save <40> move.l #AllFlags, CompDesc.componentFlags(a6) ; all scripts, languages & takes active key events <40> move.l #ActiveEventMask, CompDesc.componentFlagsMask(a6) ; only care about the active event <40> subq #4,sp ; result <40> pea CompDesc.componentType(a6) ; count components of this desc <40> _CountComponents <40> move.l (sp)+,d3 ; save result <40> ;---------------------------------------------------------------------------------- <23> ; Determine # of input methods in the System but need to know which scripts have them. So, ; do a separate count for each double-byte script and set a bit in the CJKcount byte field of ; menuFrame that indicates whether or not an input method exists for the script. Bits 0 - 4 are ; set thus: (CCJK): bit 4 = simpChinese, bit 3 = tradChinese, bit 2 = Japanese, bit1 = Korean <23> ; Bit 5 is set above if an old-style Japanese IM is available. <34> ;---------------------------------------------------------------------------------- <23> move.w d2,-(sp) ; save around calls to CountDblByteIMs <25> move.l #ScriptActiveEventMask, CompDesc.componentFlagsMask(a6) ; now care about the script & active event <23> ; count # of simplified Chinese Input Methods in the System <23> move.l #SimpChineseFlags, d0 ; simpChinese script & takes active key events move.b #HaveSimpChineseIMbit,d2 bsr CountDblByteIMs ; <25> ; count # of traditional Chinese Input Methods in the System <23> move.l #TradChineseFlags, d0 ; tradChinese script & takes active key events move.b #HaveTradChineseIMbit,d2 bsr CountDblByteIMs ; <25> ; count # of Japanese Input Methods in the System <23> move.l #JapaneseFlags, d0 ; Japanese script & takes active key events move.b #HaveJapaneseIMbit,d2 bsr CountDblByteIMs ; <25> ; count # of Korean Input Methods in the System <23> move.l #KoreanFlags, d0 ; Korean script & takes active key events move.b #HaveKoreanIMbit,d2 bsr CountDblByteIMs ; <25> ; compare grand total of IMs to compiled total to see if more exist beyond specifics above <40> cmp.l TSMInputMthdCount(a6),d3 ; are the totals the same <40> ble.s @TSMCountOK ; if so, done <40> sub.l TSMInputMthdCount(a6),d4 ; remove compiled totals from total count of KCHRs and IMs <40> move.l d3,TSMInputMthdCount(a6) ; use grand total of IMs instead of compiled<40> add.l d3,d4 ; add grand total instead <40> @TSMCountOK move.w (sp)+,d2 ; restore <25> move.l (sp)+,d3 ; restore <25> rts endWith ; menuFrame,ItemInstalledRec,smgrRecord,scriptRecord,ScriptSystemGlobals,intfRecord ;formFeed ;----------------------------------------------------------------------------------- ; BuildKCHRTable ; Initialize the ItemInstalledRec table for the KCHRs ; Adjusts input count for KCHRs in a double-byte script: will add KCHRs for ; double-byte scripts with no input methods. ; ; ---- Input ; a4 ItemInstalledRecPtr(a6) ; d4 total count of installed KCHRs & IMs ; ; ---- Register usage ; d3 loop counter ; d5 KCHRs in a double-byte script ; ; ---- Output ; a4 ItemInstalledRecPtr(a6) is pointing to next available space ;----------------------------------------------------------------------------------- BuildKCHRTable with menuFrame,ItemInstalledRec ; Build table for all KCHRs' res handles, ids, and scripts (whether belong to an enabled script or not) moveq #0,d5 ; assume no KCHRs in a double-byte script move.l d4,-(sp) ; save total count move.w KCHRcount(a6),d4 ; only want KCHRs moveq #1,d3 ; start indexing with first ind resource @GetKCHRLoop subq #4,sp ; result move.l #'KCHR',-(sp) ; resource type move.w d3,-(sp) ; push the index value _Get1IxResource move.l (sp),itemHandle(a4) ; get the KCHR ID corresponding to the KCHR handle --------------------------------------- <10> pea itemResID(a4) ; get the ID clr.l -(sp) ; donÕt need type pea itemName(a4) ; push ptr to name string _GetResInfo ; get the name, etc. ; get the script # from the ÔKCHRÕ ID: (KCHR id - #16384)/#512 + 1 move.l #smRoman,d1 ; initialize to Roman script move.w itemResID(a4),d0 sub.w #smFondStart,d0 ; beginning of non-Roman resource IDs (zero base KCHR #) bmi.s @HaveScript moveq #9,d1 ; shift amt lsr.w d1,d0 ; get into script range (div by 2^9) addq.w #1,d0 ; get real script # move.w d0,d1 ; move script to d1 for test ;-------------------------------------------------- <23> ; if the script is a double-byte script and no IM components are available, add the KCHRs ; if the appropriate bit is set in CCJKcount(a6) then have IMs for the script. tst.b CJKcount(a6) ; are there any input methods? <40> bz.s @HaveScript ; no, so add these KCHRs. ; are we the simplified Chinese (19) script? cmp.w #smSimpChinese,d0 bgt.s @HaveScript ; bra if not a double-byte script bne.s @TestKorean ; not simp. Chinese but maybe another dbl-byte script ;yep so check if any simplified Chinese IMs <23> btst.b #HaveSimpChineseIMbit, CJKcount(a6) ; <25> beq.s @HaveScript ; no IMs so add KCHRs for this script bra.s @dbKCHRCount @TestKorean ; are we the Korean script? cmp.w #smKorean,d0 bne.s @TestTradChinese ;yep so check if any Korean IMs <23> btst.b #HaveKoreanIMbit, CJKcount(a6) ; <25> beq.s @HaveScript ; no IMs so add KCHRs for this script bra.s @dbKCHRCount @TestTradChinese ; are we the traditional Chinese script? cmp.w #smTradChinese,d0 bne.s @TestJapanese ;yep so check if any traditional Chinese IMs <23> btst.b #HaveTradChineseIMbit, CJKcount(a6) ; <25> beq.s @HaveScript ; no IMs so add KCHRs for this script bra.s @dbKCHRCount @TestJapanese ; are we the Japanese script? cmp.w #smJapanese,d0 bne.s @HaveScript ; not a double-byte script ;yep so check if any Japanese IMs <23> btst.b #HaveJapaneseIMbit, CJKcount(a6) ; <25> bne.s @dbKCHRCount ; TSM-style JIMs exist so don't add KCHRs btst.b #HaveOldJapanIMbit, CJKcount(a6) ; any old-style JIMs? <34> beq.s @HaveScript ; no IMs so add KCHRs for this script <34> ; fall into @dbKCHRCount ;-------------------------------------------------- <23> @dbKCHRCount add.w #1,d5 ; count of unincluded KCHRs in a double-byte script bra.s @GetNextKCHR @HaveScript move.w d1,itemScript(a4) ; end of changes here --------------------------------------- <10> move.l #0,itemInfo(a4) ; NIL means not an Input Method (for now) <21> move.b #KCHRitem, itemInpuType(a4) ; this is a KCHR <25> add.w #ItemInstalledRecSz,a4 @GetNextKCHR addq #1,d3 ; bump the index cmp d4,d3 ; compare with the count ble @GetKCHRLoop ; loop if more to do move.l (sp)+,d4 ; restore total sub.w d5,d4 ; adjust to not include KCHRs in a double-byte script sub.w d5,KCHRcount(a6) ; adjust total KCHR count <38> rts endWith ; menuFrame,ItemInstalledRec ;formFeed ;----------------------------------------------------------------------------------- ; BuildIMTable <21> ; Initialize the ItemInstalledRec table for the Input Methods, both TSM-style and old-style ; ; ---- Input ; a4 ItemInstalledRecPtr(a6) is pointing to next available space (beyond KCHRs) ; d4 total count of installed input methods ; ; ---- Register usage ; d3 loop counter ; d5 6.x-style IMs not installed ; a0,a1 ; ; ---- Output ; a4 ItemInstalledRecPtr(a6) is pointing beyond Input Methods ;----------------------------------------------------------------------------------- BuildIMTable with menuFrame,ItemInstalledRec, smgrRecord, scriptRecord, ScriptSystemGlobals, intfRecord move.l d4,-(sp) ; save total count moveq #0,d5 ; assume no IMs that won't install <38><39> move.l TSMInputMthdCount(a6),d4 ; only want TSM-style input methods bz @DoOldIMs ; if no TSM-style input methods at all, check for old-style IMs <40> moveq #1,d3 ; start indexing with first ind resource ;-------------------------------------------------------------------------------------------- ; set up component description record to only fetch input methods for CJK scripts move.l #kTextService, CompDesc.componentType(a6) ; text service interface type move.l #kInputMethodService, CompDesc.componentSubType(a6) ; specific text service move.l #0, CompDesc.componentManufacturer(a6) move.l #$FFFFFFFF, CompDesc.componentFlags(a6) move.l #$00008000, CompDesc.componentFlagsMask(a6) ; we care about 2-byte scripts & taking active key events ; smJapanese = 1, smTradCh = 2, smKorean = 3, smSimpCh = $19 ; initial search: get TSM-style IM and then old-style IMÉ subq #4,sp ; result: component identifier move.l #0,-(sp) ; initial component of NIL => search all components pea CompDesc(a6) ; find components of this desc _FindNextComponent move.l (sp), itemInfo(a4) ; component identifier: use as input on next call move.l (sp)+, compID(a6) ; need for next FindNextComponent call cmp.l #0, itemInfo(a4) ; 0 => no more matching components beq @DoOldIMs ; <25> bra.s @GetIMInfo @GetIMLoop subq #4,sp ; result: component identifier move.l compID(a6),-(sp) ; start search after this component move.l #0, CompDesc.componentManufacturer(a6) move.l #$FFFFFFFF, CompDesc.componentFlags(a6) move.l #$00008000, CompDesc.componentFlagsMask(a6) ; we care about 2-byte scripts & taking active key events pea CompDesc(a6) ; find components of this desc _FindNextComponent move.l (sp), itemInfo(a4) ; component identifier: use as input on next call move.l (sp)+, compID(a6) ; need for next FindNextComponent call cmp.l #0, itemInfo(a4) ; 0 => no more matching components beq.s @DoOldIMs ; <25> @GetIMInfo ; must create a handle for the name moveq #0,d0 ; 0 length _NewHandle bne.s @DoOldIMs ; error in d0 (CCs set) <25> move.l a0,itemHandle(a4) ; should I branch to @NoMoreIMs?? not getting a handle may preclude other work being doneÉ ; should 0-out the itemInfo field and update the count to reflect a nil handle!! ; get name subq #2,sp ; OSErr result move.l itemInfo(a4),-(sp) ; get more info on this component pea CompDesc(a6) ; VAR: component description space move.l itemHandle(a4),-(sp) ; name handle: receives component name move.l #0,-(sp) ; NIL => don't care about component's info string move.l #0,-(sp) ; NIL => for now don't care about the icon since really want an IconSuite _GetComponentInfo tst.w (sp)+ bne.s @DoOldIMs ; bra if error (invalidComponentID) <25> ; now save name move.l itemHandle(a4),a0 ; double deref handle move.l (a0),a0 ; pointer to name lea itemName(a4),a1 ; ptr to name space on stack moveq #0,D0 ; clear high bytes for BlockMove move.b (a0)+,d0 ; get the length of this string move.b d0,(a1)+ ; store the length in the string (make a pString!) move.w d0,d1 ; save the length _BlockMove ; copy it into theString clr.b 0(a1,d1) ; set terminator byte move.l itemHandle(a4),a0 ; get rid of handle now _DisposeHandle ; inicate a new input method move.b #TSMIMitem, itemInpuType(a4) ; this is a new IM <25> ; get script move.l CompDesc.componentFlags(a6),d0 and.l #ScriptMask, d0 ; only care about script code in low word lsr.w #8,d0 ; shift script to low nibble move.w d0,itemScript(a4) add.w #ItemInstalledRecSz,a4 addq #1,d3 ; bump the index cmp d4,d3 ; compare with the count ble @GetIMLoop ;-------------------------------------------------------------------------------------------- @DoOldIMs ; now get old input methods btst.b #HaveOldJapanIMbit,CJKcount(a6) ; optimized: is there an old JIM <34> beq.s @NoMoreIMs ; no, so done <32> GetSMgrCore a1 ; get Script Mgr core <25> move.l smgrEntry+(smJapanese*4)(a1),a1 ; get handle to the Japanese system globals <25> <26><34> move.l a2,-(sp) ; save <25> move.l a1,a2 ; get handle to table of input methods move.l intfArray(a2),a2 ; load table handle <25> move.l (a2),a2 ; load table pointer <25> move.l (a2)+,d4 ; get # of old input methods <25> beq.s @RestoreA2 ; if there aren't any restore a2 and get out!!!! <28> @OldIMLoop ; pointer to next input method is in a2 move.l (a2)+,a0 ; input method source ; check if this input method is "ready" before installing it <38> btst.b #intfFReady-8,intfFlags(a0) ; is the IM ready? <38> bne.s @InstallIM ; yes, install it <38> add #1,d5 ; no, so be sure to decrement totals <38> bra.s @GetNextIM ; fetch the next one <38> @InstallIM ; get ID and save move.w intfID(a0),itemResID(a4) ; store the ID here <25> ; get and save name lea intfName(a0),a0 ; changed from intfFile to intfName <38> lea itemName(a4),a1 ; ptr to name space on stack clr.l d0 ; clear this space! <27> move.b (a0)+,d0 ; get the length of this string move.b d0,(a1)+ ; store the length in the string (make a pString!) move.w d0,d1 ; save the length _BlockMove ; copy it into theString clr.b 0(a1,d1) ; set terminator byte ; get script move.w #smJapanese,itemScript(a4) ; the only old-style input method supported <25> ; indicate an old input method move.l #0, itemInfo(a4) move.b #oldIMitem, itemInpuType(a4) ; this is an old IM <25> add.w #ItemInstalledRecSz,a4 ; point to next storage place <25> @GetNextIM subq #1,d4 ; if non-zero, loop for the next IM <25> bne.s @OldIMLoop ;-------------------------------------------------------------------------------------------- @RestoreA2 ; added new label for branch we take if there aren't any old IMs <28> move.l (sp)+,a2 ; restore <25> @NoMoreIMs move.l (sp)+,d4 ; restore total sub.w d5,d4 ; adjust total kbd & IM count <38> rts endWith ; menuFrame,ItemInstalledRec,smgrRecord,scriptRecord,ScriptSystemGlobals,intfRecord ;formFeed ;----------------------------------------------------------------------------- ; MakeIconSuite ; ; ---- Input ; a2 ptr to AuxKeyboardMenuInfo (storage for each KCHRÕs iconSuiteH) ; d2 ID of kcs icon suite ; d3 default input icon ID (either kKeyboardMenuID or kDefaultIMIconID) ; a6 stack frame, menuFrame ; usingGenericIcon(a6) flag set as desired on entry ; ---- Register usage ; a3 kcsTable: array of icon resource types ; d6 loop counter ; ; ---- Output ; iconSuite created and handle stored in AuxKeyboardMenuInfo ; result(a6) set appropriately ;----------------------------------------------------------------------------- MakeIconSuite iconSuiteRegs reg a0/a3/d6 with menuFrame, AuxKeyboardMenuInfo movem.l iconSuiteRegs,-(sp) ; save ptr to script record and a3 ; create an empty icon suite sub.w #2,sp pea iconSuiteH(a2) ; storage for this iconSuite _NewIconSuite move.w (sp)+,d0 move.w d0,result(a6) ; save (shouldn't affect CCs) bne.s @Done ; error exit really <23> ; get a handle to each scriptÕs small icon resource (Ôkcs#Õ,Ôkcs4Õ,Ôkcs8Õ) and stuff in the icon suite lea kcsTable,a3 move.l #2,d6 ; loop through for each small icon type (0 based) @KcsLoop subq #6,sp ; results for next 2 trap calls: resource handle & OSErr tst.b usingGenericIcon(a6) ; do we want to or have we already used the generic icon? <14> bne.s @UseGeneric ; yes, so keep using it. <14> move.l (a3),-(sp) ; get small color icon resource type (Ôkcs#Õ,Ôkcs4Õ,Ôkcs8Õ) move.w d2,-(sp) ; the icon id _Get1Resource tst.l (sp) bne.s @GotResource ; if the 'kcs#' is missing for this icon then use generic icon <14> cmp.l #'kcs#',(a3) ; is this a 'kcs#' that's missing? <14> bne.s @GotResource ; if not, use 'kcs#' icon on color machine ; use the generic small icons since no icon exists for this KCHR ; result space already on the stack st usingGenericIcon(a6) ; using generic icon for this KCHR <14> @UseGeneric ; <14> move.l (a3),-(sp) ; get small color icon resource type move.w d3,-(sp) ; the generic icon id is different for KCHRs and IMs _Get1Resource ; if 'kcs4' is missing use 'kcs#' icon by passing NIL as the resource ID ; if 'kcs8' is missing use 'kcs4' icon by passing NIL as the resource ID bra.s @AddIcon @GotResource cmp.b #TSMIMitem,itemType(a2) ; is this a TSM-style input method? bne.s @AddIcon ; if not, skip detachment of resource ; if we load the icon from component's resfile, then detach the resource, make a handle ; and keep it around move.l (sp),-(sp) ; push the handle _DetachResource ; this resource has to be detatched movea.l (sp),a0 ; a0 = handle _HNoPurge ; this handle cannot be purgeable @AddIcon add.l #4,a3 ; point past small color icon type ; result space and resource handle are on the stack already move.l iconSuiteH(a2),-(sp) move.l (a3)+,-(sp) ; IconUtils expects specific types (Small1BitMask,Small4BitData,Small8BitData) _AddIconToSuite move.w (sp)+,d0 ; set CCs move.w d0,result(a6) ; save but doesn't affect CCs bne.s @Done ; cleanup stack and error exit <16> dbra d6,@KcsLoop @Done movem.l (sp)+,iconSuiteRegs ; restore ptr to script record and a3 <23> rts endwith ; menuFrame ;formFeed ;----------------------------------------------------------------------------- ; MakeIMIconSuite ; Complete rewrite to use the new way of fetching iconSuite for Input Methods. <32> ; We're not using "GetKeyboardIconSuite" anymore. We get the icon resources directly from <32> ; Component resource file. By doing this, we don't need to open each Input Method. <32> ; If a TSM-styled Input Methods does not have icon resource, then we'll use <32> ; generic keyboard icon to make an iconSuite. <32> ; Got a facelift to use common routine MakeIconSuite <36> ; ---- Input ; a2 ptr to AuxKeyboardMenuInfo (storage for each KCHRÕs iconSuiteH) ; a4 ptr to ItemInstalledRec ; a6 stack frame, menuFrame ; ; ---- Register usage ; d2 ; d3 ; d4 resFile open flag for TSM-style IMs (0 => component resfile is not open) ; d4.w > 0 means component resfile is open ; d5 d5.b = saved resload flag ; d6 d6.w = 0 means resource chain has not altered, otherwise = current resfile ; ; ---- Output ; iconSuite created and handle stored in AuxKeyboardMenuInfo ;----------------------------------------------------------------------------- MakeIMIconSuite IMiconSuiteRegs reg d2-d6/a0 with menuFrame, AuxKeyboardMenuInfo, ItemInstalledRec movem.l IMiconSuiteRegs,-(sp) ; save move.w itemRsrcID(a2),d2 ; store the desired old-style IM icon ID move.w #kDefaultIMIconID,d3 ; store the default IM icon ID st usingGenericIcon(a6) ; initial assumption if old-style IM moveq #0,d4 ; component resfile not open flag move.w d4,d6 ; d6.w = 0 means resource chain has not altered move.b ResLoad,d5 ; d5.b = saved resload flag cmp.b #oldIMitem,itemType(a2) ; is this an old-style input method? beq.s @doIt ; yes, so use the default icon ; have a TSM-style input method: get the icon resource ID for the IM sf usingGenericIcon(a6) ; initial assumption if TSM-style IM clr.w result(a6) ; default = no error ; save current res file before opening the component res file subq.l #2,sp ; room for result _CurResFile ; get current res file move.w (sp)+,d6 ; d6 = current resfile subq #2,sp ; room for refnum move.l auxItemInfo(a2),-(sp) ; component identifier _OpenComponentResFile ; open the resfile move.w (sp)+,d4 ; get the refnum ble.s @UseGeneric ; can't open so use default IM icon ; crummy assumption about the resource icon ID being at the bottom of the script range but ; it has to be this way for TSM (per John and Kenny)É note the detachment of the resource ; in MakeIconSuite for this messÉ move.w ItemScript(a4),d2 ; use script code to ... subq #1,d2 ; calculate the ... lsl.w #8,d2 ; resource id add.w d2,d2 ; (code-1)*512 add.w #smFondStart,d2 ; d2.w = resource id subq #4,sp ; results for resource handle move.l #'kcs#',-(sp) ; get small keyboard icon resource type move.w d2,-(sp) ; icon resource id _Get1Resource move.l (sp)+,d0 ; do we get the icon? beq.s @noResource ; no ; if we are loading from component's resfile, better set resload to true ... st ResLoad ; set to true bra.s @doIt ; yes, use common code ; if we can't load the resource, then close the resfile and use the generic small ; icons since no icon exists for this IM @noResource sub.w #2,sp ; room for result move.w d4,-(sp) ; refnum _CloseComponentResFile tst.w (sp)+ ; pop result moveq #0,d4 ; d4 = 0 means component resfile is not open ; fall into generic icon path @UseGeneric st usingGenericIcon(a6) ; initial assumption @doIt bsr MakeIconSuite ; done, so cleanup tst.w d4 ; is resfile open? ble.s @ResChainAltered ; no sub.w #2,sp ; room for result move.w d4,-(sp) ; refnum _CloseComponentResFile tst.w (sp)+ ; pop result @ResChainAltered tst.w d6 ; have we changed resource chain? beq.s @RestoreResLoad ; no move.w d6,-(sp) ; refnum on stack _UseResFile ; restore res file @RestoreResLoad move.b d5,ResLoad ; restore state movem.l (sp)+,IMiconSuiteRegs rts endwith ; menuFrame ;formFeed ;----------------------------------------------------------------------------- ; AddMenuItem ; ; Add this new menuItem (a KCHR) to the Keyboard Menu. ; Called from InitKeyboardMenu. ; Using the a6 link from InitKeyboardMenu. ; ; ---- Input ; d3 = script # ; d5 = total num of inputs thus far in this script ; a2 = ptr to AuxKeyboardMenuInfo (storage for each KCHRÕs iconSuiteH) ; a4 = ptr to ItemInstalledRec ; a6 = stack frame, menuFrame ; ; Register usage: ; d3 = menuItem (total # of KCHRs) ; d4 = system keyscript ; d5 = total num of KCHRs thus far in this script (incr here!) ; a2 = ptr to AuxKeyboardMenuInfo (storage for each KCHRÕs iconSuiteH) ; a3 = ptr to script mgr record & then, script record ; ; trashes a1 <#29> ;----------------------------------------------------------------------------- AddMenuItem with menuFrame, ItemInstalledRec, AuxKeyboardMenuInfo AddMenuRegs reg d3/d4/a0/a2-a4 ; save a0, too <23> movem.l AddMenuRegs,-(sp) ; initializations with smgrRecord GetSMgrCore a3 move.w smgrKeyScript(a3),d4 ; get default keyscript lsl.w #2,d3 ; long word offset move.l smgrEntry(a3,d3.w),a3 ; script record move.w menuItem(a6),d3 ; item # (also, indicates the total # of inputs) ; if there's no menu then don't set item info <15> GetSMgrCore a1 ; <15> tst.b smgrKbdMenuAvail(a1) ; <15> beq.s @savePosn ; <15> endWith ; name the menu item move.l menuH(a6),-(sp) pea itemName(a4) ; name of this KCHR: pString move.w d3,-(sp) ; insert ÔafterÕ this menuItem _InsMenuItem ; set script in the item by setting the cmd to be $1C and the icon to the script # move.l menuH(a6),-(sp) move.w d3,-(sp) move.w #scriptMenuCmd,-(sp) ; indicates scripted text _SetItemCmd move.l menuH(a6),-(sp) move.w d3,-(sp) move.w itemScript(a4),-(sp) _SetItmIcon @savePosn ; set input count (also is the ordering within its script in the menu) in the AuxKeyboardMenuInfo record with ScriptRecord, smgrRecord add.w #1,d5 move.w d5,itemScriptPosn(a2) move.b d5,scriptInputCount(a3) ; save the script's input (KCHR or Input Method) count ; if this is the script's default then save its item #: process by type of input: KCHR, old-style IM, new-style IM cmp.b #TSMIMitem, itemType(a2) ; <25> blt @KCHRinput ; KCHR item <25> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; < Begin new #29 > for CJK script ..... ; At boot time, we need to mark default input method for each script, and check mark the item in the menu, ; get the default input method for this script from TSM to compare against this item. -- ; need the default language for this script subq #4,sp ; result move.w itemScript(a4),-(sp) ; script move #smScriptLang,-(sp) ; verb: I want the default lang from the 'itlb' _GetScript move.l (sp)+,scriptLangRec(a6) ; default langCode (only want low word) move.w itemScript(a4),scriptLangRec(a6) ; scriptCode in high word ; now get the default input method: the component identifier for TSM-style IMs or ; the FEF ID for old-style IMs subq #2,sp ; OSErr result pea compID(a6) ; returns default component identifier here pea scriptLangRec(a6) ; wants a ptr to this record _GetDefaultInputMethod ; need to preserve a2/a3/d3/d4 .... move.w (sp)+,d0 ; result beq.w @newDefIM ; noErr => use TSM-style IM as default ; Default isn't TSM-style so continue checkingÉ => is an old-style Japanese IM ; Now test if the default is the old-style IM (should be unless there is a problem since we've ; just tested for TSM-style defaultÉ) cmp.w #tsmInputMethodIsOldErr,d0 ; is this the special error? beq.s @oldDefIM ; yes ; Here w/ a non-zero result (tsmInputMethodNotFoundErr) => no default IM found and no-TSM IM available ; So, if this is an old-style IM, use it as the default if another one hasn't already been set. cmp.b #oldIMitem,itemType(a2) ; is this old? bne @done ; No: nothing we can do. Sorry. (this shouldn't ever happen) ; Have we done this already? tst.b ScriptKeysItemNum(a3) ; assume it was initially cleared <34> - should be a byte op bne @done ; yes, don't do it again ; OK, this old-style IM is going to be the default now. We better inform TSM about itÉ ; _InformTSM will set the default IM with this FEP ID (can't call _SetDefaultInputMethod ; since it's only valid for TSM-style IMs. However, note (as seen above) that ; _GetDefaultInputMethod will return information about an old-style default IM. Strange but true; ; a kludge to allow old-style JIMs to still work w/ TSM.) move.w itemRsrcID(a2),d0 ; this is the FEP ID move.w d0,scriptLangRec+2(a6) ; TSM needs script and id <34> - store the ID in language word subq #2,sp ; OSErr result move.w #kMsgChangeToOldJIM,-(sp) ; message number pea scriptLangRec(a6) ; wants a ptr to this record as the message's parameter _InformTSM ; hey, we are using the old-style IM now tst.w (sp)+ ; ignore error ; set secret script flag that says we are using old-style input method <34> subq #2,sp ; result <34> move.w #smJapanese,-(sp) ; script <34> move #kUsingOldInputMethodVerb,-(sp) ; verb: are we using an old IM? <34> move.l #UsingOldStyleIM,-(sp) ; TRUE <34> _SetScript tst.w (sp)+ ; ignore OSErr <34> bra.s @SaveItemNum ; and save the item num ;------------------------------------------------------------------------------------------ @oldDefIM ; default is old-style IM cmp.b #oldIMitem, itemType(a2) ; is this old? bne @done ; no move.w compID+sidFEPID(a6),d0 ; saved in low word of long cmp.w itemRsrcID(a2),d0 ; is this item the default component for this script? bne.s @done ; no ; this is the default old-style IM so use it Import GetKanjiUserIDIntf ; call local version of UserIDIntf move.w d0,-(sp) ; pass input method ID of new item jsr GetKanjiUserIDIntf GetSMgrCore a1 ; get Script Mgr core move.l smgrEntry+(smJapanese*4)(a1),a1 ; load doubleTalkRecord for Japanese. ; if an error occured, didn't active old-style IM so don't make secret SetScript call. tst.w ScriptSystemGlobals.FISError(a1) ; bad index? bne.s @done ; yes -> bail. ; we have a problem here. If the old default IM is not in the system ...... ;; what to do if we failed ???? how could it get registered as the default if ;; it's not in the system??? ; set secret script flag that says we are using old-style input method ; We make this call to tell TSM about this situation - it knows that an old-style IM ; is the default but this flag hasn't been set yet. Without it set, patches won't get ; loaded to support the old-style IMs. At boot time DoubleTalk clears this. Patches loaded ; after DoubleTalk depend on it. Set it. (details, detailsÉ) subq #2,sp ; result move.w #smJapanese,-(sp) ; script move #kUsingOldInputMethodVerb,-(sp) ; verb: are we using an old IM? move.l #UsingOldStyleIM,-(sp) ; TRUE _SetScript tst.w (sp)+ ; result OSErr bne.s @done bra.s @SaveItemNum ; ;------------------------------------------------------------------------------------------ @newDefIM ; default is TSM-style IM cmp.b #TSMIMitem, itemType(a2) ; is this new? bne.s @done ; no, move.l auxItemInfo(a2),d0 ; compare to the default cmp.l compID(a6),d0 ; is this item the default component for this script? bne.s @done ; no bra.s @SaveItemNum ; ; < End new #29 > ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;------------------------------------------------------------------------------------------ <21> @KCHRinput move.w itemRsrcID(a2),d1 ; get the first KCHR ID cmp.w scriptBundle.itlbKeys(a3),d1 bne.s @done ;------------------------------------------------------------------------------------------ <21> @SaveItemNum move.b d3,ScriptKeysItemNum(a3) ; save item # of script's default KCHR GetSMgrCore a1 ; <15> tst.b smgrKbdMenuAvail(a1) ; <15> beq.s @done ; <15> endwith ; default KCHRÕs name gets a default mark that's localizable in the STR# resource for the kbd menu move.l menuH(a6),-(sp) move.w d3,-(sp) move.w defaultMark(a6),-(sp) ; this is the script's default KCHR _SetItmMark ; Add ÔÃÕmark to the system KCHR cmp.w itemScript(a4),d4 ; is this the system KCHR? bne.s @done ; system KCHR gets ÔÃÕ mark and its icon gets put into menu name move.l menuH(a6),-(sp) move.w d3,-(sp) move.w #checkMark,-(sp) _SetItmMark @done add.w #1,menuItem(a6) ; next item # movem.l (sp)+,AddMenuRegs rts endWith ;------------------------------------------------------------------------------------------ <3> ; Utility AddDisabledLine ; Add disabled grey line ; ; ---- Input ; a2 ptr to AuxKeyboardMenuInfo (storage for each KCHRÕs iconSuiteH) ; a6 stack frame, menuFrame ; ; ---- Output ; menuItem count incremented ; a2 incremented for next menuitem's info ;------------------------------------------------------------------------------------------ AddDisabledLine with menuFrame, AuxKeyboardMenuInfo move.l menuH(a6),-(sp) ; menu handle pea #'(-' ; pString <21> move.w menuItem(a6),-(sp) ; insert ÔafterÕ this menuItem _InsMenuItem add.w #1,menuItem(a6) ; next item # ; stuff a null handle in the menu item's position in the KeyboardMenu record. add.w #AuxMenuInfoSize,a2 ; point to storage for next menuItem. rts endwith ;formFeed ;------------------------------------------------------------------------------------------ <10> ; Utility SortItems ; ; Sort the installed items by script and name using the Script Manager routine IUTextOrderSys, ; which sorts using the script ordering specified in ÔitlmÕ. ; To save moving a lot of data around, we will sort the indices of the ItemInstalledRec array ; and fetch the data later. ; ; This is a straight selection algorithm (simple idea but....) ; Search for the smallest KCHR # and exch it w/ the first KCHR # in the list. ; Repeat w/ n-1, n-2, etc. items. ; d0 & d1 are loop counters (indexes for each KCHR comparison) ; d2 & d3 contain the results of the comparisons ; ; ---- Straight selection algorithm --------------- ; for d0:= 0 to KCHRcount-1 do ; d2:= d0 ; d3:= offset[d0] ; for d1:= d0+1 to KCHRcount-1 do ; if name[d1] < name[d3] then ; d2:= d1 ; d3:= offset[d2] ; end ; end ; offset[d2]:= offset[d0] ; offset[d0]:= d3 ; end ; ; ---- Input ; d4 KCHRcount ; a6 stack frame, menuFrame ; ; ---- Register usage ----------------------------- ; d0-d2 are index counters ; d3 storage of the least KCHR # ; d4 Input count (inner loop terminator) ; d5,d6 length of names, misc temp uses ; d7 outer loop terminator ; a2 bPtr ; a3 ItemOffsetsPtr ; a4 aPtr ;------------------------------------------------------------------------------------ SortItems with menuFrame, ItemInstalledRec, AuxKeyboardMenuInfo SortRegs reg d3-d7/a3 ; initializations move.l ItemInstalledRecPtr(a6),a4 movem.l SortRegs,-(sp) ; allocate record for offsets of ItemInstalledRec to be sorted moveq #0,d0 move.w d4,d0 ; total number of installed items add.w d0,d0 ; double for # of installed items _NewPtr ,SYS,CLEAR move.l a0,ItemOffsetsPtr(a6) ; build record of offsets move.w #0,d0 ; index move.w d4,d1 ; loop terminator bra.s @CheckZero @FillArray move.w d0,(a0)+ ; save offset add.w #ItemInstalledRecSz,d0 ; incr to next offset @CheckZero dbra.w d1,@FillArray ;------- cmp.w #1,d4 ; do we have more than 1 KCHR? <12> ble @DoneSort ; nope: donÕt sort <12> move.l ItemOffsetsPtr(a6),a3 ; reset ptr move.l a4,a2 ; copy of ptr to KCHR info for sorting (a4=aPtr, a2=bPtr) ; initialize for outer loop move.w #0,d0 ; initialize outer loop controller to 0 move.w d4,d7 ; terminator for outerloop sub.w #1,d7 ; KCHRcount-1 (instead of -2) <14> @OuterLoop ; for d0:= 0 to KCHRcount-1 do ; d2:= d0 ; d3:= offset[d0] ; least index move.w d0,d2 ; d2:= d0 move.w d0,d3 add.w d3,d3 ; pt to correct offset in KCHROffsets record ; initialize for inner loop move.w d0,d1 addq.w #1,d1 move.l ItemInstalledRecPtr(a6),a2 move.w d1,d5 add.w d5,d5 ; get to correct place in offset array move.w 0(a3,d5),d5 ; get offset amount for this next element add.w d5,a2 @InnerLoop ; for d1:= d0+1 to KCHRcount-1 do ; if name[d1] < name[d3] then ; d2:= d1 ; d3:= offset[d2] ; new least index ; end ; end ; if name[d1] < name[d3] then ( now compare scripted names) ; a4 = KCHR a (aPtr, aLen, aScript) ; a2 = KCHR b (bPtr, bLen, bScript) movem.l d0-d2,-(sp) moveq #0,d5 move.b itemName(a4),d5 ; aLen moveq #0,d6 move.b itemName(a2),d6 ; bLen sub.w #2,sp ; result pea itemName+1(a4) ; aPtr pea itemName+1(a2) ; bPtr move.w d5,-(sp) ; aLen move.w d6,-(sp) ; bLen move.w itemScript(a4),-(sp) ; aScript move.w itemScript(a2),-(sp) ; bScript move.w #iuScriptDefLang,-(sp) ; aLang => script's default lang move.w #iuScriptDefLang,-(sp) ; bLang => script's default lang _IUTextOrderSys move.w (sp)+,d0 ; set CCs movem.l (sp)+,d0-d2 ble.s @GetNextID ; aPtr is <= bPtr so don't exchange move.w d1,d2 move.w d2,d3 ; d3:= new least index add.w d3,d3 ; pt to correct offset in KCHROffsets record move.l a2,a4 ; update aPtr to be the least KCHR (which is bPtr in this case) @GetNextID addq.w #1,d1 ; for d1:= d0+1 to KCHRcount do ; incr for fetch of next itemName (using current sort order) move.l ItemInstalledRecPtr(a6),a2 move.w d1,d5 add.w d5,d5 ; get to correct place in offset array move.w 0(a3,d5),d5 ; get offset amount for this next element add.w d5,a2 cmp.w d1,d4 ; KCHRcount-1 bhi.s @InnerLoop ; swap this pass' least KCHR name with the KCHR name in the current position ; offset[d2]:= offset[d0] ; offset[d0]:= d3 move.w d0,d5 ; this is the index of the higher KCHR name add.w d5,d5 move.w d2,d6 ; this is the index of the least KCHR name add.w d6,d6 move.w 0(a3,d3),d3 move.w 0(a3,d5),0(a3,d6) ; this is the highest index for this pass move.w d3,0(a3,d5) ; this is the least index for this pass ; loop again? addq.w #1,d0 ; for d0:= 1 to KCHRcount-1 do ; set ptr to next ÔKCHR aÕ move.l ItemInstalledRecPtr(a6),a4 move.w d0,d5 add.w d5,d5 ; get to correct place in offset array move.w 0(a3,d5),d5 ; get offset amount for this next element add.w d5,a4 ; set ptr to next ÔKCHR bÕ move.l a4,a2 ; just copy; incremented above ; are we done? cmp.w d0,d7 bhi @OuterLoop IF DoCmdKeyEquivalents THEN ; <10> ; finally, move the system script's default KCHR to the top of the menu. with SmgrRecord GetSMgrCore a0 move.w smgrKeyScript(a0),d3 ; get default keyscript move.l ItemInstalledRecPtr(a6),a4 ; move.w #0,d0 ; offset of default KCHR in KCHROffsets array @InxLoop move.w d0,d1 add.w d1,d1 ; index into KCHROffsets array add.w #1,d0 move.w 0(a3,d1),d2 ; get index into ItemInstalledRec cmp.w itemResID(a4,d2),d3 ; is this the default KCHR? bne.s @InxLoop ; have the default KCHR index now so shove the system script's KCHRs down a position sub.w #1,d0 ; incremented above move.w d0,d4 ; loop terminator (shift until this point) move.w #0,d1 move.w (a3),d2 ; holding cell for initial posn in array add.w d1,d1 @ShoveLoop add.w d4,d4 move.w 0(a3,d4),0(a3,d1) ; move em sub.w #1,d0 bls.s @FinalMove ; move initial KCHR into its new home move.w d4,d1 move.w d0,d4 bra.s @ShoveLoop @FinalMove move.w d2,0(a3,d4) ; finis! mission accompli! endwith ENDIF @DoneSort movem.l (sp)+,SortRegs rts ; end endwith ;formFeed ;------------------------------------------------------------------------------------------ <25> ; Utility CountDblByteIMs ; ; Count the # of TSM style Input Methods in the System for a specific double-byte script ; and set a bit in the byte CJKcount(a6) that indicates whether or not an input method ; exists for the script. Bits 0 - 4 are set thus: (CCJK): bit 4 = simpChinese, ; bit 3 = tradChinese, bit 2 = Japanese, bit1 = Korean. Also updating the total # of ; input methods in d4 and TSMInputMthdCount(a6). ; ; Input ; a6 stack frame, menuFrame ; d0 flags that indicate the script and the active key event bit ; d2 bit to set in the byte CJKcount(a6) ; d4 current count of inputs (KCHRs, input methods, etc.) ; ; Uses ; d0 result from _CountComponents ; ; Output ; d4 updated count of inputs (KCHRs, input methods (old-style and TSM-style), etc.) ; TSMInputMthdCount(a6) updated count of TSM-style input methods ;------------------------------------------------------------------------------------------ <25> CountDblByteIMs with MenuFrame move.l d0, CompDesc.componentFlags(a6) ; desired script & takes active key events subq #4,sp ; result pea CompDesc.componentType(a6) ; count components of this desc _CountComponents move.l (sp)+,d0 bz.s @noIMs bset.b d2,CJKcount(a6) add.l d0,d4 ; can there really be a longInt worth of components??? add.l d0,TSMInputMthdCount(a6) @noIMs rts endWith ;formFeed ;------------------------------------------------------------------------------------------ <7> ; FUNCTION RebuildKeybdMenu: OSErr; ;------------------------------------------------------------------------------------------ ; ; RebuildKeybdMenu is called by Mover to let us know that keyboards have ; been moved into or out of the System file, so we need to rebuild the ; keyboard menu. ; ;------------------------------------------------------------------------------------------ rkmFrame record {a6link},decr result ds.w 1 ; OSErr result code. rkmArgs equ *-8 ; size of arguments. selector ds.l 1 ; selector return ds.l 1 ; return address. a6link ds.l 1 ; old a6 ; insert any local variables here menuH ds.l 1 ; <21> rkmLocals equ * ; size of local variables endr RebuildKeybdMenu with rkmFrame,smgrRecord, AuxKeyboardMenuInfo ; link a6,#rkmLocals ; link the stack. move.w #noErr,result(a6) ; initialize noErr <36> ; delete the old ptr to AuxKeyboardMenuInfo record so can store a new one <10> movem.l a2/d3,-(sp) GetSMgrCore a0 ; set munged count to tell the Keybd CDEV to rebuild it's list of KCHRs <15> add.w #1,smgrMunged(a0) ; <15> move.l smgrKeyboardMenuPtr(a0),a2 tst.b smgrKbdMenuAvail(a0) ; <15> bne.s @gotMenu ; got menu, so use info from it <19> ; Get number of valid AuxKeyboardMenuInfo records into d3. If Keyboard menu is not <19> ; up, we have a Roman-only system, so use KCHR count for Roman. <19> with ScriptRecord ; <19> move.l smgrEntry+(smRoman*4)(a0),a0 ; <19> moveq #0,d3 ; for wordizing <19> move.b scriptInputCount(a0),d3 ; initialize item count to script's KCHR count <19> bra.s @DelIconSuiteLoop ; <19><36> endwith ; ScriptRecord <19> @gotMenu ; <19> ; Dispose of menu items & iconSuite handles for each menu item <10> ; If an application doesn't have a menuBar then _GetMHandle will fail. What we <20> ; really want is to use the system menuBar and not the application menuBar. <20> move.l MenuList,-(sp) ; save the current menuList since it may be an apps menu <20> move.l SystemMenuList,MenuList ; <20> subq #6,sp ; result for _GetMHandle & _CountMItems calls move.w #kKeyboardMenuID, -(sp) ; menuID _GetMHandle tst.l (sp) beq.s @RestoreStack move.l (sp),menuH(a6) ; want it for deletion of menuItems <21> ; leave menu handle on stack ; get # of menu items _CountMItems move.w (sp)+,d3 ; <36> move.l (sp)+,MenuList ; restore the menuList <20> move.w d3,-(sp) ; save back on stack for next loop <36> ; delete all the existing menu items (only if a menu exists!!!) <36> @DelMenuItemLoop move.l menuH(a6),-(sp) ; <21> move.w d3,-(sp) ; item number <21> _DelMenuItem ; <21> dbra.w d3,@DelMenuItemLoop move.w (sp)+,d3 ; initialize again for iconSuite loop <36> @DelIconSuiteLoop ; delete all the iconSuites tst.l iconSuiteH(a2) beq.s @NextItem sub.w #2,sp move.l iconSuiteH(a2),-(sp) ; storage for this iconSuite move.w #$00,-(sp) ; dispose data flag = False _DisposeIconSuite tst.w (sp)+ ; pop result for now and don't bail <36> ;; move.w (sp)+,d0 ; sets CCs <36> ;; move.w d0,result(a6) ; save <36> ;; bne @done ; <36> @NextItem add.w #AuxMenuInfoSize,a2 ; next menu item dbra.w d3,@DelIconSuiteLoop GetSMgrCore a0 move.l smgrKeyboardMenuPtr(a0),a0 ; auxiliary keyboard menu ptr _DisposPtr move.w d0,result(a6) subq #2,sp ; space for OSErr result <18> _InitKeybdMenu ; <18> addq #2,sp ; discard error result (we should really <18> bra.s @done @RestoreStack addq #6,sp ; results of _GetMHandle & _CountMItems move.l (sp)+,MenuList ; restore the menuList <20> @done movem.l (sp)+,a2/d3 move.w #rkmArgs,d0 ; for StdUnlink bra StdUnlink ; standard exit endwith IF DoCmdKeyEquivalents THEN ; <21> ;------------------------------------------------------------------------------------------ ; AddCmdKeyMenuItems ; ; Not really a routine- just a place I've moved the code to get it out of the ; middle of everything. Should be put back at 'bsr AddCmdKeyMenuItems' if we ; want to use it. CAN NO LONGER ASSUME "ABOUT KEYBOARDSÉ MENUITEM IS PRESENT!!! <34> ;------------------------------------------------------------------------------------------ AddCmdKeyMenuItems bsr AddDisabledLine ; separate scripts by a disabled line tst.b scriptCount(a6) ; more enabled scripts? bgt.s @EnabledScriptLoop ; yup ;------------------------------------------------------------------------------------------ <3> ; add final items to menu @SetCmdKeyEquiv move.w #NumItemsAfterKCHRs,d4 ; num of cmd key equivalent items after KCHRs sub.w #1,d4 ; loop terminator: want 0 based move.w #NextScriptIndex,d5 ; first Cmd Key menu item is ÔNext ScriptÕ ; (1st loop:) add ÔNext ScriptÕ w/ a cmd key equivalent of Ô Õ at the end ; (2nd loop:) add ÔNext KeyboardÕ w/ a cmd key equivalent of Ô Õ at the end ; my copy of the GetIndString library code: localGetIndString move.l menuItemStringHdl(a6),a0 tst.l a0 beq @SetTitle ; if empty, just add title @CmdKeyLoop bsr GetItemStr ; <10> tst.l NextItemString(a6) beq.s @SetTitle ; error ; since have a STR# resource, adding a disabled line (if it's not the last menu item) tst.w d4 ; is this the last item? beq.s @SkipLine bsr AddDisabledLine ; separate scripts by a disabled line @SkipLine ; name the menu item move.l menuH(a6),-(sp) pea NextItemString(a6) ; name of this KCHR: pString move.w menuItem(a6),-(sp) ; insert ÔafterÕ this menuItem _InsMenuItem ; Add cmd key equivalent (actually, due to current Menu Mgr limitations (no way to show ; CMD+space bar, no way to indicate CMD+SH and no way to show CMD+SH+space bar) ; I will only put up the command key symbol (with a space). ; Will need to add a table as this gets worked out, in order to add the correct chars ; for each menu item's cmd key equivalent. ; disable cmd key equivalents for now! <5> ;; move.l menuH(a6),-(sp) ; <5> ;; move.w menuItem(a6),-(sp) ; item # <5> ;; move.w d5,-(sp) ; temp: use string index (really want CMD+ÔblankÕ)<5> ;; add.w #$30,(sp) ; make it an ascii number <5> ;; _SetItemCmd ; if there is only one script enabled, disable the ÔNext ScriptÕ menuItem ; is this the ÔNext ScriptÕ menuItem? cmp.w #NextScriptIndex,d5 bne.s @NextKbd with ExpandMemRec move.l ExpandMem,a2 move.l emItlSysCachePtr(a2),a2 ; <9> endWith cmp.w #1,(a2) ; is there only 1 script enabled? bhi.s @NextItem ; nope ; only 1 script's enabled so, disable item move.l menuH(a6),-(sp) move.w menuItem(a6),-(sp) _DisableItem bra.s @NextItem @NextKbd ; if there is only one KCHR for the default script, disable the ÔNext Keyboard in ScriptÕ menuItem ; last item is ÔNext Keyboard in ScriptÕ cmp.w #NextKeybdIndex,d5 bne.s @NextItem ; is there only 1 KCHR for this script? GetSMgrCore a2 ; the forgotten one! <5> move.w smgrKeyScript(a2),d2 lsl.w #2,d2 move.l smgrEntry(a2,d2.w),a3 cmp.b #1,scriptInputCount(a3) bhi.s @NextItem ; only 1 script's enabled so, disable item move.l menuH(a6),-(sp) move.w menuItem(a6),-(sp) _DisableItem @NextItem add.w #1,menuItem(a6) add.w #1,d5 dbra.w d4,@CmdKeyLoop endWith ; <6> ENDIF ;___________________________________________________________________________________________________ endproc ; this whole thing is one proc ;formFeed ;___________________________________________________________________________________________________ ; GetIndString as taken from {Sources}Libs:InterfaceSrcs:ToolUtils.a ; (modified to return a pString) ; getindstring(theString,strListID,index) ; char *theString ; ; short strListID; ; short index; ;___________________________________________________________________________________________________ BLANKS ON STRING ASIS localGetIndString proc EXPORT gsFrame record {a6link},decr gsArgs equ *-8 ; size of arguments. <1> theString ds.l 1 strListID ds.w 1 index ds.w 1 return ds.l 1 ; return address a6link ds.l 1 ; old link pointer ; insert any local variables here gsLocals equ * ; size of local variables. endr with gsFrame link a6,#gsLocals ; link move.l d2,-(sp) ; save register d2 subq #4,sp ; GetResource result move.l #'STR#',-(sp) ; theType move.w strListID(a6),-(sp) ; strListID (was '14') _GetResource ; get resource move.l theString(a6),a1 ; theString (was '8'?) clr.b (a1) ; assume empty move.l (sp)+,d0 ; handle to string list move.l (sp)+,d2 ; restore register d2 tst.l d0 ; test result beq.s gsret ; if empty, just quit move.l d0,a0 ; handle to string list move.l (a0),a0 ; pointer to string list cmp.l #0,a0 ; is the pointer NIL? <35> bne.s gsGet ; no, continue <35> move.l d0,-(sp) ; yes, so save handle <35> move.l d2,-(sp) ; preserve register <35> move.l d0,-(sp) ; handle <35> _LoadResource ; <35> move.l (sp)+,d2 ; restore register <35> move.l (sp)+,a0 ; get handle again <35> move.l (a0),a0 ; deref again for ptr to string list <35> move.l theString(a6),a1 ; restore theString <35> gsGet move.w (a0)+,d0 ; number of strings move.w index(a6),d1 ; index (was '18'?) ble.s gsRet ; return if index <= 0 cmp.w d0,d1 ; index > number of strings ? bgt.s gsret ; return if index > number moveq #0,d0 ; clear for string lengths gsLoop subq.w #1,d1 ; decrement the index beq.s gsCopy ; found the one we are looking for move.b (a0)+,d0 ; get length of this one add.l d0,a0 ; skip over this string bra.s gsLoop ; and go on to next gsCopy move.b (a0)+,d0 ; get the length of this string move.b d0,(a1)+ ; store the length in the string (make a pString!) move.w d0,d1 ; save the length _BlockMove ; copy it into theString gsRet unlk a6 ; unlink move.l (sp)+,a0 ; pop return address. add.w #gsArgs,sp ; pop arguments. jmp (a0) ; return to the caller. endproc ;___________________________________________________________________________________________________ end ;___________________________________________________________________________________________________