JPEGView/Source/C/RequiredEventHandlers.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
15 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
static ImageHandle ImageFromSpec(FSSpec *theFile);
static OSErr DrawToPrinter(ImageHandle theImage, NestedProgressPtr progProc);
static OSErr GetPrintParams(void);
static pascal void PrintIdleProc(void);
static short gOurResFile;
static PrIdleUPP gPrintIdle = nil;
static JVDrawParamsHandle gPrintParams;
/*
* HandleOpenApplication(theEvent, reply, refCon)
*
* Purpose: AppleEvent handler for the open application event; does one of four
* tasks upon startup, as specified in the preferences
* 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 HandleOpenApplication(AppleEvent *theEvent, AppleEvent *reply, long refCon)
{
#if applec
#pragma unused(theEvent, reply, refCon)
#endif
WindowPtr front = FWFrontWindow();
OSErr theErr;
if (gInBackground) return noErr;
if (front && (GetWRefCon(front) == kHelpWindowID)) return noErr;
switch (gThePrefs.startWith) {
case swAutoSlide:
theErr = DoSlideShow();
break;
case swSlide:
HandleMenuChoice(MakeMenuSelection(rFileMenu, fileSlideItem));
break;
case swOpen:
HandleMenuChoice(MakeMenuSelection(rFileMenu, fileOpenItem));
break;
case swNone:
break;
}
return noErr;
}
/*
* GetOpenDefaults(openScreen, openFull, openPalette, drawQuality)
*
* Purpose: Translates the current prefs into enumerated parameters for opening
* Inputs: openScreen = pointer to DescType to hold enumerated open screen
* openFull = pointer to DescType to hold enumerated full screen mode
* openPalette = pointer to DescType to hold enumerated palette
* drawQuality = pointer to DescType to hold enumerated drawing quality
* Returns: nothing
*
*/
void GetOpenDefaults(DescType *openScreen, DescType *openFull, DescType *openPalette,
DescType *drawQuality)
{
switch (gThePrefs.openScreen) {
case osDeepest: *openScreen = (gThePrefs.pickColor) ? kAEOSDeepestColor : kAEOSDeepestGray; break;
case osLargest: *openScreen = (gThePrefs.pickColor) ? kAEOSLargestColor : kAEOSLargestGray; break;
case osMain: *openScreen = kAEOSMain; break;
}
switch (gThePrefs.openFull) {
case ofNoMatterWhat: *openFull = kAEOFAlways; break;
case ofAlways: *openFull = kAEOFAlwaysIfLarge; break;
case ofAsk: *openFull = kAEOFAskIfLarge; break;
case ofNever: *openFull = kAEOFNever; break;
}
switch (gThePrefs.autoQuant) {
case aqAlways: *openPalette = (gThePrefs.imagePalette) ? kAEOPQuantImageScrn :
kAEOPQuantScrn; break;
case aqOnly: *openPalette = (gThePrefs.imagePalette) ? kAEOPImageQuantScrn :
kAEOPQuantScrn; break;
case aqNever: *openPalette = (gThePrefs.imagePalette) ? kAEOPImageScrn :
kAEOPScrn; break;
}
switch (gThePrefs.imageQuality) {
case iqVHigh: *drawQuality = kAEDQVeryHigh; break;
case iqHigh: *drawQuality = kAEDQHigh; break;
case iqMedium: *drawQuality = kAEDQNormal; break;
}
}
/*
* HandleOpenDocuments(theEvent, reply, refCon)
*
* Purpose: AppleEvent handler for the open document event; accepts the input files
* one at a time and opens them in succession by calling OpenDocument
* 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 HandleOpenDocuments(AppleEvent *theEvent, AppleEvent *reply, long refCon)
{
#if applec
#pragma unused(reply, refCon)
#endif
Boolean autoExpand, openVisible, openBitmaps, autoComments, fixTypes, fixCreator;
DescType returnedType, openScreen, openFull, openPalette, drawQuality;
long theCount, theIndex;
OSErr theErr = noErr;
AEDescList theList;
AEKeyword theKey;
Boolean noErrors;
Size actualSize;
FSSpec theFile;
FInfo theInfo;
AEBegin();
theErr = AEGetParamDesc(theEvent, keyDirectObject, typeWildCard, &theList);
if ((theErr == noErr) && (theList.descriptorType != typeObjectSpecifier)) {
GetOpenDefaults(&openScreen, &openFull, &openPalette, &drawQuality);
theErr = AEExtractEnumerated(theEvent, keyOpenScreen, &returnedType);
if (theErr == noErr) openScreen = returnedType;
theErr = AEExtractEnumerated(theEvent, keyOpenFull, &returnedType);
if (theErr == noErr) openFull = returnedType;
theErr = AEExtractBoolean(theEvent, keyAutoExpand, &autoExpand);
if (theErr != noErr) autoExpand = gThePrefs.expandSmall;
theErr = AEExtractBoolean(theEvent, keyVisible, &openVisible);
if (theErr != noErr) openVisible = true;
theErr = AEExtractEnumerated(theEvent, keyOpenPalette, &returnedType);
if (theErr == noErr) openPalette = returnedType;
theErr = AEExtractEnumerated(theEvent, keyOpenQuality, &returnedType);
if (theErr == noErr) drawQuality = returnedType;
theErr = AEExtractBoolean(theEvent, keyOpenBitmaps, &openBitmaps);
if (theErr != noErr) openBitmaps = (gThePrefs.useBitmaps == ubAlways);
theErr = AEExtractBoolean(theEvent, keyAutoComments, &autoComments);
if (theErr != noErr) autoComments = gThePrefs.autoComments;
theErr = AEExtractBoolean(theEvent, keyFixTypes, &fixTypes);
if (theErr != noErr) fixTypes = gThePrefs.autoFix;
theErr = AEExtractBoolean(theEvent, keyChangeCreator, &fixCreator);
if (theErr != noErr) fixCreator = gThePrefs.changeCreator;
theErr = AEExtractBoolean(theEvent, keyNoErrors, &noErrors);
if (theErr != noErr) noErrors = false;
DisableMenus();
if (gThePrefs.onlyOne && !gSlideShow)
while (gImageRoot) SendCloseWindow((*LastImage())->window);
theErr = AECountItems(&theList, &theCount);
if (gThePrefs.onlyOne) theCount = 1;
if (theErr == noErr) {
for (theIndex = 1; theIndex <= theCount; theIndex++) {
theErr = AEGetNthPtr(&theList, theIndex, typeFSS, &theKey,
&returnedType, (void *)&theFile, sizeof(FSSpec), &actualSize);
if (theErr == noErr) {
if (FSpGetFInfo(&theFile, &theInfo) != noErr || theInfo.fdType == kPrefsType || theInfo.fdType == kHelpType)
continue;
StartSpinning();
theErr = DoOpenDocument(&theFile, theIndex == 1, openScreen, openFull,
autoExpand, openVisible, openPalette, drawQuality, openBitmaps,
autoComments, fixTypes, fixCreator);
if (!noErrors) HandleAEError(theErr, errNoLoadMemory, theFile.name);
} else {
theErr = errAEBadListItem;
break;
}
}
} else theErr = errAEWrongDataType;
AEDisposeDesc(&theList);
StopSpinning(&qd.arrow);
}
EnableMenus();
AEEnd();
return theErr;
}
pascal OSErr HandlePrintDocuments(AppleEvent *theEvent, AppleEvent *reply, long refCon)
{
#if applec
#pragma unused(reply, refCon)
#endif
OSErr theErr = noErr;
ImageHandle theImage;
AEDescList theList;
AEBegin();
theErr = AEGetParamDesc(theEvent, keyDirectObject, typeWildCard, &theList);
if (theErr == noErr) {
DisableMenus();
StartSpinning();
if (theList.descriptorType != typeObjectSpecifier) {
long theCount, theIndex;
DescType returnedType;
AEKeyword theKey;
Size actualSize;
FSSpec theFile;
theErr = AECountItems(&theList, &theCount);
if (theErr == noErr) {
for (theIndex = 1; theIndex <= theCount; theIndex++) {
theErr = AEGetNthPtr(&theList, theIndex, typeFSS, &theKey,
&returnedType, (void *)&theFile, sizeof(FSSpec), &actualSize);
if (theErr == noErr) {
theErr = DoOpenDocument(&theFile, false, kAEOSMain, kAEOFNever,
false, false, kAEOPScrn, kAEDQNormal, false,
false, false, false);
if (theErr != noErr)
HandleAEError(theErr, errNoPrintMemory, theFile.name);
else theImage = ImageFromSpec(&theFile);
if (theImage) {
theErr = DoPrintDocument(theImage, theIndex == 1);
if (theErr != noErr) {
if (theErr == codecAbortErr) {
theErr = noErr;
break;
}
HandleAEError(theErr, errNoPrintMemory, theFile.name);
}
DoCloseWindow((*theImage)->window, false);
}
} else {
theErr = errAEBadListItem;
break;
}
}
} else theErr = errAEWrongDataType;
} else {
ObjectTokenHandle theToken;
AEDesc theObject;
short count, i;
theErr = AEExtractObject(&theList, 0, &theObject);
if (theErr == noErr) {
theToken = (ObjectTokenHandle)theObject.dataHandle;
if (theObject.descriptorType == cWindow ||
theObject.descriptorType == cDocument) {
count = (*theToken)->count;
for (i = 0; i < count; i++) {
if (theErr == noErr)
theErr = DoPrintDocument(FindImage((WindowPtr)(*theToken)->object[i]),
i == 0);
}
} else theErr = errAEEventNotHandled;
AEDisposeDesc(&theObject);
}
}
AEDisposeDesc(&theList);
StopSpinning(&qd.arrow);
}
EnableMenus();
AEEnd();
return theErr;
}
static ImageHandle ImageFromSpec(FSSpec *theFile)
{
ImageHandle theImage;
for (theImage = gImageRoot; theImage; theImage = (*theImage)->next)
if (SameFile(&(*theImage)->file, theFile)) return theImage;
return nil;
}
extern OSErr DoPrintDocument(ImageHandle theImage, Boolean first)
{
NestedProgress progProc = { { nil, 0 }, 0, 0L, 0x10000L, false };
TPrStatus printStatus;
WindowPtr frontWindow;
OSErr theErr = noErr;
TPPrPort printPort;
// initialize the progress proc, and save a reference to our current resource file
progProc.prog.progressProc = gGenericProgress;
progProc.prog.progressRefCon = (long)&progProc;
gOurResFile = CurResFile();
// open the driver and, if this is the first document, handle the print dialog
PrOpen();
if (first) {
theErr = GetPrintParams();
if (theErr != noErr) return theErr;
}
// call the progress procedure to open the printing... dialog
UpdateParamText(gString[strPrinting], gNullString, gNullString, (*theImage)->file.name);
CallICMProgressProc(progProc.prog.progressProc, codecProgressOpen, kModalProgress,
progProc.prog.progressRefCon);
// store a pointer to our idle procedure in the print record
if (!gPrintIdle) gPrintIdle = NewPrIdleProc((ProcPtr)PrintIdleProc);
(*gPrintRecord)->prJob.pIdleProc = gPrintIdle;
// set up the proper document name
if (frontWindow = FrontWindow()) {
Str63 windowName;
BlockMove((*theImage)->file.name, windowName, *(*theImage)->file.name + 1);
SetWTitle(frontWindow, windowName);
PrValidate(gPrintRecord);
}
// do the actual printing
if ((printPort = PrOpenDoc(gPrintRecord, nil, nil)) && (theErr = PrError()) == noErr) {
PrOpenPage(printPort, nil);
if ((theErr = PrError()) == noErr) theErr = DrawToPrinter(theImage, &progProc);
PrClosePage(printPort);
}
PrCloseDoc(printPort);
// spool the printing, if necessary
if ((*gPrintRecord)->prJob.bJDocLoop == bSpoolLoop && theErr == noErr) {
PrPicFile(gPrintRecord, nil, nil, nil, &printStatus);
theErr = PrError();
}
// close the outer progress, along with the printer driver, and exit
CallICMProgressProc(progProc.prog.progressProc, codecProgressClose, kModalProgress,
progProc.prog.progressRefCon);
PrClose();
return theErr;
}
static OSErr DrawToPrinter(ImageHandle theImage, NestedProgressPtr progProc)
{
Rect printRect, srcRect, dstRect, boundsRect;
NestedProgress innerProg;
OSErr theErr = noErr;
// get the printing rectangle, and inset it by 1/2 inch on all sides
printRect = (*gPrintRecord)->prInfo.rPage;
InsetRect(&printRect, (*gPrintRecord)->prInfo.iHRes / 2,
(*gPrintRecord)->prInfo.iVRes / 2);
// calculate the appropriate source/destination rectangles
srcRect = (*theImage)->crect;
MaxRect(&srcRect, &printRect, &dstRect);
OffsetRect(&dstRect, (Width(&printRect) - Width(&dstRect)) / 2,
(Height(&printRect) - Height(&dstRect)) / 2);
ClipRect(&dstRect);
boundsRect = (*theImage)->grect;
// set up the bounds of the progress procedure used during drawing
innerProg = *progProc;
innerProg.begin = 0x00001000L;
innerProg.end = 0x0000F000L;
// allocate and initialize the drawing parameters
if (gPrintParams = NewDrawParams(&boundsRect, iqMedium, false, &innerProg,
(*theImage)->privateData)) {
SetUpDrawPort(gPrintParams, kOnscreenPort, (CGrafPtr)qd.thePort, &srcRect,
&dstRect, false);
// preflight the drawing here and save the port
KeepSpinning();
theErr = PreflightDrawing(gPrintParams);
PushPort();
if (theErr == noErr) {
// point to the dummy drawing port and start the inner progress proc
MySetPort((*gPrintParams)->dummy);
CallICMProgressProc((*gPrintParams)->progress.prog.progressProc, codecProgressOpen,
kModalProgress, (*gPrintParams)->progress.prog.progressRefCon);
// now do the drawing, either from the offscreen GWorld...
if ((*theImage)->gworld && GWOrigSize(theImage))
CopyGWorldToGWorld((*theImage)->gworld, (*gPrintParams)->dummy,
&(*theImage)->gworld->portRect, &(*theImage)->gworld->portRect,
srcCopy, nil);
// or from the image directly
else theErr = (*theImage)->format->draw((*theImage)->data, gPrintParams);
// clean up our drawing, checking for missed aborts
if (theErr == noErr) theErr = PostflightDrawing(gPrintParams);
else PostflightDrawing(gPrintParams);
// if we were aborted, tell the printer so, and close the inner prog.
if (theErr == codecAbortErr) PrSetError(iPrAbort);
CallICMProgressProc((*gPrintParams)->progress.prog.progressProc, codecProgressClose,
0L, (*gPrintParams)->progress.prog.progressRefCon);
KeepSpinning();
}
PopPort();
DisposeHandle((Handle)gPrintParams);
}
return theErr;
}
static OSErr GetPrintParams(void)
{
OSErr theErr = AEInteractWithUser(kAEDefaultTimeout, &gTheNotification,
gAEIdleProc);
if (!gPrintRecord) {
if (LoadPrefsHandle(kPrefsPrintType, 0, (Handle *)&gPrintRecord) != noErr) {
if (!(gPrintRecord = (THPrint)NewHandle(sizeof(TPrint)))) return memFullErr;
PrintDefault(gPrintRecord);
} else PrValidate(gPrintRecord);
}
if (theErr != errAENoUserInteraction) {
StopSpinning(&qd.arrow);
FWDeactivate();
if (!PrJobDialog(gPrintRecord)) {
FWActivate();
return codecAbortErr;
}
FWActivate();
StartSpinning();
SavePrefsHandle(kPrefsPrintType, 0, (Handle)gPrintRecord);
}
return theErr;
}
static pascal void PrintIdleProc(void)
{
short oldResFile = CurResFile();
UseResFile(gOurResFile);
PushPort();
if (CheckAbort(gPrintParams)) PrSetError(iPrAbort);
PopPort();
UseResFile(oldResFile);
}
/*
* HandleQuitApplication(theEvent, reply, refCon)
*
* Purpose: AppleEvent handler for the quit application event; we set the done flag,
* clean up all the windows, restore the menu bar, and return
* 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 HandleQuitApplication(AppleEvent *theEvent, AppleEvent *reply, long refCon)
{
#if applec
#pragma unused(theEvent, reply, refCon)
#endif
AEBegin();
gDone = true;
AEEnd();
return noErr;
}