mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-17 09:29:49 +00:00
2018 lines
86 KiB
C
2018 lines
86 KiB
C
|
/*
|
|||
|
File: TSMInternalUtils.c
|
|||
|
|
|||
|
Contains: TSM internal utility routines.
|
|||
|
|
|||
|
Written by: Kenny SC. Tung
|
|||
|
|
|||
|
Copyright: <EFBFBD> 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: << <EFBFBD><EFBFBD> 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: << <EFBFBD><EFBFBD> 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: << <EFBFBD><EFBFBD> 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: << <EFBFBD><EFBFBD> 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. *
|
|||
|
* <EFBFBD><EFBFBD> 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. *
|
|||
|
* <EFBFBD><EFBFBD> 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. *
|
|||
|
* <EFBFBD><EFBFBD> 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. *
|
|||
|
* <EFBFBD><EFBFBD> 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. *
|
|||
|
* <EFBFBD><EFBFBD> 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 *
|
|||
|
* <EFBFBD><EFBFBD> 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;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* <20><> 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". *
|
|||
|
* <EFBFBD><EFBFBD> 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. *
|
|||
|
* <EFBFBD><EFBFBD> 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> */
|
|||
|
/* <20><> must call DeactivateTSMDocument and utCloseSWMWindow before we change tsmCurrentSLRec *
|
|||
|
* <EFBFBD><EFBFBD> because DeactivateTSMDocument relies on current script and current IM are in sync ! *
|
|||
|
* <EFBFBD><EFBFBD> also, I'll have to call DeactivateTSMDocument here, because when SWM receive the AE, *
|
|||
|
* <EFBFBD><EFBFBD> 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
|