JPEGView/Source/C/FileMenu.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
16 KiB
C

/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information. */
/* Contact email: mac@aarongiles.com */
/*********************************************************/
//=====================================================================================
// Generic includes for Macintosh headers
//=====================================================================================
#if THINK_C
#include "THINK.Header"
#elif applec
#pragma load ":Headers:MPW.Header"
#elif __MWERKS__
//#include "MW.Header"
#else
#include "JPEGView.h"
#endif
//=====================================================================================
// Includes specific to this module
//=====================================================================================
#include "FileMenu.h"
//===================================================================================
// OpenData: Contains options information that is set from within the Open dialog.
//===================================================================================
typedef struct
{
Boolean showAll;
short lastVRef;
long lastDir;
} OpenData, *OpenDataPtr, **OpenDataHandle;
//===================================================================================
// SaveData: Contains options information that is set from within the Save dialog.
//===================================================================================
typedef struct
{
Boolean preview, close, palette, icons;
short cropWhat;
ImageFormatPtr format;
ImageFormatPtr formatList[kFileFormats];
ImageHandle image;
MenuHandle menuHandle;
MenuHandle cropHandle;
} SaveData, *SaveDataPtr, **SaveDataHandle;
//=====================================================================================
// Global variables local to this module
//=====================================================================================
static DlgHookYDUPP gOpenDialogHook = nil, gSaveDialogHook = nil;
static FileFilterYDUPP gOpenFileFilter = nil;
static OpenData gOpenData;
static SaveData gSaveData;
//=====================================================================================
// Prototypes for functions local to this module
//=====================================================================================
static void InitSaveMenu(ImageHandle theImage, DialogPtr theDialog);
static void DoPageSetup(void);
//===================================================================================
// void HandleFileChoice(short theItem)
//===================================================================================
// Dispatches selections from the File menu to the appropriate function.
//===================================================================================
void HandleFileChoice(short theItem)
{
switch (theItem) {
case fileImportItem:
gOpenData.showAll = true;
DoOpenDialog();
break;
case fileOpenItem:
gOpenData.showAll = false;
DoOpenDialog();
break;
case fileCloseItem:
SendCloseWindow(FWFrontWindow());
break;
case fileCloseAllItem:
SendCloseWindow((WindowPtr)kAEAll);
break;
case fileSaveItem:
DoSaveDialog();
break;
case fileSlideItem:
SendCreateWindow(kSlideShowDialogID);
break;
case fileStartSlideItem:
if (gSlideShow) gPendingButton = kPauseButton;
else SendSlideShow();
break;
case fileEndSlideItem:
gPendingButton = kStopButton;
break;
case filePageSetupItem:
DoPageSetup();
break;
case filePrintItem:
if (FrontImage()) SendPrintDocument(FrontImage());
break;
case filePrefsItem:
SendCreateWindow(kPrefsDialogID);
break;
case fileQuitItem:
SendQuitApplication();
break;
}
}
/*
* DoOpenDialog()
*
* Purpose: Presents the JPEGView custom open dialog & sends the
* open document AppleEvent
* Inputs: none
* Returns: nothing
*
*/
void DoOpenDialog(void)
{
Point where = CenterDialogWhere((gQTVersion) ? rOpenDialog : rOpenDialogNoQT);
StandardFileReply reply;
StartSpinning();
PushPort();
MySetPort(nil);
if (!gOpenFileFilter)
gOpenFileFilter = NewFileFilterYDProc((ProcPtr)OpenFileFilter);
if (!gOpenDialogHook)
gOpenDialogHook = NewDlgHookYDProc((ProcPtr)OpenDialogHook);
RequestForeground();
if (gQTVersion) CustomGetFilePreview(gOpenFileFilter, -1, 0, &reply, rOpenDialog, where,
gOpenDialogHook, gOpenSaveModalFilter, nil, nil, &reply);
else CustomGetFile(gOpenFileFilter, -1, 0, &reply, rOpenDialogNoQT, where,
gOpenDialogHook, gOpenSaveModalFilter, nil, nil, &reply);
PopPort();
if (reply.sfGood) SendOpenDocument(&reply.sfFile);
}
/*
* OpenSaveModalFilter(theDialog, theEvent, itemHit, yourDataPtr)
*
* Purpose: Filter for handling update events
* Inputs: theDialog = pointer to the dialog
* theEvent = pointer to an event record
* itemHit = the item number that was "hit"
* yourDataPtr = the refcon
* Returns: true if we want ModalDialog to continue processing the event
*
*/
extern pascal Boolean OpenSaveModalFilter(DialogPtr theDialog, EventRecord *theEvent,
short *itemHit, void *yourDataPtr)
{
#if applec
#pragma unused(theDialog, itemHit, yourDataPtr)
#endif
Boolean isDialogEvent = IsDialogEvent(theEvent);
switch (theEvent->what) {
case updateEvt:
if (isDialogEvent) HandleUpdateDialog(theEvent);
else HandleUpdateEvent(theEvent);
break;
case activateEvt:
if (isDialogEvent) HandleActivateDialog(theEvent);
else HandleActivateEvent(theEvent);
break;
}
return false;
}
/*
* OpenFileFilter(pb, dummy)
*
* Purpose: Called by CustomGetFilePreview to allow us to filter out certain types
* of files; here, depending on the status of the Show All Files button,
* we either allow all files or only PICT/JFIF/JPEG/GIFf files
* Inputs: pb = parameter block for the current file
* dummy = a dummy reference constant
* Returns: false to include the file, true otherwise
*
*/
pascal Boolean OpenFileFilter(CInfoPBPtr pb, Boolean *dummy)
{
#if applec
#pragma unused(dummy)
#endif
OSType theType = pb->hFileInfo.ioFlFndrInfo.fdType;
if (pb->dirInfo.ioDrUsrWds.frFlags & fInvisible) return true;
return !((pb->hFileInfo.ioFlAttrib & 0x10) || ValidType(theType) || gOpenData.showAll);
}
extern Boolean ValidType(OSType theType)
{
short i;
for (i = 0; i < kFileFormats; i++)
if (gFormat[i]->inType == theType || gFormat[i]->altInType == theType) return true;
return false;
}
/*
* OpenDialogHook(item, theDialog, dummy)
*
* Purpose: Called by CustomGetFilePreview to allow us to respond to our custom
* dialog items; here we have only one, the Show All Files button
* Inputs: item = the dialog item number that was hit
* theDialog = pointer to the dialog window record
* dummy = dummy reference constant
* Returns: the item that was hit, or sfHookRebuildList to redisply the files
*
*/
pascal short OpenDialogHook(short item, DialogPtr theDialog, long dummy)
{
static short gLastItem = 0, gLastVRefNum = 555;
SysEnvRec theEnvirons;
if (GetWRefCon(theDialog) != sfMainDialogRefCon) return item;
if (gLastItem == sfItemEjectButton) {
SysEnvirons(1, &theEnvirons);
if (theEnvirons.sysVRefNum != gLastVRefNum) {
UnmountVol(0, gLastVRefNum);
Eject(0, gLastVRefNum);
}
}
switch (item) {
case sfHookFirstCall:
HiliteMenu(0);
FWDeactivate();
StopSpinning(&qd.arrow);
break;
case sfHookLastCall:
FWActivate();
break;
case openScanButton:
StartSpinning();
ScanDirFiles();
DisableDControl(theDialog, openScanButton);
StopSpinning(&qd.arrow);
item = sfHookRebuildList;
break;
default:
if ((gOpenData.lastVRef != -LMGetSFSaveDisk()) ||
(gOpenData.lastDir != LMGetCurDirStore()))
EnableDControl(theDialog, openScanButton);
break;
}
gLastVRefNum = ((StandardFileReply *)dummy)->sfFile.vRefNum;
return gLastItem = item;
}
/*
* ScanDirFiles()
*
* Purpose: Scans the current standard file directory for valid input files; if it
* finds some, it changes their types accordingly
* Inputs: none
* Returns: nothing
*
*/
void ScanDirFiles(void)
{
short theFile, fileType;
CInfoPBRec block;
Str255 fileName;
OSType theType;
FSSpec theSpec;
FInfo theInfo;
block.hFileInfo.ioNamePtr = fileName;
block.hFileInfo.ioVRefNum = -LMGetSFSaveDisk();
block.hFileInfo.ioDirID = LMGetCurDirStore();
block.hFileInfo.ioFDirIndex = 1;
while (PBGetCatInfo(&block, false) == noErr) {
KeepSpinning();
theType = block.hFileInfo.ioFlFndrInfo.fdType;
if (!(block.hFileInfo.ioFlAttrib & 0x10) && !ValidType(theType)) {
FSMakeFSSpec(-LMGetSFSaveDisk(), block.hFileInfo.ioFlParID, fileName, &theSpec);
if (FSpOpenDF(&theSpec, fsRdPerm, &theFile) == noErr) {
fileType = IDImage(theFile, &theSpec);
FSClose(theFile);
if (fileType != kInvalidType) {
FSpGetFInfo(&theSpec, &theInfo);
theInfo.fdType = gFormat[fileType]->inType;
theInfo.fdCreator = kCreator;
FSpSetFInfo(&theSpec, &theInfo);
}
}
}
block.hFileInfo.ioFDirIndex++;
block.hFileInfo.ioDirID = LMGetCurDirStore();
}
gOpenData.lastDir = LMGetCurDirStore();
gOpenData.lastVRef = -LMGetSFSaveDisk();
ForceFolderUpdate(LMGetCurDirStore(), -LMGetSFSaveDisk());
}
/*
* DoSaveDialog()
*
* Purpose: Presents the JPEGView save dialog and sends the save document AppleEvent
* Inputs: none
* Returns: nothing
*
*/
void DoSaveDialog(void)
{
Point where = CenterDialogWhere(rSaveDialog);
ImageHandle theImage = FrontImage();
StandardFileReply reply;
Str255 defaultName;
OSErr theErr;
StartSpinning();
gSaveData.image = theImage;
gSaveData.format = (*theImage)->format;
gSaveData.preview = gThePrefs.savePrev;
gSaveData.icons = gThePrefs.makeIcons;
gSaveData.close = gSaveData.palette = false;
if ((*theImage)->qpalette && gSaveData.format->doesColors) {
if (gThePrefs.saveQuant == sqAlways) gSaveData.palette = true;
else if (gThePrefs.saveQuant == sqOnly) gSaveData.palette = !(*theImage)->ipalette;
}
gSaveData.cropWhat = kCropNothing;
BlockMove((*theImage)->file.name, defaultName, 64);
PushPort();
MySetPort(nil);
FWDeactivate();
if (!gSaveDialogHook) gSaveDialogHook = NewDlgHookYDProc((ProcPtr)SaveDialogHook);
RequestForeground();
CustomPutFile(gNullString, defaultName, &reply,
((*theImage)->compression == kJPEGCompression) ? rSaveDialog : rSimpleSaveDialog,
where, gSaveDialogHook, gOpenSaveModalFilter, nil, nil, 0);
PopPort();
if (reply.sfGood) {
if (!reply.sfReplacing) {
theErr = FSpCreate(&reply.sfFile, kCreator, gSaveData.format->outType,
reply.sfScript);
if (theErr != noErr) {
StringError(errCantCreateFile, reply.sfFile.name);
return;
}
}
theErr = SendSaveDocument(&reply.sfFile, gSaveData.format->outType,
gSaveData.preview && gQTVersion,
gSaveData.palette && gSaveData.format->doesColors &&
(*gSaveData.image)->depth > 8 &&
(*gSaveData.image)->compression == kJPEGCompression,
gSaveData.icons, gSaveData.cropWhat);
if (theErr == noErr) {
if (gSaveData.close) SendCloseWindow((*theImage)->window);
}
}
}
static void InitSaveMenu(ImageHandle theImage, DialogPtr theDialog)
{
short itemType, i, startValue = 1, pictItem = 0, count = 0;
Handle itemHandle;
Rect itemRect;
// first get the handle to the pop-up menu
GetDItem(theDialog, savePopupMenu, &itemType, &itemHandle, &itemRect);
if (itemHandle) gSaveData.menuHandle =
(*(PopupPrivateDataHandle)(*(ControlHandle)itemHandle)->contrlData)->mHandle;
// now loop over all formats, adding them all, but only enabling those that match the
// input format, as well as any formats that have a fix routine, but then only if the
// image compression is 'jpeg'
for (i = 0; i < kFileFormats; i++) {
if (gFormat[i] == (*theImage)->format ||
(gFormat[i]->fix && (*theImage)->compression == kJPEGCompression)) {
AppendMenu(gSaveData.menuHandle, (StringPtr)"\p( ");
gSaveData.formatList[count] = gFormat[i];
SetItem(gSaveData.menuHandle, ++count, gFormat[i]->formatName);
if (gFormat[i]->outType == kPICTType) pictItem = count;
if (gFormat[i] == (*theImage)->format) startValue = count;
if (Banded(theImage) && !gFormat[i]->doesBanded) continue;
EnableItem(gSaveData.menuHandle, count);
}
}
if (gThePrefs.savePICT && (*theImage)->format->inType == kJPEGType) {
startValue = pictItem;
gSaveData.format = &gPICTFormat;
}
SetCtlMax((ControlHandle)itemHandle, count);
SetCtlValue((ControlHandle)itemHandle, startValue);
// next get the handle to the cropping pop-up menu
GetDItem(theDialog, saveCropMenu, &itemType, &itemHandle, &itemRect);
if (itemHandle) gSaveData.cropHandle =
(*(PopupPrivateDataHandle)(*(ControlHandle)itemHandle)->contrlData)->mHandle;
}
/*
* UpdateSaveButtons(theDialog)
*
* Purpose: Updates the state of the custom buttons in the save dialog
* Inputs: theDialog
* Returns: nothing
*
*/
void UpdateSaveButtons(DialogPtr theDialog)
{
ImageHandle theImage = gSaveData.image;
Boolean enabled;
SetDCtlValue(theDialog, saveCloseBox, gSaveData.close);
enabled = (gQTVersion != 0);
if (enabled) EnableDControl(theDialog, savePreviewBox);
else DisableDControl(theDialog, savePreviewBox);
SetDCtlValue(theDialog, savePreviewBox, gSaveData.preview && enabled);
enabled = gSaveData.format->doesColors && (*gSaveData.image)->depth > 8 && (*gSaveData.image)->compression == kJPEGCompression;
if (enabled) EnableDControl(theDialog, savePaletteBox);
else DisableDControl(theDialog, savePaletteBox);
SetDCtlValue(theDialog, savePaletteBox, gSaveData.palette && enabled);
SetDCtlValue(theDialog, saveIconsBox, gSaveData.icons);
if (!gSaveData.icons && gSaveData.cropWhat == kCropIcon) SetDCtlValue(theDialog, saveCropMenu, kCropNothing + 1);
if (gSaveData.icons) EnableItem(gSaveData.cropHandle, kCropIcon + 1);
else DisableItem(gSaveData.cropHandle, kCropIcon + 1);
}
/*
* SaveDialogHook(item, theDialog, dummy)
*
* Purpose: Called by CustomPutFile to allow us to respond to our custom
* dialog items; here we have only one, the Show All Files button
* Inputs: item = the dialog item number that was hit
* theDialog = pointer to the dialog window record
* dummy = dummy reference constant
* Returns: the item that was hit
*
*/
pascal short SaveDialogHook(short item, DialogPtr theDialog, long dummy)
{
#if applec
#pragma unused(dummy)
#endif
short newValue;
if (GetWRefCon(theDialog) != sfMainDialogRefCon) return item;
switch (item) {
case sfHookFirstCall:
SetItemHandle(theDialog, saveLineUser1, (Handle)gLineItem);
SetItemHandle(theDialog, saveLineUser2, (Handle)gLineItem);
SetItemHandle(theDialog, saveLineUser3, (Handle)gLineItem);
if (!AntsHaveSelection((*gSaveData.image)->ants)) DisableDControl(theDialog, saveCropMenu);
InitSaveMenu(gSaveData.image, theDialog);
UpdateSaveButtons(theDialog);
FWDeactivate();
StopSpinning(&qd.arrow);
return item;
case sfHookLastCall:
FWActivate();
return item;
case saveCloseBox:
gSaveData.close = !gSaveData.close;
break;
case savePopupMenu:
newValue = GetDCtlValue(theDialog, savePopupMenu);
gSaveData.format = gSaveData.formatList[newValue - 1];
break;
case savePreviewBox:
gSaveData.preview = !gSaveData.preview;
break;
case savePaletteBox:
gSaveData.palette = !gSaveData.palette;
break;
case saveIconsBox:
gSaveData.icons = !gSaveData.icons;
break;
case saveCropMenu:
gSaveData.cropWhat = GetDCtlValue(theDialog, saveCropMenu) - 1;
break;
default:
return item;
}
UpdateSaveButtons(theDialog);
return sfHookNullEvent;
}
static void DoPageSetup(void)
{
PrOpen();
if (!gPrintRecord) {
if (LoadPrefsHandle(kPrefsPrintType, 0, (Handle *)&gPrintRecord) != noErr) {
if (!(gPrintRecord = (THPrint)NewHandle(sizeof(TPrint)))) {
MinorError(errNoMemory);
return;
}
PrintDefault(gPrintRecord);
} else PrValidate(gPrintRecord);
}
FWDeactivate();
PrStlDialog(gPrintRecord);
FWActivate();
PrClose();
SavePrefsHandle(kPrefsPrintType, 0, (Handle)gPrintRecord);
}