387 lines
11 KiB
C++
387 lines
11 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1991 - 1994.
|
|
//
|
|
// File: TSource.cxx
|
|
//
|
|
// Contents: TEXT_SOURCE implementation
|
|
//
|
|
// Classes: CTextSource
|
|
//
|
|
// History: 14-Apr-94 KyleP Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <tsource.hxx>
|
|
#include <mapper.hxx>
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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
|
|
}
|
|
|
|
|