270 lines
7.0 KiB
C
Executable File
270 lines
7.0 KiB
C
Executable File
/* ===========================================================================
|
|
|
|
PROJECT: FakeHandles
|
|
|
|
FILE: FakeHandles.c
|
|
|
|
PURPOSE: Simulate Handles on machines which only have ANSI-C to easily
|
|
port some of the more simple Macintosh code fragments to other
|
|
platforms.
|
|
|
|
(C) Copyright 1998 by Uli Kusterer, all rights reserved.
|
|
|
|
======================================================================== */
|
|
|
|
#pragma mark [Headers]
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Headers:
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#include "FakeHandles.h"
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Globals:
|
|
// -----------------------------------------------------------------------------
|
|
|
|
/* The last entry in the master pointer array is mis-used to hold a pointer
|
|
to another master pointer array. Thus, we have a linked list of master
|
|
pointer arrays in RAM, and we don't run out of master pointers as easily. */
|
|
MasterPointer gMasterPointers[MASTERPOINTER_CHUNK_SIZE];
|
|
long gFakeHandleError = noErr;
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
FakeInitHandles:
|
|
Call this to initialize the fake memory Manager at the start of your
|
|
program. Only call this once or you'll lose all your Handles and will have
|
|
stale memory lying around. Pass the global gMasterPointers in
|
|
masterPtrArray.
|
|
|
|
REVISIONS:
|
|
98-08-30 UK Created.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
void FakeInitHandles( MasterPointer* masterPtrArray )
|
|
{
|
|
long x;
|
|
|
|
for( x = 0; x < MASTERPOINTER_CHUNK_SIZE; x++ )
|
|
{
|
|
masterPtrArray[x].actualPointer = NULL;
|
|
masterPtrArray[x].used = false;
|
|
masterPtrArray[x].memoryFlags = 0;
|
|
masterPtrArray[x].size = 0;
|
|
}
|
|
|
|
gFakeHandleError = noErr;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
FakeMoreMasters:
|
|
Call this if you need more master pointers Called internally by
|
|
FakeNewHandle() when it runs out of master pointers.
|
|
|
|
REVISIONS:
|
|
98-08-30 UK Created.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
void FakeMoreMasters()
|
|
{
|
|
long x;
|
|
MasterPointer* vMPtrBlock;
|
|
MasterPointer* vCurrBlock;
|
|
|
|
// Make a new master pointer block:
|
|
vMPtrBlock = malloc( MASTERPOINTER_CHUNK_SIZE *sizeof(MasterPointer) );
|
|
if( vMPtrBlock == NULL )
|
|
{
|
|
gFakeHandleError = memFulErr;
|
|
return;
|
|
}
|
|
|
|
// Clear it:
|
|
for( x = 0; x < MASTERPOINTER_CHUNK_SIZE; x++ )
|
|
{
|
|
vMPtrBlock[x].actualPointer = NULL;
|
|
vMPtrBlock[x].used = false;
|
|
vMPtrBlock[x].memoryFlags = 0;
|
|
vMPtrBlock[x].size = 0;
|
|
}
|
|
|
|
// Find last master pointer in last master pointer block:
|
|
vCurrBlock = gMasterPointers;
|
|
while( vCurrBlock[MASTERPOINTER_CHUNK_SIZE -1].used == true )
|
|
vCurrBlock = (MasterPointer*) vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer;
|
|
|
|
// Make this last master pointer point to our new block:
|
|
vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer = (char*) vMPtrBlock;
|
|
vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used = true;
|
|
vMPtrBlock[MASTERPOINTER_CHUNK_SIZE-1].size = MASTERPOINTER_CHUNK_SIZE *sizeof(MasterPointer);
|
|
|
|
gFakeHandleError = noErr;
|
|
}
|
|
|
|
|
|
Handle FakeNewEmptyHandle()
|
|
{
|
|
Handle theHandle = NULL;
|
|
long x;
|
|
MasterPointer* vCurrBlock = gMasterPointers;
|
|
bool notFound = true;
|
|
|
|
gFakeHandleError = noErr;
|
|
|
|
while( notFound )
|
|
{
|
|
for( x = 0; x < (MASTERPOINTER_CHUNK_SIZE-1); x++ )
|
|
{
|
|
if( !(vCurrBlock[x].used) )
|
|
{
|
|
vCurrBlock[x].used = true;
|
|
vCurrBlock[x].memoryFlags = 0;
|
|
vCurrBlock[x].size = 0;
|
|
|
|
theHandle = (Handle) &(vCurrBlock[x]);
|
|
notFound = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used ) // Last is unused? We need a new master pointer block!
|
|
{
|
|
FakeMoreMasters();
|
|
if( !vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used ) // No new block added?!
|
|
notFound = false; // Terminate, it's very likely an error occurred.
|
|
}
|
|
vCurrBlock = (MasterPointer*) vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer; // Go next master pointer block.
|
|
}
|
|
|
|
return theHandle;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
NewHandle:
|
|
Create a new Handle. This creates a new entry in the Master Ptr array and
|
|
allocates memory of the specified size for it. Then it returns a Ptr to
|
|
this entry.
|
|
|
|
Returns NULL if not successful. If MemError() is noErr upon a NULL return
|
|
value, we are out of master pointers.
|
|
|
|
REVISIONS:
|
|
2001-02-16 UK Added support for error codes.
|
|
1998-08-30 UK Created.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
Handle FakeNewHandle( long theSize )
|
|
{
|
|
MasterPointer * theHandle = (MasterPointer*) FakeNewEmptyHandle();
|
|
|
|
theHandle->actualPointer = malloc( theSize );
|
|
if( theHandle->actualPointer == NULL )
|
|
{
|
|
FakeDisposeHandle( (Handle) theHandle );
|
|
gFakeHandleError = memFulErr;
|
|
}
|
|
else
|
|
theHandle->size = theSize;
|
|
|
|
return (Handle)theHandle;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
DisposeHandle:
|
|
Dispose an existing Handle. Only call this once or you might kill valid
|
|
memory or worse.
|
|
|
|
This frees the memory we use and marks the entry for the specified Handle
|
|
as unused.
|
|
|
|
REVISIONS:
|
|
1998-08-30 UK Created.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
void FakeDisposeHandle( Handle theHand )
|
|
{
|
|
MasterPointer* theEntry = (MasterPointer*) theHand;
|
|
|
|
if( theEntry->actualPointer )
|
|
free( theEntry->actualPointer );
|
|
theEntry->used = false;
|
|
theEntry->actualPointer = NULL;
|
|
theEntry->memoryFlags = 0;
|
|
theEntry->size = 0;
|
|
}
|
|
|
|
|
|
void FakeEmptyHandle( Handle theHand )
|
|
{
|
|
MasterPointer* theEntry = (MasterPointer*) theHand;
|
|
|
|
if( theEntry->actualPointer )
|
|
free( theEntry->actualPointer );
|
|
theEntry->actualPointer = NULL;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
GetHandleSize:
|
|
Return the size of an existing Handle. This simply examines the "size"
|
|
field of the Handle's entry.
|
|
|
|
REVISIONS:
|
|
1998-08-30 UK Created.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
long FakeGetHandleSize( Handle theHand )
|
|
{
|
|
MasterPointer* theEntry = (MasterPointer*) theHand;
|
|
|
|
gFakeHandleError = noErr;
|
|
|
|
return( theEntry->size );
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
SetHandleSize:
|
|
Change the size of an existing Handle. This reallocates the Handle (keeping
|
|
its data) and updates the size field of the Handle's entry accordingly.
|
|
|
|
REVISIONS:
|
|
1998-08-30 UK Created.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
void FakeSetHandleSize( Handle theHand, long theSize )
|
|
{
|
|
MasterPointer* theEntry = (MasterPointer*) theHand;
|
|
char* thePtr;
|
|
|
|
thePtr = theEntry->actualPointer;
|
|
thePtr = realloc( thePtr, theSize );
|
|
|
|
if( thePtr )
|
|
{
|
|
theEntry->actualPointer = thePtr;
|
|
theEntry->size = theSize;
|
|
gFakeHandleError = noErr;
|
|
}
|
|
else
|
|
gFakeHandleError = memFulErr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|