/**************************************************************************** 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 */