home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Messaging / OSL / OSLClAcc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  13.9 KB  |  486 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        OSLClAcc.c (Orignal name: OSLCallAccessor.c)
  3.  
  4.     Contains:    
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1992 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <7>     6/28/95    eeh        1262143: dispose swap token
  13.          <6>     5/12/95    NP        1246047: OSL doesn't dispose tokens
  14.                                     correctly when swapping.
  15.          <5>     3/13/95    NP        1226003: Remove GetContainingFrame from the
  16.                                     API. Don't null out user token.
  17.          <4>     2/22/95    eeh        1222904: fix use of SetCurrentContext
  18.          <3>      2/8/95    NP        1218550: Don't allocate OSLContexts
  19.                                     dynamically.
  20.          <2>     8/19/94    NP        1181622: Ownership fix.
  21.         <17>      5/2/94    eeh        bug #1160654: various PPC native changes
  22.         <16>      2/7/94    NP        Tiger Team doings.
  23.         <15>    11/30/93    NP        Added error checking.
  24.         <14>    11/18/93    JA        Made RecursiveCallObjectAccessor static
  25.                                     (prevents missing-prototype error in THINK)
  26.         <13>     11/2/93    NP        Moved back pascal keyword for MPW C.
  27.         <12>     11/2/93    NP        Move pascal keyword.
  28.         <11>    10/28/93    NP        Fixed bug where switching contexts could
  29.                                     only be done once. Is now a recursive
  30.                                     routine.
  31.         <10>    10/22/93    NP        Removed obsolete context parameter from
  32.                                     some functions.
  33.          <9>    10/18/93    NP        Added #pragma unused statements.
  34.          <8>    10/11/93    NP        Added DebugStr.
  35.          <7>     9/10/93    NP        Fixed some bugs.
  36.          <6>      9/3/93    NP        Use "switch" constant instead of
  37.                                     hard-coded.
  38.          <5>     8/18/93    NP        Implemented for new context scheme.
  39.          <4>     8/16/93    NP        Adjusted for latest OSL proposal.
  40.          <3>     7/28/93    NP        Mods for new token type, OSLToken.
  41.          <2>     7/21/93    NP        Fixed #includes.
  42.          <1>     7/21/93    NP        first checked in
  43.  
  44.     To Do:
  45. */
  46.  
  47. #include <Errors.h>
  48.  
  49. #ifndef _OSLPRIV_
  50. #include "OSLPriv.h"
  51. #endif
  52.  
  53. #ifndef _CNTXTOSL_
  54. #include "CntxtOSL.h"
  55. #endif
  56.  
  57. #ifndef _OSLTOKEN_
  58. #include "OSLToken.h"
  59. #endif
  60.  
  61. #pragma segment AEObjSuppt
  62.  
  63. pascal OSErr 
  64. iAERemoveObjectAccessor(    DescType        desiredClass ,
  65.                             DescType        containerType ,
  66.                             OSLAccessorUPP    handler ,
  67.                             Boolean            isSysHandler);
  68.  
  69.  
  70. // GetTableInfo()
  71. // find the handler and refcon for the corresponding key, wildcard is used
  72. // This is lifted directly from Ed's AEHandlerTable.inc1.p
  73. // NOTE: <eeh> this duplicates a function in the AEM.  When we fold this into AEM
  74. // we need to take it out.
  75.  
  76. static Boolean
  77. GetTableInfo(     HHand theTable ,                 //--> handle to table
  78.                   OSType key1, OSType key2 ,     // --> search these keys
  79.                 ObjectAccessorValue* theHandlerRec )  // <-- return this ProcPtr record }
  80. {
  81.     ObjectAccessorKey theKeyRec ;
  82.  
  83.     Boolean result = true ;
  84.     theKeyRec.firstKey = key1;
  85.     theKeyRec.secondKey = key2;
  86.  
  87.     if ( AEGetKeyValue( theTable, NULL, (KeyPtr)&theKeyRec,
  88.             (HEntryPtr)theHandlerRec ) != noErr )
  89.     {
  90.         theKeyRec.firstKey = typeWildCard ;
  91.         if ( AEGetKeyValue( theTable, NULL, (KeyPtr)&theKeyRec, 
  92.             (HEntryPtr)theHandlerRec) != noErr )
  93.         {
  94.             theKeyRec.firstKey = key1;
  95.             theKeyRec.secondKey = typeWildCard;
  96.             if ( AEGetKeyValue( theTable, NULL, (KeyPtr)&theKeyRec, 
  97.                     (HEntryPtr)theHandlerRec) != noErr )
  98.             {
  99.                 theKeyRec.firstKey = typeWildCard;
  100.                 result = AEGetKeyValue( theTable, NULL, (KeyPtr)&theKeyRec, 
  101.                     (HEntryPtr)theHandlerRec) == noErr ;
  102.             }
  103.         }
  104.     }
  105.     return result ;
  106. }
  107.  
  108. // Recursively build a new range descriptor whose ccnt containers have been
  109. // replaced by the token container
  110.  
  111. static OSErr
  112. DoSubst( AEDesc *theObj, ContainedTokenRecord *tokenRec,
  113.         DescType containerClass, OSLToken dContainerToken ) //recurse until reach bottom }
  114. {
  115.     AERecord dObjRecord ;
  116.     AEDesc dTheContainer ;
  117.     OSErr err;
  118.  
  119.     if ( theObj->descriptorType == typeObjectSpecifier )    
  120.     {
  121.         err = AECoerceDesc( theObj, typeAERecord, &dObjRecord ) ;
  122.         IgnoreOSErr( AEDisposeDesc( theObj ) ) ;
  123.         if ( err != noErr ) goto L100 ;
  124.  
  125.         err = AEGetKeyDesc( &dObjRecord, keyAEContainer, typeWildCard,
  126.                 &dTheContainer ) ;
  127.         if ( err != noErr ) goto L200 ;
  128.  
  129.         err = DoSubst( &dTheContainer, tokenRec, containerClass,
  130.                 dContainerToken ) ;
  131.         if ( err != noErr ) goto L200 ;
  132.  
  133.         err = AEPutKeyDesc( &dObjRecord, keyAEContainer, &dTheContainer ) ;
  134.         if ( err != noErr ) goto L300 ;
  135.  
  136.         err = AECoerceDesc( &dObjRecord, typeObjectSpecifier, theObj ) ;
  137.  
  138. L300:
  139.         IgnoreOSErr( AEDisposeDesc( &dTheContainer ) ) ;
  140. L200:
  141.         IgnoreOSErr( AEDisposeDesc( &dObjRecord ) ) ;
  142.     }
  143.     else if ( theObj->descriptorType == typeCurrentContainer )
  144.     {
  145.         IgnoreOSErr( AEDisposeDesc( theObj ) ) ;
  146.         tokenRec->tokenClass = containerClass ;
  147.         tokenRec->token = dContainerToken ;
  148.         err = AECreateDesc( typeToken, (Ptr)tokenRec, sizeof( *tokenRec ),
  149.             theObj ) ;
  150.     }
  151.     else
  152.         err = noErr ;
  153. L100:
  154.     return err ;
  155. }
  156.  
  157.  
  158. static OSErr
  159. SubstContainerForccnt( OSLToken dContainerToken, DescType containerClass,
  160.     AEDesc *rangeDesc )
  161. {
  162.     AEDesc obj, dRangeRecord ;
  163.     OSErr err ;
  164.     ContainedTokenRecord tokenRec ;
  165.         
  166.  
  167.     err = AECoerceDesc( rangeDesc, typeAERecord, &dRangeRecord ) ;
  168.     if ( err != noErr ) goto L100 ;
  169.  
  170. //        IgnoreOSErr( AEDisposeDesc( rangeSelData ) ) ;        { don't dispose: this is just a local copy }
  171.  
  172.     err = AEGetKeyDesc( &dRangeRecord, keyAERangeStart, typeWildCard, &obj ) ;
  173.     if ( err != noErr ) goto L200 ;
  174.         
  175.     err = DoSubst( &obj, &tokenRec, containerClass, dContainerToken ) ;
  176.     if ( err != noErr ) goto L200 ;
  177.  
  178.     err = AEPutKeyDesc( &dRangeRecord, keyAERangeStart, &obj ) ;
  179.     IgnoreOSErr( AEDisposeDesc( &obj ) ) ;
  180.     if ( err != noErr ) goto L200 ;
  181.  
  182.  
  183.  
  184.     err = AEGetKeyDesc( &dRangeRecord, keyAERangeStop, typeWildCard, &obj ) ;
  185.     if ( err != noErr ) goto L200 ;
  186.  
  187.     err = DoSubst( &obj, &tokenRec, containerClass, dContainerToken ) ;
  188.     if ( err != noErr ) goto L200 ;
  189.  
  190.     err = AEPutKeyDesc( &dRangeRecord, keyAERangeStop, &obj ) ;
  191.     IgnoreOSErr( AEDisposeDesc( &obj ) ) ;
  192.     if ( err != noErr ) goto L200 ;
  193.  
  194.     err = AECoerceDesc( &dRangeRecord, typeRangeDescriptor, rangeDesc ) ;
  195. L200:
  196.     IgnoreOSErr( AEDisposeDesc( &dRangeRecord ) ) ;
  197. L100:
  198.     return err ;
  199. }
  200.  
  201.  
  202.  
  203.     /*———————————————————————— TryAccessor ————————————————————————*/
  204.  
  205. static OSErr
  206. TryAccessor( GlobalRecHandle aGlobalRef, Boolean *iFoundIt,
  207.         OSLToken  container, DescType  wantType, AEDesc selectionData,
  208.         DescType  containerClass, DescType form, OSLToken *value ) 
  209. {
  210.     OSErr                 err ;
  211.     ObjectAccessorValue theValue ;
  212.  
  213.     err = errAEEventNotHandled ;
  214.     if ( aGlobalRef != NULL )
  215. //    WITH aGlobalRef** DO
  216.     {
  217.         GlobalRecPointer gp = *aGlobalRef ;
  218.         if ( GetTableInfo( gp->accessorHashTable, wantType,
  219.             container.descriptorType, &theValue ) )
  220.             {
  221.             // <eeh> need to check for NULL if  don't check for NULL
  222.             // when installing
  223.                 err = CallOSLAccessorProc( theValue.handler, wantType,
  224.                         &container, containerClass, form, &selectionData,
  225.                         value, theValue.handlerRefcon ) ;
  226.                 *iFoundIt = true ;
  227.             }
  228.         }
  229.     return err ;
  230. } // TryAccessor
  231.  
  232.     /*———————————————————— RecursiveCallObjectAccessor ——————————————————————*/
  233.  
  234. static
  235. OSErr RecursiveCallObjectAccessor( DescType  wantType , OSLToken  container ,
  236.         DescType  containerClass , DescType form,
  237.          AEDesc selectionData , OSLToken *value, Boolean* iFoundIt,
  238.         OSLContext* curContext )
  239. {
  240.     OSLContext    afterContext;
  241.     OSErr        err = noErr;
  242.  
  243.     err = (*(ObjectAccessorCaller)(*curContext->getCallerProc)
  244.             (kObjectAccessor))
  245.             (wantType, &container, containerClass, form, &selectionData, value,
  246.                 iFoundIt, curContext->refCon);
  247.     // CONTEXT CHANGED?
  248.     if (value->descriptorType == kSwitchDescType && (err == noErr))
  249.     {
  250.         // DISPOSE OLD CONTAINER TOKEN????
  251.         err = OSLGetTokenContext(value, &afterContext);
  252.         if (err)
  253.             return err;
  254.         err = SetCurrentContext(&afterContext);
  255.         if (err)
  256.             return err;
  257.  
  258.         // this will leak if not disposed now; it's done its job.
  259.         iAEDisposeToken( value );
  260.  
  261.         // DISPOSE TOKEN???? PROBABLY.
  262.         containerClass = typeNull;
  263. //        THIS LINE BELOW DOESN'T SEEM TO WORK. THE DESCRIPTOR WILL GET DISPOSED
  264. //        TWICE. ONCE HERE AND ONCE IN INTERNALRESOLVE (LOOK FOR DISPOSAL OF
  265. //        dContainerToken.)
  266. //        iAEDisposeToken(&container);
  267.         MakeNullToken(&container);
  268.         err = RecursiveCallObjectAccessor(wantType, container, containerClass,
  269.                                             form, selectionData, value,
  270.                                             iFoundIt, &afterContext);
  271.     }
  272.     return err;
  273. } /* RecursiveCallObjectAccessor */
  274.  
  275.     /*———————————————————————— iCallAccessor ————————————————————————*/
  276.  
  277. pascal OSErr
  278. iCallAccessor( DescType  wantType , OSLToken  container ,
  279.         DescType  containerClass , DescType form,
  280.          AEDesc selectionData , OSLToken *value )
  281. {
  282.  
  283.     OSErr                  err ;
  284.     long                  nElements ;
  285.     OSLContext            curContext;
  286.  
  287.     // 5/13 This guy allows to distinguish between an access||NotFound
  288.     // error and the case where there was an access|| but it returned
  289.     //eventNotHandled (as when it decides it _does_ want me to do whoses). */
  290.  
  291.     Boolean  madeACopy, iFoundIt ;
  292.     
  293.     
  294.     err = noErr ;
  295.     iFoundIt = false ;
  296.     
  297.     // if marking not being used and container is an empty list and we're not
  298.     // looking for kAEAll of something then return error.  If we do want all
  299.     // then just return the empty list. Fixes LLD-???
  300.  
  301.     if ( container.descriptorType == typeAEList )            // type of 'list' assumes not a mark token.  Tell Mitch  
  302.     {
  303.         err = AECountItems( &container, &nElements ) ;
  304.         if ( err != noErr )
  305.         {
  306.             return err ;
  307.         }
  308.         if ( nElements == 0 )
  309.         {
  310.             if ( (form == formAbsolutePosition) 
  311.                     && (selectionData.descriptorType == typeAbsoluteOrdinal)
  312.                     && (**((DescTypeHandle)(selectionData.dataHandle)) == kAEAll) )
  313.             {
  314.                 DebugStr("\pOSLCllAcc.iCallAccessor: Creating list. Call Nick.");
  315.                 err = AECreateList( NULL, 0, false, value ) ;
  316.             }
  317.             else
  318.                 err = errAENoSuchObject ; // was errAEEmptyListContainer: fixes LLD-UPG-??? */
  319.             return err ;
  320.         }
  321.     }
  322.  
  323.     // If this is a range, then create a new range specifier in which any 
  324.     // 'ccnt' descriptors are replaced with the token representing the 
  325.     // actual container.  Do not dispose the previous range specifier.  The
  326.     // new one we create exists only as long as it takes to make this
  327.     // call.  The old one still lives in other data structures, which will
  328.     // need to be allowed to do the disposal
  329.  
  330.     if ( form == formRange )
  331.     {
  332.         FailErr( SubstContainerForccnt( container, containerClass,
  333.             &selectionData ), err, errExit ) ;
  334.         madeACopy = true ;
  335.     }
  336.     else
  337.         madeACopy = false ;
  338.  
  339.      // try the application specific dispatch first
  340. //      err = TryAccessor( GetGlobalRef(), &iFoundIt, container, wantType,
  341. //            selectionData, containerClass, form, value ) ;
  342.  
  343.     err = GetCurrentContext(&curContext);
  344.     if (!err)
  345.         err = RecursiveCallObjectAccessor(wantType, container, containerClass,
  346.                                             form, selectionData, value,
  347.                                             &iFoundIt, &curContext);
  348.  
  349.     if ( err == errAEEventNotHandled )
  350.         err = TryAccessor(GetSysGlobal(), &iFoundIt, container, wantType,
  351.                 selectionData, containerClass, form, value ) ;
  352.     if ( (err == errAEEventNotHandled) && (! iFoundIt) )
  353.         err = errAEAccessorNotFound ;
  354.  
  355.     if ( madeACopy )
  356.         IgnoreOSErr( AEDisposeDesc( &selectionData ) ) ;
  357.  
  358.  
  359. FAIL_ERR_PROC(err,errExit)
  360. END_FAIL_ERR_PROC(err)
  361.     
  362. } /* iCallAccessor */
  363.  
  364. //———————————————————————— iAEGetObjectAccessor ————————————————————————
  365. pascal OSErr
  366. iAEGetObjectAccessor(    DescType            desiredClass,
  367.                         DescType            containerType,
  368.                         OSLAccessorUPP        *handler,
  369.                         long                 *handlerRefcon,
  370.                         Boolean                isSysHandler)
  371.  
  372. {
  373.     ObjectAccessorKey        key ;
  374.     ObjectAccessorValue        theValue ;
  375.     GlobalRecHandle            properGlobal ;
  376.     OSErr                    out;
  377.         
  378.     // NEED TO IMPLEMENT THIS TO CALL THROUGH CONTEXTS
  379.     DebugStr("\pOSLClAcc.iAEGetObjectAccessor: No good. Exit to shell, please.");
  380.  
  381.     out = noErr;
  382.     
  383.     if ( isSysHandler )
  384.         properGlobal = GetSysGlobal() ;
  385.     else
  386.         properGlobal = GetGlobalRef() ;
  387.         
  388.     key.firstKey = desiredClass;
  389.     key.secondKey = containerType;
  390.     
  391.     out = AEGetKeyValue( (*properGlobal)->accessorHashTable,
  392.         NULL, (KeyPtr)&key, (HEntryPtr)&theValue ) ;
  393.  
  394.     if ( out == noErr )
  395.     {
  396.         *handler = theValue.handler ;
  397.         *handlerRefcon = theValue.handlerRefcon ;
  398.     }
  399.  
  400.     return out ;        //<eeh> these hash mgr errors may require translation
  401. }
  402.  
  403.  
  404.  
  405. //———————————————————————— iAEInstallObjectAccessor ————————————————————————}
  406. pascal OSErr
  407. iAEInstallObjectAccessor(DescType            desiredClass ,
  408.                         DescType            containerType ,
  409.                         OSLAccessorUPP        handler ,
  410.                         long                handlerRefcon ,
  411.                         Boolean                isSysHandler)
  412.  
  413. {
  414.     ObjectAccessorKey    key;
  415.     ObjectAccessorValue    theValue;
  416.     GlobalRecHandle        properGlobal;
  417.         
  418.     // NEED TO IMPLEMENT THIS TO CALL THROUGH CONTEXTS
  419.     DebugStr("\pOSLClAcc.iAEInstallObjectAccessor: No good. Exit to shell, please.");
  420.  
  421.     // CHECK PASCAL CODE!!!! should "|" below be "||"? I think so.
  422.     // add check for non-nil and non-odd handler
  423.     if ( ( handler == NULL ) || ( (long)handler & 1) )     //if it's nil or odd... (this is stupid) ...fixes LLD-UPG-4 and -5 
  424.     {
  425.         return paramErr ;
  426.     }
  427.  
  428.     if ( isSysHandler )
  429.         properGlobal = GetSysGlobal() ;
  430.     else
  431.         properGlobal = GetGlobalRef() ;
  432.  
  433.     key.firstKey = desiredClass;
  434.     key.secondKey = containerType;
  435.     theValue.handler = handler;
  436.     theValue.handlerRefcon = handlerRefcon;
  437.     
  438.     // <eeh> do I need to translate this error?
  439.     return AEReplaceEntry( (*properGlobal)->accessorHashTable, NULL,
  440.             (KeyPtr)&key, (HEntryPtr)&theValue ) ;
  441. }
  442.     
  443.  
  444. //———————————————————————— iAERemoveObjectAccessor ————————————————————————
  445. pascal OSErr
  446. iAERemoveObjectAccessor(    DescType        desiredClass ,
  447.                             DescType        containerType ,
  448.                             OSLAccessorUPP    handler ,
  449.                             Boolean            isSysHandler)
  450. {
  451.     ObjectAccessorKey    key ;
  452.     ObjectAccessorValue    theValue ;
  453.     GlobalRecHandle        properGlobal ;
  454.     OSErr                out ;
  455.         
  456.     // NEED TO IMPLEMENT THIS TO CALL THROUGH CONTEXTS
  457.     DebugStr("\pOSLClAcc.iAERemoveObjectAccessor: No good. Exit to shell, please.");
  458.  
  459.     out = noErr;
  460.  
  461.     if ( isSysHandler )
  462.         properGlobal = GetSysGlobal() ;
  463.     else
  464.         properGlobal = GetGlobalRef() ;
  465.  
  466.     key.firstKey = desiredClass ;
  467.     key.secondKey = containerType ;
  468.     
  469.     out = AEGetKeyValue( (*properGlobal)->accessorHashTable,
  470.             NULL, (KeyPtr)&key, (HEntryPtr)&theValue ) ;
  471.  
  472.     // was checking both in same IF, and returning noErr though refusing 
  473.     // to install if the ptrs didn't match. 2/3 
  474.  
  475.     if ( out == noErr )            // added 3/10
  476.     {
  477.         if ( (handler != nil) && (handler != theValue.handler) )                        // fixes LLD-UPG-7 
  478.             out = errAEAccessorNotFound    ;    // changed from handlerNotFound as per LLD??? (comment) 
  479.         else // IF out = NoErr THEN
  480.             out = AERemoveKeyEntry( (*properGlobal)->accessorHashTable,
  481.                 NULL, (KeyPtr)&key) ;
  482.     }
  483.     return out ;        // <eeh> these hash mgr errors may require translation 
  484. }
  485.                                 
  486.