mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-06 21:29:27 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
23 KiB
C
1 line
23 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
|
|
|
|
void SaveWindowPosition(WindowPtr theWindow, Rect *position)
|
|
{
|
|
*position = theWindow->portRect;
|
|
GlobalRect(position, theWindow);
|
|
if (!gDone) SaveGeneralPrefs();
|
|
}
|
|
|
|
void PlaceWindow(WindowPtr theWindow, Rect *theRect, Point defaultLoc)
|
|
{
|
|
if (GetWVariant(theWindow) == dBoxProc || theRect->top == theRect->bottom ||
|
|
DoSetWindowBounds(theWindow, theRect) != noErr) {
|
|
FWMoveWindow(theWindow, defaultLoc.h, defaultLoc.v, true);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ChangeActive(theWindow)
|
|
*
|
|
* Purpose: Changes the active window, flipping the menu bar if necessary and
|
|
* updating the gActive* variables
|
|
* Inputs: theWindow = the new active window
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
void ChangeActive(WindowPtr theWindow)
|
|
{
|
|
static WindowPtr gLastWindow = nil;
|
|
ImageHandle oldImage = FrontImage(), newImage = nil;
|
|
WindowPtr oldWindow = FWFrontWindow();
|
|
Point thePoint = { 0, 0 };
|
|
|
|
MySetPort(nil);
|
|
if (theWindow) {
|
|
newImage = FindImage(theWindow);
|
|
if (gSlideShow != kPaused) {
|
|
if (theWindow == GetSlideBackWindow()) {
|
|
if ((*gMainMonitor)->full) RehideMenuBar();
|
|
else FullScreen(gMainMonitor);
|
|
} else if (WindowKind(theWindow) != floatingWindowKind) {
|
|
if (!newImage || !Full(newImage)) {
|
|
if (newImage && !AnotherFull(newImage)) NormalScreen((*newImage)->dmon);
|
|
else UnhideMenuBar();
|
|
} else {
|
|
if ((*(*newImage)->dmon)->full) RehideMenuBar();
|
|
else FullScreen((*newImage)->dmon);
|
|
}
|
|
}
|
|
}
|
|
if (!WindowVisible(theWindow)) FWShowWindow(theWindow);
|
|
FWSelectWindow(theWindow);
|
|
MySetPort((CGrafPtr)theWindow);
|
|
if (theWindow) {
|
|
if (theWindow == GetColorsWindow()) DrawColorsWindow();
|
|
else if (theWindow == GetStatWindow()) DrawStatWindow();
|
|
}
|
|
if (newImage && !EmptyRgn((*newImage)->update)) InvalRgn((*newImage)->update);
|
|
if (newImage) ActivateAnts((*newImage)->ants);
|
|
}
|
|
SetStatistics();
|
|
if (theWindow != gLastWindow && (!theWindow || WindowKind(theWindow) != floatingWindowKind)) {
|
|
gLastWindow = theWindow;
|
|
if ((!gSlideShow && gThePrefs.autoComments) ||
|
|
(gSlideShow && (*gSlideOptions)->autoComments)) {
|
|
newImage = FrontImage();
|
|
if (!newImage || !(*newImage)->comments) {
|
|
if (GetCommentsWindow())
|
|
if ((!gSlideShow && !gCommentsOpen) || gSlideShow) CloseComments();
|
|
} else if (!CommentsClosed(newImage) && !GetCommentsWindow() &&
|
|
OpenComments() == noErr) {
|
|
FWSelectWindow(GetCommentsWindow());
|
|
FWShowWindow(GetCommentsWindow());
|
|
}
|
|
}
|
|
if (GetSlideControlsWindow()) DrawSlideControlsWindow();
|
|
if (GetSlideOptionsWindow()) UpdateSlideOptionsButtons();
|
|
}
|
|
AdjustMenus();
|
|
}
|
|
|
|
/*
|
|
* DoCloneWindow(theWindow, behindWindow, newWindow)
|
|
*
|
|
* Purpose: Makes a clone of the given window
|
|
* Inputs: theWindow = the window to clone
|
|
* behindWindow = the window behind which to put the newcomer
|
|
* newWindow = a pointer to a WindowPtr to receive the new window
|
|
* Returns: an OSErr describing the result
|
|
*
|
|
*/
|
|
|
|
OSErr DoCloneWindow(WindowPtr theWindow, WindowPtr behindWindow, WindowPtr *newWindow)
|
|
{
|
|
ImageHandle newImage, theImage = FindImage(theWindow);
|
|
DescType thePalette;
|
|
short palette;
|
|
OSErr theErr;
|
|
|
|
if (!theImage) return errAENotModifiable;
|
|
if (newImage = CopyImage(theImage)) {
|
|
palette = (*newImage)->npalette;
|
|
theErr = MakeNewWindow(newImage, true, gThePrefs.expandSmall);
|
|
if (theErr == noErr) {
|
|
switch ((*theImage)->npalette) {
|
|
case plSys: thePalette = kAEPSystem; break;
|
|
case plGrey: thePalette = kAEPGrayscale; break;
|
|
case plImage: thePalette = kAEPImage; break;
|
|
case plQuant: thePalette = kAEPQuantized; break;
|
|
}
|
|
DoSetPalette((*newImage)->window, thePalette);
|
|
AddWindowItem(newImage);
|
|
if (behindWindow) SendBehind((*newImage)->window, behindWindow);
|
|
*newWindow = (*newImage)->window;
|
|
}
|
|
} else theErr = memFullErr;
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* DoCloseWindow(theWindow, restore)
|
|
*
|
|
* Purpose: Handles the closing of the given window, disposing of the associated
|
|
* image, if necessary
|
|
* Inputs: theWindow = the window to close
|
|
* restore = flag: true to restore colors when closing last image
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
OSErr DoCloseWindow(WindowPtr theWindow, Boolean restore)
|
|
{
|
|
WindowPtr statWindow = GetStatWindow(), commentsWindow = GetCommentsWindow(),
|
|
colorsWindow = GetColorsWindow(), slideBackWindow = GetSlideBackWindow(),
|
|
slideControlsWindow = GetSlideControlsWindow();
|
|
ImageHandle theImage = FindImage(theWindow);
|
|
long dialogID = GetWRefCon(theWindow);
|
|
Boolean reset = false;
|
|
ushort i = 0;
|
|
|
|
MySetPort(nil);
|
|
if (WindowKind(theWindow) == dialogKind) DispatchDialogEvent(theWindow, kDialogClose);
|
|
else if (dialogID == kHelpWindowID) CloseHelp();
|
|
else if (theWindow == statWindow) CloseStats();
|
|
else if (theWindow == commentsWindow) {
|
|
ImageHandle frontImage = FrontImage();
|
|
gCommentsOpen = false, CloseComments();
|
|
if ((!gSlideShow && gThePrefs.autoComments) ||
|
|
(gSlideShow && (*gSlideOptions)->autoComments))
|
|
if (frontImage) (*frontImage)->flags |= ifCommentsClosed;
|
|
} else if (theWindow == colorsWindow) CloseColors();
|
|
else if (theWindow == slideControlsWindow) CloseSlideControls();
|
|
else if (theWindow == slideBackWindow) CloseSlideBackWindow();
|
|
else if (theImage) {
|
|
Boolean normal = (Full(theImage) && !AnotherFull(theImage));
|
|
MonitorHandle imageMonitor = (*theImage)->dmon;
|
|
|
|
if (normal) NormalScreen(imageMonitor);
|
|
DeleteWindowItem(theImage);
|
|
DisposeImage(theImage);
|
|
if (!gImageRoot && theImage && (restore || gDone)) ResetColors();
|
|
}
|
|
ChangeActive(FWFrontWindow());
|
|
return noErr;
|
|
}
|
|
|
|
/*
|
|
* DoCreateWindow(theType, behindWindow, theWindow)
|
|
*
|
|
* Purpose: Handles the creation of static windows and positions them correctly
|
|
* Inputs: theType = the type of window to create
|
|
* behindWindow = the window's location
|
|
* theWindow = pointer to receive the new WindowPtr
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
OSErr DoCreateWindow(DescType theType, WindowPtr behindWindow, WindowPtr *theWindow)
|
|
{
|
|
ImageHandle theImage;
|
|
OSErr theErr = noErr;
|
|
|
|
switch (theType) {
|
|
case kAEWTPreferences:
|
|
OpenPrefs();
|
|
if (*theWindow = GetPrefsWindow()) ChangeActive(*theWindow);
|
|
else theErr = memFullErr;
|
|
break;
|
|
case kAEWTSlideShow:
|
|
OpenSlideOptions();
|
|
if (*theWindow = GetSlideOptionsWindow()) ChangeActive(*theWindow);
|
|
else theErr = memFullErr;
|
|
break;
|
|
case kAEWTAboutHelp:
|
|
OpenAboutHelp();
|
|
if (*theWindow = GetAboutHelpWindow()) ChangeActive(*theWindow);
|
|
else theErr = memFullErr;
|
|
break;
|
|
case kAEWTHelp:
|
|
if (!gHelpFound) theErr = errNoHelpFound;
|
|
else {
|
|
OpenHelp();
|
|
if (*theWindow = GetHelpWindow()) {
|
|
DoMoveWindow(*theWindow, behindWindow);
|
|
FWShowWindow(*theWindow);
|
|
} else theErr = memFullErr;
|
|
}
|
|
break;
|
|
case kAEWTStatistics:
|
|
OpenStats();
|
|
if (*theWindow = GetStatWindow()) {
|
|
DoMoveWindow(*theWindow, behindWindow);
|
|
FWShowWindow(*theWindow);
|
|
} else theErr = memFullErr;
|
|
break;
|
|
case kAEWTComments:
|
|
OpenComments();
|
|
if (*theWindow = GetCommentsWindow()) {
|
|
DoMoveWindow(*theWindow, behindWindow);
|
|
FWShowWindow(*theWindow);
|
|
} else theErr = memFullErr;
|
|
break;
|
|
case kAEWTColors:
|
|
OpenColors();
|
|
if (*theWindow = GetColorsWindow()) {
|
|
DoMoveWindow(*theWindow, behindWindow);
|
|
FWShowWindow(*theWindow);
|
|
} else theErr = memFullErr;
|
|
break;
|
|
case kAEWTSlideControls:
|
|
OpenSlideControls();
|
|
if (*theWindow = GetColorsWindow()) {
|
|
DoMoveWindow(*theWindow, behindWindow);
|
|
FWShowWindow(*theWindow);
|
|
} else theErr = memFullErr;
|
|
case kAEWTAbout:
|
|
OpenAbout();
|
|
for (theImage = gImageRoot; theImage; theImage = (*theImage)->next)
|
|
if (IsAboutBox(theImage)) break;
|
|
if (theImage && (*theWindow = (*theImage)->window)) {
|
|
DoMoveWindow(*theWindow, behindWindow);
|
|
FWShowWindow(*theWindow);
|
|
} else theErr = memFullErr;
|
|
break;
|
|
}
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* DoMoveWindow(theWindow, behindWindow)
|
|
*
|
|
* Purpose: Handles the proper moving of windows in the floating window environment
|
|
* Inputs: theWindow = the window to move
|
|
* behindWindow = the window's location
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
OSErr DoMoveWindow(WindowPtr theWindow, WindowPtr behindWindow)
|
|
{
|
|
if (theWindow == behindWindow) return noErr;
|
|
if (WindowKind(theWindow) == floatingWindowKind) {
|
|
if (!behindWindow) ChangeActive(theWindow);
|
|
else {
|
|
if (WindowKind(behindWindow) != floatingWindowKind)
|
|
behindWindow = FWBottomFloatingWindow();
|
|
SendBehind(theWindow, behindWindow);
|
|
}
|
|
} else {
|
|
if (!behindWindow || WindowKind(behindWindow) == floatingWindowKind)
|
|
ChangeActive(theWindow);
|
|
else SendBehind(theWindow, behindWindow);
|
|
}
|
|
return noErr;
|
|
}
|
|
|
|
/*
|
|
* IsZoomed(theWindow)
|
|
*
|
|
* Purpose: Determines the zoomed state of the given window
|
|
* Inputs: theWindow = the window to examine
|
|
* Returns: a boolean: true if the window is zoomed; false otherwise
|
|
*
|
|
*/
|
|
|
|
Boolean IsZoomed(WindowPtr theWindow)
|
|
{
|
|
ImageHandle theImage = FindImage(theWindow);
|
|
|
|
if (theImage) return !EqualSizeRect(&(*theImage)->wrect, &(*theImage)->crect);
|
|
else if (theWindow == GetStatWindow()) return gThePrefs.statsZoomed;
|
|
else if (theWindow == GetHelpWindow()) {
|
|
Rect defaultRect = { 0, 0, 300, 480 };
|
|
return !EqualSizeRect(&theWindow->portRect, &defaultRect);
|
|
} else return false;
|
|
}
|
|
|
|
/*
|
|
* DoZoomWindow(theWindow, zoomed)
|
|
*
|
|
* Purpose: Zooms the given window
|
|
* Inputs: theWindow = the window to clone
|
|
* zoomed = flag: true to zoom the window, false to unzoom
|
|
* Returns: an OSErr describing the result
|
|
*
|
|
*/
|
|
|
|
OSErr DoZoomWindow(WindowPtr theWindow, Boolean zoomed)
|
|
{
|
|
ImageHandle theImage = FindImage(theWindow);
|
|
Rect newRect, oldRect, monRect;
|
|
|
|
if (theImage) {
|
|
oldRect = (*theImage)->wrect;
|
|
newRect = (*theImage)->crect;
|
|
GetActiveRect((*theImage)->dmon, &monRect);
|
|
if (!Full(theImage)) monRect.top += gTitleBarHeight;
|
|
if (zoomed || (Width(&newRect) > Width(&monRect)) || (Height(&newRect) > Height(&monRect))) {
|
|
OffsetRect(&newRect, -newRect.left, -newRect.top);
|
|
newRect.right = (long)newRect.right * (long)Height(&monRect) / (long)newRect.bottom;
|
|
newRect.bottom = Height(&monRect);
|
|
if (Width(&newRect) > Width(&monRect)) {
|
|
newRect.bottom = (long)newRect.bottom * (long)Width(&monRect) / (long)newRect.right;
|
|
newRect.right = Width(&monRect);
|
|
}
|
|
}
|
|
(*theImage)->wrect = newRect;
|
|
ResizeWindow(theImage);
|
|
if (AntsHaveSelection((*theImage)->ants)) {
|
|
Rect selRect;
|
|
GetAntsSelection((*theImage)->ants, &selRect);
|
|
MapRect(&selRect, &oldRect, &(*theImage)->wrect);
|
|
SetAntsSelection((*theImage)->ants, &selRect);
|
|
}
|
|
} else if ((theWindow == GetStatWindow()) && (!gThePrefs.statsZoomed != !zoomed))
|
|
ZoomStats();
|
|
else if (theWindow == GetHelpWindow()) {
|
|
Rect defaultRect = { 0, 0, 300, 480 };
|
|
if (zoomed) {
|
|
defaultRect = theWindow->portRect;
|
|
GlobalRect(&defaultRect, theWindow);
|
|
GetActiveRect(GetMostDevice(&defaultRect), &defaultRect);
|
|
InsetRect(&defaultRect, kWindowBorderWidth, kWindowBorderHeight);
|
|
defaultRect.top += gTitleBarHeight;
|
|
} else {
|
|
GlobalRect(&defaultRect, theWindow);
|
|
NudgeWindowRect(&defaultRect, GetMostDevice(&defaultRect));
|
|
}
|
|
FWMoveWindow(theWindow, defaultRect.left, defaultRect.top, false);
|
|
ResizeHelp(&defaultRect);
|
|
}
|
|
return noErr;
|
|
}
|
|
|
|
/*
|
|
* MakeNewWindow(theImage, first, autoExpand)
|
|
*
|
|
* Purpose: Creates a new window for the given image, closing the old one if it exists
|
|
* Inputs: theImage = a pointer to the image record
|
|
* first = flag: true if this is the first image in a series, false
|
|
* if this is just a follower
|
|
* autoExpand = flag: true to expand small images to largest size
|
|
* Returns: an OSErr describing the problem (hopefully noErr)
|
|
*
|
|
*/
|
|
|
|
OSErr MakeNewWindow(ImageHandle theImage, Boolean first, Boolean autoExpand)
|
|
{
|
|
static WindowPtr gLastWindow = nil;
|
|
short resID = Full(theImage) ? rFullImageWindow :
|
|
((IsAboutBox(theImage)) ? rAboutImageWindow : rImageWindow);
|
|
Rect winRect, oldRect = { 0, 0, 0, 0 };
|
|
WindowPtr behindWindow;
|
|
WCTabHandle winColors;
|
|
Str255 theTitle;
|
|
|
|
if (AntsHaveSelection((*theImage)->ants)) HideAnts((*theImage)->ants);
|
|
(*theImage)->wrect = (*theImage)->crect;
|
|
ScaleRect(&(*theImage)->wrect, (*theImage)->dmon, Full(theImage), autoExpand);
|
|
if (Full(theImage)) {
|
|
winRect = (*(*theImage)->dmon)->rect;
|
|
OffsetRect(&(*theImage)->wrect,
|
|
(Width(&winRect) - Width(&(*theImage)->wrect)) >> 1,
|
|
(Height(&winRect) - Height(&(*theImage)->wrect)) >> 1);
|
|
} else {
|
|
winRect = (*theImage)->wrect;
|
|
PositionWindow(&winRect, (*theImage)->dmon);
|
|
}
|
|
if (gSlideShow) behindWindow = FWFrontWindow();
|
|
else behindWindow = (first) ? (WindowPtr)-1 : gLastWindow;
|
|
if ((*theImage)->window) {
|
|
oldRect = (*theImage)->window->portRect;
|
|
GlobalRect(&oldRect, (*theImage)->window);
|
|
FWCloseWindow((*theImage)->window);
|
|
} else {
|
|
(*theImage)->window = AllocateWindow();
|
|
if (!(*theImage)->window) return memFullErr;
|
|
}
|
|
MakeTitle(theImage, theTitle);
|
|
MySetPort(nil);
|
|
if (!FWGetNewCWindow(resID, (Ptr)(*theImage)->window, behindWindow)) return memFullErr;
|
|
SetWindowKind((*theImage)->window, userKind);
|
|
if (NeedsWhiteBG(theImage) && !Full(theImage) &&
|
|
(winColors = (WCTabHandle)GetResource('wctb', 0)))
|
|
SetWinColor((*theImage)->window, winColors);
|
|
SizeWindow((*theImage)->window, Width(&winRect), Height(&winRect), false);
|
|
FWMoveWindow((*theImage)->window, winRect.left, winRect.top, false);
|
|
SetWTitle((*theImage)->window, theTitle);
|
|
SetAntsPort((*theImage)->ants, (*theImage)->window);
|
|
SetAntsLimitRect((*theImage)->ants, &(*theImage)->wrect);
|
|
gLastWindow = (*theImage)->window;
|
|
if (AntsHaveSelection((*theImage)->ants)) {
|
|
Rect selRect;
|
|
GetAntsSelection((*theImage)->ants, &selRect);
|
|
MapRect(&selRect, &oldRect, &(*theImage)->wrect);
|
|
SetAntsSelection((*theImage)->ants, &selRect);
|
|
}
|
|
if (!GWOrigSize(theImage) &&
|
|
(!EqualSizeRect(&(*theImage)->wrect, &oldRect) || Dithered(theImage)))
|
|
KillGWorld(theImage);
|
|
return noErr;
|
|
}
|
|
|
|
/*
|
|
* ScaleRect(theRect, theMonitor, full)
|
|
*
|
|
* Purpose: Scales the given rectangle to fit on the specified monitor
|
|
* Inputs: theRect = pointer to the rectangle to be fit
|
|
* theMonitor = pointer to the monitor to put the rect on
|
|
* full = flag: true if it will be displayed full screen
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
void ScaleRect(Rect *theRect, MonitorHandle theMonitor, Boolean full, Boolean autoExpand)
|
|
{
|
|
long theWidth, theHeight;
|
|
|
|
theWidth = Width(&(*theMonitor)->rect);
|
|
theHeight = Height(&(*theMonitor)->rect);
|
|
if (!full) {
|
|
theHeight -= gTitleBarHeight;
|
|
if (theMonitor == gMainMonitor) theHeight -= gMenuHeight;
|
|
}
|
|
OffsetRect(theRect, -theRect->left, -theRect->top);
|
|
if ((theRect->right > theWidth) || autoExpand) {
|
|
theRect->bottom = (long)theRect->bottom * theWidth / (long)theRect->right;
|
|
theRect->right = theWidth;
|
|
}
|
|
if (theRect->bottom > theHeight) {
|
|
theRect->right = (long)theRect->right * theHeight / (long)theRect->bottom;
|
|
theRect->bottom = theHeight;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* MakeTitle(theImage, theTitle)
|
|
*
|
|
* Purpose: Creates a window title for the given image
|
|
* Inputs: theImage = a pointer to the image
|
|
* theTitle = an Str255 to store the title in
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
void MakeTitle(ImageHandle theImage, StringPtr theTitle)
|
|
{
|
|
long scaleX, scaleY;
|
|
|
|
BlockMove((*theImage)->file.name, theTitle, 64);
|
|
if ((*theImage)->num) {
|
|
AddChar(theTitle, ' ');
|
|
AddNumber(theTitle, (*theImage)->num);
|
|
}
|
|
if (!EqualSizeRect(&(*theImage)->wrect, &(*theImage)->crect)) {
|
|
scaleX = 200L * (long)Width(&(*theImage)->wrect) / Width(&(*theImage)->crect);
|
|
scaleX = (scaleX + 1) >> 1;
|
|
scaleY = 200L * (long)Height(&(*theImage)->wrect) / Height(&(*theImage)->crect);
|
|
scaleY = (scaleY + 1) >> 1;
|
|
AddChar(theTitle, ' ');
|
|
AddChar(theTitle, '(');
|
|
if (abs(scaleX - scaleY) <= 1) {
|
|
AddNumber(theTitle, (scaleX + scaleY) / 2);
|
|
} else {
|
|
AddNumber(theTitle, scaleX);
|
|
AddChar(theTitle, '%');
|
|
AddChar(theTitle, '/');
|
|
AddNumber(theTitle, scaleY);
|
|
}
|
|
AddChar(theTitle, '%');
|
|
AddChar(theTitle, ')');
|
|
}
|
|
}
|
|
|
|
/*
|
|
* PositionWindow(theRect, theMonitor)
|
|
*
|
|
* Purpose: Attempts to find the next free slot for a given image rectangle; it first
|
|
* tries the given upper-left, then scans downward, and finally to the
|
|
* right for an ideal spot; if nothing else is found, the original
|
|
* upper-left is returned
|
|
* Inputs: theRect = a pointer to the proposed image rectangle in global coordinates
|
|
* theMonitor = a pointer to the monitor rectangle
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
void PositionWindow(Rect *theRect, MonitorHandle theMonitor)
|
|
{
|
|
short rightSpace, bottomSpace, shift;
|
|
Rect monRect, startRect;
|
|
|
|
monRect = (*theMonitor)->rect;
|
|
monRect.top += gTitleBarHeight;
|
|
if (theMonitor == gMainMonitor) monRect.top += gMenuHeight;
|
|
OffsetRect(theRect, monRect.left - theRect->left, monRect.top - theRect->top);
|
|
rightSpace = monRect.right - theRect->right;
|
|
bottomSpace = monRect.bottom - theRect->bottom;
|
|
if (rightSpace < (2 * kWindowBorderWidth)) OffsetRect(theRect, rightSpace >> 1, 0);
|
|
else OffsetRect(theRect, kWindowBorderWidth, 0);
|
|
if (bottomSpace < (2 * kWindowBorderHeight)) OffsetRect(theRect, 0, bottomSpace >> 1);
|
|
else OffsetRect(theRect, 0, kWindowBorderHeight);
|
|
rightSpace = monRect.right - theRect->right;
|
|
bottomSpace = monRect.bottom - theRect->bottom;
|
|
startRect = *theRect;
|
|
|
|
for (shift = 0; shift < bottomSpace; shift += kWindowStepDown) {
|
|
*theRect = startRect;
|
|
OffsetRect(theRect, 0, shift);
|
|
while ((theRect->right <= monRect.right) && (theRect->bottom <= monRect.bottom)) {
|
|
if (!SlotTaken(theRect)) return;
|
|
OffsetRect(theRect, kWindowStepRight, kWindowStepDown);
|
|
}
|
|
}
|
|
for (shift = 0; shift < rightSpace; shift += kWindowStepRight) {
|
|
*theRect = startRect;
|
|
OffsetRect(theRect, shift, 0);
|
|
while ((theRect->right <= monRect.right) && (theRect->bottom <= monRect.bottom)) {
|
|
if (!SlotTaken(theRect)) return;
|
|
OffsetRect(theRect, kWindowStepRight, kWindowStepDown);
|
|
}
|
|
}
|
|
*theRect = startRect;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* SlotTaken(theRect)
|
|
*
|
|
* Purpose: Determines if the proposed rectangle is already taken by another
|
|
* window, within half of the step distance
|
|
* Inputs: theRect = the proposed rectangle
|
|
* Returns: true if the given slot is free; false otherwise
|
|
*
|
|
*/
|
|
|
|
Boolean SlotTaken(Rect *theRect)
|
|
{
|
|
ImageHandle theImage;
|
|
WindowPtr theWindow;
|
|
register short temp;
|
|
|
|
for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) {
|
|
theWindow = (*theImage)->window;
|
|
if (theWindow && GetContRgn(theWindow) && WindowVisible(theWindow)) {
|
|
temp = theRect->left - (*GetContRgn(theWindow))->rgnBBox.left;
|
|
if (temp < 0) temp = -temp;
|
|
if (temp >= (kWindowStepRight / 2)) continue;
|
|
temp = theRect->top - (*GetContRgn(theWindow))->rgnBBox.top;
|
|
if (temp < 0) temp = -temp;
|
|
if (temp >= (kWindowStepDown / 2)) continue;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* ResizeWindow(theImage)
|
|
*
|
|
* Purpose: Resizes and displays the window for the given image
|
|
* Inputs: theImage = a pointer to the image record
|
|
* Returns: true if everything went okay; false otherwise
|
|
*
|
|
*/
|
|
|
|
Boolean ResizeWindow(ImageHandle theImage)
|
|
{
|
|
Rect windowRect, oldRect, oldLocalRect;
|
|
Str255 theTitle;
|
|
short space;
|
|
|
|
if (!(*theImage)->window) return false;
|
|
if (AntsHaveSelection((*theImage)->ants)) HideAnts((*theImage)->ants);
|
|
oldLocalRect = oldRect = (*theImage)->window->portRect;
|
|
GlobalRect(&oldRect, (*theImage)->window);
|
|
windowRect = (*theImage)->wrect;
|
|
OffsetRect(&(*theImage)->wrect, -windowRect.left, -windowRect.top);
|
|
OffsetRect(&windowRect, oldRect.left - windowRect.left, oldRect.top - windowRect.top);
|
|
if (Full(theImage)) {
|
|
space = Width(&(*(*theImage)->dmon)->rect) - Width(&(*theImage)->wrect);
|
|
OffsetRect(&(*theImage)->wrect, space >> 1, 0);
|
|
space = Height(&(*(*theImage)->dmon)->rect) - Height(&(*theImage)->wrect);
|
|
OffsetRect(&(*theImage)->wrect, 0, space >> 1);
|
|
} else {
|
|
if (NudgeWindowRect(&windowRect, (*theImage)->dmon))
|
|
FWMoveWindow((*theImage)->window, windowRect.left, windowRect.top, false);
|
|
(*theImage)->wrect = windowRect;
|
|
OffsetRect(&(*theImage)->wrect, -(*theImage)->wrect.left, -(*theImage)->wrect.top);
|
|
SizeWindow((*theImage)->window, Width(&windowRect), Height(&windowRect), false);
|
|
}
|
|
//if (EqualRect(&(*theImage)->wrect, &oldLocalRect)) return true;
|
|
PushPort();
|
|
MySetPort((CGrafPtr)(*theImage)->window);
|
|
InvalRect(&(*theImage)->window->portRect);
|
|
PopPort();
|
|
if (!GWOrigSize(theImage) &&
|
|
(!EqualRect(&(*theImage)->wrect, &oldLocalRect) || Dithered(theImage)))
|
|
KillGWorld(theImage);
|
|
MakeTitle(theImage, theTitle);
|
|
SetWTitle((*theImage)->window, theTitle);
|
|
SetAntsLimitRect((*theImage)->ants, &(*theImage)->wrect);
|
|
if (AntsHaveSelection((*theImage)->ants)) {
|
|
Rect selRect;
|
|
GetAntsSelection((*theImage)->ants, &selRect);
|
|
MapRect(&selRect, &oldLocalRect, &(*theImage)->wrect);
|
|
SetAntsSelection((*theImage)->ants, &selRect);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* NudgeWindowRect(windowRect, theMonitor)
|
|
*
|
|
* Purpose: Nudges the given rectangle to fit on the monitor
|
|
* Inputs: windowRect = pointer to the rectangle to nudge
|
|
* theMonitor = handle to the monitor the rect is on
|
|
* Returns: true if it needed to be moved; false otherwise
|
|
*
|
|
*/
|
|
|
|
Boolean NudgeWindowRect(Rect *windowRect, MonitorHandle theMonitor)
|
|
{
|
|
Boolean nudged = false;
|
|
Rect screenRect;
|
|
short space;
|
|
|
|
GetActiveRect(theMonitor, &screenRect);
|
|
screenRect.top += gTitleBarHeight;
|
|
if (screenRect.right <= windowRect->right) {
|
|
OffsetRect(windowRect, screenRect.right - windowRect->right, 0);
|
|
space = windowRect->left - screenRect.left;
|
|
if (space > (2 * kWindowBorderWidth))
|
|
OffsetRect(windowRect, -kWindowBorderWidth, 0);
|
|
else OffsetRect(windowRect, -(space >> 1), 0);
|
|
nudged = true;
|
|
}
|
|
if (screenRect.left > windowRect->left) {
|
|
OffsetRect(windowRect, screenRect.left - windowRect->left, 0);
|
|
space = screenRect.right - windowRect->right;
|
|
if (space > (2 * kWindowBorderWidth))
|
|
OffsetRect(windowRect, kWindowBorderWidth, 0);
|
|
else OffsetRect(windowRect, (space >> 1), 0);
|
|
nudged = true;
|
|
}
|
|
if (screenRect.bottom <= windowRect->bottom) {
|
|
OffsetRect(windowRect, 0, screenRect.bottom - windowRect->bottom);
|
|
space = windowRect->top - screenRect.top;
|
|
if (space > (2 * kWindowBorderHeight))
|
|
OffsetRect(windowRect, 0, -kWindowBorderHeight);
|
|
else OffsetRect(windowRect, -(space >> 1), 0);
|
|
nudged = true;
|
|
}
|
|
if (screenRect.top > windowRect->top) {
|
|
OffsetRect(windowRect, 0, screenRect.top - windowRect->top);
|
|
space = screenRect.bottom - windowRect->bottom;
|
|
if (space > (2 * kWindowBorderHeight))
|
|
OffsetRect(windowRect, 0, kWindowBorderHeight);
|
|
else OffsetRect(windowRect, (space >> 1), 0);
|
|
nudged = true;
|
|
}
|
|
return nudged;
|
|
}
|