/*********************************************************/
/* 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

/*
 * HandleClone(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the clone event
 *      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., noErr)
 *
 */

pascal OSErr HandleClone(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(refCon)
#endif
	Boolean visible = false, foundVisible = false;
	WindowPtr newWindow, behindWindow;
	ObjectTokenHandle theToken;
	AEDesc theList, theObject;
	OSErr theErr = noErr;
	short i, count;
	
	AEBegin();
	theErr = AEExtractBoolean(theEvent, keyVisible, &visible);
	if (theErr == noErr) foundVisible = true;
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		theToken = (ObjectTokenHandle)theObject.dataHandle;
		if ((theObject.descriptorType == cWindow) || 
			(theObject.descriptorType == cDocument)) {
			count = (*theToken)->count;
			theErr = AEExtractInsertionLoc(theEvent, keyAEInsertHere, &behindWindow);
			if (theErr != noErr) {
				behindWindow = (WindowPtr)(*theToken)->object[count - 1];
				theErr = noErr;
			}
			if (count > 1) theErr = AECreateList(nil, 0, false, &theList);
			for (i = 0; i < count; i++) {
				if (theErr == noErr) {
					theErr = DoCloneWindow((WindowPtr)(*theToken)->object[i], 
											behindWindow, &newWindow);
					if (theErr == noErr) {
						if (visible || (!foundVisible &&
							 WindowVisible((WindowPtr)(*theToken)->object[i]))) {
							FWShowWindow(newWindow);
							if (newWindow == FWFrontWindow()) ChangeActive(newWindow);
						}
						theErr = MakeWindowObject((WindowPtr)newWindow, &theObject);
						if (theErr == noErr) {
							if (count == 1) {
								if (reply->dataHandle) 
									theErr = AEPutParamDesc(reply, keyAEResult, &theObject);
							} else theErr = AEPutDesc(&theList, i + 1, &theObject);
						}
						AEDisposeDesc(&theObject);
					}
					behindWindow = newWindow;
				}
			}
			if (count > 1) {
				if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList);
				AEDisposeDesc(&theList);
			}
		} else theErr = errAEEventNotHandled;
		AEDisposeDesc(&theObject);
	}
	AEEnd();
	return theErr;
}

/*
 * HandleClose(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the close event
 *      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., noErr)
 *
 */

pascal OSErr HandleClose(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(reply, refCon)
#endif
	ObjectTokenHandle theToken;
	Boolean restoreColors;
	OSErr theErr = noErr;
	AEDesc theObject;
	short i, count;
	
	AEBegin();
	theErr = AEExtractBoolean(theEvent, keyRestoreColors, &restoreColors);
	if (theErr != noErr) restoreColors = gThePrefs.restoreColors;
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		theToken = (ObjectTokenHandle)theObject.dataHandle;
		if ((theObject.descriptorType == cWindow) || 
			(theObject.descriptorType == cDocument)) {
			count = (*theToken)->count;
			for (i = count - 1; i >= 0; i--) {
				if (theErr == noErr)
					theErr = DoCloseWindow((WindowPtr)(*theToken)->object[i], restoreColors);
			}
		} else theErr = errAEEventNotHandled;
		AEDisposeDesc(&theObject);
	}
	AEEnd();
	return theErr;
}

/*
 * HandleCountElements(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the count elements event
 *      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., noErr)
 *
 */

pascal OSErr HandleCountElements(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(refCon)
#endif
	ObjectTokenHandle theToken;
	AEDesc theList, theObject;
	OSErr theErr = noErr;
	DescType theType;
	short i, count;
	long val;
	
	AEBegin();
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		theErr = AEExtractType(theEvent, keyAEObjectClass, &theType);
		if (theErr == noErr) {
			theToken = (ObjectTokenHandle)theObject.dataHandle;
			count = (*theToken)->count;
			if (count > 1) theErr = AECreateList(nil, 0, false, &theList);
			for (i = 0; i < count; i++) {
				val = 0;
				switch (theObject.descriptorType) {
					case typeNull:
						if (theType == cWindow) val = CountWindows();
						else if (theType == cDocument) val = CountDocuments();
						break;
					case cWindow:
						if ((theType == cDocument) || (theType == cDrawingArea)) 
							if (FindImage((WindowPtr)(*theToken)->object[i])) val = 1;
						break;
					case cDocument:
						if ((theType == cImage) || (theType == cFile)) val = 1;
						break;
					case cDrawingArea:
						if (theType == cImage) val = 1;
						break;
					case cImage:
						if (theType == cPixelMap) 
							if ((*FindImage((WindowPtr)(*theToken)->object[i]))->gworld) 
								val = 1;
						break;
					case cFile:
						if (theType == cImage) val = 1;
						break;
					case typeProperty:
						if (((*theToken)->objclass == cWindow) &&
							((*theToken)->property == pSelection)) val = 1;
						break;
				}
				if (reply->dataHandle) {
					if (count == 1) theErr = AEPutParamPtr(reply, keyAEResult, 
											 typeLongInteger, (void *)&val, sizeof(long));
					else theErr = AEPutPtr(&theList, i + 1, typeLongInteger, (void *)&val, 
								  sizeof(long));
				}
				if (theErr != noErr) break;
			}
			if (count > 1) {
				if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList);
				AEDisposeDesc(&theList);
			}
		} else theErr = errAEEventNotHandled;
		AEDisposeDesc(&theObject);
	}
	AEEnd();
	return theErr;
}

