Back to index

lightning-sunbird  0.9+nobinonly
nsAEUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 Communicator client 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) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Simon Fraser <sfraser@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 
00040 #include <string.h>
00041 
00042 
00043 #include "nsAETokens.h"
00044 #include "nsAEUtils.h"
00045 
00046 static OSErr AECoerceDescData(const AEDesc *theAEDesc, DescType typeCode, void *dataPtr, Size maximumSize);
00047 
00048 /*----------------------------------------------------------------------------
00049        CreateAliasAEDesc 
00050        
00051        Create an AE descriptor for an alias
00052 ----------------------------------------------------------------------------*/
00053 
00054 OSErr CreateAliasAEDesc(AliasHandle theAlias, AEDesc *ioDesc)
00055 {
00056        char          state = HGetState((Handle)theAlias);
00057        OSErr  err;
00058 
00059        HLock((Handle)theAlias);
00060        err = AECreateDesc(typeAlias, *theAlias, GetHandleSize((Handle)theAlias), ioDesc);
00061        HSetState((Handle)theAlias, state);
00062        return err;
00063 }
00064 
00065 
00066 /*----------------------------------------------------------------------------
00067        GetTextFromAEDesc 
00068        
00069        Get a text handle from an AEDesc
00070 ----------------------------------------------------------------------------*/
00071 OSErr GetTextFromAEDesc(const AEDesc *inDesc, Handle *outTextHandle)
00072 {
00073        Handle textHandle = nil;
00074        Size          textLength;
00075        OSErr  err;
00076 
00077        textLength = AEGetDescDataSize(inDesc);
00078 
00079        err = MyNewHandle(textLength, &textHandle);
00080        if (err != noErr) return err;
00081        
00082        MyHLock(textHandle);
00083        err = AECoerceDescData(inDesc, typeChar, *textHandle, textLength);
00084        MyHUnlock(textHandle);
00085        
00086        if (err != noErr)
00087               goto exit;
00088        
00089        *outTextHandle = textHandle;
00090        return noErr;
00091        
00092 exit:
00093        MyDisposeHandle(textHandle);
00094        return err;
00095 }
00096 
00097 
00098 #if !TARGET_CARBON
00099 
00100 /*----------------------------------------------------------------------------
00101        AEGetDescData 
00102        
00103        Get a copy of the data from the AE desc. The will attempt to coerce to the
00104        requested type, returning an error on failure.
00105 ----------------------------------------------------------------------------*/
00106 
00107 OSErr AEGetDescData(const AEDesc *theAEDesc, void *dataPtr, Size maximumSize)
00108 {
00109   OSErr err = noErr;
00110   
00111        if (theAEDesc->dataHandle)
00112        {
00113               Size dataLength = GetHandleSize(theAEDesc->dataHandle);
00114               BlockMoveData(*theAEDesc->dataHandle, dataPtr, Min(dataLength, maximumSize));
00115        }
00116        else
00117               err = paramErr;
00118               
00119        return err;
00120 }
00121 
00122 /*----------------------------------------------------------------------------
00123        AEGetDescDataSize 
00124        
00125        Get the size of the datahandle.
00126 ----------------------------------------------------------------------------*/
00127 Size AEGetDescDataSize(const AEDesc *theAEDesc)
00128 {
00129        Size          dataSize = 0;
00130        
00131        if (theAEDesc->dataHandle)
00132               dataSize = GetHandleSize(theAEDesc->dataHandle);
00133        
00134        return dataSize;
00135 }
00136 
00137 /*----------------------------------------------------------------------------
00138        AEReplaceDescData 
00139        
00140        Replace the data in the descriptor
00141 ----------------------------------------------------------------------------*/
00142 OSErr AEReplaceDescData(DescType typeCode, const void *dataPtr, Size dataSize, AEDesc* theAEDesc)
00143 {
00144        AEDisposeDesc(theAEDesc);
00145        return AECreateDesc(typeCode, dataPtr, dataSize, theAEDesc);
00146 }
00147 
00148 #endif //TARGET_CARBON
00149 
00150 static OSErr AECoerceDescData(const AEDesc *theAEDesc, DescType typeCode, void *dataPtr, Size maximumSize)
00151 {
00152        OSErr err;
00153        
00154        if (theAEDesc->descriptorType != typeCode)
00155        {
00156               AEDesc coercedDesc = { typeNull, nil };
00157               err = AECoerceDesc(theAEDesc, typeCode, &coercedDesc);
00158               if (err != noErr) return err;
00159               
00160               err = AEGetDescData(&coercedDesc, dataPtr, maximumSize);
00161               AEDisposeDesc(&coercedDesc);
00162               return err;
00163        }
00164        else
00165        {
00166            return AEGetDescData(theAEDesc, dataPtr, maximumSize);
00167        }
00168 }
00169 
00170 #pragma mark -
00171 
00172 
00173 /*----------------------------------------------------------------------------
00174        CreateThreadAEInfo 
00175        
00176        Allocate a block for the thread info, and fill it.
00177 ----------------------------------------------------------------------------*/
00178 OSErr CreateThreadAEInfo(const AppleEvent *event, AppleEvent *reply, TThreadAEInfoPtr *outThreadAEInfo)
00179 {
00180        TThreadAEInfo *threadAEInfo = nil;
00181        OSErr         err;
00182        
00183        err = MyNewBlockClear(sizeof(TThreadAEInfo), (void**)&threadAEInfo);
00184        if (err != noErr) return err;
00185        
00186        threadAEInfo->mAppleEvent = *event;
00187        threadAEInfo->mReply = *reply;
00188        threadAEInfo->mGotEventData = event && reply;
00189        threadAEInfo->mSuspendCount = nil;
00190        
00191        *outThreadAEInfo = threadAEInfo;
00192        return noErr;
00193 
00194 exit:
00195        MyDisposeBlock(threadAEInfo);
00196        return err;
00197 }
00198 
00199 
00200 /*----------------------------------------------------------------------------
00201        DisposeThreadAEInfo 
00202        
00203        Dispose of the thread AE info
00204 ----------------------------------------------------------------------------*/
00205 void DisposeThreadAEInfo(TThreadAEInfo *threadAEInfo)
00206 {
00207        AE_ASSERT(threadAEInfo && threadAEInfo->mSuspendCount == 0, "Bad suspend count");
00208        MyDisposeBlock(threadAEInfo);
00209 }
00210 
00211 
00212 /*----------------------------------------------------------------------------
00213        SuspendThreadAE 
00214        
00215        If this if the first suspend, suspend the event. Increment the suspend count.
00216 ----------------------------------------------------------------------------*/
00217 OSErr SuspendThreadAE(TThreadAEInfo *threadAEInfo)
00218 {
00219        if (threadAEInfo == nil) return noErr;
00220        if (!threadAEInfo->mGotEventData) return noErr;
00221        
00222        if (threadAEInfo->mSuspendCount == 0)
00223        {
00224               OSErr  err = AESuspendTheCurrentEvent(&threadAEInfo->mAppleEvent);
00225               if (err != noErr) return err;
00226        }
00227        
00228        ++ threadAEInfo->mSuspendCount;
00229        return noErr;
00230 }
00231 
00232 
00233 /*----------------------------------------------------------------------------
00234        ResumeThreadAE 
00235        
00236        Decrement the suspend count. If this is the last resume, resume the event.
00237 ----------------------------------------------------------------------------*/
00238 
00239 static OSErr AddErrorCodeToReply(TThreadAEInfo *threadAEInfo, OSErr threadError)
00240 {
00241        long          errorValue = threadError;
00242        
00243        if (threadError == noErr) return noErr;
00244        
00245        return AEPutParamPtr(&threadAEInfo->mReply, keyErrorNumber, typeLongInteger,  (Ptr)&errorValue, sizeof(long));
00246 }
00247 
00248 
00249 /*----------------------------------------------------------------------------
00250        ResumeThreadAE 
00251        
00252        Decrement the suspend count. If this is the last resume, resume the event.
00253 ----------------------------------------------------------------------------*/
00254 OSErr ResumeThreadAE(TThreadAEInfo *threadAEInfo, OSErr threadError)
00255 {
00256        if (threadAEInfo == nil) return noErr;
00257        if (!threadAEInfo->mGotEventData) return noErr;
00258 
00259        -- threadAEInfo->mSuspendCount;
00260        
00261        AddErrorCodeToReply(threadAEInfo, threadError);
00262        
00263        if (threadAEInfo->mSuspendCount == 0)
00264               return AEResumeTheCurrentEvent(&threadAEInfo->mAppleEvent, &threadAEInfo->mReply, (AEEventHandlerUPP)kAENoDispatch, 0);
00265 
00266        return noErr;
00267 }
00268 
00269 
00270 #pragma mark -
00271 
00272 /*----------------------------------------------------------------------------
00273        Copy ctor
00274        
00275        this can throw 
00276        
00277 ----------------------------------------------------------------------------*/
00278 
00279 StAEDesc::StAEDesc(const StAEDesc& rhs)
00280 {
00281        ThrowIfOSErr(AEDuplicateDesc(&rhs, this));
00282 }
00283 
00284 /*----------------------------------------------------------------------------
00285        operator =
00286        
00287        this can throw 
00288        
00289 ----------------------------------------------------------------------------*/
00290 
00291 StAEDesc& StAEDesc::operator= (const StAEDesc& rhs)
00292 {
00293        ThrowIfOSErr(AEDuplicateDesc(&rhs, this));
00294        return *this;
00295 }
00296 
00297 
00298 /*----------------------------------------------------------------------------
00299        Data getters
00300        
00301        These should try to coerce when necessary also.
00302 ----------------------------------------------------------------------------*/
00303 
00304 Boolean StAEDesc::GetBoolean()
00305 {
00306     Boolean result = false;
00307     OSErr err = ::AECoerceDescData(this, typeBoolean, &result, sizeof(result));
00308     if (err != noErr)
00309         ThrowOSErr(errAECoercionFail);
00310     return result;
00311 }
00312 
00313 SInt16 StAEDesc::GetShort()
00314 {
00315     SInt16 result = 0;
00316     OSErr err = ::AECoerceDescData(this, typeShortInteger, &result, sizeof(result));
00317     if (err != noErr)
00318         ThrowOSErr(errAECoercionFail);
00319     return result;
00320 }
00321 
00322 SInt32 StAEDesc::GetLong()
00323 {
00324     SInt32 result = 0;
00325     OSErr err = ::AECoerceDescData(this, typeLongInteger, &result, sizeof(result));
00326     if (err != noErr)
00327         ThrowOSErr(errAECoercionFail);
00328     return result;
00329 }
00330 
00331 DescType StAEDesc::GetEnumType()
00332 {
00333     DescType result = typeNull;
00334     OSErr err = ::AECoerceDescData(this, typeEnumeration, &result, sizeof(result));
00335     if (err != noErr)
00336         ThrowOSErr(errAECoercionFail);
00337     return result;
00338 }
00339 
00340 void StAEDesc::GetRect(Rect& outData)
00341 {
00342     OSErr err = ::AECoerceDescData(this, typeQDRectangle, &outData, sizeof(Rect));
00343     if (err != noErr)
00344         ThrowOSErr(errAECoercionFail);
00345 }
00346 
00347 
00348 void StAEDesc::GetRGBColor(RGBColor& outData)
00349 {
00350     OSErr err = ::AECoerceDescData(this, typeRGBColor, &outData, sizeof(RGBColor));
00351     if (err != noErr)
00352         ThrowOSErr(errAECoercionFail);
00353 }
00354 
00355 void StAEDesc::GetLongDateTime(LongDateTime& outDateTime)
00356 {
00357     OSErr err = ::AECoerceDescData(this, typeLongDateTime, &outDateTime, sizeof(LongDateTime));
00358     if (err != noErr)
00359         ThrowOSErr(errAECoercionFail);
00360 }
00361 
00362 void StAEDesc::GetFileSpec(FSSpec &outFileSpec)
00363 {
00364     OSErr err = ::AECoerceDescData(this, typeFSS, &outFileSpec, sizeof(FSSpec));
00365     if (err != noErr)
00366         ThrowOSErr(errAECoercionFail);
00367 }
00368 
00369 void StAEDesc::GetCString(char *outString, short maxLen)
00370 {
00371        if (descriptorType == typeChar)
00372        {
00373               long dataSize = GetDataSize();
00374               dataSize = Min(dataSize, maxLen-1);
00375               if (AEGetDescData(this, outString, dataSize) == noErr)
00376               outString[dataSize] = '\0';
00377        }
00378        else
00379        {
00380               StAEDesc tempDesc;
00381               if (::AECoerceDesc(this, typeChar, &tempDesc) == noErr)
00382               {
00383                      long dataSize = tempDesc.GetDataSize();
00384               dataSize = Min(dataSize, maxLen-1);
00385               if (AEGetDescData(&tempDesc, outString, dataSize) == noErr)
00386                      outString[dataSize] = '\0';
00387               }
00388               else
00389                      ThrowOSErr(errAECoercionFail);
00390        }
00391 }
00392 
00393 void StAEDesc::GetPString(Str255 outString)
00394 {
00395        if (descriptorType == typeChar)
00396        {
00397               long stringLen = GetDataSize();
00398               if (stringLen > 255)
00399                      stringLen = 255;
00400               AEGetDescData(this, outString+1, stringLen);
00401               outString[0] = stringLen;
00402        }
00403        else
00404        {
00405               StAEDesc      tempDesc;
00406               if (::AECoerceDesc(this, typeChar, &tempDesc) == noErr)
00407               {
00408                      long stringLen = tempDesc.GetDataSize();
00409                      if (stringLen > 255)
00410                             stringLen = 255;
00411                      AEGetDescData(&tempDesc, outString+1, stringLen);
00412                      outString[0] = stringLen;
00413               }
00414               else
00415                      ThrowOSErr(errAECoercionFail);
00416        }
00417 }
00418 
00419 Handle StAEDesc::GetTextHandle()
00420 {
00421     Handle data = nil;
00422     
00423        if (descriptorType == typeChar)
00424        {
00425            Size dataSize = GetDataSize();
00426            data = ::NewHandle(dataSize);
00427            if (data == NULL)
00428                ThrowOSErr(memFullErr);
00429         ::HLock(data);
00430         ::AEGetDescData(this, *data, dataSize);
00431         ::HUnlock(data);
00432        }
00433        else
00434        {
00435        StAEDesc tempDesc;
00436               if (::AECoerceDesc(this, typeChar, &tempDesc) == noErr)
00437                   data = tempDesc.GetTextHandle();
00438               else
00439                   ThrowOSErr(errAECoercionFail);
00440        }
00441        
00442        return data;
00443 }
00444 
00445 
00446 #pragma mark -
00447 
00448 /*----------------------------------------------------------------------------
00449        GetFirstNonListToken
00450        
00451        Note: make sure the result descriptor is {typeNull, nil} when it is passed in to this
00452        
00453 ----------------------------------------------------------------------------*/
00454 OSErr AEListUtils::GetFirstNonListToken(const AEDesc *token, AEDesc *result)
00455 {
00456        OSErr         err = noErr;
00457        AEDesc               tempToken = { typeNull, nil };
00458        AEKeyword     keyword;
00459        long                 numItems;
00460        long                 itemNum;
00461        
00462        if (result->descriptorType == typeNull)
00463        {
00464               if (TokenContainsTokenList(token) == false)
00465               {
00466                      err = AEDuplicateDesc(token, result);
00467               }
00468               else
00469               {
00470                      err = AECountItems(token, &numItems);
00471                      
00472                      for (itemNum = 1; itemNum <= numItems; itemNum++)
00473                      {
00474                             err = AEGetNthDesc((AEDescList *)token, itemNum, typeWildCard, &keyword, &tempToken);
00475                             if (err != noErr)
00476                                    goto CleanUp;
00477                                    
00478                             err = GetFirstNonListToken(&tempToken, result);                       
00479                             if ((err != noErr) || (result->descriptorType != typeNull))
00480                                    break;
00481                                    
00482                             AEDisposeDesc(&tempToken);
00483                      }
00484               }
00485        }
00486        
00487 CleanUp:
00488        if (err != noErr)
00489               AEDisposeDesc(result);
00490               
00491        AEDisposeDesc(&tempToken);
00492        return err;
00493 }
00494 
00495 /*----------------------------------------------------------------------------
00496        FlattenAEList
00497        
00498 ----------------------------------------------------------------------------*/
00499 OSErr AEListUtils::FlattenAEList(AEDescList *deepList, AEDescList *flatList)
00500 {
00501        OSErr         err = noErr;
00502        AEDesc        item   = {typeNull, nil};
00503        AEKeyword     keyword;
00504        long                 itemNum;
00505        long                 numItems;
00506 
00507        err = AECountItems(deepList, &numItems);
00508        if (err != noErr)
00509               goto CleanUp;
00510        
00511        for (itemNum = 1; itemNum <= numItems; itemNum++)
00512        {
00513               err = AEGetNthDesc(deepList, itemNum, typeWildCard, &keyword, &item);
00514               if (err != noErr)
00515                      goto CleanUp;
00516                      
00517               if (item.descriptorType == typeAEList)
00518                      err = FlattenAEList(&item, flatList);
00519               else
00520                      err = AEPutDesc(flatList, 0L, &item);
00521               
00522               if (err != noErr)
00523                      goto CleanUp;
00524                      
00525               AEDisposeDesc(&item);
00526        }
00527 
00528 CleanUp:
00529        if (err != noErr)
00530               AEDisposeDesc(flatList);
00531 
00532        AEDisposeDesc(&item);
00533        
00534        return err;
00535 }
00536 
00537 
00538 #pragma mark -
00539 
00540 /*----------------------------------------------------------------------------
00541        StEventSuspender
00542        
00543 ----------------------------------------------------------------------------*/
00544 StEventSuspender::StEventSuspender(const AppleEvent *appleEvent, AppleEvent *reply, Boolean deleteData)
00545 :      mThreadAEInfo(nil)
00546 ,      mDeleteData(deleteData)
00547 {
00548        ThrowIfOSErr(CreateThreadAEInfo(appleEvent, reply, &mThreadAEInfo));
00549 }
00550 
00551 
00552 /*----------------------------------------------------------------------------
00553        ~StEventSuspender
00554        
00555 ----------------------------------------------------------------------------*/
00556 StEventSuspender::~StEventSuspender()
00557 {
00558        if (mDeleteData)
00559               DisposeThreadAEInfo(mThreadAEInfo);
00560 }
00561 
00562 /*----------------------------------------------------------------------------
00563        SuspendEvent
00564        
00565 ----------------------------------------------------------------------------*/
00566 void StEventSuspender::SuspendEvent()
00567 {
00568        ThrowIfOSErr(SuspendThreadAE(mThreadAEInfo));
00569 }
00570 
00571 
00572 /*----------------------------------------------------------------------------
00573        ResumeEvent
00574        
00575 ----------------------------------------------------------------------------*/
00576 void StEventSuspender::ResumeEvent()
00577 {
00578        ThrowIfOSErr(ResumeThreadAE(mThreadAEInfo, noErr));
00579 }
00580 
00581 
00582 
00583 #pragma mark -
00584 
00585 
00586 /*----------------------------------------------------------------------------
00587        StHandleHolder
00588        
00589 ----------------------------------------------------------------------------*/
00590 StHandleHolder::StHandleHolder(Handle inHandle)
00591 :      mHandle(inHandle)
00592 ,      mLockCount(0)
00593 {
00594 }
00595 
00596 
00597 /*----------------------------------------------------------------------------
00598        ~StHandleHolder
00599        
00600 ----------------------------------------------------------------------------*/
00601 StHandleHolder::~StHandleHolder()
00602 {
00603        if (mHandle)
00604               DisposeHandle(mHandle);
00605 }
00606 
00607 
00608 /*----------------------------------------------------------------------------
00609        operator=
00610        
00611 ----------------------------------------------------------------------------*/
00612 StHandleHolder& StHandleHolder::operator=(Handle rhs)
00613 {
00614        AE_ASSERT(mLockCount == 0, "Bad lock count");
00615        mLockCount = 0;
00616        
00617        if (mHandle)
00618               DisposeHandle(mHandle);
00619               
00620        mHandle = rhs;
00621        return *this;
00622 }
00623 
00624 /*----------------------------------------------------------------------------
00625        Lock
00626        
00627 ----------------------------------------------------------------------------*/
00628 void StHandleHolder::Lock()
00629 {
00630        ThrowIfNil(mHandle);
00631        if (++mLockCount > 1) return;
00632        mOldHandleState = HGetState(mHandle);
00633        HLock(mHandle);
00634 }
00635 
00636 /*----------------------------------------------------------------------------
00637        Unlock
00638        
00639 ----------------------------------------------------------------------------*/
00640 void StHandleHolder::Unlock()
00641 {
00642        ThrowIfNil(mHandle);
00643        AE_ASSERT(mLockCount > 0, "Bad lock count");
00644        if (--mLockCount == 0)
00645               HSetState(mHandle, mOldHandleState);
00646 }
00647 
00648 
00649 #pragma mark -
00650 
00651 
00652 /*----------------------------------------------------------------------------
00653        StAEListIterator
00654        
00655 ----------------------------------------------------------------------------*/
00656 AEListIterator::AEListIterator(AEDesc *token)
00657 :      mNumItems(0)
00658 ,      mCurItem(0)
00659 ,      mIsListDesc(false)
00660 {
00661        ThrowIfNil(token);
00662        mListToken = *token;
00663        mIsListDesc = AEListUtils::TokenContainsTokenList(&mListToken);
00664        if (mIsListDesc)
00665        {
00666               ThrowIfOSErr(::AECountItems(token, &mNumItems));
00667               mCurItem = 1;
00668        }
00669        else
00670        {
00671               mCurItem = 0;
00672               mNumItems = 1;
00673        }
00674 }
00675 
00676 
00677 /*----------------------------------------------------------------------------
00678        Next
00679        
00680 ----------------------------------------------------------------------------*/
00681 Boolean AEListIterator::Next(AEDesc* outItemData)
00682 {
00683        if (mIsListDesc)
00684        {
00685               AEKeyword     keyword;
00686               
00687               if (mCurItem == 0 || mCurItem > mNumItems)
00688                      return false;
00689               
00690               ThrowIfOSErr(::AEGetNthDesc(&mListToken, mCurItem, typeWildCard, &keyword, outItemData));
00691               
00692               // what about nested lists?
00693               AE_ASSERT(!AEListUtils::TokenContainsTokenList(outItemData), "Nested list found");
00694        }
00695        else
00696        {
00697               if (mCurItem > 0)
00698                      return false;
00699               
00700               ThrowIfOSErr(::AEDuplicateDesc(&mListToken, outItemData));
00701        }
00702        
00703        mCurItem ++;
00704        return true;
00705 }
00706 
00707 
00708 
00709 #pragma mark -
00710 
00711 /*----------------------------------------------------------------------------
00712        CheckForUnusedParameters 
00713        
00714        Check to see if there exist any additional required parameters in the Apple Event.
00715        If so, return an err to the calling routine, because we didn't extract them all.
00716 ----------------------------------------------------------------------------*/
00717 OSErr  CheckForUnusedParameters(const AppleEvent* appleEvent)
00718 {
00719        OSErr         err           = noErr;
00720        
00721        DescType      actualType    = typeNull;
00722        Size          actualSize    = 0L;
00723        
00724        err = AEGetAttributePtr(appleEvent, 
00725                                                                keyMissedKeywordAttr, 
00726                                                                typeWildCard,
00727                                                                &actualType, 
00728                                                                nil, 
00729                                                                0, 
00730                                                                &actualSize);
00731                                                                
00732        if (err == errAEDescNotFound)
00733               err = noErr;
00734        else
00735               err = errAEParamMissed;
00736               
00737        return err;
00738 }
00739 
00740 /*----------------------------------------------------------------------------
00741        PutReplyErrorNumber 
00742        
00743        If a reply is expected, the err number is returned in the reply parameter.
00744 ----------------------------------------------------------------------------*/
00745 OSErr  PutReplyErrorNumber(AppleEvent* reply, long errorNumber)
00746 {
00747        OSErr err = noErr;
00748        
00749        if (reply->dataHandle != nil && errorNumber != noErr)
00750        {
00751               err = AEPutParamPtr(reply, 
00752                                                                 keyErrorNumber, 
00753                                                                 typeLongInteger, 
00754                                                                 (Ptr)&errorNumber, 
00755                                                                 sizeof(long));
00756        }
00757        return err;
00758 }
00759 
00760 /*----------------------------------------------------------------------------
00761        PutReplyErrorMessage 
00762        
00763        If a reply is expected, the err message is inserted into the reply parameter.
00764 ----------------------------------------------------------------------------*/
00765 OSErr  PutReplyErrorMessage(AppleEvent* reply, char *message)
00766 {
00767        OSErr err = noErr;
00768        
00769        if (reply->dataHandle != nil && message != NULL)
00770        {
00771               err = AEPutParamPtr(reply, 
00772                                                                 keyErrorString, 
00773                                                                 typeChar, 
00774                                                                 (Ptr)message, 
00775                                                                 strlen(message));
00776        }
00777        return err;
00778 }
00779 
00780 
00781 /*----------------------------------------------------------------------------
00782        GetObjectClassFromAppleEvent 
00783        
00784        This is used to extract the type of object that an appleevent is supposed
00785        to work with. In the Core events, this includes:
00786               count <reference> each <typeOfObject>
00787               make new <typeOfObject>
00788               save <reference> in <alias> as <typeOfObject>
00789 ---------------------------------------------------------------------------*/
00790 OSErr GetObjectClassFromAppleEvent(const AppleEvent *appleEvent, DescType *objectClass)
00791 {
00792        OSErr  err     = noErr;
00793        OSType typeCode;                                 // should be typeType
00794        long          actualSize;
00795        
00796        // Get the class of object that we will count
00797 
00798        err = AEGetParamPtr(appleEvent, 
00799                                                          keyAEObjectClass, 
00800                                                          typeType, 
00801                                                          &typeCode,
00802                                                          (Ptr)objectClass, 
00803                                                          sizeof(DescType), 
00804                                                          &actualSize);
00805                                                          
00806        if (typeCode != typeType) 
00807               err = errAECoercionFail;
00808        
00809        return err;
00810 }
00811 
00812 #pragma mark -
00813 
00814 /*----------------------------------------------------------------------------
00815        DescToPString 
00816        
00817        Converts descriptor dataHandle  to a pascal string
00818        
00819 ---------------------------------------------------------------------------*/
00820 OSErr DescToPString(const AEDesc* desc, Str255 aPString, short maxLength)
00821 {
00822        if (desc->descriptorType == typeChar)
00823        {
00824               long stringLen = AEGetDescDataSize(desc);
00825               if (stringLen > maxLength)
00826                      stringLen = maxLength;
00827               AEGetDescData(desc, aPString+1, stringLen);
00828               aPString[0] = stringLen;
00829        }
00830        else
00831        {
00832        StAEDesc tempDesc;
00833               if (AECoerceDesc(desc, typeChar, &tempDesc) == noErr) {
00834               long stringLen = tempDesc.GetDataSize();
00835               if (stringLen > maxLength)
00836                      stringLen = maxLength;
00837               AEGetDescData(&tempDesc, aPString+1, stringLen);
00838               aPString[0] = stringLen;
00839               } else
00840                      return errAECoercionFail;
00841        }
00842        return noErr;
00843 }
00844 
00845 
00846 /*----------------------------------------------------------------------------
00847        DescToCString 
00848        
00849        Converts descriptor dataHandle  to a C string
00850        
00851 --------------------------------------------------------------------------- */
00852 OSErr DescToCString(const AEDesc* desc, CStr255 aCString, short maxLength)
00853 {
00854        if (desc->descriptorType == typeChar)
00855        {
00856            long stringLen = AEGetDescDataSize(desc);
00857            if (stringLen >= maxLength)
00858                stringLen = maxLength - 1;
00859               if (AEGetDescData(desc, aCString, stringLen) == noErr)
00860               aCString[stringLen] = '\0';
00861        else
00862                      return errAECoercionFail;
00863        }
00864        else
00865        {
00866        StAEDesc tempDesc;
00867               if (AECoerceDesc(desc, typeChar, &tempDesc) == noErr) {
00868            long stringLen = AEGetDescDataSize(&tempDesc);
00869            if (stringLen >= maxLength)
00870                stringLen = maxLength - 1;
00871               if (AEGetDescData(&tempDesc, aCString, stringLen) == noErr)
00872                      aCString[stringLen] = '\0';
00873               else
00874                      return errAECoercionFail;
00875               } else
00876                      return errAECoercionFail;
00877        }
00878        return noErr;
00879 }
00880 
00881 //----------------------------------------------------------------------------------
00882 //     Converts descriptor dataHandle  to a DescType
00883 //----------------------------------------------------------------------------------
00884 
00885 OSErr DescToDescType(const AEDesc *desc, DescType *descType)
00886 {
00887        if (AEGetDescDataSize(desc) == sizeof(DescType))
00888            return AEGetDescData(desc, descType, sizeof(DescType));
00889        else
00890               return errAECoercionFail;
00891 }
00892 
00893 //----------------------------------------------------------------------------------
00894 //     Converts descriptor dataHandle  to a boolean
00895 //----------------------------------------------------------------------------------
00896 
00897 OSErr DescToBoolean(const AEDesc* desc, Boolean* aBoolean)
00898 {
00899     return AECoerceDescData(desc, typeBoolean, aBoolean, sizeof(Boolean));
00900 }
00901 
00902 //----------------------------------------------------------------------------------
00903 //     Converts descriptor dataHandle  to a Fixed
00904 //----------------------------------------------------------------------------------
00905 
00906 OSErr DescToFixed(const  AEDesc* desc, Fixed* aFixed)
00907 {
00908     return AECoerceDescData(desc, typeFixed, aFixed, sizeof(Fixed));
00909 }
00910 
00911 //----------------------------------------------------------------------------------
00912 //     Converts descriptor dataHandle  to a float
00913 //----------------------------------------------------------------------------------
00914 
00915 OSErr DescToFloat(const  AEDesc* desc, float* aFloat)
00916 {
00917     return AECoerceDescData(desc, typeFloat, aFloat, sizeof(float));
00918 }
00919 
00920 //----------------------------------------------------------------------------------
00921 //     Converts descriptor dataHandle  to a long
00922 //----------------------------------------------------------------------------------
00923 
00924 OSErr DescToLong(const AEDesc* desc, long* aLong)
00925 {
00926     return AECoerceDescData(desc, typeLongInteger, aLong, sizeof(long));
00927 }
00928 
00929 //----------------------------------------------------------------------------------
00930 //     Converts descriptor dataHandle  to a RGBColor 
00931 //----------------------------------------------------------------------------------
00932 
00933 OSErr DescToRGBColor(const  AEDesc* desc, RGBColor* aRGBColor)
00934 {
00935     return AECoerceDescData(desc, typeRGBColor, aRGBColor, sizeof(RGBColor));
00936 }
00937 
00938 //----------------------------------------------------------------------------------
00939 //     Converts descriptor dataHandle  to a short.
00940 //----------------------------------------------------------------------------------
00941 
00942 OSErr DescToShort(const  AEDesc* desc, short* aShort)
00943 {
00944     return AECoerceDescData(desc, typeShortInteger, aShort, sizeof(short));
00945 }
00946 
00947 //----------------------------------------------------------------------------------
00948 //     Copies descriptor dataHandle to another handle, if its text
00949 //----------------------------------------------------------------------------------
00950 
00951 OSErr DescToTextHandle(const AEDesc* desc, Handle *text)
00952 {
00953     Handle data = nil;
00954     
00955        if (desc->descriptorType == typeChar)
00956        {
00957            Size dataSize = ::AEGetDescDataSize(desc);
00958            data = ::NewHandle(dataSize);
00959            if (data == NULL)
00960                return memFullErr;
00961         ::HLock(data);
00962         ::AEGetDescData(desc, *data, dataSize);
00963         ::HUnlock(data);
00964        }
00965        else
00966        {
00967        StAEDesc tempDesc;
00968               if (::AECoerceDesc(desc, typeChar, &tempDesc) == noErr)
00969                   data = tempDesc.GetTextHandle();
00970               else
00971                   return errAECoercionFail;
00972        }
00973        *text = data;
00974        return noErr;
00975 }
00976 
00977 //----------------------------------------------------------------------------------
00978 //     Converts descriptor dataHandle  to a Rectangle 
00979 //----------------------------------------------------------------------------------
00980 
00981 OSErr DescToRect(const  AEDesc* desc, Rect* aRect)
00982 {
00983     return AECoerceDescData(desc, typeRectangle, aRect, sizeof(Rect));
00984 }
00985 
00986 //----------------------------------------------------------------------------------
00987 //     Converts descriptor dataHandle  to a Point 
00988 //----------------------------------------------------------------------------------
00989 
00990 OSErr DescToPoint(const  AEDesc* desc, Point* aPoint)
00991 {
00992     return AECoerceDescData(desc, typeQDPoint, aPoint, sizeof(Point));
00993 }
00994 
00995 #pragma mark -
00996 
00997 /*----------------------------------------------------------------------------
00998        NormalizeAbsoluteIndex 
00999        
01000         Handles formAbsolutePosition resolution
01001        
01002 ---------------------------------------------------------------------------*/
01003 OSErr NormalizeAbsoluteIndex(const AEDesc *keyData, long *index, long maxIndex, Boolean *isAllItems)
01004 {
01005        OSErr err = noErr;
01006        
01007        *isAllItems = false;                                                  // set to true if we receive kAEAll constant
01008        
01009        // Extract the formAbsolutePosition data, either a integer or a literal constant
01010        
01011        switch (keyData->descriptorType)
01012        {
01013               case typeLongInteger:                                          // positve or negative index
01014                      if (DescToLong(keyData, index) != noErr)
01015                             return errAECoercionFail;
01016 
01017                      if (*index < 0)                                                // convert a negative index from end of list to a positive index from beginning of list
01018                             *index = maxIndex + *index + 1;
01019                      break;
01020                      
01021           case typeAbsoluteOrdinal:                                                                      // 'abso'
01022                      DescType             ordinalDesc;
01023                      if (DescToDescType((AEDesc*)keyData, &ordinalDesc) != noErr)
01024                             ThrowOSErr(errAECoercionFail);
01025                      
01026                      switch (ordinalDesc)
01027                      {
01028                             case kAEFirst:
01029                                    *index = 1;
01030                                    break;
01031                                    
01032                             case kAEMiddle:
01033                                    *index = (maxIndex >> 1) + (maxIndex % 2);
01034                                    break;
01035                                           
01036                             case kAELast:
01037                                    *index = maxIndex;
01038                                    break;
01039                                           
01040                             case kAEAny:
01041                                    *index = (TickCount() % maxIndex) + 1;           // poor man's random
01042                                    break;
01043                                           
01044                             case kAEAll:
01045                                    *index = 1;
01046                                    *isAllItems = true;
01047                                    break;
01048                      }
01049                      break;
01050 
01051               default:
01052                      return errAEWrongDataType;
01053                      break;
01054        }
01055 
01056        // range-check the new index number
01057        if ((*index < 1) || (*index > maxIndex))                              
01058        {
01059               err = errAEIllegalIndex;
01060        }
01061 
01062        return err;
01063 }
01064 
01065 
01066 //----------------------------------------------------------------------------------
01067 // Handles formRange resolution of boundary objects
01068 
01069 OSErr ProcessFormRange(AEDesc *keyData, AEDesc *start, AEDesc *stop)
01070 {
01071        OSErr         err = noErr;
01072        StAEDesc             rangeRecord;
01073        StAEDesc             ospec;
01074        
01075        // coerce the range record data into an AERecord 
01076        
01077        err = AECoerceDesc(keyData, typeAERecord, &rangeRecord);
01078        if (err != noErr)
01079               return err;
01080         
01081        // object specifier for first object in the range
01082        err = AEGetKeyDesc(&rangeRecord, keyAERangeStart, typeWildCard, &ospec);
01083        if (err == noErr && ospec.descriptorType == typeObjectSpecifier)
01084               err = AEResolve(&ospec, kAEIDoMinimum, start);
01085               
01086        if (err != noErr)
01087               return err;
01088               
01089        ospec.Clear();
01090               
01091        // object specifier for last object in the range
01092        
01093        err = AEGetKeyDesc(&rangeRecord, keyAERangeStop, typeWildCard, &ospec);
01094        if (err == noErr && ospec.descriptorType == typeObjectSpecifier)
01095               err = AEResolve(&ospec, kAEIDoMinimum, stop);
01096 
01097        return err;
01098 }