JPEGView/Source/C/AppleEventUtils.c
Aaron Giles 92bdb55672 JPEGView 3.3 for Macintosh
These are the sources for the final official release of JPEGView for the
Mac, back in 1994.
2015-02-05 00:18:10 -08:00

1 line
21 KiB
C

/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information. */
/* Contact email: mac@aarongiles.com */
/*********************************************************/
#if THINK_C
#include "THINK.Header"
#elif applec
#pragma load ":Headers:MPW.Header"
#elif __MWERKS__
//#include "MW.Header"
#else
#include "JPEGView.h"
#endif
/*
* Local structures:
* eventList, eventListPtr = structure containing event handlers to install
* objectList, objectListPtr = structure containing object accessors to install
*
*/
#if THINK_C
extern pascal OSErr AEObjectInit(void);
#endif
typedef struct
{
AEEventClass evclass;
AEEventID evid;
void *handler;
long refcon;
} eventList, *eventListPtr;
typedef struct
{
DescType evclass;
DescType container;
void *handler;
} objectList, *objectListPtr;
/*
* AppleEventInit()
*
* Purpose: Installs AppleEvent handlers for the AppleEvents we support
* Inputs: none
* Returns: nothing
*
*/
void AppleEventInit(void)
{
eventList theEventList[] =
{
{ kCoreEventClass, kAEOpenApplication, HandleOpenApplication, 0 },
{ kCoreEventClass, kAEOpenDocuments, HandleOpenDocuments, 0 },
{ kCoreEventClass, kAEPrintDocuments, HandlePrintDocuments, 0 },
{ kCoreEventClass, kAEQuitApplication, HandleQuitApplication, 0 },
{ kAECoreSuite, kAEClone, HandleClone, 0 },
{ kAECoreSuite, kAEClose, HandleClose, 0 },
{ kAECoreSuite, kAECountElements, HandleCountElements, 0 },
{ kAECoreSuite, kAECreateElement, HandleCreateElement, 0 },
{ kAECoreSuite, kAEDelete, HandleDelete, 0 },
{ kAECoreSuite, kAEDoObjectsExist, HandleDoObjectsExist, 0 },
{ kAECoreSuite, kAEGetData, HandleGetData, 0 },
{ kAECoreSuite, kAEGetDataSize, HandleGetDataSize, 0 },
{ kAECoreSuite, kAEMove, HandleMove, 0 },
{ kAECoreSuite, kAESave, HandleSave, 0 },
{ kAECoreSuite, kAESetData, HandleSetData, 0 },
{ kAEMiscStandards, kAECopy, HandleCopy, 0 },
{ kJPEGViewSuite, kAEQuantizeImage, HandleQuantize, 0 },
{ kJPEGViewSuite, kAESlideShow, HandleSlideShow, 0 },
{ 0, 0, nil, 0 }
};
objectList theObjectList[] =
{
{ cWindow, typeNull, WindowAccessor },
{ cWindow, cWindow, WindowAccessor },
{ cDocument, typeNull, DocumentAccessor },
{ cDocument, cWindow, DocumentAccessor },
{ cDocument, cDocument, DocumentAccessor },
{ cFile, cDocument, FileAccessor },
{ cFile, cFile, FileAccessor },
{ cDrawingArea, cWindow, DrawingAreaAccessor },
{ cDrawingArea, cDrawingArea, DrawingAreaAccessor },
{ cImage, cDocument, ImageAccessor },
{ cImage, cDrawingArea, ImageAccessor },
{ cImage, cImage, ImageAccessor },
{ cPixelMap, cImage, PixelMapAccessor },
{ cPixelMap, cPixelMap, PixelMapAccessor },
{ typeProperty, typeNull, AppPropertyAccessor },
{ typeProperty, cWindow, WinPropertyAccessor },
{ typeProperty, cDocument, DocPropertyAccessor },
{ typeProperty, cFile, FilePropertyAccessor },
{ typeProperty, cDrawingArea, DrawPropertyAccessor },
{ typeProperty, cImage, ImagePropertyAccessor },
{ typeProperty, cPixelMap, PixelPropertyAccessor },
{ typeProperty, cSelection, SelPropertyAccessor },
{ 0, 0, nil }
};
eventListPtr theEvent;
objectListPtr theObject;
if ((Ptr)AEObjectInit == kUnresolvedSymbolAddress) {
gFoundOSL = false;
theEventList[4].handler = nil;
}
for (theEvent = theEventList; theEvent->handler; theEvent++)
if (AEInstallEventHandler(theEvent->evclass, theEvent->evid,
NewAEEventHandlerProc((ProcPtr)theEvent->handler),
theEvent->refcon, 0) != noErr)
FatalError(errNoAppleEvents);
if (!gFoundOSL) return;
if (AEObjectInit() != noErr) FatalError(errNoAppleEvents);
for (theObject = theObjectList; theObject->handler; theObject++)
if (AEInstallObjectAccessor(theObject->evclass, theObject->container,
NewOSLAccessorProc((ProcPtr)theObject->handler), 0, false) != noErr)
FatalError(errNoAppleEvents);
AEInstallCoercionHandler(typeIntlText, typeChar,
(AECoercionHandlerUPP)NewAECoercePtrProc((ProcPtr)AECoerceIntlToChar),
0, false, false);
AEInstallCoercionHandler(typeQDRectangle, typeAEList,
(AECoercionHandlerUPP)NewAECoercePtrProc((ProcPtr)AECoerceRectToList),
0, false, false);
AEInstallCoercionHandler(typeAEList, typeQDRectangle,
(AECoercionHandlerUPP)NewAECoerceDescProc((ProcPtr)AECoerceListToRect),
0, true, false);
}
/*
* HandleUnsupportedEvent()
*
* Purpose: Dummy event handler for unsupported AppleEvents
* Inputs: theEvent = the AppleEvent record
* reply = the AppleEvent reply
* refCon = our personal work variable
* Returns: an OSErr with the overall result of the operation
* (i.e., errAEEventNotHandled)
*
*/
pascal OSErr HandleUnsupportedEvent(AppleEvent *theEvent, AppleEvent *reply, long refCon)
{
#if applec
#pragma unused(theEvent, reply, refCon)
#endif
return errAEEventNotHandled;
}
/*
* AENewEvent(theEvent, theClass, theID)
*
* Purpose: Creates a new AppleEvent, directed toward the current application
* Inputs: theEvent = a pointer to an AppleEvent record
* theClass = the event class of the event
* theID = the event ID of the event
* Returns: an OSErr describing what went wrong
*
*/
OSErr AENewEvent(AppleEvent *theEvent, AEEventClass theClass, AEEventID theID)
{
ProcessSerialNumber theProcess = { 0, kCurrentProcess };
AEDesc theDesc;
OSErr theErr;
theErr = AECreateDesc(typeProcessSerialNumber, (void *)&theProcess,
sizeof(ProcessSerialNumber), &theDesc);
if (theErr == noErr) {
theErr = AECreateAppleEvent(theClass, theID, &theDesc, kAutoGenerateReturnID,
kAnyTransactionID, theEvent);
AEDisposeDesc(&theDesc);
}
return theErr;
}
/*
* AEMakeIntlDesc(theString, theDesc)
*
* Purpose: Creates a typeIntlText descriptor from the given string
* Inputs: theString = the source string
* theDesc = a pointer to the descriptor to put the record into
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEMakeIntlDesc(StringPtr theString, AEDesc *theDesc)
{
struct {
short script;
short language;
char text[256];
} theIText;
theIText.script = smCurrentScript;
theIText.language = currentCurLang;
BlockMove(&theString[1], theIText.text, theString[0]);
return AECreateDesc(typeIntlText, (void *)&theIText, 4 + theString[0], theDesc);
}
/*
* AEMakeBeginningILoc(theDesc)
*
* Purpose: Creates an insertionLoc record pointing to the beginning of the null
* container
* Inputs: theDesc = a pointer to the descriptor to put the record into
* floating = flag: true if this is a floating window
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEMakeBeginningILoc(AEDesc *theDesc, Boolean floating)
{
AEDesc theContainer, theRecord;
DescType beginning;
OSErr theErr;
theErr = AECreateList(nil, 0, true, &theRecord);
if (theErr == noErr) {
if (GetFirstWindow()) {
theErr = MakeWindowObject(floating ? GetFirstWindow() : FWFrontWindow(), &theContainer);
beginning = kAEBefore;
} else {
theContainer.descriptorType = typeNull;
theContainer.dataHandle = nil;
beginning = kAEBeginning;
}
if (theErr == noErr) {
theErr = AEPutParamDesc(&theRecord, keyAEObject, &theContainer);
if (theContainer.descriptorType != typeNull) AEDisposeDesc(&theContainer);
}
if (theErr == noErr) theErr = AEAddEnumerated(&theRecord, keyAEPosition, &beginning);
if (theErr == noErr) theErr = AECoerceDesc(&theRecord, typeInsertionLoc, theDesc);
AEDisposeDesc(&theRecord);
}
return theErr;
}
/*
* AECreateHandleDesc(theType, theHandle, theDesc)
*
* Purpose: Creates a descriptor record based on a handle
* Inputs: theType = the type to create
* theHandle = the handle
* theDesc = a pointer to the descriptor to put the record into
* Returns: an OSErr describing what went wrong
*
*/
OSErr AECreateHandleDesc(DescType theType, Handle theHandle, AEDesc *theDesc)
{
char hState = HGetState(theHandle);
OSErr theErr;
HLock(theHandle);
theErr = AECreateDesc(theType, (void *)*theHandle, GetHandleSize(theHandle), theDesc);
HSetState(theHandle, hState);
return theErr;
}
/*
* AEAddAlias(theEvent, theKey, theSpec)
*
* Purpose: Creates an alias descriptor from an FSSpec and adds it to the given
* event under the given keyword
* Inputs: theEvent = a pointer to the AppleEvent record
* theKey = the keyword identifying this parameter
* theSpec = the file system specification for the file
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEAddAlias(AppleEvent *theEvent, AEKeyword theKey, FSSpec *theSpec)
{
AliasHandle theAlias;
AEDesc theDesc;
OSErr theErr;
theErr = NewAlias(nil, theSpec, &theAlias);
if (theErr == noErr) {
HLock((Handle)theAlias);
theErr = AECreateDesc(typeAlias, (void *)*theAlias, GetHandleSize((Handle)theAlias), &theDesc);
DisposeHandle((Handle)theAlias);
if (theErr == noErr) {
theErr = AEPutParamDesc(theEvent, theKey, &theDesc);
AEDisposeDesc(&theDesc);
}
}
return theErr;
}
/*
* AEAddAliasList(theEvent, theKey, theSpec, count)
*
* Purpose: Creates an alias list descriptor from an array of FSSpecs and adds it
* to the given event under the given keyword
* Inputs: theEvent = a pointer to the AppleEvent record
* theKey = the keyword identifying this parameter
* theSpec = pointer to an array of file system specifications
* count = the number of entries in the above array
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEAddAliasList(AppleEvent *theEvent, AEKeyword theKey, FSSpec *theSpec, short count)
{
AliasHandle theAlias;
AEDescList theList;
AEDesc theDesc;
OSErr theErr;
short i;
theErr = AECreateList(nil, 0, false, &theList);
if (theErr == noErr) {
for (i = 0; (theErr == noErr) && (i < count); i++) {
theErr = NewAlias(nil, theSpec++, &theAlias);
if (theErr == noErr) {
HLock((Handle)theAlias);
theErr = AECreateDesc(typeAlias, (void *)*theAlias, GetHandleSize((Handle)theAlias),
&theDesc);
HUnlock((Handle)theAlias);
if (theErr == noErr) {
theErr = AEPutDesc(&theList, i + 1, &theDesc);
AEDisposeDesc(&theDesc);
}
DisposeHandle((Handle)theAlias);
}
}
if (theErr == noErr) theErr = AEPutParamDesc(theEvent, theKey, &theList);
AEDisposeDesc(&theList);
}
return theErr;
}
/*
* AEExtractObject(theEvent, theKey, theToken)
*
* Purpose: Extracts a parameter of typeObjectSpecifier from the given event
* Inputs: theEvent = a pointer to the AppleEvent record
* theKey = the keyword identifying this parameter, or 0 if theEvent is
* actually a simple descriptor containing the parameter
* theToken = pointer to a destination location to store the result
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEExtractObject(AppleEvent *theEvent, AEKeyword theKey, AEDesc *theToken)
{
AEDesc coercedDesc, theDesc;
OSErr theErr = noErr;
if (theKey) theErr = AEGetParamDesc(theEvent, theKey, typeWildCard, &theDesc);
else theErr = AEDuplicateDesc(theEvent, &theDesc);
if (theErr == noErr) {
if (theDesc.descriptorType == typeNull) {
theToken->descriptorType = typeNull;
theToken->dataHandle = nil;
AEDisposeDesc(&theDesc);
return noErr;
} else if (theDesc.descriptorType != typeObjectSpecifier)
theErr = AECoerceDesc(&theDesc, typeObjectSpecifier, &coercedDesc);
else theErr = AEDuplicateDesc(&theDesc, &coercedDesc);
AEDisposeDesc(&theDesc);
if (theErr == noErr) {
theErr = AEResolve(&coercedDesc, kAEIDoMinimum, theToken);
AEDisposeDesc(&coercedDesc);
}
}
return theErr;
}
/*
* AEExtractInsertionLoc(theEvent, theKey, theWindow)
*
* Purpose: Extracts a parameter of typeInsertionLoc from the given event
* Inputs: theEvent = a pointer to the AppleEvent record
* theKey = the keyword identifying this parameter, or 0 if theEvent is
* actually a simple descriptor containing the parameter
* theWindow = pointer to a WindowPtr behind which we should put a new window
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEExtractInsertionLoc(AppleEvent *theEvent, AEKeyword theKey, WindowPtr *theWindow)
{
AEDesc coercedDesc, theObject;
ObjectTokenHandle theToken;
OSErr theErr = noErr;
DescType position;
WindowPtr window;
if (theKey)
theErr = AEGetParamDesc(theEvent, theKey, typeAERecord, &coercedDesc);
else {
if (theEvent->descriptorType != typeAERecord)
theErr = AECoerceDesc(theEvent, typeAERecord, &coercedDesc);
else theErr = AEDuplicateDesc(theEvent, &coercedDesc);
}
if (theErr == noErr) {
theErr = AEExtractObject(&coercedDesc, keyAEObject, &theObject);
if (theErr == noErr) {
theErr = AEExtractEnumerated(&coercedDesc, keyAEPosition, &position);
if (theErr == noErr) {
theToken = (ObjectTokenHandle)theObject.dataHandle;
if ((theObject.descriptorType == typeNull) || ((*theToken)->count == 1)) {
if (theObject.descriptorType != typeNull) {
*theWindow = (WindowPtr)(*theToken)->object[0];
for (window = GetFirstWindow(); window && (window != *theWindow);
window = NextWindow(window));
} else window = GetFirstWindow();
switch (position) {
case kAEBefore:
if ((theObject.descriptorType == cWindow) ||
(theObject.descriptorType == cDocument)) {
if (GetFirstWindow() == *theWindow) *theWindow = nil;
else {
for (window = GetFirstWindow();
window && (NextWindow(window) != *theWindow);
window = NextWindow(window));
*theWindow = window;
}
} else theErr = errAEEventFailed;
break;
case kAEAfter:
if ((theObject.descriptorType == cWindow) ||
(theObject.descriptorType == cDocument)) break;
else theErr = errAEEventFailed;
break;
case kAEBeginning:
if (theObject.descriptorType == typeNull) *theWindow = nil;
else theErr = errAEEventFailed;
break;
case kAEEnd:
if (theObject.descriptorType == typeNull) {
if (!GetFirstWindow()) *theWindow = nil;
else {
for (window = GetFirstWindow(); NextWindow(window);
window = NextWindow(window));
*theWindow = window;
}
} else theErr = errAEEventFailed;
break;
case kAEReplace:
for (window = GetFirstWindow();
window && (NextWindow(window) != *theWindow);
window = NextWindow(window));
theErr = DoCloseWindow(*theWindow, gThePrefs.restoreColors);
if (theErr == noErr) *theWindow = (WindowPtr)window;
break;
}
} else theErr = errAENotASingleObject;
}
AEDisposeDesc(&theObject);
}
AEDisposeDesc(&coercedDesc);
}
return theErr;
}
/*
* AEExtractGeneric(theEvent, theKey, theType, theSize, theData)
*
* Purpose: Extracts a parameter of typeLongInteger from the given event
* Inputs: theEvent = a pointer to the AppleEvent record
* theKey = the keyword identifying this parameter, or 0 if theEvent is
* actually a simple descriptor containing the parameter
* theType = the type we want
* theSize = the size of our data
* theData = pointer to a destination location to store the result
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEExtractGeneric(AppleEvent *theEvent, AEKeyword theKey, DescType theType,
Size theSize, void *theData)
{
OSErr theErr = noErr;
DescType actualType;
AEDesc coercedDesc;
long actualSize;
if (theKey)
theErr = AEGetParamPtr(theEvent, theKey, theType, &actualType, theData,
theSize, &actualSize);
else {
if (theEvent->descriptorType != theType)
theErr = AECoerceDesc(theEvent, theType, &coercedDesc);
else theErr = AEDuplicateDesc(theEvent, &coercedDesc);
if (theErr == noErr) {
actualSize = GetHandleSize(coercedDesc.dataHandle);
if (theSize > actualSize) theSize = actualSize;
HLock(coercedDesc.dataHandle);
BlockMove(*coercedDesc.dataHandle, theData, theSize);
AEDisposeDesc(&coercedDesc);
}
}
return theErr;
}
/*
* AEExtractTypeList(theEvent, theKey, theData)
*
* Purpose: Extracts a list of typeType records from the given event
* Inputs: theEvent = a pointer to the AppleEvent record
* theKey = the keyword identifying this parameter, or 0 if theEvent is
* actually a simple descriptor containing the parameter
* theData = a pointer to a handle to store our result
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEExtractTypeList(AppleEvent *theEvent, AEKeyword theKey, DescType ***theData)
{
long theCount, theIndex, actualSize;
DescType returnedType, theType;
OSErr theErr = noErr;
AEDesc theList;
if (theKey)
theErr = AEGetParamDesc(theEvent, theKey, typeAEList, &theList);
else {
if (theEvent->descriptorType != typeAEList)
theErr = AECoerceDesc(theEvent, typeAEList, &theList);
else theErr = AEDuplicateDesc(theEvent, &theList);
}
if (theErr == noErr) {
theErr = AECountItems(&theList, &theCount);
if (theErr == noErr) {
*theData = (DescType **)NewHandle(theCount * sizeof(DescType));
if (*theData) {
for (theIndex = 1; theIndex <= theCount; theIndex++) {
theErr = AEGetNthPtr(&theList, theIndex, typeType, &theKey,
&returnedType, (void *)&theType, sizeof(typeType), &actualSize);
if (theErr == noErr) (**theData)[theIndex - 1] = theType;
else {
theErr = errAEBadListItem;
break;
}
}
} else theErr = memFullErr;
} else theErr = errAEWrongDataType;
AEDisposeDesc(&theList);
}
return theErr;
}
/*
* AEExtractPString(theEvent, theKey, theString)
*
* Purpose: Extracts a parameter of typeChar from the given event
* Inputs: theEvent = a pointer to the AppleEvent record
* theKey = the keyword identifying this parameter, or 0 if theEvent is
* actually a simple descriptor containing the parameter
* theString = pointer to a destination location to store the result
* Returns: an OSErr describing what went wrong
*
*/
OSErr AEExtractPString(AppleEvent *theEvent, AEKeyword theKey, uchar *theString)
{
long actualSize, theSize = 255;
OSErr theErr = noErr;
DescType actualType;
AEDesc coercedDesc;
if (theKey) {
theErr = AEGetParamPtr(theEvent, theKey, typeChar, &actualType, (void *)&theString[1],
theSize, &actualSize);
if (theSize > actualSize) theSize = actualSize;
} else {
if (theEvent->descriptorType == typeChar)
AEDuplicateDesc(theEvent, &coercedDesc);
else theErr = AECoerceDesc(theEvent, typeChar, &coercedDesc);
if (theErr == noErr) {
actualSize = GetHandleSize(coercedDesc.dataHandle);
BlockMove(*coercedDesc.dataHandle, &theString[1],
*(uchar *)*coercedDesc.dataHandle);
if (theSize > actualSize) theSize = actualSize;
AEDisposeDesc(&coercedDesc);
}
}
theString[0] = theSize;
return theErr;
}
/*
* AECoerceIntlToChar(theEvent, theKey, theSpec, count)
*
* Purpose: Coercion handler for making typeChars out of typeIntlTexts
* Inputs: fromType = the original type of data (typeIntlText)
* theData = pointer to the data
* theSize = size of the pointed-to data
* toType = the new type (typeChar)
* refCon = a reference constant
* result = a descriptor record containing the result
* Returns: an OSErr describing what went wrong
*
*/
pascal OSErr AECoerceIntlToChar(DescType fromType, Ptr theData, Size theSize,
DescType toType, long refCon, AEDesc *result)
{
#if applec
#pragma unused(fromType, toType, refCon)
#endif
return AECreateDesc(typeChar, (void *)(theData + 4), theSize - 4, result);
}
pascal OSErr AECoerceRectToList(DescType fromType, Ptr theData, Size theSize,
DescType toType, long refCon, AEDesc *result)
{
#if applec
#pragma unused(fromType, theSize, toType, refCon)
#endif
short *theItem = (short *)theData, i;
OSErr theErr;
theErr = AECreateList(nil, 0, false, result);
if (theErr == noErr) {
for (i = 0; i < 4; i++)
if (theErr == noErr)
theErr = AEPutPtr(result, 0, typeShortInteger, (Ptr)(theItem++), sizeof(short));
if (theErr != noErr) AEDisposeDesc(result);
}
return theErr;
}
pascal OSErr AECoerceListToRect(AEDesc *theAEDesc, DescType toType, long refCon,
AEDesc *result)
{
#if applec
#pragma unused(toType, refCon)
#endif
Rect theRect;
short *theItem = (short *)&theRect, i;
OSErr theErr = noErr;
AEKeyword theKey;
DescType theType;
Size actualSize;
for (i = 1; i <= 4; i++)
if (theErr == noErr)
theErr = AEGetNthPtr(theAEDesc, i, typeShortInteger, &theKey, &theType,
(Ptr)(theItem++), sizeof(short), &actualSize);
if (theErr == noErr)
return AECreateDesc(typeQDRectangle, (void *)&theRect, sizeof(Rect), result);
else return theErr;
}
/*
* AEIdleProc(theEvent, theKey, theSpec, count)
*
* Purpose: Catch-all idle procedure used during AppleEvent processing
* Inputs: theEvent = a pointer to the event record
* sleep = a pointer to a sleep parameter we can set
* mouseRgn = a pointer to a RgnHandle we can use to track mouseMoved events
* Returns: true if we want to abort processing; false otherwise
*
*/
pascal Boolean AEIdleProc(EventRecord *theEvent, long *sleep, RgnHandle *mouseRgn)
{
#if applec
#pragma unused(sleep, mouseRgn)
#endif
Boolean isDialogEvent = IsDialogEvent(theEvent);
switch (theEvent->what) {
case activateEvt:
if (isDialogEvent) HandleActivateDialog(theEvent);
else HandleActivateEvent(theEvent);
break;
case updateEvt:
if (isDialogEvent) HandleUpdateDialog(theEvent);
else HandleUpdateEvent(theEvent);
break;
case osEvt:
HandleOSEvent(theEvent);
break;
case diskEvt:
HandleDiskEvent(theEvent);
break;
}
return false;
}