windows-nt/Source/XPSP1/NT/com/ole32/olecnv32/bufio.c
2020-09-26 16:20:57 +08:00

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)0;
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( HANDLE 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 = (ULONG) 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 ) 0;
}
}
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 */