//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1991 - 1994. // // File: TSource.cxx // // Contents: TEXT_SOURCE implementation // // Classes: CTextSource // // History: 14-Apr-94 KyleP Created // //---------------------------------------------------------------------------- #include #pragma hdrstop #include #include //+------------------------------------------------------------------------- // // Member: CTextSource::CTextSource, public // // Synopsis: Constructor // // Arguments: [pFilter] -- IFilter (source of data) // [Stat] -- Chunk statistics // // History: 01-Aug-93 AmyA Created // 14-Apr-94 KyleP Sync with wordbreaker spec // //-------------------------------------------------------------------------- CTextSource::CTextSource( IFilter * pFilter, STAT_CHUNK & Stat, CSourceMapper* pMapper ) : _pMapper (pMapper), _pFilter(pFilter), _Stat( Stat ), _sc( S_OK ) { #if CIDBG == 1 CFullPropSpec & ps = *((CFullPropSpec *)&Stat.attribute); ciDebugOut(( DEB_WORDS, "TEXT SOURCE: Initial chunk of " "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\\", ps.GetPropSet().Data1, ps.GetPropSet().Data2, ps.GetPropSet().Data3, ps.GetPropSet().Data4[0], ps.GetPropSet().Data4[1], ps.GetPropSet().Data4[2], ps.GetPropSet().Data4[3], ps.GetPropSet().Data4[4], ps.GetPropSet().Data4[5], ps.GetPropSet().Data4[6], ps.GetPropSet().Data4[7] )); if ( ps.IsPropertyName() ) ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, "%ws\n", ps.GetPropertyName() )); else ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, "0x%x\n", ps.GetPropertyPropid() )); #endif // CIDBG == 1 iEnd = 0; iCur = 0; awcBuffer = _awcFilterBuffer; pfnFillTextBuffer = CTextSource::FillBuf; if (_pMapper) { if (_Stat.idChunk == _Stat.idChunkSource) { _pMapper->NewChunk ( _Stat.idChunk, 0 ); } else { _pMapper->NewDerivedChunk ( _Stat.idChunkSource, _Stat.cwcStartSource, _Stat.cwcLenSource); } } FillBuf( this ); } //+------------------------------------------------------------------------- // // Member: CTextSource::FillBuf, public // // Synopsis: Fills buffer with IFilter::GetText and IFilter::GetChunk // // History: 01-Aug-93 AmyA Created // 20-Apr-94 KyleP Sync with spec // // Notes: NOTE! In several places, this function casts const away // from awcBuffer. This is an acceptable cast from const to // non-const. The buffer is const to the client but non-const // to the server. // //-------------------------------------------------------------------------- SCODE CTextSource::FillBuf( TEXT_SOURCE * pTextSource ) { CTextSource * pthis = (CTextSource *)pTextSource; // // Never continue past an error condition other than FILTER_E_NO_MORE_TEXT // if ( FAILED( pthis->_sc ) && pthis->_sc != FILTER_E_NO_MORE_TEXT ) return( pthis->_sc ); // Don't allow wordbreaker bugs with iEnd/iCur to overwrite memory. Win4Assert ( pthis->iEnd >= pthis->iCur ); if ( pthis->iCur > pthis->iEnd ) { pthis->_sc = WBREAK_E_END_OF_TEXT; return WBREAK_E_END_OF_TEXT; } // // Move any existing text to beginning of buffer. // ULONG ccLeftOver = pthis->iEnd - pthis->iCur; if ( ccLeftOver > 0 ) { RtlMoveMemory( (WCHAR *)pthis->awcBuffer, &pthis->awcBuffer[pthis->iCur], ccLeftOver * sizeof (WCHAR) ); } if (pthis->_pMapper) { // this much has been processed from the current chunk pthis->_pMapper->Advance ( pthis->iCur ); } pthis->iCur = 0; pthis->iEnd = ccLeftOver; ULONG ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver; const BUFFER_SLOP = 10; // Buffer is attempted to be filled until BUFFER_SLOP remains // // Get some more text. If *previous* call to GetText returned // FILTER_S_LAST_TEXT, or FILTER_E_NO_MORE_TEXT then don't even // bother trying. // if ( pthis->_sc == FILTER_S_LAST_TEXT || pthis->_sc == FILTER_E_NO_MORE_TEXT ) pthis->_sc = FILTER_E_NO_MORE_TEXT; else { pthis->_sc = pthis->_pFilter->GetText( &ccRead, (WCHAR *) &pthis->awcBuffer[ccLeftOver] ); if ( SUCCEEDED( pthis->_sc ) ) { pthis->iEnd += ccRead; ccLeftOver += ccRead; ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver; while ( pthis->_sc == S_OK && ccRead > BUFFER_SLOP ) { // // Attempt to fill in as much of buffer as possible before returning // pthis->_sc = pthis->_pFilter->GetText( &ccRead, (WCHAR *) &pthis->awcBuffer[ccLeftOver] ); if ( SUCCEEDED( pthis->_sc ) ) { pthis->iEnd += ccRead; ccLeftOver += ccRead; ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver; } } #if CIDBG == 1 DebugPrintBuffer( pthis ); #endif // // Either return FILTER_S_LAST_TEXT or return S_OK because we have succeeded in // adding text to the buffer // if ( pthis->_sc == FILTER_S_LAST_TEXT ) return FILTER_S_LAST_TEXT; else return S_OK; } if ( pthis->_sc != FILTER_E_NO_MORE_TEXT ) { // // Weird failure, hence return, else goto next chunk // return pthis->_sc; } } // // Go to next chunk, if necessary. // while ( pthis->_sc == FILTER_E_NO_MORE_TEXT ) { pthis->_sc = pthis->_pFilter->GetChunk( &pthis->_Stat ); if ( pthis->_sc == FILTER_E_END_OF_CHUNKS ) return WBREAK_E_END_OF_TEXT; if ( pthis->_sc == FILTER_E_PARTIALLY_FILTERED ) return WBREAK_E_END_OF_TEXT; if ( FAILED( pthis->_sc ) ) return( pthis->_sc ); if ( pthis->_Stat.flags & CHUNK_VALUE ) { pthis->_sc = FILTER_E_NO_TEXT; return WBREAK_E_END_OF_TEXT; } if ( pthis->_Stat.breakType != CHUNK_NO_BREAK ) { pthis->_sc = WBREAK_E_END_OF_TEXT; return WBREAK_E_END_OF_TEXT; } ciDebugOut(( DEB_WORDS, "TEXT SOURCE: NoBreak chunk\n" )); if (pthis->_pMapper) { ULONG idChunk = pthis->_Stat.idChunk; if (idChunk == pthis->_Stat.idChunkSource) { pthis->_pMapper->NewChunk ( idChunk, ccLeftOver ); } else { pthis->_sc = WBREAK_E_END_OF_TEXT; return WBREAK_E_END_OF_TEXT; } } ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver; pthis->_sc = pthis->_pFilter->GetText( &ccRead, (WCHAR *) &pthis->awcBuffer[ccLeftOver] ); if ( SUCCEEDED( pthis->_sc ) ) { pthis->iEnd += ccRead; ccLeftOver += ccRead; ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver; while ( pthis->_sc == S_OK && ccRead > BUFFER_SLOP ) { // // Attempt to fill in as much of buffer as possible before returning // pthis->_sc = pthis->_pFilter->GetText( &ccRead, (WCHAR *) &pthis->awcBuffer[ccLeftOver] ); if ( SUCCEEDED( pthis->_sc ) ) { pthis->iEnd += ccRead; ccLeftOver += ccRead; ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver; } } #if CIDBG == 1 DebugPrintBuffer( pthis ); #endif // // Either return FILTER_S_LAST_TEXT or return S_OK because we have succeeded in // adding text to the buffer // if ( pthis->_sc == FILTER_S_LAST_TEXT ) return FILTER_S_LAST_TEXT; else return S_OK; } } if ( FAILED( pthis->_sc ) ) return( pthis->_sc ); if ( ccRead == 0 ) return WBREAK_E_END_OF_TEXT; Win4Assert( pthis->iCur == 0 ); Win4Assert( pthis->iEnd == ccLeftOver ); ciDebugOut(( DEB_WORDS, "TEXT SOURCE: Fill buffer with %d characters. %d left over\n", pthis->iEnd, ccLeftOver )); return S_OK; } //+------------------------------------------------------------------------- // // Member: CTextSource::DebugPrintBuffer // // Synopsis: Debug print the text buffer // // Arguments: [pThis] -- Pointer to text source // // History: 08-Apr-97 SitaramR Created // //-------------------------------------------------------------------------- void CTextSource::DebugPrintBuffer( CTextSource *pthis ) { #if CIDBG == 1 if ( ciInfoLevel & DEB_WORDS ) { ciDebugOut(( DEB_WORDS, "CTextSource::FillBuf -- iCur = %u, iEnd = %u\n", pthis->iCur, pthis->iEnd )); BOOL fOk = TRUE; for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ ) { if ( pthis->awcBuffer[i] > 0xFF ) { fOk = FALSE; break; } } if ( fOk ) { unsigned j = 0; WCHAR awcTemp[71]; for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ ) { awcTemp[j] = pthis->awcBuffer[i]; j++; if ( j == sizeof(awcTemp)/sizeof(awcTemp[0]) - 1 ) { awcTemp[j] = 0; ciDebugOut(( DEB_WORDS, "%ws\n", awcTemp )); j = 0; } } awcTemp[j] = 0; ciDebugOut(( DEB_WORDS, "%ws\n", awcTemp )); } else { unsigned j = 0; for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ ) { if ( 0 == j ) ciDebugOut(( DEB_WORDS, "%04X", pthis->awcBuffer[i] )); else if ( 14 == j ) { ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, " %04X\n", pthis->awcBuffer[i] )); } else ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, " %04X", pthis->awcBuffer[i] )); j++; if ( j > 14 ) j = 0; } ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, "\n" )); } } #endif }