344 lines
12 KiB
C++
344 lines
12 KiB
C++
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
|
/*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1999 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#include "nscore.h"
|
|
#include "nsMacEventHandler.h"
|
|
#include "nsMacTSMMessagePump.h"
|
|
#include "nsString.h"
|
|
#include <Script.h>
|
|
#include <TextServices.h>
|
|
|
|
#include "nsCarbonHelpers.h"
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// TSM AE Handler routines UPPs
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
AEEventHandlerUPP nsMacTSMMessagePump::mPos2OffsetUPP = NULL;
|
|
AEEventHandlerUPP nsMacTSMMessagePump::mOffset2PosUPP = NULL;
|
|
AEEventHandlerUPP nsMacTSMMessagePump::mUpdateUPP = NULL;
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Constructor/Destructors
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsMacTSMMessagePump::nsMacTSMMessagePump()
|
|
{
|
|
OSErr err;
|
|
|
|
mPos2OffsetUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::PositionToOffsetHandler);
|
|
NS_ASSERTION(mPos2OffsetUPP!=NULL,"nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[Pos2Pffset] failed");
|
|
|
|
mOffset2PosUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::OffsetToPositionHandler);
|
|
NS_ASSERTION(mPos2OffsetUPP!=NULL,"nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[Pos2Pffset] failed");
|
|
|
|
mUpdateUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::UpdateHandler);
|
|
NS_ASSERTION(mPos2OffsetUPP!=NULL,"nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[Pos2Pffset] failed");
|
|
|
|
err = AEInstallEventHandler(kTextServiceClass,kPos2Offset,mPos2OffsetUPP,(long)this,false);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Pos2Offset] failed");
|
|
|
|
err = AEInstallEventHandler(kTextServiceClass,kOffset2Pos,mOffset2PosUPP,(long)this,false);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Offset2Pos] failed");
|
|
|
|
err = AEInstallEventHandler(kTextServiceClass,kUpdateActiveInputArea,mUpdateUPP,(long)this,false);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Update] failed");
|
|
|
|
}
|
|
|
|
nsMacTSMMessagePump::~nsMacTSMMessagePump()
|
|
{
|
|
OSErr err;
|
|
|
|
err = AERemoveEventHandler(kTextServiceClass,kPos2Offset,mPos2OffsetUPP,false);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Pos2Offset] failed");
|
|
|
|
err = AERemoveEventHandler(kTextServiceClass,kOffset2Pos,mOffset2PosUPP,false);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Offset2Pos] failed");
|
|
|
|
err = AERemoveEventHandler(kTextServiceClass,kUpdateActiveInputArea,mUpdateUPP,false);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Update] failed");
|
|
|
|
::DisposeAEEventHandlerUPP(mPos2OffsetUPP);
|
|
::DisposeAEEventHandlerUPP(mOffset2PosUPP);
|
|
::DisposeAEEventHandlerUPP(mUpdateUPP);
|
|
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
nsMacTSMMessagePump* nsMacTSMMessagePump::gSingleton = nsnull;
|
|
//-------------------------------------------------------------------------
|
|
nsMacTSMMessagePump* nsMacTSMMessagePump::GetSingleton()
|
|
{
|
|
if(nsnull == gSingleton)
|
|
{
|
|
gSingleton = new nsMacTSMMessagePump();
|
|
NS_ASSERTION(gSingleton!=NULL,"nsMacTSMMessagePump::GetSingleton: Unable to create TSM Message Pump.");
|
|
}
|
|
return gSingleton;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
void nsMacTSMMessagePump::Shutdown()
|
|
{
|
|
if(gSingleton) {
|
|
delete gSingleton;
|
|
gSingleton = nsnull;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// TSM AE Handler routines
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
pascal OSErr nsMacTSMMessagePump::PositionToOffsetHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
|
|
{
|
|
OSErr err;
|
|
DescType returnedType;
|
|
nsMacEventHandler* eventHandler;
|
|
Size actualSize;
|
|
Point thePoint;
|
|
long offset;
|
|
short regionClass;
|
|
|
|
//
|
|
// Extract the nsMacEventHandler for this TSMDocument. It's stored as the TSMDocument's
|
|
// refcon
|
|
//
|
|
err = AEGetParamPtr(theAppleEvent,keyAETSMDocumentRefcon,typeLongInteger,&returnedType,
|
|
&eventHandler,sizeof(eventHandler),&actualSize);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::PositionToOffsetHandler: AEGetParamPtr[TSMRefcon] failed");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
//
|
|
// Extract the Position parameter.
|
|
//
|
|
err = AEGetParamPtr(theAppleEvent,keyAECurrentPoint,typeQDPoint,&returnedType,
|
|
&thePoint,sizeof(thePoint),&actualSize);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::PositionToOffsetHandler: AGGetParamPtr[Point] failed");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
//
|
|
// pass the request to the widget system
|
|
//
|
|
offset = eventHandler->HandlePositionToOffset(thePoint,®ionClass);
|
|
|
|
//
|
|
// build up the AE reply (need offset and region class)
|
|
//
|
|
err = AEPutParamPtr(reply,keyAEOffset,typeLongInteger,&offset,sizeof(offset));
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::PositionToOffsetHandler: AEPutParamPtr failed");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
err = AEPutParamPtr(reply,keyAERegionClass,typeShortInteger,®ionClass,sizeof(regionClass));
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::PositionToOffsetHandler: AEPutParamPtr failed");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
return noErr;
|
|
}
|
|
pascal OSErr nsMacTSMMessagePump::OffsetToPositionHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
|
|
{
|
|
OSErr err;
|
|
DescType returnedType;
|
|
nsMacEventHandler* eventHandler;
|
|
Size actualSize;
|
|
Point thePoint;
|
|
long offset;
|
|
nsresult res;
|
|
|
|
//
|
|
// Extract the nsMacEvenbtHandler for this TSMDocument. It's stored as the refcon.
|
|
//
|
|
err = AEGetParamPtr(theAppleEvent,keyAETSMDocumentRefcon,typeLongInteger,&returnedType,
|
|
&eventHandler,sizeof(eventHandler),&actualSize);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::OffsetToPositionHandler: AEGetParamPtr[TSMRefcon] failed.");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
//
|
|
// Extract the Offset parameter
|
|
//
|
|
err = AEGetParamPtr(theAppleEvent,keyAEOffset,typeLongInteger,&returnedType,
|
|
&offset,sizeof(offset),&actualSize);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::PositionToOffsetHandler: AEGetParamPtr[Offset] failed.");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
//
|
|
// Pass the OffsetToPosition request to the widgets to handle
|
|
//
|
|
res = eventHandler->HandleOffsetToPosition(offset,&thePoint);
|
|
NS_ASSERTION(NS_SUCCEEDED(res),"nsMacMessagePup::PositionToOffsetHandler: OffsetToPosition handler failed.");
|
|
if (NS_FAILED(res))
|
|
return paramErr;
|
|
|
|
//
|
|
// build up the reply (point)
|
|
//
|
|
err = AEPutParamPtr(reply,keyAEPoint,typeQDPoint,&thePoint,sizeof(Point));
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::PositionToOffsetHandler: AEPutParamPtr[Point][ failed.");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
return noErr;
|
|
}
|
|
pascal OSErr nsMacTSMMessagePump::UpdateHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
|
|
{
|
|
OSErr err;
|
|
DescType returnedType;
|
|
nsMacEventHandler* eventHandler;
|
|
Size actualSize;
|
|
AEDesc text, hiliteRangeArray;
|
|
ScriptCode textScript;
|
|
long fixLength;
|
|
nsresult res;
|
|
TextRangeArray* hiliteRangePtr;
|
|
|
|
|
|
//
|
|
// refcon stores the nsMacEventHandler
|
|
//
|
|
err = AEGetParamPtr(theAppleEvent,keyAETSMDocumentRefcon,typeLongInteger,&returnedType,
|
|
&eventHandler,sizeof(eventHandler),&actualSize);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::UpdateHandler: AEGetParamPtr[TSMRefcon] failed.");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
//
|
|
// IME update text
|
|
//
|
|
err = AEGetParamDesc(theAppleEvent,keyAETheData,typeChar,&text);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::UpdateHandler: AEGetParamDesc[Text] failed.");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
//
|
|
// get the script of text for Unicode conversion
|
|
//
|
|
textScript=smUninterp;
|
|
AEDesc slr;
|
|
err = AEGetParamDesc(theAppleEvent,keyAETSMScriptTag,typeIntlWritingCode,&slr);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::UpdateHandler: AEGetParamDesc[keyAETSMScriptTag] failed.");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
#if TARGET_CARBON
|
|
ScriptLanguageRecord scriptLangRec;
|
|
err = AEGetDescData(&slr, (void *) &scriptLangRec, sizeof(ScriptLanguageRecord));
|
|
if (err!=noErr)
|
|
return err;
|
|
textScript = scriptLangRec.fScript;
|
|
#else
|
|
textScript = ((ScriptLanguageRecord *)(*(slr.dataHandle)))->fScript;
|
|
#endif
|
|
NS_ASSERTION( (textScript < smUninterp), "Illegal script code");
|
|
|
|
NS_ASSERTION(textScript == (ScriptCode)::GetScriptManagerVariable(smKeyScript) , "wrong script code");
|
|
//
|
|
// length of converted text
|
|
//
|
|
err = AEGetParamPtr(theAppleEvent,keyAEFixLength,typeLongInteger,&returnedType,
|
|
&fixLength,sizeof(fixLength),&actualSize);
|
|
NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::UpdateHandler: AEGetParamPtr[fixlen] failed.");
|
|
if (err!=noErr)
|
|
return err;
|
|
|
|
//
|
|
// extract the hilite ranges (optional param)
|
|
//
|
|
err = AEGetParamDesc(theAppleEvent,keyAEHiliteRange,typeTextRangeArray,&hiliteRangeArray);
|
|
NS_ASSERTION(err==noErr||err==errAEDescNotFound,"nsMacTSMMessagePump::UpdateHandler: AEGetParamPtr[fixlen] failed.");
|
|
if (err==errAEDescNotFound) {
|
|
hiliteRangePtr=NULL;
|
|
} else if (err==noErr) {
|
|
#if TARGET_CARBON
|
|
Size hiliteRangeSize = ::AEGetDescDataSize(&hiliteRangeArray);
|
|
hiliteRangePtr = (TextRangeArray *) NewPtr(hiliteRangeSize);
|
|
if(!hiliteRangePtr)
|
|
return MemError();
|
|
err = AEGetDescData(&hiliteRangeArray, (void *) hiliteRangePtr, hiliteRangeSize);
|
|
if (err!=noErr) {
|
|
DisposePtr((Ptr) hiliteRangePtr);
|
|
return err;
|
|
}
|
|
#else
|
|
::HLock(hiliteRangeArray.dataHandle);
|
|
hiliteRangePtr=(TextRangeArray*)*(hiliteRangeArray.dataHandle);
|
|
#endif
|
|
} else {
|
|
return err;
|
|
}
|
|
|
|
#if TARGET_CARBON
|
|
nsCAutoString mbcsText;
|
|
Size text_size = ::AEGetDescDataSize(&text);
|
|
mbcsText.SetCapacity(text_size+1);
|
|
char* mbcsTextPtr = (char*)mbcsText.get();
|
|
err = AEGetDescData(&text, (void *) mbcsTextPtr, text_size);
|
|
if (err!=noErr) {
|
|
DisposePtr((Ptr) hiliteRangePtr);
|
|
return err;
|
|
}
|
|
mbcsTextPtr[text_size]=0;
|
|
#else
|
|
nsCAutoString mbcsText;
|
|
Size text_size = ::GetHandleSize(text.dataHandle);
|
|
mbcsText.SetCapacity(text_size+1);
|
|
char* mbcsTextPtr = (char*)mbcsText.get();
|
|
strncpy(mbcsTextPtr,*(text.dataHandle),text_size);
|
|
mbcsTextPtr[text_size]=0;
|
|
#endif
|
|
|
|
//
|
|
// must pass HandleUpdateInputArea a null-terminated multibyte string, the text size must include the terminator
|
|
//
|
|
res = eventHandler->HandleUpdateInputArea(mbcsTextPtr,text_size,textScript,fixLength,hiliteRangePtr);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(res),"nsMacMessagePump::UpdateHandler: HandleUpdated failed.");
|
|
if (NS_FAILED(res))
|
|
err = paramErr;
|
|
|
|
//
|
|
// clean up
|
|
//
|
|
#if TARGET_CARBON
|
|
if(hiliteRangePtr)
|
|
DisposePtr((Ptr) hiliteRangePtr);
|
|
#else
|
|
if(hiliteRangePtr)
|
|
::HUnlock(hiliteRangeArray.dataHandle);
|
|
#endif
|
|
|
|
(void)AEDisposeDesc(&text);
|
|
(void)AEDisposeDesc(&hiliteRangeArray);
|
|
|
|
return noErr;
|
|
}
|