Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3281 lines
80 KiB

/*
| CHUNKER.C
|
| So chunky, you'll be tempted to use a fork.
*/
#define XCHUNK
#include <platform.h>
#include <sccut.h>
#include <sccch.h>
#include "chunker.pro"
#include "chprtns.pro"
#include "chbmrtns.pro"
#include "chssrtns.pro"
#include "chdbrtns.pro"
#include "chartns.pro"
#include "chvrtns.pro"
#include "sccss.pro"
#include "chmaps.h"
#ifdef WIN32
#include "sccch_n.c"
#endif
/*** Here's one that proto refuses to deal with. ***/
extern VOID SO_ENTRYMOD SOPutReversedRGBData( BYTE VWPTR * pData, DWORD dwUser1, DWORD dwUser2 );
LPCHUNKMEISTER Chunker;
PCHUNK ChunkTable;
LPSTR ChunkBufPtr;
BYTE CharMap[512];
#define NULLHANDLE (HANDLE) NULL
#include "chdefs.h"
#ifdef CHDEBUG
VOID DebugCall( WORD, HANDLE );
#define DebugCall(c,h) if(hDebugWnd!=NULLHANDLE) SendMessage(hDebugWnd,WM_COMMAND,666,MAKELONG(c,h))
HWND hDebugWnd = NULLHANDLE;
VOID RegisterDebug( HWND hwnd )
{
hDebugWnd = hwnd;
}
#endif
VOID SO_ENTRYMOD SOBailOut( wType, dwUser1, dwUser2 )
WORD wType;
DWORD dwUser1;
DWORD dwUser2;
{
PFILTER pFilter;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( GETHFILTER(dwUser2) );
VwBailOut(pFilter,SCCCHERR_VIEWERBAIL);
RestoreWorld();
}
VOID CHBailOut(wErr)
WORD wErr;
{
PFILTER pFilter = (PFILTER) UTGlobalLock(Chunker->hFilter);
VwBailOut(pFilter,wErr);
}
VOID SOPutSysChar( wCh, dwUser1, dwUser2 )
WORD wCh;
DWORD dwUser1;
DWORD dwUser2;
{
if( !Chunker->ChunkFinished )
{
*CHUNKBUFPTR++ = (BYTE) wCh;
Chunker->CurChunkSize++;
}
}
VOID SOPutWord( wVal, dwUser1, dwUser2 )
WORD wVal;
DWORD dwUser1;
DWORD dwUser2;
{
if( !Chunker->ChunkFinished )
{
CHMemCopy( CHUNKBUFPTR, (LPSTR) (WORD FAR *)&wVal, 2 );
Chunker->CurChunkSize += 2;
CHUNKBUFPTR += 2;
}
}
VOID SOPutDWord( dwVal, dwUser1, dwUser2 )
DWORD dwVal;
DWORD dwUser1;
DWORD dwUser2;
{
if( !Chunker->ChunkFinished )
{
CHMemCopy( CHUNKBUFPTR, (LPSTR) (DWORD FAR *)&dwVal, 4 );
Chunker->CurChunkSize += 4;
CHUNKBUFPTR += 4;
}
}
// Make sure this is kept up-to-date.
#define SO_BREAKSIZE 3
WORD SO_ENTRYMOD SOPutBreak( wType, dwInfo, dwUser1, dwUser2 )
WORD wType;
DWORD dwInfo;
DWORD dwUser1;
DWORD dwUser2;
{
PCHUNK pCurChunk;
WORD Ret = SO_CONTINUE;
PFILTER pFilter;
HPSOTABLEROWFORMAT pRow;
SetupWorld();
if( Chunker->IDCurChunk != ID_NULLCHUNK )
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
else
pCurChunk = NULL;
pFilter = (PFILTER) UTGlobalLock( GETHFILTER(dwUser2) );
switch( wType )
{
case SO_SECTIONBREAK:
if( Chunker->ChunkFinished )
{
UTGlobalUnlock ( GETHFILTER(dwUser2) );
RestoreWorld();
return SO_STOP;
}
// Set up the section structure for the next new section.
// (We're guaranteed not to have a section break at the end of the document.)
if( Chunker->wFlags & CH_LOOKAHEAD ) // Chunk boundaries have been established.
{
if( CHAddNewSection(GETHFILTER(dwUser2)) )
CHBailOut(SCCCHERR_OUTOFMEMORY); // Error!
}
if( Chunker->pSection->wType != SO_PARAGRAPHS )
{
switch( Chunker->pSection->wType )
{
case SO_VECTOR:
CHFinishUpVectorChunk( pCurChunk );
case SO_CELLS:
case SO_BITMAP:
case SO_ARCHIVE:
case SO_FIELDS:
if( Chunker->pSection->wType == SO_FIELDS )
UTGlobalUnlock( Chunker->pSection->Attr.Fields.hCol );
Chunker->pSection->Flags |= CH_SECTIONFINISHED;
if( !(pCurChunk->Flags & CH_COMPLETE) )
{
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
if( Chunker->CurChunkSize )
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
break;
}
Ret = SO_STOP;
break;
}
// If we're in a paragraph section, we'll fall through to handle the
// section break with the paragraph breaks.
Chunker->pSection->Flags |= CH_SECTIONFINISHED;
case SO_PARABREAK:
if( Chunker->CurChunkSize+SO_BREAKSIZE > SO_CHUNK_LIMIT )
CHSetupNewChunk( GETHFILTER(dwUser2) );
if( !Chunker->ChunkFinished && wType == SO_PARABREAK )
{
Chunker->dwChunkCountables++;
SOPutSysChar( SO_BEGINTOKEN, dwUser1, dwUser2 );
SOPutSysChar( SO_BREAK, dwUser2, dwUser2 );
SOPutSysChar( SO_PARABREAK, dwUser1, dwUser2 );
}
if( !(Chunker->wFlags & CH_LOOKAHEAD) ) // Chunk boundaries have been established.
{
// Have we hit the end of the chunk?
if( !Chunker->ChunkFinished &&
(Chunker->dwChunkCountables == pCurChunk->Info.Text.dwEndOfCountables) )
{
Chunker->ChunkFinished = TRUE;
pCurChunk->Info.Text.Size = (SHORT)Chunker->CurChunkSize;
pCurChunk->Flags &= ~CH_OVERFLOW;
*CHUNKBUFPTR++ = (BYTE)SO_BEGINTOKEN;
*CHUNKBUFPTR++ = (BYTE)SO_ENDOFCHUNK;
}
}
else if( wType == SO_SECTIONBREAK && !Chunker->ChunkFinished )
{
if( !(pCurChunk->Flags & CH_COMPLETE) )
{
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
if( Chunker->CurChunkSize )
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
pCurChunk->Info.Text.Size = (SHORT)Chunker->CurChunkSize;
pCurChunk->Info.Text.dwEndOfCountables = Chunker->dwChunkCountables;
Chunker->ChunkFinished = TRUE;
*CHUNKBUFPTR++ = (BYTE)SO_BEGINTOKEN;
*CHUNKBUFPTR++ = (BYTE)SO_ENDOFCHUNK;
}
if( !Chunker->ChunkFinished )
{
// If we're in a table, we only set seek positions on row boundaries.
if( !(Chunker->wFlags & CH_TABLETEXT) )
CHResetParaSeek( GETHFILTER(dwUser2) );
CHResetParaAttributeFunctions( pFilter );
}
else
Ret = SO_STOP;
break;
case SO_TABLECELLBREAK:
if( Chunker->CurChunkSize+SO_BREAKSIZE > SO_CHUNK_LIMIT )
CHSetupNewChunk( GETHFILTER(dwUser2) );
if( !Chunker->ChunkFinished )
{
Chunker->dwChunkCountables++;
SOPutSysChar( SO_BEGINTOKEN, dwUser1, dwUser2 );
SOPutSysChar( SO_BREAK, dwUser2, dwUser2 );
SOPutSysChar( SO_TABLECELLBREAK, dwUser1, dwUser2 );
CHResetParaAttributeFunctions( pFilter );
Chunker->Doc.Text.wCurTableColumn++;
/*** No need for this now, I guess.
if( Chunker->Doc.Text.wCurTableColumn == Chunker->Doc.Text.wNumTableColumns )
{
// Last cell of the row.
}
****/
}
break;
case SO_TABLEROWBREAK:
if( Chunker->CurChunkSize+SO_BREAKSIZE > SO_CHUNK_LIMIT )
CHSetupNewChunk( GETHFILTER(dwUser2) );
if( !Chunker->ChunkFinished )
{
SOPutSysChar( SO_BEGINTOKEN, dwUser1, dwUser2 );
SOPutSysChar( SO_BREAK, dwUser2, dwUser2 );
SOPutSysChar( SO_TABLEROWBREAK, dwUser1, dwUser2 );
Chunker->Doc.Text.wCurTableColumn = 0;
Chunker->Doc.Text.wCurTableRow++;
Chunker->Doc.Text.bRowFormatted = FALSE;
CHResetParaAttributeFunctions( pFilter );
if( Chunker->wFlags & CH_LOOKAHEAD )
{
pRow = CHLockRowFormat( Chunker->pSection->Attr.Para.hRowInfo, Chunker->Doc.Text.dwRowFormatOffset);
pRow->wNumRows++;
UTGlobalUnlock( Chunker->pSection->Attr.Para.hRowInfo );
CHResetParaSeek( GETHFILTER(dwUser2) );
}
else
{
// Have we hit the end of the chunk?
if( Chunker->dwChunkCountables == pCurChunk->Info.Text.dwEndOfCountables )
{
Chunker->ChunkFinished = TRUE;
pCurChunk->Info.Text.Size = (SHORT)Chunker->CurChunkSize;
pCurChunk->Flags &= ~CH_OVERFLOW;
*CHUNKBUFPTR++ = (BYTE)SO_BEGINTOKEN;
*CHUNKBUFPTR++ = (BYTE)SO_ENDOFCHUNK;
Ret = SO_STOP;
}
}
}
else
Ret = SO_STOP;
break;
case SO_ARCHIVEBREAK:
if( Chunker->CurChunkSize + sizeof(WORD) > SO_CHUNK_LIMIT )
CHSetupNewChunk( GETHFILTER(dwUser2) );
if( !Chunker->ChunkFinished )
{
SOPutWord( SO_ARCENDOFRECORD, dwUser1, dwUser2 );
SSMark(GETHFILTER(dwUser2));
Chunker->Doc.Archive.IndexPtr--;
if( Chunker->wFlags & CH_LOOKAHEAD )
{
pCurChunk->Info.Archive.wLastRec = Chunker->Doc.Archive.wCurRecord;
Chunker->Doc.Archive.wCurRecord++;
}
// Set the lookup table entry for the next archive record in advance.
if( (LPSTR) Chunker->Doc.Archive.IndexPtr > CHUNKBUFPTR )
*Chunker->Doc.Archive.IndexPtr = (SHORT)Chunker->CurChunkSize;
else
{
CHSetupNewChunk( GETHFILTER(dwUser2) );
Ret = SO_STOP;
}
}
else
Ret = SO_STOP;
break;
case SO_CELLBREAK:
if( Chunker->ChunkFinished )
Ret = SO_STOP;
else
{
SSMark(GETHFILTER(dwUser2));
if( Chunker->wFlags & CH_LOOKAHEAD )
{
pCurChunk->Info.Cells.Last.Row = Chunker->Doc.Cells.CurRow;
pCurChunk->Info.Cells.Last.Col = Chunker->Doc.Cells.CurCol;
pCurChunk->Info.Cells.dwLastCell = Chunker->Doc.Cells.dwCurCell;
}
Chunker->Doc.Cells.dwCurCell++;
if( Chunker->Doc.Cells.CellGrouping == GROUPED_IN_ROWS )
{
if( ++(Chunker->Doc.Cells.CurCol) >= (WORD)Chunker->Doc.Cells.dwGroupSize )
{
// We need to jump to the next row.
Chunker->Doc.Cells.CurCol = 0;
Chunker->Doc.Cells.CurRow++;
}
}
else
{
if( ++(Chunker->Doc.Cells.CurRow) > (WORD)Chunker->Doc.Cells.dwGroupSize )
{
// We need to jump to the next column.
Chunker->Doc.Cells.CurRow = 0;
Chunker->Doc.Cells.CurCol++;
}
}
}
break;
case SO_RECORDBREAK:
if( Chunker->ChunkFinished )
Ret = SO_STOP;
else
{
// Force token alignment for next record to be on even addresses?
AlignMacro;
if( Chunker->wFlags & CH_LOOKAHEAD )
{
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
pCurChunk->Info.Fields.dwLastRec = Chunker->Doc.Fields.dwCurRec;
SSMark( GETHFILTER(dwUser2) );
}
else if( Chunker->Doc.Fields.dwCurRec == pCurChunk->Info.Fields.dwLastRec )
Ret = SO_STOP;
Chunker->Doc.Fields.wCurField = 0;
Chunker->Doc.Fields.dwCurRec++;
Chunker->Doc.Fields.wRecordSize = 0;
}
break;
case SO_VECTORBREAK:
if( Chunker->CurChunkSize + sizeof(WORD) > SO_CHUNK_LIMIT )
CHSetupNewChunk( GETHFILTER(dwUser2) );
if( !Chunker->ChunkFinished )
{
if( Chunker->wFlags & CH_LOOKAHEAD )
pCurChunk->Info.Vector.dwVectorSize = Chunker->CurChunkSize;
}
else
Ret = SO_STOP;
break;
case SO_SCANLINEBREAK:
Chunker->CurChunkSize += pCurChunk->Info.Bitmap.wLineBytes;
Chunker->Doc.Bitmap.wCurScanLine++;
if( Chunker->Doc.Bitmap.wDirection != UPSIDEDOWN )
CHUNKBUFPTR += pCurChunk->Info.Bitmap.wLineBytes;
else
CHUNKBUFPTR -= pCurChunk->Info.Bitmap.wLineBytes;
if( Chunker->Doc.Bitmap.wCurScanLine ==
pCurChunk->Info.Bitmap.wYOffset + pCurChunk->Info.Bitmap.wYClip )
{
CHSetupNewChunk( GETHFILTER(dwUser2) );
if( !(CHUNKTABLE[Chunker->IDCurChunk].Flags & CH_CONTINUATION) )
Ret = SO_STOP;
}
break;
case SO_EOFBREAK:
switch( Chunker->pSection->wType )
{
case SO_PARAGRAPHS:
if( Chunker->CurChunkSize )
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
if( Chunker->CurChunkSize+SO_BREAKSIZE > SO_CHUNK_LIMIT )
CHSetupNewChunk( GETHFILTER(dwUser2) );
SOPutSysChar( SO_BEGINTOKEN, dwUser1, dwUser2 );
SOPutSysChar( SO_BREAK, dwUser2, dwUser2 );
SOPutSysChar( (BYTE) wType, dwUser1, dwUser2 );
if( !Chunker->ChunkFinished )
{
*CHUNKBUFPTR++ = (BYTE)SO_BEGINTOKEN;
*CHUNKBUFPTR++ = (BYTE)SO_ENDOFCHUNK;
Chunker->dwChunkCountables++; // Eof break is countable.
pCurChunk->Info.Text.dwEndOfCountables = Chunker->dwChunkCountables;
Chunker->pSection->Flags |= CH_SECTIONFINISHED;
Chunker->EofFlag = -1;
Chunker->ChunkFinished = TRUE;
pCurChunk->Info.Text.Size = (SHORT)Chunker->CurChunkSize;
if( !(pCurChunk->Flags & CH_COMPLETE) )
{
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
}
break;
case SO_VECTOR:
CHFinishUpVectorChunk( pCurChunk );
// fall through
case SO_CELLS:
case SO_BITMAP:
case SO_ARCHIVE:
if( Chunker->CurChunkSize )
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
// still fall through
case SO_FIELDS:
if( Chunker->pSection->wType == SO_FIELDS )
UTGlobalUnlock( Chunker->pSection->Attr.Fields.hCol );
if( !Chunker->ChunkFinished && (Chunker->wFlags & CH_LOOKAHEAD) )
{
Chunker->pSection->Flags |= CH_SECTIONFINISHED;
Chunker->EofFlag = EOF;
Chunker->ChunkFinished = TRUE;
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
break;
}
Ret = SO_STOP;
break;
case SO_SUBDOCBEGINBREAK:
CHUpdateParagraphFunctions( CH_INACTIVE, GETHFILTER(dwUser2) );
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOSubdocPutBreak, pFilter->hProc );
Chunker->SubdocLevel++;
break;
}
UTGlobalUnlock( GETHFILTER(dwUser2) );
RestoreWorld();
return( Ret );
}
/****************
WORD SO_ENTRYMOD SOQueryRecordBreak( wType, dwUser1, dwUser2 )
WORD wType;
DWORD dwUser1;
DWORD dwUser2;
{
switch( wType )
{
case SO_RECORDBREAK:
break;
}
}
***************/
WORD SO_ENTRYMOD SOSubdocPutBreak( wType, dwInfo, dwUser1, dwUser2 )
WORD wType;
DWORD dwInfo;
DWORD dwUser1;
DWORD dwUser2;
{
PFILTER pFilter;
SetupWorld();
if( wType == SO_SUBDOCENDBREAK )
{
Chunker->SubdocLevel--;
if( !Chunker->SubdocLevel )
{
if( Chunker->wFlags & CH_SKIPTEXT )
{
CHSetDeletionFunctions( GETHFILTER(dwUser2) );
if( !(Chunker->wFlags & CH_NOPARAATTR) )
{
// If we haven't already deleted a paragraph break within
// our current text (which is being skipped), we need to
// restore the addresses of our paragraph attribute functions.
pFilter = (PFILTER) UTGlobalLock( GETHFILTER(dwUser2) );
if( Chunker->Doc.Text.MarginOffset > 0 )
pFilter->VwRtns.SetSoRtn( SOPUTMARGINS, SOUpdatePageMargins, pFilter->hProc );
else
pFilter->VwRtns.SetSoRtn( SOPUTMARGINS, SOPutMargins, pFilter->hProc );
if( Chunker->Doc.Text.IndentOffset > 0 )
pFilter->VwRtns.SetSoRtn( SOPUTPARAINDENTS, SOUpdateParaIndents, pFilter->hProc );
else
pFilter->VwRtns.SetSoRtn( SOPUTPARAINDENTS, SOPutParaIndents, pFilter->hProc );
if( Chunker->Doc.Text.SpacingOffset > 0 )
pFilter->VwRtns.SetSoRtn( SOPUTPARASPACING, SOUpdateParaSpacing, pFilter->hProc );
else
pFilter->VwRtns.SetSoRtn( SOPUTPARASPACING, SOPutParaSpacing, pFilter->hProc );
if( Chunker->Doc.Text.AlignOffset > 0 )
pFilter->VwRtns.SetSoRtn( SOPUTPARAALIGN, SOUpdateParaAlign, pFilter->hProc );
else
pFilter->VwRtns.SetSoRtn( SOPUTPARAALIGN, SOPutParaAlign, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOSTARTTABSTOPS , SOStartTabstops, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTTABSTOP , SOPutTabstop, pFilter->hProc );
UTGlobalUnlock( GETHFILTER(dwUser2) );
}
}
else
CHUpdateParagraphFunctions( CH_ACTIVE, GETHFILTER(dwUser2) );
}
}
else if( wType == SO_SUBDOCBEGINBREAK )
Chunker->SubdocLevel++;
RestoreWorld();
return SO_CONTINUE;
}
#define SO_GRAPHICOBJECTSIZE (2*sizeof(BYTE)+sizeof(DWORD))
VOID SO_ENTRYMOD SOPutGraphicObject( pObject, dwUser1, dwUser2 )
PSOGRAPHICOBJECT pObject;
DWORD dwUser1;
DWORD dwUser2;
{
BYTE HUGE * pTable;
DWORD dwEmbedOffset;
SetupWorld();
if( Chunker->CurChunkSize+SO_GRAPHICOBJECTSIZE > SO_CHUNK_LIMIT )
CHSetupNewChunk( GETHFILTER(dwUser2) );
if( !Chunker->ChunkFinished )
{
if( Chunker->wFlags & CH_LOOKAHEAD )
{
if( Chunker->pSection->dwEmbedCount % CH_EMBEDDEDALLOCCOUNT == 0 )
{
if( Chunker->pSection->hEmbedded == NULLHANDLE )
Chunker->pSection->hEmbedded = UTGlobalAlloc(pObject->wStructSize * CH_EMBEDDEDALLOCCOUNT);
else
Chunker->pSection->hEmbedded = CHGlobalRealloc(Chunker->pSection->hEmbedded,
pObject->wStructSize * Chunker->pSection->dwEmbedCount,
pObject->wStructSize * (Chunker->pSection->dwEmbedCount+CH_EMBEDDEDALLOCCOUNT) );
if( Chunker->pSection->hEmbedded == NULLHANDLE )
CHBailOut(SCCCHERR_OUTOFMEMORY);
}
pTable = UTGlobalLock(Chunker->pSection->hEmbedded);
dwEmbedOffset = pObject->wStructSize * Chunker->pSection->dwEmbedCount;
pTable += dwEmbedOffset;
#ifdef WINDOWS
// Segment bullshit.
if( (dwEmbedOffset+pObject->wStructSize)/0x010000 > dwEmbedOffset/0x010000 )
{
// We're crossing a segment boundary. Let's split our copying
// because we can't trust a copy across a segment boundary.
DWORD dwPieceSize;
BYTE HUGE * pObj = (BYTE HUGE *)pObject;
dwPieceSize = 0x010000 - (dwEmbedOffset%0x010000);
UTmemcpy( pTable, pObj, (WORD)dwPieceSize );
pTable += dwPieceSize;
pObj += dwPieceSize;
UTmemcpy( pTable, pObj, pObject->wStructSize-(WORD)dwPieceSize );
}
else
UTmemcpy( pTable, (BYTE HUGE *) pObject, pObject->wStructSize );
#endif
#ifdef MAC
UTmemcpy( pTable, pObject, pObject->wStructSize );
#endif
#ifdef OS2
UTmemcpy( pTable, pObject, pObject->wStructSize );
#endif
Chunker->pSection->dwEmbedCount++;
UTGlobalUnlock(Chunker->pSection->hEmbedded);
}
SOPutSysChar( SO_BEGINTOKEN, dwUser1, dwUser2 );
SOPutSysChar( SO_GRAPHICOBJECT, dwUser2, dwUser2 );
SOPutDWord( Chunker->Doc.Text.dwCurGraphicId++, dwUser1, dwUser2 );
}
RestoreWorld();
}
VOID SO_ENTRYMOD SOGetInfo( wId, lpData, dwUser1, dwUser2 )
WORD wId;
VOID FAR * lpData;
DWORD dwUser1;
DWORD dwUser2;
{
DWORD dwVal;
SetupWorld();
switch( wId )
{
case SOINFO_COLUMNRANGE:
if( Chunker->Doc.Cells.CellGrouping == GROUPED_IN_ROWS )
dwVal = MAKELONG( 0, (Chunker->pSection->Attr.Cells.wNumCols-1) );
else
dwVal = MAKELONG( 0, (WORD)(Chunker->pSection->Attr.Cells.dwNumRows-1) );
CHMemCopy( lpData, (LPSTR) &dwVal, sizeof(DWORD) );
break;
case SOINFO_STARTRECORD:
break;
}
RestoreWorld();
}
//*************************************************************
// SECTION ROUTINES
//*************************************************************
VOID SO_ENTRYMOD SOPutSectionType( wType, dwUser1, dwUser2 )
WORD wType;
DWORD dwUser1;
DWORD dwUser2;
{
PFILTER pFilter;
HPROC hProc;
#ifdef OS2
void (* VW_ENTRYMOD SetSoRtn)(SHORT, VOID (* SO_ENTRYMOD)(), HPROC);
#else
void (VW_ENTRYMOD * SetSoRtn)(SHORT, VOID (SO_ENTRYMOD *)(), HPROC);
#endif
BYTE locStr[20];
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( GETHFILTER(dwUser2) );
SetSoRtn = pFilter->VwRtns.SetSoRtn;
hProc = pFilter->hProc;
if( Chunker->pSection->Flags & CH_NEWSECTION )
{
(*(SetSoRtn))( SOPUTSECTIONNAME, SOPutSectionName, hProc );
(*(SetSoRtn))( SOSETDATEBASE, SOSetDateBase, hProc );
(*(SetSoRtn))( SOSTARTHDRINFO, SOStartHdrInfo, hProc );
(*(SetSoRtn))( SOENDHDRINFO, SOEndHdrInfo, hProc );
(*(SetSoRtn))( SOPUTHDRENTRY, SOPutHdrEntry, hProc );
switch( wType )
{
case SO_PARAGRAPHS:
pFilter->VwRtns.SetSoRtn( SOSTARTFONTTABLE, SOStartFontTable, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOBEGINTABLE, SOBeginTable, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTGRAPHICOBJECT, SOPutGraphicObject, pFilter->hProc );
CHUpdateParagraphFunctions( CH_ACTIVE, GETHFILTER(dwUser2) );
Chunker->NumTextSections++;
UTNumToString(Chunker->NumTextSections,locStr);
UTstrcpy(Chunker->pSection->szName,"Document ");
UTstrcat(Chunker->pSection->szName,locStr);
Chunker->pSection->Attr.Para.wNumTables = 0;
Chunker->pSection->Attr.Para.hRowInfo = NULLHANDLE;
Chunker->pSection->Attr.Para.hTables = NULLHANDLE;
Chunker->Doc.Text.dwRowBufSize = 0L;
Chunker->Doc.Text.dwRowBufSize = 0L;
Chunker->Doc.Text.dwRowBufCount = 0L;
Chunker->Doc.Text.dwRowFormatOffset = 0L;
Chunker->Doc.Text.wTableBufSize = 0;
Chunker->Doc.Text.wTablesPresent = 0;
Chunker->Doc.Text.dwCurGraphicId = 0L;
break;
case SO_CELLS:
Chunker->pSection->Attr.Cells.pCol = NULL;
Chunker->pSection->Attr.Cells.hCol = NULLHANDLE;
Chunker->pSection->Attr.Cells.wNumCols = 0;
Chunker->pSection->Attr.Cells.dwDateBase = 0;
Chunker->pSection->Attr.Cells.dwLayoutFlags = 0;
Chunker->pSection->Attr.Cells.wPrefWidth = 0;
Chunker->pSection->Attr.Cells.wPrefHeight = 0;
(*(SetSoRtn))( SOSTARTCOLUMNINFO, SOStartCellInfo, hProc );
(*(SetSoRtn))( SOPUTCOLUMNINFO, SOPutColumnInfo, hProc );
(*(SetSoRtn))( SOENDCOLUMNINFO, NULL, hProc );
(*(SetSoRtn))( SOCELLLAYOUTINFO, SOCellLayoutInfo, hProc );
Chunker->NumCellSections++;
UTNumToString(Chunker->NumCellSections,locStr);
UTstrcpy(Chunker->pSection->szName,"Sheet ");
UTstrcat(Chunker->pSection->szName,locStr);
break;
case SO_FIELDS:
Chunker->pSection->Attr.Fields.pCol = NULL;
Chunker->pSection->Attr.Fields.hCol = NULLHANDLE;
Chunker->pSection->Attr.Fields.wNumCols = 0;
Chunker->pSection->Attr.Fields.dwDateBase = 0;
/**** Intended for use with database query and sort.
Chunker->pSection->Attr.Fields.hColFlags = NULL;
Chunker->pSection->Attr.Fields.pColFlags = NULL;
***/
(*(SetSoRtn))( SOSTARTFIELDINFO, SOStartFieldInfo, hProc );
(*(SetSoRtn))( SOPUTFIELDINFO, SOPutFieldInfo, hProc );
(*(SetSoRtn))( SOENDFIELDINFO, NULL, hProc );
Chunker->NumFieldSections++;
UTNumToString(Chunker->NumFieldSections,locStr);
UTstrcpy(Chunker->pSection->szName,"Database ");
UTstrcat(Chunker->pSection->szName,locStr);
break;
case SO_ARCHIVE:
Chunker->Doc.Archive.wCurRecord = 0;
break;
case SO_VECTOR:
SetSoRtn( SOPUTVECTORHEADER, SOPutVectorHeader, hProc );
SetSoRtn( SOSTARTPALETTE , SOStartVectorPalette , hProc );
SetSoRtn( SOPUTPALETTEENTRY, SOPutVectorPaletteEntry, hProc );
Chunker->Doc.Vector.wCurItem = 0;
Chunker->NumGraphicSections++;
UTNumToString(Chunker->NumGraphicSections,locStr);
UTstrcpy(Chunker->pSection->szName,"Image ");
UTstrcat(Chunker->pSection->szName,locStr);
Chunker->pSection->Flags |= (CH_CACHEBACKWARDS | CH_SEEKONLYTOTOP);
break;
case SO_BITMAP:
SetSoRtn( SOPUTBITMAPHEADER, SOPutBitmapHeader, hProc );
SetSoRtn( SOPUTSCANLINEDATA, SOPutScanLineData, hProc );
Chunker->NumGraphicSections++;
UTNumToString(Chunker->NumGraphicSections,locStr);
UTstrcpy(Chunker->pSection->szName,"Image ");
UTstrcat(Chunker->pSection->szName,locStr);
break;
}
Chunker->pSection->wType = wType;
}
UTGlobalUnlock( GETHFILTER(dwUser2) );
RestoreWorld();
}
VOID SO_ENTRYMOD SOPutSectionName( lpName, dwUser1, dwUser2 )
LPSTR lpName;
DWORD dwUser1;
DWORD dwUser2;
{
WORD size, x;
SetupWorld();
size = min( CH_SECTIONNAMESIZE-1, UTstrlen(lpName) );
// CHMemCopy( Chunker->pSection->szName, lpName, size );
for (x=0;x<size;x++)
Chunker->pSection->szName[x] = CharMap[(BYTE)lpName[x]];
Chunker->pSection->szName[size] = '\0';
RestoreWorld();
}
VOID SO_ENTRYMOD SOStartHdrInfo( dwUser1, dwUser2 )
DWORD dwUser1;
DWORD dwUser2;
{
SetupWorld();
if( Chunker->pSection->hHeaderInfo != NULLHANDLE )
UTGlobalFree( Chunker->pSection->hHeaderInfo );
Chunker->pSection->wNumHeaderItems = 0;
RestoreWorld();
}
VOID SO_ENTRYMOD SOPutHdrEntry( pStr1, pStr2, wId, dwUser1, dwUser2 )
LPSTR pStr1;
LPSTR pStr2;
WORD wId;
DWORD dwUser1;
DWORD dwUser2;
{
WORD wNewDataSize;
LPSTR lpData;
WORD wStrSize1;
WORD wStrSize2;
SetupWorld();
wStrSize1 = UTstrlen( pStr1 );
wStrSize2 = UTstrlen( pStr2 );
wNewDataSize = wStrSize1 + wStrSize2 + (3*sizeof(WORD));
if( Chunker->pSection->wNumHeaderItems )
Chunker->pSection->hHeaderInfo = CHGlobalRealloc( Chunker->pSection->hHeaderInfo,
Chunker->pSection->wTotalHeaderSize,
Chunker->pSection->wTotalHeaderSize+wNewDataSize );
else
Chunker->pSection->hHeaderInfo = UTGlobalAlloc( wNewDataSize );
if( Chunker->pSection->hHeaderInfo == NULLHANDLE )
{
// Error!!!
}
else
{
lpData = UTGlobalLock( Chunker->pSection->hHeaderInfo );
lpData += Chunker->pSection->wTotalHeaderSize;
CHMemCopy( lpData, (LPSTR) &wId, sizeof(WORD));
lpData += sizeof(WORD);
CHMemCopy( lpData, (LPSTR) &wStrSize1, sizeof(WORD) );
lpData += sizeof(WORD);
CHMemCopy( lpData, (LPSTR) &wStrSize2, sizeof(WORD) );
lpData += sizeof(WORD);
UTstrcpy( lpData, pStr1 );
lpData += wStrSize1;
UTstrcpy( lpData, pStr2 );
lpData += wStrSize2;
Chunker->pSection->wTotalHeaderSize += wNewDataSize;
Chunker->pSection->wNumHeaderItems++;
}
RestoreWorld();
}
VOID SO_ENTRYMOD SOEndHdrInfo( dwUser1, dwUser2 )
DWORD dwUser1;
DWORD dwUser2;
{
}
VOID SO_ENTRYMOD SOSetDateBase( dwBase, wFlags, dwUser1, dwUser2 )
DWORD dwBase;
WORD wFlags;
DWORD dwUser1;
DWORD dwUser2;
{
SetupWorld();
if( Chunker->pSection->wType == SO_CELLS )
{
Chunker->pSection->Attr.Cells.dwDateBase = dwBase;
Chunker->pSection->Attr.Cells.wDateFlags = wFlags;
}
else
{
Chunker->pSection->Attr.Fields.dwDateBase = dwBase;
Chunker->pSection->Attr.Fields.wDateFlags = wFlags;
}
RestoreWorld();
}
VOID SO_ENTRYMOD SOStartFontTable( dwUser1, dwUser2 )
DWORD dwUser1;
DWORD dwUser2;
{
PFILTER pFilter;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( GETHFILTER(dwUser2) );
pFilter->VwRtns.SetSoRtn( SOSTARTFONTTABLE, NULL, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTFONTTABLEENTRY, SOPutFontTableEntry, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOENDFONTTABLE, SOEndFontTable, pFilter->hProc );
UTGlobalUnlock( GETHFILTER(dwUser2) );
if( Chunker->pSection->hFontTable != NULLHANDLE )
{
UTGlobalFree( Chunker->pSection->hFontTable );
Chunker->pSection->hFontTable = NULLHANDLE;
Chunker->pSection->wNumFonts = 0;
}
Chunker->pSection->hFontTable = UTGlobalAlloc( sizeof(SOFONTENTRY)*SOFONTSPERALLOC );
RestoreWorld();
}
VOID SO_ENTRYMOD SOPutFontTableEntry( dwId, wType, pName, dwUser1, dwUser2 )
DWORD dwId;
WORD wType;
LPSTR pName;
DWORD dwUser1;
DWORD dwUser2;
{
PSOFONTENTRY pTable;
// ATOM aName;
HANDLE hFontTable;
WORD wNameSize;
BYTE pNullFontName[2] = "\0";
SetupWorld();
if( Chunker->pSection->hFontTable != NULLHANDLE )
{
if( Chunker->pSection->wNumFonts &&
!(Chunker->pSection->wNumFonts % SOFONTSPERALLOC) )
{
hFontTable = CHGlobalRealloc( Chunker->pSection->hFontTable,
Chunker->pSection->wNumFonts * sizeof(SOFONTENTRY),
(Chunker->pSection->wNumFonts+SOFONTSPERALLOC) * sizeof(SOFONTENTRY) );
if( hFontTable == NULLHANDLE )
{
RestoreWorld();
return;
}
else
Chunker->pSection->hFontTable = hFontTable;
}
pTable = (PSOFONTENTRY) UTGlobalLock( Chunker->pSection->hFontTable );
pTable[Chunker->pSection->wNumFonts].dwId = dwId;
pTable[Chunker->pSection->wNumFonts].wType = wType;
if (pName == NULL)
pName = pNullFontName;
wNameSize = min( SOFONTNAMESIZE-1, UTstrlen(pName) );
UTmemcpy( pTable[Chunker->pSection->wNumFonts].szName, pName, wNameSize );
pTable[Chunker->pSection->wNumFonts].szName[SOFONTNAMESIZE-1] = '\0'; // Make sure strings are null terminated.
Chunker->pSection->wNumFonts++;
UTGlobalUnlock( Chunker->pSection->hFontTable );
}
RestoreWorld();
}
WORD CHAddFontTableEntry( lpName, wType, lpId, dwUser1, dwUser2 )
LPSTR lpName;
WORD wType;
LPDWORD lpId;
DWORD dwUser1;
DWORD dwUser2;
{
PSOFONTENTRY pTable;
DWORD dwId;
WORD i;
WORD ret = TRUE;
if( Chunker->pSection->hFontTable != NULLHANDLE )
{
pTable = (PSOFONTENTRY) UTGlobalLock( Chunker->pSection->hFontTable );
for( i=0; i<Chunker->pSection->wNumFonts; i++ )
{
// Prevent duplicates.
if( !UTstrcmp( pTable[i].szName, lpName ) )
{
*lpId = pTable[i].dwId;
UTGlobalUnlock( Chunker->pSection->hFontTable );
return( TRUE );
}
}
dwId = CHGENERATEDFONTID | Chunker->pSection->wNumFonts;
for( i=0; i<Chunker->pSection->wNumFonts; i++ )
{
// Prevent duplicates.
if( pTable[i].dwId == dwId )
{
dwId++;
i = 0;
continue;
}
}
UTGlobalUnlock( Chunker->pSection->hFontTable );
*lpId = dwId;
SOPutFontTableEntry( dwId, wType, lpName, dwUser1, dwUser2 );
}
else
ret = FALSE;
return( ret );
}
VOID SO_ENTRYMOD SOEndFontTable( dwUser1, dwUser2 )
DWORD dwUser1;
DWORD dwUser2;
{
PFILTER pFilter;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( GETHFILTER(dwUser2) );
pFilter->VwRtns.SetSoRtn( SOSTARTFONTTABLE, SOStartFontTable, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTFONTTABLEENTRY, NULL, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOENDFONTTABLE, NULL, pFilter->hProc );
UTGlobalUnlock( GETHFILTER(dwUser2) );
RestoreWorld();
}
/*************** REPLACED WITH ROUTINE BELOW so deal with it. *****
VOID CH_ENTRYMOD CHGetSecInfo( hFilter, wSection, SecInfo )
HFILTER hFilter;
WORD wSection;
PCHSECTIONINFO SecInfo;
{
PFILTER pFilter;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( hFilter );
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
*SecInfo = Chunker->pSectionTable[wSection];
UTGlobalUnlock( pFilter->hChunkInfo );
UTGlobalUnlock( hFilter );
RestoreWorld();
}
**************************/
CH_ENTRYSC PCHSECTIONINFO CH_ENTRYMOD CHLockSectionInfo( hFilter, wSection )
HFILTER hFilter;
WORD wSection;
{
PFILTER pFilter;
PCHSECTIONINFO SecInfo;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( hFilter );
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
SecInfo = &(Chunker->pSectionTable[wSection]);
UTGlobalUnlock( pFilter->hChunkInfo );
UTGlobalUnlock( hFilter );
RestoreWorld();
return( SecInfo );
}
CH_ENTRYSC VOID CH_ENTRYMOD CHUnlockSectionInfo(hFilter,wSection)
HFILTER hFilter;
WORD wSection;
{
SetupWorld();
RestoreWorld();
}
CH_ENTRYSC HANDLE CH_ENTRYMOD CHGetSecData( hFilter, wSection )
HFILTER hFilter;
WORD wSection;
{
PFILTER pFilter;
HANDLE hData;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( hFilter );
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
if( Chunker->pSectionTable[ wSection ].wType == SO_CELLS )
hData = Chunker->pSectionTable[ wSection ].Attr.Cells.hCol;
else
hData = Chunker->pSectionTable[ wSection ].Attr.Fields.hCol;
UTGlobalUnlock( pFilter->hChunkInfo );
UTGlobalUnlock( hFilter );
RestoreWorld();
return( hData );
}
WORD SO_ENTRYMOD SOPutDeletedBreak( wType, dwInfo, dwUser1, dwUser2 )
WORD wType;
DWORD dwInfo;
DWORD dwUser1;
DWORD dwUser2;
{
PFILTER pFilter;
WORD SuppressParaAttr = FALSE;
SetupWorld();
if( wType == SO_PARABREAK )
{
// Don't let subsequent paragraphs affect the formatting
// of the current paragraph.
SuppressParaAttr = TRUE;
Chunker->wFlags |= CH_NOPARAATTR;
Chunker->dwChunkCountables++;
if( Chunker->dwChunkCountables == Chunker->dwDesiredCountable )
{
EDLeaveDeletion( GETHFILTER(dwUser2) );
}
}
else if( wType == SO_SUBDOCBEGINBREAK )
{
SuppressParaAttr = TRUE;
CHUpdateParagraphFunctions( CH_INACTIVE, GETHFILTER(dwUser2) );
Chunker->SubdocLevel++;
pFilter = (PFILTER) UTGlobalLock( GETHFILTER(dwUser2) );
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOSubdocPutBreak, pFilter->hProc );
UTGlobalUnlock( GETHFILTER(dwUser2) );
}
if( SuppressParaAttr && !(Chunker->wFlags & CH_NOPARAATTR) )
{
pFilter = (PFILTER) UTGlobalLock( GETHFILTER(dwUser2) );
(*(pFilter->VwRtns.SetSoRtn))( SOPUTPARAALIGN , NULL, pFilter->hProc );
(*(pFilter->VwRtns.SetSoRtn))( SOPUTPARAINDENTS, NULL, pFilter->hProc );
(*(pFilter->VwRtns.SetSoRtn))( SOPUTPARASPACING, NULL, pFilter->hProc );
(*(pFilter->VwRtns.SetSoRtn))( SOSTARTTABSTOPS , NULL, pFilter->hProc );
(*(pFilter->VwRtns.SetSoRtn))( SOENDTABSTOPS , NULL, pFilter->hProc );
(*(pFilter->VwRtns.SetSoRtn))( SOPUTTABSTOP , NULL, pFilter->hProc );
(*(pFilter->VwRtns.SetSoRtn))( SOPUTMARGINS , NULL, pFilter->hProc );
UTGlobalUnlock( GETHFILTER(dwUser2) );
}
return( SO_CONTINUE );
RestoreWorld();
}
VOID CHSetupNewChunk( hFilter )
HFILTER hFilter;
{
PCHUNK pCurChunk;
PCHUNK pNextChunk;
PFILTER pFilter;
HPROC hProc;
SHORT i;
WORD IDNextChunk;
pFilter = (PFILTER) UTGlobalLock(hFilter);
hProc = pFilter->hProc;
if( !Chunker->ChunkFinished )
{
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
switch( Chunker->pSection->wType )
{
case SO_PARAGRAPHS:
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
if( Chunker->wFlags & CH_LOOKAHEAD )
{
IDNextChunk = IDNextNewChunk();
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
pNextChunk = &(CHUNKTABLE[ IDNextChunk ]);
if( !(pCurChunk->Flags & CH_COMPLETE) )
{
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
Chunker->ChunkFinished = CHHandleParaChunkBoundary( pCurChunk, pNextChunk, hFilter );
}
else
{
// We've filled a chunk to its previously determined number of
// countables. This condition is handled in SOPutBreak, except
// for chunks that don't contain a paragraph break. Thus, the
// next chunk will be a "continuation chunk".
Chunker->ChunkFinished = TRUE;
pCurChunk->Info.Text.Size = (SHORT)Chunker->CurChunkSize;
// Add the end-of-chunk token.
*CHUNKBUFPTR++ = (BYTE)SO_BEGINTOKEN;
*CHUNKBUFPTR++ = (BYTE)SO_ENDOFCHUNK;
}
if( Chunker->ChunkFinished )
CHUpdateParagraphFunctions( CH_INACTIVE, hFilter );
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, hProc );
Chunker->CurChunkSize = 0;
break;
case SO_ARCHIVE:
Chunker->ChunkFinished = TRUE;
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
if( Chunker->wFlags & CH_LOOKAHEAD )
{
IDNextChunk = IDNextNewChunk();
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
pNextChunk = &(CHUNKTABLE[ IDNextChunk ]);
// Save the seek data for the next chunk.
SSSave( &(pNextChunk->SeekID), hFilter );
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
Chunker->CurChunkSize = 0;
break;
case SO_CELLS:
if( !(pCurChunk->Flags & CH_COMPLETE) )
{
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
// Turn off the SOPutCell functions.
Chunker->ChunkFinished = TRUE;
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
pFilter->VwRtns.SetSoRtn( SOPUTDATACELL, NULL, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTTEXTCELL, NULL, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTMORETEXT, NULL, pFilter->hProc );
if( Chunker->wFlags & CH_LOOKAHEAD )
{
IDNextChunk = IDNextNewChunk();
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
pNextChunk = &(CHUNKTABLE[ IDNextChunk ]);
pNextChunk->Info.Cells.First.Row = Chunker->Doc.Cells.CurRow;
pNextChunk->Info.Cells.First.Col = Chunker->Doc.Cells.CurCol;
pNextChunk->Info.Cells.dwFirstCell = Chunker->Doc.Cells.dwCurCell;
pNextChunk->Info.Cells.dwLastCell = Chunker->Doc.Cells.dwCurCell;
SSSave( &(pNextChunk->SeekID), hFilter );
}
break;
case SO_FIELDS:
if( !(pCurChunk->Flags & CH_COMPLETE) )
{
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
Chunker->ChunkFinished = TRUE;
pFilter->VwRtns.SetSoRtn( SOPUTFIELD, NULL, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTVARFIELD, NULL, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTMOREVARFIELD, NULL, pFilter->hProc );
UTGlobalUnlock( Chunker->pSection->Attr.Fields.hCol );
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
if( Chunker->wFlags & CH_LOOKAHEAD )
{
IDNextChunk = IDNextNewChunk();
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
pNextChunk = &(CHUNKTABLE[ IDNextChunk ]);
pNextChunk->Info.Fields.dwFirstRec = pNextChunk->Info.Fields.dwLastRec
= Chunker->Doc.Fields.dwCurRec;
SSSave( &(pNextChunk->SeekID), hFilter );
}
break;
case SO_VECTOR:
/*
| Okay, here's the deal. On or about the week of 10-11-93, we've
| decided that vector chunks will be retrieved only in order, and
| that we may only seek to the first chunk in a vector image.
| So we added the code that grows vector chunks larger until a
| valid break point, and we will mark all vector chunks after
| the first as continuation chunks, and let the existing code
| deal with them nicely.
*/
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
if( Chunker->wFlags & CH_LOOKAHEAD )
{
Chunker->pSection->wCurTotalChunks++;
IDNextChunk = IDNextNewChunk();
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
pNextChunk = &(CHUNKTABLE[ IDNextChunk ]);
pCurChunk->Flags |= CH_COMPLETE;
Chunker->ChunkFinished = TRUE;
CHFinishUpVectorChunk( pCurChunk );
// Mark the next chunk as a continuation chunk.
// Because we grew the chunk, instead of throwing away data,
// we won't need to seek to read the next chunk.
pNextChunk->Flags |= (CH_CONTINUATION | CH_DONTSEEKCHUNK);
pNextChunk->SeekID = pCurChunk->SeekID;
pNextChunk->Info.Vector.wFirstItem = Chunker->Doc.Vector.wCurItem;
}
else
{
if( Chunker->CurChunkSize != CHUNKTABLE[Chunker->IDCurChunk].Info.Vector.dwVectorSize )
CHBailOut((WORD)-1);
CHUNKBUFPTR = &(Chunker->CurChunkBuf[pCurChunk->Info.Vector.dwVectorSize]);
i = (SHORT) SO_VECTORENDOFCHUNK;
CHMemCopy( CHUNKBUFPTR, (LPSTR) &i, sizeof(SHORT) );
Chunker->ChunkFinished = TRUE;
}
Chunker->Doc.Vector.wLastSectionSeen = Chunker->IDCurSection;
Chunker->CurChunkSize = 0;
break;
case SO_BITMAP:
if( !(pCurChunk->Flags & CH_COMPLETE) )
{
pCurChunk->Flags |= CH_COMPLETE;
Chunker->pSection->wCurTotalChunks++;
}
Chunker->ChunkFinished = TRUE;
Chunker->pSection->Flags &= ~CH_EMPTYSECTION;
if( Chunker->wFlags & CH_LOOKAHEAD )
{
if( Chunker->pSection->wCurTotalChunks != Chunker->pSection->wChunkTableSize )
{
IDNextChunk = IDNextNewChunk();
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
if( CHUNKTABLE[IDNextChunk].Flags & CH_CONTINUATION )
{
CHUNKTABLE[IDNextChunk].SeekID = pCurChunk->SeekID;
// We're going to keep going, so that we don't have to
// break out of our call to VwStreamRead.
// Store the current chunk in the ChunksInMemory array.
if( Chunker->ChunksInMemory == MAXCHUNKSINMEMORY )
{
i = IDNextChunk;
while( CHUNKTABLE[i].SeekID == pCurChunk->SeekID && i > 0)
i--;
CHFlushChunks( Chunker->IDCurSection, (WORD)(i+1), hFilter );
if( Chunker->ChunksInMemory == MAXCHUNKSINMEMORY && (WORD)i+2 < IDNextChunk )
CHFlushChunks( Chunker->IDCurSection, (WORD)(i+2), hFilter );
}
if( Chunker->ChunksInMemory < MAXCHUNKSINMEMORY )
{
Chunker->LoadedChunks[ Chunker->ChunksInMemory++ ] = Chunker->LookAheadChunk;
Chunker->LookAheadChunk.hMem = UTGlobalAlloc( Chunker->Doc.Bitmap.wChunkSize);
if( Chunker->LookAheadChunk.hMem == NULLHANDLE )
CHBailOut(SCCCHERR_OUTOFMEMORY);
Chunker->CurChunkBuf = CHUNKBUFPTR = (LPSTR) UTGlobalLock( Chunker->LookAheadChunk.hMem );
Chunker->IDCurChunk = Chunker->LookAheadChunk.IDChunk = IDNextChunk;
CHTopOfChunk( hFilter, hProc, pFilter );
}
else
CHBailOut(SCCCHERR_OUTOFMEMORY);
}
else
{
SSMark( hFilter );
SSSave( &(CHUNKTABLE[IDNextChunk].SeekID), hFilter );
}
}
}
break;
}
}
UTGlobalUnlock( hFilter );
}
// Takes a pointer to a MEMORYCHUNK structure. Adds the specified
// chunk to the cache of chunks, and sets the structure's fields
// to those of the chunk that was bumped out of the cache, if any.
// Returns TRUE if a chunk was bumped, FALSE otherwise.
BOOL CHStoreChunkInMemory( pMemChunk )
PMEMORYCHUNK pMemChunk;
{
SHORT i, wLastChunk;
MEMORYCHUNK locMemChunk;
BOOL bRet = TRUE;
if( Chunker->ChunksInMemory == MAXCHUNKSINMEMORY )
{
wLastChunk = MAXCHUNKSINMEMORY-1;
locMemChunk = Chunker->LoadedChunks[ wLastChunk ];
}
else
{
wLastChunk = Chunker->ChunksInMemory;
Chunker->ChunksInMemory++;
locMemChunk.IDChunk = ID_NULLCHUNK;
locMemChunk.hMem = NULLHANDLE;
bRet = FALSE;
}
// Put the new chunk in the front of the loaded chunk list.
for( i = wLastChunk; i > 0; i-- )
Chunker->LoadedChunks[i] = Chunker->LoadedChunks[i-1];
Chunker->LoadedChunks[0] = *pMemChunk;
*pMemChunk = locMemChunk;
return bRet;
}
CH_ENTRYSC WORD CH_ENTRYMOD CHFlushChunks( wIdSection, wIdLastChunk, hFilter )
WORD wIdSection;
WORD wIdLastChunk;
HFILTER hFilter;
{
PFILTER pFilter;
WORD i,j;
WORD wChunksFreed = 0;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( hFilter );
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
for( i=0; i < Chunker->ChunksInMemory; i++ )
{
if( Chunker->LoadedChunks[i].IDChunk < wIdLastChunk ||
(wIdLastChunk == (WORD)-1) ||
Chunker->LoadedChunks[i].IDSection != Chunker->IDCurSection )
{
// UTGlobalUnlock( Chunker->LoadedChunks[i].hMem );
UTGlobalFree( Chunker->LoadedChunks[i].hMem );
for( j=i+1; j<Chunker->ChunksInMemory; j++ )
{
Chunker->LoadedChunks[j-1] = Chunker->LoadedChunks[j];
Chunker->LoadedChunks[j].hMem = NULLHANDLE;
}
wChunksFreed++;
}
}
Chunker->ChunksInMemory -= wChunksFreed;
UTGlobalUnlock( pFilter->hChunkInfo );
UTGlobalUnlock( hFilter );
RestoreWorld();
return( wChunksFreed );
}
WORD CHLoadBuffer( IDChunk, phChunk )
WORD IDChunk;
HANDLE VWPTR * phChunk;
{
SHORT index;
MEMORYCHUNK locChunk;
SHORT ChunkIndexLimit;
WORD wChunkSize;
WORD ret = CHLOAD_DIRTYCHUNK;
// Try to find the desired chunk within the array of loaded chunks.
// If the chunk isn't found, and we've allocated less than the
// maximum amount of chunk buffers, attempt to allocate a new one.
// If we've already allocated the maximum, or if the allocation fails,
// reuse an existing chunk buffer.
ChunkIndexLimit = min( Chunker->ChunksInMemory+1, MAXCHUNKSINMEMORY );
for( index = 0; index < ChunkIndexLimit; index++ )
{
locChunk = Chunker->LoadedChunks[ index ];
if( locChunk.hMem != NULLHANDLE )
{
if( locChunk.IDChunk == IDChunk &&
locChunk.IDSection == Chunker->IDCurSection )
{
// Found it.
ret = CHLOAD_VALIDCHUNK;
break;
}
}
else
{
// Attempt to allocate a new buffer for the chunk.
// If successful, increment the ChunksInMemory count.
if( !CHUNKTABLE[IDChunk].dwSize )
CHUNKTABLE[IDChunk].dwSize = SO_CHUNK_SIZE;
wChunkSize = (WORD)CHUNKTABLE[IDChunk].dwSize;
Chunker->wChunkBufSize = CHUNKTABLE[IDChunk].dwSize;
if( (Chunker->LoadedChunks[ index ].hMem =
UTGlobalAlloc(Chunker->wChunkBufSize)) != NULLHANDLE )
{
Chunker->ChunksInMemory++;
ret = CHLOAD_FRESHCHUNK;
break;
}
else if( index == 0 ) // nothing left to swap out of cache
CHBailOut(SCCCHERR_OUTOFMEMORY);
}
}
if( ret == CHLOAD_DIRTYCHUNK )
{
if( (Chunker->LookAheadChunk.IDChunk == IDChunk) &&
(Chunker->LookAheadChunk.hMem != NULLHANDLE) &&
(Chunker->LookAheadChunk.IDSection == Chunker->IDCurSection) )
{
*phChunk = Chunker->LookAheadChunk.hMem;
return( CHLOAD_VALIDCHUNK );
}
// Desired chunk is not in memory. Swap a chunk from the cache.
index = Chunker->ChunksInMemory - 1;
if( Chunker->pSection->Flags & CH_CACHEBACKWARDS )
{
// Leave the last chunks in the cache. This is for formats that
// need to run through the whole file every time you need any
// chunk. (Such as most vector formats.)
SHORT i;
WORD locId;
locId = Chunker->LoadedChunks[ index ].IDChunk;
i = index;
while( i >= 0 )
{
if( Chunker->LoadedChunks[i].IDChunk < locId )
{
locId = Chunker->LoadedChunks[i].IDChunk;
index = i;
}
i--;
}
if( (Chunker->LookAheadChunk.IDChunk < Chunker->LoadedChunks[index].IDChunk) &&
(Chunker->LookAheadChunk.hMem != NULLHANDLE) &&
(Chunker->LookAheadChunk.IDSection == Chunker->IDCurSection) )
{
// Swap the lookahead chunk with the found chunk.
locChunk = Chunker->LookAheadChunk;
Chunker->LookAheadChunk = Chunker->LoadedChunks[index];
Chunker->LoadedChunks[index] = locChunk;
}
}
// ...else index is already set to the least recently used chunk.
if( Chunker->LoadedChunks[index].dwSize != CHUNKTABLE[IDChunk].dwSize )
{
UTGlobalFree( Chunker->LoadedChunks[index].hMem );
Chunker->LoadedChunks[index].hMem = UTGlobalAlloc( CHUNKTABLE[IDChunk].dwSize );
while( Chunker->LoadedChunks[index].hMem == NULL )
{
if( Chunker->ChunksInMemory )
Chunker->ChunksInMemory--;
else
CHBailOut(SCCCHERR_OUTOFMEMORY);
while( (WORD)index < Chunker->ChunksInMemory )
{
Chunker->LoadedChunks[ index ] = Chunker->LoadedChunks[ index+1 ];
index++;
}
index = Chunker->ChunksInMemory-1;
UTGlobalFree( Chunker->LoadedChunks[index].hMem );
Chunker->LoadedChunks[index].hMem = UTGlobalAlloc( CHUNKTABLE[IDChunk].dwSize );
}
}
}
Chunker->LoadedChunks[ index ].IDChunk = IDChunk;
Chunker->LoadedChunks[ index ].IDSection = Chunker->IDCurSection;
Chunker->LoadedChunks[ index ].dwSize = CHUNKTABLE[IDChunk].dwSize;
Chunker->wChunkBufSize = CHUNKTABLE[IDChunk].dwSize;
// Move the current chunk to the first position in the array.
locChunk = Chunker->LoadedChunks[ index ];
while( index > 0 )
{
Chunker->LoadedChunks[ index ] = Chunker->LoadedChunks[ index-1 ];
index--;
}
Chunker->LoadedChunks[ 0 ] = locChunk;
*phChunk = locChunk.hMem;
return( ret );
}
WORD IDNextNewChunk()
{
HANDLE hMem;
DWORD dwMemSize;
if( Chunker->pSection->IDLastChunk+1 == Chunker->pSection->wChunkTableSize )
{
UTGlobalUnlock( Chunker->pSection->hChunkTable );
dwMemSize = sizeof(CHUNK) * (Chunker->pSection->wChunkTableSize + CHUNKTABLEUNIT);
#ifdef WINDOWS
if( dwMemSize > 0x0000FFFF ) // Stupid segments
hMem = NULLHANDLE;
else
#endif
hMem = CHGlobalRealloc( Chunker->pSection->hChunkTable,
sizeof(CHUNK) * Chunker->pSection->wChunkTableSize,
dwMemSize );
if( hMem == NULLHANDLE )
CHBailOut(SCCCHERR_OUTOFMEMORY);
else
{
Chunker->pSection->wChunkTableSize += CHUNKTABLEUNIT;
Chunker->pSection->hChunkTable = hMem;
CHUNKTABLE = (PCHUNK) UTGlobalLock( hMem );
}
}
return( ++(Chunker->pSection->IDLastChunk) );
}
WORD CHAddNewSection(hFilter)
HFILTER hFilter;
{
DWORD dwTableSize;
WORD wOldSize;
wOldSize = sizeof(CHSECTIONINFO) * Chunker->NumSections;
Chunker->NumSections++;
dwTableSize = sizeof(CHSECTIONINFO) * Chunker->NumSections;
#ifdef WINDOWS
if( dwTableSize > 0x0000FFFF ) // Segment stuff
return 1;
#endif
if( Chunker->pSectionTable == NULL )
Chunker->hSectionTable = UTLocalAlloc( (WORD)dwTableSize );
else
{
UTLocalUnlock( Chunker->hSectionTable );
Chunker->hSectionTable = CHLocalRealloc( Chunker->hSectionTable, wOldSize, (WORD)dwTableSize );
}
if( Chunker->hSectionTable == NULLHANDLE )
return 1;
Chunker->pSectionTable = (CHSECTIONINFO *)UTLocalLock( Chunker->hSectionTable );
Chunker->pSection = &(Chunker->pSectionTable[Chunker->IDCurSection]);
return 0;
}
VOID CHHandleSectionBoundary()
{
PCHUNK pChunk;
PFILTER pFilter;
WORD wIdPrevSection;
pFilter = (PFILTER) UTGlobalLock( Chunker->hFilter );
wIdPrevSection = Chunker->IDCurSection;
Chunker->IDCurSection = Chunker->NumSections-1;
Chunker->pSection = &(Chunker->pSectionTable[Chunker->IDCurSection]);
Chunker->pSection->szName[0] = '\0';
Chunker->pSection->IDLastChunk = 0;
Chunker->pSection->Flags = CH_NEWSECTION | CH_EMPTYSECTION;
Chunker->pSection->dwEmbedCount = 0;
CHSetupCharMap(Chunker->hFilter);
/*
| 12/4/94 added NP StreamSection so threading can be used to check for
| infinite loops.
|
| Old code
| pFilter->VwRtns.StreamSection( pFilter->hFile, pFilter->hProc );
*/
StreamSectionNP(pFilter);
if( Chunker->pSection->wType == SO_BITMAP )
{
// The exact number of chunks can be determined up front for a bitmap.
Chunker->pSection->hChunkTable = UTGlobalAlloc( Chunker->pSection->wChunkTableSize*sizeof(CHUNK) );
CHSetupBitmapChunkTable();
}
else
{
Chunker->pSection->hChunkTable = UTGlobalAlloc( CHUNKTABLEUNIT*sizeof(CHUNK) );
Chunker->pSection->wChunkTableSize = CHUNKTABLEUNIT;
}
SSSectionSave( &(Chunker->pSection->dwSeekId), Chunker->hFilter );
// Set the seek info for the top of the next section.
pChunk = (PCHUNK) UTGlobalLock( Chunker->pSection->hChunkTable );
pChunk->Flags = 0;
SSMark( Chunker->hFilter );
SSSave( &(pChunk->SeekID), Chunker->hFilter );
UTGlobalUnlock( Chunker->pSection->hChunkTable );
UTGlobalUnlock( Chunker->hFilter );
Chunker->IDCurSection = wIdPrevSection;
Chunker->pSection = &(Chunker->pSectionTable[Chunker->IDCurSection]);
}
WORD CHTopOfChunk( hFilter, hProc, pFilter )
HFILTER hFilter;
HPROC hProc;
PFILTER pFilter;
{
PCHUNK pCurChunk;
SOTAB TempTabstop;
PSOTAB TabArray;
SHORT i;
#ifdef OS2
void (* VW_ENTRYMOD SetSoRtn)(SHORT, VOID (* SO_ENTRYMOD)(), HPROC);
#else
void (VW_ENTRYMOD * SetSoRtn)(SHORT, VOID (SO_ENTRYMOD *)(), HPROC);
#endif
WORD ret = FALSE;
SetSoRtn = pFilter->VwRtns.SetSoRtn;
Chunker->ChunkFinished = FALSE;
Chunker->CurChunkSize = 0;
pCurChunk = &(CHUNKTABLE[ Chunker->IDCurChunk ]);
if( Chunker->pSection->Flags & CH_NEWSECTION )
ret = TRUE;
CHSetupCharMap(hFilter);
if( Chunker->wFlags & CH_LOOKAHEAD )
pFilter->VwRtns.SetSoRtn( SOBEGINTAG, SOBeginTag, pFilter->hProc );
else
{
pFilter->VwRtns.SetSoRtn( SOBEGINTAG, SOBeginSkipTag, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOENDTAG, SOEndSkipTag, pFilter->hProc );
}
switch( Chunker->pSection->wType )
{
case SO_PARAGRAPHS:
// Initialize paragraph stuff.
if( Chunker->wFlags & CH_LOOKAHEAD )
{
if( Chunker->pSection->Flags & CH_NEWSECTION )
{
pCurChunk->Info.Text.dwCountableOffset = 0;
pCurChunk->Info.Text.dwSeekCountableOffset = 0;
}
}
Chunker->Doc.Text.CurParaOffset = 0;
Chunker->Doc.Text.wParaBreakOffset = 0;
Chunker->Doc.Text.MarginOffset = -1;
Chunker->Doc.Text.IndentOffset = -1;
Chunker->Doc.Text.SpacingOffset = -1;
Chunker->Doc.Text.AlignOffset = -1;
Chunker->Doc.Text.wCurTableColumn = 0;
pCurChunk->Flags |= CH_WRAPINVALID;
// Set up minimum amount of tabstops for top of chunk.
if( !(pCurChunk->Flags & CH_CONTINUATION) )
{
Chunker->Doc.Text.NumTabstops = 0;
Chunker->Doc.Text.TabSetSize = TOPOFCHUNK_MINTABSTOPS;
TempTabstop.wType = SO_TABEMPTY;
// DELETE ME: Temp for comparison purposes.
TempTabstop.wChar = 0;
TempTabstop.wLeader = 0;
TempTabstop.dwOffset = 0L;
*CHUNKBUFPTR++ = (BYTE)SO_BEGINTOKEN;
*CHUNKBUFPTR++ = SO_TABSTOPS;
Chunker->Doc.Text.TabstopsOffset = 2*sizeof(BYTE);
*((WORD VWPTR *) CHUNKBUFPTR) = TOPOFCHUNK_MINTABSTOPS;
CHUNKBUFPTR += sizeof(WORD);
TabArray = (PSOTAB)(CHUNKBUFPTR);
for( i = 0; i < TOPOFCHUNK_MINTABSTOPS; i ++ )
{
TabArray[i] = TempTabstop;
CHUNKBUFPTR += sizeof( SOTAB );
}
Chunker->Doc.Text.AttrSize = 2*sizeof(BYTE) + sizeof(WORD) + (sizeof( SOTAB ) * TOPOFCHUNK_MINTABSTOPS);
Chunker->CurChunkSize = Chunker->Doc.Text.AttrSize;
}
else
{
Chunker->Doc.Text.NumTabstops = 0;
Chunker->Doc.Text.TabstopsOffset = -1;
Chunker->Doc.Text.TabSetSize = TOPOFCHUNK_MINTABSTOPS;
Chunker->CurChunkSize = 0;
Chunker->Doc.Text.AttrSize = 0;
}
Chunker->Doc.Text.dwCurTableId = pCurChunk->Info.Text.dwTableId;
Chunker->Doc.Text.bRowFormatted = FALSE;
if( pCurChunk->Flags & CH_STARTSINTABLE )
{
if( pCurChunk->Info.Text.wTableRow == 0 )
{
// First row of table was moved to this chunk, so the
// "begin table" token needs to be put into the chunk.
SOPutSysChar( SO_BEGINTOKEN, 0L, 0L );
SOPutSysChar( SO_TABLE, 0L, 0L );
SOPutDWord( pCurChunk->Info.Text.dwTableId, 0L, 0L );
// pCurChunk->Flags &= ~CH_STARTSINTABLE;
}
Chunker->Doc.Text.wCurTableRow = pCurChunk->Info.Text.wTableRow;
Chunker->Doc.Text.wCurTableColumn = pCurChunk->Info.Text.wTableCol;
Chunker->wFlags |= CH_TABLETEXT;
if( pCurChunk->Flags & CH_TOPROWFORMATTED )
Chunker->Doc.Text.bRowFormatted = TRUE;
}
else
Chunker->wFlags &= ~CH_TABLETEXT;
Chunker->Doc.Text.dwCurGraphicId = pCurChunk->Info.Text.dwFirstGraphic;
CHUpdateParagraphFunctions(CH_ACTIVE,hFilter);
Chunker->dwChunkCountables = pCurChunk->Info.Text.dwSeekCountableOffset;
Chunker->Doc.Text.dwParaCountableOffset = 0;
if( (pCurChunk->Flags & CH_CONTINUATION) &&
(pCurChunk->Info.Text.dwCountableOffset !=
pCurChunk->Info.Text.dwSeekCountableOffset) )
{
// We're looking for a continuation chunk.
// Set up the chunker to ignore tokens that precede the
// beginning of this chunk's text.
CHSetContinuationFunctions( hFilter );
EDDeleteUntil( CHUNKTABLE[ Chunker->IDCurChunk ].Info.Text.dwCountableOffset, hFilter );
}
break;
case SO_CELLS:
// Initialize cell stuff.
SetSoRtn( SOPUTDATACELL, SOPutDataCell, pFilter->hProc );
SetSoRtn( SOPUTTEXTCELL, SOPutTextCell, pFilter->hProc );
SetSoRtn( SOPUTMORETEXT, SOPutMoreText, pFilter->hProc );
CHResetDataChunk();
if( Chunker->wFlags & CH_LOOKAHEAD )
{
if( Chunker->pSection->Flags & CH_NEWSECTION )
if( CHInitCellSection() )
ret = (WORD)-1;
}
Chunker->Doc.Cells.Flags = 0; // CH_SETFIRSTCELL;
Chunker->Doc.Cells.CurRow = pCurChunk->Info.Cells.First.Row;
Chunker->Doc.Cells.CurCol = pCurChunk->Info.Cells.First.Col;
Chunker->Doc.Cells.dwCurCell = pCurChunk->Info.Cells.dwFirstCell;
if( Chunker->pSection->Attr.Cells.dwLayoutFlags & SO_CELLLAYOUTVERTICAL )
Chunker->Doc.Cells.CellGrouping = GROUPED_IN_COLS;
else
Chunker->Doc.Cells.CellGrouping = GROUPED_IN_ROWS;
SetSoRtn( SOSTARTCOLUMNINFO, NULL, hProc );
SetSoRtn( SOPUTCOLUMNINFO, NULL, hProc );
SetSoRtn( SOENDCOLUMNINFO, NULL, hProc );
SetSoRtn( SOSETDATEBASE, NULL, hProc );
SetSoRtn( SOCELLLAYOUTINFO, NULL, hProc );
SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, hProc );
break;
case SO_ARCHIVE:
Chunker->Doc.Archive.IndexPtr = (WORD VWPTR *)(Chunker->CurChunkBuf + (SO_CHUNK_SIZE - sizeof(WORD)));
*Chunker->Doc.Archive.IndexPtr = (SHORT)Chunker->CurChunkSize;
if( Chunker->wFlags & CH_LOOKAHEAD )
pCurChunk->Info.Archive.wFirstRec = pCurChunk->Info.Archive.wLastRec = Chunker->Doc.Archive.wCurRecord;
SetSoRtn( SOPUTARCHIVEFIELD, SOPutArchiveField, hProc );
SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, hProc );
break;
case SO_VECTOR:
if( pCurChunk->Flags & CH_CONTINUATION &&
(Chunker->Doc.Vector.wCurItem != pCurChunk->Info.Vector.wFirstItem ||
Chunker->Doc.Vector.wLastSectionSeen != Chunker->IDCurSection) )
{
SetSoRtn( SOVECTOROBJECT, SOPutVectorContinuationItem, hProc );
SetSoRtn( SOVECTORATTR, SOPutVectorContinuationItem, hProc );
SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutVectorContinuationBreak, hProc );
Chunker->Doc.Vector.wIgnoredChunk = Chunker->IDCurChunk;
while( pCurChunk->Flags & CH_CONTINUATION )
{
pCurChunk--;
Chunker->Doc.Vector.wIgnoredChunk--;
}
SSRecall( pCurChunk->SeekID, hFilter );
}
else
{
SetSoRtn( SOVECTOROBJECT, SOVectorObject, hProc );
SetSoRtn( SOVECTORATTR, SOVectorAttr, hProc );
SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, hProc );
}
Chunker->Doc.Vector.wCurItem = pCurChunk->Info.Vector.wFirstItem;
break;
case SO_FIELDS:
// Set up the Index pointer to point at the last WORD in the chunk.
Chunker->Doc.Fields.IndexPtr = (WORD VWPTR *)(Chunker->CurChunkBuf + (SO_CHUNK_SIZE - sizeof(WORD)));
SetSoRtn( SOPUTFIELD, SOPutField, pFilter->hProc );
SetSoRtn( SOPUTVARFIELD, SOPutVarField, pFilter->hProc );
SetSoRtn( SOPUTMOREVARFIELD, SOPutMoreVarField, pFilter->hProc );
SetSoRtn( SOSTARTFIELDINFO, NULL, hProc );
SetSoRtn( SOPUTFIELDINFO, NULL, hProc );
SetSoRtn( SOENDFIELDINFO, NULL, hProc );
SetSoRtn( SOSETDATEBASE, NULL, hProc );
SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, hProc );
// Initialize field stuff.
if( Chunker->wFlags & CH_LOOKAHEAD )
{
if( Chunker->pSection->Flags & CH_NEWSECTION )
{
pCurChunk->Info.Fields.dwFirstRec = pCurChunk->Info.Fields.dwLastRec = 0;
CHInitFieldSection();
}
}
Chunker->pSection->Attr.Fields.pCol = (PSOFIELD) UTGlobalLock( Chunker->pSection->Attr.Fields.hCol );
Chunker->Doc.Fields.dwCurRec = pCurChunk->Info.Fields.dwFirstRec;
Chunker->Doc.Fields.wCurField = 0;
break;
case SO_BITMAP: // Spam, spam, spam, spam, eggs, and spam
if( Chunker->Doc.Bitmap.wDirection == UPSIDEDOWN )
CHUNKBUFPTR = &(Chunker->CurChunkBuf[ (pCurChunk->Info.Bitmap.wYClip - 1) * Chunker->pSection->Attr.Bitmap.wScanLineBufSize ]);
Chunker->Doc.Bitmap.wCurScanLine = pCurChunk->Info.Bitmap.wYOffset;
if( Chunker->pSection->Attr.Bitmap.bmpHeader.wBitsPerPixel != 24 )
{
i = 8 / Chunker->pSection->Attr.Bitmap.bmpHeader.wBitsPerPixel;
// Calculate the minimal number of bytes for a scan line, so we don't
// read off the edge of the scan line buffer supplied by a filter.
Chunker->pSection->Attr.Bitmap.wScanLineSize = pCurChunk->Info.Bitmap.wXClip / i;
if( pCurChunk->Info.Bitmap.wXClip % i )
Chunker->pSection->Attr.Bitmap.wScanLineSize++;
}
else
Chunker->pSection->Attr.Bitmap.wScanLineSize = pCurChunk->Info.Bitmap.wXClip * 3;
Chunker->Doc.Bitmap.wChunkSize = (WORD)pCurChunk->dwSize;
if( pCurChunk->Flags & CH_CONTINUATION &&
!(Chunker->wFlags & CH_LOOKAHEAD))
{
// Continuation chunk.
Chunker->Doc.Bitmap.wCurScanLine = pCurChunk->Info.Bitmap.wSeekYOffset;
SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutContinuationBitmapBreak, hProc );
SetSoRtn( SOPUTSCANLINEDATA, NULL, hProc );
}
else
{
SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, hProc );
if( Chunker->pSection->Attr.Bitmap.bmpHeader.wImageFlags & SO_RGBCOLOR )
SetSoRtn( SOPUTSCANLINEDATA, SOPutReversedRGBData, hProc );
else
SetSoRtn( SOPUTSCANLINEDATA, SOPutScanLineData, hProc );
}
SetSoRtn( SOPUTBITMAPHEADER, NULL, hProc );
SetSoRtn( SOSTARTPALETTE , NULL, hProc );
SetSoRtn( SOPUTPALETTEENTRY, NULL, hProc );
SetSoRtn( SOENDPALETTE , NULL, hProc );
break;
}
return(ret);
}
CH_ENTRYSC HANDLE CH_ENTRYMOD CHGetChunk( wSection, IDChunk, hFilter )
WORD wSection;
WORD IDChunk;
HFILTER hFilter;
{
PFILTER pFilter;
HANDLE hChunk;
WORD SavedFlags;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( hFilter );
// Set up CHUNKTABLE and Chunker according to values in hFilter.
CHLockChunkerVars( wSection, hFilter );
if( CHLoadBuffer(IDChunk,&hChunk) != CHLOAD_VALIDCHUNK )
{
Chunker->IDCurChunk = IDChunk;
hChunk = Chunker->LoadedChunks[0].hMem;
Chunker->CurChunkBuf = CHUNKBUFPTR = (BYTE VWPTR *) UTGlobalLock( Chunker->LoadedChunks[ 0 ].hMem );
if( pFilter->pWakeFunc != NULL )
pFilter->pWakeFunc(hFilter);
// Some flags used in reading ahead need to be preserved.
SavedFlags = Chunker->wFlags;
Chunker->wFlags = 0;
// Restore seek data.
if( !(CHUNKTABLE[ IDChunk ].Flags & CH_DONTSEEKCHUNK) )
SSRecall( CHUNKTABLE[ IDChunk ].SeekID, hFilter );
if( -1 == CHTopOfChunk( hFilter, pFilter->hProc, pFilter ) )
CHBailOut((WORD)-1);
else
{
// Get that filter in gear.
do
{
Chunker->wFlags &= ~CH_CALLFILTER;
/*
| 12/4/94 added NP StreamRead so threading can be used to check for
| infinite loops.
|
| Old code
| pFilter->VwRtns.StreamRead( pFilter->hFile, pFilter->hProc );
*/
#if _DEBUG
pFilter->VwRtns.StreamRead( pFilter->hFile, pFilter->hProc );
#else
StreamReadNP(pFilter);
#endif
} while( Chunker->wFlags & CH_CALLFILTER );
#ifdef CHDEBUG
DebugCall ( IDChunk, hChunk );
#endif
UTGlobalUnlock( hChunk );
}
Chunker->wFlags = SavedFlags;
if( pFilter->pSleepFunc != NULL )
pFilter->pSleepFunc(hFilter);
}
else if(hChunk == (HANDLE) CHLOAD_MEMERROR ) // Error: couldn't allocate any chunks.
CHBailOut(SCCCHERR_OUTOFMEMORY);
CHUnlockChunkerVars(hFilter);
UTGlobalUnlock( hFilter );
RestoreWorld();
return( hChunk );
}
/*
| This routine allows the caller to take over all responsibility
| for the memory allocated for a chunk.
*/
CH_ENTRYSC HANDLE CH_ENTRYMOD CHTakeChunk( wSection, IDChunk, hFilter )
WORD wSection;
WORD IDChunk;
HFILTER hFilter;
{
HANDLE hRet;
PFILTER pFilter;
WORD i;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( hFilter );
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
hRet = CHGetChunk( wSection, IDChunk, hFilter );
// The chunk is now in the first element of the loaded chunk array.
// We'll forget we ever had it, and let the caller worry about
// the ungrateful little bastard.
if( hRet == Chunker->LookAheadChunk.hMem )
Chunker->LookAheadChunk.hMem = NULL;
else
{
Chunker->LoadedChunks[0].hMem = NULL;
Chunker->ChunksInMemory--;
for( i=0; i < Chunker->ChunksInMemory; i++ )
{
Chunker->LoadedChunks[i] = Chunker->LoadedChunks[i+1];
Chunker->LoadedChunks[i+1].hMem = NULLHANDLE;
}
}
UTGlobalUnlock( pFilter->hChunkInfo );
UTGlobalUnlock( hFilter );
RestoreWorld();
return( hRet );
}
CH_ENTRYSC WORD CH_ENTRYMOD CHReadAhead( hFilter, wSection, bNewSection )
HFILTER hFilter;
WORD VWPTR * wSection;
BOOL VWPTR * bNewSection;
{
PFILTER pFilter;
WORD Ret;
WORD RetainChunk;
SHORT i;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( hFilter );
// Retrieve the ID of the last section.
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
i = Chunker->NumSections -1;
UTGlobalUnlock( pFilter->hChunkInfo );
// Set up CHUNKTABLE and Chunker according to values in hFilter.
CHLockChunkerVars( i, hFilter);
if( Chunker->EofFlag )
{
/**** What the hell, let's keep it around.
if( Chunker->LookAheadChunk.hMem != NULL )
{
UTGlobalFree( Chunker->LookAheadChunk.hMem );
Chunker->LookAheadChunk.hMem = NULL;
}
***/
*wSection = Chunker->IDCurSection;
*bNewSection = FALSE;
CHUnlockChunkerVars( hFilter );
UTGlobalUnlock( hFilter );
RestoreWorld();
return 0;
}
Chunker->wFlags |= CH_LOOKAHEAD;
Ret = TRUE;
if( pFilter->pWakeFunc != NULL )
pFilter->pWakeFunc(hFilter);
RetainChunk = TRUE;
// Load the next chunk.
Chunker->IDCurChunk = Chunker->LookAheadChunk.IDChunk = Chunker->pSection->IDLastChunk;
Chunker->LookAheadChunk.IDSection = Chunker->IDCurSection;
if( Chunker->LookAheadChunk.hMem != NULLHANDLE )
UTGlobalFree( Chunker->LookAheadChunk.hMem );
if( Chunker->pSection->wType != SO_BITMAP )
Chunker->LookAheadChunk.dwSize = SO_CHUNK_SIZE;
else
{
Chunker->Doc.Bitmap.wChunkSize = (WORD)CHUNKTABLE[Chunker->IDCurChunk].dwSize;
Chunker->LookAheadChunk.dwSize = (DWORD)Chunker->Doc.Bitmap.wChunkSize;
}
Chunker->LookAheadChunk.hMem = UTGlobalAlloc( Chunker->LookAheadChunk.dwSize );
if( Chunker->LookAheadChunk.hMem == NULLHANDLE )
{
// Attempt to borrow a previously allocated chunk from the
// LoadedChunks table.
if( Chunker->ChunksInMemory )
{
Chunker->LookAheadChunk.hMem = Chunker->LoadedChunks[ Chunker->ChunksInMemory-1 ].hMem;
Chunker->ChunksInMemory--;
}
else
CHBailOut(SCCCHERR_OUTOFMEMORY); // allocation failed.
}
Chunker->wChunkBufSize = Chunker->LookAheadChunk.dwSize;
CHUNKTABLE[Chunker->IDCurChunk].dwSize = Chunker->LookAheadChunk.dwSize;
Chunker->CurChunkBuf = CHUNKBUFPTR = (LPSTR) UTGlobalLock( Chunker->LookAheadChunk.hMem );
// Restore seek data.
if( !(CHUNKTABLE[ Chunker->IDCurChunk ].Flags & CH_DONTSEEKCHUNK) )
SSRecall( CHUNKTABLE[ Chunker->IDCurChunk ].SeekID, hFilter );
i = CHTopOfChunk( hFilter, pFilter->hProc, pFilter );
if( i == -1 )
{
// error in CHTopOfChunk.
CHBailOut(SCCCHERR_OUTOFMEMORY);
}
else
*bNewSection = i;
*wSection = Chunker->IDCurSection;
do
{
Chunker->wFlags &= ~CH_CALLFILTER;
/*
| 12/4/94 added NP StreamRead so threading can be used to check for
| infinite loops.
|
| Old code
| pFilter->VwRtns.StreamRead( pFilter->hFile, pFilter->hProc );
*/
StreamReadNP(pFilter);
} while( Chunker->wFlags & CH_CALLFILTER );
if( Chunker->pSection->Flags & CH_NOCHUNKBUILT )
{
// No valid chunk was found.
Chunker->pSection->Flags &= ~CH_NOCHUNKBUILT;
*wSection = Chunker->IDCurSection;
if( Chunker->EofFlag )
{
*bNewSection = FALSE;
UTGlobalUnlock( Chunker->LookAheadChunk.hMem );
UTGlobalFree( Chunker->LookAheadChunk.hMem );
Chunker->LookAheadChunk.hMem = NULLHANDLE;
Ret = 0;
}
}
else if( RetainChunk )
{
UTGlobalUnlock( Chunker->LookAheadChunk.hMem );
#ifdef CHDEBUG
DebugCall( Chunker->LookAheadChunk.IDChunk, Chunker->LookAheadChunk.hMem );
#endif
// If there's room in the loaded chunk table, store this chunk there
// for later access.
if( Chunker->ChunksInMemory < MAXCHUNKSINMEMORY )
{
Chunker->LoadedChunks[ Chunker->ChunksInMemory ] = Chunker->LookAheadChunk;
Chunker->LookAheadChunk.hMem = NULLHANDLE;
Chunker->ChunksInMemory++;
}
else if( Chunker->pSection->Flags & CH_CACHEBACKWARDS )
CHStoreChunkInMemory( &(Chunker->LookAheadChunk) );
}
Chunker->pSection->Flags &= ~CH_NEWSECTION;
// Are we at a boundary between sections?
// If so, let's handle our boundary conditions.
if( Chunker->IDCurSection != Chunker->NumSections-1 )
CHHandleSectionBoundary();
Chunker->wFlags &= ~CH_LOOKAHEAD;
if( pFilter->pSleepFunc != NULL )
pFilter->pSleepFunc(hFilter);
CHUnlockChunkerVars( hFilter );
UTGlobalUnlock( hFilter );
RestoreWorld();
return( Ret );
}
CH_ENTRYSC WORD CH_ENTRYMOD CHInit( hFilter )
HFILTER hFilter;
{
PFILTER pFilter;
SHORT i;
SetupWorld();
// Allocate the chunk table.
pFilter = (PFILTER) UTGlobalLock( hFilter );
pFilter->hChunkInfo = (HANDLE) UTGlobalAlloc( sizeof(CHUNKMEISTER) );
if( pFilter->hChunkInfo == NULLHANDLE )
{
UTGlobalUnlock( hFilter );
RestoreWorld();
return 0;
}
if( pFilter->pWakeFunc != NULL )
pFilter->pWakeFunc(hFilter);
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
Chunker->hFilter = hFilter;
Chunker->wSeekDataSize = SSInit( hFilter ); // Initialize filter seek stuff.
for( i=0; i < MAXCHUNKSINMEMORY; i++ )
Chunker->LoadedChunks[i].hMem = NULLHANDLE;
Chunker->LoadedChunks[0].IDChunk = 0;
Chunker->LoadedChunks[0].IDSection = 0;
Chunker->IDCurChunk = 0;
Chunker->CurChunkSize = 0;
Chunker->ChunksInMemory = 0;
Chunker->wFlags = 0;
Chunker->EofFlag = 0;
Chunker->SubdocLevel = 0;
Chunker->NumSections = 0;
Chunker->NumTextSections = 0;
Chunker->NumCellSections = 0;
Chunker->NumFieldSections = 0;
Chunker->NumGraphicSections = 0;
if( CHAddNewSection(hFilter) )
{
CHDeInit(hFilter);
UTGlobalUnlock( hFilter );
RestoreWorld();
return 0;
}
else
{
// Set up the dwUser variables for all the chunker routines.
pFilter->VwRtns.SetUser( (DWORD) pFilter->hChunkInfo, (DWORD) hFilter, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOPUTSECTIONTYPE, SOPutSectionType, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOBAILOUT, SOBailOut, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOGETINFO, SOGetInfo, pFilter->hProc );
Chunker->IDCurSection = 0;
CHHandleSectionBoundary();
// Unlock the chunker...
UTGlobalUnlock( pFilter->hChunkInfo );
// ... then re-lock it, with all the other chunker variables.
CHLockChunkerVars( 0, hFilter );
}
// Initialize first chunk (chunk 0):
// Allocate memory for the first chunk.
if( Chunker->pSection->wType != SO_BITMAP )
Chunker->LookAheadChunk.dwSize = SO_CHUNK_SIZE;
else
Chunker->LookAheadChunk.dwSize = Chunker->Doc.Bitmap.wChunkSize;
Chunker->LookAheadChunk.hMem = UTGlobalAlloc( Chunker->LookAheadChunk.dwSize );
Chunker->wChunkBufSize = Chunker->LookAheadChunk.dwSize;
if( Chunker->LookAheadChunk.hMem == NULLHANDLE )
{
CHDeInit( hFilter );
UTGlobalUnlock( hFilter );
RestoreWorld();
return 0;
}
Chunker->wFilterCharSet = pFilter->VwInfo.wFilterCharSet;
if( pFilter->pSleepFunc != NULL )
pFilter->pSleepFunc(hFilter);
CHUnlockChunkerVars( hFilter );
UTGlobalUnlock( hFilter );
RestoreWorld();
return 1;
}
VOID CHSetupCharMap(hFilter)
HFILTER hFilter;
{
PFILTER pFilter;
WORD i;
pFilter = (PFILTER)UTGlobalLock(hFilter);
switch( pFilter->VwInfo.wFilterCharSet )
{
case SO_MAC:
#ifdef WINDOWS
for( i=0; i<32; i++ )
CharMap[i] = 1;
for( ; i < 127; i++ )
CharMap[i] = (BYTE) i;
CharMap[127] = 1;
CHMemCopy( &(CharMap[128]), Mac2Win, 128 );
#endif
#ifdef OS2
for( i=0; i<32; i++ )
CharMap[i] = 1;
for( ; i < 127; i++ )
CharMap[i] = (BYTE) i;
CharMap[127] = 1;
CHMemCopy( &(CharMap[128]), Mac2Win, 128 );
#endif
#ifdef MAC
for( i=0; i < 256; i++ )
CharMap[i] = (BYTE) i;
#endif
break;
case SO_DBCS:
case SO_WINDOWS:
#ifdef WINDOWS
for( i=0; i < 256; i++ )
CharMap[i] = (BYTE) i;
#endif
#ifdef OS2
for( i=0; i < 256; i++ )
CharMap[i] = (BYTE) i;
#endif
#ifdef MAC
CHMemCopy( CharMap, Win2Mac, 256 );
#endif
break;
case SO_DCA:
#ifdef WINDOWS
CHMemCopy( CharMap, DCA2Win, 512 );
#endif
#ifdef OS2
CHMemCopy( CharMap, DCA2Win, 512 );
#endif
#ifdef MAC
CHMemCopy( CharMap, DCA2Mac, 512 );
#endif
break;
default:
case SO_PC:
#ifdef WINDOWS
for( i=0; i < 256; i++ )
CharMap[i] = (BYTE) i;
OemToAnsiBuff( CharMap, CharMap, 256 );
#endif
#ifdef OS2
// OEMTOANSI BUFF ?? SDN 8.31.93
for( i=0; i < 256; i++ )
CharMap[i] = (BYTE) i;
// UTOemToAnsiBuff( CharMap, CharMap, 256 );
#endif
#ifdef MAC
CHMemCopy( CharMap, PC2Mac, 256 );
#endif
break;
}
for( i=0;i < 256; i++ )
{
if( CharMap[i] == 0 )
CharMap[i] = 1;
else if( CharMap[i] == SO_BEGINTOKEN )
CharMap[i] = 0;
}
UTGlobalUnlock(hFilter);
}
CH_ENTRYSC VOID CH_ENTRYMOD CHDeInit( hFilter )
HFILTER hFilter;
{
PFILTER pFilter;
WORD i;
SetupWorld();
if( hFilter != NULLHANDLE )
{
pFilter = (PFILTER) UTGlobalLock( hFilter );
}
else
{
RestoreWorld();
return;
}
if( pFilter->hChunkInfo != NULLHANDLE )
{
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
SSDeinit( hFilter ); // De-initialize filter seek stuff.
for( i = 0; i < Chunker->ChunksInMemory; i++ )
UTGlobalFree( Chunker->LoadedChunks[ i ].hMem );
if( Chunker->LookAheadChunk.hMem != 0 )
UTGlobalFree(Chunker->LookAheadChunk.hMem);
if( Chunker->hSectionTable != NULLHANDLE )
{
for( i = 0; i < Chunker->NumSections; i++ )
{
if( Chunker->pSectionTable[i].hChunkTable != NULLHANDLE )
UTGlobalFree( Chunker->pSectionTable[i].hChunkTable );
if( Chunker->pSectionTable[i].hHeaderInfo != NULLHANDLE )
UTGlobalFree( Chunker->pSectionTable[i].hHeaderInfo );
if( Chunker->pSectionTable[i].hFontTable != NULLHANDLE )
UTGlobalFree( Chunker->pSection->hFontTable );
switch( Chunker->pSectionTable[i].wType )
{
case SO_PARAGRAPHS:
if( Chunker->pSectionTable[i].Attr.Para.hRowInfo != NULLHANDLE )
{
UTGlobalFree( Chunker->pSectionTable[i].Attr.Para.hRowInfo );
UTGlobalFree( Chunker->pSectionTable[i].Attr.Para.hTables );
}
if( Chunker->pSectionTable[i].hEmbedded != NULLHANDLE )
UTGlobalFree(Chunker->pSectionTable[i].hEmbedded);
break;
case SO_CELLS:
if( Chunker->pSectionTable[i].Attr.Cells.hCol != NULLHANDLE )
UTGlobalFree( Chunker->pSectionTable[i].Attr.Cells.hCol );
break;
case SO_FIELDS:
if( Chunker->pSectionTable[i].Attr.Fields.hCol != NULLHANDLE )
UTGlobalFree( Chunker->pSectionTable[i].Attr.Fields.hCol );
/**** Intended for use with database query and sort.
if( Chunker->pSectionTable[i].Attr.Fields.hColFlags != NULLHANDLE )
UTLocalFree( Chunker->pSectionTable[i].Attr.Fields.hColFlags );
*****/
break;
case SO_BITMAP:
if( Chunker->pSectionTable[i].Attr.Bitmap.hPalInfo != NULLHANDLE )
UTGlobalFree( Chunker->pSectionTable[i].Attr.Bitmap.hPalInfo );
break;
case SO_VECTOR:
if( Chunker->pSectionTable[i].Attr.Vector.hPalette != NULLHANDLE )
UTGlobalFree( Chunker->pSectionTable[i].Attr.Vector.hPalette );
break;
}
}
}
if( Chunker->hSectionTable != NULLHANDLE )
{
UTLocalUnlock( Chunker->hSectionTable );
UTLocalFree( Chunker->hSectionTable );
}
UTGlobalUnlock( pFilter->hChunkInfo );
UTGlobalFree( pFilter->hChunkInfo );
}
UTGlobalUnlock( hFilter );
RestoreWorld();
}
VOID CHLockChunkerVars( wSection, hFilter)
WORD wSection;
HFILTER hFilter;
{
PFILTER pFilter;
pFilter = (PFILTER) UTGlobalLock( hFilter );
// Set up CHUNKTABLE and Chunker according to values in hFilter.
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
Chunker->pSection = &(Chunker->pSectionTable[wSection]);
if( wSection != Chunker->IDCurSection )
{
Chunker->IDCurSection = wSection;
SSSectionRecall(Chunker->pSection->dwSeekId, hFilter);
#ifdef NEVER
switch( Chunker->pSection->wType )
{
case SO_BITMAP:
// Reset section variables used in building/displaying bitmaps.
if( Chunker->pSection->Flags & CH_SECTIONFINISHED )
CHInitBitmapSection(hFilter);
break;
}
#endif
}
CHUNKTABLE = (PCHUNK) UTGlobalLock( Chunker->pSection->hChunkTable );
UTGlobalUnlock( hFilter );
}
VOID CHUnlockChunkerVars( hFilter )
HFILTER hFilter;
{
PFILTER pFilter;
pFilter = (PFILTER) UTGlobalLock( hFilter );
UTGlobalUnlock( Chunker->pSection->hChunkTable );
UTGlobalUnlock( pFilter->hChunkInfo );
UTGlobalUnlock( hFilter );
}
CH_ENTRYSC WORD CH_ENTRYMOD CHTotalChunks( wSection, hFilter )
WORD wSection;
HFILTER hFilter;
{
PFILTER pFilter;
WORD ret;
SetupWorld();
pFilter = (PFILTER) UTGlobalLock( hFilter );
Chunker = (LPCHUNKMEISTER) UTGlobalLock( pFilter->hChunkInfo );
ret = Chunker->pSectionTable[wSection].IDLastChunk+1;
UTGlobalUnlock( pFilter->hChunkInfo );
UTGlobalUnlock( hFilter );
RestoreWorld();
return( ret );
}
WORD SO_ENTRYMOD SODummyBreak( wType, dwInfo, dwUser1, dwUser2 )
WORD wType;
DWORD dwInfo;
DWORD dwUser1;
DWORD dwUser2;
{
return SO_CONTINUE;
}
CH_ENTRYSC VOID CH_ENTRYMOD CHDoFilterSpecial( dw1, dw2, dw3, dw4, dw5, hFilter )
DWORD dw1;
DWORD dw2;
DWORD dw3;
DWORD dw4;
DWORD dw5;
HFILTER hFilter;
{
PFILTER pFilter;
SetupWorld();
pFilter = (PFILTER)UTGlobalLock( hFilter );
if( pFilter->pWakeFunc != NULL )
pFilter->pWakeFunc(hFilter);
pFilter->VwRtns.DoSpecial( pFilter->hFile, dw1, dw2, dw3, dw4, dw5, pFilter->hProc );
if( pFilter->pSleepFunc != NULL )
pFilter->pSleepFunc(hFilter);
UTGlobalUnlock( hFilter );
RestoreWorld();
}
VOID CHSetDocPropRtns(hFilter,bEntering)
HFILTER hFilter;
BOOL bEntering;
{
PFILTER pFilter;
HPROC hProc;
pFilter = (PFILTER) UTGlobalLock( hFilter );
hProc = pFilter->hProc;
if( bEntering )
{
if( Chunker->pSection->wType == SO_PARAGRAPHS )
CHUpdateParagraphFunctions( CH_INACTIVE, hFilter );
pFilter->VwRtns.SetSoRtn( SOPUTCHAR, SOPutDPChar, hProc );
pFilter->VwRtns.SetSoRtn( SOPUTCHARX, SOPutDPCharX, hProc );
pFilter->VwRtns.SetSoRtn( SOPUTSPECIALCHARX, SOPutDPSpecialCharX, hProc );
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutDPBreak, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOBEGINTAG, NULL, hProc );
pFilter->VwRtns.SetSoRtn( SOENDTAG, SOEndTag, hProc );
}
else
{
if( Chunker->SubdocLevel || Chunker->ChunkFinished
|| Chunker->pSection->wType != SO_PARAGRAPHS )
{
pFilter->VwRtns.SetSoRtn( SOPUTCHAR, NULL, hProc );
pFilter->VwRtns.SetSoRtn( SOPUTCHARX, NULL, hProc );
pFilter->VwRtns.SetSoRtn( SOPUTSPECIALCHARX, NULL, hProc );
}
else
CHUpdateParagraphFunctions( CH_ACTIVE, hFilter );
if( Chunker->SubdocLevel )
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOSubdocPutBreak, pFilter->hProc );
else
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, pFilter->hProc );
pFilter->VwRtns.SetSoRtn( SOBEGINTAG, SOBeginTag, hProc );
pFilter->VwRtns.SetSoRtn( SOENDTAG, NULL, hProc );
}
UTGlobalUnlock( hFilter );
}
#define DOCPROP_ALLOCSIZE 512
VOID CHGrowDPBuf()
{
HANDLE hNewMem;
UTGlobalUnlock(Chunker->pSection->hHeaderInfo);
hNewMem = CHGlobalRealloc( Chunker->pSection->hHeaderInfo,
Chunker->wDPBufSize,
Chunker->wDPBufSize + DOCPROP_ALLOCSIZE );
if( hNewMem )
{
Chunker->wDPBufSize += DOCPROP_ALLOCSIZE;
Chunker->pSection->hHeaderInfo = hNewMem;
}
else
CHBailOut(SCCCHERR_OUTOFMEMORY); // Error!
Chunker->pDocProp = (LPSTR)UTGlobalLock(Chunker->pSection->hHeaderInfo);
Chunker->pDocProp += Chunker->pSection->wTotalHeaderSize;
}
VOID SO_ENTRYMOD SOBeginSkipTag( dwType, dwTagId, pInfo, dwUser1, dwUser2 )
DWORD dwType;
DWORD dwTagId;
VOID FAR * pInfo;
DWORD dwUser1;
DWORD dwUser2;
{
PFILTER pFilter;
SetupWorld();
// We only read these on the first pass, since we keep them around
// independent of the chunks.
CHUpdateParagraphFunctions( CH_INACTIVE, GETHFILTER(dwUser2) );
pFilter = (PFILTER)UTGlobalLock(GETHFILTER(dwUser2));
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SODummyBreak, pFilter->hProc );
UTGlobalUnlock(GETHFILTER(dwUser2));
RestoreWorld();
}
VOID SO_ENTRYMOD SOEndSkipTag( dwType, dwTagId, dwUser1, dwUser2 )
DWORD dwType;
DWORD dwTagId;
DWORD dwUser1;
DWORD dwUser2;
{
PFILTER pFilter;
SetupWorld();
pFilter = (PFILTER)UTGlobalLock(GETHFILTER(dwUser2));
if( Chunker->pSection->wType == SO_PARAGRAPHS )
{
if( Chunker->wFlags & CH_SKIPTEXT )
{
// We're in a continuation chunk.
CHSetDeletionFunctions( GETHFILTER(dwUser2) );
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutDeletedBreak, pFilter->hProc );
}
else
{
CHUpdateParagraphFunctions( CH_ACTIVE, GETHFILTER(dwUser2) );
if( Chunker->SubdocLevel )
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOSubdocPutBreak, pFilter->hProc );
else
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, pFilter->hProc );
}
}
else if( Chunker->SubdocLevel )
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOSubdocPutBreak, pFilter->hProc );
else
pFilter->VwRtns.SetSoRtn( SOPUTBREAK, (SOFUNCPTR)SOPutBreak, pFilter->hProc );
UTGlobalUnlock(GETHFILTER(dwUser2));
RestoreWorld();
}
VOID SO_ENTRYMOD SOBeginTag( dwType, dwTagId, pInfo, dwUser1, dwUser2 )
DWORD dwType;
DWORD dwTagId;
VOID FAR * pInfo;
DWORD dwUser1;
DWORD dwUser2;
{
PSODOCPROP pPropInfo;
SetupWorld();
pPropInfo = (PSODOCPROP) pInfo;
if( Chunker->pSection->hHeaderInfo == NULL )
{
Chunker->pSection->hHeaderInfo = UTGlobalAlloc( DOCPROP_ALLOCSIZE );
if( Chunker->pSection->hHeaderInfo == NULL )
CHBailOut(SCCCHERR_OUTOFMEMORY); // Error!
Chunker->pSection->wTotalHeaderSize = 0;
Chunker->wDPBufSize = DOCPROP_ALLOCSIZE;
}
Chunker->pDocProp = (LPSTR)UTGlobalLock(Chunker->pSection->hHeaderInfo)
+ Chunker->pSection->wTotalHeaderSize;
if( Chunker->pSection->wTotalHeaderSize + sizeof(DWORD) > Chunker->wDPBufSize )
CHGrowDPBuf();
*(DWORD FAR *)Chunker->pDocProp = pPropInfo->dwPropertyId;
Chunker->pDocProp += sizeof(DWORD);
Chunker->pSection->wTotalHeaderSize += sizeof(DWORD);
CHSetDocPropRtns(GETHFILTER(dwUser2),TRUE);
RestoreWorld();
}
VOID SO_ENTRYMOD SOEndTag( dwType, dwTagId, dwUser1, dwUser2 )
DWORD dwType;
DWORD dwTagId;
DWORD dwUser1;
DWORD dwUser2;
{
SetupWorld();
Chunker->pSection->wNumHeaderItems++;
if( Chunker->pSection->wTotalHeaderSize+SO_BREAKSIZE >= Chunker->wDPBufSize )
CHGrowDPBuf();
*(Chunker->pDocProp++) = (BYTE)SO_BEGINTOKEN;
*(Chunker->pDocProp++) = SO_BREAK;
*(Chunker->pDocProp++) = SO_PROPERTYBREAK;
Chunker->pSection->wTotalHeaderSize += SO_BREAKSIZE;
UTGlobalUnlock(Chunker->pSection->hHeaderInfo);
CHSetDocPropRtns(GETHFILTER(dwUser2),FALSE);
RestoreWorld();
}
VOID SO_ENTRYMOD SOPutDPChar( wCh, dwUser1, dwUser2 )
WORD wCh;
DWORD dwUser1;
DWORD dwUser2;
{
WORD wChMap;
SetupWorld();
if( wCh == 0 )
return;
#ifdef DBCS
if ( wCh & 0x8000 ) /* This is a Double Byte Character */
{
#ifdef WINDOWS
if ( IsDBCSLeadByte((BYTE)(wCh>>8)) == FALSE )
wCh = 1; /* Not supported on this system so map to unknown */
else
{
if( Chunker->pSection->wTotalHeaderSize+2 >= Chunker->wDPBufSize )
CHGrowDPBuf();
*(Chunker->pDocProp++) = (BYTE) (wCh>>8);
*(Chunker->pDocProp++) = (BYTE) wCh;
Chunker->pSection->wTotalHeaderSize += 2;
RestoreWorld();
return;
}
#else
wCh = 1; /* Will map to the unknown character */
#endif
}
#endif
wChMap = (BYTE) CharMap[wCh];
if( wChMap > 1 )
{
if( Chunker->pSection->wTotalHeaderSize >= Chunker->wDPBufSize )
CHGrowDPBuf();
*(Chunker->pDocProp++) = (BYTE) wChMap;
Chunker->pSection->wTotalHeaderSize++;
}
else if( wChMap == 1 ) // Unknown characters.
SOPutDPSpecialCharX( SO_CHUNKNOWN, SO_COUNTBIT, dwUser1, dwUser2 );
else
SOPutDPCharX( wCh, SO_COUNTBIT, dwUser1, dwUser2 );
RestoreWorld();
}
// Make sure this is kept up-to-date.
#define SO_DPSPECIALCHARSIZE 4
VOID SO_ENTRYMOD SOPutDPCharX( wCh, wType, dwUser1, dwUser2 )
WORD wCh;
WORD wType;
DWORD dwUser1;
DWORD dwUser2;
{
SetupWorld();
wCh = (BYTE) CharMap[wCh];
if( Chunker->pSection->wTotalHeaderSize+SO_DPSPECIALCHARSIZE > Chunker->wDPBufSize )
CHGrowDPBuf();
*(Chunker->pDocProp++) = (BYTE) SO_BEGINTOKEN;
if( wCh == 1 )
{
*(Chunker->pDocProp++) = SO_SPECIALCHAR;
*(Chunker->pDocProp++) = (BYTE) wType;
*(Chunker->pDocProp++) = (BYTE) SO_CHUNKNOWN;
}
else
{
if( !wCh ) // This is the convoluted way we map a character
wCh = (BYTE) SO_BEGINTOKEN; // with the same value as SO_BEGINTOKEN.
*(Chunker->pDocProp++) = SO_CHARX;
*(Chunker->pDocProp++) = (BYTE) wType;
*(Chunker->pDocProp++) = (BYTE) wCh;
}
Chunker->pSection->wTotalHeaderSize += SO_DPSPECIALCHARSIZE;
RestoreWorld();
}
VOID SO_ENTRYMOD SOPutDPSpecialCharX( wCh, wType, dwUser1, dwUser2 )
WORD wCh;
WORD wType;
DWORD dwUser1;
DWORD dwUser2;
{
SetupWorld();
if( Chunker->pSection->wTotalHeaderSize+SO_DPSPECIALCHARSIZE > Chunker->wDPBufSize )
CHGrowDPBuf();
*(Chunker->pDocProp++) = (BYTE)SO_BEGINTOKEN;
*(Chunker->pDocProp++) = (BYTE)SO_SPECIALCHAR;
*(Chunker->pDocProp++) = (BYTE) wType;
*(Chunker->pDocProp++) = (BYTE) wCh;
Chunker->pSection->wTotalHeaderSize += SO_DPSPECIALCHARSIZE;
RestoreWorld();
}
WORD SO_ENTRYMOD SOPutDPBreak( wType, dwInfo, dwUser1, dwUser2 )
WORD wType;
DWORD dwInfo;
DWORD dwUser1;
DWORD dwUser2;
{
SetupWorld();
if( wType == SO_PARABREAK )
{
if( Chunker->pSection->wTotalHeaderSize+SO_BREAKSIZE > Chunker->wDPBufSize )
CHGrowDPBuf();
*(Chunker->pDocProp++) = (BYTE)SO_BEGINTOKEN;
*(Chunker->pDocProp++) = SO_BREAK;
*(Chunker->pDocProp++) = SO_PARABREAK;
}
Chunker->pSection->wTotalHeaderSize += SO_BREAKSIZE;
RestoreWorld();
return SO_CONTINUE;
}