/*
 * HandleCreateElement(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the create element event
 *      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., noErr)
 *
 */

pascal OSErr HandleCreateElement(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(refCon)
#endif
	DescType theClass, theType, actualType;
	WindowPtr behindWindow, theWindow;
	AEDesc theRecord, theObject;
	OSErr theErr = noErr;
	long actualSize;
	
	AEBegin();
	theErr = AEExtractType(theEvent, keyAEObjectClass, &theClass);
	if (theErr == noErr) {
		if (theClass == cWindow) {
			theErr = AEExtractInsertionLoc(theEvent, keyAEInsertHere, &behindWindow);
			if (theErr == noErr) {
				theErr = AEGetParamDesc(theEvent, keyAEPropData, typeAERecord, &theRecord);
				if (theErr == noErr) {
					theErr = AEGetKeyPtr(&theRecord, pWindowType, typeEnumerated, 
							 &actualType, (void *)&theType, sizeof(DescType), &actualSize);
					if (theErr == noErr) 
						theErr = DoCreateWindow(theType, behindWindow, &theWindow);
					else theErr = errAENoSuchObject;
					if (theErr == noErr) {
						theErr = MakeWindowObject(theWindow, &theObject);
						if (theErr == noErr) {
							if (reply->dataHandle)
								theErr = AEPutParamDesc(reply, keyAEResult, &theObject);
							AEDisposeDesc(&theObject);
						}
					}
					AEDisposeDesc(&theRecord);
				} else theErr = errAENoSuchObject;
			}
		} else theErr = errAEEventNotHandled;
	}
	AEEnd();
	return theErr;
}

/*
 * HandleDelete(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the delete event
 *      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., noErr)
 *
 */

pascal OSErr HandleDelete(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(reply, refCon)
#endif
	ObjectTokenHandle theToken;
	OSErr theErr = noErr;
	ImageHandle theImage;
	AEDesc theObject;
	short i, count;
	
	AEBegin();
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		theToken = (ObjectTokenHandle)theObject.dataHandle;
		if ((theObject.descriptorType == cWindow) || 
			(theObject.descriptorType == cDocument)) {
			count = (*theToken)->count;
			for (i = count - 1; i >= 0; i--) {
				if (theErr == noErr)
					theErr = DoCloseWindow((WindowPtr)(*theToken)->object[i], 
							 gThePrefs.restoreColors);
			}
		} else if (theObject.descriptorType == cPixelMap) {
			count = (*theToken)->count;
			for (i = 0; i < count; i++) {
				theImage = FindImage((WindowPtr)(*theToken)->object[i]);
				if (theImage) KillGWorld(theImage);
				else {
					theErr = errAENoSuchObject;
					break;
				}
			}
		} else theErr = errAEEventNotHandled;
		AEDisposeDesc(&theObject);
	}
	AEEnd();
	return theErr;
}

/*
 * HandleDoObjectsExist(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the do objects exist event
 *      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., noErr)
 *
 */

pascal OSErr HandleDoObjectsExist(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(refCon)
#endif
	OSErr theErr = noErr;
	Boolean theResult;
	AEDesc theObject;
	
	AEBegin();
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	AEDisposeDesc(&theObject);
	theResult = (theErr == noErr);
	if (reply->dataHandle)
		theErr = AEPutParamPtr(reply, keyAEResult, typeBoolean, (void *)&theResult, sizeof(Boolean));
	AEEnd();
	return theErr;
}

/*
 * HandleGetData(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the get data event
 *      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., noErr)
 *
 */

