JPEGView/Source/C/MonitorUtils.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
15 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
/*
* MonitorInit()
*
* Purpose: Sets up the linked list of screen devices, and sets their inverse color
* table resolutions to 5 bits per component
* Inputs: none
* Returns: nothing
*
*/
void MonitorInit(void)
{
DeviceLoopDrawingUPP addDevice = NewDeviceLoopDrawingProc((ProcPtr)AddDevice);
MonitorHandle theMonitor;
GDHandle theDevice;
if (!(theDevice = GetMainDevice())) FatalError(errNoDeviceInfo);
if (!(theMonitor = gMainMonitor = NewMonitor(theDevice))) FatalError(errNoMemory);
DeviceLoop(nil, addDevice, (long)&theMonitor, allDevices + singleDevices);
DisposeRoutineDescriptor((UniversalProcPtr)addDevice);
SetUpDevices();
KeepSpinning();
}
/*
* AddDevice(depth, deviceFlags, targetDevice, userData)
*
* Purpose: DeviceLoop routine to add the current device to the linked list
* Inputs: depth = depth of the device
* deviceFlags = device flags for the device
* targetDevice = handle to the target device
* userData = a refCon we can use
* Returns: nothing
*
*/
pascal void AddDevice(short depth, short deviceFlags, GDHandle targetDevice,
MonitorHandle *theMonitor)
{
#if applec
#pragma unused(depth, deviceFlags)
#endif
if (targetDevice != (*gMainMonitor)->device) {
if ((**theMonitor)->next = NewMonitor(targetDevice))
*theMonitor = (**theMonitor)->next;
}
}
/*
* NewMonitor()
*
* Purpose: Allocates and initializes a new monitor record based on the given device
* Inputs: theDevice = handle to the new device
* Returns: a pointer to the new monitor record
*
*/
MonitorHandle NewMonitor(GDHandle theDevice)
{
MonitorHandle theMonitor;
Rect theRect;
if (theMonitor = (MonitorHandle)NewHandle(sizeof(MonitorItem))) {
if ((*theMonitor)->gray = NewRgn()) {
if ((*theMonitor)->screen = NewRgn()) {
(*theMonitor)->next = nil;
(*theMonitor)->device = theDevice;
(*theMonitor)->oldres = (*theDevice)->gdResPref;
(*theMonitor)->color = IsColorDevice(theDevice);
(*theMonitor)->depth = MonitorDepth(theMonitor);
(*theMonitor)->full = false;
theRect = (*theMonitor)->rect = (*theDevice)->gdRect;
RectRgn((*theMonitor)->screen, &theRect);
SectRgn((*theMonitor)->screen, GetGrayRgn(), (*theMonitor)->gray);
return theMonitor;
}
DisposeHandle((Handle)(*theMonitor)->gray);
}
DisposeHandle((Handle)theMonitor);
}
return nil;
}
/*
* MonitorChanged()
*
* Purpose: Checks to see if any monitors have changed depth/greys
* Inputs: none
* Returns: a pointer to the changed monitor, or nil if everything is the same
*
*/
MonitorHandle MonitorChanged(void)
{
MonitorHandle theMonitor;
Boolean color;
short depth;
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) {
color = IsColorDevice((*theMonitor)->device);
depth = MonitorDepth(theMonitor);
if (((*theMonitor)->color != color) || ((*theMonitor)->depth != depth)) {
(*theMonitor)->color = color;
(*theMonitor)->depth = depth;
return theMonitor;
}
}
return nil;
}
/*
* SetUpDevices()
*
* Purpose: Restores the new inverse table resolutions on the various devices
* Inputs: none
* Returns: nothing
*
*/
void SetUpDevices(void)
{
MonitorHandle theMonitor;
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) {
/*(*(*theMonitor)->device)->gdResPref = 5;
if ((*(*theMonitor)->device)->gdITable)
(*(*(*theMonitor)->device)->gdITable)->iTabSeed = GetCTSeed();
GDeviceChanged((*theMonitor)->device);*/
}
}
/*
* ResetDevices()
*
* Purpose: Restores the original inverse table resolutions on the various devices
* Inputs: none
* Returns: nothing
*
*/
void ResetDevices(void)
{
MonitorHandle theMonitor;
if (!gMenuVisible && !(*gMainMonitor)->full) UnhideMenuBar();
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next)
if ((*theMonitor)->full) NormalScreen(theMonitor);
}
/*
* ResetColors()
*
* Purpose: Restores the colors of all active screens to their original CLUTs
* Inputs: none
* Returns: nothing
*
*/
void ResetColors(void)
{
MonitorHandle theMonitor;
RgnHandle theRgn;
if (gInBackground) return;
if (theRgn = NewRgn()) {
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) {
if (!(*(*theMonitor)->device)->gdType) {
RestoreDeviceClut((*theMonitor)->device);
UnionRgn(theRgn, (*theMonitor)->gray, theRgn);
}
}
if (!EmptyRgn(theRgn)) {
LMSetPaintWhite(true);
PaintBehind((WindowPeek)GetFirstWindow(), theRgn);
LMSetPaintWhite(false);
PaintOne(nil, theRgn);
LMSetPaintWhite(true);
}
DisposeRgn(theRgn);
}
}
/*
* FullScreen(theMonitor)
*
* Purpose: Fixes up theMonitor to allow full-screen windows
* Inputs: theMonitor = pointer to the monitor we're interested in, or nil for all
* Returns: nothing
*
*/
void FullScreen(MonitorHandle theMonitor)
{
RgnHandle updateRgn;
if (!theMonitor) {
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next)
FullScreen(theMonitor);
return;
}
if ((*theMonitor)->full) return;
UnionRgn(GetGrayRgn(), (*theMonitor)->screen, GetGrayRgn());
if (theMonitor == gMainMonitor && gInBackground && (updateRgn = GetMenuRgn()))
DiffRgn(GetGrayRgn(), updateRgn, GetGrayRgn());
if (updateRgn = NewRgn()) {
DiffRgn((*theMonitor)->screen, (*theMonitor)->gray, updateRgn);
PaintOne((WindowPeek)FrontWindow(), updateRgn);
PaintBehind((WindowPeek)FrontWindow(), updateRgn);
CalcVis((WindowPeek)FrontWindow());
CalcVisBehind((WindowPeek)FrontWindow(), updateRgn);
DisposeRgn(updateRgn);
if (theMonitor == gMainMonitor && !gInBackground) {
LMSetMBarHeight(0);
gMenuVisible = false;
RestoreMenuArea();
}
(*theMonitor)->full = true;
}
}
/*
* NormalScreen(theMonitor)
*
* Purpose: Fixes up theMonitor to remove the effects of FullScreen
* Inputs: theMonitor = pointer to the monitor we're interested in, or nil for all
* Returns: nothing
*
*/
void NormalScreen(MonitorHandle theMonitor)
{
Boolean oldMenuVis = gMenuVisible;
RgnHandle updateRgn;
GrafPort tempPort;
if (!theMonitor) {
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next)
NormalScreen(theMonitor);
return;
}
if (!(*theMonitor)->full) return;
if (updateRgn = NewRgn()) {
if (theMonitor == gMainMonitor) SaveMenuArea();
DiffRgn((*theMonitor)->screen, (*theMonitor)->gray, updateRgn);
PushPort();
OpenPort(&tempPort);
CopyRgn(GetGrayRgn(), tempPort.visRgn);
MySetPort((CGrafPtr)&tempPort);
RGBForeColor(&gBlack);
PaintRgn(updateRgn);
ClosePort(&tempPort);
PopPort();
DiffRgn(GetGrayRgn(), updateRgn, GetGrayRgn());
CalcVis((WindowPeek)FrontWindow());
CalcVisBehind((WindowPeek)FrontWindow(), updateRgn);
DisposeRgn(updateRgn);
if (theMonitor == gMainMonitor) {
LMSetMBarHeight(gMenuHeight);
gMenuVisible = true;
AdjustMenus();
DrawMenuBar();
NudgeWindoids();
}
}
(*theMonitor)->full = false;
}
/*
* NudgeWindoids()
*
* Purpose: Check all windoids to be sure they're not under the menubar
* Inputs: none
* Returns: nothing
*
*/
void NudgeWindoids(void)
{
WindowPtr theWindow = GetFirstWindow();
Rect theRect, menuRect, tempRect;
menuRect = (*gMainMonitor)->rect;
menuRect.bottom = menuRect.top + GetMBarHeight();
while (theWindow) {
if (WindowKind((WindowPtr)theWindow) == floatingWindowKind) {
theRect = theWindow->portRect;
theRect.top -= gTitleBarHeight * 2 / 3;
GlobalRect(&theRect, theWindow);
if (SectRect(&theRect, &menuRect, &tempRect)) {
theRect.top = GetMBarHeight() + gTitleBarHeight * 2 / 3;
MoveWindow(theWindow, theRect.left, theRect.top, false);
}
}
theWindow = NextWindow(theWindow);
}
}
/*
* UnhideMenuBar()
*
* Purpose: Displays the menubar on the main screen, if it's currently full-screen
* Inputs: none
* Returns: nothing
*
*/
void UnhideMenuBar(void)
{
Boolean oldMenuVis = gMenuVisible;
RgnHandle menuRgn = GetMenuRgn();
if (!(*gMainMonitor)->full || gMenuVisible) return;
SaveMenuArea();
DiffRgn(GetGrayRgn(), menuRgn, GetGrayRgn());
CalcVis((WindowPeek)FrontWindow());
CalcVisBehind((WindowPeek)FrontWindow(), menuRgn);
LMSetMBarHeight(gMenuHeight);
gMenuVisible = true;
if (oldMenuVis) MyInvalMenuBar();
else {
AdjustMenus();
DrawMenuBar();
}
}
/*
* RehideMenuBar()
*
* Purpose: Removes the menu bar from the main screen, if it's currently full-screen
* Inputs: none
* Returns: nothing
*
*/
void RehideMenuBar(void)
{
RgnHandle menuRgn = GetMenuRgn();
if (!(*gMainMonitor)->full || !gMenuVisible || gInBackground) return;
UnionRgn(GetGrayRgn(), menuRgn, GetGrayRgn());
PaintOne((WindowPeek)FrontWindow(), menuRgn);
PaintBehind((WindowPeek)FrontWindow(), menuRgn);
CalcVis((WindowPeek)FrontWindow());
CalcVisBehind((WindowPeek)FrontWindow(), menuRgn);
LMSetMBarHeight(0);
gMenuVisible = false;
RestoreMenuArea();
}
/*
* FrontWindowRgn(theRgn)
*
* Purpose: Finds the frontmost window that lies unobscured in theRgn
* Inputs: theRgn = the region of interest, in global coordinates
* Returns: a pointer to the window found, or nil if none qualify
*
*/
WindowPtr FrontWindowRgn(RgnHandle theRgn)
{
WindowPtr theWindow = FWFrontWindow();
WindowPtr theResult = nil;
RgnHandle testRgn;
if (testRgn = NewRgn()) {
for ( ; theWindow; theWindow = NextWindow(theWindow)) {
CopyRgn(theWindow->visRgn, testRgn);
GlobalRgn(testRgn, theWindow);
SectRgn(theRgn, testRgn, testRgn);
if (EqualRgn(theRgn, testRgn)) {
theResult = theWindow;
break;
} else if (!EmptyRgn(testRgn)) break;
}
DisposeRgn(testRgn);
}
return theResult;
}
/*
* GetMenuRgn()
*
* Purpose: Calculates the region occupied by the menubar
* Inputs: none
* Returns: a handle to the region of the menu bar
*
*/
RgnHandle GetMenuRgn(void)
{
static RgnHandle gMenuRgn = nil;
if (!gMenuRgn) {
gMenuRgn = NewRgn();
gMenuHeight = GetMBarHeight();
}
if (gMenuRgn) SetRectRgn(gMenuRgn, (*gMainMonitor)->rect.left, (*gMainMonitor)->rect.top,
(*gMainMonitor)->rect.right, (*gMainMonitor)->rect.top + gMenuHeight);
return gMenuRgn;
}
/*
* GetActiveRect(theMonitor, theRect)
*
* Purpose: Determines the active area of the monitor, with or without menu bar as
* appropriate
* Inputs: theMonitor = a handle to the monitor record
* theRect = a pointer to the destination rectangle
* Returns: nothing
*
*/
void GetActiveRect(MonitorHandle theMonitor, Rect *theRect)
{
if ((theMonitor != gMainMonitor) || !gMenuVisible) *theRect = (*theMonitor)->rect;
else *theRect = (*(*theMonitor)->gray)->rgnBBox;
}
/*
* GetMinMaxMonitor(theImage)
*
* Purpose: Calculates the shallowest and deepest monitors intersecting the given
* image's window
* Inputs: theImage = a pointer to the image
* Returns: nothing
*
*/
void GetMinMaxMonitor(ImageHandle theImage)
{
MonitorHandle theMonitor, deepMon = nil, shallowMon = nil;
ushort pass, depth, shallowest = 100, deepest = 0;
Rect winRect, tmpRect;
if (!WindowVisible((*theImage)->window)) {
if (!(*theImage)->dmon) (*theImage)->dmon = gMainMonitor;
if (!(*theImage)->smon) (*theImage)->smon = gMainMonitor;
return;
}
for (pass = 1; pass <= 2; pass++) {
winRect = (pass == 1) ? (*GetContRgn((*theImage)->window))->rgnBBox :
(*GetStrucRgn((*theImage)->window))->rgnBBox;
InsetRect(&winRect, 1, 1);
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) {
if (SectRect(&winRect, &(*theMonitor)->rect, &tmpRect)) {
depth = (*theMonitor)->depth;
if (depth > deepest) {
deepest = depth;
deepMon = theMonitor;
}
if (depth < shallowest) {
shallowest = depth;
shallowMon = theMonitor;
}
}
}
if (deepMon && shallowMon) break;
}
if (deepMon && shallowMon) {
(*theImage)->dmon = deepMon;
(*theImage)->smon = shallowMon;
} else if (deepMon) (*theImage)->dmon = (*theImage)->smon = deepMon;
else if (shallowMon) (*theImage)->dmon = (*theImage)->smon = shallowMon;
else (*theImage)->dmon = (*theImage)->smon = gMainMonitor;
}
/*
* GetDeepMonitor(pickColor)
*
* Purpose: Returns a pointer to the current deepest monitor
* Inputs: pickColor = flag: true to pick color monitors first
* Returns: a MonitorHandle pointing to the deepest monitor
*
*/
MonitorHandle GetDeepMonitor(Boolean pickColor)
{
ushort depth, deepest = 0, color = pickColor;
MonitorHandle theMonitor, deepMon = nil;
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) {
depth = (*theMonitor)->depth;
if ((depth > deepest) ||
((depth == deepest) && ((pickColor && !color) || (!pickColor && color)))) {
deepest = depth;
deepMon = theMonitor;
color = (*theMonitor)->color;
}
}
return deepMon;
}
/*
* GetBigMonitor(pickColor)
*
* Purpose: Returns a handle to the current biggest monitor
* Inputs: pickColor = flag: true to pick color monitors first
* Returns: a MonitorHandle pointing to the biggest monitor
*
*/
MonitorHandle GetBigMonitor(Boolean pickColor)
{
ulong biggest = 0, size, color = pickColor;
MonitorHandle theMonitor, bigMon = nil;
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) {
size = (long)Height(&(*theMonitor)->rect) * (long)Width(&(*theMonitor)->rect);
if ((size > biggest) ||
((size == biggest) && ((pickColor && !color) || (!pickColor && color)))) {
biggest = size;
bigMon = theMonitor;
color = (*theMonitor)->color;
}
}
return bigMon;
}
/*
* GetImageMonitor(theImage)
*
* Purpose: Returns a pointer to the deepest monitor intersected by the image window
* Inputs: theImage = pointer to the image we're interested in
* Returns: a MonitorHandle of the deepest intersecting monitor
*
*/
MonitorHandle GetImageMonitor(ImageHandle theImage)
{
MonitorHandle theMonitor, deepMon = nil;
ushort depth, deepest = 0;
Rect theRect, tmpRect;
if (!theImage || !(*theImage)->window) return nil;
theRect = (*theImage)->wrect;
GlobalRect(&theRect, (*theImage)->window);
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) {
if (SectRect(&theRect, &(*theMonitor)->rect, &tmpRect)) {
depth = (*theMonitor)->depth;
if (depth > deepest) {
deepest = depth;
deepMon = theMonitor;
}
}
}
return deepMon;
}
/*
* GetMostDevice(theRect)
*
* Purpose: Returns a pointer to the monitor containing the most area of the window
* Inputs: theRect = pointer to a global rectangle
* Returns: a MonitorHandle of the relevant intersecting monitor
*
*/
MonitorHandle GetMostDevice(Rect *theRect)
{
MonitorHandle theMonitor, mostMon = gMainMonitor;
long area, largest = 0;
Rect tmpRect;
for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) {
SectRect(&(*theMonitor)->rect, theRect, &tmpRect);
area = (long)Width(&tmpRect) * (long)Height(&tmpRect);
if (area > largest) {
largest = area;
mostMon = theMonitor;
}
}
return mostMon;
}