375 lines
9.2 KiB
C
375 lines
9.2 KiB
C
|
/*
|
|||
|
* tkMacHLEvents.c --
|
|||
|
*
|
|||
|
* Implements high level event support for the Macintosh. Currently,
|
|||
|
* the only event that really does anything is the Quit event.
|
|||
|
*
|
|||
|
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
|
|||
|
*
|
|||
|
* See the file "license.terms" for information on usage and redistribution
|
|||
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|||
|
*
|
|||
|
* SCCS: @(#) tkMacHLEvents.c 1.15 96/09/05 11:21:33
|
|||
|
*/
|
|||
|
|
|||
|
#include "tcl.h"
|
|||
|
#include "tclMacInt.h"
|
|||
|
#include "tkMacInt.h"
|
|||
|
|
|||
|
#include <Aliases.h>
|
|||
|
#include <AppleEvents.h>
|
|||
|
#include <SegLoad.h>
|
|||
|
#include <ToolUtils.h>
|
|||
|
|
|||
|
static pascal OSErr QuitHandler _ANSI_ARGS_((AppleEvent* event,
|
|||
|
AppleEvent* reply, long refcon));
|
|||
|
static pascal OSErr OappHandler _ANSI_ARGS_((AppleEvent* event,
|
|||
|
AppleEvent* reply, long refcon));
|
|||
|
static pascal OSErr OdocHandler _ANSI_ARGS_((AppleEvent* event,
|
|||
|
AppleEvent* reply, long refcon));
|
|||
|
static pascal OSErr PrintHandler _ANSI_ARGS_((AppleEvent* event,
|
|||
|
AppleEvent* reply, long refcon));
|
|||
|
static pascal OSErr ScriptHandler _ANSI_ARGS_((AppleEvent* event,
|
|||
|
AppleEvent* reply, long refcon));
|
|||
|
static int MissedAnyParameters _ANSI_ARGS_((AppleEvent *theEvent));
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* TkMacInitAppleEvents --
|
|||
|
*
|
|||
|
* Initilize the Apple Events on the Macintosh. This registers the
|
|||
|
* core event handlers.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
TkMacInitAppleEvents(interp)
|
|||
|
Tcl_Interp *interp;
|
|||
|
{
|
|||
|
OSErr err;
|
|||
|
AEEventHandlerUPP OappHandlerUPP, OdocHandlerUPP,
|
|||
|
PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP;
|
|||
|
|
|||
|
/* Install event handlers for the core apple events. */
|
|||
|
QuitHandlerUPP = NewAEEventHandlerProc(QuitHandler);
|
|||
|
err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
|
|||
|
QuitHandlerUPP, (long) interp, false);
|
|||
|
|
|||
|
OappHandlerUPP = NewAEEventHandlerProc(OappHandler);
|
|||
|
err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
|
|||
|
OappHandlerUPP, (long) interp, false);
|
|||
|
|
|||
|
OdocHandlerUPP = NewAEEventHandlerProc(OdocHandler);
|
|||
|
err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
|
|||
|
OdocHandlerUPP, (long) interp, false);
|
|||
|
|
|||
|
PrintHandlerUPP = NewAEEventHandlerProc(PrintHandler);
|
|||
|
err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
|
|||
|
PrintHandlerUPP, (long) interp, false);
|
|||
|
|
|||
|
if (interp != NULL) {
|
|||
|
ScriptHandlerUPP = NewAEEventHandlerProc(ScriptHandler);
|
|||
|
err = AEInstallEventHandler('misc', 'dosc',
|
|||
|
ScriptHandlerUPP, (long) interp, false);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* TkMacDoHLEvent --
|
|||
|
*
|
|||
|
* Dispatch incomming highlevel events.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* Depends on the incoming event.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
TkMacDoHLEvent(theEvent)
|
|||
|
EventRecord *theEvent;
|
|||
|
{
|
|||
|
AEProcessAppleEvent(theEvent);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* QuitHandler, OappHandler, etc. --
|
|||
|
*
|
|||
|
* These are the core Apple event handlers. Only the Quit event does
|
|||
|
* anything interesting.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
static pascal OSErr
|
|||
|
QuitHandler(theAppleEvent, reply, handlerRefcon)
|
|||
|
AppleEvent *theAppleEvent;
|
|||
|
AppleEvent *reply;
|
|||
|
long handlerRefcon;
|
|||
|
{
|
|||
|
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
|
|||
|
|
|||
|
/*
|
|||
|
* Call the exit command. However, if it doesn't quit - quit anyway.
|
|||
|
*/
|
|||
|
if (interp != NULL) {
|
|||
|
Tcl_GlobalEval(interp, "exit");
|
|||
|
}
|
|||
|
Tcl_Exit(0);
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
static pascal OSErr
|
|||
|
OappHandler(theAppleEvent, reply, handlerRefcon)
|
|||
|
AppleEvent *theAppleEvent;
|
|||
|
AppleEvent *reply;
|
|||
|
long handlerRefcon;
|
|||
|
{
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
static pascal OSErr
|
|||
|
OdocHandler(theAppleEvent, reply, handlerRefcon)
|
|||
|
AppleEvent *theAppleEvent;
|
|||
|
AppleEvent *reply;
|
|||
|
long handlerRefcon;
|
|||
|
{
|
|||
|
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
|
|||
|
AEDescList fileSpecList;
|
|||
|
FSSpec file;
|
|||
|
OSErr err;
|
|||
|
DescType type;
|
|||
|
Size actual;
|
|||
|
long count;
|
|||
|
AEKeyword keyword;
|
|||
|
long index;
|
|||
|
Tcl_DString command;
|
|||
|
Tcl_DString pathName;
|
|||
|
Tcl_CmdInfo dummy;
|
|||
|
|
|||
|
/*
|
|||
|
* Don't bother if we don't have an interp or
|
|||
|
* the open document procedure doesn't exist.
|
|||
|
*/
|
|||
|
if ((interp == NULL) ||
|
|||
|
(Tcl_GetCommandInfo(interp, "tkOpenDocument", &dummy)) == 0) {
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* If we get any errors wil retrieving our parameters
|
|||
|
* we just return with no error.
|
|||
|
*/
|
|||
|
err = AEGetParamDesc(theAppleEvent, keyDirectObject,
|
|||
|
typeAEList, &fileSpecList);
|
|||
|
if (err != noErr) {
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
err = MissedAnyParameters(theAppleEvent);
|
|||
|
if (err != noErr) {
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
err = AECountItems(&fileSpecList, &count);
|
|||
|
if (err != noErr) {
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
Tcl_DStringInit(&command);
|
|||
|
Tcl_DStringInit(&pathName);
|
|||
|
Tcl_DStringAppend(&command, "tkOpenDocument", -1);
|
|||
|
for (index = 1; index <= count; index++) {
|
|||
|
int length;
|
|||
|
Handle fullPath;
|
|||
|
|
|||
|
Tcl_DStringSetLength(&pathName, 0);
|
|||
|
err = AEGetNthPtr(&fileSpecList, index, typeFSS,
|
|||
|
&keyword, &type, (Ptr) &file, sizeof(FSSpec), &actual);
|
|||
|
if ( err != noErr ) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
err = FSpPathFromLocation(&file, &length, &fullPath);
|
|||
|
HLock(fullPath);
|
|||
|
Tcl_DStringAppend(&pathName, *fullPath, length);
|
|||
|
HUnlock(fullPath);
|
|||
|
DisposeHandle(fullPath);
|
|||
|
|
|||
|
Tcl_DStringAppendElement(&command, pathName.string);
|
|||
|
}
|
|||
|
|
|||
|
Tcl_GlobalEval(interp, command.string);
|
|||
|
|
|||
|
Tcl_DStringFree(&command);
|
|||
|
Tcl_DStringFree(&pathName);
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
static pascal OSErr
|
|||
|
PrintHandler(theAppleEvent, reply, handlerRefcon)
|
|||
|
AppleEvent *theAppleEvent;
|
|||
|
AppleEvent *reply;
|
|||
|
long handlerRefcon;
|
|||
|
{
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* DoScriptHandler --
|
|||
|
*
|
|||
|
* This handler process the do script event.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* Scedules the given event to be processed.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
static pascal OSErr
|
|||
|
ScriptHandler(theAppleEvent, reply, handlerRefcon)
|
|||
|
AppleEvent *theAppleEvent;
|
|||
|
AppleEvent *reply;
|
|||
|
long handlerRefcon;
|
|||
|
{
|
|||
|
OSErr theErr;
|
|||
|
AEDescList theDesc;
|
|||
|
int tclErr = -1;
|
|||
|
Tcl_Interp *interp;
|
|||
|
char errString[128];
|
|||
|
|
|||
|
interp = (Tcl_Interp *) handlerRefcon;
|
|||
|
|
|||
|
/*
|
|||
|
* The do script event receives one parameter that should be data or a file.
|
|||
|
*/
|
|||
|
theErr = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard,
|
|||
|
&theDesc);
|
|||
|
if (theErr != noErr) {
|
|||
|
sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", theErr);
|
|||
|
theErr = AEPutParamPtr(reply, keyErrorString, typeChar, errString,
|
|||
|
strlen(errString));
|
|||
|
} else if (MissedAnyParameters(theAppleEvent)) {
|
|||
|
sprintf(errString, "AEDoScriptHandler: extra parameters");
|
|||
|
AEPutParamPtr(reply, keyErrorString, typeChar, errString,
|
|||
|
strlen(errString));
|
|||
|
theErr = -1771;
|
|||
|
} else {
|
|||
|
if (theDesc.descriptorType == (DescType)'TEXT') {
|
|||
|
short length;
|
|||
|
|
|||
|
length = GetHandleSize(theDesc.dataHandle);
|
|||
|
SetHandleSize(theDesc.dataHandle, length + 1);
|
|||
|
*(*theDesc.dataHandle + length) = '\0';
|
|||
|
|
|||
|
HLock(theDesc.dataHandle);
|
|||
|
tclErr = Tcl_GlobalEval(interp, *theDesc.dataHandle);
|
|||
|
HUnlock(theDesc.dataHandle);
|
|||
|
} else if (theDesc.descriptorType == (DescType)'alis') {
|
|||
|
Boolean dummy;
|
|||
|
FSSpec theFSS;
|
|||
|
Handle fullPath;
|
|||
|
int length;
|
|||
|
|
|||
|
theErr = ResolveAlias(NULL, (AliasHandle)theDesc.dataHandle,
|
|||
|
&theFSS, &dummy);
|
|||
|
if (theErr == noErr) {
|
|||
|
FSpPathFromLocation(&theFSS, &length, &fullPath);
|
|||
|
HLock(fullPath);
|
|||
|
Tcl_EvalFile(interp, *fullPath);
|
|||
|
HUnlock(fullPath);
|
|||
|
DisposeHandle(fullPath);
|
|||
|
} else {
|
|||
|
sprintf(errString, "AEDoScriptHandler: file not found");
|
|||
|
AEPutParamPtr(reply, keyErrorString, typeChar,
|
|||
|
errString, strlen(errString));
|
|||
|
}
|
|||
|
} else {
|
|||
|
sprintf(errString,
|
|||
|
"AEDoScriptHandler: invalid script type '%-4.4s', must be 'alis' or 'TEXT'",
|
|||
|
&theDesc.descriptorType);
|
|||
|
AEPutParamPtr(reply, keyErrorString, typeChar,
|
|||
|
errString, strlen(errString));
|
|||
|
theErr = -1770;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* If we actually go to run Tcl code - put the result in the reply.
|
|||
|
*/
|
|||
|
if (tclErr >= 0) {
|
|||
|
if (tclErr == TCL_OK) {
|
|||
|
AEPutParamPtr(reply, keyDirectObject, typeChar,
|
|||
|
interp->result, strlen(interp->result));
|
|||
|
} else {
|
|||
|
AEPutParamPtr(reply, keyErrorString, typeChar,
|
|||
|
interp->result, strlen(interp->result));
|
|||
|
AEPutParamPtr(reply, keyErrorNumber, typeInteger,
|
|||
|
(Ptr) &tclErr, sizeof(int));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
AEDisposeDesc(&theDesc);
|
|||
|
|
|||
|
return theErr;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* MissedAnyParameters --
|
|||
|
*
|
|||
|
* Checks to see if parameters are still left in the event.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* True or false.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
static int
|
|||
|
MissedAnyParameters(theEvent)
|
|||
|
AppleEvent *theEvent;
|
|||
|
{
|
|||
|
DescType returnedType;
|
|||
|
Size actualSize;
|
|||
|
OSErr err;
|
|||
|
|
|||
|
err = AEGetAttributePtr(theEvent, keyMissedKeywordAttr, typeWildCard,
|
|||
|
&returnedType, NULL, 0, &actualSize);
|
|||
|
|
|||
|
return (err != errAEDescNotFound);
|
|||
|
}
|