home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Papers / C++ Exceptions / µShell / Core Utilities / AEExtras.cp next >
Encoding:
Text File  |  1998-04-02  |  29.2 KB  |  1,397 lines  |  [TEXT/CWIE]

  1. #ifndef __AEEXTRAS__
  2. #include "AEExtras.h"
  3. #endif
  4. #ifndef __AETYPECOERCIONS__
  5. #include "AETypeCoercions.h"
  6. #endif
  7. #ifndef __EXCEPTIONS__
  8. #include "Exceptions.h"
  9. #endif
  10.  
  11. #include <OSA.h>
  12. #include <stdarg.h>
  13. #include <AEObjects.h>
  14. #include <AERegistry.h>
  15. #include <ASRegistry.h>
  16.  
  17. #include <Patches.h>
  18. #include <Traps.h>
  19.  
  20. #include "AEBuild.h"
  21. #include "DebugWrite.h"
  22.  
  23. const ProcessSerialNumber    kAESelfPSN            = { 0, kCurrentProcess };
  24. AEAddressDesc                gSelfAddrDesc        = {typeNull, nil };
  25. static AEIdleUPP            gDefaultAEIdleUPP    = nil;
  26. static AEFilterUPP            gDefaultAEFilterUPP    = nil;
  27.  
  28. #define ZeroDesc(d)    { (d).descriptorType = typeNull; (d).dataHandle = nil; }
  29.  
  30. //------------------------------------------------------------------------------
  31.  
  32.     static OSStatus vCoerceDescProc(va_list arg)
  33.     {
  34.         VA_ARG(const AEDesc*,        fromDesc,    arg);    
  35.         VA_ARG(DescType,            toType,        arg);    
  36.         VA_ARG(AECoerceDescProcPtr,    proc,        arg);    
  37.         VA_ARG(AEDesc*,                toDesc,        arg);    
  38.     
  39.         return (*proc)(fromDesc, toType, 0, toDesc);
  40.     }
  41.  
  42.     static pascal OSErr XCoerceDescProc(
  43.         const AEDesc*    fromDesc,
  44.         DescType        toType,
  45.         long            handlerRefcon,
  46.         AEDesc*            toDesc)
  47.     {
  48.         return Exception::CatchOSErrors(vCoerceDescProc, fromDesc, toType, handlerRefcon, toDesc);
  49.     }
  50.  
  51. pascal void XAEInstallCoerceDescProc(
  52.     DescType                 fromType,
  53.     DescType                 toType,
  54.     AECoerceDescProcPtr     handler)
  55. {
  56. #if GENERATINGCFM
  57.  
  58.     static RoutineDescriptor UPP =
  59.         BUILD_ROUTINE_DESCRIPTOR(uppAECoerceDescProcInfo, XCoerceDescProc);
  60.  
  61.     FailOSErr(AEInstallCoercionHandler(fromType, toType, &UPP, (long) handler, true, false));
  62.  
  63. #else
  64.  
  65.     FailOSErr(AEInstallCoercionHandler(fromType, toType,
  66.                    (AECoercionHandlerUPP) &XCoerceDescProc, (long) handler, true, false));
  67.  
  68. #endif
  69.  
  70. }
  71.  
  72. //------------------------------------------------------------------------------
  73.  
  74.     static OSStatus vCoercePtrProc(va_list arg)
  75.     {
  76.         VA_ARG(DescType,            typeCode,    arg);    
  77.         VA_ARG(const void*,            dataPtr,    arg);    
  78.         VA_ARG(Size,                dataSize,    arg);    
  79.         VA_ARG(DescType,            toType,        arg);    
  80.         VA_ARG(AECoercePtrProcPtr,    proc,        arg);    
  81.         VA_ARG(AEDesc*,                toDesc,        arg);    
  82.     
  83.         return (*proc)(typeCode, dataPtr, dataSize, toType, 0, toDesc);
  84.     }
  85.  
  86.     static pascal OSErr XCoercePtrProc(
  87.         DescType            typeCode,
  88.         const void*            dataPtr,
  89.         Size                dataSize,
  90.         DescType            toType,
  91.         long                handlerRefcon,
  92.         AEDesc*                result)
  93.     {
  94.         return Exception::CatchOSErrors(vCoercePtrProc, typeCode, dataPtr, dataSize, toType, handlerRefcon, result);
  95.     }
  96.  
  97. pascal void XAEInstallCoercePtrProc(
  98.     DescType                 fromType,
  99.     DescType                 toType,
  100.     AECoercePtrProcPtr         handler)
  101. {
  102. #if GENERATINGCFM
  103.  
  104.     static RoutineDescriptor UPP =
  105.         BUILD_ROUTINE_DESCRIPTOR(uppAECoercePtrProcInfo, XCoerceDescProc);
  106.  
  107.     FailOSErr(AEInstallCoercionHandler(fromType, toType, &UPP, (long) handler, false, false));
  108.  
  109. #else
  110.  
  111.     FailOSErr(AEInstallCoercionHandler(fromType, toType,
  112.                    (AECoercionHandlerUPP) &XCoerceDescProc, (long) handler, false, false));
  113.  
  114. #endif
  115.  
  116. }
  117.  
  118. //------------------------------------------------------------------------------
  119.  
  120. static pascal OSErr CoerceToInsertion(
  121.     const AEDesc*    fromDesc,
  122.     DescType        /*toType*/,
  123.     long            /*handlerRefcon*/,
  124.     AEDesc*            toDesc)
  125. {
  126.     AEDesc    tempDesc;
  127.     
  128.     OSErr err = AECreateList(nil, 0, true, &tempDesc);
  129.     
  130.     if (err == noErr)
  131.     {
  132.         err = AEPutParamDesc(&tempDesc, keyAEObject, fromDesc);
  133.     
  134.         if (err == noErr)
  135.         {
  136.             DescType in = formIn;
  137.         
  138.             err = AEPutParamPtr(&tempDesc, keyAEPosition, typeEnumeration, &in, sizeof(in));
  139.         
  140.             if (err == noErr)
  141.             {
  142.                 err = AECoerceDesc(&tempDesc, typeInsertionLoc, toDesc);
  143.             }
  144.         }
  145.     
  146.         AEDisposeDesc(&tempDesc);
  147.     }
  148.     
  149.     return err;
  150. }
  151.  
  152. //------------------------------------------------------------------------------
  153.  
  154. pascal OSErr InitAEExtras(AEIdleUPP idle, AEFilterUPP filter)
  155. {
  156.     OSErr err = noErr;
  157.     
  158.     gDefaultAEIdleUPP    = idle;
  159.     gDefaultAEFilterUPP    = filter;
  160.  
  161.     if (gSelfAddrDesc.dataHandle == nil)
  162.     {
  163.         err = AECreateDesc(typeProcessSerialNumber, &kAESelfPSN, sizeof(kAESelfPSN), &gSelfAddrDesc);
  164.     }
  165.  
  166.     if (err == noErr)
  167.     {
  168.         err = AEInstallTypeCoercions();
  169.     }
  170.  
  171.     if (err == noErr)
  172.     {
  173. #if GENERATINGCFM
  174.     static RoutineDescriptor sCoerceTypeUPP =
  175.                 BUILD_ROUTINE_DESCRIPTOR(uppAECoerceDescProcInfo, CoerceToInsertion);
  176.  
  177.         err = AEInstallCoercionHandler(typeObjectSpecifier, typeInsertionLoc, &sCoerceTypeUPP, 0, true, false);
  178. #else
  179.  
  180.         err = AEInstallCoercionHandler(typeObjectSpecifier, typeInsertionLoc,
  181.                 (AECoercionHandlerUPP)NewAECoerceDescProc(CoerceToInsertion), 0, true, false);
  182. #endif
  183.     }
  184.     
  185.     return err;
  186. }
  187.  
  188. //------------------------------------------------------------------------------
  189.  
  190. pascal OSErr    TempAECreateDesc(DescType typeCode, const void* dataPtr, Size dataSize, AEDesc *result)
  191. {
  192.     OSErr    err = noErr;
  193.  
  194.     result->descriptorType = typeCode;
  195.     result->dataHandle = TempNewHandle(dataSize,&err);
  196.     
  197.     if ((err != noErr) || (result->dataHandle == nil))
  198.     {
  199.         result->dataHandle = NewHandle(dataSize);
  200.         err = MemError();
  201.     }
  202.     
  203.     if ( ( err == noErr ) && ( result->dataHandle != nil ) && ( dataPtr != nil ) )
  204.         BlockMoveData(dataPtr,*(result->dataHandle),dataSize);
  205.     
  206.     return err;
  207. }
  208.  
  209. //------------------------------------------------------------------------------
  210.  
  211. pascal OSErr    TempAEDuplicateDesc(const AEDesc *source, AEDesc *dest)
  212. {
  213.     OSErr    err = noErr;
  214.     
  215.     if (source->dataHandle != nil)
  216.     {
  217.         char    state = HGetState(source->dataHandle);
  218.     
  219.         HLockHi(source->dataHandle);
  220.         
  221.         err = TempAECreateDesc(source->descriptorType,
  222.                                 *source->dataHandle, GetHandleSize(source->dataHandle),
  223.                                 dest);
  224.         
  225.         HSetState(source->dataHandle, state);
  226.     }
  227.     else
  228.     {
  229.         *dest = *source;
  230.     }
  231.     
  232.     return err;
  233. }
  234.  
  235. //------------------------------------------------------------------------------
  236.  
  237. AEIdleUPP AEGetDefaultIdleProc(void)
  238. {
  239.     return gDefaultAEIdleUPP;
  240. }
  241.  
  242. //------------------------------------------------------------------------------
  243.  
  244. AEIdleUPP AESetDefaultIdleProc(AEIdleUPP newProc)
  245. {
  246.     AEIdleUPP old = gDefaultAEIdleUPP;
  247.     gDefaultAEIdleUPP = newProc;
  248.     return old;
  249. }
  250.  
  251. //------------------------------------------------------------------------------
  252.  
  253. AEFilterUPP AEGetDefaultFilterProc(void)
  254. {
  255.     return gDefaultAEFilterUPP;
  256. }
  257.  
  258. //------------------------------------------------------------------------------
  259.  
  260. AEFilterUPP AESetDefaultFilterProc(AEFilterUPP newProc)
  261. {
  262.     AEFilterUPP old = gDefaultAEFilterUPP;
  263.     gDefaultAEFilterUPP = newProc;
  264.     return old;
  265. }
  266.  
  267. //------------------------------------------------------------------------------
  268.  
  269. const AEAddressDesc* AEGetSelfAddress()
  270. {
  271.     return &gSelfAddrDesc;
  272. }
  273.  
  274. //------------------------------------------------------------------------------
  275.  
  276. enum AEHandlerType    // Search order for handlers
  277. {
  278.     kAETypeTypeAppHandler,
  279.     kAETypeWildAppHandler,
  280.     kAEWildTypeAppHandler,
  281.     kAEWildWildAppHandler,
  282.     kAETypeTypeSysHandler,
  283.     kAETypeWildSysHandler,
  284.     kAEWildTypeSysHandler,
  285.     kAEWildWildSysHandler
  286. };
  287.  
  288.  
  289. pascal OSErr XAEGetCoercionHandler(
  290.     DescType                fromType,
  291.     DescType                toType,
  292.     AECoercionHandlerUPP*    handler,
  293.     long*                    handlerRefcon,
  294.     Boolean*                fromTypeIsDesc,
  295.     AECoercionHandlerUPP    skipMe)
  296. {
  297.     OSErr err = AEGetCoercionHandler(fromType, toType, handler, handlerRefcon, fromTypeIsDesc, false);
  298.  
  299.     if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
  300.     {
  301.         err = AEGetCoercionHandler(typeWildCard, toType, handler, handlerRefcon, fromTypeIsDesc, false);
  302.     }
  303.  
  304.     if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
  305.     {
  306.         err = AEGetCoercionHandler(fromType, typeWildCard, handler, handlerRefcon, fromTypeIsDesc, false);
  307.     }
  308.  
  309.     if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
  310.     {
  311.         err = AEGetCoercionHandler(typeWildCard, typeWildCard, handler, handlerRefcon, fromTypeIsDesc, false);
  312.     }
  313.     
  314.     if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
  315.     {
  316.         err = AEGetCoercionHandler(fromType, toType, handler, handlerRefcon, fromTypeIsDesc, true);
  317.     }
  318.     
  319.     if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
  320.     {
  321.         err = AEGetCoercionHandler(typeWildCard, toType, handler, handlerRefcon, fromTypeIsDesc, true);
  322.     }
  323.  
  324.     if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
  325.     {
  326.         err = AEGetCoercionHandler(fromType, typeWildCard, handler, handlerRefcon, fromTypeIsDesc, true);
  327.     }
  328.  
  329.     if (err == errAEHandlerNotFound || err == noErr && *handler == skipMe)
  330.     {
  331.         err = AEGetCoercionHandler(typeWildCard, typeWildCard, handler, handlerRefcon, fromTypeIsDesc, true);
  332.     }
  333.     
  334.     if (err == noErr && *handler == skipMe)
  335.     {
  336.         err = errAEHandlerNotFound;
  337.     }
  338.  
  339.     return err;
  340. }
  341.  
  342. //------------------------------------------------------------------------------
  343.  
  344. pascal OSErr XAECoercePtr(
  345.     DescType         typeCode,
  346.     const void*        dataPtr,
  347.     Size            dataSize,
  348.     DescType        toType,
  349.     AEDesc*            result)
  350. {
  351.     AECoercionHandlerUPP    handler;
  352.     long                    handlerRefcon;
  353.     Boolean                    fromTypeIsDesc;
  354.     
  355.     OSErr err = XAEGetCoercionHandler(typeCode, toType, &handler, &handlerRefcon, &fromTypeIsDesc);
  356.  
  357.     if (err == noErr)
  358.     {
  359.         if (fromTypeIsDesc)
  360.         {
  361.             AEDesc fromDesc;
  362.  
  363.             err = TempAECreateDesc(typeCode, dataPtr,dataSize, &fromDesc);
  364.             
  365.             if (err == noErr)
  366.             {
  367.                 err = CallAECoerceDescProc((AECoerceDescUPP) handler, &fromDesc, toType, handlerRefcon, result);
  368.             }
  369.             
  370.             AEDisposeDesc(&fromDesc);
  371.         }
  372.         else
  373.         {
  374.             err = CallAECoercePtrProc((AECoercePtrUPP) handler, typeCode, dataPtr, dataSize, toType, handlerRefcon, result);
  375.         }
  376.     }
  377.     
  378.     return err;
  379. }
  380.  
  381. //------------------------------------------------------------------------------
  382.  
  383. pascal OSErr XAECoerceDesc(
  384.     const AEDesc*    fromDesc,
  385.     DescType        toType,
  386.     AEDesc*            result)
  387. {
  388.     AECoercionHandlerUPP    handler;
  389.     long                    handlerRefcon;
  390.     Boolean                    fromTypeIsDesc;
  391.     
  392.     OSErr err = XAEGetCoercionHandler(fromDesc->descriptorType, toType, &handler, &handlerRefcon, &fromTypeIsDesc);
  393.  
  394.     if (err == noErr)
  395.     {
  396.         if (fromTypeIsDesc)
  397.         {
  398.             err = CallAECoerceDescProc((AECoerceDescUPP) handler, fromDesc, toType, handlerRefcon, result);
  399.         }
  400.         else
  401.         {
  402.             Handle        h       = fromDesc->dataHandle;
  403.             SignedByte    state = HGetState(h); 
  404.                 
  405.             err = MemError();    // Validate handle
  406.             
  407.             if (err == noErr)
  408.             {
  409.                 HLock(h);    // Assume only possible failure here is handle already locked
  410.         
  411.                 Size size = GetHandleSize(h);
  412.             
  413.                 err = CallAECoercePtrProc((AECoercePtrUPP) handler, fromDesc->descriptorType, *h, size, toType, handlerRefcon, result);
  414.  
  415.                 HSetState(h, state);
  416.             }
  417.         }
  418.     }
  419.     
  420.     return err;
  421. }
  422.  
  423. //------------------------------------------------------------------------------
  424.  
  425. pascal OSErr AEGetDescPtr(
  426.     const AEDesc*    theAEDesc,
  427.     DescType         desiredType,
  428.     DescType*        typeCode,
  429.     void*            dataPtr,
  430.     Size             maximumSize,
  431.     Size*            actualSize)
  432. {
  433.     AEDesc tempDesc;
  434.     
  435.     tempDesc.descriptorType = typeNull;
  436.     tempDesc.dataHandle        = nil;
  437.  
  438.     const AEDesc *desc    = theAEDesc;
  439.     OSErr err            = noErr;
  440.     Size  offset        = 0;
  441.  
  442.     if (desiredType != typeWildCard
  443.     &&    desiredType != theAEDesc->descriptorType)
  444.     {
  445.         DescType oldType = desc->descriptorType;
  446.     
  447.         if (desc->dataHandle == nil) switch (oldType)
  448.         {
  449.         case typeTrue:                // for speed 
  450.         case typeFalse:
  451.             switch (desiredType)
  452.             {
  453.             case typeBoolean:
  454.                 *(Boolean*)dataPtr = (oldType == typeTrue);
  455.                 goto done;
  456.             }
  457.         
  458.             break;
  459.         }
  460.     
  461.         desc = &tempDesc;
  462.         err  = AECoerceDesc(theAEDesc, desiredType, &tempDesc); 
  463.     }
  464.     
  465.     if (err == noErr)
  466.     {
  467.         Size dataSize = desc->dataHandle ? GetHandleSize(desc->dataHandle) : 0;
  468.         
  469.         *typeCode    = desc->descriptorType;
  470.         *actualSize = dataSize;
  471.         
  472.         if (dataSize > maximumSize)
  473.             dataSize = maximumSize;
  474.             
  475.         BlockMoveData(*desc->dataHandle, dataPtr, dataSize);
  476.     }
  477.     
  478.     AEDisposeDesc(&tempDesc);
  479.  
  480. done:    
  481.     return err;    
  482. }
  483.  
  484. //------------------------------------------------------------------------------
  485.  
  486. pascal OSErr AEParseInsertionLocation(
  487.     const AEDesc*    insertLoc,
  488.     AEDesc*            container,    // the affected container
  489.     DescType*        position,    // the position enumeration
  490.     AEDesc*            reference,
  491.     DescType*        refClass)    // objects to be replaced
  492. {
  493.     AEDesc            tempRecord;
  494.     AEDesc            tempObject;
  495.     DescType        actualType;
  496.     Size            actualSize;
  497.     DescType        localPosition;
  498.     OSErr            err            = noErr;
  499.     OSErr            err1;
  500.     
  501.     ZeroDesc(tempRecord);
  502.     ZeroDesc(tempObject);
  503.         
  504.     if (position != nil)
  505.     {
  506.         *position = 0;
  507.     }
  508.     else
  509.     {
  510.         position = &localPosition;
  511.     }
  512.     
  513.     if (container != nil)
  514.     {
  515.         if (container == insertLoc)
  516.         {
  517.             tempRecord    = *insertLoc;
  518.             insertLoc    = &tempRecord;
  519.         }
  520.     
  521.         ZeroDesc(*container);
  522.     }
  523.  
  524.     if (reference != nil)
  525.     {
  526.         if (reference == insertLoc)
  527.         {
  528.             tempRecord    = *insertLoc;
  529.             insertLoc    = &tempRecord;
  530.         }
  531.     
  532.         ZeroDesc(*reference);
  533.     }
  534.  
  535.     if (refClass != nil)
  536.     {
  537.         *refClass = 0;
  538.     }
  539.  
  540.     if (insertLoc == nil)
  541.     {
  542.         err = paramErr;
  543.     }
  544.     else switch (insertLoc->descriptorType)
  545.     {
  546.     case typeObjectSpecifier:
  547.     case typeNull:
  548.     case typeObjectBeingExamined:
  549.     case typeAEList:
  550.  
  551.         // an object specifier used an an insertion location is the container
  552.         
  553.         if (container != nil)
  554.         {
  555.             if (insertLoc == &tempRecord)    // If we own it, just return it
  556.             {
  557.                 *container = *insertLoc;
  558.                 ZeroDesc(tempRecord);
  559.             }
  560.             else
  561.             {
  562.                 err = AEDuplicateDesc(insertLoc, container);
  563.             }
  564.         }
  565.         
  566.         *position = formIn;
  567.         break;
  568.         
  569.     case typeInsertionLoc:    // Coerce our input into a record (if necessary)
  570.         err = AECoerceDesc(insertLoc, typeAERecord, &tempRecord);
  571.         insertLoc = &tempRecord;
  572.     case typeAERecord:        // We're already a record
  573.         if (err == noErr)
  574.         {
  575.             // Get the position parameter
  576.             
  577.             err = AEGetKeyPtr(insertLoc,
  578.                               keyAEPosition,
  579.                               typeEnumeration,
  580.                               &actualType,
  581.                               position,
  582.                               sizeof(*position),
  583.                               &actualSize);
  584.  
  585.             // Get the reference object
  586.             
  587.             err1 = AEGetKeyDesc(insertLoc, keyAEObject, typeWildCard, &tempObject);
  588.             
  589.             if (err == noErr)
  590.             {
  591.                 err = err1;
  592.             }
  593.             
  594.             if (err == errAEDescNotFound)
  595.             {
  596.                 err = errAENotAnObjSpec;
  597.             }
  598.         }
  599.         
  600.         if (err == noErr)
  601.         {
  602.             switch (*position)
  603.             {
  604.             case kAEBefore:        // tempObject is the reference object
  605.             case kAEAfter:        
  606.             case kAEReplace:
  607.                 if (reference)
  608.                 {
  609.                     *reference                    = tempObject;
  610.                     tempObject.descriptorType    = typeNull;
  611.                     tempObject.dataHandle        = nil;
  612.                 }
  613.                 else
  614.                 {
  615.                     reference = &tempObject;
  616.                 }
  617.                 
  618.                 err = AEParseObjectSpecifier(reference, refClass, container, nil, nil);
  619.                 break;
  620.                     
  621.             case kAEBeginning:    // tempObject is the container
  622.             case kAEEnd:
  623.             case formIn:
  624.                 if (container)
  625.                 {
  626.                     *container                    = tempObject;
  627.                     tempObject.descriptorType    = typeNull;
  628.                     tempObject.dataHandle        = nil;
  629.                 }
  630.                 break;
  631.             
  632.             default:
  633.                 err = errAECorruptData;                
  634.             }
  635.         }    
  636.         break;
  637.  
  638.     default:
  639.         err = errAENotAnObjSpec;
  640.     }
  641.  
  642.     // Clean up any temporary descriptors
  643.  
  644.     err1 = AEDisposeDesc(&tempObject);
  645.     err1 = AEDisposeDesc(&tempRecord);
  646.  
  647.     return err;
  648. }
  649.  
  650. //------------------------------------------------------------------------------
  651.  
  652. pascal OSErr AEParseObjectSpecifier(
  653.     const AEDesc*        object,
  654.     DescType*            desiredClass,
  655.     AEDesc*                container,
  656.     DescType*            keyForm,
  657.     AEDesc*                keyData)
  658. {
  659.     if (object->descriptorType == typeInsertionLoc)
  660.     {
  661.         // hand off insertion locations...
  662.     
  663.         return AEParseInsertionLocation(object, container, keyForm, keyData, desiredClass);
  664.     }
  665.     else
  666.     {
  667.         AEDesc            tempRecord;
  668.         DescType        actualType;
  669.         Size            actualSize;
  670.         OSErr            err            = noErr;
  671.         OSErr            err1;
  672.         
  673.         // Clear our temporaries
  674.         
  675.         ZeroDesc(tempRecord);
  676.         
  677.         // Clear our output parameters
  678.  
  679.         if (container != nil)
  680.         {
  681.             if (container == object) 
  682.             {
  683.                 tempRecord = *object;
  684.                 object = &tempRecord;
  685.             }
  686.  
  687.             ZeroDesc(*container);
  688.         }
  689.     
  690.         if (desiredClass != nil)
  691.         {
  692.             *desiredClass = 0;
  693.         }
  694.         
  695.         if (keyForm != nil)
  696.         {
  697.             *keyForm = 0;
  698.         }
  699.  
  700.         if (keyData != nil)
  701.         {
  702.             if (keyData == object) 
  703.             {
  704.                 tempRecord = *object;
  705.                 object = &tempRecord;
  706.             }
  707.  
  708.             ZeroDesc(*keyData);
  709.         }
  710.         
  711.         if (object == nil)
  712.         {
  713.             err = paramErr;
  714.         }
  715.         else switch (object->descriptorType)
  716.         {
  717.         case typeAEList:
  718.         case typeNull:
  719.         case typeObjectBeingExamined:
  720.             if (keyForm != nil)
  721.             {
  722.                 *keyForm = formSelf;
  723.             }
  724.             if (keyData != nil)
  725.             {
  726.                 err = TempAEDuplicateDesc(object, keyData);
  727.             }
  728.             break;
  729.  
  730.         case typeObjectSpecifier:
  731.             err = AECoerceDesc(object, typeAERecord, &tempRecord);
  732.             object = &tempRecord;
  733.         case typeAERecord:
  734.             if (err == noErr)
  735.             {
  736.                 if (desiredClass != nil)
  737.                 {
  738.                     err = AEGetKeyPtr(object,
  739.                               keyAEDesiredClass,
  740.                               typeType,
  741.                               &actualType,
  742.                               desiredClass,
  743.                               sizeof(*desiredClass),
  744.                               &actualSize);
  745.                               
  746.                     if (err == errAEDescNotFound)
  747.                     {
  748.                         err = errAENotAnObjSpec;
  749.                     }
  750.                 }
  751.                 
  752.                 if (container != nil)
  753.                 {
  754.                     err1 = AEGetKeyDesc(object, keyAEContainer, typeWildCard, container);
  755.                     
  756.                     if (err == noErr)
  757.                     {
  758.                         err = (err1 == errAEDescNotFound) ? errAENotAnObjSpec : err1;
  759.                     }
  760.                 }
  761.                 
  762.                 if (keyForm != nil)
  763.                 {
  764.                     err1 = AEGetKeyPtr(object,
  765.                               keyAEKeyForm,
  766.                               typeEnumerated,
  767.                               &actualType,
  768.                               keyForm,
  769.                               sizeof(*keyForm),
  770.                               &actualSize);
  771.                     
  772.                     if (err == noErr)
  773.                     {
  774.                         err = (err1 == errAEDescNotFound) ? errAENotAnObjSpec : err1;
  775.                     }
  776.                 }
  777.                 
  778.                 if (keyData != nil)
  779.                 {
  780.                     err1 = AEGetKeyDesc(object, keyAEKeyData, typeWildCard, keyData);
  781.                     
  782.                     if (err == noErr)
  783.                     {
  784.                         err = (err1 == errAEDescNotFound) ? errAENotAnObjSpec : err1;
  785.                     }
  786.                 }
  787.             }
  788.             break;
  789.             
  790.         default:
  791.             err = errAENotAnObjSpec;
  792.  
  793.         }
  794.  
  795.         err1 = AEDisposeDesc(&tempRecord);
  796.             
  797.         return err;
  798.     }
  799. }
  800.  
  801. //------------------------------------------------------------------------------
  802.  
  803. DescType IsObjectSpecifier(const AEDesc* desc)
  804. {
  805.     DescType type = desc->descriptorType;
  806.  
  807.     switch (type)                            // these types are considered to be
  808.     {                                        // valid as object specifiers - note
  809.     case typeObjectSpecifier:                // that we get no help from the 
  810.     case typeObjectBeingExamined:            // toolbox for typeAEList
  811.     case typeNull:
  812.         return type;
  813.  
  814.     case typeAEList:
  815.         return GetUniformItemType(desc, typeObjectSpecifier, true);
  816.     
  817.     default:
  818.         return 0;
  819.     }
  820. }
  821.  
  822. //------------------------------------------------------------------------------
  823.  
  824. DescType IsObjectSpecifierOrInsertion(const AEDesc* desc)
  825. {
  826.     if ((desc->descriptorType) == typeInsertionLoc)
  827.     {
  828.         return typeInsertionLoc;
  829.     }
  830.     else
  831.     {
  832.         return IsObjectSpecifier(desc);
  833.     }
  834. }
  835.  
  836. //------------------------------------------------------------------------------
  837.  
  838. DescType GetUniformItemType(const AEDesc* list, DescType type, bool recursive)
  839. {
  840.     DescType    actualType;
  841.     Size        actualSize;
  842.     AEKeyword    actualKey;
  843.  
  844.     OSErr err = AECountItems(list, &actualSize);
  845.  
  846.     if (err != noErr)
  847.     {
  848.         type = 0;
  849.     }
  850.     else
  851.     {
  852.         long count = actualSize;
  853.  
  854.         switch (type)    // indicate initial pass 
  855.         {
  856.         case 0:
  857.         case 1:
  858.         case typeWildCard:
  859.         case typeBest:
  860.             type = 1;
  861.         }
  862.         
  863.         for (long i = 1; i <= count; i++)
  864.         {
  865.             err = AESizeOfNthItem(list, i, &actualType, &actualSize);
  866.         
  867.             if (err != noErr)
  868.             {
  869.                 type = 0;
  870.                 break;
  871.             }
  872.             else if (actualType == typeAEList && recursive)
  873.             {
  874.                 AEDesc temp;
  875.                 
  876.                 err = AEGetNthDesc(list, i, typeAEList, &actualKey, &temp);
  877.                 
  878.                 if (err == noErr)
  879.                 {
  880.                     type = GetUniformItemType(&temp, type, recursive);
  881.                 }
  882.  
  883.                 AEDisposeDesc(&temp);
  884.                 
  885.                 if (err != noErr || type == 0)
  886.                 {
  887.                     break;
  888.                 }
  889.             }
  890.             else if (actualType != type)
  891.             {
  892.                 if (type == 1)
  893.                 {
  894.                     type = actualType;
  895.                 }
  896.                 else
  897.                 {
  898.                     type = 0;
  899.                     break;
  900.                 }
  901.             }
  902.         }
  903.         
  904.         if (type == 1)    // type never got initialized (count == 0)
  905.         {
  906.             type = typeWildCard;
  907.         }
  908.     }
  909.  
  910.     return type;
  911. }
  912. //------------------------------------------------------------------------------
  913. /*
  914. DescType GetUniformObjectClass(const AEDesc* list, DescType type, bool recursive)
  915. {
  916.     DebugStr("\pGetUniformObjectClass() is not implemented yet.");
  917.  
  918.     return 0;
  919. }
  920. */
  921. //------------------------------------------------------------------------------
  922.  
  923. pascal OSErr AEGetEventTarget(
  924.     const AppleEvent*    event,
  925.     AEDesc*                container,
  926. /*    DescType*            containerClass,
  927. */    DescType*            desiredClass,
  928. /*    DescType*            keyForm,
  929.     AEDesc*                keyData,
  930. */
  931.     long                flags,
  932.     AEKeyword*            psource)
  933. {
  934.     AEKeyword    source;
  935.     DescType    actualType;
  936.     Size        actualSize;
  937.     DescType    keyword;
  938.  
  939.     if (desiredClass)
  940.     {
  941.         *desiredClass = 0;
  942.     }
  943.  
  944. /*
  945.     if (keyForm)
  946.     {
  947.         *keyForm = 0;
  948.     }
  949.  
  950.     if (keyData != nil)
  951.     {
  952.         keyData->descriptorType = typeNull;
  953.         keyData->dataHandle        = nil;
  954.     }
  955. */
  956.  
  957.     OSErr err = AEGetAttributeDesc(event, source = keyAEEventTargetAttr, typeWildCard, container);
  958.  
  959.     if ((err == noErr && IsObjectSpecifierOrInsertion(container))
  960.     ||     (err != errAEDescNotFound))
  961.     {
  962.         goto done;
  963.     }
  964.     
  965.     if (flags & kOSAModeDispatchToSubject)
  966.     {
  967.         err = AEGetAttributeDesc(event, source = keySubjectAttr, typeWildCard, container);
  968.         
  969.         if (err == noErr ? IsObjectSpecifierOrInsertion(container) : err != errAEDescNotFound)
  970.         {
  971.             goto done;
  972.         }
  973.     }
  974.     
  975.     if (flags & kOSAModeDispatchToDirectObject)
  976.     {
  977.         err = AEGetParamDesc(event, source = keyDirectObject, typeWildCard, container);
  978.  
  979.         if (err == noErr ? IsObjectSpecifierOrInsertion(container) : err != errAEDescNotFound)
  980.         {
  981.             goto done;
  982.         }
  983.     }
  984.     
  985.     err = AEGetParamDesc(event, source = keyAEInsertHere, typeWildCard, container);
  986.  
  987.     if (err == noErr ? IsObjectSpecifierOrInsertion(container) : err != errAEDescNotFound)
  988.     {
  989.         goto done;
  990.     }
  991.     
  992.     err = AEGetParamDesc(event, source = keyDirectObject, typeWildCard, container);
  993.     
  994.     // there's a system coerction handler for typeFSS -> typeObjectSpecifier!!
  995.     // (so we have to do it the hard way)
  996.  
  997.     if (err == noErr ? (IsObjectSpecifierOrInsertion(container)) : err != errAEDescNotFound)
  998.     {
  999.         goto done;
  1000.     }
  1001.  
  1002.     // Try the subject attribute (innermost tell block from AppleScript)
  1003.         
  1004.     err = AEGetAttributeDesc(event, source = keySubjectAttr, typeWildCard, container);
  1005.  
  1006.     if (err == noErr ? IsObjectSpecifierOrInsertion(container) : err != errAEDescNotFound)
  1007.     {
  1008.         goto done;
  1009.     }
  1010.     
  1011.     source = 0;
  1012.  
  1013. done:
  1014.     
  1015.     // now, do some post processing
  1016.  
  1017.     if (err == noErr || err == errAEDescNotFound)
  1018.     {
  1019.         if (source == 0 || source == keySubjectAttr)
  1020.         {
  1021.             // AppleScript forgets to put a keyAEInsertHere into create events whose
  1022.             // target is implied by a tell block, so we need to clean up after it
  1023.         
  1024.             if (AEGetAttributePtr(event, keyEventClassAttr, typeType, &actualType, &keyword, sizeof(keyword), &actualSize) == noErr
  1025.             &&    keyword == kAECoreSuite
  1026.             &&    AEGetAttributePtr(event, keyEventIDAttr, typeType, &actualType, &keyword, sizeof(keyword), &actualSize) == noErr
  1027.             &&    keyword == kAECreateElement)
  1028.             {
  1029.                 err        = noErr;
  1030.                 source    = keyAEInsertHere;
  1031.             }
  1032.         }
  1033.     }
  1034.  
  1035.     if (err == noErr)
  1036.     {
  1037.         // see if we have a keyAEObjectClass paramater
  1038.     
  1039.         err = AEGetParamPtr(event, keyAEObjectClass, typeType, &actualType, &keyword, sizeof(keyword), &actualSize);
  1040.         
  1041.         if (err != noErr)
  1042.         {
  1043.             keyword = 0;
  1044.         }
  1045.         
  1046.         if (source == keyAEInsertHere)
  1047.         {
  1048.             // if the event has an insert here param, we're going to dispatch to its container
  1049.  
  1050.             switch (err)
  1051.             {
  1052.             case errAEDescNotFound:
  1053.                 if (desiredClass != nil)    // if we've looking for a desired class and there was no keyAEObjectClass
  1054.                 {                            // parameter then see if the DO is an object specifier
  1055.                     err = AESizeOfParam(event, keyDirectObject, &actualType, &actualSize);
  1056.                     
  1057.                     if (err == noErr) switch (actualType)
  1058.                     {
  1059.                     case typeNull:                    // ObjSpec for the application
  1060.                     case typeAEList:                // Blow off common type for the moment
  1061.                         *desiredClass = actualType;
  1062.                         break;
  1063.                         
  1064.                     case typeObjectSpecifier:
  1065.                         {
  1066.                             AEDesc directObject;
  1067.                             
  1068.                             err = AEGetParamDesc(event, keyDirectObject, typeAERecord, &directObject);
  1069.                             
  1070.                             if (err == noErr)
  1071.                             {
  1072.                                 err = AEGetParamPtr(&directObject,
  1073.                                                     keyAEDesiredClass,
  1074.                                                     typeType,
  1075.                                                     &actualType,
  1076.                                                     &keyword,
  1077.                                                     sizeof(keyword),
  1078.                                                     &actualSize);
  1079.                             
  1080.                                 if (err != noErr)
  1081.                                 {
  1082.                                     keyword = 0;
  1083.                                 }
  1084.                             
  1085.                                 AEDisposeDesc(&directObject);
  1086.                             }
  1087.                         }
  1088.                     }
  1089.                 }
  1090.             case noErr:
  1091.                 if (desiredClass != nil)
  1092.                 {
  1093.                     *desiredClass = keyword;
  1094.                 }
  1095. //                err = AEParseInsertionLocation(container, container, keyForm, keyData, err == noErr ? nil : desiredClass);
  1096.             
  1097.                 err = noErr;
  1098.             }
  1099.         }
  1100.         else
  1101.         {
  1102.             err = noErr;
  1103. //            err = AEParseObjectSpecifier(container, containerClass, nil, nil, nil);
  1104.         }
  1105.         
  1106.         if (err == errAENotAnObjSpec)
  1107.         {
  1108.             err = errAEDescNotFound;
  1109.         }
  1110.     }
  1111.     
  1112.     if (psource) *psource = err ? 0 : source;    // report where we found it
  1113.  
  1114.     return err;
  1115. }
  1116.  
  1117. //------------------------------------------------------------------------------
  1118.  
  1119. pascal OSErr AECopyParams(const AERecord *src, AERecord *dst, Boolean overwrite)
  1120. {
  1121.     long         srccount;
  1122.     long         dstcount;
  1123.     OSErr        err;
  1124.     AERecord    temp;
  1125.  
  1126.     DescType    dsttype = dst->descriptorType;
  1127.     
  1128.     temp.dataHandle = nil;
  1129.  
  1130.     // pre-process destination
  1131.  
  1132.     switch (dsttype)
  1133.     {
  1134.     case typeNull:                    // accept typeNull as an empty list
  1135.         dstcount = 0;
  1136.         err         = noErr;
  1137.         break;
  1138.  
  1139.     default:                        // try to coerce input to record
  1140.         err = AECoerceDesc(dst, typeAERecord, &temp);
  1141.         if (err == noErr)
  1142.         {
  1143.             *dst = temp;
  1144.             temp.dataHandle = nil;
  1145.         }
  1146.         else
  1147.         {
  1148.             break;
  1149.         }
  1150.     case typeAERecord:                // known record types
  1151.     case typeAppleEvent:
  1152.         err = AECountItems(dst, &dstcount);
  1153.         break;
  1154.  
  1155.     }
  1156.  
  1157.     // pre-process destination
  1158.  
  1159.     if (err == noErr) switch (src->descriptorType)
  1160.     {
  1161.     case typeNull:                    // accept typeNull as an empty list
  1162.         srccount    = 0;
  1163.         err        = noErr;
  1164.         break;
  1165.  
  1166.     default:                        // try to coerce input to record
  1167.         err = AECoerceDesc(src, typeAERecord, &temp);
  1168.         if (err == noErr)
  1169.         {
  1170.             src = &temp;
  1171.         }
  1172.         else
  1173.         {
  1174.             break;
  1175.         }
  1176.     case typeAERecord:                // known record types
  1177.     case typeAppleEvent:
  1178.         err = AECountItems(src, &srccount);
  1179.         break;
  1180.  
  1181.     }
  1182.  
  1183.     if (err == noErr)
  1184.     {
  1185.         if (dsttype == typeNull)
  1186.         {
  1187.             // Do NOT do this optimization on AppleEvent's
  1188.         
  1189.             // dst is either a null descriptor or an empty record, so we can
  1190.             // just return a copy of the input
  1191.             
  1192.             /*        
  1193.             if (srccount > 0 && dst->descriptorType != typeNull)
  1194.             {
  1195.                 // dispose of empty list unless we're returning an empty list
  1196.             
  1197.                 err = AEDisposeDesc(dst);
  1198.             }
  1199.             */
  1200.  
  1201.             if (srccount == 0)
  1202.             {
  1203.                 // Create an empty record (if we don't have one already)
  1204.             
  1205.                 if (dst->descriptorType == typeNull)
  1206.                 {
  1207.                     err = AECreateList(nil, 0, true, dst);
  1208.                 }
  1209.             }
  1210.             else if (src == &temp)
  1211.             {
  1212.                 // src is a temporary copy, just return it
  1213.             
  1214.                 *dst = temp;
  1215.                 temp.dataHandle = nil;
  1216.             }
  1217.             else
  1218.             {
  1219.                 // return a copy of the input
  1220.             
  1221.                 err = TempAEDuplicateDesc(src, dst);
  1222.             }
  1223.         }
  1224.         else
  1225.         {
  1226.             for (long i = 1; err == noErr && i <= srccount; i++)
  1227.             {
  1228.                 AEKeyword    keyword;
  1229.                 AEDesc        desc;
  1230.             
  1231.                 err = AEGetNthDesc(src, i, typeWildCard, &keyword, &desc);
  1232.                 
  1233.                 if (err == noErr)
  1234.                 {
  1235.                     DescType    typeCode;
  1236.                     Size        dataSize;
  1237.                     
  1238.                     if (!overwrite)
  1239.                     {
  1240.                         err = AESizeOfParam(dst, keyword, &typeCode, &dataSize);
  1241.                     }
  1242.                     
  1243.                     if (overwrite || err == errAEDescNotFound)
  1244.                     {
  1245.                         err = AEPutKeyDesc(dst, keyword, &desc);
  1246.                     }
  1247.  
  1248.                     AEDisposeDesc(&desc);
  1249.                 }
  1250.             }    
  1251.         }
  1252.     }
  1253.     
  1254.     if (temp.dataHandle != nil)    // clean up if needed
  1255.     {
  1256.         AEDisposeDesc(&temp);
  1257.     }
  1258.     
  1259.     return err;
  1260. }
  1261.  
  1262. //------------------------------------------------------------------------------
  1263.  
  1264. pascal long RandomInRange(long start, long end)
  1265. {
  1266.     unsigned long rand = (unsigned short) Random()
  1267.                         + (((unsigned long) (unsigned short) Random()) << 16);
  1268.  
  1269.     return (((long long) (end - start + 1) * rand) >> 32) + start;
  1270. }
  1271.  
  1272. //------------------------------------------------------------------------------
  1273.  
  1274. #pragma mark -
  1275.     
  1276. OSErr    AEBuildEventToSelf(
  1277.     AppleEvent*        event,
  1278.     AEEventClass    theAEEventClass,
  1279.     AEEventID        theAEEventID,
  1280.     char*             format, ...)
  1281. {
  1282.     OSErr result;
  1283.  
  1284.     if (format != nil)
  1285.     {
  1286.         static ProcessSerialNumber kCurentProcess = { 0, kCurrentProcess };
  1287.  
  1288.         va_list ap;
  1289.         
  1290.         va_start(ap, format);
  1291.  
  1292.         result = vAEBuildAppleEvent(theAEEventClass, theAEEventID,
  1293.                             typeProcessSerialNumber, &kCurentProcess, sizeof(kCurentProcess),
  1294.                             kAutoGenerateReturnID, kAnyTransactionID, event,
  1295.                             format, ap);
  1296.         va_end(ap)
  1297.     }
  1298.     else
  1299.     {
  1300.         result = AECreateAppleEvent(theAEEventClass, theAEEventID, &gSelfAddrDesc, kAutoGenerateReturnID, kAnyTransactionID, event);
  1301.     }
  1302.     
  1303.     return result;
  1304. }
  1305.  
  1306. //------------------------------------------------------------------------------
  1307.  
  1308. OSErr    AESendEventToSelf(
  1309.     AEEventClass    theAEEventClass,
  1310.     AEEventID        theAEEventID,
  1311.     long             addition_send_flags,
  1312.     AppleEvent        *reply,
  1313.     char*             format, ...)
  1314. {
  1315.     OSErr        result;
  1316.     AppleEvent    event;
  1317.  
  1318.     if (format != nil)
  1319.     {
  1320.         va_list ap;
  1321.         
  1322.         va_start(ap, format);
  1323.  
  1324.         result = vAEBuildAppleEvent(theAEEventClass, theAEEventID,
  1325.                             typeProcessSerialNumber, &kAESelfPSN, sizeof(kAESelfPSN),
  1326.                             kAutoGenerateReturnID, kAnyTransactionID, &event,
  1327.                             format, ap);
  1328.         va_end(ap)
  1329.     }
  1330.     else
  1331.     {
  1332.         result = AECreateAppleEvent(theAEEventClass,
  1333.                                     theAEEventID,
  1334.                                     &gSelfAddrDesc,
  1335.                                     kAutoGenerateReturnID,
  1336.                                     kAnyTransactionID,
  1337.                                     &event);
  1338.     }
  1339.  
  1340. //    DebugWriteAE(&event);
  1341.  
  1342.     if (result == noErr)
  1343.     {
  1344.         AppleEvent    loc_reply;
  1345.         bool        dispose_reply = (reply == nil);
  1346.  
  1347.         AESendMode    send_mode = kAECanSwitchLayer | (dispose_reply ? kAENoReply : kAEWaitReply);
  1348.             
  1349.         if (dispose_reply)
  1350.             reply = &loc_reply;
  1351.         
  1352. //        if (record_only)
  1353. //            send_mode |= kAEDontExecute;
  1354. // JimC 980227
  1355.         send_mode |= addition_send_flags;
  1356.             
  1357.         result = AESend(&event,
  1358.                         reply,
  1359.                         send_mode,
  1360.                         kAEHighPriority,
  1361.                         kNoTimeOut,
  1362.                         gDefaultAEIdleUPP,
  1363.                         gDefaultAEFilterUPP);
  1364.  
  1365.         AEDisposeDesc(&event);
  1366.         
  1367.         if (dispose_reply)
  1368.             AEDisposeDesc(reply);
  1369.     }
  1370.     
  1371.     return result;
  1372. }
  1373.  
  1374. //------------------------------------------------------------------------------
  1375.  
  1376. OSErr    AECreateEventToSelf(
  1377.     AEEventClass    theAEEventClass,
  1378.     AEEventID         theAEEventID,
  1379.     AppleEvent*        event,
  1380.     const AEDesc*    target)
  1381. {
  1382.     OSErr    err = AECreateAppleEvent(theAEEventClass,
  1383.                                      theAEEventID,
  1384.                                      &gSelfAddrDesc,
  1385.                                      kAutoGenerateReturnID,
  1386.                                      kAnyTransactionID,
  1387.                                      event);
  1388.     
  1389.     if ((err == noErr) && (target != nil))
  1390.         err = AEPutParamDesc(event, keyDirectObject, target);
  1391.         
  1392.     return err;
  1393. }
  1394.  
  1395. //------------------------------------------------------------------------------
  1396.  
  1397.