pascal OSErr HandleGetData(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(refCon)
#endif
	DescType **theTypes = nil, typeWanted;
	AEDesc theList, theObject, theData;
	ObjectTokenHandle theToken;
	short i, j, count, types;
	OSErr theErr = noErr;
	
	AEBegin();
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		AEExtractTypeList(theEvent, keyAEObjectClass, &theTypes);
		types = (theTypes) ? GetHandleSize((Handle)theTypes) / sizeof(DescType) : 1;
		theToken = (ObjectTokenHandle)theObject.dataHandle;
		count = (*theToken)->count;
		if (count > 1) theErr = AECreateList(nil, 0, false, &theList);
		for (i = 0; i < count; i++) {
			theData.descriptorType = typeNull;
			for (j = 0; j < types; j++) {
				typeWanted = (theTypes) ? (*theTypes)[j] : typeWildCard;
				theErr = DoGetData(theObject.descriptorType, theToken, i, typeWanted, 
						 &theData);
				if (theErr == noErr) {
					if (reply->dataHandle) {
						if (count == 1) theErr = AEPutParamDesc(reply, keyAEResult, &theData);
						else theErr = AEPutDesc(&theList, i + 1, &theData);
					}
					AEDisposeDesc(&theData);
					break;
				}
			}
			if (j == types) theErr = errAECantSupplyType;
			if (theErr != noErr) break;
		}
		if (count > 1) {
			if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList);
			AEDisposeDesc(&theList);
		}
		AEDisposeDesc(&theObject);
		if (theTypes) DisposeHandle((Handle)theTypes);
	}
	AEEnd();
	return theErr;
}

/*
 * DoGetData(theType, theToken, index, typeWanted, theData)
 *
 *     Purpose: Dispatches the get data event to the appropriate handler
 *      Inputs: theType = the object class whose data we want
 *				theToken = the tokens for the objects
 *				index = the index of the token we're interested in
 *				typeWanted = the type we're looking to get back
 *				theData = descriptor to put the data in
 *     Returns: an OSErr with the overall result of the operation (i.e., noErr)
 *
 */

OSErr DoGetData(DescType theType, ObjectTokenHandle theToken, short index, 
	DescType typeWanted, AEDesc *theData)
{
	WindowPtr theWindow = (WindowPtr)(*theToken)->object[index];
	OSErr theErr;
	
	switch (theType) {
		case typeNull:
			theErr = GetApplicationData(typeWanted, theData);
			break;
		case cWindow:
			theErr = GetWindowData(theWindow, typeWanted, theData);
			break;
		case cDocument:
			theErr = GetDocumentData(theWindow, typeWanted, theData);
			break;
		case cDrawingArea:
			theErr = GetDrawingAreaData(theWindow, typeWanted, theData);
			break;
		case cImage:
			theErr = GetImageData(theWindow, typeWanted, theData);
			break;
		case cFile:
			theErr = GetFileData(theWindow, typeWanted, theData);
			break;
		case cPixelMap:
			theErr = GetPixelMapData(theWindow, typeWanted, theData);
			break;
		case cSelection:
			theErr = GetSelectionData(theWindow, typeWanted, theData);
			break;
		case typeProperty:
			switch ((*theToken)->objclass) {
				case typeNull:
					theErr = GetAppPropertyData((*theToken)->property, 
							 typeWanted, theData);
					break;
				case cWindow:
					theErr = GetWinPropertyData(theWindow, (*theToken)->property,
							 typeWanted, theData);
					break;
				case cDocument:
					theErr = GetDocPropertyData(theWindow, (*theToken)->property,
							 typeWanted, theData);
					break;
				case cDrawingArea:
					theErr = GetDrawPropertyData(theWindow, (*theToken)->property,
							 typeWanted, theData);
					break;
				case cImage:
					theErr = GetImagePropertyData(theWindow, (*theToken)->property,
							 typeWanted, theData);
					break;
				case cFile:
					theErr = GetFilePropertyData(theWindow, (*theToken)->property,
							 typeWanted, theData);
					break;
				case cPixelMap:
					theErr = GetPixelPropertyData(theWindow, (*theToken)->property,
							 typeWanted, theData);
					break;
				case cSelection:
					theErr = GetSelPropertyData(theWindow, (*theToken)->property,
							 typeWanted, theData);
					break;
			}
			break;
		default:
			theErr = errAEReadDenied;
			break;
	}
	return theErr;
}

/*
 * HandleGetDataSize(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the get data size event
 *      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., noErr)
 *
 */

