mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-15 04:29:26 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
19 KiB
C
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 */
|
|
/*********************************************************/
|
|
|
|
//=====================================================================================
|
|
// 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 "SlideControlsWindow.h"
|
|
|
|
//=====================================================================================
|
|
// Global variables local to this module
|
|
//=====================================================================================
|
|
|
|
static short gButtonStatus[4] = { standard, standard, standard, standard };
|
|
static CIconHandle gStandardButton[4] = { nil, nil, nil, nil };
|
|
static CIconHandle gDepressedButton[4] = { nil, nil, nil, nil };
|
|
static CIconHandle gDisabledButton[4] = { nil, nil, nil, nil };
|
|
static WindowPtr gSlideControlsWindow = nil;
|
|
static Str255 gSlideControlsText = "\p";
|
|
static Rect gButtonRect[4];
|
|
|
|
//=====================================================================================
|
|
// Prototypes for functions local to this module
|
|
//=====================================================================================
|
|
|
|
static OSErr LoadButtons(void);
|
|
|
|
//=====================================================================================
|
|
// OSErr OpenSlideControls(void)
|
|
//
|
|
// Creates and initializes the slide show controls floating window.
|
|
//
|
|
// External calls: AllocateWindow, PushPort, MySetPort, GetActiveRect, PlaceWindow,
|
|
// PopPort
|
|
//=====================================================================================
|
|
|
|
extern OSErr OpenSlideControls(void)
|
|
{
|
|
Rect theRect, mainRect;
|
|
OSErr theErr = noErr;
|
|
short width, height;
|
|
FontInfo theInfo;
|
|
Point where;
|
|
short i;
|
|
|
|
if (gSlideControlsWindow) return noErr;
|
|
if (!gStandardButton[0]) theErr = LoadButtons();
|
|
if (!(gSlideControlsWindow = AllocateWindow())) theErr = memFullErr;
|
|
if (theErr != noErr) return theErr;
|
|
PushPort();
|
|
MySetPort(nil);
|
|
if (gSlideControlsWindow = FWGetNewFloatingWindow(rSlideControlsWindow,
|
|
(Ptr)gSlideControlsWindow, (WindowPtr)-1)) {
|
|
MySetPort((CGrafPtr)gSlideControlsWindow);
|
|
TextFont(geneva);
|
|
TextSize(9);
|
|
GetFontInfo(&theInfo);
|
|
width = Width(&(*gStandardButton[0])->iconPMap.bounds);
|
|
height = Height(&(*gStandardButton[0])->iconPMap.bounds);
|
|
theRect.top = theRect.left = 0;
|
|
theRect.right = width * 4;
|
|
theRect.bottom = height + theInfo.ascent + theInfo.descent + theInfo.leading;
|
|
SizeWindow(gSlideControlsWindow, Width(&theRect), Height(&theRect), true);
|
|
GetActiveRect(gMainMonitor, &mainRect);
|
|
where.h = mainRect.right - kWindowBorderWidth - Width(&theRect);
|
|
where.v = mainRect.bottom - kWindowBorderHeight - Height(&theRect);
|
|
PlaceWindow(gSlideControlsWindow, &gThePrefs.slideControlsBounds, where);
|
|
for (i = 0; i < 4; i++) {
|
|
gButtonRect[i].bottom = theRect.bottom;
|
|
gButtonRect[i].top = theRect.bottom - height;
|
|
gButtonRect[i].left = i * width;
|
|
gButtonRect[i].right = i * width + width;
|
|
}
|
|
if (!*gSlideControlsText)
|
|
SetSlideControlsText(gString[strSlideReady], gNullString, gNullString, gNullString);
|
|
PopPort();
|
|
return noErr;
|
|
} else theErr = memFullErr;
|
|
CloseSlideControls();
|
|
PopPort();
|
|
return theErr;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// OSErr LoadButtons(void)
|
|
//
|
|
// Loads up the color icons used for buttons.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
static OSErr LoadButtons(void)
|
|
{
|
|
short buttonType[4] = { rReverseButton, rStopButton, rPauseButton, rForwardButton };
|
|
short button;
|
|
|
|
for (button = 0; button < 4; button++) {
|
|
if (!(gStandardButton[button] = GetCIcon(buttonType[button] + rStandardButton)) ||
|
|
!(gDepressedButton[button] = GetCIcon(buttonType[button] + rDepressedButton)) ||
|
|
!(gDisabledButton[button] = GetCIcon(buttonType[button] + rDisabledButton)))
|
|
return memFullErr;
|
|
HLockHi((Handle)gStandardButton[button]);
|
|
HLockHi((Handle)gDepressedButton[button]);
|
|
HLockHi((Handle)gDisabledButton[button]);
|
|
}
|
|
return noErr;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// OSErr CloseSlideControls(void)
|
|
//
|
|
// Closes the slide show controls window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern void CloseSlideControls(void)
|
|
{
|
|
PushPort();
|
|
MySetPort(nil);
|
|
if (gSlideControlsWindow) {
|
|
SaveWindowPosition(gSlideControlsWindow, &gThePrefs.slideControlsBounds);
|
|
FWCloseWindow(gSlideControlsWindow);
|
|
DeallocateWindow(gSlideControlsWindow);
|
|
}
|
|
gSlideControlsWindow = nil;
|
|
PopPort();
|
|
}
|
|
|
|
//=====================================================================================
|
|
// WindowPtr GetSlideControlsWindow(void)
|
|
//
|
|
// Returns a pointer to the slide show controls window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern WindowPtr GetSlideControlsWindow(void)
|
|
{
|
|
return gSlideControlsWindow;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void SetSlideControlButton(short id, short status)
|
|
//
|
|
// Sets the status of a given control button.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern void SetSlideControlButton(short id, short status)
|
|
{
|
|
gButtonStatus[id] = status;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// short GetSlideControlButton(short id)
|
|
//
|
|
// Returns the status of the given control button.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern short GetSlideControlButton(short id)
|
|
{
|
|
return gButtonStatus[id];
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void DrawSlideControlsWindow(void)
|
|
//
|
|
// Draws the contents of the slide show controls window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern void DrawSlideControlsWindow(void)
|
|
{
|
|
FontInfo theInfo;
|
|
Rect theRect;
|
|
short i;
|
|
|
|
if (!gSlideControlsWindow) return;
|
|
PushPort();
|
|
MySetPort((CGrafPtr)gSlideControlsWindow);
|
|
theRect = gSlideControlsWindow->portRect;
|
|
theRect.bottom = gButtonRect[0].top;
|
|
TextFont(geneva);
|
|
TextSize(9);
|
|
GetFontInfo(&theInfo);
|
|
MoveTo(2, theInfo.ascent + theInfo.leading);
|
|
EraseRect(&theRect);
|
|
TruncString(Width(&gSlideControlsWindow->portRect) - 4, gSlideControlsText, smTruncEnd);
|
|
DrawString(gSlideControlsText);
|
|
for (i = 0; i < 4; i++) {
|
|
if (gButtonStatus[i] == depressed || gPendingButton == i)
|
|
PlotCIcon(&gButtonRect[i], gDepressedButton[i]);
|
|
else if (gButtonStatus[i] == standard) PlotCIcon(&gButtonRect[i], gStandardButton[i]);
|
|
else PlotCIcon(&gButtonRect[i], gDisabledButton[i]);
|
|
}
|
|
PopPort();
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void HandleSlideControlsClick(Point where, short modifiers, Boolean actNow)
|
|
//
|
|
// Draws the contents of the slide show controls window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern void HandleSlideControlsClick(Point where, short modifiers, Boolean actNow)
|
|
{
|
|
long startTime = TickCount();
|
|
Boolean isDepressed = false;
|
|
short button, buttonFunction;
|
|
|
|
gPendingButton = -1;
|
|
PushPort();
|
|
MySetPort((CGrafPtr)gSlideControlsWindow);
|
|
|
|
// convert to local coordinates, and look for a match to a button rectangle
|
|
GlobalToLocal(&where);
|
|
for (button = 0; button < 4; button++)
|
|
if (gButtonStatus[button] == standard && PtInRect(where, &gButtonRect[button])) break;
|
|
|
|
if (gSlideShow == kPaused && PtInRect(where, &gButtonRect[kPauseButton]))
|
|
button = kPauseButton;
|
|
|
|
// if we found one, track it until the mouse is released
|
|
if (button < 4) {
|
|
PlotCIcon(&gButtonRect[button], gDepressedButton[button]);
|
|
isDepressed = true;
|
|
while (StillDown()) {
|
|
GetMouse(&where);
|
|
if (PtInRect(where, &gButtonRect[button])) {
|
|
if (!isDepressed) {
|
|
PlotCIcon(&gButtonRect[button], gDepressedButton[button]);
|
|
isDepressed = true;
|
|
}
|
|
} else if (isDepressed) {
|
|
PlotCIcon(&gButtonRect[button], gStandardButton[button]);
|
|
isDepressed = false;
|
|
}
|
|
}
|
|
|
|
// if button was depressed when released, and we're allowed to act immediately,
|
|
// do the appropriate action
|
|
if (isDepressed) {
|
|
buttonFunction = button;
|
|
if ((modifiers & optionKey) && button == kPauseButton) buttonFunction = kHideButton;
|
|
if (actNow && gSlideShow != kPaused) {
|
|
while ((TickCount() - startTime) < 8);
|
|
PlotCIcon(&gButtonRect[button], gStandardButton[button]);
|
|
if ((*gSlideOptions)->userControl) gSlideShow = HandleUserControlButton(buttonFunction);
|
|
else gSlideShow = HandleAutomaticButton(buttonFunction);
|
|
if (!gSlideShow) CleanUpSlideShow();
|
|
} else gPendingButton = buttonFunction;
|
|
}
|
|
}
|
|
PopPort();
|
|
if (HMIsBalloon()) HMRemoveBalloon();
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void HandleSlideControlsKey(char theChar, short modifiers, Boolean actNow)
|
|
//
|
|
// Draws the contents of the slide show controls window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern void HandleSlideControlsKey(char theChar, short modifiers, Boolean actNow)
|
|
{
|
|
long startTime = TickCount();
|
|
short button, buttonFunction;
|
|
|
|
gPendingButton = -1;
|
|
// associate the keypress with one of the buttons
|
|
if (theChar == kEscapeChar || (theChar == '.' && (modifiers & cmdKey)))
|
|
button = kStopButton;
|
|
else if (theChar == kLeftArrowChar) button = kReverseButton;
|
|
else if (theChar == kUpArrowChar) button = kPauseButton;
|
|
else button = kForwardButton;
|
|
|
|
// if the button is disabled, beep
|
|
if (gButtonStatus[button] == disabled) SysBeep(1);
|
|
|
|
// otherwise, depress the button (if visible)
|
|
else {
|
|
PushPort();
|
|
if (gSlideControlsWindow) {
|
|
MySetPort((CGrafPtr)gSlideControlsWindow);
|
|
PlotCIcon(&gButtonRect[button], gDepressedButton[button]);
|
|
}
|
|
|
|
buttonFunction = button;
|
|
if ((modifiers & optionKey) && button == kPauseButton) buttonFunction = kHideButton;
|
|
|
|
// if we're to act now, dispatch the button to the appropriate handler
|
|
if (actNow && gSlideShow != kPaused) {
|
|
while ((TickCount() - startTime) < 8);
|
|
if (gSlideControlsWindow) PlotCIcon(&gButtonRect[button], gStandardButton[button]);
|
|
if ((*gSlideOptions)->userControl) gSlideShow = HandleUserControlButton(buttonFunction);
|
|
else gSlideShow = HandleAutomaticButton(buttonFunction);
|
|
if (!gSlideShow) CleanUpSlideShow();
|
|
} else gPendingButton = buttonFunction;
|
|
PopPort();
|
|
}
|
|
if (HMIsBalloon()) HMRemoveBalloon();
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void Boolean HandleUserControlButton(short button)
|
|
//
|
|
// Handles button commands during a user-controlled slide show.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern Boolean HandleUserControlButton(short button)
|
|
{
|
|
Boolean advance;
|
|
|
|
switch (button) {
|
|
case kStopButton:
|
|
return false;
|
|
case kPauseButton:
|
|
gSlideShow = PauseSlideShow(&advance);
|
|
return gSlideShow;
|
|
case kHideButton:
|
|
gSlideShow = HideSlideShow(&advance);
|
|
return gSlideShow;
|
|
case kReverseButton:
|
|
PointToPreviousSlide();
|
|
case kForwardButton:
|
|
do {
|
|
advance = false;
|
|
gSlideShow = NextSlide(&advance);
|
|
if (gSlideShow) gSlideShow = LoadSlide(&advance);
|
|
} while (advance && gSlideShow);
|
|
return gSlideShow;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// Boolean HandleAutomaticButton(short button)
|
|
//
|
|
// Handles button commands during an automatic slide show.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern Boolean HandleAutomaticButton(short button)
|
|
{
|
|
Boolean advance;
|
|
|
|
switch (button) {
|
|
case kStopButton:
|
|
return false;
|
|
case kPauseButton:
|
|
gSlideShow = PauseSlideShow(&advance);
|
|
return gSlideShow;
|
|
case kHideButton:
|
|
gSlideShow = HideSlideShow(&advance);
|
|
return gSlideShow;
|
|
case kReverseButton:
|
|
PointToPreviousSlide();
|
|
case kForwardButton:
|
|
do {
|
|
advance = false;
|
|
gSlideShow = NextSlide(&advance);
|
|
if (gSlideShow) gSlideShow = LoadSlide(&advance);
|
|
} while (advance && gSlideShow);
|
|
return gSlideShow;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// Boolean PauseSlideShow(Boolean *advance)
|
|
//
|
|
// Oversees the pausing of the slide show.
|
|
//
|
|
// External calls: UnhideMenuBar, DispatchMainEvent, RehideMenuBar
|
|
//=====================================================================================
|
|
|
|
extern Boolean PauseSlideShow(Boolean *advance)
|
|
{
|
|
Boolean result, isNullEvent, isDialogEvent, wasHidden = false;
|
|
short oldBackwardStatus = gButtonStatus[kReverseButton];
|
|
short oldForwardStatus = gButtonStatus[kForwardButton];
|
|
short oldPauseStatus = gButtonStatus[kPauseButton];
|
|
EventRecord theEvent;
|
|
Str255 oldText;
|
|
|
|
if (HMIsBalloon()) HMRemoveBalloon();
|
|
*advance = false;
|
|
gSlideShow = kPaused;
|
|
if (!gMenuVisible) UnhideMenuBar();
|
|
if (!gSlideControlsWindow && OpenSlideControls() == noErr) {
|
|
ChangeActive(gSlideControlsWindow);
|
|
wasHidden = true;
|
|
}
|
|
gButtonStatus[kPauseButton] = depressed;
|
|
gButtonStatus[kForwardButton] = disabled;
|
|
gButtonStatus[kReverseButton] = disabled;
|
|
BlockMove(gSlideControlsText, oldText, *gSlideControlsText + 1);
|
|
SetSlideControlsText(gString[strSlidePaused], gNullString, gNullString, gNullString);
|
|
gPendingButton = -1;
|
|
PushPort();
|
|
MySetPort((CGrafPtr)FWFrontWindow());
|
|
while (true) {
|
|
isNullEvent = !WaitNextEvent(everyEvent - highLevelEventMask, &theEvent, kSleepTime, nil);
|
|
isDialogEvent = FWIsDialogEvent(&theEvent);
|
|
if (isNullEvent) {
|
|
DialogPtr theDialog;
|
|
short itemHit;
|
|
theDialog = FWFrontWindow();
|
|
if (theDialog && WindowKind(theDialog) == dialogKind)
|
|
FWDialogSelect(&theEvent, &theDialog, &itemHit);
|
|
if (HMGetBalloons()) DispatchBalloonHelp();
|
|
} else DispatchMainEvent(&theEvent, isDialogEvent);
|
|
if (gPendingButton != -1 || gDone) {
|
|
short button = gPendingButton;
|
|
gPendingButton = -1;
|
|
if (button == kStopButton || gDone) {
|
|
result = false;
|
|
break;
|
|
} else if (button == kPauseButton) {
|
|
result = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (GetSlideOptionsWindow()) CloseSlideOptions();
|
|
if (GetPrefsWindow()) ClosePrefs();
|
|
if (GetHelpWindow()) CloseHelp();
|
|
gSlideShow = kRunning;
|
|
ChangeActive(FWFrontWindow());
|
|
BlockMove(oldText, gSlideControlsText, *oldText + 1);
|
|
if (wasHidden && gSlideControlsWindow) CloseSlideControls();
|
|
gButtonStatus[kPauseButton] = oldPauseStatus;
|
|
gButtonStatus[kForwardButton] = oldForwardStatus;
|
|
gButtonStatus[kReverseButton] = oldBackwardStatus;
|
|
DrawSlideControlsWindow();
|
|
PopPort();
|
|
return result;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// extern Boolean HideSlideShow(void)
|
|
//
|
|
// Hides the slide show by hiding all open windows, and then moving another process to
|
|
// the front and pausing the slide show.
|
|
//
|
|
// External calls:
|
|
//=====================================================================================
|
|
|
|
extern Boolean HideSlideShow(Boolean *advance)
|
|
{
|
|
ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
|
|
ProcessSerialNumber noProcess = { 0, kNoProcess };
|
|
ProcessSerialNumber newFrontProcess;
|
|
ImageHandle theImage, frontImage;
|
|
ProcessInfoRec theInfo;
|
|
Boolean isSame, result;
|
|
WindowPtr theWindow;
|
|
OSErr theErr;
|
|
|
|
// hide the slide background and all image windows; hide the front image last
|
|
gHidden = true;
|
|
if (theWindow = GetSlideBackWindow()) FWHideWindow(theWindow);
|
|
frontImage = FrontImage();
|
|
for (theImage = gImageRoot; theImage; theImage = (*theImage)->next)
|
|
if ((*theImage)->window && theImage != frontImage) FWHideWindow((*theImage)->window);
|
|
if (frontImage) FWHideWindow((*frontImage)->window);
|
|
ResetColors();
|
|
|
|
// move the process that launched us into the foreground; if we can't find it,
|
|
// then move some other process to the front
|
|
theInfo.processInfoLength = sizeof(ProcessInfoRec);
|
|
theInfo.processName = nil;
|
|
theInfo.processAppSpec = nil;
|
|
theErr = GetProcessInformation(¤tProcess, &theInfo);
|
|
if (theErr == noErr) {
|
|
theErr = SameProcess(&noProcess, &theInfo.processLauncher, &isSame);
|
|
if (!isSame) newFrontProcess = theInfo.processLauncher;
|
|
else {
|
|
newFrontProcess = noProcess;
|
|
do {
|
|
theErr = GetNextProcess(&newFrontProcess);
|
|
theErr = SameProcess(¤tProcess, &newFrontProcess, &isSame);
|
|
} while (isSame);
|
|
}
|
|
theErr = SetFrontProcess(&newFrontProcess);
|
|
}
|
|
|
|
// pause the slide show now
|
|
result = PauseSlideShow(advance);
|
|
return result;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void SetSlideControlsText(StringPtr string0, StringPtr string1, StringPtr string2,
|
|
// StringPtr string3)
|
|
//
|
|
// Sets the text of the slide show controls status.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern void SetSlideControlsText(StringPtr string0, StringPtr string1, StringPtr string2,
|
|
StringPtr string3)
|
|
{
|
|
Str255 newString;
|
|
|
|
BlockMove(string0, newString, *string0 + 1);
|
|
StuffString(newString, 1, string1);
|
|
StuffString(newString, 2, string2);
|
|
StuffString(newString, 3, string3);
|
|
if (!EqualString(newString, gSlideControlsText, true, true)) {
|
|
BlockMove(newString, gSlideControlsText, *newString + 1);
|
|
if (gSlideControlsWindow) DrawSlideControlsWindow();
|
|
}
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void DoSlideControlsHelp(void)
|
|
//
|
|
// Handles balloon help in the slide controls floating window.
|
|
//
|
|
// External calls: none
|
|
//=====================================================================================
|
|
|
|
extern void DoSlideControlsHelp(Point globalPt)
|
|
{
|
|
Point tip = { 0, 0 }, localPt = globalPt;
|
|
HMMessageRecord theRecord;
|
|
short index = -1, i;
|
|
Rect aRect;
|
|
|
|
if (HMIsBalloon() || gInBackground) return;
|
|
PushPort();
|
|
MySetPort((CGrafPtr)gSlideControlsWindow);
|
|
GlobalToLocal(&localPt);
|
|
if (localPt.v < gButtonRect[0].top) {
|
|
index = 1;
|
|
aRect = gSlideControlsWindow->portRect;
|
|
aRect.bottom = gButtonRect[0].top;
|
|
tip.h = aRect.right - 5;
|
|
tip.v = aRect.bottom - 5;
|
|
} else
|
|
for (i = 0; i < 4; i++) {
|
|
if (PtInRect(localPt, &gButtonRect[i])) {
|
|
if (gButtonStatus[i] == standard) index = 2 + i;
|
|
else if (gButtonStatus[i] == depressed) index = 6 + i;
|
|
else if (gButtonStatus[i] == disabled) index = 10 + i;
|
|
aRect = gButtonRect[i];
|
|
tip.h = aRect.right - 5;
|
|
tip.v = aRect.bottom - 5;
|
|
}
|
|
}
|
|
if (index &&
|
|
HMExtractHelpMsg(kHMRectListResType, rSlideControlsWindow, index, kHMEnabledItem,
|
|
&theRecord) == noErr) {
|
|
LocalToGlobal(&tip);
|
|
GlobalRect(&aRect, gSlideControlsWindow);
|
|
HMShowBalloon(&theRecord, tip, &aRect, nil, 0, 0, kHMRegularWindow);
|
|
}
|
|
PopPort();
|
|
}
|