Back to index

lightning-sunbird  0.9+nobinonly
nsMacTSMMessagePump.cpp
Go to the documentation of this file.
00001 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nscore.h"
00039 #include "nsMacEventHandler.h"
00040 #include "nsMacTSMMessagePump.h"
00041 #include "nsString.h"
00042 #include <Script.h>
00043 #include <TextServices.h>
00044 #include <AEDataModel.h>
00045 
00046 #include "nsCarbonHelpers.h"
00047 
00048 
00049 //-------------------------------------------------------------------------
00050 //
00051 // TSM AE Handler routines UPPs 
00052 //
00053 //-------------------------------------------------------------------------
00054 
00055 AEEventHandlerUPP nsMacTSMMessagePump::mPos2OffsetUPP = NULL;
00056 AEEventHandlerUPP nsMacTSMMessagePump::mOffset2PosUPP = NULL;
00057 AEEventHandlerUPP nsMacTSMMessagePump::mUpdateUPP = NULL;
00058 AEEventHandlerUPP nsMacTSMMessagePump::mKeyboardUPP = NULL;
00059 AEEventHandlerUPP nsMacTSMMessagePump::mGetSelectedTextUPP = NULL;
00060 
00061 //-------------------------------------------------------------------------
00062 //
00063 // Constructor/Destructors
00064 //
00065 //-------------------------------------------------------------------------
00066 nsMacTSMMessagePump::nsMacTSMMessagePump()
00067 {
00068        OSErr  err;
00069 
00070        mPos2OffsetUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::PositionToOffsetHandler);
00071        NS_ASSERTION(mPos2OffsetUPP!=NULL, "nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[Pos2Pffset] failed");
00072 
00073        mOffset2PosUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::OffsetToPositionHandler);
00074        NS_ASSERTION(mPos2OffsetUPP!=NULL, "nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[Pos2Pffset] failed");
00075 
00076   mUpdateUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::UnicodeUpdateHandler);
00077   NS_ASSERTION(mPos2OffsetUPP!=NULL, "nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[Pos2Pffset] failed");
00078 
00079   err = AEInstallEventHandler(kTextServiceClass, kPos2Offset, mPos2OffsetUPP, (long)this, false);
00080   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[Pos2Offset] failed");
00081 
00082   err = AEInstallEventHandler(kTextServiceClass, kOffset2Pos, mOffset2PosUPP, (long)this, false);
00083   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[Offset2Pos] failed");
00084 
00085   err = AEInstallEventHandler(kTextServiceClass, kUpdateActiveInputArea, mUpdateUPP, (long)this, false);
00086   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[Update] failed");
00087 
00088   mKeyboardUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::UnicodeNotFromInputMethodHandler);
00089   NS_ASSERTION(mKeyboardUPP!=NULL, "nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[FromInputMethod] failed");
00090 
00091   err = AEInstallEventHandler(kTextServiceClass, kUnicodeNotFromInputMethod, mKeyboardUPP, (long)this, false);
00092   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[FromInputMethod] failed");
00093 
00094   mGetSelectedTextUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::UnicodeGetSelectedTextHandler);
00095   NS_ASSERTION(mGetSelectedTextUPP!=NULL, "nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[GetSelectedText] failed");
00096 
00097   err = AEInstallEventHandler(kTextServiceClass, kGetSelectedText, mGetSelectedTextUPP, (long)this, false);
00098   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[GetSelectedText] failed");
00099 
00100 }
00101 
00102 nsMacTSMMessagePump::~nsMacTSMMessagePump()
00103 {
00104        OSErr  err;
00105        
00106        err = AERemoveEventHandler(kTextServiceClass, kPos2Offset, mPos2OffsetUPP, false);
00107        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[Pos2Offset] failed");
00108 
00109        err = AERemoveEventHandler(kTextServiceClass, kOffset2Pos, mOffset2PosUPP, false);
00110        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[Offset2Pos] failed");
00111 
00112        err = AERemoveEventHandler(kTextServiceClass, kUpdateActiveInputArea, mUpdateUPP, false);
00113        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[Update] failed");
00114 
00115        ::DisposeAEEventHandlerUPP(mPos2OffsetUPP);
00116        ::DisposeAEEventHandlerUPP(mOffset2PosUPP);
00117        ::DisposeAEEventHandlerUPP(mUpdateUPP);
00118 
00119   err = AERemoveEventHandler(kTextServiceClass, kUnicodeNotFromInputMethod, mKeyboardUPP, false);
00120   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[FromInputMethod] failed");
00121   ::DisposeAEEventHandlerUPP(mKeyboardUPP);
00122 
00123   err = AERemoveEventHandler(kTextServiceClass, kGetSelectedText, mGetSelectedTextUPP, false);
00124   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[GetSelectedText] failed");
00125   ::DisposeAEEventHandlerUPP(mGetSelectedTextUPP);
00126 
00127 }
00128 
00129 //-------------------------------------------------------------------------
00130 nsMacTSMMessagePump* nsMacTSMMessagePump::gSingleton = nsnull;
00131 //-------------------------------------------------------------------------
00132 nsMacTSMMessagePump* nsMacTSMMessagePump::GetSingleton()
00133 {
00134        if (nsnull == gSingleton)
00135        {
00136               gSingleton = new nsMacTSMMessagePump();
00137               NS_ASSERTION(gSingleton!=NULL, "nsMacTSMMessagePump::GetSingleton: Unable to create TSM Message Pump.");
00138        }
00139        return gSingleton;
00140 }
00141 //-------------------------------------------------------------------------
00142 void nsMacTSMMessagePump::Shutdown()
00143 {
00144        if (gSingleton) {
00145               delete gSingleton;
00146               gSingleton = nsnull;
00147        }
00148 }
00149 
00150 //-------------------------------------------------------------------------
00151 //
00152 // TSM AE Handler routines
00153 //
00154 //-------------------------------------------------------------------------
00155 
00156 pascal OSErr nsMacTSMMessagePump::PositionToOffsetHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
00157 {
00158        OSErr                       err;
00159        DescType                    returnedType;
00160        nsMacEventHandler*   eventHandler; 
00161        Size                        actualSize;
00162        Point                       thePoint;
00163        long                        offset;
00164        short                       regionClass;
00165 
00166        //
00167        // Extract the nsMacEventHandler for this TSMDocument.  It's stored as the TSMDocument's
00168        //     refcon
00169        //
00170        err = AEGetParamPtr(theAppleEvent, keyAETSMDocumentRefcon, typeLongInteger, &returnedType,
00171                                           &eventHandler, sizeof(eventHandler), &actualSize);
00172        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::PositionToOffsetHandler: AEGetParamPtr[TSMRefcon] failed");
00173        if (err!=noErr) 
00174               return err;
00175        
00176        //
00177        // Extract the Position parameter.
00178        //
00179        err = AEGetParamPtr(theAppleEvent, keyAECurrentPoint, typeQDPoint, &returnedType,
00180                                           &thePoint, sizeof(thePoint), &actualSize);
00181        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::PositionToOffsetHandler: AGGetParamPtr[Point] failed");
00182        if (err!=noErr) 
00183               return err;
00184 
00185        //
00186        // pass the request to the widget system
00187        //
00188        offset = eventHandler->HandlePositionToOffset(thePoint, &regionClass);
00189        
00190        //
00191        // build up the AE reply (need offset and region class)
00192        //
00193        err = AEPutParamPtr(reply, keyAEOffset, typeLongInteger, &offset, sizeof(offset));
00194        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::PositionToOffsetHandler: AEPutParamPtr failed");
00195        if (err!=noErr) 
00196               return err;
00197        
00198        err = AEPutParamPtr(reply, keyAERegionClass, typeShortInteger, &regionClass, sizeof(regionClass));
00199        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::PositionToOffsetHandler: AEPutParamPtr failed");
00200        if (err!=noErr) 
00201               return err;
00202 
00203        return noErr;
00204 }
00205 pascal OSErr nsMacTSMMessagePump::OffsetToPositionHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
00206 {
00207        OSErr                       err;
00208        DescType                    returnedType;
00209        nsMacEventHandler*   eventHandler; 
00210        Size                        actualSize;
00211        Point                       thePoint;
00212        long                        offset;
00213        nsresult                    res;
00214 
00215        //
00216        // Extract the nsMacEvenbtHandler for this TSMDocument.  It's stored as the refcon.
00217        //
00218        err = AEGetParamPtr(theAppleEvent, keyAETSMDocumentRefcon, typeLongInteger, &returnedType,
00219                                           &eventHandler, sizeof(eventHandler), &actualSize);
00220        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::OffsetToPositionHandler: AEGetParamPtr[TSMRefcon] failed.");
00221        if (err!=noErr) 
00222               return err;
00223        
00224        //
00225        // Extract the Offset parameter
00226        //
00227        err = AEGetParamPtr(theAppleEvent, keyAEOffset, typeLongInteger, &returnedType,
00228                                           &offset, sizeof(offset), &actualSize);
00229        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::PositionToOffsetHandler: AEGetParamPtr[Offset] failed.");
00230        if (err!=noErr) 
00231               return err;
00232        
00233        //
00234        // Pass the OffsetToPosition request to the widgets to handle
00235        //
00236        res = eventHandler->HandleOffsetToPosition(offset, &thePoint);
00237        NS_ASSERTION(NS_SUCCEEDED(res), "nsMacMessagePup::PositionToOffsetHandler: OffsetToPosition handler failed.");
00238        if (NS_FAILED(res)) 
00239               return paramErr;
00240        
00241        //
00242        // build up the reply (point)
00243        //
00244        err = AEPutParamPtr(reply, keyAEPoint, typeQDPoint, &thePoint, sizeof(Point));
00245        NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::PositionToOffsetHandler: AEPutParamPtr[Point] failed.");
00246        if (err!=noErr) 
00247               return err;
00248        
00249        return noErr;
00250 }
00251 
00252 static OSErr GetAppleEventTSMData(const AppleEvent *inAE, nsMacEventHandler **outEventHandler, AEDesc *outText)
00253 {
00254   *outEventHandler = nsnull;
00255   //*outText = nsnull;
00256 
00257   //
00258   // refcon stores the nsMacEventHandler
00259   //
00260   DescType returnedType;
00261   Size actualSize;
00262   OSErr err = ::AEGetParamPtr(inAE, keyAETSMDocumentRefcon, typeLongInteger, &returnedType,
00263                               outEventHandler, sizeof(nsMacEventHandler *), &actualSize);
00264   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::GetAppleEventTSMData: AEGetParamPtr[TSMRefcon] failed.");
00265   if (err)
00266     return err;
00267  
00268   //
00269   // get text
00270   //
00271   err = ::AEGetParamDesc(inAE, keyAETheData, typeUnicodeText, outText);
00272   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::GetAppleEventTSMData: AEGetParamDesc[Text] failed.");
00273   return err;
00274 }
00275 
00276 static OSErr AETextToString(AEDesc &aAEDesc, nsString& aOutString, Size& text_size)
00277 {
00278   OSErr err = noErr;
00279   PRUnichar* unicodeTextPtr;
00280   text_size = 0;
00281   aOutString.Truncate(0);
00282 
00283 
00284   text_size = ::AEGetDescDataSize(&aAEDesc) / 2;
00285   if (!EnsureStringLength(aOutString, text_size + 1))
00286     return memFullErr;
00287   unicodeTextPtr = aOutString.BeginWriting();
00288   err = AEGetDescData(&aAEDesc, (void *) unicodeTextPtr, text_size * 2);
00289   if (err!=noErr) 
00290     return err;
00291 
00292   unicodeTextPtr[text_size ] = PRUnichar('\0'); // null terminate it.
00293   return noErr;
00294 }
00295 
00296 
00297 
00298 pascal OSErr nsMacTSMMessagePump::UnicodeUpdateHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
00299 {
00300   OSErr                 err = noErr;
00301   DescType              returnedType;
00302   nsMacEventHandler*    eventHandler;
00303   Size                  actualSize;
00304   AEDesc                text, hiliteRangeArray;
00305   long                  fixLength;
00306   nsresult              res;
00307   TextRangeArray*       hiliteRangePtr;
00308 
00309   err = GetAppleEventTSMData(theAppleEvent, &eventHandler, &text);
00310   if (err) 
00311     return err;
00312 
00313   //
00314   // length of converted text
00315   //
00316   err = ::AEGetParamPtr(theAppleEvent, keyAEFixLength, typeLongInteger, &returnedType,
00317                         &fixLength, sizeof(fixLength), &actualSize);
00318   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::UnicodeUpdateHandler: AEGetParamPtr[fixlen] failed.");
00319   if (err) 
00320     return err;
00321 
00322   //
00323   // extract the hilite ranges (optional param)
00324   //
00325   err = ::AEGetParamDesc(theAppleEvent, keyAEHiliteRange, typeTextRangeArray, &hiliteRangeArray);
00326   NS_ASSERTION(err==noErr||err==errAEDescNotFound, "nsMacTSMMessagePump::UnicodeUpdateHandler: AEGetParamDesc[hiliteRangeArray] failed.");
00327   if (errAEDescNotFound == err)
00328   {
00329     hiliteRangePtr = NULL;
00330   } 
00331   else if (noErr == err)
00332   { 
00333 
00334     Size hiliteRangeSize = ::AEGetDescDataSize(&hiliteRangeArray);
00335     hiliteRangePtr = (TextRangeArray *) NewPtr(hiliteRangeSize);
00336     if (!hiliteRangePtr)
00337     {
00338       err = MemError();
00339       goto err2;
00340     }
00341     err = ::AEGetDescData(&hiliteRangeArray, (void *)hiliteRangePtr, hiliteRangeSize);
00342     if (noErr != err)
00343     {
00344       goto err1; 
00345     }
00346   }
00347   else
00348   {
00349     goto err3;
00350   }
00351 
00352   // grab the text now
00353   {
00354     nsAutoString unicodeText;
00355     Size text_size;
00356     err = AETextToString(text, unicodeText, text_size);
00357     if (noErr == err)
00358     {
00359       res = eventHandler->UnicodeHandleUpdateInputArea(unicodeText.get(), text_size, fixLength / 2, hiliteRangePtr);
00360       NS_ASSERTION(NS_SUCCEEDED(res), "nsMacMessagePump::UnicodeUpdateHandler: HandleUpdated failed.");
00361       if (NS_FAILED(res))
00362         err = paramErr;
00363         // fall to cleanup below
00364     }
00365   }
00366 
00367   //
00368   // clean up
00369   //
00370 err1:
00371     if (hiliteRangePtr)
00372       ::DisposePtr((Ptr)hiliteRangePtr);
00373 
00374 err2:
00375   (void)::AEDisposeDesc(&hiliteRangeArray);
00376 err3:
00377   (void)::AEDisposeDesc(&text);
00378 
00379   return err;
00380 }
00381 
00382 pascal OSErr nsMacTSMMessagePump::UnicodeNotFromInputMethodHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
00383 {
00384   OSErr               err;
00385   nsMacEventHandler*  eventHandler;
00386   AEDesc              text;
00387   DescType            returnedType;
00388   Size                actualSize;
00389   EventRecord         event;
00390 
00391   err = GetAppleEventTSMData(theAppleEvent, &eventHandler, &text);
00392   if (err != noErr) 
00393     return err;
00394   
00395   err = ::AEGetParamPtr(theAppleEvent, keyAETSMEventRecord, typeLowLevelEventRecord, &returnedType,
00396                         &event, sizeof(event), &actualSize);
00397   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::UnicodeNotFromInputMethodHandler: AEGetParamPtr[event] failed.");
00398   if (noErr != err)
00399   {
00400     (void)::AEDisposeDesc(&text);
00401     return err;
00402   }
00403 
00404   nsAutoString unicodeText;
00405   Size text_size;
00406   err = AETextToString(text, unicodeText, text_size);
00407   if (noErr == err)
00408   {
00409     nsresult res;
00410     res = eventHandler->HandleUKeyEvent(unicodeText.get(), text_size, event);
00411     NS_ASSERTION(NS_SUCCEEDED(res), "nsMacMessagePump::UnicodeNotFromInputMethodHandler: HandleUpdated failed.");
00412     if (NS_FAILED(res)) {
00413       err = paramErr;
00414       // fall to cleanup below
00415     }
00416   }
00417 
00418   (void)::AEDisposeDesc(&text);
00419   return err;
00420 }
00421 
00422 
00423 pascal OSErr nsMacTSMMessagePump::UnicodeGetSelectedTextHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
00424 {
00425   OSErr err;  
00426   DescType returnedType;
00427   nsMacEventHandler*  eventHandler;  
00428   Size actualSize;
00429   long maxReturnSize = 0;
00430   long returnSize;
00431   nsresult res;
00432 
00433   //
00434   // Extract the nsMacEvenbtHandler for this TSMDocument.  It's stored as the refcon.
00435   //
00436   err = AEGetParamPtr(theAppleEvent, keyAETSMDocumentRefcon, typeLongInteger, &returnedType,
00437             &eventHandler, sizeof(eventHandler), &actualSize);
00438   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::UnicodeGetSelectedTextHandler: AEGetParamPtr[TSMRefcon] failed.");
00439   if (err!=noErr) 
00440     return err;
00441   
00442   //
00443   // Extract the Offset parameter
00444   //
00445   err = AEGetParamPtr(theAppleEvent, keyAEBufferSize, typeLongInteger, &returnedType,
00446             &maxReturnSize, sizeof(maxReturnSize), &actualSize);
00447   // optional parameter, ignore if we cannot get it.
00448   
00449   //
00450   // Pass the OffsetToPosition request to the widgets to handle
00451   //
00452   nsAutoString outString;
00453   res = eventHandler->HandleUnicodeGetSelectedText(outString);
00454   NS_ASSERTION(NS_SUCCEEDED(res), "nsMacMessagePup::UnicodeGetSelectedTextHandler: HandleGetSelectedText handler failed.");
00455   if (NS_FAILED(res)) 
00456     return paramErr;
00457   
00458   //
00459   // build up the reply (point)
00460   //
00461   returnSize = outString.Length()*sizeof(PRUnichar);
00462   if ((maxReturnSize >0) && (returnSize > maxReturnSize))
00463     returnSize = maxReturnSize & ~1L; // Round down
00464   
00465   err = AEPutParamPtr(reply, keyAETheData, typeUnicodeText, outString.get(), returnSize);
00466   NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::UnicodeGetSelectedTextHandler: AEPutParamPtr[Point] failed.");
00467   if (err!=noErr) 
00468     return err;
00469   
00470   return noErr;
00471 }