mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-01 03:41:27 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
15 KiB
C
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;
|
|
}
|