|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 2000.
//
// File: LANG.CXX
//
// Contents: Language Support
//
// Classes: CLanguage
// CLangList
//
// History: 02-May-91 BartoszM Created
//
// Notes: The filtering pipeline is hidden in the Data Repository
// object which serves as a sink for the filter.
// The sink for the Data Repository is the Key Repository.
// The language dependent part of the pipeline
// is obtained from the Language List object and is called
// Key Maker. It consists of:
//
// Word Breaker
// Stemmer (optional)
// Normalizer
// Noise List
//
// Each object serves as a sink for its predecessor,
// Key Repository is the final sink.
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <tfilt.hxx>
#include <tsource.hxx>
#include <defbreak.hxx>
#include <lang.hxx>
#include <keymak.hxx>
#include <norm.hxx>
#include <noise.hxx>
#include <ciregkey.hxx>
#define DEB_LLIST DEB_USER10
//+-------------------------------------------------------------------------
//
// Method: CLangList::CLangList, public
//
// Synopsis: Create all languages.
//
// Arguments: [pICiCLangRes] -- Client-provided language creator
// [ulMaxIdle] -- Max time (in seconds) before idle language
// object is elegible for deletion.
//
// History: 02-May-91 BartoszM Created
// 14-Jul-94 SitaramR Moved constructor here from lang.hxx
//
//--------------------------------------------------------------------------
CLangList::CLangList( ICiCLangRes * pICiCLangRes, ULONG ulMaxIdle ) : _xICiCLangRes(pICiCLangRes), _ulMaxIdle( ulMaxIdle * 1000 ) { _xICiCLangRes->AddRef(); }
//+-------------------------------------------------------------------------
//
// Method: CLangList::~CLangList, public
//
// Synopsis: Delete all languages.
//
// History: 27-Apr-1994 KyleP Created
//
//--------------------------------------------------------------------------
CLangList::~CLangList() { Shutdown(); }
//+-------------------------------------------------------------------------
//
// Method: CLangList::Shutdown, public
//
// Synopsis: Delete all languages.
//
// History: 2-July-1996 dlee Moved from the destructor
//
//--------------------------------------------------------------------------
void CLangList::Shutdown() { for ( CLanguage *pLang = _langsAvailable.Pop(); 0 != pLang; pLang = _langsAvailable.Pop() ) { delete pLang; } } //Shutdown
//+-------------------------------------------------------------------------
//
// Method: CLangList::Supports, public
//
// Synopsis: Determines if language object is suitable for lcid/pid
//
// Arguments: [pLang] -- Language object
// [pid] -- PROPID to-be-used by [pLang]
// [lcid] -- Locale to-be-used by [pLang]
//
// Returns: TRUE is [pLang] can be used to break/stem/etc. the
// locale/property specified by [lcid]/[pid]
//
// History: 05-Jan-1998 KyleP Created
//
//--------------------------------------------------------------------------
BOOL CLangList::Supports( CLanguage const * pLang, PROPID pid, LCID lcid ) { ciDebugOut(( DEB_LLIST, "Supports, lcid %#x, pid %#x\n", lcid, pid ));
LANGID langId = LANGIDFROMLCID(lcid);
//
// Easy case: Different language.
//
if ( !pLang->IsLocale( langId ) ) { ciDebugOut(( DEB_LLIST, " supports: lcid doesn't match\n" )); return FALSE; }
//
// Easy case: Everything matches.
//
if ( pLang->IsPid( pid ) ) return TRUE;
CLangPidStateInfo stateInfo;
if ( pLang->IsPid( CI_DEFAULT_PID ) ) { //
// Hard case: Mismatch, but possible default match to previously
// seen pid.
//
if ( _pidHash.LokLookupOrAddLang( langId, stateInfo ) && _pidHash.LokIsUseDefaultPid( pid, stateInfo.GetLangIndex() ) ) { ciDebugOut(( DEB_LLIST, "CLangList::Supports -- Pid 0x%x can use current [default] language object\n", pid )); return TRUE; }
//
// Hardest case: Mismatch, but possible default match to brand
// new pid.
//
CLanguage * pNewLang = FindLangAndActivate( langId, pid );
if ( 0 != pNewLang ) { //
// Obviously not a default match if there is already a specific
// language created. Note that extra work searching the list
// in FindLangAndActivate is not wasted, as the ReturnLang below
// will place the activated language on the top of the list for
// easy access when the call is soon made to fetch the new
// language object supporting this pid/locale.
//
ReturnLang( pNewLang ); ciDebugOut(( DEB_LLIST, " supports found it, but returning FALSE\n" )); return FALSE; }
pNewLang = CreateLang( langId, pid, stateInfo, pLang );
if ( 0 == pNewLang ) { ciDebugOut(( DEB_LLIST, "CLangList::Supports -- New pid 0x%x can use current [default] language object\n", pid )); Win4Assert( pLang->IsPid( CI_DEFAULT_PID ) ); // May be a bogus assert...
return TRUE; } else { ciDebugOut(( DEB_LLIST, "CLangList::Supports -- New pid 0x%x cannot use current language object\n", pid )); ReturnLang( pNewLang ); // This one should get used in just a few calls...
return FALSE; } }
return FALSE; } //Supports
//+---------------------------------------------------------------------------
//
// Member: CLangList::BorrowLang
//
// Synopsis: Borrows a language object
//
// Arguments: [locale] -- Locale
// [pid] -- property id
// [resources] -- Which resources to load.
//
// History: 19-Sep-91 BartoszM Created original GetLang.
// 15-Aug-94 SitaramR Renamed GetLang to BorrowLang and
// added code to look up registry.
// 2-14-97 mohamedn use ICiCLangRes, use lang specific
// default pid cache.
//
//----------------------------------------------------------------------------
CLanguage* CLangList::BorrowLang( LCID locale, PROPID pid, ULONG resources ) { LANGID langId = LANGIDFROMLCID(locale);
ciDebugOut(( DEB_LLIST, "BorrowLang lang %#x, pid %#x, resources %#x\n", locale, pid, resources ));
CLanguage * pLang = FindLangAndActivate( langId, pid ); if ( 0 != pLang ) return pLang;
//==========================================================
{ //
// We have to create a new language object. Serialize so that
// multiple threads are not creating simultaneously.
//
CLock lockCreat( _mtxCreate );
//
// lookup the given pid if a default pid hash table exist
// for the given LangID.
// If pid found in default pid cache, use CI_DEFAULT_PID
//
CLangPidStateInfo stateInfo;
if ( _pidHash.LokLookupOrAddLang( langId, stateInfo ) ) { if ( _pidHash.LokIsUseDefaultPid( pid, stateInfo.GetLangIndex() ) ) pid = CI_DEFAULT_PID; }
// Check to see if one became available while we were waiting.
pLang = FindLangAndActivate( langId, pid );
if ( 0 != pLang ) return pLang;
// Create a new CLanguage object
pLang = CreateLang( langId, pid, stateInfo, 0, resources ); } //==========================================================
Win4Assert( pLang );
return pLang; } //BorrowLang
//+---------------------------------------------------------------------------
//
// Member: CLangList::CreateLang
//
// Synopsis: Creates & Returns a language object
//
// Arguments: [langId] -- Locale
// [pid] -- property id
// [stateInfo] -- stateInfo to set internal state info.
// [pDup] -- Don't create a language just like this.
// Instead, return this one.
// [resources] -- Which to load.
//
// Returns: [pLang] -- a valid pointer to CLanguage object.
//
// History: 19-Sep-91 BartoszM Created original GetLang.
// 15-Aug-94 SitaramR Renamed GetLang to BorrowLang and
// added code to look up registry.
// 2-27-97 mohamedn use ICiCLangRes,
// use lang specific default pid cache.
//
//----------------------------------------------------------------------------
CLanguage * CLangList::CreateLang( LANGID langId, PROPID pid, CLangPidStateInfo & stateInfo, CLanguage const * pDup, ULONG resources ) { ciDebugOut(( DEB_LLIST, "CreateLang lang %#x, pid %#x, resources %#x\n", langId, pid, resources ));
ULONG pidFlags = 0;
if ( LoadWB( resources ) ) pidFlags |= USE_WB_DEFAULT_PID; if ( LoadST( resources ) ) pidFlags |= USE_STEMMER_DEFAULT_PID; if ( LoadNO( resources ) ) pidFlags |= USE_NWL_DEFAULT_PID;
//
// Get interfaces to the wordbreaker, stemmer and noise word list
// via ICiCLangRes
//
XInterface<IWordBreaker> xIWBreak; XInterface<IStemmer> xIStemmer; XInterface<IStream> xIStrmNoiseFile;
if ( pid == CI_DEFAULT_PID ) { // create default word breaker, stemmer & nwl
if ( LoadWB( resources ) ) xIWBreak.Set( GetWordBreaker ( langId, pid, stateInfo, TRUE ) );
if ( LoadST( resources ) ) xIStemmer.Set( GetStemmer ( langId, pid, stateInfo ) );
if ( LoadNO( resources ) ) xIStrmNoiseFile.Set( GetNoiseWordList ( langId, pid, stateInfo ) ); } else { // try to create wb, stemmer, and nwl using this pid (non-default)
if ( LoadWB( resources ) ) xIWBreak.Set( GetWordBreaker( langId, pid, stateInfo, FALSE ) );
if ( LoadST( resources ) ) xIStemmer.Set( GetStemmer( langId, pid, stateInfo ) );
if ( LoadNO( resources ) ) xIStrmNoiseFile.Set( GetNoiseWordList( langId, pid, stateInfo ) );
ciDebugOut(( DEB_LLIST, " GetPidFlags: %#x\n", stateInfo.GetPidFlags() ));
if ( stateInfo.GetPidFlags() == pidFlags ) { // Client requested to use DEFAULT_PID:
// add pid to the default pid cache for this langid,
// scan availble lang objects for a match, and return it if
// found else create default wb, stemmer, and nwl.
Win4Assert ( xIWBreak.IsNull() ); Win4Assert ( xIStemmer.IsNull() ); Win4Assert ( xIStrmNoiseFile.IsNull() );
_pidHash.LokAddDefaultPid( pid, stateInfo.GetLangIndex() );
pid = CI_DEFAULT_PID;
if ( 0 != pDup && pDup->IsLocale( langId ) && pDup->IsPid( pid ) ) return 0;
CLanguage * pLang = FindLangAndActivate( langId, pid );
if ( 0 != pLang ) return pLang;
if ( LoadWB( resources ) ) xIWBreak.Set( GetWordBreaker( langId, pid, stateInfo, TRUE ) );
if ( LoadST( resources ) ) xIStemmer.Set( GetStemmer( langId, pid, stateInfo ) );
if ( LoadNO( resources ) ) xIStrmNoiseFile.Set( GetNoiseWordList( langId, pid, stateInfo ) ); } else { // Client didn't request default pid for all, create default wb, stemmer or nwl
// only if client requested using default pid for it.
if ( stateInfo.IsPidFlagSet( USE_WB_DEFAULT_PID ) ) { if ( LoadWB( resources ) ) xIWBreak.Set( GetWordBreaker( langId, CI_DEFAULT_PID, stateInfo, TRUE ) ); } else Win4Assert ( !xIWBreak.IsNull() );
if ( stateInfo.IsPidFlagSet( USE_STEMMER_DEFAULT_PID ) ) { if ( LoadST( resources ) ) xIStemmer.Set( GetStemmer( langId, CI_DEFAULT_PID, stateInfo ) ); }
if ( stateInfo.IsPidFlagSet( USE_NWL_DEFAULT_PID ) ) { if ( LoadNO( resources ) ) xIStrmNoiseFile.Set( GetNoiseWordList ( langId, CI_DEFAULT_PID, stateInfo ) ); } } }
// create a language object given the wb, stemmer & nwl.
CLanguage * pLang = new CLanguage( langId, pid, xIWBreak, xIStemmer, xIStrmNoiseFile );
// Queue can't fail, so no smart pointer for pLang is needed
//------------------------------------------------------
{ CLock lock( _mtxList );
_langsInUse.Queue( pLang ); } //------------------------------------------------------
return pLang; } //CreateLang
//+---------------------------------------------------------------------------
//
// Member: CLangList::GetWordBreaker, private
//
// Synopsis: gets a word breaker interface given a langid and a pid
//
// Arguments: [langid] -- langid
// [pid] -- property id
// [stateInfo] -- stateInfo to set internal state info.
// [fCreateDefault]-- flag to create default word breaker if TRUE
//
// Returns: IWordBreaker interface upon success, throws upon failure.
//
// History: 2-27-97 MohamedN Created (from borrowlang)
//
//----------------------------------------------------------------------------
IWordBreaker * CLangList::GetWordBreaker( LANGID langid, PROPID pid, CLangPidStateInfo & stateInfo, BOOL fCreateDefault ) { IWordBreaker * pIWordBreaker = 0;
ciDebugOut(( DEB_LLIST, "!!! Actually creating a wordbreaker\n" ));
SCODE sc = _xICiCLangRes->GetWordBreaker( langid, pid, &pIWordBreaker ); if ( SUCCEEDED(sc) ) { Win4Assert( 0 != pIWordBreaker ); } else { switch (sc) { case CI_E_NOT_FOUND: if ( fCreateDefault ) { ciDebugOut(( DEB_ERROR,"Using default word breaker for locale 0x%x\n", langid ));
pIWordBreaker = new CDefWordBreaker(); }
// force fall thru
case CI_E_USE_DEFAULT_PID: stateInfo.SetPidFlags( USE_WB_DEFAULT_PID ); break;
default: ciDebugOut(( DEB_ERROR, "GetWordBreaker Failed(locale: %x,pid: %x): sc: %x\n", langid, pid, sc ));
THROW( CException( sc ) ); } // switch
} // else
return pIWordBreaker; } //GetWordBreaker
//+---------------------------------------------------------------------------
//
// Member: CLangList::GetStemmer, private
//
// Synopsis: gets a stemmer interface given a langid and a pid
//
// Arguments: [langid] -- langid
// [pid] -- property id
// [stateInfo] -- stateInfo to set internal state info.
//
// Returns: IStemmer interface upon success, null or throws upon failure.
//
// History: 2-27-97 MohamedN Created (from borrowlang)
//
//----------------------------------------------------------------------------
IStemmer * CLangList::GetStemmer( LANGID langid, PROPID pid, CLangPidStateInfo & stateInfo ) { SCODE sc = S_OK; IStemmer * pIStemmer = 0;
sc = _xICiCLangRes->GetStemmer( langid, pid, &pIStemmer ); if ( FAILED(sc) ) { switch (sc) {
case CI_E_NOT_FOUND:
ciDebugOut(( DEB_ITRACE,"no stemmer found for locale 0x%x\n", langid ));
break;
case CI_E_USE_DEFAULT_PID:
stateInfo.SetPidFlags( USE_STEMMER_DEFAULT_PID );
break;
default: ciDebugOut(( DEB_ERROR, "GetStemmer Failed(locale: %x,pid: %x): sc: %x\n", langid,pid, sc ));
THROW( CException(sc) ); } // switch
} // else
return pIStemmer; } // GetStemmer
//+---------------------------------------------------------------------------
//
// Member: CLangList::GetNoiseWordList, private
//
// Synopsis: gets an IStream pointer to the noise word list, given a langid & locale.
//
// Arguments: [langid] -- langid
// [pid] -- property id
// [stateInfo] -- stateInfo to set internal state info.
//
// Returns: IStream interface upon success, null or throws upon failure.
//
// History: 2-27-97 MohamedN Created (from borrowlang)
//
//----------------------------------------------------------------------------
IStream * CLangList::GetNoiseWordList( LANGID langid, PROPID pid, CLangPidStateInfo & stateInfo ) { SCODE sc = S_OK; IStream * pIStream = 0;
sc = _xICiCLangRes->GetNoiseWordList( langid, pid, &pIStream ); if ( FAILED(sc) ) { switch (sc) {
case CI_E_NOT_FOUND:
ciDebugOut(( DEB_ITRACE,"no NoiseWordList found for locale 0x%x\n", langid ));
break;
case CI_E_USE_DEFAULT_PID:
stateInfo.SetPidFlags( USE_NWL_DEFAULT_PID );
break;
default: ciDebugOut(( DEB_ERROR, "GetNoiseWordList Failed(locale: %x,pid: %x): sc: %x\n", langid, pid, sc ));
THROW( CException(sc) ); } // switch
} // else
return pIStream; } //GetNoiseWordList
//+---------------------------------------------------------------------------
//
// Member: CLangList::FindLangAndActivate, private
//
// Synopsis: If a language with the given locale exits, then return the
// language after making it active
//
// Arguments: [locale] -- Locale
// [pid] -- property id
//
// Notes:
//
// History: 14-Sep-94 SitaramR Created
//
//----------------------------------------------------------------------------
CLanguage *CLangList::FindLangAndActivate( LCID locale, PROPID pid ) { ciDebugOut(( DEB_LLIST, "FindLangAndActivate lcid %#x, pid %#x\n", locale, pid ));
ULONG dwTick = GetTickCount();
CLock lock( _mtxList );
CLanguage *pLang = 0;
CLangIter iter( _langsAvailable );
while ( !_langsAvailable.AtEnd(iter) ) { ciDebugOut(( DEB_LLIST, " looking for match, lcid %#x, iter->IsPid %d\n", iter->Locale(), iter->IsPid(pid) ));
if ( iter->IsLocale(locale) && iter->IsPid(pid) ) { pLang = iter.GetLang();
_langsAvailable.Advance(iter);
// move from Available list to InUse list
pLang->Unlink(); _langsInUse.Queue( pLang );
//
// Check one beyond, just to make some progress removing extra copies.
//
if ( !_langsAvailable.AtEnd(iter) && (dwTick - iter->LastUsed()) > _ulMaxIdle ) { CLanguage *pLangTemp = iter.GetLang(); _langsAvailable.Advance(iter); pLangTemp->Unlink(); delete pLangTemp; }
break; }
//
// Is it idle? Ignore overflow. It just means we delete too early
// once every few days.
//
if ( (dwTick - iter->LastUsed()) > _ulMaxIdle ) { ciDebugOut(( DEB_LLIST, "deleting idle language object\n" ));
pLang = iter.GetLang(); _langsAvailable.Advance(iter); pLang->Unlink(); delete pLang; pLang = 0; } else _langsAvailable.Advance(iter); }
ciDebugOut(( DEB_LLIST, " FindLangAndActivate returning %p\n", pLang ));
return pLang; } //FindLangAndActivate
//+---------------------------------------------------------------------------
//
// Member: CLangList::ReturnLang, public
//
// Synopsis: Returns a Language
//
// Arguments: [pLang] -- language to be returned
//
// History: 15-Aug-94 SitaramR Created.
//
//----------------------------------------------------------------------------
void CLangList::ReturnLang( CLanguage *pLang ) { ULONG dwTick = GetTickCount();
CLock lock( _mtxList );
Win4Assert( pLang != 0 );
if ( pLang->IsZombie() ) delete pLang; else { // Move from InUse list to Available list. Put it at the front of
// the list so we don't cycle through the cached languages.
pLang->Unlink(); pLang->SetLastUsed( dwTick ); _langsAvailable.Push( pLang ); } } //ReturnLang
//+---------------------------------------------------------------------------
//
// Member: CLangList::InvalidateLangResources, public
//
// Synopsis: Delete all language objects so that new language objects
// can be demand loaded from registry.
//
// History: 15-Aug-94 SitaramR Created.
//
//----------------------------------------------------------------------------
void CLangList::InvalidateLangResources() { CLock lock( _mtxList );
ciDebugOut(( DEB_LLIST, "InvalidateLangResources\n" ));
for ( CLanguage *pLang = _langsAvailable.Pop(); 0 != pLang; pLang = _langsAvailable.Pop() ) { delete pLang; }
for ( pLang = _langsInUse.Pop(); pLang; pLang = _langsInUse.Pop() ) { pLang->Zombify(); // because language is still in use
} } //InvalidateLangResources
//+---------------------------------------------------------------------------
//
// Member: CDefaultPidHash::LokLookupOrAddLang
//
// Synopsis: Sets internal index to the position of langId
// if langId is found, else creates a langId and
// a corresponding default pid hash table.
//
// Arguments: [langid] -- langid
// [stateInfo] -- to set internal langId specific index value.
//
// Returns: TRUE if lang is found
// FALSE if lang is not found
//
// History: 2-27-97 MohamedN Created
//
//----------------------------------------------------------------------------
BOOL CDefaultPidHash::LokLookupOrAddLang( LANGID langId, CLangPidStateInfo & stateInfo ) {
BOOL fLangIdFound = FALSE; unsigned i;
//
// find whether langId is in _aLangId Table
//
for ( i = 0; i < _langIdCount ; i++ ) { if ( _aLangId[i] == langId ) { fLangIdFound = TRUE;
break; } }
//
// if _aLangId is not found in _aLangID table,
// add it, and create a corresponding hash table for it.
//
if ( !fLangIdFound ) { BOOL fAddedLangId = FALSE;
TRY { _aLangId.Add( langId, i );
fAddedLangId = TRUE;
XPtr<CPidHash> xPidHash( new CPidHash( INIT_PID_HASH_TABLE_SIZE ) );
_aHashPidTables.Add( xPidHash.GetPointer(), i );
xPidHash.Acquire();
_langIdCount++; } CATCH( CException, e ) { if ( fAddedLangId ) _aLangId.Remove( i );
RETHROW(); } END_CATCH }
//
// store position of langId in our state object (found or created).
//
stateInfo.SetLangIndex(i);
return fLangIdFound; } //LokLookupOrAddLang
//+---------------------------------------------------------------------------
//
// Member: CDefaultPidHash::LokIsUseDefaultPid
//
// Synopsis: Determines if the passed-in pid belongs to the
// default pid group.
//
// Arguments: [pid] -- property id
// [index] -- position of langid cache table
//
// Returns: TRUE if pid is a member of the default pid group
// FALSE if pid is not a member of the default pid group
//
// History: 2-27-97 MohamedN Created
//
//----------------------------------------------------------------------------
BOOL CDefaultPidHash::LokIsUseDefaultPid( PROPID pid, unsigned index ) { CWidHashEntry entry(pid);
if ( _aHashPidTables[index] ) return _aHashPidTables[index]->LookUpWorkId( entry );
Win4Assert( !"invalid _aHashPidTables[index]" ); return FALSE; }
//+---------------------------------------------------------------------------
//
// Member: CDefaultPidHash::LokAddDefaultPid
//
// Synopsis: Inserts pid into the default pid hash table for a given langId
//
// Arguments: [pid] -- property id
// [index] -- position of langid cache table
//
// Returns: none
//
// History: 2-27-97 MohamedN Created
//----------------------------------------------------------------------------
void CDefaultPidHash::LokAddDefaultPid( PROPID pid, unsigned index ) { CWidHashEntry entry(pid);
Win4Assert( _aHashPidTables[index] );
_aHashPidTables[index]->AddEntry(entry); }
//+---------------------------------------------------------------------------
//
// Member: CLanguage::CLanguage
//
// Synopsis: Finds language information
//
// History: 16-Jul-91 BartoszM Created.
// 15-Aug-94 SitaramR Changed constructor to take
// wordbreaker and noisefile.
//
//----------------------------------------------------------------------------
#define NOISE_SIZE 257
CLanguage::CLanguage( LCID locale, PROPID pid, XInterface<IWordBreaker> & xWBreak, XInterface<IStemmer> & xStemmer, XInterface<IStream> & xIStrmNoiseFile ) : _locale( locale ), _pid( pid ), _xWBreak( xWBreak.Acquire() ), _xStemmer( xStemmer.Acquire() ), _xIStrmNoiseFile( xIStrmNoiseFile.Acquire() ), _zombie( FALSE ) { ciDebugOut(( DEB_LLIST, "CLanguage, locale %#x, pid %#x\n", locale, pid ));
//
// Set up for filtering noise word list. This will always use the
// default filter. We don't go through CFilterDriver, because that
// performs too much extra work: Ole binding, property filtering, etc.
//
if ( !_xIStrmNoiseFile.IsNull() ) { XInterface<CTextIFilter> xTextIFilter( new CTextIFilter ); SCODE sc = xTextIFilter->Load( _xIStrmNoiseFile.GetPointer() ); if ( FAILED(sc) ) { ciDebugOut(( DEB_ERROR, "Filter of pIStrmNoiseFile(%x) returned 0x%x\n", _xIStrmNoiseFile.GetPointer(), sc )); } else { ULONG fBulkyObject; sc = xTextIFilter->Init( IFILTER_INIT_CANON_PARAGRAPHS | IFILTER_INIT_CANON_HYPHENS | IFILTER_INIT_CANON_SPACES | IFILTER_INIT_APPLY_INDEX_ATTRIBUTES | IFILTER_INIT_INDEXING_ONLY, 0, 0, &fBulkyObject ); if ( FAILED(sc) ) { ciDebugOut(( DEB_ERROR, "IFilter->Init() of pIStrmNoiseFile(%x) returned 0x%x.\n", _xIStrmNoiseFile.GetPointer(), sc )); } else { STAT_CHUNK statChunk; for ( sc = xTextIFilter->GetChunk( &statChunk ); SUCCEEDED(sc) && (statChunk.flags & CHUNK_TEXT) == 0; sc = xTextIFilter->GetChunk( &statChunk ) ); if ( FAILED(sc) ) { ciDebugOut(( DEB_ERROR, "IFilter->GetChunk() of pIStrmNoiseFile(%x) returned 0x%x.\n", _xIStrmNoiseFile.GetPointer(), sc )); } else { CNoiseListInit noiseInit( NOISE_SIZE ); //
// If we got this far, try creating the key maker.
//
CKeyMaker keymak( _xWBreak.GetPointer(), noiseInit ); OCCURRENCE occ = 0; CTextSource tsource( xTextIFilter.GetPointer(), statChunk ); keymak.PutStream( occ, &tsource ); _xNoiseTable.Set( noiseInit.AcqStringTable() ); } } } } else { //
// _xIStrmNoiseFile is null, don't use a noise file in filtering
//
ciDebugOut(( DEB_ITRACE, "Creating language object 0x%x, noise file = EMPTY\n", locale )); } } //CLanguage
CLanguage::~CLanguage() { }
|