home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Development Tools / Unsupported Tools / AE Coercion / InstallCoercions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-19  |  10.3 KB  |  204 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. *
  3. *  Apple Developer Technical Support
  4. *
  5. *  AppleEvent Coercion Handler and INIT sample
  6. *
  7. *  Program:    AECoercionINIT
  8. *  File: InstallCoercions.c -    C Source
  9. *
  10. *  by:   C.K. Haun <TR>
  11. *
  12. *  Copyright © 1991 Apple Computer, Inc.
  13. *  All rights reserved.
  14. *
  15. *------------------------------------------------------------------------------
  16. * This file contains the coercion installing routine.
  17. * This will get called by our assembly stub at INIT 31 time.
  18. * Here we get space in the System Heap for our coercions (System level coercions MUST
  19. * be in the system heap) and move the code to the sys heap, then tell the 
  20. * AppleEvent manager about the coercions.
  21. * For my BoolToChar, I also grab some resources from my INIT file, since it's
  22. * open now.
  23. * Of course, please read the section on coercion routines in Inside Mac VI, AppleEvents
  24. *------------------------------------------------------------------------------
  25. */
  26. /* our includes */
  27. #include <Types.h>
  28. #include <memory.h>
  29. #include <Resources.h>
  30. #include <toolutils.h>
  31. #include <AppleEvents.h>
  32. #include <GestaltEqu.h>
  33. #include <Errors.h>
  34. /* externs defining the coercion routines in Coercions.c */
  35. extern pascal OSErr CoerceCharToPString(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result);
  36. extern pascal OSErr CoercePStringToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result);
  37. extern pascal OSErr CoerceBooleanToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result);
  38. extern void Dummy(void);
  39. /* my special AE data type */
  40. #define typeMyPString 'MPST'    
  41. /* resource IDs for my strings */
  42. #define kFalseString 128
  43. #define kTrueString 129
  44. /* For this example, I created a typePString.  A typePString would be... */
  45. /* descriptorType = 'MPST' 
  46. dataHandle = (handle containing a Pascal-type string) */
  47.  
  48. /* A structure I use for my BoolToChar coercion */
  49. struct myBtoCData {
  50.     Handle falseString;
  51.     Handle trueString;
  52. };
  53. typedef struct myBtoCData myBtoCData, *myBtoCDataPtr, **myBtoCDataHdl;
  54.  
  55. /* This code installs all our coercion routines */
  56. /* Also, I'm checking to see if there is already a converter for this type, if there */
  57. /* is (unlikely) I do not replace it. You may want to install a hander even if */
  58. /* there is already one there, or rather you may want */
  59. /* to chain to it after you've done your work.  I would put the old coercion */
  60. /* proc pointer in the RefCon when I install my coercer, so It will always be passed */
  61. /* to me, since I'm not allocating any global storage in this example */
  62.  
  63. OSErr cInstall(void)
  64. {
  65.     OSErr myErr;
  66.     OSErr installErr;
  67.     long aLong;
  68.     Ptr functionStart, functionEnd, newLocation;
  69.     ProcPtr oldHandler;
  70.     long oldRefCon;
  71.     Boolean typeIsDesc;
  72.     myBtoCDataHdl stringData;
  73.     /* First thing we have to do is see if AppleEvents are installed on this machine */
  74.     /* if they are NOT, then we bail out fast.  Or at least at 8 Mhz */
  75.     /* unless we're on a PowerBook in slowdown mode, then it's slower.  But anyway */
  76.     /* fast enough */
  77.     myErr = Gestalt(gestaltAppleEventsAttr, &aLong);
  78.     if (!myErr) {
  79.         /* we're OK, the manager is installed */
  80.         /* install the first one.  Remember, you can pass any number in the refCon */
  81.         /* field during installs, that number will always get passed to your */
  82.         /* coercion routine.  It could be a procptr if your chaining, or it could */
  83.         /* be a handle if you want some permenent storage */
  84.         /* First check to see if there is one already, unlikely as all get out */
  85.         installErr = AEGetCoercionHandler(typeChar, typeMyPString, &oldHandler, &oldRefCon, &typeIsDesc, true);
  86.         
  87.         /* check the error.  If the handler isn't there, we'll install our own */
  88.         /* if it is there, we don't.  You may want to, if you want to add */
  89.         /* a handler where one already exsists, PLEASE keep the information  */
  90.         /* about the old one, and chain to it when you're through.  See the AEM */
  91.         /* chapter for more details */
  92.         if ((installErr == errAEHandlerNotFound)) {
  93.             /* Get a pointer for this coercion */
  94.             
  95.             functionStart = (Ptr)CoerceCharToPString;
  96.             functionEnd = (Ptr)CoercePStringToChar;
  97.             newLocation = NewPtrSys(functionEnd - functionStart);
  98.             installErr = noErr;
  99.             if (newLocation) {
  100.                 BlockMove(functionStart, newLocation, (functionEnd - functionStart));
  101.                 /* Install my handler.  Remember, you can pass any longint in the refCon */
  102.                 /* field here (I've left it nil) and that number will be passed to your coercion */
  103.                 /* routine anytime it's called.  Maybe you want to allocate a handle */
  104.                 /* and keep data in it, or something like that */
  105.                 /* see the BoolToChar coercion for an example of this */
  106.                 installErr = AEInstallCoercionHandler(typeChar, typeMyPString, (ProcPtr)newLocation, nil, false, true);
  107.             }
  108.             if (installErr)
  109.                 DisposPtr(newLocation);
  110.         }
  111.         installErr = AEGetCoercionHandler(typeMyPString, typeChar, &oldHandler, &oldRefCon, &typeIsDesc, true);
  112.         if ((installErr == errAEHandlerNotFound)) {
  113.             functionStart = (Ptr)CoercePStringToChar;
  114.             functionEnd = (Ptr)CoerceBooleanToChar;
  115.             newLocation = NewPtrSys(functionEnd - functionStart);
  116.             
  117.             installErr = noErr;
  118.             if (newLocation) {
  119.                 BlockMove(functionStart, newLocation, (functionEnd - functionStart));
  120.                 installErr = AEInstallCoercionHandler(typeMyPString, typeChar, (ProcPtr)newLocation, nil, false, true);
  121.             }
  122.             if (installErr)
  123.                 DisposPtr(newLocation);
  124.         }
  125.         
  126.         /* This one is a bit more interesting, because I need some additional resources */
  127.         /* to make it work, two text strings.  I will create a handle to hold these, */
  128.         /* and pass that handle in the refCon so I always get it when I do the coercion */
  129.         installErr = AEGetCoercionHandler(typeBoolean, typeChar, &oldHandler, &oldRefCon, &typeIsDesc, true);
  130.         if ((installErr == errAEHandlerNotFound)) {
  131.             functionStart = (Ptr)CoerceBooleanToChar;
  132.             functionEnd = (Ptr)Dummy;
  133.             newLocation = NewPtrSys(functionEnd - functionStart);
  134.             
  135.             installErr = noErr;
  136.             if (newLocation) {
  137.                 /* we got the memory for the routine, now can we get the memory for the */
  138.                 /* strings and the strings themselves??? */
  139.                 stringData = (myBtoCDataHdl)NewHandleSys(sizeof(myBtoCData));
  140.                 if (stringData) {
  141.                     
  142.                     HLock((Handle)stringData);              /* get the resources, if possible */
  143.                     /* ••• CAUTION ••• CAUTION ••• */
  144.                     /* These resources MUST be in the System heap! */
  145.                     /* I have made sure of this by marking them as "sysheap" */
  146.                     /* in their resource attributes, please see the AECoerceINIT.r file. */
  147.                     /* You can do this, or move them to the system heap after you have  */
  148.                     /* loaded them.  You MUST have them in the system heap!   */
  149.                     /* If you don't mark them as "sysheap", or don't */
  150.                     /* move them yourself, then they will be in this  */
  151.                     /* installer INIT heap, which will go away */
  152.                     /* when this INIT is finished, and the resources will also */
  153.                     /* go away! */
  154.                     /* If you want resources to stay around from an INIT, */
  155.                     /* make sure they're in the system heap!!!!! */
  156.                     (*stringData)->falseString = GetResource('STR ', kFalseString);
  157.                     if (!ResError() && (*stringData)->falseString) {
  158.                         /* remove any resource references to this handle, and  */
  159.                         /* make sure it won't get purged */
  160.                         DetachResource((*stringData)->falseString);
  161.                         HNoPurge((*stringData)->falseString);
  162.                         
  163.                         (*stringData)->trueString = GetResource('STR ', kTrueString);
  164.                         if (!ResError() && (*stringData)->trueString) {
  165.                             /* remove any resource references to this handle, and  */
  166.                             /* make sure it won't get purged */
  167.                             DetachResource((*stringData)->trueString);
  168.                             HNoPurge((*stringData)->trueString);
  169.                             /* Got our strings */
  170.                             HUnlock((Handle)stringData);
  171.                             BlockMove(functionStart, newLocation, (functionEnd - functionStart));
  172.                             installErr = AEInstallCoercionHandler(typeBoolean, typeChar, (ProcPtr)newLocation, (long)stringData,
  173.                                                                   false, true);
  174.                             if (installErr) {
  175.                                 /* Had an error installing the coercion */
  176.                                 /* kill the memory for our resources */
  177.                                 DisposHandle((*stringData)->falseString);
  178.                                 DisposHandle((*stringData)->trueString);
  179.                                 DisposHandle((Handle)stringData);
  180.                             }
  181.                         } else {
  182.                             /* Couldn't get the 'true' string, stop the process */
  183.                             /* and release the memory we had gotten */
  184.                             DisposHandle((*stringData)->falseString);
  185.                             DisposHandle((Handle)stringData);
  186.                             installErr = -9;
  187.                         }
  188.                     } else {
  189.                         /* couldn't get the false string, installation failed */
  190.                         DisposHandle((Handle)stringData);
  191.                         installErr = -9;
  192.                     }
  193.                 }
  194.             } else {
  195.                 /* string handle error */
  196.                 installErr = memFullErr;
  197.             }
  198.             if (installErr)
  199.                 DisposPtr(newLocation);
  200.         }
  201.     }
  202.     return(myErr);
  203. }
  204.