JPEGView/Source/C/SlideControlsWindow.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 */
/*********************************************************/
//=====================================================================================
// 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(&currentProcess, &theInfo);
if (theErr == noErr) {
theErr = SameProcess(&noProcess, &theInfo.processLauncher, &isSame);
if (!isSame) newFrontProcess = theInfo.processLauncher;
else {
newFrontProcess = noProcess;
do {
theErr = GetNextProcess(&newFrontProcess);
theErr = SameProcess(&currentProcess, &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();
}