tkMacHLEvents.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:11k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkMacHLEvents.c --
  3.  *
  4.  * Implements high level event support for the Macintosh.  Currently, 
  5.  * the only event that really does anything is the Quit event.
  6.  *
  7.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: tkMacHLEvents.c,v 1.5 2001/08/06 18:29:41 dgp Exp $
  13.  */
  14. #include "tcl.h"
  15. #include "tclMacInt.h"
  16. #include "tkMacInt.h"
  17. #include <Aliases.h>
  18. #include <AppleEvents.h>
  19. #include <SegLoad.h>
  20. #include <ToolUtils.h>
  21. /*
  22.  * This is a Tcl_Event structure that the Quit AppleEvent handler
  23.  * uses to schedule the tkReallyKillMe function.
  24.  */
  25.  
  26. typedef struct KillEvent {
  27.     Tcl_Event header; /* Information that is standard for
  28.  * all events. */
  29.     Tcl_Interp *interp; /* Interp that was passed to the
  30.                                  * Quit AppleEvent */
  31. } KillEvent;
  32. /*
  33.  * Static functions used only in this file.
  34.  */
  35. static pascal OSErr QuitHandler _ANSI_ARGS_((AppleEvent* event,
  36. AppleEvent* reply, long refcon));
  37. static pascal OSErr OappHandler _ANSI_ARGS_((AppleEvent* event,
  38. AppleEvent* reply, long refcon));
  39. static pascal OSErr OdocHandler _ANSI_ARGS_((AppleEvent* event,
  40. AppleEvent* reply, long refcon));
  41. static pascal OSErr PrintHandler _ANSI_ARGS_((AppleEvent* event,
  42. AppleEvent* reply, long refcon));
  43. static pascal OSErr ScriptHandler _ANSI_ARGS_((AppleEvent* event,
  44. AppleEvent* reply, long refcon));
  45. static int MissedAnyParameters _ANSI_ARGS_((AppleEvent *theEvent));
  46. static int ReallyKillMe _ANSI_ARGS_((Tcl_Event *eventPtr, int flags));
  47. /*
  48.  *----------------------------------------------------------------------
  49.  *
  50.  * TkMacInitAppleEvents --
  51.  *
  52.  * Initilize the Apple Events on the Macintosh.  This registers the
  53.  * core event handlers.
  54.  *
  55.  * Results:
  56.  * None.
  57.  *
  58.  * Side effects:
  59.  * None.
  60.  *
  61.  *----------------------------------------------------------------------
  62.  */
  63. void 
  64. TkMacInitAppleEvents(
  65.     Tcl_Interp *interp) /* Interp to handle basic events. */
  66. {
  67.     OSErr err;
  68.     AEEventHandlerUPP OappHandlerUPP, OdocHandlerUPP,
  69. PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP;
  70.     /*
  71.      * Install event handlers for the core apple events.
  72.      */
  73.     QuitHandlerUPP = NewAEEventHandlerProc(QuitHandler);
  74.     err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  75.     QuitHandlerUPP, (long) interp, false);
  76.     OappHandlerUPP = NewAEEventHandlerProc(OappHandler);
  77.     err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  78.     OappHandlerUPP, (long) interp, false);
  79.     OdocHandlerUPP = NewAEEventHandlerProc(OdocHandler);
  80.     err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
  81.     OdocHandlerUPP, (long) interp, false);
  82.     PrintHandlerUPP = NewAEEventHandlerProc(PrintHandler);
  83.     err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
  84.     PrintHandlerUPP, (long) interp, false);
  85.     if (interp != NULL) {
  86. ScriptHandlerUPP = NewAEEventHandlerProc(ScriptHandler);
  87. err = AEInstallEventHandler('misc', 'dosc',
  88.     ScriptHandlerUPP, (long) interp, false);
  89.     }
  90. }
  91. /*
  92.  *----------------------------------------------------------------------
  93.  *
  94.  * TkMacDoHLEvent --
  95.  *
  96.  * Dispatch incomming highlevel events.
  97.  *
  98.  * Results:
  99.  * None.
  100.  *
  101.  * Side effects:
  102.  * Depends on the incoming event.
  103.  *
  104.  *----------------------------------------------------------------------
  105.  */
  106. void
  107. TkMacDoHLEvent(
  108.     EventRecord *theEvent)
  109. {
  110.     AEProcessAppleEvent(theEvent);
  111.     return;
  112. }
  113. /*
  114.  *----------------------------------------------------------------------
  115.  *
  116.  * QuitHandler, OappHandler, etc. --
  117.  *
  118.  * These are the core Apple event handlers.  Only the Quit event does
  119.  * anything interesting.
  120.  *
  121.  * Results:
  122.  * None.
  123.  *
  124.  * Side effects:
  125.  * None.
  126.  *
  127.  *----------------------------------------------------------------------
  128.  */
  129. static pascal OSErr
  130. QuitHandler(
  131.     AppleEvent *theAppleEvent,
  132.     AppleEvent *reply,
  133.     long handlerRefcon)
  134. {
  135.     Tcl_Interp  *interp = (Tcl_Interp *) handlerRefcon;
  136.     KillEvent *eventPtr;
  137.     
  138.     /*
  139.      * Call the exit command from the event loop, since you are not supposed
  140.      * to call ExitToShell in an Apple Event Handler.  We put this at the head
  141.      * of Tcl's event queue because this message usually comes when the Mac is
  142.      * shutting down, and we want to kill the shell as quickly as possible.
  143.      */
  144.     
  145.     eventPtr = (KillEvent *) ckalloc(sizeof(KillEvent));
  146.     eventPtr->header.proc = ReallyKillMe;
  147.     eventPtr->interp = interp;
  148.      
  149.     Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD);
  150.     return noErr;
  151. }
  152. static pascal OSErr
  153. OappHandler(
  154.     AppleEvent *theAppleEvent,
  155.     AppleEvent *reply,
  156.     long handlerRefcon)
  157. {
  158.     return noErr;
  159. }
  160. static pascal OSErr
  161. OdocHandler(
  162.     AppleEvent *theAppleEvent,
  163.     AppleEvent *reply,
  164.     long handlerRefcon)
  165. {
  166.     Tcl_Interp  *interp = (Tcl_Interp *) handlerRefcon;
  167.     AEDescList fileSpecList;
  168.     FSSpec file;
  169.     OSErr err;
  170.     DescType type;
  171.     Size actual;
  172.     long count;
  173.     AEKeyword keyword;
  174.     long index;
  175.     Tcl_DString command;
  176.     Tcl_DString pathName;
  177.     Tcl_CmdInfo dummy;
  178.     /*
  179.      * Don't bother if we don't have an interp or
  180.      * the open document procedure doesn't exist.
  181.      */
  182.     if ((interp == NULL) || 
  183.      (Tcl_GetCommandInfo(interp, "::tk::mac::OpenDocument", &dummy)) == 0) {
  184.      return noErr;
  185.     }
  186.     
  187.     /*
  188.      * If we get any errors wil retrieving our parameters
  189.      * we just return with no error.
  190.      */
  191.     err = AEGetParamDesc(theAppleEvent, keyDirectObject,
  192.     typeAEList, &fileSpecList);
  193.     if (err != noErr) {
  194. return noErr;
  195.     }
  196.     err = MissedAnyParameters(theAppleEvent);
  197.     if (err != noErr) {
  198. return noErr;
  199.     }
  200.     err = AECountItems(&fileSpecList, &count);
  201.     if (err != noErr) {
  202. return noErr;
  203.     }
  204.     Tcl_DStringInit(&command);
  205.     Tcl_DStringAppend(&command, "::tk::mac::OpenDocument", -1);
  206.     for (index = 1; index <= count; index++) {
  207. int length;
  208. Handle fullPath;
  209. err = AEGetNthPtr(&fileSpecList, index, typeFSS,
  210. &keyword, &type, (Ptr) &file, sizeof(FSSpec), &actual);
  211. if ( err != noErr ) {
  212.     continue;
  213. }
  214. err = FSpPathFromLocation(&file, &length, &fullPath);
  215. HLock(fullPath);
  216.         Tcl_ExternalToUtfDString(NULL, *fullPath, length, &pathName);
  217. HUnlock(fullPath);
  218. DisposeHandle(fullPath);
  219. Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
  220. Tcl_DStringFree(&pathName);
  221.     }
  222.     
  223.     Tcl_GlobalEval(interp, Tcl_DStringValue(&command));
  224.     Tcl_DStringFree(&command);
  225.     return noErr;
  226. }
  227. static pascal OSErr
  228. PrintHandler(
  229.     AppleEvent *theAppleEvent,
  230.     AppleEvent *reply,
  231.     long handlerRefcon)
  232. {
  233.     return noErr;
  234. }
  235. /*
  236.  *----------------------------------------------------------------------
  237.  *
  238.  * DoScriptHandler --
  239.  *
  240.  * This handler process the do script event.  
  241.  *
  242.  * Results:
  243.  * Scedules the given event to be processed.
  244.  *
  245.  * Side effects:
  246.  * None.
  247.  *
  248.  *----------------------------------------------------------------------
  249.  */
  250.  
  251. static pascal OSErr 
  252. ScriptHandler(
  253.     AppleEvent *theAppleEvent,
  254.     AppleEvent *reply,
  255.     long handlerRefcon)
  256. {
  257.     OSErr theErr;
  258.     AEDescList theDesc;
  259.     int tclErr = -1;
  260.     Tcl_Interp *interp;
  261.     char errString[128];
  262.     interp = (Tcl_Interp *) handlerRefcon;
  263.     /*
  264.      * The do script event receives one parameter that should be data or a file.
  265.      */
  266.     theErr = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard,
  267.     &theDesc);
  268.     if (theErr != noErr) {
  269. sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", theErr);
  270. theErr = AEPutParamPtr(reply, keyErrorString, typeChar, errString,
  271. strlen(errString));
  272.     } else if (MissedAnyParameters(theAppleEvent)) {
  273. sprintf(errString, "AEDoScriptHandler: extra parameters");
  274. AEPutParamPtr(reply, keyErrorString, typeChar, errString,
  275. strlen(errString));
  276. theErr = -1771;
  277.     } else {
  278. if (theDesc.descriptorType == (DescType)'TEXT') {
  279.     Tcl_DString encodedText;
  280.     short length, i;
  281.     
  282.     length = GetHandleSize(theDesc.dataHandle);
  283.     SetHandleSize(theDesc.dataHandle, length + 1);
  284.     *(*theDesc.dataHandle + length) = '';
  285.     for (i=0; i<length; i++) {
  286. if ((*theDesc.dataHandle)[i] == 'r') {
  287.     (*theDesc.dataHandle)[i] = 'n';
  288. }
  289.     }
  290.     HLock(theDesc.dataHandle);
  291.     Tcl_ExternalToUtfDString(NULL, *theDesc.dataHandle, length,
  292.     &encodedText);
  293.     tclErr = Tcl_GlobalEval(interp, Tcl_DStringValue(&encodedText));
  294.     Tcl_DStringFree(&encodedText);
  295.     HUnlock(theDesc.dataHandle);
  296. } else if (theDesc.descriptorType == (DescType)'alis') {
  297.     Boolean dummy;
  298.     FSSpec theFSS;
  299.     Handle fullPath;
  300.     int length;
  301.     
  302.     theErr = ResolveAlias(NULL, (AliasHandle)theDesc.dataHandle,
  303.     &theFSS, &dummy);
  304.     if (theErr == noErr) {
  305. FSpPathFromLocation(&theFSS, &length, &fullPath);
  306. HLock(fullPath);
  307. Tcl_EvalFile(interp, *fullPath);
  308. HUnlock(fullPath);
  309. DisposeHandle(fullPath);
  310.     } else {
  311. sprintf(errString, "AEDoScriptHandler: file not found");
  312. AEPutParamPtr(reply, keyErrorString, typeChar,
  313. errString, strlen(errString));
  314.     }
  315. } else {
  316.     sprintf(errString,
  317.     "AEDoScriptHandler: invalid script type '%-4.4s', must be 'alis' or 'TEXT'",
  318.     &theDesc.descriptorType);
  319.     AEPutParamPtr(reply, keyErrorString, typeChar,
  320.     errString, strlen(errString));
  321.     theErr = -1770;
  322. }
  323.     }
  324.     /*
  325.      * If we actually go to run Tcl code - put the result in the reply.
  326.      */
  327.     if (tclErr >= 0) {
  328. if (tclErr == TCL_OK)  {
  329.     AEPutParamPtr(reply, keyDirectObject, typeChar,
  330. Tcl_GetStringResult(interp),
  331. strlen(Tcl_GetStringResult(interp)));
  332. } else {
  333.     AEPutParamPtr(reply, keyErrorString, typeChar,
  334. Tcl_GetStringResult(interp),
  335. strlen(Tcl_GetStringResult(interp)));
  336.     AEPutParamPtr(reply, keyErrorNumber, typeInteger,
  337. (Ptr) &tclErr, sizeof(int));
  338. }
  339.     }
  340.     AEDisposeDesc(&theDesc);
  341.     return theErr;
  342. }
  343. /*
  344.  *----------------------------------------------------------------------
  345.  *
  346.  * ReallyKillMe --
  347.  *
  348.  * This proc tries to kill the shell by running exit, and if that 
  349.  *      has not succeeded (e.g. because someone has renamed the exit 
  350.  *      command), calls Tcl_Exit to really kill the shell.  Called from 
  351.  *      an event scheduled by the "Quit" AppleEvent handler.
  352.  *
  353.  * Results:
  354.  * Kills the shell.
  355.  *
  356.  * Side effects:
  357.  * None.
  358.  *
  359.  *----------------------------------------------------------------------
  360.  */
  361. int 
  362. ReallyKillMe(Tcl_Event *eventPtr, int flags) 
  363. {
  364.     Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp;
  365.     if (interp != NULL) {
  366.         Tcl_GlobalEval(interp, "exit");
  367.     }
  368.     Tcl_Exit(0);
  369.     
  370.     return 1;
  371. }
  372. /*
  373.  *----------------------------------------------------------------------
  374.  *
  375.  * MissedAnyParameters --
  376.  *
  377.  * Checks to see if parameters are still left in the event.  
  378.  *
  379.  * Results:
  380.  * True or false.
  381.  *
  382.  * Side effects:
  383.  * None.
  384.  *
  385.  *----------------------------------------------------------------------
  386.  */
  387.  
  388. static int 
  389. MissedAnyParameters(
  390.     AppleEvent *theEvent)
  391. {
  392.    DescType returnedType;
  393.    Size actualSize;
  394.    OSErr err;
  395.    err = AEGetAttributePtr(theEvent, keyMissedKeywordAttr, typeWildCard, 
  396.     &returnedType, NULL, 0, &actualSize);
  397.    
  398.    return (err != errAEDescNotFound);
  399. }