mac-rom/Toolbox/TextServicesMgr/TSMInternalUtils.c
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

2018 lines
86 KiB
C

/*
File: TSMInternalUtils.c
Contains: TSM internal utility routines.
Written by: Kenny SC. Tung
Copyright: © 1992 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<48> 10/30/92 DTY Use Get/Set macros to access ExpandMem.
<47> 8/4/92 KST #1038606 <JH>: Apparently, when I ran the compare the crucial
code change wasn't copied over. Trying again.
<46> 8/4/92 DCL Changed spelling of Pallete to Palette (for HidePaletteWindow
and all others)
<45> 8/4/92 KST #1038311 <gbm>: Undo the previous fix. We want to call
FixTSMDocument(). The right fix is in ScriptMgrKeyGetSet.a
<44> 7/31/92 KST #1038311 <JH>: We can't call application to fix input area when
script changes because the SetTextServiceLanguage() call is
issued inside of the GetOSEventPatch of Script Manager code.
When we are running inside of GetOSEvent(), the A5 points to
Process Manager's global. If we call FixTSMDocument(), input
method will send AE to the application, and very bad thing could
happen when the app accesses its globals.
<43> 7/31/92 KST #1037798 <GM>: <JH> Fixed a memory leak bug in
utCleanUpPreviousDoc().
<42> 7/22/92 JH #1031828 <KT>: On Rubiks when tsmFinder launches a application
they deactivate the Finder's TSMDocuments. Then if a non-TSM
aware calls InitMenus and then calls GetNextEvent, SWM will
activate its document when it gets the accRun call (as a result
of the GetNextEvent call). When the swm document is activated
TSM will insert the input methods menu in the menulist. The
trouble with this is that if there are no menus in the list
(i.e. InitMenus was called but no insertMenu yet), the FEP menu
will be the only system menu in the menulist. This apparently
prevents the other system menus from being added. We fixed this
by checking to see if there are any menus in the menulist before
we insert the FEP menu. Change is in utCreateSystemVersionOfMenu.
<41> 7/8/92 KST #1033475 <JH>: Changed the routine name utHasNoInputMethod() to
utScriptIsNotCCJK() to be more descriptive.
<40> 7/6/92 KST #1033507,1033505 <JH>: For the fix 38, when we close the
instance, need to call HidePaletteWindows().
<39> 7/2/92 KST #1034430 <LP>: When handling input methods, in some cases I
forgot to check if the script is one of CCJK. If it is not we
should not call utGetScriptIndex() because later on when
accessing the array, we'll write to memory that does not belong
to us and trashes the heap.
<38> 7/1/92 JH #1033507,1033505 <KsT>: Adding Kurita's CheckHeapSlop call to
here. Fromerly resided in ComponentMgr.
<37> 6/26/92 KST #1033450,1033456,1031316 <JH>: utCloseIM4Document() will now
take an extra parameter to indicate if it should send
HidePalette() command to input method. Only set it to true when
called in SetDefaultInputMethod().
<36> 6/24/92 KST #1033456 <JH>: When we close an input method, we better take
down its palette too. Added a new call
utDeleteCleanUpTSMDocument().
<35> 6/22/92 KST #1032492 <JH>: (For the #33 fix) When switching input methods,
we need to remove the old input method's menu from the system
menulist I was using the wrong routine, I should use
'utDeleteInputMethodsPreviousMenu', not 'utDeleteMenu'.
<34> 6/22/92 KST #1030843 <JH>: Close the instance event it is not active so that
memory can be released. Undo change #28.
<33> 6/19/92 KST #1032492 <JH>: When switching input methods within the same
script, need to delete the previous menu and then insert the new
one. In the case when input method does not have a menu, need to
make sure no previous menu left over in the menu bar.
<32> 6/17/92 KST #1030843 <JH>: Changed the function name from
utaIsApplicationTSMAware to utaIsAppTSMAwareAndNotUsingIW to be
more precise and descriptive.
<31> 6/16/92 KST #1032645 <JH>: In utJustDeactivateIM4Document, need to set the
document activep flag when there is no Component.
<30> 6/14/92 KST #M. Sang 2, <JH>: When DeleteTSMDocument calls
utCloseIM4Document, we remove IM's menu only from system menu
list but keep it in app's menu so that when a TSM aware
application (using Akiko in Roman promary script) deletes all
the TSM documents, Akiko's menu will still stays in the menu
bar.
<29> 6/14/92 KST #M. Sang 1, <JH>: If we open the input method the first time, need
to inform Process Manager if it should route events to SWM.
(This is a new bug only happens when we use a TSM aware
application in Roman as a primary script).
<28> 6/14/92 KST in utCloseIM4Document: Check the flag and close the text service
only if it is active.
<27> 6/13/92 KST #1032463 <JH>: when switch from a TSM aware application, but is
using Input Window, to Finder, we need to keep the pencil in
that app's menu but we don't want to see it when we launch other
applications.
<26> 6/10/92 KST #1031142,1030881 <JH>: Since we removed the docID param from
TSMEvent, UseInputWindow has been broken because keydown event
is routed to SWM recursively. Fix it with a TSM global keeping
track of which doc is using the input window. Changed many
routines such as: utFixDocumentAndCloseSWMWindow,
utJustDeactivateIM4Document in this file.
<25> 6/4/92 KST #1031578 <JH>: Need to remove IM's menu from the system menulist
when the primary script is not CJK.
<24> 6/2/92 pvh Change MenuList to ApplicationMenuList.
<23> 6/2/92 JH #1028635,1030481,1030631,1030634,1030647 <KST>: Added routine to
turn input method windows into system menus (sorry can't
remember the name and this is a dialog so I can't look)
<22> 5/20/92 KST In utDeactivateIMforDocument, validate the document signature.
If not valid, return tsmInvalidDocIDErr error.
<21> 5/19/92 KST #1029247 <hsK>: Added a new routine: utBadSandL to verify the
script and language code.
<20> 5/8/92 KST Added documentation only.
<19> 5/1/92 KST #1028881,<HSK>: If open IM for SWM's document, set the zone to
system zone so that the instance will not get closed when the
application exits (in utOpenIM4Document).
<18> 4/30/92 KST Add some documentation describing the calls that activate Input
Method for document.
<17> 4/20/92 YK #1026761: Avoid HUnlocking of the disposed handle.
<16> 4/20/92 YK #1026761: Before calling InsertMenu and DrawMenuBar, make sure
that the menu handle is not NIL.
<15> 4/10/92 KST JH,When switch from a TSM aware app to a non-TSM aware app, and
both use the same IM, we didn't inform PM that it should
start/stop sending events to SWM.
<14> 4/9/92 KST JH,modifying utCloseSWMWindow to support the fact that SWM is no
longer an application but a driver. Adding a new call
"utSuspendResumeApp".
<13> 3/30/92 KST JH, 1025008, 1025009. First attempt to solve the palette/menu
bar flickering problem. Also, we synchronize the keyboard menu
with the script of the TSM document.
<12> 3/23/92 KST Code changed according to the comments from the code review.
<11> 3/12/92 KST "utActivateThisDocsInputMethod" takes only a doc ID parameter.
<10> 3/10/92 KST Need to lock document ID handle.
<9> 3/6/92 KST In "utCloseSWMWindow", send Apple Event only if we got SWM's
process number.
<8> 3/6/92 KST Removed debugger code.
<7> 3/2/92 KST In "utOpenActivateDefaultIM" and "utOpenIM4Document", it now
takes a Boolean flag to indicate if we should activate the input
method.
<6> 2/27/92 KST In "utCloseSWMWindow", send AE failed because the app is not
high level event aware.
<5> 2/27/92 KST Added 2 new calls -- "utCloseSWMWindow", and "utDeleteMenu".
Remove the menu from menu bar only if tsmKillApplicationP flag
is false.
<4> 2/18/92 KST In "utOpenIM4Document", When openning input method Component, we
set the system to system mode so that files openned get charged
to the system.
<3> 2/11/92 DCL Changed the name of TSMEqu.[aph] to TextServices.[aph] for
better read-ability.
<2> 2/10/92 KST Moved all internal routines from TSMUtility.c and TSMFunction.c
to TSMInternalUtil.c file.
*/
/* ********************************************************************************
* File: "TSMInternalUtils.c"
*
* Written by Kenny SC. Tung
*
* Modification History:
* 09Feb92 KSCT New today.
*
* TSM internal utility routines:
*
* utJustDeactivateIM4Document
* utDeactivateIMforDocument
* utDeleteCleanUpTSMDocument
*
* utSupportedSL
* utAppendTS2Document
* utMakeRoom4SInfoHandle
* utHidePaletteAndMenu
* utCleanUpPreviousDoc
* utCreateSystemVersionOfMenu
* utActivateIM4Document
* utCloseIM4Document
*
* utDeleteInputMethodsPreviousMenu
* utOpenIM4Document
* utOpenActivateDefaultIM
* utActivateThisDocsInputMethod
*
* utScriptIsNotCCJK
* utScriptIsCCJKAndNeedsIM
* utGetScriptIndex
* utGetTSMDefaultInputMethod
* utSLRec2CompFlag
* utChangeToOldJIM
* utSuspendResumeApp
* utAddTSMResource
* utUpdateDefaultInputMethodResource
* utCloseSWMWindow <#5>
* utBadSandL <#21>
*
*
* utActivateIM4Document: << ¥¥ already open, just activate >>
* Activate the input method of the current script for this document.
* Add its menu and activate the instance. The instance must be open already.
* utOpenIM4Document: << ¥¥ open an IM only >>
* Open the Component for the document as its default input method of the current script.
* Assume no input method of this script opened for this document !!
* This is the only path where I open an input method for the document.
* utOpenActivateDefaultIM: << ¥¥ open or activate >>
* Open the default input method for the current keyscript if it is not already open,
* -- with utOpenIM4Document.
* If the default input method is already open, then activate it,
* -- with utActivateIM4Document.
* utActivateThisDocsInputMethod: << ¥¥ synchronize IM used by the document >>
* This document was deactivated and is now being activated, if user is still using
* the same IM, then just activate it; -- with utActivateIM4Document.
* else, close the previous Input Method and open the new one.
*
* ******************************************************************************** */
#include <Traps.h>
#include <OSUtils.h>
#include <Script.h>
#include <Devices.h>
#include <MFPrivate.h>
#include <Resources.h>
#include <TextServices.h>
#include <TSMPrivate.h>
#include <Menus.h>
/* *************************************************************** *
* Function: utJustDeactivateIM4Document *
* Deactivate the IM for the Document only. *
* stillActiveP flag tells if the document should keep *
* active or not. *
* If the IM is already deactivated, return noErr. *
* Input: docID, script code, and stillActiveP flag. *
* *************************************************************** */
OSErr utJustDeactivateIM4Document( TSMDocumentID theDocID, ScriptCode theScript, Boolean stillActiveP )
{
OSErr err = noErr;
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
idocRecPtr = (TSMDocRecord *) *((Handle) theDocID); /* dereference the handle */
if (! idocRecPtr->iDocActiveP) /* if not active */
return tsmDocNotActiveErr; /* stop right now */
if (!utScriptIsNotCCJK(theScript)) { /* if the script needs IM */
/* Deactivate the default input method of the current script if it is open */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[utGetScriptIndex(theScript)]);
if (openedDefIMRecordPtr->openedDefIMCInstance) { /* if there is one open */
if (openedDefIMRecordPtr->openedDefIMActiveP) { /* if the input method is active */
err = DeactivateTextService(openedDefIMRecordPtr->openedDefIMCInstance); /* what the app can do on error ??? */
if (err == noErr) {
idocRecPtr = (TSMDocRecord *) *((Handle) theDocID);/* dereference the handle */
openedDefIMRecordPtr->openedDefIMActiveP = false; /* not active anymore */
}
}
}
}
idocRecPtr->iDocActiveP = stillActiveP; /* keep it active option */
return err;
}
/* **************************************************** *
* utBadSandL: *
* Verify the Language code is correct corresponding *
* to the script code., if NOT valid return true. *
* ( Congress will bail out the bad S&L. ) *
* **************************************************** */
Boolean utBadSandL(ScriptLanguageRecord *slRecPtr)
{ LangCode languageCode;
languageCode = (LangCode) GetScript(slRecPtr->fScript, smScriptLang);
return (languageCode != slRecPtr->fLanguage ? true : false );
}
/* ******************************************** *
* Verify the idocID, if valid return true. *
* ******************************************** */
OSErr utVerifyTSMDocID(TSMDocumentID idocID)
{
if (idocID == nil ||
((TSMDocRecordPtr) *(Handle) idocID)->iDocSignature != kTSMDocumentSignature )
return tsmInvalidDocIDErr;
else return noErr; /* ID verified */
}
/* ******************************************** *
* append the object to the linked list of open *
* text services in the document record. *
* Assume: this routine does not move memory *
* ******************************************** */
void utAppendTS2Document(TSMDocRecord *idocRecPtr,
CIListRec *theListRecPtrToAppend)
{
CIListRec *aListRecPtr;
if (idocRecPtr->iDocOpenTextServiceN) { /* if we have open text services */
aListRecPtr = idocRecPtr->iDocCIHead; /* get the first open TS record in the linked list */
while (aListRecPtr->ciNextCIListRec) /* find the end of the list */
aListRecPtr = aListRecPtr->ciNextCIListRec;
aListRecPtr->ciNextCIListRec = theListRecPtrToAppend;
}
else { /* this is the first one open */
idocRecPtr->iDocCIHead = theListRecPtrToAppend;
}
theListRecPtrToAppend->ciNextCIListRec = nil; /* mark the end */
idocRecPtr->iDocOpenTextServiceN++; /* bump the counter of open instances */
}
/* ************************************************************************
* Check if the handle has memory for the Nth record, N specified in pos,
* Return noErr if there is enough room ...
* Recall the structure is:
* typedef struct {
* short fTextServiceCount;
* TextServiceInfo fServices[fScriptLanguageCount];
* } TextServiceList;
* ***********************************************************************/
OSErr utMakeRoom4SInfoHandle(
TextServiceListHandle serviceInfoHandle,
int pos)
{
Size requestSize, handleSize;
OSErr err = noErr;
handleSize = GetHandleSize((Handle) serviceInfoHandle);
requestSize = 2 + sizeof(TextServiceInfo) * (pos+1);
if (handleSize < requestSize) { /* not enough space */
SetHandleSize((Handle) serviceInfoHandle, requestSize);
err = MemError();
}
return err;
}
/* ******************************************************************************* *
* Function: utHidePaletteAndMenu *
* Hide input method's palette, if it has a menu, remove it too. *
* Used only in this file by utCleanUpPreviousDoc and utForceDeactivateIM4Document *
* Input: openedDefIMRecordPtr = the input method record to clean up. *
* ******************************************************************************* */
void utHidePaletteAndMenu(DefIMInstanceRecord *openedDefIMRecordPtr)
{
/* if it has a menu and the menu is displayed in the menu bar, then remove the menu */
if (openedDefIMRecordPtr->openedDefIMServiceMenuHdl && openedDefIMRecordPtr->openedDefIMMenuVisibleP) {
utDeleteMenu((*(openedDefIMRecordPtr->openedDefIMServiceMenuHdl))->menuID);
openedDefIMRecordPtr->openedDefIMMenuVisibleP = false; /* not visible anymore */
}
(void) HidePaletteWindows(openedDefIMRecordPtr->openedDefIMCInstance);
}
/* ************************************************************************************ *
* Function: utCleanUpPreviousDoc *
* we deactivated the previous TSM document without taking down its palette now we are *
* activating another TSM document, if scripts are different or input methods are *
* different, then need to ask the previous IM to hide its palette. *
* *
* Input: theNewDocID = new document to activate, it could be nil when called *
* from xSetTextServiceLanguage where there is no new document to activate. *
* (this is not the previous document ID) !! *
* Modification history: *
* 30Mar92 KST The tsmPreviousDocID could contain a shadow ID handle because the real *
* ID has been deleted (xDeleteTSMDocument). Check iDocSignature. *
* ************************************************************************************ */
void utCleanUpPreviousDoc(TSMDocumentID theNewDocID, /* new document to activate */
ScriptCode theNewScript)
{
Boolean need2HidePalette = false;
short imIndex;
Component currentComponent = nil;
ScriptCode previousScript;
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
previousScript = TSMVarsPtr->tsmPreviousScript;
if (utScriptIsNotCCJK(previousScript)) { /* if the script doesn't need IM, such as Arabic or Roman */
TSMVarsPtr->tsmPreviousDocID = nil; /* done <12Jun92 #27> */
return;
}
if (utScriptIsCCJKAndNeedsIM(theNewScript)) { /* this is one of CJK */
imIndex = utGetScriptIndex(theNewScript); /* index for the current script */
if (theNewDocID) {
idocRecPtr = (TSMDocRecordPtr) *((Handle) theNewDocID); /* dereference the current ID */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[imIndex]); /* the default IM we will use */
currentComponent = openedDefIMRecordPtr->openedDefIMComponent; /* the current Component */
}
//else
// currentComponent = nil; /* if script is the same, then this will take down the palette */
}
/* dereference here so that openedDefIMRecordPtr can be used when need2HidePalette is true */
HLock((Handle) TSMVarsPtr->tsmPreviousDocID);
idocRecPtr = (TSMDocRecordPtr) *((Handle) TSMVarsPtr->tsmPreviousDocID); /* dereference the previous ID */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[utGetScriptIndex( previousScript )]);
if (idocRecPtr->iDocSignature == kTSMShadowDocumentSig) /* a special ID */
openedDefIMRecordPtr->openedDefIMCInstance = nil; /* make sure it is nil */
/* if there is any instance, then hide the Palette ... */
/* else, the Palette should be taken down by the IM. when the last instance is closed. <#45> */
if ( CountComponentInstances( openedDefIMRecordPtr->openedDefIMComponent ) > 0 ) {
if (previousScript == theNewScript) { /* same script, check if IM changed */
if (currentComponent != openedDefIMRecordPtr->openedDefIMComponent) /* IM switched */
need2HidePalette = true; /* then need to clean up the previous IM stuff */
}
else /* different scripts */
need2HidePalette = true; /* input method must be also changed */
}
if (need2HidePalette) { /* if we need to hide the Palette, then need to open the Component */
if (idocRecPtr->iDocSignature == kTSMShadowDocumentSig) { /* a special ID */
openedDefIMRecordPtr->openedDefIMServiceMenuHdl = nil; /* shadow document does not have menu */
openedDefIMRecordPtr->openedDefIMCInstance = OpenComponent(openedDefIMRecordPtr->openedDefIMComponent);
} /* open the component for the next call */
if ( openedDefIMRecordPtr->openedDefIMCInstance ) /* if we have open Component */
utHidePaletteAndMenu(openedDefIMRecordPtr); /* then talk to it */
}
if (idocRecPtr->iDocSignature == kTSMShadowDocumentSig) { /* a special ID */
if (openedDefIMRecordPtr->openedDefIMCInstance) /* need to close the Instance, */
(void) CloseComponent(openedDefIMRecordPtr->openedDefIMCInstance);
DisposeHandle((Handle) TSMVarsPtr->tsmPreviousDocID); /* and release the handle */
TSMVarsPtr->tsmPreviousDocID = nil; /* avoid HUnlocking to tsmPreviousDocID <17> */
}
HUnlock((Handle) TSMVarsPtr->tsmPreviousDocID);
TSMVarsPtr->tsmPreviousDocID = nil; /* done */
}
/********************************************************************
* take the menuresult and change the ID to the input method
* then send it to the input method
**********************************************************************/
pascal void ChangeMenuResultForInputMethod( long *MenuResult )
{
register TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
short imIndex;
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
long cmResult;
imIndex = utGetScriptIndex(TSMVarsPtr->tsmCurrentSLRec.fScript);
idocRecPtr = (TSMDocRecordPtr) *((Handle) TSMVarsPtr->tsmActiveDocID); /* dereference the previous ID */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[imIndex]);
if ( openedDefIMRecordPtr->openedDefIMServiceMenuHdl ) {
if ( *MenuResult >> 16 == -kTSMSystemMenuID ) {
(void) BeginSystemMode(); /* input method is treated as system service <#18> */
cmResult = TextServiceMenuSelect(openedDefIMRecordPtr->openedDefIMCInstance, openedDefIMRecordPtr->openedDefIMServiceMenuHdl, (short)*MenuResult);
(void) EndSystemMode(); /* close the window really quick <#18> */
}
}
}
/*******************************************************************************
* Function utCreateSystemVersionOfMenu
* Take a menu that belongs to an input method, make a copy of it,
* change the ID of our copy to be our special -16500 menuID, and stick it
* in the system Menu
********************************************************************************/
pascal void SetRomMapInsertToTrue() =
{
0x31FC, 0xFFFF, 0x0B9E //move.w #MapTrue,RomMapInsert
};
Boolean utCreateSystemVersionOfMenu( MenuHandle mHdl, TSMVarsRec *TSMVarsPtr)
{
#define MBDFHndl (0x0B58)
#define kKeyboardMenuID (-16491) // -16491: The keyboard menu ID
typedef struct MListRecord {
short lastMenu; //Offset to last regular menu in the MenuList }
short lastRight; //Pixel location of rgt edge of rgtmost menu }
short mbResID //High 13 bits = RSRC ID of MBDF, Low 3 = MBVariant }
} MListRecord;
typedef pascal long (*CallMBARProc)( short selector, short message, short param1, long param2);
long theMenuList = ( *(long *)ApplicationMenuList );
long theSystemMenuList = ( *(long *)SystemMenuList );
Handle mbarHandle;
long hstate;
short numberOfMenusInList;
if ( theMenuList == 0L )
return false;
numberOfMenusInList = **(short **)(theMenuList);
numberOfMenusInList /= 6;
if ( numberOfMenusInList == 0 )
return false;
//
//remember the old menuID and Change the menuID of the menu to -16500
//
TSMVarsPtr->tsmRealSystemMenuID = (*mHdl)->menuID;
(*mHdl)->menuID = -kTSMSystemMenuID;
//
//now load the iconsuite for the component(maybe)
//
if ( theMenuList != nil ) {
InsertMenu(mHdl,kKeyboardMenuID);
if ( theSystemMenuList != nil ) { //change menulist to be the systemmenulist
( *(long *)SystemMenuList ) = theMenuList;
InsertMenu(mHdl,kKeyboardMenuID);
( *(long *)SystemMenuList ) = theSystemMenuList;
}
//
//call the MBDF proc to update
//
SetRomMapInsertToTrue();
mbarHandle = GetResource( 'MBDF',(*(MListRecord **)theMenuList)->mbResID & (short)0xFFF8);
if (mbarHandle) { // check for error
(* (Handle *)MBDFHndl) = mbarHandle;
hstate = HGetState(mbarHandle);
HLock(mbarHandle);
(void)((CallMBARProc)(*mbarHandle))((*(MListRecord **)theMenuList)->mbResID & (short)0x0007,2,0,0);
HSetState(mbarHandle, hstate);
}
InvalMenuBar();
return true;
}
return false;
}
/* *************************************************************************** *
* Function: utActivateIM4Document *
* Activate the input method of the current script for this document. *
* Add its menu and activate the instance. The instance is not opened anew *
* If the instance is not open, this call returns an error. *
* ¥¥ Warning: 1. No error checking on the doc ID !! *
* *
* Modification history: *
* 25Mar92 KST If there is a previous document ID saved in the TSM global *
* then need to make check if we need to remove its palette. *
* *************************************************************************** */
OSErr utActivateIM4Document(
TSMDocumentID theDocID,
ScriptCode theScript)
{
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
MenuHandle serviceMenuHandle = nil;
ComponentResult cmResult = 0;
if (TSMVarsPtr->tsmPreviousDocID) { /* something to clean up */
utCleanUpPreviousDoc(theDocID, theScript);
}
idocRecPtr = (TSMDocRecordPtr) *((Handle) theDocID); /* dereference the handle */
/* Activate the default input method of the current script if it is open */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[utGetScriptIndex(theScript)]);
if (openedDefIMRecordPtr->openedDefIMCInstance) { /* if there is one open */
if (openedDefIMRecordPtr->openedDefIMActiveP) /* if the input method is already active */
return noErr;
HLock((Handle) theDocID); /* <10Mar92 #10> */
cmResult = InitiateTextService(openedDefIMRecordPtr->openedDefIMCInstance);
cmResult = ActivateTextService(openedDefIMRecordPtr->openedDefIMCInstance); /* what the app can do on error ??? */
if (cmResult == tsmComponentNoErr) {
openedDefIMRecordPtr->openedDefIMActiveP = true; /* active now */
if (openedDefIMRecordPtr->openedDefIMServiceMenuHdl) { /* if the IM has menu */
openedDefIMRecordPtr->openedDefIMMenuVisibleP = utCreateSystemVersionOfMenu(openedDefIMRecordPtr->openedDefIMServiceMenuHdl, TSMVarsPtr);
//InsertMenu(openedDefIMRecordPtr->openedDefIMServiceMenuHdl, 0);
//DrawMenuBar();
//openedDefIMRecordPtr->openedDefIMMenuVisibleP = true;/* menu is visible */
}
}
HUnlock((Handle) theDocID); /* <10Mar92 #10> */
return cmResult;
}
else return tsmTSNotOpenErr; /* IM has never opened */
}
/* ******************************************************************************** *
* Function: utDeactivateIMforDocument *
* Deactivate the input method of the current script for this document. *
* Only deactivate the instance. The instance is not closed. *
* If the instance is not open, this call is just a noop. *
* If theHideFlag == true, then remove its menu and call utHidePaletteAndMenu. *
* If theHideFlag == false, then don't remove its menu. *
* %% This routine has no public entry point, it is used only internally by *
* %% utForceDeactivateIM4Document, and utSoftDeactivateIM4Document. *
* ¥¥ Warning:1. Assume theScript is one of the CCJK scripts. *
* 2. The document is still active after the call. *
* *
* Modification history: *
* 27Feb92 KST If tsmKillApplicationP flag is set, then the menu is *
* already killed by Process Manager, don't do "DeleteMenu" !! *
* 24Mar92 KST When we deactivate the input method, now TSM will not *
* remove the menu from the menu bar. Instead, the ID is saved *
* in TSM globals, and delay the operation later in Activate. *
* 24Mar92 KST Added 2 new calls: *
* utForceDeactivateIM4Document (theHideFlag = true), *
* utSoftDeactivateIM4Document (theHideFlag = false). *
* ******************************************************************************** */
OSErr utDeactivateIMforDocument(
TSMDocumentID theDocID,
ScriptCode theScript,
Boolean theHideFlag)
{
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
MenuHandle serviceMenuHandle = nil;
OSErr err = noErr;
/* if a TSM aware app. exits without calling CloseTSMAwareApp, its docID is invalid */
/* this check will prevent from accessing garbage doc ID. <#22> */
if (utVerifyTSMDocID(theDocID)) return tsmInvalidDocIDErr;
/* For a TSM aware app. its docID can be valid, but the script is changed to Arabic. */
if ( utScriptIsNotCCJK( theScript ) ) /* if not one of CJK */
return noErr;
idocRecPtr = (TSMDocRecordPtr) *(Handle) theDocID; /* dereference the handle */
/* Deactivate the default input method of the current script if it is open */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[utGetScriptIndex(theScript)]);
if (openedDefIMRecordPtr->openedDefIMCInstance) { /* if there is one open */
if (!openedDefIMRecordPtr->openedDefIMActiveP) /* if the input method is NOT active */
return noErr; /* nothing to do then */
HLock((Handle) theDocID); /* <10Mar92 #10> */
if (theHideFlag) { /* force to hide the palette */
utHidePaletteAndMenu(openedDefIMRecordPtr); /* <29Mar92 #13> */
TSMVarsPtr->tsmPreviousDocID = nil; /* clear <#13> */
TSMVarsPtr->tsmPreviousScript = kNoSuchScript; /* don't care <#13> */
}
else {
/* Don't hide the palette/menu, just save the document ID we are deactivating */
TSMVarsPtr->tsmPreviousDocID = theDocID; /* save this ID <#13> */
TSMVarsPtr->tsmPreviousScript = theScript; /* save this script <#13> */
/* don't remove the menu now (not done yet) ????? */
/* if we do this, this means input method can have only one global menu handle */
// if (openedDefIMRecordPtr->openedDefIMServiceMenuHdl && openedDefIMRecordPtr->openedDefIMMenuVisibleP) { /* if the menu is displayed in the menu bar */
// utDeleteMenu((*(openedDefIMRecordPtr->openedDefIMServiceMenuHdl))->menuID);
// openedDefIMRecordPtr->openedDefIMMenuVisibleP = false; /* not visible anymore */
// }
}
if (openedDefIMRecordPtr->openedDefIMActiveP ) { /* we know the input method is active */
(void) DeactivateTextService(openedDefIMRecordPtr->openedDefIMCInstance); /* what the app can do on error ??? */
openedDefIMRecordPtr->openedDefIMActiveP = false; /* not active anymore */
}
HUnlock((Handle) theDocID); /* <10Mar92 #10> */
}
else err = tsmTSNotOpenErr;
return err;
}
/* **************************************************** *
* Function: utDeleteCleanUpTSMDocument *
* Delete the document and then clean it up. *
* This will remove the palette when app crashes. *
* Used in XCLOSETSMAWAREAPPLICATION() only. *
* Modification history: *
* 23Jun92 KST New today *
* **************************************************** */
void utDeleteCleanUpTSMDocument(TSMDocumentID theDocID)
{ OSErr err;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
err = xDeleteTSMDocument(theDocID); /* delete the document */
if (err == noErr) {
if (TSMVarsPtr->tsmPreviousDocID) /* something to clean up */
utCleanUpPreviousDoc(nil, TSMVarsPtr->tsmPreviousScript);
}
}
/* ************************************************************************ *
* Function: utCloseIM4Document *
* Close the input method of the current script for this document. *
* If there is no Input Method open, then return noErr. *
* ¥¥ Warning: 1. No error checking on the doc ID !! *
* 09Apr92 KST IM's menu handle is never released by TSM. IM should *
* use one menu and keep track of it itself. *
* 14Jun92 KST Delete from system menu list but keep in app's menu so that *
* when a TSM aware application (using Akiko in Roman promary *
* script) deletes all the TSM documents, Akiko's menu will *
* still stays in the menu bar. *
* 18Jun92 KST After closing the input method, reset TSM globals. <#33> *
* 23Jun92 KST Take down the palette as well when hidePaletteP is true. *
* ************************************************************************ */
OSErr utCloseIM4Document(
TSMDocumentID theDocID,
ScriptCode theScript,
Boolean hidePaletteP) /* only true when called by SetDefaultInputMethod */
{
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
MenuHandle serviceMenuHandle = nil;
short imIndex;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
idocRecPtr = (TSMDocRecordPtr) *((Handle) theDocID); /* dereference the handle */
/* close the default input method of the current script if it is open */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[utGetScriptIndex(theScript)]);
if (openedDefIMRecordPtr->openedDefIMCInstance) { /* if there is one open */
HLock((Handle) theDocID); /* <10Mar92 #10> */
if (openedDefIMRecordPtr->openedDefIMServiceMenuHdl) { /* if it has a menu */
if (openedDefIMRecordPtr->openedDefIMMenuVisibleP) { /* and if menu is visible */
if (CountComponentInstances( openedDefIMRecordPtr->openedDefIMComponent ) == 1) {
/* If this is the last instance, remove the menu from the menulist before closing it, *
* because when closing the last instance, input method will dispose the menu handle! ... */
utDeleteMenu((*(openedDefIMRecordPtr->openedDefIMServiceMenuHdl))->menuID);
imIndex = utGetScriptIndex(theScript); /* index for the new script <#45> */
TSMVarsPtr->tsmDefIMInfoTable[imIndex].gMenuHandle = nil; /* no menu handle now <#45> */
/* If we delete the last instance because we switch to another input method within the same script, */
/* utDeleteMenu() will not delete the menu from the system menulist, so we have to do it explicitly */
utDeleteSysMenu((*(openedDefIMRecordPtr->openedDefIMServiceMenuHdl))->menuID, 0); /* <14Jun92 #30> */
}
//systemLong = GetEnvirons(smSysScript); /* need to remove it for non-CJK primary script<14Jun92 #30> */
//utDeleteSysMenu((*(openedDefIMRecordPtr->openedDefIMServiceMenuHdl))->menuID, systemLong); /* <14Jun92 #30> */
}
// DisposeHandle((Handle) openedDefIMRecordPtr->openedDefIMServiceMenuHdl); /* release the menu handle */
// never release the menu ....
}
if (hidePaletteP)
(void) HidePaletteWindows(openedDefIMRecordPtr->openedDefIMCInstance); /* hide it please <#36> */
if (openedDefIMRecordPtr->openedDefIMActiveP) /* if it is active <24Jun92 #37> */
(void) DeactivateTextService(openedDefIMRecordPtr->openedDefIMCInstance); /* what the app can do on error ??? */
CloseComponent(openedDefIMRecordPtr->openedDefIMCInstance); /* and then close it */
/* reset all flags and globals ... */
/* close IM doesn't change this information. Open IM will update it */
// imIndex = utGetScriptIndex(theScript); /* index for the new script <#33> */
// TSMVarsPtr->tsmDefIMInfoTable[imIndex].gComponent = nil; /* save this new comp <#33> */
// TSMVarsPtr->tsmDefIMInfoTable[imIndex].gMenuHandle = nil; /* no menu handle now <#33> */
openedDefIMRecordPtr->openedDefIMCInstance = nil;
openedDefIMRecordPtr->openedDefIMComponent = nil;
openedDefIMRecordPtr->openedDefIMServiceMenuHdl = nil;
openedDefIMRecordPtr->openedDefIMMenuVisibleP = false;
openedDefIMRecordPtr->openedDefIMActiveP = false; /* clear every thing */
HUnlock((Handle) theDocID); /* <10Mar92 #10> */
}
return noErr;
}
/* **************************************************************** *
* Remove the previous menu from menu bar because the input method *
* has no menu. Called only by 'utOpenIM4Document'. <#33> *
* *
* 18Jun92 KST New today. *
* **************************************************************** */
void utDeleteInputMethodsPreviousMenu(short menuID)
{
long theMenuList;
long theSystemMenuList = ( *(long *)SystemMenuList );
DeleteMenu(menuID);
if ( theSystemMenuList != nil ) { /* change menulist to be the systemmenulist */
theMenuList = ( *(long *) ApplicationMenuList ); /* save app's menulist */
( *(long *) ApplicationMenuList ) = theSystemMenuList;
DeleteMenu(menuID);
( *(long *) ApplicationMenuList ) = theMenuList; /* restore */
}
InvalMenuBar(); /* this does not redraw */
}
// avoid linking in evil glue. we don't have PurgeSpaceSys, anyway.
#pragma parameter __A0 PurgeSpaceSysContig
pascal unsigned long
PurgeSpaceSysContig(void) = {0xA562};
/* _PurgeSpace ,SYS
* On exit A0: contig (long word)
* D0: total (long word)
*/
Boolean utCheckSysHeapSlop() /* for Cube-E by YK. */
{
unsigned long minSysHeapFreeSpace;
unsigned long hiSysRoom, lowTempRoom;
Handle tempHandle;
minSysHeapFreeSpace = GetExpandMemMinSysHeapFreeSpace();
if ( GetExpandMemProcessMgrExists() ) // if the Process Manager is there,
{ // the bottom part of the Process Mgr heap can be considered potential System Heap.
SysZoneFloatSizes( nil, &lowTempRoom); // try fairly cheap call to get free space at bottom of PM heap.
if ( lowTempRoom>=minSysHeapFreeSpace )
return true;
SysZoneFloatSizes( &hiSysRoom, nil); // try more expensive call for free space at top of System heap.
if ( (hiSysRoom+lowTempRoom)>=minSysHeapFreeSpace )
return true;
if ( PurgeSpaceSysContig()>=minSysHeapFreeSpace ) // take purgeable space into account.
return true;
}
else
{
if ( PurgeSpaceSysContig()>=minSysHeapFreeSpace )
return true;
tempHandle = NewHandle( minSysHeapFreeSpace); // hope System heap grows.
if ( tempHandle!=nil )
{
DisposeHandle( tempHandle);
return true;
}
}
return false;
}
/* **************************************************************************************** *
* Function: utOpenIM4Document (Just open) *
* Open this Component for the document as its default input method of the current script. *
* ¥¥ Warning: 1. Assume no input method of this script opened for this document !! *
* 2. No error checking on the doc ID !! *
* 3. We are not using the old Japanese input method. *
* *
* Modification history: *
* 18Feb92 KST Call BeginSystemMode before OpenComponent and BeginSystemMode after. <#4> *
* 02Mar92 KST It now takes a Boolean flag to indicate if we should activate the input *
* method. (SWM creates new TSM document but don't want IM activated.) *
* If the flag is false, then we will not activate the input method, and will *
* not insert its menu. *
* 30Apr92 KST If open IM for SWM's document, set the zone to system zone so that the *
* instance will not get closed when the application exits. <#19> *
* 18Jun92 KST After openning the input method, save the Component and menu handle!<#33> *
* **************************************************************************************** */
OSErr utOpenIM4Document(
TSMDocumentID theDocID,
Component theComponent,
ScriptCode theScript,
Boolean activateP)
{
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
ComponentInstance aCompInstance;
MenuHandle serviceMenuHandle = nil;
ComponentResult cmResult = 0;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
short imIndex;
THz aZone = nil;
imIndex = utGetScriptIndex(theScript);
HLock((Handle) theDocID); /* <10Mar92 #10> */
idocRecPtr = (TSMDocRecordPtr) *((Handle) theDocID); /* dereference the handle */
/* open the default input method of the current script if it is not already opened */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[imIndex]);
/* open the IM Component in system mode ... */
(void) BeginSystemMode(); /* so that files will be openned in system mode <# 4> */
if (idocRecPtr->iDocPSNRecord == TSMVarsPtr->tsmSWMsPSNRecord) /* only if doc belongs to SWM <#19> */
aZone = utSwapZone( SystemZone() ); /* open the Component in system zone <#19> */
aCompInstance = OpenComponent(theComponent);
(void) EndSystemMode(); /* and use MF temp memory ... <#4> */
if (aCompInstance == nil) { /* can't open it */
HUnlock((Handle) theDocID); /* <10Mar92 #10> */
if (aZone) (void) utSwapZone(aZone); /* restore the zone <#19> */
return tsmCantOpenComponentErr; /* Component Manager never tells us what's wrong -- too bad */
}
if ( !utCheckSysHeapSlop() ) { /* Ok if it is opened, check the sysheap slop, if not enough close it */
(void) HidePaletteWindows(aCompInstance); /* thank you */
(void) CloseComponent(aCompInstance); /* close the instance */
HUnlock((Handle) theDocID);
if (aZone) (void) utSwapZone(aZone); /* restore the zone */
return memFullErr; /* return the MemFull error in this case */
}
/* associate the instance with the document */
openedDefIMRecordPtr->openedDefIMCInstance = aCompInstance;
openedDefIMRecordPtr->openedDefIMComponent = theComponent;
TSMVarsPtr->tsmDefIMInfoTable[imIndex].gComponent = theComponent; /* save this new component <#33> */
if (activateP) { /* activate the input method only if flag is true <#7> */
cmResult = InitiateTextService(aCompInstance); /* inform Component to start servicing */
cmResult = ActivateTextService(aCompInstance); /* and activate the service */
if (cmResult == tsmComponentNoErr)
openedDefIMRecordPtr->openedDefIMActiveP = true; /* I.M. is active */
else
return cmResult;
}
cmResult = GetTextServiceMenu(aCompInstance, &serviceMenuHandle);
if (cmResult == tsmComponentNoErr) { /* it has menu */
openedDefIMRecordPtr->openedDefIMServiceMenuHdl = serviceMenuHandle;
if (TSMVarsPtr->tsmDefIMInfoTable[imIndex].gMenuHandle != serviceMenuHandle) { /* menu has changed <#33> */
if (activateP) utDeleteInputMethodsPreviousMenu( -kTSMSystemMenuID ); /* delete the previous menu <#35> */
TSMVarsPtr->tsmDefIMInfoTable[imIndex].gMenuHandle = serviceMenuHandle; /* keep in the global too <#33> */
}
if (activateP) { /* insert the menu only if 'activate' flag is true <#7> */
if ( serviceMenuHandle != nil )
openedDefIMRecordPtr->openedDefIMMenuVisibleP = utCreateSystemVersionOfMenu(openedDefIMRecordPtr->openedDefIMServiceMenuHdl, TSMVarsPtr);
}
}
else if (cmResult == tsmTSHasNoMenuErr) { /* if it has no menu, then make sure no left over in the system menu <#33> */
utDeleteInputMethodsPreviousMenu( -kTSMSystemMenuID ); /* delete the previous menu <#33> */
TSMVarsPtr->tsmDefIMInfoTable[imIndex].gMenuHandle = nil; /* no menu now <#33> */
}
HUnlock((Handle) theDocID); /* <10Mar92 #10> */
if (aZone) (void) utSwapZone(aZone); /* restore the zone <#19> */
return noErr;
}
/************************************************************************************* *
* Function: utOpenActivateDefaultIM *
* Open the default input method for the current keyscript if it is not already open. *
* If the default input method is already open, we return noErr also to signal the *
* presence of a default input method. And we will also make sure it is activated. *
* If the current script does not need input method, then this routine will return *
* tsmScriptHasNoIMErr error. *
* *
* Output: tsmScriptHasNoIMErr = if we are using the old Japanese IM, or *
* if the current keyscript does not need an IM, *
* tsmInvalidDocIDErr = if the activeDocID is not a valid ID, *
* *
* This function is called by: NewTSMDocument, SetTextServiceLanguage. *
* I assume the default input method has been set up before this call is made. *
* ¥¥ What to do if we cannot find or cannot open the default input method ?????????? *
* *
* Modification history: *
* 23Jan92 KST Changed to open Input method for the document. One instance for each *
* open document. Not shared in a global sense. *
* 02Mar92 KST It now takes a Boolean flag to indicate if we should activate the input *
* method. (SWM creates new TSM document but don't want IM activated.) *
* This flag only applies when we want to open, not activate, the IM. *
* The flag will be true except when called from NewTSMDocument by SWM. *
* The flag is passed down to "utOpenIM4Document" and is used there. <#7> *
************************************************************************************* */
OSErr utOpenActivateDefaultIM(TSMDocumentID activeDocID,
Boolean activateP)
{
OSErr err;
long tempLong;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
DefIMInstanceRecord *openedDefIMRecordPtr;
TSMDocRecord *idocRecPtr;
Component aComponent;
ScriptCode currentScript;
ComponentResult cmResult = 0;
#ifdef TSMDebug
if (TSMVarsPtr->tsmDebugSignature != kDebugSignature) {
utTSMDebug(1);
return -1;
}
#endif
currentScript = TSMVarsPtr->tsmCurrentSLRec.fScript;
/* but first check if user is using an old Japanese input method */
if (currentScript == smJapanese) { /* only check for Japanese script */
tempLong = GetScript(smJapanese, kUseOldJapaneseIM); /* use old script? */
if (tempLong) return tsmScriptHasNoIMErr; /* Yes, so return. */
}
if (utScriptIsNotCCJK(currentScript)) /* does the script need IM? */
return tsmScriptHasNoIMErr; /* no, only CJK uses IM */
err = utVerifyTSMDocID(activeDocID); /* is this a valid TSM ID? */
if (err != noErr) /* invalid id */
return err;
idocRecPtr = (TSMDocRecordPtr) *((Handle) activeDocID); /* dereference the handle */
/* open the default input method of the current script if it is not already opened. */
/* we might called from "SetTextServiceLanguage", where we just want to activate an input method. */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[utGetScriptIndex(currentScript)]);
if (openedDefIMRecordPtr->openedDefIMCInstance) { /* already opened */
return utActivateIM4Document(activeDocID, currentScript); /* activate and return */
}
/* IM is not open, find the default input method from TSM ... */
err = xGetDefaultInputMethod(&aComponent, &TSMVarsPtr->tsmCurrentSLRec);
if (err == noErr) { /* if a default input method is found */
err = utOpenIM4Document(activeDocID, aComponent, currentScript, activateP); /* then open it */
}
return err;
}
/* ******************************************************************** *
* utActivateThisDocsInputMethod: *
* This document was deactivated and is now being activated, if *
* user is still using the same IM, then just activate it; else, *
* close the previous Input Method and open the new one. *
* Used in "xActivateTSMDocument" and "xUseInputWindow". *
* Note: We checked that we are not using Old JIM. *
* Input: idocID = document ID *
* ¥¥ This document could be active and the input method's is not in *
* the case when user turn UseInputWindow to false for this doc. *
* Modification history: *
* 10Apr92 KST When switch from a TSM aware app to a non-TSM aware app *
* and both use the same IM, we didn't inform PM that it *
* should start/stop sending events to SWM. *
* Note that this happens when script and IM are not *
* changed. If they do changed, PM will be notified then. *
* 08Jun92 KST If we open the input method for the document, then we *
* need to check if the app is currently using Input *
* Window, if yes then tell PM start sending events to SWM *
* ******************************************************************** */
OSErr utActivateThisDocsInputMethod(TSMDocumentID idocID)
{
short imIndex;
OSErr err;
Boolean need2InformPM = false;
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
ProcessSerialNumber PSNRecord;
#ifdef TSMDebug
if (TSMVarsPtr->tsmDebugSignature != kDebugSignature) {
utTSMDebug(1);
return -1;
}
#endif
/* Check if the default IM has been switched after this document is deactivated ... *
* The keyboard script might have switched as well, but we only care about the IM *
* of the current script. Because all IM should be deactivated at this state. */
imIndex = utGetScriptIndex(TSMVarsPtr->tsmCurrentSLRec.fScript); /* index for the current script */
#ifdef TSMDebug
if (TSMVarsPtr->tsmDefIMInfoTable[imIndex].gComponent == nil) {
DebugStr("\pNo input method for the current script to activate");
}
#endif
idocRecPtr = (TSMDocRecordPtr) *((Handle) idocID); /* dereference the handle */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[imIndex]); /* the default IM we were using */
if (TSMVarsPtr->tsmDefIMInfoTable[imIndex].gComponent == openedDefIMRecordPtr->openedDefIMComponent) { /* IM never switched */
err = utActivateIM4Document(idocID, TSMVarsPtr->tsmCurrentSLRec.fScript);
/* Current script is one of CJK, and requires TSM input method then inform */
/* process Manager to start or stop sending events to SWM */
/* We are switching between a TSM aware and a non-TSM aware app using the same IM. */
/* We need to do this because we don't know when a process has swapped in. */
if (err == noErr) need2InformPM = true; /* so set the flag */
}
else { /* IM or script switched while we are deactivated. OR we have never opened the IM */
/* The problem with a TSM aware application in Roman script. Select Akiko and then click in TeachText, *
* now the script is still in Japanese, but you not type into SWM because RouteEvent is still false.... */
if (openedDefIMRecordPtr->openedDefIMComponent == nil) {
err = utOpenIM4Document (idocID, TSMVarsPtr->tsmDefIMInfoTable[imIndex].gComponent, TSMVarsPtr->tsmCurrentSLRec.fScript, true);
if (err == noErr) need2InformPM = true; /* so set the flag */
}
else {
(void) utCloseIM4Document(idocID, TSMVarsPtr->tsmCurrentSLRec.fScript, false); /* close the old one if open */
err = utOpenIM4Document (idocID, TSMVarsPtr->tsmDefIMInfoTable[imIndex].gComponent, TSMVarsPtr->tsmCurrentSLRec.fScript, true);
}
}
if ( need2InformPM ) {
(void) GetCurrentProcess(&PSNRecord); /* get current process's PSN */
if (utaIsAppTSMAwareAndNotUsingIW(&PSNRecord) == noErr) /* if the current application is TSM aware */
(void) RouteEventToSWM(false); /* then do not send events to SWM */
else /* if the current application is not TSM aware or is using input window */
(void) RouteEventToSWM(true); /* then always sending events to SWM */
}
return err;
}
/* ¥¥ not complete yet (is this necessary?) */
Boolean /* return true if the script is installed in the System */
utSupportedSL(ScriptLanguageRecord *slRecPtr)
{ #pragma unused (slRecPtr)
return true;
}
/* ******************************************************** *
* utScriptIsNotCCJK: *
* return true if the script has no input method (not CJK) *
* *
* Input: script -- the script to check. *
* Output: true (non-zero) if script is not one of CJK. *
* Modification History: *
* Changed the name from utHasNoInputMethod() to new one. *
* ******************************************************** */
Boolean
utScriptIsNotCCJK( ScriptCode script)
{
switch (script) {
case smTradChinese:
case smSimpChinese:
case smJapanese:
case smKorean: return false; /* we all need input method */
break;
default: return true;
}
}
/* ******************************************************** *
* utScriptIsCCJKAndNeedsIM: *
* return true if the script (CCJK) needs input method. *
* *
* Input: script -- the script to check. *
* Output: true (non-zero) if script is one of CJK and *
* need TSM-styled input method. *
* ******************************************************** */
Boolean utScriptIsCCJKAndNeedsIM(ScriptCode script)
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
switch (script) {
case smTradChinese:
case smSimpChinese:
case smKorean: return true; /* we all need input method */
case smJapanese: if (TSMVarsPtr->tsmUseOldJInputMethodP) /* are we using the old JIM? */
return false; /* yes, so return false */
return true; /* else we need input method */
default: return false;
}
}
/* **************************************************** *
* utInformPMgr: *
* If Process Manager is active, then inform it if we *
* should start sending events to SWM. *
* *
* Called by SWM when it is launched. This is the first *
* chance we have to sync'nize the script with PM. *
* **************************************************** */
void utInformPMgr()
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
long addr1, addr2;
#ifdef TSMDebug
if (TSMVarsPtr->tsmDebugSignature != kDebugSignature) {
utTSMDebug(1);
return -1;
}
#endif
if (!TSMVarsPtr->tsmPMgrActiveP) { /* if PM not active */
addr1 = GetToolTrapAddress(_Unimplemented); /* check again */
addr2 = GetToolTrapAddress(_OSDispatch);
if (addr1 != addr2) /* active now. this should only excute once */
TSMVarsPtr->tsmPMgrActiveP = true;
else /* if not, return now */
return;
}
/* Here, PM is activated .... */
/* If the system is using old Japanese input method, then don't activate SWM. <12Jan92 #12> */
/* If current script is one of CJK, then inform process Manager to start sending events to SWM */
/* Activate SWM only if we are not using old Japanese Input Method. -- <31Jan92 #17> */
if (TSMVarsPtr->tsmCurrentSLRec.fScript == smJapanese) { /* only check for Japanese script */
if (GetScript(smJapanese, kUseOldJapaneseIM)) { /* use old script? */
(void) RouteEventToSWM(false); /* don't send events to SWM */
return; /* Yes, so return. */
}
}
if (!utScriptIsNotCCJK(TSMVarsPtr->tsmCurrentSLRec.fScript)) /* if current script needs input method */
(void) RouteEventToSWM(true); /* then send events to SWM */
else
(void) RouteEventToSWM(false); /* else, don't send events to SWM */
}
/* **************************************************************************************************** *
* Note: "utDocNeedsInputMethod" does not and can not move memory ! *
* Return true if the document/application needs input method. (not in any of the following states). *
* 1. If the script is not CJK, then it doesn't need input method. *
* 2. If the script is Japanese and it's using old JIM, then it doesn't need input method. *
* 3. If the document is using Input Window (locally or globally), then it doesn't need input method. *
* **************************************************************************************************** */
Boolean
utDocNeedsInputMethod( ScriptCode script,
ProcessSerialNumber *PSNRecordPtr)
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
if (utaIsAppTSMAwareAndNotUsingIW(PSNRecordPtr) != noErr)
return false; /* if using bottom window then return false */
switch (script) {
case smTradChinese:
case smSimpChinese:
case smKorean: return true; /* we all need input method */
break;
case smJapanese: if (TSMVarsPtr->tsmUseOldJInputMethodP) /* are we using the old JIM? */
return false; /* yes, so return false */
return true; /* we need input method */
default: return false;
}
}
/* ******************************************** *
* return array index based on script code. *
* Warning: no error checking on the script! *
* ******************************************** */
int
utGetScriptIndex(ScriptCode script)
{
// 4 input methods for the following scripts ...
// smJapanese = 1, /* map to 1 => Japanese */
// smTradChinese = 2, /* map to 2 => Traditional Chinese */
// smKorean = 3, /* map to 3 => Korean */
// smSimpChinese = 25, /* map to 0 => Simplified Chinese */
#ifdef BuildTSMInit
switch (script) {
case smTradChinese:
case smSimpChinese:
case smKorean:
case smJapanese: break; /* these scripts are OK */
default: DebugStr("\pIllegal script!");
}
#endif
if (script == smSimpChinese) return 0;
else return script; /* use the script as index */
}
/* *************************************************************************************** *
* Search the System resource for the default input method according to script. If we have *
* saved the default IM, then return noErr and return the Component description in "cdPtr". *
* ¥¥ Note: Assume "utScriptIsNotCCJK" has been called before using this function. *
* *
* Modification history: *
* 06Feb92 KST We now save old input method info in the same 'inpm' resource. If the *
* default is old IM, we return a special error - "tsmInputMethodIsOldErr" *
* and return the script code in componentType, FEP ID in componentSubType *
* *************************************************************************************** */
OSErr utGetTSMDefaultInputMethod( ComponentDescription *cdPtr,
ScriptLanguageRecord *slRecPtr)
{
DefIMRecordHandle defIMInfoHandle;
IMSRecord *imRecordPtr;
Handle defIMResource = nil;
OSErr err;
int index;
/* "utScriptIsNotCCJK" has been called by "xGetDefaultInputMethod" */
index = utGetScriptIndex(slRecPtr->fScript);
/* get the resource from System file, defined in TSMPrivate.H */
defIMResource = GetResource( kTSMDefInputMethodType, kTSMDefInputMethodID);
err = ResError(); /* this will return noErr -- BAD */
if (err) return err;
if (defIMResource == nil) return resNotFound;
if (*defIMResource == nil) { /* if handle is empty */
LoadResource(defIMResource);
if (*defIMResource == nil) /* still cannot load it */
return resNotFound;
}
defIMInfoHandle = (DefIMRecordHandle) defIMResource;
if ((*defIMInfoHandle)->defRsrcSignature != kINPMresourceSig) /* is this the right TSM resource? */
return resNotFound; /* better stop now */
if ((*defIMInfoHandle)->defIMCount != kSavedDefaultIMCount) /* if we saved any, then search for it */
return resNotFound; /* this might overkill */
imRecordPtr = &((*defIMInfoHandle)->defIMRecordArray[index]); /* index set above */
/* Verify if the record is valid and script is the same */
if (imRecordPtr->imValidP) { /* don't check script code <06Feb92 #23> */
if (imRecordPtr->imUseOldInputMethodP) { /* if the default is old one <06Feb92 #23> */
cdPtr->componentType = (OSType) slRecPtr->fScript; /* return script and FEP ID <06Feb92 #23> */
cdPtr->componentSubType = (OSType) imRecordPtr->imOldInputMethodFEPID; /* <06Feb92 #23> */
err = tsmInputMethodIsOldErr; /* return special error <06Feb92 #23> */
}
else { /* default is TSM-styled */
*cdPtr = imRecordPtr->imCDRec; /* copy the structure */
err = noErr;
}
}
else err = tsmInputMethodNotFoundErr; /* no valid info saved */
return err;
}
/* compose Component flag from Script/Language record pointer ... */
unsigned long
utSLRec2CompFlag(ScriptLanguageRecord *slRecPtr)
{
unsigned long flag = slRecPtr->fScript;
return ((flag << 8) + slRecPtr->fLanguage);
}
/* **************************************************************************** *
* User wants to switch to old input method (for Japanese script only) *
* If the current document is using a new JIM, then we need to deactivate it *
* This call implies we are switching to Japanese keyscript too ..... *
* *
* Modification history: *
* 24Mar92 KST Need to call utForceDeactivateIM4Document instead of *
* utDeactivateIM4Document. *
* **************************************************************************** */
OSErr utChangeToOldJIM(ScriptIDRecordPtr sidrecptr)
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
int index;
OSErr err;
ScriptCode oldScript, deactivateScript;
DefIMRecordHandle defIMHandle;
IMSRecord *imRecordPtr;
/* script is smJapanese, I hope the caller is correct */
if (sidrecptr->sidScript != smJapanese) {
#ifdef TSMDebug
DebugStr("\putChangeToOldJIM: Script is not Japanese");
#endif
return tsmScriptHasNoIMErr;
}
if (TSMVarsPtr->tsmPMgrActiveP) /* if PM has booted */
(void) RouteEventToSWM(false); /* don't send events to SWM any more */
TSMVarsPtr->tsmUseOldJInputMethodP = true; /* set the flag -- <#22> */
oldScript = TSMVarsPtr->tsmCurrentSLRec.fScript; /* current script - we might switch from Roman to Japanese */
/* need to update the resource */
index = utGetScriptIndex(smJapanese);
/* Save the resource in System file, as defined in TSMPrivate.H */
/* first let's see if we have created the resource ... */
defIMHandle = (DefIMRecordHandle) GetResource( kTSMDefInputMethodType, kTSMDefInputMethodID);
/* if not, create it now ... */
if (defIMHandle == nil) { /* if there is no such resource */
err = utAddTSMResource(&defIMHandle); /* then allocate and add one */
if (defIMHandle == nil) return err; /* probably no memory */
}
if (*defIMHandle == nil) { /* if handle is empty */
LoadResource((Handle) defIMHandle); /* then load it */
if (*defIMHandle == nil) { /* still cannot load it */
return resNotFound;
}
}
if ((*defIMHandle)->defRsrcSignature != kINPMresourceSig) /* is this the right TSM IM resource? */
return resNotFound; /* better stop now */
/* now we have the resource, update the default */
imRecordPtr = &((*defIMHandle)->defIMRecordArray[index]); /* index set above */
imRecordPtr->imValidP = true; /* it's valid now */
imRecordPtr->imUseOldInputMethodP = true; /* default is old input method */
imRecordPtr->imOldInputMethodFEPID = sidrecptr->sidFEPID; /* this is the FEP id */
HNoPurge((Handle) defIMHandle); /* make it no purgeable before we write to it */
ChangedResource((Handle) defIMHandle); /* save current resfile */
WriteResource( (Handle) defIMHandle); /* write it back to System resource */
HPurge((Handle) defIMHandle);
/* *********************** END processing resource file **************************/
if (TSMVarsPtr->tsmActiveDocID == nil) /* if there is no active document */
return noErr; /* then just bow and quit */
/* If there is no active document, and the current script is not CJK, *
* then we don't change the current TSM script ... */
TSMVarsPtr->tsmCurrentSLRec.fScript = smJapanese; /* set current new script */
/* Here we got an active current document, since old Japanese input method *
* does not need TSM document, so we need to deactivate it and its TSM style IM */
// deactivateScript = kNoSuchScript;
// if (oldScript != smJapanese) { /* if we switch from C. or K. to old Japanese IM */
// if (oldScript==smTradChinese || oldScript==smKorean || oldScript==smSimpChinese)
// deactivateScript = oldScript;
// }
// else deactivateScript = smJapanese; /* else we switch from new JIM to old JIM */
if ( utScriptIsNotCCJK(oldScript) ) /* if not one of CJK */
deactivateScript = kNoSuchScript;
else
deactivateScript = oldScript;
if (deactivateScript != kNoSuchScript) { /* if we switch from new (CJK) IM to old Japanese IM */
utFixDocumentAndCloseSWMWindow(deactivateScript); /* then deactivate IM of the current doc and close SWM's window */
}
return noErr;
}
/* ******************************************************************** *
* utSuspendResumeApp: Suspend or resume a non-TSM aware application. *
* Used by InformTSM. *
* Called by PM in StartForegroundSwitch (ScrapCoercion.c) *
* We are sure: 1. SWM is around, and *
* 2. The app is not TSM aware. *
* Output: always returns noErr. *
* Modification history: *
* 09Apr92 KST New today. *
* ******************************************************************** */
OSErr utSuspendResumeApp( short flag )
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
TSMDocRecord *idocRecPtr;
DefIMInstanceRecord *openedDefIMRecordPtr;
long systemScript;
short imIndex;
char handleState;
ScriptCode currentScript;
TSMDocumentID currentTSMActiveDocID;
systemScript = GetEnvirons(smSysScript);
currentTSMActiveDocID = TSMVarsPtr->tsmActiveDocID;
if ( currentTSMActiveDocID ) { /* if we have current active doc -- must be SWM's */
currentScript = TSMVarsPtr->tsmCurrentSLRec.fScript;
handleState = HGetState( (Handle) currentTSMActiveDocID ); /* save the handle state <#27> */
HLock( (Handle) currentTSMActiveDocID );
idocRecPtr = (TSMDocRecordPtr) *((Handle) currentTSMActiveDocID ); /* dereference the current ID */
if (utScriptIsNotCCJK(currentScript)) { /* if the script has no input method */
if (idocRecPtr->iDocActiveP) { /* if it is active */
/* We take the advantage that xDeactivateTSMDocument() will check and deactivate *
* each input method when it is called while the document is not active !!! */
idocRecPtr->iDocActiveP = false; /* like I said above*/
(void) xDeactivateTSMDocument( currentTSMActiveDocID ); /* ignore error */
}
HSetState( (Handle) currentTSMActiveDocID, handleState); /* restore the handle state <#27> */
return noErr;
}
imIndex = utGetScriptIndex( currentScript ); /* index for the last script */
openedDefIMRecordPtr = &(idocRecPtr->iDocDefIMInstanceArray[imIndex]); /* the default IM we were using */
if (flag == kTSMSuspend) {
/* This application is not TSM aware. But it can be because of 2 reasons: *
* a. The app is really non-TSM aware, *
* b. The app is TSM aware but is using Input Window. *
* Case a: Need to deactivate the document, otherwise the doc is active. *
* Case b: Don't do anything because the app should make deactivate call. *
*
*
* TSM aware Roman DeactivateTSMDoc, SetTextServiceLanguage
* non-TSM non-TSM CJK Leave SWM document active, don't take down its window and menu.
* Script is not changed.
* non-TSM switch to Roman utSuspendResumeApp, take down its window and menu from app's menulist.
* Finder If you don't take down the menu and switch from Roman back to the app,
* the pencil shows up in Roman script. Document has to be deactivated,
* otherwise, pencil will not show up in the menu bar when switch to Akiko.
* And need to take down SWM's window as well.
* non-TSM quit to Roman SetTextServiceLanguage, since there is no utSuspendResumeApp call,
* Finder the active document is non-nil. SetTextServiceLanguage will clean up
* palette, and SWM's window. (Note, Finder doesn't have IM's menu.
*/
if (currentTSMActiveDocID == TSMVarsPtr->tsmUseInputWindowDocID) { /* app is not TSM aware, and this must be SWM's doc */
//if ( utDocNeedsInputMethod(currentScript, &idocRecPtr->iDocPSNRecord) ) {
//(void) xDeactivateTSMDocument( currentTSMActiveDocID ); /* ignore error */
//(void) utSoftDeactivateIM4Document(currentTSMActiveDocID, currentScript );
// utJustDeactivateIM4Document( TSMVarsPtr->tsmActiveDocID, TSMVarsPtr->tsmCurrentSLRec.fScript, false );
//TSMVarsPtr->tsmActiveDocID = nil;
//TSMVarsPtr->tsmUseInputWindowDocID = nil;
//TSMVarsPtr->tsmActiveTSCount = 0; /* no active TS */
//}
}
if (systemScript != currentScript && /* only take down menu when they don't match */
utScriptIsNotCCJK((ScriptCode) systemScript)) { /* and the system script is not CJK */
/* If the system script is CJK, then we don't take down the menu because there will be *
* an Input method and therefore a menu, What if no menu?? So we keep the menu and keep *
* SWM's document active. If we switch to non-TSM aware application, then SWM needs to *
* be active anyway. If we switch to a TSM aware application, then that application will*
* have to activate a document, we will deactivate SWM's document and clean up menu and *
* synchronize everything when that magic moment happens. */
if (currentTSMActiveDocID == TSMVarsPtr->tsmUseInputWindowDocID) { /* app is not TSM aware, and this must be SWM's doc */
// can't fix text, because when this is called, the app is being suspended,
// if we fix text, then text will be posted to the next application.
//(void) xFixTSMDocument( currentTSMActiveDocID ); /* fix the current input area */
(void) xDeactivateTSMDocument( currentTSMActiveDocID ); /* ignore error */
utCloseSWMWindow(false); /* close window if visible */
if (openedDefIMRecordPtr->openedDefIMServiceMenuHdl ) { /* if IM has a menu */
/* remove IM's menu from the application menulist so it will not reappear again ..... *
* and remove it from the system menu too so it will not appear in other applications *
* TSM aware app will not go thru this path, but the menu will be removed when *
* SetTextServiceLanguage is called when we switch back to Finder. */
utDeleteMenu((*(openedDefIMRecordPtr->openedDefIMServiceMenuHdl))->menuID);
openedDefIMRecordPtr->openedDefIMMenuVisibleP = false; /* not visible */
}
}
else /* use input window case */
if (openedDefIMRecordPtr->openedDefIMServiceMenuHdl ) { /* if IM has a menu */
/* remove IM's menu from the application menulist so it will not reappear again ..... *
* and remove it from the system menu too so it will not appear in other applications *
* TSM aware app will not go thru this path, but the menu will be removed when *
* SetTextServiceLanguage is called when we switch back to Finder. */
utDeleteSysMenu((*(openedDefIMRecordPtr->openedDefIMServiceMenuHdl))->menuID, systemScript);
openedDefIMRecordPtr->openedDefIMMenuVisibleP = false; /* not visible */
}
}
}
else { /* not used for now */
if (systemScript == TSMVarsPtr->tsmCurrentSLRec.fScript) { /* only add menu when they match */
if (openedDefIMRecordPtr->openedDefIMServiceMenuHdl ) { /* if the IM has menu */
InsertMenu(openedDefIMRecordPtr->openedDefIMServiceMenuHdl, 0);
DrawMenuBar();
//openedDefIMRecordPtr->openedDefIMMenuVisibleP = true; /* menu is visible */
}
}
}
HSetState( (Handle) currentTSMActiveDocID, handleState); /* restore the handle state <#27> */
}
return noErr;
}
/* ******************************************************************************** *
* utAddTSMResource: allocate and add a resource to system resource file for TSM. *
* Note: we only add the resource without writing it to disk !! *
* Modification history: *
* 29Jan92 KST Set sysheap and purgeable bits. *
* ******************************************************************************** */
OSErr utAddTSMResource( DefIMRecordHandle *theHandlePtr )
{
short curResfile;
DefIMRecordHandle defIMHandle;
IMSRecord *imRecordPtr;
*theHandlePtr = nil; /* default is nil */
defIMHandle = (DefIMRecordHandle) NewHandleClear(sizeof(DefIMRecord));
if (defIMHandle == nil) return memFullErr; /* no memory */
(*defIMHandle)->defRsrcSignature = kINPMresourceSig; /* TSM resource */
(*defIMHandle)->defUseFloatWindow = false; /* don't use floating input window */
(*defIMHandle)->defIMCount = kSavedDefaultIMCount; /* size of the array */
// 4 input methods for the following scripts ...
// smJapanese = 1, /* Japanese */
// smTradChinese = 2, /* Traditional Chinese */
// smKorean = 3, /* Korean */
// smSimpChinese = 25, /* Simplified Chinese */
imRecordPtr = &((*defIMHandle)->defIMRecordArray[0]); /* 0 = Simplified Chinese */
imRecordPtr->imValidP = false; /* not valid until we set it */
imRecordPtr->imUseOldInputMethodP = false; /* default is to use TSM-style input method */
imRecordPtr->imOldInputMethodFEPID = 0; /* FEP id = 0 */
imRecordPtr = &((*defIMHandle)->defIMRecordArray[1]); /* 1 = Japanese */
imRecordPtr->imValidP = false; /* not valid until we set it */
imRecordPtr->imUseOldInputMethodP = false; /* default is to use TSM-style input method */
imRecordPtr->imOldInputMethodFEPID = 0; /* FEP id = 0 */
imRecordPtr = &((*defIMHandle)->defIMRecordArray[2]); /* 2 = Traditional Chinese */
imRecordPtr->imValidP = false; /* not valid until we set it */
imRecordPtr->imUseOldInputMethodP = false; /* default is to use TSM-style input method */
imRecordPtr->imOldInputMethodFEPID = 0; /* FEP id = 0 */
imRecordPtr = &((*defIMHandle)->defIMRecordArray[3]); /* 3 = Korean */
imRecordPtr->imValidP = false; /* not valid until we set it */
imRecordPtr->imUseOldInputMethodP = false; /* default is to use TSM-style input method */
imRecordPtr->imOldInputMethodFEPID = 0; /* FEP id = 0 */
curResfile = CurResFile(); /* save current resfile */
UseResFile(0); /* use System resource */
AddResource((Handle) defIMHandle, kTSMDefInputMethodType, kTSMDefInputMethodID, "\pTSM Resource");
SetResAttrs((Handle) defIMHandle, resSysHeap+resPurgeable);
UseResFile(curResfile);
*theHandlePtr = defIMHandle; /* return the handle */
return noErr;
}
/* ******************************************************************************** *
* utUpdateDefaultInputMethodResource: *
* Update the default input method in the system resource for the script. *
* Only used when we switch between TSM-styled input methods. That's why I *
* always set imUseOldInputMethodP to false. *
* Note: We don't open or close any instances ... *
* Side effect: The resource will be changed in the System file. *
* ******************************************************************************** */
OSErr utUpdateDefaultInputMethodResource ( Component aComp,
ScriptLanguageRecord *slRecPtr)
{
OSErr err;
int index;
ComponentDescription cdRec;
DefIMRecordHandle defIMHandle;
IMSRecord *imRecordPtr;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
/* see if there is such an Input Method supports the script/language */
err = GetComponentInfo(aComp, &cdRec, nil, nil, nil); /* fill in CD */
if (err) return err;
if (utScriptIsNotCCJK(slRecPtr->fScript)) /* does the script needs IM? */
return tsmUnknownErr; /* only CJK uses IM */
index = utGetScriptIndex(slRecPtr->fScript);
/* Save the resource in System file, as defined in TSMPrivate.H */
/* first let's see if we have created the resource ... */
defIMHandle = (DefIMRecordHandle) GetResource( kTSMDefInputMethodType, kTSMDefInputMethodID);
/* if not, create it now ... */
if (defIMHandle == nil) { /* if there is no such resource */
err = utAddTSMResource(&defIMHandle); /* then allocate and add one */
if (defIMHandle == nil) return err; /* probably no memory */
}
if (*defIMHandle == nil) { /* if handle is empty */
LoadResource((Handle) defIMHandle); /* then load it */
if (*defIMHandle == nil) { /* still cannot load it */
return resNotFound;
}
}
if ((*defIMHandle)->defRsrcSignature != kINPMresourceSig) /* is this the right TSM resource? */
return resNotFound; /* better stop now */
TSMVarsPtr->tsmDefIMInfoTable[index].gComponent = aComp; /* update the in memory copy */
/* now we have the resource, update the default */
imRecordPtr = &((*defIMHandle)->defIMRecordArray[index]); /* index set above */
imRecordPtr->imValidP = true; /* it's valid now */
imRecordPtr->imUseOldInputMethodP = false; /* set to false */
imRecordPtr->imOldInputMethodFEPID = 0;
imRecordPtr->imLanguage = slRecPtr->fLanguage; /* language */
imRecordPtr->imCDRec = cdRec; /* can we copy the structure? -> Yes ! */
HNoPurge((Handle) defIMHandle); /* make it no purgeable before we write to it */
ChangedResource((Handle) defIMHandle); /* save current resfile */
WriteResource( (Handle) defIMHandle); /* write it back System resource */
HPurge((Handle) defIMHandle);
err = ResError();
}
/* **************************************************************************** *
* Function: utFixDocumentAndCloseSWMWindow: *
* If there IS a current active TSM document, then: *
* 1. fix the input area, *
* 2. Force deactivate the input method, and *
* 3. If this document belongs to SWM, then *
* a. close SWM's input window by sending Apple Event to SWM, *
* b. and then deactivate SWM's document. (SWM's document has *
* to be deactivated because it has been decided that SWM's *
* window should go away. It will be activated again when *
* user starts typing. *
* ¥¥ Note that we don't deactivate TSM aware app's document. *
* Side effect: Text in the inline hole will be lost. *
* Called by "xActivateTSMDocument", and "xSetTextServiceLanguage". *
* *
* Modification history: *
* 24Mar92 KST Since we have 2 active documents now, need to be careful as *
* which document to deactivate here. *
* If tsmActiveDocID == tsmUseInputWindowDocID == SWM's doc, then *
* deactivate SWM's doc. Otherwise we make tsmActiveDocID equals *
* to tsmUseInputWindowDocID because when we return from this code,*
* xSetTextServiceLanguage will open the new IM for this TSM aware *
* application's document based on tsmActiveDocID. *
* 31Jul92 KST Do not fix TSMDocument since the A5 world might not be set up *
* correctly in a keydown (cmd-space) event. *
* **************************************************************************** */
void utFixDocumentAndCloseSWMWindow(ScriptCode deactivateScript)
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
TSMDocRecord *currentActiveDocPtr;
TSMDocumentID currentTSMActiveDocID;
currentTSMActiveDocID = TSMVarsPtr->tsmActiveDocID;
if ( currentTSMActiveDocID ) { /* if currently has active document <01Feb92 #21> */
currentActiveDocPtr = (TSMDocRecord *) *((Handle) currentTSMActiveDocID); /* <04Mar92 #28> */
if (currentActiveDocPtr->iDocPSNRecord == TSMVarsPtr->tsmSWMsPSNRecord) { /* doc belongs to SWM <#28> */
/* ¥¥ must call DeactivateTSMDocument and utCloseSWMWindow before we change tsmCurrentSLRec *
* ¥¥ because DeactivateTSMDocument relies on current script and current IM are in sync ! *
* ¥¥ also, I'll have to call DeactivateTSMDocument here, because when SWM receive the AE, *
* ¥¥ it is after xSetTextServiceLanguage routine already been executed ... */
(void) xFixTSMDocument( currentTSMActiveDocID ); // Akiko crashes if we do this??? works now <09Jun92 #26>
/* <4/5/92> John, we have a problem here. utForceDeactivateIM4Document will remove IM's menu
* and hide the Palette (utHidePaletteAndMenu). However, it might be too late to
* remove the menu in the following situation:
* Use Roman as the primary script. Launch any non-TSM aware application then select Akiko,
* switch to finder and switch back to that application. Notice that Akiko's menu stays.
*
* <4/6/92> Hmmm, I think we'll have the same problem in trying to fix the input area as well.
* By the time we do all these, the application already swapped out. And Akiko crashes.
*
* The solution is to send "suspend" event to SWM and SWM call DeactivateTSMDocument4SWM.
*/
(void) utForceDeactivateIM4Document( currentTSMActiveDocID, deactivateScript); /* need to deactivate the IM */
if ( currentTSMActiveDocID == TSMVarsPtr->tsmUseInputWindowDocID ) { /* SWM is the sole player */
xDeactivateTSMDocument( currentTSMActiveDocID ); /* tsmActiveDocID will be cleared .... */
}
else { /* if using Input Window */
TSMVarsPtr->tsmActiveDocID = TSMVarsPtr->tsmUseInputWindowDocID; /* they must be match */
currentActiveDocPtr = (TSMDocRecord *) *((Handle) currentTSMActiveDocID); /* dereference <09Jun92 #26> */
currentActiveDocPtr->iDocActiveP = false; /* not active <09Jun92 #26> */
}
/* SWM has to call xFixTSMDocument, and DeactivateTSMDocument in its own context */
/* remove DeactivateTSMDocument when we switch SWM to a driver, and add fixText! */
utCloseSWMWindow(false); /* ask SWM to close her input window <04Mar92 #28> */
} /* end if */
else { /* if not SWM, then I can call xFixTSMDocument in TSM aware application's context */
(void) xFixTSMDocument( currentTSMActiveDocID ); /* fix current input area ... <18Mar92 #30> */
(void) utForceDeactivateIM4Document( currentTSMActiveDocID, deactivateScript );
}
}
}
/* **************************************************************************** *
* Function: utCloseSWMWindow: <#5> *
* Close SWM's input window by sending Apple Event to SWM. *
* Side effect: Text in the inline hole will be lost. *
* Called by "xActivateTSMDocument", and "xSetTextServiceLanguage". *
* Modification History: *
* 25Jun92 KST Added one new param FlushBufferP to SWM. true = flush TE buffer *
* **************************************************************************** */
void utCloseSWMWindow(Boolean FlushBufferP)
{
ProcessSerialNumber PSNRecord;
OSErr err;
AEAddressDesc addrDescriptor;
AppleEvent theAEvent, theReply;
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
#pragma unused (theReply,theAEvent,addrDescriptor,err,PSNRecord)
#ifdef TSMDebug
if (TSMVarsPtr->tsmDebugSignature != kDebugSignature) {
utTSMDebug(1);
return;
}
#endif
if (TSMVarsPtr->tsmSWMsPSNRecord.highLongOfPSN==0 && TSMVarsPtr->tsmSWMsPSNRecord.lowLongOfPSN==0)
return; /* return if no PSN */
(void) TSMVarsPtr->tsmCloseSWMWindowProc( TSMVarsPtr->tsmSWMDrvrRefNum, FlushBufferP );
}
/* ************************************************************************ *
* Remove the menu from menu bar only if tsmKillApplicationP flag is false. *
* If tsmKillApplicationP flag is set, then the menu is already killed by *
* Process Manager, so don't do "DeleteMenu" !! (trust me). *
* *
* 27Feb92 KST New today. *
* 27Feb92 KST Need to remove IM's menu from the system menulist if we *
* are running in a non-CJK primary system. *
* ************************************************************************ */
void utDeleteMenu(short menuID)
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
long theMenuList;
long theSystemMenuList = ( *(long *)SystemMenuList );
long systemLong;
#ifdef TSMDebug
if (TSMVarsPtr->tsmDebugSignature != kDebugSignature) {
utTSMDebug(1);
return;
}
#endif
if (!TSMVarsPtr->tsmKillApplicationP) { /* if app is not exiting to shell */
DeleteMenu(menuID);
if (menuID == -kTSMSystemMenuID) { /* if this is a system menu */
systemLong = GetEnvirons(smSysScript); /* need to remove it for non-CJK system */
if (!utScriptIsNotCCJK((ScriptCode) systemLong)) { /* if current script needs input method */
if (systemLong == smJapanese) { /* special case for Japanese */
if ( !TSMVarsPtr->tsmUseOldJInputMethodP ) /* if not use old JIM */
return; /* return right now */
}
else return; /* leave the menu in system menu */
}
if ( theSystemMenuList != nil ) { /* change menulist to be the systemmenulist */
theMenuList = ( *(long *) ApplicationMenuList ); /* save app's menulist */
( *(long *) ApplicationMenuList ) = theSystemMenuList;
DeleteMenu(menuID);
( *(long *) ApplicationMenuList ) = theMenuList; /* restore */
}
}
InvalMenuBar();
}
}
void utDeleteAppsMenu(short menuID)
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
if (!TSMVarsPtr->tsmKillApplicationP) { /* if app is not exiting to shell */
DeleteMenu(menuID); /* delete it from the app's menulist */
InvalMenuBar();
}
}
/* *********************************************************************** *
* remove the menu from the system menulist, so that it will not show up *
* in other application's menu bar. The menu is not removed from the *
* current application's menulist. So it always stays with the application. *
* Useful when switch from a TSM aware application to Finder, we need to *
* keep the pencil in that app's menu but we don't want to see it when we *
* launch other applications. Called by 'utSuspendResumeApp'. *
* Note: we only remove the menu if the script is one of CCJK. *
* *********************************************************************** */
void utDeleteSysMenu(short menuID, long systemScript)
{
TSMVarsRec *TSMVarsPtr = GetExpandMemTSMGlobals();
long theMenuList;
long theSystemMenuList = ( *(long *)SystemMenuList );
if (!TSMVarsPtr->tsmKillApplicationP) { /* if app is not exiting to shell */
if (menuID == -kTSMSystemMenuID) { /* if this is a system menu */
if (!utScriptIsNotCCJK((ScriptCode) systemScript)) { /* if current script needs input method */
if (systemScript == smJapanese) { /* special case for Japanese */
if ( !TSMVarsPtr->tsmUseOldJInputMethodP ) /* if not using old JIM */
return; /* return right now */
}
else return; /* leave the menu in system menu */
}
if ( theSystemMenuList != nil ) { /* change menulist to be the systemmenulist */
theMenuList = ( *(long *) ApplicationMenuList ); /* save app's menulist */
( *(long *) ApplicationMenuList ) = theSystemMenuList;
DeleteMenu(menuID);
( *(long *) ApplicationMenuList ) = theMenuList; /* restore */
}
}
}
}
/* *********************************************************************** *
* set current zone to theZone, and return the current zone before setting *
* *********************************************************************** */
THz utSwapZone( register THz theZone )
{
register THz savedZone;
savedZone = GetZone( );
SetZone( theZone );
return( savedZone );
}
#ifdef TSMDebug
void utTSMDebug(short whocalled)
{
switch (whocalled) {
case 1:
DebugStr("\pNot TSM globals");
break;
default:
}
}
#endif