JPEGView/Source/C/GeneralMenus.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
19 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 variables:
* lFileMenu = handle to the File menu
* lEditMenu = handle to the Edit menu
* lViewMenu = handle to the View menu
* lColorMenu = handle to the Colors menu
* lWindowMenu = handle to the Window menu
* lHelpMenu = handle to the help menu
* lMenuPalette = handle to the palette used when saving the window contents
* lMenuGWorld = pointer to the GWorld to CopyBits() into
* lMenuDither = flag: true if we dithered the image under the menu bar
* lMenuimage = pointer to the image whose contents are saved in lMenuGWorld
*
*/
static MenuHandle gFileMenu, gEditMenu, gViewMenu, gColorMenu, gWindowMenu, gHelpMenu,
gQualityMenu;
static PaletteHandle gMenuPalette = nil;
static GWorldPtr gMenuGWorld = nil;
static Boolean gMenuDither = false;
static ImageHandle gMenuImage = nil;
static short gMenuDepth = 32;
static Rect gMenuRect;
/*
* MenuBarInit()
*
* Purpose: Loads the menu resources, installs the help item, and gets handles to
* all the menus
* Inputs: none
* Returns: nothing
*
*/
void MenuBarInit(void)
{
Handle theMenuBar;
RgnHandle theRgn;
FSSpec theSpec;
Rect theRect;
if (theRgn = GetMenuRgn()) {
theRect = (*theRgn)->rgnBBox;
if (!(gMenuGWorld = MyNewGWorld(&theRect, 32, nil, nil, false, false)))
FatalError(errNoMemory);
} else FatalError(errNoMemory);
if ((theMenuBar = GetNewMBar(rMenuBar)) == nil) FatalError(errNoMenu);
SetMenuBar(theMenuBar);
if ((gQualityMenu = GetMenu(rQualityMenu)) == nil) FatalError(errNoMenu);
InsertMenu(gQualityMenu, hierMenu);
if ((gAppleMenu = GetMHandle(rAppleMenu)) == nil) FatalError(errNoMenu);
AddResMenu(gAppleMenu, 'DRVR');
if ((gFileMenu = GetMHandle(rFileMenu)) == nil) FatalError(errNoMenu);
if ((gEditMenu = GetMHandle(rEditMenu)) == nil) FatalError(errNoMenu);
if ((gViewMenu = GetMHandle(rViewMenu)) == nil) FatalError(errNoMenu);
if ((gColorMenu = GetMHandle(rColorsMenu)) == nil) FatalError(errNoMenu);
if ((gWindowMenu = GetMHandle(rWindowMenu)) == nil) FatalError(errNoMenu);
if (HMGetHelpMenuHandle(&gHelpMenu) != noErr) gHelpMenu = nil;
if (gHelpMenu) {
gHelpItem = CountMItems(gHelpMenu);
InsMenuItem(gHelpMenu, gString[strJPEGViewHelp], gHelpItem++);
SetItemCmd(gHelpMenu, gHelpItem, '?');
}
DrawMenuBar();
gSlideFolderValid = (GetSlideSpec(&theSpec) == noErr);
KeepSpinning();
}
extern long MakeMenuSelection(short menu, short item)
{
return ((long)menu << 16) + item;
}
/*
* HandleMenuChoice(theChoice)
*
* Purpose: Handles menu selection and dispatches to the proper menu handler
* Inputs: theChoice = the menu selection, where the high word is the menu ID and
* the low word is the item number
* Returns: nothing
*
*/
void HandleMenuChoice(long theChoice)
{
short item = theChoice & 0xffff, menu = (ulong)theChoice >> 16;
ImageHandle theImage;
theImage = FrontImage();
if (theImage && Full(theImage) && ((*theImage)->dmon == gMainMonitor) &&
gMenuVisible && gSlideShow != kPaused) {
RehideMenuBar();
ActivateAnts((*theImage)->ants);
}
switch (menu) {
case rAppleMenu:
HandleAppleChoice(item);
break;
case rFileMenu:
HandleFileChoice(item);
break;
case rEditMenu:
HandleEditChoice(item);
break;
case rViewMenu:
HandleViewChoice(item);
break;
case rColorsMenu:
HandleColorChoice(item);
break;
case rQualityMenu:
HandleQualityChoice(item);
break;
case rWindowMenu:
HandleWindowChoice(item);
break;
case kHMHelpMenuID:
HandleHelpChoice(item);
break;
}
SetStatistics();
if (!gDone) {
MySetPort(nil);
HiliteMenu(0);
}
}
/*
* SaveMenuArea()
*
* Purpose: Saves the area behind the menubar in the offscreen GWorld
* Inputs: none
* Returns: nothing
*
*/
void SaveMenuArea(void)
{
RgnHandle menuRgn = GetMenuRgn();
Rect menuRect = (*menuRgn)->rgnBBox;
PixMapHandle src, dst;
WindowPtr theWindow;
char sState, dState, pState;
ImageHandle theImage;
Boolean newGWorld = false;
if (theWindow = FWFrontWindow()) {
if (theImage = FindImage(theWindow)) {
if (gMenuGWorld) {
PushPort();
MySetPort(gMenuGWorld);
sState = HGetState((Handle)(src = GetGWorldPixMap((GWorldPtr)theWindow)));
dState = HGetState((Handle)(dst = GetGWorldPixMap(gMenuGWorld)));
pState = GetPixelsState(dst);
HLock((Handle)src);
HLock((Handle)dst);
LockPixels(dst);
RGBForeColor(&gBlack);
RGBBackColor(&gWhite);
HideCursor();
CopyBits((BitMap *)*src, (BitMap *)*dst, &menuRect, &menuRect, srcCopy, nil);
ShowCursor();
SetPixelsState(dst, pState);
HSetState((Handle)dst, dState);
HSetState((Handle)src, sState);
gMenuImage = theImage;
gMenuDither = Dithered(theImage);
gMenuPalette = (*theImage)->palette;
gMenuRect = (*theImage)->wrect;
gMenuDepth = (*(*(*gMainMonitor)->device)->gdPMap)->pixelSize;
PopPort();
return;
}
}
}
gMenuImage = nil;
}
/*
* RestoreMenuArea()
*
* Purpose: Restores the area behind the menubar in the offscreen GWorld
* Inputs: none
* Returns: nothing
*
*/
void RestoreMenuArea(void)
{
RgnHandle menuRgn = GetMenuRgn();
Rect menuRect = (*menuRgn)->rgnBBox;
PixMapHandle src, dst;
ImageHandle theImage;
WindowPtr theWindow;
char sState, dState, pState;
if (!gMenuGWorld) return;
if (theWindow = FWFrontWindow()) {
if (theWindow && gMenuImage && (theImage = FindImage(theWindow)) == gMenuImage) {
if (Dithered(theImage) == gMenuDither &&
(*theImage)->palette == gMenuPalette &&
(*(*(*gMainMonitor)->device)->gdPMap)->pixelSize == gMenuDepth &&
EqualSizeRect(&(*theImage)->wrect, &gMenuRect)) {
PushPort();
MySetPort((CGrafPtr)theWindow);
ClipRect(&menuRect);
sState = HGetState((Handle)(src = GetGWorldPixMap(gMenuGWorld)));
dState = HGetState((Handle)(dst = GetGWorldPixMap((GWorldPtr)theWindow)));
pState = GetPixelsState(src);
HLock((Handle)src);
HLock((Handle)dst);
LockPixels(src);
RGBForeColor(&gBlack);
RGBBackColor(&gWhite);
HideCursor();
CopyBits((BitMap *)*src, (BitMap *)*dst, &menuRect, &menuRect, srcCopy, nil);
ShowCursor();
SetPixelsState(src, pState);
HSetState((Handle)dst, dState);
HSetState((Handle)src, sState);
ValidRect(&menuRect);
PopPort();
return;
}
}
}
}
/*
* DisableMenus()
*
* Purpose: Disables all the menu titles
* Inputs: none
* Returns: nothing
*
*/
void DisableMenus(void)
{
DisableItem(gAppleMenu, 0);
DisableItem(gFileMenu, 0);
DisableItem(gEditMenu, 0);
DisableItem(gViewMenu, 0);
DisableItem(gColorMenu, 0);
DisableItem(gWindowMenu, 0);
gMenuEnabled = false;
if (gMenuVisible) {
PushPort();
MySetPort(nil);
MyInvalMenuBar();
PopPort();
}
}
/*
* EnableMenus()
*
* Purpose: Enables all appropriate menu titles
* Inputs: none
* Returns: nothing
*
*/
void EnableMenus(void)
{
EnableItem(gAppleMenu, 0);
EnableItem(gFileMenu, 0);
if (FrontImage()) {
EnableItem(gEditMenu, CanSelectScreen());
EnableItem(gViewMenu, 0);
EnableItem(gColorMenu, 0);
}
EnableItem(gWindowMenu, 0);
MyInvalMenuBar();
gMenuEnabled = true;
}
/*
* AdjustMenus()
*
* Purpose: Adjusts the menus to reflect the current program status
* Inputs: none
* Returns: nothing
*
*/
void AdjustMenus(void)
{
short var;
var = FWFrontWindow() ? GetWVariant(FWFrontWindow()) : 0;
MenuEnable(gAppleMenu, 0, var != dBoxProc);
MenuEnable(gAppleMenu, appleAboutItem, var != movableDBoxProc && !gDrawing && !gSlideShow);
MenuEnable(gAppleMenu, appleAboutHelpItem, var != movableDBoxProc && !gDrawing && !gSlideShow);
AdjustFile(var);
AdjustEdit(var);
AdjustView(var);
AdjustColor(var);
AdjustWindow(var);
if (gHelpMenu) MenuEnable(gHelpMenu, gHelpItem,
var != movableDBoxProc && !gDrawing && gSlideShow != kRunning);
if (LMGetTheMenu()) MyInvalMenuBar();
else DrawMenuBar();
}
/*
* AdjustFile(var)
*
* Purpose: Adjusts the File menu to reflect the current program status
* Inputs: var = the window type so we can enable/disable for dialogs
* Returns: nothing
*
*/
void AdjustFile(short var)
{
WindowPtr frontWindow = FWFrontWindow();
ImageHandle theImage = FrontImage();
MenuEnable(gFileMenu, 0, var != dBoxProc && var != movableDBoxProc && !gDrawing);
if (gSlideShow) {
DisableItem(gFileMenu, fileOpenItem);
DisableItem(gFileMenu, fileImportItem);
MenuEnable(gFileMenu, fileCloseItem,
frontWindow && frontWindow != GetSlideBackWindow() && !theImage);
DisableItem(gFileMenu, fileCloseAllItem);
DisableItem(gFileMenu, fileSaveItem);
DisableItem(gFileMenu, filePageSetupItem);
DisableItem(gFileMenu, filePrintItem);
SetItem(gFileMenu, fileStartSlideItem, gString[strResumeSlideShow]);
MenuEnable(gFileMenu, fileStartSlideItem, gSlideShow == kPaused);
EnableItem(gFileMenu, fileEndSlideItem);
} else {
EnableItem(gFileMenu, fileOpenItem);
EnableItem(gFileMenu, fileImportItem);
MenuEnable(gFileMenu, fileCloseItem, frontWindow);
MenuEnable(gFileMenu, fileCloseAllItem, gImageRoot);
MenuEnable(gFileMenu, fileSaveItem, theImage);// && !Cropped(theImage));
SetItem(gFileMenu, fileStartSlideItem, gString[strBeginSlideShow]);
MenuEnable(gFileMenu, fileStartSlideItem, ((*gSlideOptions)->fromMemory && gImageRoot) ||
(!(*gSlideOptions)->fromMemory && gSlideFolderValid));
DisableItem(gFileMenu, fileEndSlideItem);
EnableItem(gFileMenu, filePageSetupItem);
MenuEnable(gFileMenu, filePrintItem, theImage);
EnableItem(gFileMenu, fileQuitItem);
}
}
/*
* AdjustEdit(var)
*
* Purpose: Adjusts the Edit menu to reflect the current program status
* Inputs: var = the window type so we can enable/disable for dialogs
* Returns: nothing
*
*/
void AdjustEdit(short var)
{
#if applec
#pragma unused(var)
#endif
WindowPtr frontWindow = FWFrontWindow();
ImageHandle theImage = FrontImage();
Boolean dialog = (frontWindow && WindowKind(frontWindow) == dialogKind);
Boolean enable = theImage && !gSlideShow && CanSelectScreen();
long dialogID = 0;
if (frontWindow) var = GetWVariant(frontWindow);
if (dialog) dialogID = GetWRefCon(frontWindow);
if (dialog && (dialogID != kSlideShowDialogID || (*gSlideOptions)->userControl)) {
MenuEnable(gEditMenu, 0, false);
return;
}
if (gDrawing || gSlideShow == kRunning) {
MenuEnable(gEditMenu, 0, false);
return;
}
MenuEnable(gEditMenu, 0, dialog || theImage);
MenuEnable(gEditMenu, editUndoItem, false);
MenuEnable(gEditMenu, editCutItem, dialog);
MenuEnable(gEditMenu, editCopyItem, dialog || theImage);
MenuEnable(gEditMenu, editPasteItem, dialog);
MenuEnable(gEditMenu, editClearItem, dialog);
MenuEnable(gEditMenu, editSelectScreenItem, enable);
MenuEnable(gEditMenu, editCropItem, !gSlideShow && theImage &&
!IsAboutBox(theImage) && AntsHaveSelection((*theImage)->ants));
MenuEnable(gEditMenu, editUncropItem, !gSlideShow && theImage && Cropped(theImage) &&
!Banded(theImage));
}
/*
* CanSelectScreen()
*
* Purpose: Determines if we should allow select screen area
* Inputs: none
* Returns: true if we're allowed to select the screen area; false otherwise
*
*/
Boolean CanSelectScreen(void)
{
ImageHandle theImage = FrontImage();
Rect theRect;
if (!theImage) return false;
GetActiveRect((*theImage)->dmon, &theRect);
if (!Full(theImage)) theRect.top += gTitleBarHeight;
return (Width(&(*theImage)->crect) > Width(&theRect)) ||
(Height(&(*theImage)->crect) > Height(&theRect));
}
/*
* AdjustView(var)
*
* Purpose: Adjusts the View menu to reflect the current program status
* Inputs: var = the window type so we can enable/disable for dialogs
* Returns: nothing
*
*/
void AdjustView(short var)
{
#if applec
#pragma unused(var)
#endif
ImageHandle theImage = FrontImage();
Rect theRect;
if (theImage) {
GetActiveRect((*theImage)->dmon, &theRect);
if (!Full(theImage)) theRect.top += gTitleBarHeight;
}
MenuEnable(gViewMenu, 0, !gSlideShow && !gDrawing && theImage && theImage == FrontImage());
CheckItem(gViewMenu, viewFullScreenItem, theImage && Full(theImage));
MenuEnable(gViewMenu, viewNormalItem,
theImage && !EqualSizeRect(&(*theImage)->wrect, &(*theImage)->crect));
MenuEnable(gViewMenu, viewHalfItem, theImage && !IsAboutBox(theImage) &&
(Width(&(*theImage)->wrect) > 64) && (Height(&(*theImage)->wrect) > 64));
MenuEnable(gViewMenu, viewDoubleItem, theImage && !IsAboutBox(theImage) &&
((Width(&(*theImage)->wrect) << 1) <= Width(&theRect)) &&
((Height(&(*theImage)->wrect) << 1) <= Height(&theRect)));
MenuEnable(gViewMenu, viewMaxItem, theImage && !IsAboutBox(theImage) &&
(Width(&(*theImage)->wrect) != Width(&theRect)) &&
(Height(&(*theImage)->wrect) != Height(&theRect)));
MenuEnable(gViewMenu, viewShrinkItem, theImage && !IsAboutBox(theImage) &&
(Width(&(*theImage)->wrect) > 36) && (Height(&(*theImage)->wrect) > 36));
MenuEnable(gViewMenu, viewExpandItem, theImage && !IsAboutBox(theImage) &&
((11 * Width(&(*theImage)->wrect) / 10) <= Width(&theRect)) &&
((11 * Height(&(*theImage)->wrect) / 10) <= Height(&theRect)));
}
/*
* AdjustColor(var)
*
* Purpose: Adjusts the Color menu to reflect the current program status
* Inputs: var = the window type so we can enable/disable for dialogs
* Returns: nothing
*
*/
void AdjustColor(short var)
{
#if applec
#pragma unused(var)
#endif
short mdepth = 0, depth = 0, palette;
ImageHandle theImage = FrontImage();
Boolean enabled;
if (!gSlideShow && !gDrawing && theImage && (*theImage)->smon && (*theImage)->dmon) {
EnableItem(gColorMenu, 0);
mdepth = (*(*theImage)->smon)->depth;
depth = (*(*theImage)->dmon)->depth;
palette = (*theImage)->npalette;
enabled = (depth >= 4);
MenuEnable(gColorMenu, colorSysItem, enabled);
CheckItem(gColorMenu, colorSysItem, enabled && (palette == plSys));
enabled = (mdepth <= 8);
MenuEnable(gColorMenu, colorGrayItem, enabled);
CheckItem(gColorMenu, colorGrayItem, enabled && (palette == plGrey));
enabled = ((*theImage)->ipalette != nil) && (depth >= 4) && (mdepth <= 8) &&
((*(*theImage)->ipalette)->pmEntries <= (1L << depth));
MenuEnable(gColorMenu, colorImageItem, enabled);
CheckItem(gColorMenu, colorImageItem, enabled && (palette == plImage));
enabled = (depth >= 4) && (mdepth <= 8) && ((*theImage)->depth >= 16);
MenuEnable(gColorMenu, colorQuantItem, enabled);
CheckItem(gColorMenu, colorQuantItem, enabled && (palette == plQuant));
enabled = (depth <= 16);
MenuEnable(gColorMenu, colorDitherItem, enabled);
CheckItem(gColorMenu, colorDitherItem, enabled && Dithered(theImage));
enabled = ((*theImage)->depth >= 24) &&
((depth > 8) || ((depth == 8) && ((*theImage)->npalette != plSys) &&
((*theImage)->npalette != plGrey)));
MenuEnable(gColorMenu, colorQualityItem, enabled);
MenuEnable(gQualityMenu, 0, enabled);
CheckItem(gQualityMenu, qualityVHighItem, enabled &&
((*theImage)->quality == iqVHigh));
MenuEnable(gQualityMenu, qualityHighItem, enabled && (depth < 24));
CheckItem(gQualityMenu, qualityHighItem, enabled && (depth < 24) &&
((*theImage)->quality == iqHigh));
CheckItem(gQualityMenu, qualityMediumItem, enabled &&
((*theImage)->quality == iqMedium) ||
(((*theImage)->quality == iqHigh) && (depth >= 24)));
} else {
CheckItem(gColorMenu, colorSysItem, false);
CheckItem(gColorMenu, colorGrayItem, false);
CheckItem(gColorMenu, colorImageItem, false);
CheckItem(gColorMenu, colorQuantItem, false);
CheckItem(gColorMenu, colorDitherItem, false);
DisableItem(gColorMenu, 0);
}
}
/*
* AdjustWindow(var)
*
* Purpose: Adjusts the Window menu to reflect the current program status
* Inputs: var = the window type so we can enable/disable for dialogs
* Returns: nothing
*
*/
void AdjustWindow(short var)
{
ImageHandle theImage;
short theItem;
MenuEnable(gWindowMenu, 0, var != dBoxProc && var != movableDBoxProc && !gDrawing);
MenuEnable(gWindowMenu, windowStatItem, true);
MenuEnable(gWindowMenu, windowCommentsItem, true);
MenuEnable(gWindowMenu, windowPreviousItem, !gSlideShow && gImageRoot && (*gImageRoot)->next);
MenuEnable(gWindowMenu, windowNextItem, !gSlideShow && gImageRoot && (*gImageRoot)->next);
for (theImage = gImageRoot, theItem = windowFirstItem; theImage;
theImage = (*theImage)->next, theItem++) {
CheckItem(gWindowMenu, theItem, (*theImage)->window == FWFrontWindow());
MenuEnable(gWindowMenu, theItem, !gSlideShow);
}
if (GetStatWindow()) SetItem(gWindowMenu, windowStatItem, gString[strHideStatistics]);
else SetItem(gWindowMenu, windowStatItem, gString[strShowStatistics]);
if (GetCommentsWindow()) SetItem(gWindowMenu, windowCommentsItem, gString[strHideComments]);
else SetItem(gWindowMenu, windowCommentsItem, gString[strShowComments]);
if (GetColorsWindow()) SetItem(gWindowMenu, windowColorsItem, gString[strHideColors]);
else SetItem(gWindowMenu, windowColorsItem, gString[strShowColors]);
theImage = FrontImage();
if (theImage && (*theImage)->comments)
SetItemMark(gWindowMenu, windowCommentsItem, diamondMark);
else SetItemMark(gWindowMenu, windowCommentsItem, noMark);
}
/*
* AddWindowItem(theImage)
*
* Purpose: Adds the name of theImage to the bottom of the Window menu
* Inputs: none
* Returns: nothing
*
*/
void AddWindowItem(ImageHandle theImage)
{
int item = GetDocumentIndex((*theImage)->window) + windowFirstItem - 1;
Str255 theItem;
if (gImageRoot == theImage && !(*theImage)->next) AppendMenu(gWindowMenu, (StringPtr)"\p(-");
AppendMenu(gWindowMenu, (StringPtr)"\p ");
BlockMove((*theImage)->file.name, theItem, 64);
if ((*theImage)->num) {
AddChar(theItem, ' ');
AddNumber(theItem, (*theImage)->num);
}
SetItem(gWindowMenu, item, theItem);
if (item < (9 + windowFirstItem))
SetItemCmd(gWindowMenu, item, item - windowFirstItem + '1');
}
/*
* DeleteWindowItem(theImage)
*
* Purpose: Removes the name of theImage from the Window menu
* Inputs: none
* Returns: nothing
*
*/
void DeleteWindowItem(ImageHandle theImage)
{
int item = GetDocumentIndex((*theImage)->window) + windowFirstItem - 1;
ImageHandle image;
if (item > CountMItems(gWindowMenu)) return;
DelMenuItem(gWindowMenu, item);
for (item = windowFirstItem, image = gImageRoot; image; image = (*image)->next)
if (image != theImage && item < (9 + windowFirstItem)) {
SetItemCmd(gWindowMenu, item, item - windowFirstItem + '1');
item++;
}
if (gImageRoot == theImage && !(*theImage)->next)
DelMenuItem(gWindowMenu, windowFirstItem - 1);
}