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

838 lines
26 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2000.
  5. //
  6. // File: QPARSE.CXX
  7. //
  8. // Contents: Query parser
  9. //
  10. // Classes: CQParse -- query parser
  11. //
  12. // History: 19-Sep-91 BartoszM Implemented.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <qparse.hxx>
  18. #include <norm.hxx>
  19. #include <drep.hxx>
  20. #include <cci.hxx>
  21. #include <pidmap.hxx>
  22. #include <fa.hxx>
  23. #include <compare.hxx>
  24. #include "qkrep.hxx"
  25. DECLARE_SMARTP( InternalPropertyRestriction )
  26. static GUID guidQuery = DBQUERYGUID;
  27. static CFullPropSpec psUnfiltered( guidQuery, DISPID_QUERY_UNFILTERED );
  28. static GUID guidStorage = PSGUID_STORAGE;
  29. static CFullPropSpec psFilename( guidStorage, PID_STG_NAME );
  30. static CFullPropSpec psRevName( guidQuery, DISPID_QUERY_REVNAME );
  31. //+---------------------------------------------------------------------------
  32. //
  33. // Member: CQParse::CQParse, public
  34. //
  35. // Synopsis: Break phrases, normalize, and stem the query expression
  36. //
  37. // Arguments: [pidmap] -- Propid mapper
  38. // [langList] -- Language list
  39. //
  40. // History: 19-Sep-91 BartoszM Created.
  41. //
  42. //----------------------------------------------------------------------------
  43. CQParse::CQParse( CPidMapper & pidmap, CLangList & langList )
  44. : _flags(0),
  45. _pidmap( pidmap ),
  46. _langList( langList ),
  47. _lcidSystemDefault( GetSystemDefaultLCID() )
  48. {
  49. }
  50. //+---------------------------------------------------------------------------
  51. //
  52. // Member: CQParse::Parse, public
  53. //
  54. // Synopsis: Recursively parse expression
  55. //
  56. // Arguments: [pRst] -- Tree of query expressions
  57. //
  58. // Returns: Possibly modified expression
  59. //
  60. // History: 19-Sep-91 BartoszM Created.
  61. // 18-Jan-92 KyleP Use restrictions
  62. // 15-May-96 DwightKr Add check for NULL NOT restriction
  63. //
  64. // Notes: The return CRestriction will be different than [pRst].
  65. // [pRst] is not touched.
  66. //
  67. //----------------------------------------------------------------------------
  68. CRestriction* CQParse::Parse( CRestriction* pRst )
  69. {
  70. // go through leaves:
  71. // normalize values
  72. // break and normalize phrases (create phrase nodes)
  73. // GenerateMethod level 1 -- convert to ranges
  74. // higher GenerateMethod levels -- use stemmer
  75. if ( pRst->IsLeaf() )
  76. {
  77. return Leaf ( pRst );
  78. }
  79. else
  80. {
  81. if ( pRst->Type() == RTNot )
  82. {
  83. CNotRestriction * pnrst = (CNotRestriction *)pRst;
  84. XRestriction xRst( Parse( pnrst->GetChild() ) );
  85. if ( xRst.GetPointer() == 0 )
  86. {
  87. THROW( CException( QUERY_E_INVALIDRESTRICTION ) );
  88. }
  89. CNotRestriction *pNotRst = new CNotRestriction( xRst.GetPointer() );
  90. Win4Assert( pNotRst->IsValid() );
  91. xRst.Acquire();
  92. return pNotRst;
  93. }
  94. CNodeRestriction* pnrstSource = pRst->CastToNode();
  95. XNodeRestriction xnrstTarget;
  96. BOOL fVector;
  97. if ( pRst->Type() == RTVector )
  98. {
  99. fVector = TRUE;
  100. xnrstTarget.Set( new CVectorRestriction( ((CVectorRestriction *)pRst)->RankMethod(),
  101. pRst->CastToNode()->Count() ) );
  102. }
  103. else
  104. {
  105. fVector = FALSE;
  106. xnrstTarget.Set( new CNodeRestriction( pRst->Type(),
  107. pRst->CastToNode()->Count() ) );
  108. }
  109. Win4Assert( xnrstTarget->IsValid() );
  110. //
  111. // Vector nodes must be treated slightly differently than
  112. // AND/OR/ANDNOT nodes. Noise words must be placeholders
  113. // in a vector node.
  114. //
  115. BOOL fAndNode = ( xnrstTarget->Type() == RTAnd || xnrstTarget->Type() == RTProximity );
  116. ULONG cOrCount = ( fAndNode ? 1: pnrstSource->Count() ); // Number of non-noise OR components
  117. for ( unsigned i = 0; i < pnrstSource->Count(); i++ )
  118. {
  119. CRestriction * px = Parse ( pnrstSource->GetChild(i) );
  120. //
  121. // Don't store noise phrases (null nodes) during parse,
  122. // *unless* this is a vector node.
  123. if ( 0 == px && fVector )
  124. {
  125. px = new CRestriction;
  126. }
  127. if ( 0 != px )
  128. {
  129. XRestriction xRst( px );
  130. xnrstTarget->AddChild ( px );
  131. xRst.Acquire();
  132. }
  133. else
  134. {
  135. cOrCount--;
  136. if ( 0 == cOrCount ) // all components are noise only
  137. THROW( CException( QUERY_E_ALLNOISE ) );
  138. }
  139. }
  140. return xnrstTarget.Acquire();
  141. }
  142. } //Parse
  143. //+---------------------------------------------------------------------------
  144. //
  145. // Member: CQParse::Leaf, private
  146. //
  147. // Synopsis: Parse the leaf node of expression tree
  148. //
  149. // Arguments: [pExpr] -- leaf expression
  150. //
  151. // Returns: Possibly modified expression
  152. //
  153. // Requires: pExpr->IsLeaf() TRUE
  154. //
  155. // History: 19-Sep-91 BartoszM Created.
  156. // 18-Jan-92 KyleP Use restrictions
  157. // 05-Nov-93 DwightKr Changed PutUnsignedValue => PutValue
  158. //
  159. //----------------------------------------------------------------------------
  160. CRestriction* CQParse::Leaf ( CRestriction* pRst )
  161. {
  162. Win4Assert ( pRst->IsLeaf() );
  163. switch( pRst->Type() )
  164. {
  165. case RTContent:
  166. {
  167. CContentRestriction* pContRst = (CContentRestriction *) pRst;
  168. ULONG GenerateMethod = pContRst->GenerateMethod();
  169. if ( GenerateMethod > GENERATE_METHOD_MAX_USER )
  170. {
  171. vqDebugOut(( DEB_ERROR,
  172. "QParse: GenerateMethod 0x%x > GENERATE_METHOD_MAX_USER\n",
  173. GenerateMethod ));
  174. THROW( CException( QUERY_E_INVALIDRESTRICTION ) );
  175. }
  176. CQueryKeyRepository keyRep( GenerateMethod );
  177. CRestriction * pPhraseRst;
  178. switch ( BreakPhrase ( pContRst->GetPhrase(),
  179. pContRst->GetProperty(),
  180. pContRst->GetLocale(),
  181. GenerateMethod,
  182. keyRep,
  183. 0,
  184. _pidmap,
  185. _langList) )
  186. {
  187. case BP_NOISE:
  188. _flags |= CI_NOISE_IN_PHRASE;
  189. // Note fall through...
  190. case BP_OK:
  191. pPhraseRst = keyRep.AcqRst();
  192. if ( pPhraseRst )
  193. pPhraseRst->SetWeight( pRst->Weight() );
  194. else
  195. _flags |= CI_NOISE_PHRASE;
  196. break;
  197. default:
  198. Win4Assert( !"How did we get here?" );
  199. case BP_INVALID_PROPERTY:
  200. pPhraseRst = 0;
  201. break;
  202. } // switch
  203. return pPhraseRst;
  204. break;
  205. }
  206. case RTNatLanguage:
  207. {
  208. CNatLanguageRestriction* pNatLangRst = (CNatLanguageRestriction *) pRst;
  209. CVectorKeyRepository vecKeyRep( pNatLangRst->GetProperty(),
  210. pNatLangRst->GetLocale(),
  211. pRst->Weight(),
  212. _pidmap,
  213. _langList );
  214. CRestriction* pVectorRst;
  215. switch ( BreakPhrase ( pNatLangRst->GetPhrase(),
  216. pNatLangRst->GetProperty(),
  217. pNatLangRst->GetLocale(),
  218. GENERATE_METHOD_INFLECT,
  219. vecKeyRep,
  220. &vecKeyRep,
  221. _pidmap,
  222. _langList ) )
  223. {
  224. case BP_NOISE:
  225. _flags |= CI_NOISE_IN_PHRASE;
  226. // Note fall through...
  227. case BP_OK:
  228. pVectorRst = vecKeyRep.AcqRst();
  229. if ( pVectorRst )
  230. pVectorRst->SetWeight( pRst->Weight() );
  231. else
  232. _flags |= CI_NOISE_PHRASE;
  233. break;
  234. default:
  235. Win4Assert( !"How did we get here?" );
  236. case BP_INVALID_PROPERTY:
  237. pVectorRst = 0;
  238. break;
  239. } // switch
  240. return pVectorRst;
  241. break;
  242. }
  243. case RTProperty:
  244. {
  245. CPropertyRestriction * prstProp = (CPropertyRestriction *)pRst;
  246. if ( getBaseRelop(prstProp->Relation()) > PRSomeBits )
  247. {
  248. vqDebugOut(( DEB_ERROR,
  249. "QParse: Invalid comparison operator %d\n",
  250. prstProp->Relation() ));
  251. THROW( CException( QUERY_E_INVALIDRESTRICTION ) );
  252. }
  253. PROPID pid = _pidmap.NameToPid( prstProp->GetProperty() );
  254. if ( pidInvalid != pid )
  255. pid = _pidmap.PidToRealPid( pid );
  256. if ( pidInvalid == pid )
  257. {
  258. vqDebugOut(( DEB_ERROR,
  259. "QParse: Invalid property\n" ));
  260. THROW( CException( QUERY_E_INVALIDRESTRICTION ) );
  261. }
  262. CInternalPropertyRestriction * prstIProp =
  263. new CInternalPropertyRestriction( prstProp->Relation(),
  264. pid,
  265. prstProp->Value() );
  266. Win4Assert( prstIProp->IsValid() );
  267. XInternalPropertyRestriction xrstIProp( prstIProp );
  268. //
  269. // If the property restriction is over a string value, then create
  270. // a helper content restriction.
  271. //
  272. switch( prstProp->Value().Type() )
  273. {
  274. case VT_LPSTR:
  275. AddLpstrHelper( prstProp, prstIProp );
  276. break;
  277. case VT_LPWSTR:
  278. AddLpwstrHelper( prstProp, prstIProp );
  279. break;
  280. case VT_LPWSTR | VT_VECTOR:
  281. AddLpwstrVectorHelper( prstProp, prstIProp );
  282. break;
  283. case VT_BOOL:
  284. if ( prstProp->Value().GetBOOL() != FALSE &&
  285. prstProp->Relation() == PREQ &&
  286. prstProp->GetProperty() == psUnfiltered )
  287. {
  288. delete xrstIProp.Acquire();
  289. CUnfilteredRestriction *pUnfiltRst = new CUnfilteredRestriction;
  290. return( pUnfiltRst );
  291. }
  292. break;
  293. default:
  294. break;
  295. }
  296. return( xrstIProp.Acquire() );
  297. }
  298. default:
  299. {
  300. vqDebugOut(( DEB_ERROR,
  301. "QParse: Invalid restriction type %d\n",
  302. pRst->Type() ));
  303. THROW( CException( QUERY_E_INVALIDRESTRICTION ) );
  304. return 0;
  305. }
  306. }
  307. } //Leaf
  308. //+---------------------------------------------------------------------------
  309. //
  310. // Member: CQParse::AddLpwstrHelper, private
  311. //
  312. // Synopsis: Add content helpers for VT_LPWSTR properties.
  313. //
  314. // Arguments: [prstProp] -- Property restriction (input)
  315. // [prstIProp] -- Internal property restriction (output)
  316. //
  317. // History: 03-Oct-95 KyleP Broke out as method.
  318. //
  319. //----------------------------------------------------------------------------
  320. void CQParse::AddLpwstrHelper( CPropertyRestriction * prstProp,
  321. CInternalPropertyRestriction * prstIProp )
  322. {
  323. //
  324. // For equality, we create a content restriction with GenerateMethod level 0.
  325. //
  326. if ( prstProp->Relation() == PREQ )
  327. {
  328. CQueryKeyRepository keyRep( GENERATE_METHOD_EXACT );
  329. BreakPhrase ( (WCHAR *)prstProp->Value().GetLPWSTR(),
  330. prstProp->GetProperty(),
  331. _lcidSystemDefault,
  332. GENERATE_METHOD_EXACT,
  333. keyRep,
  334. 0,
  335. _pidmap,
  336. _langList );
  337. prstIProp->SetContentHelper( keyRep.AcqRst() );
  338. }
  339. //
  340. // For regular expression, create a GenerateMethod match for any fixed prefix
  341. // on the string.
  342. //
  343. else if ( prstProp->Relation() == PRRE )
  344. {
  345. const MAX_PREFIX_LENGTH = 50;
  346. unsigned i = wcscspn( prstProp->Value().GetLPWSTR(),
  347. awcSpecialRegex );
  348. //
  349. // Should the 0 below be a registry parameter?
  350. //
  351. if ( i > 0 )
  352. {
  353. WCHAR wcs[MAX_PREFIX_LENGTH];
  354. if ( i > sizeof(wcs)/sizeof(WCHAR) - 2 )
  355. i = sizeof(wcs)/sizeof(WCHAR) - 2;
  356. memcpy( wcs, prstProp->Value().GetLPWSTR(), i*sizeof(WCHAR) );
  357. wcs[i] = 0;
  358. //
  359. // Trickery: Key repository is GENERATE_METHOD_PREFIX which turns key into ranges.
  360. // Phrase is broken with GENERATE_METHOD_EXACTPREFIXMATCH which does 'exact'
  361. // prefix matching: e.g. it uses the noise word list. The result is
  362. // that we match ranges, but don't set a content helper if we hit
  363. // a noise word. This is different from a user GENERATE_METHOD_PREFIX
  364. // which uses a very minimal noise word list (only 1 character
  365. // prefixes are noise).
  366. //
  367. CQueryKeyRepository keyRep( GENERATE_METHOD_PREFIX );
  368. if ( BP_OK == BreakPhrase ( wcs,
  369. prstProp->GetProperty(),
  370. _lcidSystemDefault,
  371. GENERATE_METHOD_EXACTPREFIXMATCH,
  372. keyRep,
  373. 0,
  374. _pidmap,
  375. _langList ) )
  376. {
  377. prstIProp->SetContentHelper( keyRep.AcqRst() );
  378. }
  379. }
  380. //
  381. // If this is the filename property, then add to the content helper
  382. // the reversed suffix string w/o wildcards. For *.cxx we would
  383. // add xxc.
  384. //
  385. if ( prstProp->GetProperty() == psFilename )
  386. {
  387. WCHAR wcs[MAX_PREFIX_LENGTH];
  388. WCHAR const * pBegin = prstProp->Value().GetLPWSTR();
  389. WCHAR const * pEnd = pBegin + wcslen(pBegin) - 1;
  390. i = 0;
  391. for ( ; pEnd >= pBegin && i < MAX_PREFIX_LENGTH - 1 ; pEnd-- )
  392. {
  393. if ( wcschr( awcSpecialRegexReverse, *pEnd ) == 0 )
  394. wcs[i++] = *pEnd;
  395. else
  396. {
  397. wcs[i] = 0;
  398. break;
  399. }
  400. }
  401. if ( i < MAX_PREFIX_LENGTH )
  402. wcs[i] = 0;
  403. wcs[MAX_PREFIX_LENGTH - 1] = 0;
  404. if ( i > 0 )
  405. {
  406. CQueryKeyRepository keyRep( GENERATE_METHOD_PREFIX );
  407. if ( prstIProp->GetContentHelper() == 0 )
  408. {
  409. if ( BP_OK == BreakPhrase ( wcs,
  410. psRevName,
  411. _lcidSystemDefault,
  412. GENERATE_METHOD_EXACTPREFIXMATCH,
  413. keyRep,
  414. 0,
  415. _pidmap,
  416. _langList ) )
  417. {
  418. prstIProp->SetContentHelper( keyRep.AcqRst() );
  419. }
  420. }
  421. else
  422. {
  423. if ( BP_OK == BreakPhrase ( wcs,
  424. psRevName,
  425. _lcidSystemDefault,
  426. GENERATE_METHOD_EXACTPREFIXMATCH,
  427. keyRep,
  428. 0,
  429. _pidmap,
  430. _langList ) )
  431. {
  432. CNodeRestriction *pNodeRst = new CNodeRestriction( RTAnd, 2 );
  433. XNodeRestriction rstAnd( pNodeRst );
  434. Win4Assert( rstAnd->IsValid() );
  435. unsigned posOrig;
  436. rstAnd->AddChild( prstIProp->GetContentHelper(), posOrig );
  437. prstIProp->AcquireContentHelper();
  438. XRestriction xRst( keyRep.AcqRst() );
  439. unsigned pos;
  440. rstAnd->AddChild( xRst.GetPointer(), pos );
  441. xRst.Acquire();
  442. if ( 0 == rstAnd->GetChild( pos ) )
  443. {
  444. prstIProp->SetContentHelper( rstAnd->RemoveChild( posOrig ) );
  445. }
  446. else
  447. {
  448. prstIProp->SetContentHelper( rstAnd.Acquire() );
  449. }
  450. }
  451. }
  452. }
  453. }
  454. }
  455. } //AddLpwstrHelper
  456. //+---------------------------------------------------------------------------
  457. //
  458. // Member: CQParse::AddLpstrHelper, private
  459. //
  460. // Synopsis: Add content helpers for VT_LPSTR properties.
  461. //
  462. // Arguments: [prstProp] -- Property restriction (input)
  463. // [prstIProp] -- Internal property restriction (output)
  464. //
  465. // History: 03-Oct-95 KyleP Broke out as method.
  466. //
  467. //----------------------------------------------------------------------------
  468. void CQParse::AddLpstrHelper( CPropertyRestriction * prstProp,
  469. CInternalPropertyRestriction * prstIProp )
  470. {
  471. //
  472. // For equality, we create a content restriction with GenerateMethod level 0.
  473. //
  474. if ( prstProp->Relation() == PREQ )
  475. {
  476. CQueryKeyRepository keyRep( GENERATE_METHOD_EXACT );
  477. BreakPhrase ( prstProp->Value().GetLPSTR(),
  478. prstProp->GetProperty(),
  479. _lcidSystemDefault,
  480. GENERATE_METHOD_EXACT,
  481. keyRep,
  482. 0,
  483. _pidmap,
  484. _langList );
  485. prstIProp->SetContentHelper( keyRep.AcqRst() );
  486. }
  487. //
  488. // For regular expression, create a GenerateMethod match for any fixed prefix
  489. // on the string.
  490. //
  491. else if ( prstProp->Relation() == PRRE )
  492. {
  493. const MAX_PREFIX_LENGTH = 50;
  494. unsigned i = strcspn( prstProp->Value().GetLPSTR(),
  495. acSpecialRegex );
  496. //
  497. // Should the 0 below be a registry parameter?
  498. //
  499. if ( i > 0 )
  500. {
  501. char ac[MAX_PREFIX_LENGTH];
  502. if ( i > sizeof(ac) - 1 )
  503. i = sizeof(ac) - 1;
  504. memcpy( ac, prstProp->Value().GetLPSTR(), i );
  505. ac[i] = 0;
  506. //
  507. // Trickery: Key repository is GENERATE_METHOD_PREFIX which turns key into ranges.
  508. // Phrase is broken with GENERATE_METHOD_EXACTPREFIXMATCH which does 'exact'
  509. // prefix matching: e.g. it uses the noise word list. The result is
  510. // that we match ranges, but don't set a content helper if we hit
  511. // a noise word. This is different from a user GENERATE_METHOD_PREFIX
  512. // which uses a very minimal noise word list (only 1 character
  513. // prefixes are noise).
  514. //
  515. CQueryKeyRepository keyRep( GENERATE_METHOD_PREFIX );
  516. if ( BP_OK == BreakPhrase ( ac,
  517. prstProp->GetProperty(),
  518. _lcidSystemDefault,
  519. GENERATE_METHOD_EXACTPREFIXMATCH,
  520. keyRep,
  521. 0,
  522. _pidmap,
  523. _langList ) )
  524. {
  525. prstIProp->SetContentHelper( keyRep.AcqRst() );
  526. }
  527. }
  528. }
  529. } //AddLpstrHelper
  530. //+---------------------------------------------------------------------------
  531. //
  532. // Member: CQParse::AddLpwstrVectorHelper, private
  533. //
  534. // Synopsis: Add content helpers for VT_LPWSTR | VT_VECTOR properties.
  535. //
  536. // Arguments: [prstProp] -- Property restriction (input)
  537. // [prstIProp] -- Internal property restriction (output)
  538. //
  539. // History: 03-Oct-95 KyleP Created
  540. //
  541. //----------------------------------------------------------------------------
  542. void CQParse::AddLpwstrVectorHelper( CPropertyRestriction * prstProp,
  543. CInternalPropertyRestriction * prstIProp )
  544. {
  545. if ( prstProp->Value().Count() == 0 )
  546. {
  547. //
  548. // Null vector, hence no helper restriction
  549. //
  550. return;
  551. }
  552. if ( prstProp->Relation() == PREQ || prstProp->Relation() == (PREQ | PRAll) )
  553. {
  554. XNodeRestriction xrstAnd( new CNodeRestriction( RTAnd, prstProp->Value().Count() ) );
  555. Win4Assert( xrstAnd->IsValid() );
  556. for ( unsigned i = 0; i < prstProp->Value().Count(); i++ )
  557. {
  558. CQueryKeyRepository keyRep( GENERATE_METHOD_EXACT );
  559. BreakPhrase ( (WCHAR *)prstProp->Value().GetLPWSTR( i ),
  560. prstProp->GetProperty(),
  561. _lcidSystemDefault,
  562. GENERATE_METHOD_EXACT,
  563. keyRep,
  564. 0,
  565. _pidmap,
  566. _langList );
  567. CRestriction * prst = keyRep.AcqRst();
  568. if ( 0 != prst )
  569. {
  570. XPtr<CRestriction> xRst( prst );
  571. xrstAnd->AddChild( prst );
  572. xRst.Acquire();
  573. }
  574. else
  575. {
  576. _flags |= CI_NOISE_IN_PHRASE;
  577. }
  578. }
  579. //
  580. // If there aren't any nodes (because of noise words) don't set the
  581. // content helper, so we can fall back on enumeration. Set _flags
  582. // in this case so it's obvious why we had to fall back on enumration.
  583. //
  584. if ( xrstAnd->Count() == 1 )
  585. prstIProp->SetContentHelper( xrstAnd->RemoveChild( 0 ) );
  586. else if ( 0 != xrstAnd->Count() )
  587. prstIProp->SetContentHelper( xrstAnd.Acquire() );
  588. }
  589. else if ( prstProp->Relation() == (PREQ | PRAny) )
  590. {
  591. XNodeRestriction xrstOr( new CNodeRestriction( RTOr, prstProp->Value().Count() ) );
  592. for ( unsigned i = 0; i < prstProp->Value().Count(); i++ )
  593. {
  594. CQueryKeyRepository keyRep( GENERATE_METHOD_EXACT );
  595. BreakPhrase ( (WCHAR *)prstProp->Value().GetLPWSTR( i ),
  596. prstProp->GetProperty(),
  597. _lcidSystemDefault,
  598. GENERATE_METHOD_EXACT,
  599. keyRep,
  600. 0,
  601. _pidmap,
  602. _langList );
  603. CRestriction * prst = keyRep.AcqRst();
  604. if ( 0 != prst )
  605. {
  606. XPtr<CRestriction> xRst( prst );
  607. xrstOr->AddChild( prst );
  608. xRst.Acquire();
  609. }
  610. else
  611. break; // If we can't match all OR clauses, then we're in trouble.
  612. }
  613. //
  614. // RTAny is all-or-nothing. A missed clause in one that CI can't resolve, which
  615. // means there are objects that match this query that CI won't find.
  616. //
  617. if ( xrstOr->Count() == prstProp->Value().Count() )
  618. {
  619. if ( xrstOr->Count() == 1 )
  620. prstIProp->SetContentHelper( xrstOr->RemoveChild( 0 ) );
  621. else
  622. prstIProp->SetContentHelper( xrstOr.Acquire() );
  623. }
  624. else
  625. {
  626. _flags |= CI_NOISE_IN_PHRASE;
  627. }
  628. }
  629. } //AddLpwstrVectorHelper
  630. //+---------------------------------------------------------------------------
  631. //
  632. // Function: BreakPhrase
  633. //
  634. // Synopsis: Break phrase into words and noun phrases
  635. //
  636. // Arguments: [phrase] -- string
  637. // [ps] -- property specification
  638. // [GenerateMethod] -- GenerateMethod flag
  639. // [keyRep] -- key repository into which words will be deposited
  640. // [pPhraseSink] -- sink for phrases
  641. // [pidMap] -- pid mapper used to convert property to propid
  642. //
  643. // Returns: Noise word status.
  644. //
  645. // History: 19-Sep-1991 BartoszM Created.
  646. // 18-Jan-1992 KyleP Use restrictions
  647. // 12-Feb-2000 KitmanH Added hack to fix German word breaking
  648. // issue for prefix matching queries
  649. //
  650. //----------------------------------------------------------------------------
  651. BreakPhraseStatus BreakPhrase ( WCHAR const * phrase,
  652. const CFullPropSpec & ps,
  653. LCID lcid,
  654. ULONG GenerateMethod,
  655. PKeyRepository& krep,
  656. IPhraseSink *pPhraseSink,
  657. CPidMapper & pidMap,
  658. CLangList & langList )
  659. {
  660. CDataRepository drep( krep, pPhraseSink, TRUE, GenerateMethod, pidMap, langList );
  661. if ( drep.PutLanguage( lcid ) && drep.PutPropName( ps ) )
  662. {
  663. ciDebugOut (( DEB_ITRACE,
  664. "BreakPhrase: phrase = \"%ws\" Propid = %lu\n",
  665. phrase, drep.GetPropId() ));
  666. drep.PutPhrase( phrase, wcslen(phrase) + 1 );
  667. krep.FixUp( drep );
  668. if ( drep.ContainedNoiseWords() )
  669. return BP_NOISE;
  670. else
  671. return BP_OK;
  672. }
  673. else
  674. return BP_INVALID_PROPERTY;
  675. } //BreakPhrase
  676. //
  677. // DBCS version of the previous function.
  678. //
  679. BreakPhraseStatus BreakPhrase ( char const * phrase,
  680. const CFullPropSpec & ps,
  681. LCID lcid,
  682. ULONG GenerateMethod,
  683. PKeyRepository& krep,
  684. IPhraseSink *pPhraseSink,
  685. CPidMapper & pidMap,
  686. CLangList & langList )
  687. {
  688. CDataRepository drep( krep, pPhraseSink, TRUE, GenerateMethod, pidMap, langList );
  689. if ( drep.PutLanguage( lcid ) && drep.PutPropName( ps ) )
  690. {
  691. ciDebugOut (( DEB_ITRACE,
  692. "BreakPhrase: phrase = \"%s\" Propid = %lu\n",
  693. phrase, drep.GetPropId() ));
  694. drep.PutPhrase( phrase, strlen(phrase) + 1 );
  695. krep.FixUp( drep );
  696. if ( drep.ContainedNoiseWords() )
  697. return BP_NOISE;
  698. else
  699. return BP_OK;
  700. }
  701. else
  702. return BP_INVALID_PROPERTY;
  703. } //BreakPhrase