pascal OSErr HandleGetDataSize(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(refCon)
#endif
	AEDesc theList, theObject, theData;
	DescType **theTypes, typeWanted;
	ObjectTokenHandle theToken;
	short i, j, count, types;
	OSErr theErr = noErr;
	long theSize;
	
	AEBegin();
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		AEExtractTypeList(theEvent, keyAEObjectClass, &theTypes);
		types = (theTypes) ? GetHandleSize((Handle)theTypes) / sizeof(DescType) : 1;
		theToken = (ObjectTokenHandle)theObject.dataHandle;
		count = (*theToken)->count;
		if (count > 1) theErr = AECreateList(nil, 0, false, &theList);
		for (i = 0; i < count; i++) {
			theData.descriptorType = typeNull;
			for (j = 0; j < types; j++) {
				typeWanted = (theTypes) ? (*theTypes)[j] : typeWildCard;
				theErr = DoGetData(theObject.descriptorType, theToken, i, typeWanted, 
						 &theData);
				if (theErr == noErr) {
					theSize = GetHandleSize(theData.dataHandle);
					AEDisposeDesc(&theData);
					if (reply->dataHandle) {
						if (count == 1) theErr = AEPutParamPtr(reply, keyAEResult,
												 typeLongInteger, (void *)&theSize, sizeof(long));
						else theErr = AEPutPtr(&theList, i + 1, typeLongInteger, (void *)&theSize,
									  sizeof(long));
						break;
					}
				}
			}
			if (j == types) theErr = errAECantSupplyType;
			if (theErr != noErr) break;
		}
		if (count > 1) {
			if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList);
			AEDisposeDesc(&theList);
		}
		AEDisposeDesc(&theObject);
		if (theTypes) DisposeHandle((Handle)theTypes);
	}
	AEEnd();
	return theErr;
}

/*
 * HandleMove(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the move event
 *      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., noErr)
 *
 */

pascal OSErr HandleMove(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(refCon)
#endif
	AEDesc theList, theObject, newObject;
	WindowPtr theWindow, behindWindow;
	ObjectTokenHandle theToken;
	OSErr theErr = noErr;
	short i, count;
	
	AEBegin();
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		theToken = (ObjectTokenHandle)theObject.dataHandle;
		if ((theObject.descriptorType == cWindow) || 
			(theObject.descriptorType == cDocument)) {
			count = (*theToken)->count;
			theErr = AEExtractInsertionLoc(theEvent, keyAEInsertHere, &behindWindow);
			if (theErr == noErr) {
				if (count > 1) theErr = AECreateList(nil, 0, false, &theList);
				for (i = 0; i < count; i++) {
					if (theErr == noErr) {
						theWindow = (WindowPtr)(*theToken)->object[i];
						theErr = DoMoveWindow(theWindow, behindWindow);
						if (theErr == noErr) 
							theErr = MakeWindowObject(theWindow, &newObject);
						if (theErr == noErr) {
							if (count == 1) {
								if (reply->dataHandle)
									theErr = AEPutParamDesc(reply, keyAEResult, &newObject);
							} else theErr = AEPutDesc(&theList, i + 1, &newObject);
						}
						AEDisposeDesc(&newObject);
						behindWindow = theWindow;
					}
				}
				if (count > 1) {
					if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList);
					AEDisposeDesc(&theList);
				}
			} else theErr = errAEEventFailed;
		} else theErr = errAECantHandleClass;
		AEDisposeDesc(&theObject);
	}
	AEEnd();
	return theErr;
}

/*
 * HandleSave(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the save event
 *      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., noErr)
 *
 */

pascal OSErr HandleSave(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(reply, refCon)
#endif
	Boolean preview, palette, icons;
	ObjectTokenHandle theToken;
	OSErr theErr = noErr;
	ImageHandle theImage;
	AEDesc theObject;
	DescType theType;
	FSSpec theSpec;
	short cropWhat;
	
	AEBegin();
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		theToken = (ObjectTokenHandle)theObject.dataHandle;
		if ((theObject.descriptorType == cDocument) ||
			(theObject.descriptorType == cWindow)) {
			if ((*theToken)->count == 1) {
				theImage = FindImage((WindowPtr)(*theToken)->object[0]);
				if (theImage) {
					theErr = AEExtractAlias(theEvent, keyAEFile, &theSpec);
					if (theErr != noErr) theSpec = (*theImage)->file;
					theErr = AEExtractType(theEvent, keyAEFileType, &theType);
					if (theErr != noErr) 
						theType = ((*theImage)->compression == kJPEGCompression && gThePrefs.savePICT) 
									? kPICTType : (*theImage)->format->inType;
					theErr = AEExtractBoolean(theEvent, keyCreatePreview, &preview);
					if (theErr != noErr) preview = gThePrefs.savePrev;
					theErr = AEExtractBoolean(theEvent, keySaveQuant, &palette);
					if (theErr != noErr) 
						palette = (*theImage)->qpalette && 
									(theType == kPICTType || (*theImage)->format->doesColors) &&
							((gThePrefs.saveQuant == sqOnly && !(*theImage)->ipalette) ||
							 gThePrefs.saveQuant == sqAlways);
					theErr = AEExtractBoolean(theEvent, keyMakeIcons, &icons);
					if (theErr != noErr) icons = gThePrefs.makeIcons;
					if (theErr == noErr) theErr = AEExtractShort(theEvent, keyCropWhat, &cropWhat);
					if (theErr != noErr || !AntsHaveSelection((*theImage)->ants))
						cropWhat = kCropNothing;
					StartSpinning();
					theErr = DoSaveDocument(theImage, &theSpec, theType, preview, palette,
											icons, cropWhat);
					StopSpinning(&qd.arrow);
				} else theErr = errAENoSuchObject;
			} else theErr = errAENotASingleObject;
		} else theErr = errAECantHandleClass;
		AEDisposeDesc(&theObject);
	}
	AEEnd();
	return theErr;
}

