/* | CHUNKER.C | | So chunky, you'll be tempted to use a fork. */ #define XCHUNK #include #include #include #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;xpSection->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; ipSection->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; ipSection->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; jChunksInMemory; 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; }