JPEGView/Source/C/MemoryUtils.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
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;*/
}