/*
 * HandleSetData(theEvent, reply, refCon)
 *
 *     Purpose: AppleEvent handler for the set data event
 *      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., noErr)
 *
 */

pascal OSErr HandleSetData(AppleEvent *theEvent, AppleEvent *reply, long refCon) 
{
#if applec
#pragma unused(reply, refCon)
#endif
	ObjectTokenHandle theToken;
	AEDesc theObject, theData, dataObject;
	OSErr theErr = noErr;
	short i, count;
	
	AEBegin();
	theErr = AEExtractObject(theEvent, keyDirectObject, &theObject);
	if (theErr == noErr) {
		theData.descriptorType = typeNull;
		theErr = AEGetParamDesc(theEvent, keyAEData, typeWildCard, &theData);
		if ((theErr == noErr) && (theData.descriptorType == typeObjectSpecifier)) {
			theErr = AEExtractObject(&theData, 0, &dataObject);
			AEDisposeDesc(&theData);
			if (theErr == noErr) {
				theToken = (ObjectTokenHandle)dataObject.dataHandle;
				if ((*theToken)->count == 1)
					theErr = DoGetData(dataObject.descriptorType, theToken, 0,
							 typeWildCard, &theData);
				else theErr = errAENotASingleObject;
			}
		}
		if (theErr == noErr) {
			theToken = (ObjectTokenHandle)theObject.dataHandle;
			count = (*theToken)->count;
			for (i = 0; i < count; i++)
				if (theErr == noErr)
					theErr = DoSetData(theObject.descriptorType, theToken, i, &theData);
			AEDisposeDesc(&theData);
		}
		AEDisposeDesc(&theObject);
	}
	AEEnd();
	return theErr;
}

/*
 * DoSetData(theType, theToken, index, typeWanted, theData)
 *
 *     Purpose: Dispatches the set data event to the appropriate handler
 *      Inputs: theType = the object class whose data we want to set
 *				theToken = the tokens for the objects
 *				index = the index of the token we're interested in
 *				theData = descriptor to get the data from
 *     Returns: an OSErr with the overall result of the operation (i.e., noErr)
 *
 */

OSErr DoSetData(DescType theType, ObjectTokenHandle theToken, short index, AEDesc *theData)
{
	WindowPtr theWindow = (WindowPtr)(*theToken)->object[index];
	OSErr theErr;
	
	switch (theType) {
		case typeProperty:
			switch ((*theToken)->objclass) {
				case typeNull:
					theErr = SetAppPropertyData((*theToken)->property, theData);
					break;
				case cWindow:
					theErr = SetWinPropertyData(theWindow, (*theToken)->property, theData);
					break;
				case cDocument:
					theErr = SetDocPropertyData(theWindow, (*theToken)->property, theData);
					break;
				case cDrawingArea:
					theErr = SetDrawPropertyData(theWindow, (*theToken)->property, theData);
					break;
				case cImage:
					theErr = SetImagePropertyData(theWindow, (*theToken)->property, theData);
					break;
				case cFile:
					theErr = SetFilePropertyData(theWindow, (*theToken)->property, theData);
					break;
				case cPixelMap:
					theErr = SetPixelPropertyData(theWindow, (*theToken)->property, theData);
					break;
				case cSelection:
					theErr = SetSelPropertyData(theWindow, (*theToken)->property, theData);
					break;
			}
			break;
		default:
			theErr = errAEWriteDenied;
			break;
	}
	return theErr;
}
