395 lines
10 KiB
C
395 lines
10 KiB
C
/****************************************************************************
|
|
Unit Bufio; Implementation
|
|
*****************************************************************************
|
|
|
|
Bufio implements the structured reading of the imput stream. As such, it
|
|
will handle the necessary byte-swapping that must occur when reading a
|
|
native Macintosh file.
|
|
|
|
This interface will also shield the calling application from knowledge of
|
|
the source format (file vs. memory).
|
|
|
|
Module Prefix: IO
|
|
|
|
****************************************************************************/
|
|
|
|
#include "headers.c"
|
|
#pragma hdrstop
|
|
|
|
#include "filesys.h"
|
|
|
|
#ifndef _OLECNV32_
|
|
//#include "status.h"
|
|
#endif // _OLECNV32_
|
|
|
|
/*********************** Exported Data **************************************/
|
|
|
|
|
|
/*********************** Private Data ***************************************/
|
|
|
|
#define UNKNOWN 0
|
|
#define FILE 1
|
|
#define MEMORY 2
|
|
#define RTF 3
|
|
|
|
#define BUFFERSIZE 1024
|
|
|
|
private LongInt numBytesRead;
|
|
private LongInt pictureSize;
|
|
private LongInt beginOffset;
|
|
|
|
private LongInt bufferCount;
|
|
private Byte buffer[BUFFERSIZE];
|
|
private Byte * nextCharPtr;
|
|
private Byte huge * nextCharHPtr;
|
|
|
|
private Byte sourceType = UNKNOWN;
|
|
private Integer fileHandle = ( Integer ) NULL;
|
|
private Str255 fileName;
|
|
private Boolean openFile;
|
|
|
|
private Byte huge * memoryHPtr;
|
|
private Handle memoryHandle;
|
|
|
|
private Handle dialogHandle;
|
|
|
|
/*********************** Private Function Definitions ***********************/
|
|
|
|
private void ReadNextBuffer( void );
|
|
/* Replenish the i/o buffer with the next set of characters */
|
|
|
|
/* Memory operations - check return values on usage */
|
|
#define MDisposHandle( h ) ((void) GlobalFree( h ))
|
|
#define MLock( h ) ((LPtr) GlobalLock( h ))
|
|
#define MUnlock( h ) ((void) GlobalUnlock( h ))
|
|
#define MDR( h ) ((LPtr) GlobalLock( h ))
|
|
#define MUR( h ) ((void) GlobalUnlock( h ))
|
|
#define MNewHandle( s ) GlobalAlloc( GMEM_MOVEABLE, s )
|
|
|
|
/*********************** Function Implementation ****************************/
|
|
|
|
void IOGetByte( Byte far * byteLPtr )
|
|
/*============*/
|
|
/* Read a byte from the input stream. If the buffer is empty, then
|
|
it is replenished. */
|
|
{
|
|
/* Make sure that no global error code has been set before read */
|
|
if (ErGetGlobalError() != NOERR )
|
|
{
|
|
*byteLPtr = 0;
|
|
return;
|
|
}
|
|
|
|
/* Check for an attempt to read past the EOF or memory block. This
|
|
would indicate that the opcode parsing was thrown off somewhere. */
|
|
if (numBytesRead >= pictureSize)
|
|
{
|
|
ErSetGlobalError( ErReadPastEOF );
|
|
*byteLPtr = 0;
|
|
return;
|
|
}
|
|
|
|
/* Check to see if we need to replenish the read buffer */
|
|
if (bufferCount <= 0)
|
|
{
|
|
ReadNextBuffer();
|
|
}
|
|
|
|
/* Decrement the count of characters in the buffer, increment the total
|
|
number of bytes read from the file, and return the next character. */
|
|
bufferCount--;
|
|
numBytesRead++;
|
|
|
|
/* determine where to read the next byte from - use short or huge ptrs */
|
|
*byteLPtr = (sourceType == FILE) ? *nextCharPtr++ : *nextCharHPtr++;
|
|
|
|
} /* IOGetByte */
|
|
|
|
|
|
|
|
void IOSkipBytes( LongInt byteCount )
|
|
/*==============*/
|
|
/* Skip the designated number of bytes */
|
|
{
|
|
/* make sure we are skipping a valid number of bytes */
|
|
if (byteCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Check for an attempt to read past the EOF or memory block. This
|
|
would indicate that the opcode parsing was thrown off somewhere. */
|
|
if (numBytesRead + byteCount >= pictureSize)
|
|
{
|
|
ErSetGlobalError( ErReadPastEOF );
|
|
}
|
|
else
|
|
{
|
|
/* determine if there are sufficient bytes remaining in the buffer */
|
|
if (bufferCount >= byteCount)
|
|
{
|
|
/* decrement # bytes remaining, increment # bytes read and pointer */
|
|
bufferCount -= byteCount;
|
|
numBytesRead += byteCount;
|
|
|
|
/* increment the appropriate pointer based on media type */
|
|
if (sourceType == FILE)
|
|
{
|
|
/* increment near pointer to data segment buffer */
|
|
nextCharPtr += byteCount;
|
|
}
|
|
else
|
|
{
|
|
/* increment huge pointer to global memory block */
|
|
nextCharHPtr += byteCount;
|
|
}
|
|
}
|
|
else /* sourceType == FILE and buffer needs to be replenished */
|
|
{
|
|
Byte unusedByte;
|
|
|
|
/* continue calling IOGetByte() until desired number are skipped */
|
|
while (byteCount--)
|
|
{
|
|
/* call IOGetByte to make sure the cache is replenished */
|
|
IOGetByte( &unusedByte );
|
|
}
|
|
}
|
|
}
|
|
|
|
} /* IOSkipBytes */
|
|
|
|
|
|
|
|
void IOAlignToWordOffset( void )
|
|
/*======================*/
|
|
/* Align next memory read to Word boundary. */
|
|
{
|
|
/* check to see if we have read an odd number of bytes so far. Skip
|
|
the ensuing byte if necessary to align. */
|
|
if (numBytesRead & 0x0001)
|
|
{
|
|
IOSkipBytes( 1 );
|
|
}
|
|
|
|
} /* IOAlignToWordOffset */
|
|
|
|
|
|
#ifndef _OLECNV32_
|
|
void IOSetFileName( StringLPtr pictFileName )
|
|
/*================*/
|
|
/* Interface routine to set the source filename */
|
|
{
|
|
lstrcpy( fileName, pictFileName );
|
|
sourceType = FILE;
|
|
openFile = TRUE;
|
|
|
|
} /* IOSetFileName */
|
|
|
|
void IOSetFileHandleAndSize( Integer pictFileHandle, LongInt pictFileSize )
|
|
/*=========================*/
|
|
/* Interface routine to set the source file Handle */
|
|
{
|
|
fileHandle = pictFileHandle;
|
|
pictureSize = pictFileSize;
|
|
sourceType = FILE;
|
|
openFile = FALSE;
|
|
|
|
} /* IOSetFIleHandle */
|
|
#endif // !_OLECNV32_
|
|
|
|
|
|
|
|
void IOSetMemoryHandle( Integer pictMemoryHandle )
|
|
/*==================*/
|
|
/* Interface routine to set the source file Handle */
|
|
{
|
|
memoryHandle = ( Handle ) pictMemoryHandle;
|
|
sourceType = MEMORY;
|
|
|
|
} /* IOSetMemoryHandle */
|
|
|
|
|
|
|
|
void IOSetReadOffset( LongInt readOffset )
|
|
/*==================*/
|
|
/* Set the beginning offset to seek to when the file is opened */
|
|
{
|
|
beginOffset = readOffset;
|
|
}
|
|
|
|
|
|
|
|
void IOOpenPicture( Handle dialog )
|
|
/*================*/
|
|
/* Open the input stream depending on the source type set by a previous
|
|
IOSet___ interface routine. Determine the size of the picture image. */
|
|
{
|
|
#ifndef _OLECNV32_
|
|
OSErr openError;
|
|
#endif // !_OLECNV32_
|
|
|
|
/* if the type isn't set, return error */
|
|
if (sourceType == UNKNOWN)
|
|
{
|
|
ErSetGlobalError( ErNoSourceFormat );
|
|
return;
|
|
}
|
|
|
|
/* initialize the various reader variables */
|
|
numBytesRead = 0;
|
|
bufferCount = 0;
|
|
|
|
/* determine how to open the soure data stream */
|
|
#ifndef _OLECNV32_
|
|
if (sourceType == FILE)
|
|
{
|
|
/* if we are openning and converting an entire file */
|
|
if (openFile)
|
|
{
|
|
/* open the file */
|
|
openError = FSOpen( (StringLPtr)fileName, OF_READ | OF_SHARE_DENY_WRITE, &fileHandle );
|
|
if (openError)
|
|
{
|
|
ErSetGlobalError( ErOpenFail);
|
|
}
|
|
else
|
|
{
|
|
/* and determine the file length */
|
|
FSSetFPos( fileHandle, FSFROMLEOF, 0L );
|
|
FSGetFPos( fileHandle, &pictureSize );
|
|
}
|
|
}
|
|
|
|
/* set position to the designated start position */
|
|
FSSetFPos( fileHandle, FSFROMSTART, beginOffset );
|
|
numBytesRead = beginOffset;
|
|
}
|
|
else /* if (sourceType == MEMORY) */
|
|
#endif // !_OLECNV32_
|
|
{
|
|
/* lock the memory block */
|
|
memoryHPtr = (Byte huge *) MLock( memoryHandle );
|
|
if (memoryHPtr == NULL)
|
|
{
|
|
ErSetGlobalError( ErMemoryFail );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
/* and determine the overall memory block size */
|
|
pictureSize = GlobalSize( memoryHandle );
|
|
}
|
|
|
|
/* set the huge character read pointer, bytes read, and buffer count */
|
|
nextCharHPtr = memoryHPtr + beginOffset;
|
|
bufferCount = pictureSize - beginOffset;
|
|
numBytesRead = beginOffset;
|
|
}
|
|
|
|
#ifndef _OLECNV32_
|
|
/* make sure that a dialog handle was supplied for update */
|
|
if (dialog)
|
|
{
|
|
/* save off the dialog box handle */
|
|
dialogHandle = dialog;
|
|
|
|
/* calculate the interval to update the status dialog */
|
|
SendMessage( dialogHandle, SM_SETRANGE, 0, pictureSize );
|
|
}
|
|
#endif // !OLECNV32
|
|
|
|
} /* IOOpenPicture */
|
|
|
|
|
|
|
|
void IOClosePicture( void )
|
|
/*=================*/
|
|
/* Close the source input stream */
|
|
{
|
|
/* if this is a file-based metafile */
|
|
#ifndef _OLECNV32_
|
|
if (sourceType == FILE)
|
|
{
|
|
/* make sure this isn't the ImportEmbeddedGr() entry point */
|
|
if (openFile)
|
|
{
|
|
/* close the file if necessary */
|
|
FSCloseFile( fileHandle );
|
|
fileHandle = ( Integer ) NULL;
|
|
}
|
|
}
|
|
else
|
|
#endif // !_OLECNV32_
|
|
{
|
|
/* unlock the global memory block */
|
|
MUnlock( memoryHandle );
|
|
memoryHandle = NULL;
|
|
}
|
|
|
|
/* de-initialize the module variables */
|
|
sourceType = UNKNOWN;
|
|
dialogHandle = NULL;
|
|
|
|
} /* IOClosePicture */
|
|
|
|
|
|
|
|
void IOUpdateStatus( void )
|
|
/*=================*/
|
|
/* Update the status bar dialog to reflect current progress */
|
|
{
|
|
#ifndef _OLECNV32_
|
|
/* update only if a dialog box was created */
|
|
if (dialogHandle)
|
|
{
|
|
/* calculate the interval to update the status dialog */
|
|
SendMessage( dialogHandle, SM_SETPOSITION, 0, numBytesRead );
|
|
}
|
|
#endif // !_OLECNV32_
|
|
|
|
} /* IOUpdateStatus */
|
|
|
|
|
|
|
|
/******************************* Private Routines ***************************/
|
|
|
|
|
|
private void ReadNextBuffer( void )
|
|
/*-------------------------*/
|
|
/* Replenish the i/o buffer with the next set of characters. This should
|
|
only be called if performing buffered I/O - not with MEMORY-based file */
|
|
{
|
|
#ifndef _OLECNV32_
|
|
OSErr fileError;
|
|
|
|
/* Read the required number of bytes from the file. Check the error
|
|
code return and set the global status error if the read failed. */
|
|
|
|
if (sourceType == FILE)
|
|
{
|
|
/* Calculate the number of bytes that should be read into the buffer.
|
|
This needs to be done, since this may be a memory source picture,
|
|
in which an invalid read could produce a GP violation */
|
|
if (numBytesRead + BUFFERSIZE > pictureSize)
|
|
bufferCount = pictureSize - numBytesRead;
|
|
else
|
|
bufferCount = BUFFERSIZE;
|
|
|
|
/* read the bytes from the file */
|
|
fileError = FSRead( fileHandle, &bufferCount, &buffer);
|
|
|
|
/* if there is any error, notify the error module */
|
|
if (fileError != 0)
|
|
{
|
|
ErSetGlobalError( ErReadFail );
|
|
return;
|
|
}
|
|
|
|
/* reset the character read pointer to the beginning of the buffer */
|
|
nextCharPtr = buffer;
|
|
}
|
|
#endif // _OLECNV32_
|
|
|
|
} /* ReadNextBuffer */
|