mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-14 12:29:33 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
6.6 KiB
C
1 line
6.6 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
|
|
|
|
#include <string.h>
|
|
|
|
/*
|
|
* AllocatePort()
|
|
*
|
|
* Purpose: Allocates a port (actually a dialog record) from our global pool
|
|
* Inputs: none
|
|
* Returns: a pointer to the memory location
|
|
*
|
|
*/
|
|
|
|
CGrafPtr AllocatePort(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < kMaxPorts; i++)
|
|
if (!gPortPool[i].window.port.portBits.baseAddr) {
|
|
gPortPool[i].window.port.portBits.baseAddr = (Ptr)0xffffffff;
|
|
return (CGrafPtr)&gPortPool[i];
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
/*
|
|
* DecallocatePort(thePort)
|
|
*
|
|
* Purpose: Deallocates a port from our global pool
|
|
* Inputs: thePort = the port to deallocate
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
void DeallocatePort(CGrafPtr thePort)
|
|
{
|
|
Ptr theStart = StripAddress(gPortPool);
|
|
Ptr theEnd = theStart + kMaxPorts * sizeof(DialogRecord);
|
|
Ptr theAdr = StripAddress(thePort);
|
|
short i;
|
|
|
|
if ((theAdr >= theStart) && (theAdr < theEnd))
|
|
for (i = 0; i < sizeof(DialogRecord); i++) *theAdr++ = 0;
|
|
}
|
|
|
|
/*
|
|
* CheckedNewHandle(theSize, canForce)
|
|
*
|
|
* Purpose: Allocates a handle, either in the application heap or in the system heap
|
|
* Inputs: theSize = the size of the handle to allocate
|
|
* canForce = true if we're allowed to delete GWorlds to force memory
|
|
* Returns: a new handle, or nil if not enough memory
|
|
*
|
|
*/
|
|
|
|
Handle CheckedNewHandle(Size theSize, Boolean canForce)
|
|
{
|
|
OSErr theErr = noErr;
|
|
Handle theHandle;
|
|
|
|
if (!IsMemAvailable(theSize) || !(theHandle = NewHandle(theSize))) {
|
|
theHandle = TempNewHandle(theSize, &theErr);
|
|
if (theErr != noErr && canForce) {
|
|
if (!MakeMemAvailable(theSize) || !(theHandle = NewHandle(theSize)))
|
|
return nil;
|
|
}
|
|
}
|
|
return (theErr == noErr) ? theHandle : nil;
|
|
}
|
|
|
|
/*
|
|
* AnyNewHandle(theSize)
|
|
*
|
|
* Purpose: Allocates a handle, either in the application heap or in the system heap
|
|
* Inputs: theSize = the size of the handle to allocate
|
|
* Returns: a new handle, or nil if not enough memory
|
|
*
|
|
*/
|
|
|
|
Handle AnyNewHandle(Size theSize)
|
|
{
|
|
OSErr theErr = noErr;
|
|
Handle theHandle;
|
|
|
|
if (!(theHandle = NewHandle(theSize))) theHandle = TempNewHandle(theSize, &theErr);
|
|
return (theErr == noErr) ? theHandle : nil;
|
|
}
|
|
|
|
/*
|
|
* ClearMem(thePtr, theSize)
|
|
*
|
|
* Purpose: Zeroes out a block of memory
|
|
* Inputs: thePtr = pointer to the memory
|
|
* theSize = the size of the block to clear
|
|
* Returns: nothing
|
|
*
|
|
*/
|
|
|
|
void ClearMem(Ptr thePtr, register Size theSize)
|
|
{
|
|
register union {
|
|
uchar *cPtr;
|
|
ushort *sPtr;
|
|
ulong *lPtr;
|
|
} p;
|
|
|
|
p.cPtr = (uchar *)thePtr;
|
|
if (theSize && ((long)p.cPtr & 1)) *p.cPtr++ = 0, theSize--;
|
|
if (theSize && ((long)p.sPtr & 2)) *p.sPtr++ = 0, theSize -= 2;
|
|
while (theSize >= 4) *p.lPtr++ = 0, theSize -= 4;
|
|
if (theSize >= 2) *p.sPtr++ = 0, theSize -= 2;
|
|
if (theSize) *p.cPtr++ = 0;
|
|
// memset(thePtr, 0, theSize);
|
|
}
|
|
|
|
/*
|
|
* GWorldSize(theGWorld)
|
|
*
|
|
* Purpose: Returns the real size of the given GWorld
|
|
* Inputs: theGWorld = a pointer to the GWorld
|
|
* Returns: the size, in bytes
|
|
*
|
|
*/
|
|
|
|
long GWorldSize(GWorldPtr theGWorld)
|
|
{
|
|
long theSize = sizeof(CGrafPort) + sizeof(GDevice) + 4096;
|
|
PixMapHandle thePixMap;
|
|
|
|
if (!theGWorld) return 0;
|
|
thePixMap = GetGWorldPixMap(theGWorld);
|
|
if (thePixMap) {
|
|
if ((*thePixMap)->pmTable) {
|
|
theSize += (sizeof(ColorTable) + sizeof(ColorSpec) *
|
|
((*(*thePixMap)->pmTable)->ctSize + 1));
|
|
theSize += (1L << (*gMainMonitor)->oldres) * (1L << (*gMainMonitor)->oldres) *
|
|
(1L << (*gMainMonitor)->oldres);
|
|
}
|
|
theSize += (long)((*thePixMap)->rowBytes & 0x3fff) *
|
|
(long)Height(&(*thePixMap)->bounds);
|
|
}
|
|
return theSize;
|
|
}
|
|
|
|
/*
|
|
* EstGWorldSize(bounds, depth)
|
|
*
|
|
* Purpose: Returns an estimate of the GWorld size for a given rectangle and depth
|
|
* Inputs: bounds = the bounding rectange of the proposed GWorld
|
|
* depth = the proposed depth
|
|
* Returns: the size, in bytes
|
|
*
|
|
*/
|
|
|
|
long EstGWorldSize(Rect *bounds, short depth)
|
|
{
|
|
long theSize = sizeof(CGrafPort) + sizeof(GDevice) + 16384L;
|
|
|
|
if (depth <= 8) {
|
|
theSize += sizeof(ColorTable) + sizeof(ColorSpec) * (1 << depth);
|
|
theSize += (1 << (*gMainMonitor)->oldres) * (1 << (*gMainMonitor)->oldres) *
|
|
(1 << (*gMainMonitor)->oldres);
|
|
}
|
|
theSize += (((long)Width(bounds) * (long)depth) / 8L + 4L) * (long)Height(bounds);
|
|
return theSize;
|
|
}
|
|
|
|
/*
|
|
* IsMemAvailable(request)
|
|
*
|
|
* Purpose: Determines in a block of memory of the given size is available
|
|
* Inputs: request = the requested memory size
|
|
* Returns: true if there's room; false otherwise
|
|
*
|
|
*/
|
|
|
|
Boolean IsMemAvailable(long request)
|
|
{
|
|
long total, contig;
|
|
|
|
if (MaxBlock() > (request + gMemSlop)) return true;
|
|
PurgeSpace(&total, &contig);
|
|
return (request < contig) && ((request + gMemSlop) < total);
|
|
}
|
|
|
|
/*
|
|
* MakeMemAvailable(request)
|
|
*
|
|
* Purpose: Determines in a block of memory of the given size is available;
|
|
* if not, we try killing off some GWorlds to do it
|
|
* Inputs: request = the requested memory size
|
|
* Returns: true if there's room; false otherwise
|
|
*
|
|
*/
|
|
|
|
Boolean MakeMemAvailable(long request)
|
|
{
|
|
Boolean answer;
|
|
|
|
while (!(answer = IsMemAvailable(request)) && GetMem());
|
|
return answer;
|
|
}
|
|
|
|
/*
|
|
* GetMem()
|
|
*
|
|
* Purpose: Kills off the GWorld of the most-hidden window
|
|
* Inputs: none
|
|
* Returns: true if we found something to kill; false if we're out of options
|
|
*
|
|
*/
|
|
|
|
long GetMem(void)
|
|
{
|
|
WindowPtr theWindow, bestWindow = nil;
|
|
ImageHandle theImage, bestImage;
|
|
long theSize;
|
|
|
|
if (gThePrefs.useBitmaps == ubAlways) return 0;
|
|
for (theWindow = FWFrontWindow(); theWindow; theWindow = NextWindow(theWindow))
|
|
if ((theImage = FindImage(theWindow)) && (*theImage)->gworld) {
|
|
bestWindow = theWindow;
|
|
bestImage = theImage;
|
|
}
|
|
if (bestWindow == nil) return 0;
|
|
theSize = GWorldSize((*bestImage)->gworld);
|
|
KillGWorld(bestImage);
|
|
return theSize;
|
|
}
|
|
|
|
/*
|
|
* GrowZone(cbNeeded)
|
|
*
|
|
* Purpose: Called in emergencies; kills off unnecessary GWorlds
|
|
* Inputs: cbNeeded = the number of bytes we need
|
|
* Returns: the number of bytes we freed
|
|
*
|
|
*/
|
|
|
|
pascal long GrowZone(Size cbNeeded)
|
|
{
|
|
#if applec
|
|
#pragma unused(cbNeeded)
|
|
#endif
|
|
return 0;
|
|
/* long theA5 = SetCurrentA5(), val;
|
|
short tmpVal = gThePrefs.useBitmaps;
|
|
|
|
if (tmpVal == ubAlways) gThePrefs.useBitmaps = ubOptional;
|
|
val = GetMem();
|
|
gThePrefs.useBitmaps = tmpVal;
|
|
theA5 = SetA5(theA5);
|
|
return val;*/
|
|
}
|