Leaked source code of windows server 2003
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.

751 lines
19 KiB

  1. //
  2. // candfunc.cpp
  3. //
  4. #include "private.h"
  5. #include "globals.h"
  6. #include "mscandui.h"
  7. #include "candmgr.h"
  8. #include "candfunc.h"
  9. #include "candutil.h"
  10. #include "candobj.h"
  11. #include "candui.h"
  12. /*============================================================================*/
  13. /* */
  14. /* C C A N D F N A U T O F I L T E R */
  15. /* */
  16. /*============================================================================*/
  17. /* C C A N D F N A U T O F I L T E R */
  18. /*------------------------------------------------------------------------------
  19. Constructor of CCandFnAutoFilter
  20. ------------------------------------------------------------------------------*/
  21. CCandFnAutoFilter::CCandFnAutoFilter( CCandidateUI *pCandUI )
  22. {
  23. m_pCandUI = pCandUI;
  24. m_fEnable = FALSE;
  25. m_bstrFilter = NULL;
  26. m_pSink = NULL;
  27. InitEventSink( pCandUI->GetCandListMgr() );
  28. }
  29. /* ~ C C A N D F N A U T O F I L T E R */
  30. /*------------------------------------------------------------------------------
  31. Destructor of CCandFnAutoFilter
  32. ------------------------------------------------------------------------------*/
  33. CCandFnAutoFilter::~CCandFnAutoFilter( void )
  34. {
  35. ReleaseEventSink();
  36. ClearFilterString();
  37. FilterCandidateList();
  38. DoneEventSink();
  39. }
  40. /* O N S E T C A N D I D A T E L I S T */
  41. /*------------------------------------------------------------------------------
  42. Callback function on SetCandidateList
  43. (CCandListEventSink method)
  44. NOTE: Do not update candidate item in the callback functios
  45. ------------------------------------------------------------------------------*/
  46. void CCandFnAutoFilter::OnSetCandidateList( void )
  47. {
  48. ClearFilterString();
  49. }
  50. /* O N C L E A R C A N D I D A T E L I S T */
  51. /*------------------------------------------------------------------------------
  52. Callback function on ClearCandidateList
  53. (CCandListEventSink method)
  54. NOTE: Do not update candidate item in the callback functios
  55. ------------------------------------------------------------------------------*/
  56. void CCandFnAutoFilter::OnClearCandidateList( void )
  57. {
  58. ClearFilterString();
  59. }
  60. /* O N C A N D I T E M U P D A T E */
  61. /*------------------------------------------------------------------------------
  62. Callback function of candiate item has been updated
  63. (CCandListEventSink method)
  64. NOTE: Do not update candidate item in the callback functios
  65. ------------------------------------------------------------------------------*/
  66. void CCandFnAutoFilter::OnCandItemUpdate( void )
  67. {
  68. // nothing to do...
  69. }
  70. /* O N S E L E C T I O N C H A N G E D */
  71. /*------------------------------------------------------------------------------
  72. Callback function of candiate selection has been changed
  73. (CCandListEventSink method)
  74. NOTE: Do not update candidate item in the callback functios
  75. ------------------------------------------------------------------------------*/
  76. void CCandFnAutoFilter::OnSelectionChanged( void )
  77. {
  78. ClearFilterString();
  79. }
  80. /* E N A B L E */
  81. /*------------------------------------------------------------------------------
  82. ------------------------------------------------------------------------------*/
  83. HRESULT CCandFnAutoFilter::Enable( BOOL fEnable )
  84. {
  85. if (m_fEnable != fEnable) {
  86. m_fEnable = fEnable;
  87. ClearFilterString();
  88. FilterCandidateList();
  89. // notify
  90. if (fEnable) {
  91. m_pCandUI->NotifyFilteringEvent( CANDUIFEV_ENABLED );
  92. }
  93. else {
  94. m_pCandUI->NotifyFilteringEvent( CANDUIFEV_DISABLED );
  95. }
  96. }
  97. return S_OK;
  98. }
  99. /* G E T F I L T E R I N G R E S U L T */
  100. /*------------------------------------------------------------------------------
  101. ------------------------------------------------------------------------------*/
  102. HRESULT CCandFnAutoFilter::GetFilteringResult( CANDUIFILTERSTR strtype, BSTR *pbstr )
  103. {
  104. CCandidateItem *pCandItem;
  105. LPCWSTR pchCandidate;
  106. LPCWSTR pchFiltering;
  107. LPCWSTR pchReturn;
  108. WCHAR szNull[] = L"";
  109. int iItemSel;
  110. if (pbstr == NULL) {
  111. return E_INVALIDARG;
  112. }
  113. if (!IsEnabled()) {
  114. return E_FAIL;
  115. }
  116. // check if candidate list has been set
  117. if (GetCandListMgr()->GetCandList() == NULL) {
  118. return E_FAIL;
  119. }
  120. //
  121. iItemSel = GetCandListMgr()->GetCandList()->GetSelection();
  122. pCandItem = GetCandListMgr()->GetCandList()->GetCandidateItem( iItemSel );
  123. if (pCandItem == NULL)
  124. {
  125. Assert( FALSE );
  126. return E_FAIL;
  127. }
  128. //
  129. pchCandidate = pCandItem->GetString();
  130. pchFiltering = GetFilterString();
  131. if (pchFiltering == NULL) {
  132. pchFiltering = szNull;
  133. }
  134. pchReturn = NULL;
  135. switch (strtype) {
  136. case CANDUIFST_COMPLETE: {
  137. /* complete string */
  138. pchReturn = pchCandidate;
  139. break;
  140. }
  141. case CANDUIFST_DETERMINED: {
  142. /* determined string (filtering string) */
  143. pchReturn = pchFiltering;
  144. break;
  145. }
  146. case CANDUIFST_UNDETERMINED: {
  147. /* undetermined string (incoming string) */
  148. Assert( wcslen(pchFiltering) <= wcslen(pchCandidate) );;
  149. pchReturn = pchCandidate + wcslen(pchFiltering);
  150. break;
  151. }
  152. }
  153. if (pchReturn == NULL) {
  154. return E_FAIL;
  155. }
  156. *pbstr = SysAllocString( pchReturn );
  157. return (*pbstr != NULL) ? S_OK : E_OUTOFMEMORY;
  158. }
  159. /* I S E N A B L E D */
  160. /*------------------------------------------------------------------------------
  161. ------------------------------------------------------------------------------*/
  162. BOOL CCandFnAutoFilter::IsEnabled( void )
  163. {
  164. return m_fEnable;
  165. }
  166. /* S E T F I L T E R S T R I N G */
  167. /*------------------------------------------------------------------------------
  168. Set filter string
  169. Note that this never update filter result. Call FilterCandidateList.
  170. ------------------------------------------------------------------------------*/
  171. void CCandFnAutoFilter::SetFilterString( LPCWSTR psz )
  172. {
  173. ClearFilterString();
  174. if (psz != NULL && *psz != L'\0') {
  175. m_bstrFilter = SysAllocString( psz );
  176. }
  177. }
  178. /* G E T F I L T E R S T R I N G */
  179. /*------------------------------------------------------------------------------
  180. Get filter string
  181. ------------------------------------------------------------------------------*/
  182. LPCWSTR CCandFnAutoFilter::GetFilterString( void )
  183. {
  184. return m_bstrFilter;
  185. }
  186. /* C L E A R F I L T E R S T R I N G */
  187. /*------------------------------------------------------------------------------
  188. Clear filter string
  189. Note that this never update filter result. Call FilterCandidateList.
  190. ------------------------------------------------------------------------------*/
  191. void CCandFnAutoFilter::ClearFilterString( void )
  192. {
  193. if (m_bstrFilter != NULL) {
  194. SysFreeString( m_bstrFilter );
  195. m_bstrFilter = NULL;
  196. }
  197. }
  198. /* F I L T E R C A N D I D A T E L I S T */
  199. /*------------------------------------------------------------------------------
  200. Do filtering
  201. ------------------------------------------------------------------------------*/
  202. int CCandFnAutoFilter::FilterCandidateList( void )
  203. {
  204. CCandidateList *pCandList;
  205. int cchFilter;
  206. int i;
  207. int nItem;
  208. int nItemVisible;
  209. BOOL fFirst;
  210. pCandList = GetCandListMgr()->GetCandList();
  211. if (pCandList == NULL) {
  212. return 0;
  213. }
  214. cchFilter = (m_bstrFilter == NULL) ? 0 : wcslen( m_bstrFilter );
  215. nItem = pCandList->GetItemCount();
  216. nItemVisible = 0;
  217. fFirst = TRUE;
  218. for (i = 0; i < nItem; i++) {
  219. CCandidateItem *pCandItem = pCandList->GetCandidateItem( i );
  220. BOOL fMatch = TRUE;
  221. if (cchFilter != 0) {
  222. fMatch = (CompareString( pCandItem->GetString(), m_bstrFilter, cchFilter ) == 0);
  223. }
  224. pCandItem->SetVisibleState( fMatch );
  225. if (fMatch) {
  226. nItemVisible++;
  227. // select first visible item
  228. if (fFirst) {
  229. GetCandListMgr()->SetSelection( i, this );
  230. fFirst = FALSE;
  231. }
  232. }
  233. }
  234. GetCandListMgr()->NotifyCandItemUpdate( this );
  235. return nItemVisible;
  236. }
  237. /* F E X I S T I T E M M A T C H E S */
  238. /*------------------------------------------------------------------------------
  239. Check if item exist matches with the string
  240. ------------------------------------------------------------------------------*/
  241. BOOL CCandFnAutoFilter::FExistItemMatches( LPCWSTR psz )
  242. {
  243. CCandidateList *pCandList;
  244. int cchFilter;
  245. int i;
  246. int nItem;
  247. int nItemVisible;
  248. pCandList = GetCandListMgr()->GetCandList();
  249. if (pCandList == NULL) {
  250. return 0;
  251. }
  252. cchFilter = (psz == NULL) ? 0 : wcslen( psz );
  253. nItem = pCandList->GetItemCount();
  254. nItemVisible = 0;
  255. for (i = 0; i < nItem; i++) {
  256. CCandidateItem *pCandItem = pCandList->GetCandidateItem( i );
  257. BOOL fMatch = TRUE;
  258. if (cchFilter != 0) {
  259. fMatch = (CompareString( pCandItem->GetString(), psz, cchFilter ) == 0);
  260. }
  261. if (fMatch) {
  262. nItemVisible++;
  263. }
  264. }
  265. return (nItemVisible != 0);
  266. }
  267. /* C R E A T E I N T E R F A C E O B J E C T */
  268. /*------------------------------------------------------------------------------
  269. ------------------------------------------------------------------------------*/
  270. HRESULT CCandFnAutoFilter::CreateInterfaceObject( REFIID riid, void **ppvObj )
  271. {
  272. CCandUIFnAutoFilter *pObject;
  273. HRESULT hr;
  274. pObject = new CCandUIFnAutoFilter( m_pCandUI, this );
  275. if (pObject == NULL) {
  276. return E_OUTOFMEMORY;
  277. }
  278. hr = pObject->QueryInterface( riid, ppvObj );
  279. pObject->Release();
  280. return hr;
  281. }
  282. /*============================================================================*/
  283. /* */
  284. /* C C A N D F N S O R T */
  285. /* */
  286. /*============================================================================*/
  287. /* C C A N D F N S O R T */
  288. /*------------------------------------------------------------------------------
  289. Constructor of CCandFnSort
  290. ------------------------------------------------------------------------------*/
  291. CCandFnSort::CCandFnSort( CCandidateUI *pCandUI )
  292. {
  293. m_pCandUI = pCandUI;
  294. m_SortType = CANDSORT_NONE;
  295. m_pSink = NULL;
  296. InitEventSink( pCandUI->GetCandListMgr() );
  297. }
  298. /* ~ C C A N D F N S O R T */
  299. /*------------------------------------------------------------------------------
  300. Destructor of CCandFnSort
  301. ------------------------------------------------------------------------------*/
  302. CCandFnSort::~CCandFnSort( void )
  303. {
  304. ReleaseEventSink();
  305. SortCandidateList( CANDSORT_NONE );
  306. DoneEventSink();
  307. }
  308. /* O N S E T C A N D I D A T E L I S T */
  309. /*------------------------------------------------------------------------------
  310. Callback function on SetCandidateList
  311. (CCandListEventSink method)
  312. NOTE: Do not update candidate item in the callback functios
  313. ------------------------------------------------------------------------------*/
  314. void CCandFnSort::OnSetCandidateList( void )
  315. {
  316. m_SortType = CANDSORT_NONE;
  317. }
  318. /* O N C L E A R C A N D I D A T E L I S T */
  319. /*------------------------------------------------------------------------------
  320. Callback function on ClearCandidateList
  321. (CCandListEventSink method)
  322. NOTE: Do not update candidate item in the callback functios
  323. ------------------------------------------------------------------------------*/
  324. void CCandFnSort::OnClearCandidateList( void )
  325. {
  326. m_SortType = CANDSORT_NONE;
  327. }
  328. /* O N C A N D I T E M U P D A T E */
  329. /*------------------------------------------------------------------------------
  330. Callback function of candiate item has been updated
  331. (CCandListEventSink method)
  332. NOTE: Do not update candidate item in the callback functios
  333. ------------------------------------------------------------------------------*/
  334. void CCandFnSort::OnCandItemUpdate( void )
  335. {
  336. // nothing to do
  337. }
  338. /* O N S E L E C T I O N C H A N G E D */
  339. /*------------------------------------------------------------------------------
  340. Callback function of candiate selection has been changed
  341. (CCandListEventSink method)
  342. NOTE: Do not update candidate item in the callback functios
  343. ------------------------------------------------------------------------------*/
  344. void CCandFnSort::OnSelectionChanged( void )
  345. {
  346. // nothing to do
  347. }
  348. /* S O R T C A N D I D A T E L I S T */
  349. /*------------------------------------------------------------------------------
  350. Sort candidate items
  351. NOTE: Do not call SetSelection during sort to prevent from clearing
  352. filtering string. Selection will be updated in CCandListMgr,
  353. and candidate window rebuilds candidate list including selection
  354. when candidate item has been updates...
  355. ------------------------------------------------------------------------------*/
  356. HRESULT CCandFnSort::SortCandidateList( CANDSORT type )
  357. {
  358. if (GetCandListMgr()->GetCandList() == NULL) {
  359. return E_FAIL;
  360. }
  361. if (m_SortType != type) {
  362. // do sort
  363. m_SortType = type;
  364. SortProc( 0, GetCandListMgr()->GetCandList()->GetItemCount() - 1 );
  365. GetCandListMgr()->NotifyCandItemUpdate( this );
  366. // notify event
  367. if (m_SortType != CANDSORT_NONE) {
  368. m_pCandUI->NotifySortEvent( CANDUISEV_SORTED );
  369. }
  370. else {
  371. m_pCandUI->NotifySortEvent( CANDUISEV_RESTORED );
  372. }
  373. }
  374. return S_OK;
  375. }
  376. /* G E T S O R T T Y P E */
  377. /*------------------------------------------------------------------------------
  378. Get sort type
  379. ------------------------------------------------------------------------------*/
  380. HRESULT CCandFnSort::GetSortType( CANDSORT *ptype )
  381. {
  382. if (ptype == NULL) {
  383. return E_INVALIDARG;
  384. }
  385. *ptype = m_SortType;
  386. return S_OK;
  387. }
  388. /* C R E A T E I N T E R F A C E O B J E C T */
  389. /*------------------------------------------------------------------------------
  390. ------------------------------------------------------------------------------*/
  391. HRESULT CCandFnSort::CreateInterfaceObject( REFIID riid, void **ppvObj )
  392. {
  393. CCandUIFnSort *pObject;
  394. HRESULT hr;
  395. pObject = new CCandUIFnSort( m_pCandUI, this );
  396. if (pObject == NULL) {
  397. return E_OUTOFMEMORY;
  398. }
  399. hr = pObject->QueryInterface( riid, ppvObj );
  400. pObject->Release();
  401. return hr;
  402. }
  403. /* S O R T P R O C */
  404. /*------------------------------------------------------------------------------
  405. perform quick sort
  406. ------------------------------------------------------------------------------*/
  407. void CCandFnSort::SortProc( int iItemFirst, int iItemLast )
  408. {
  409. CCandidateList *pCandList;
  410. int i;
  411. int iItemMid;
  412. if (iItemFirst >= iItemLast) {
  413. return;
  414. }
  415. pCandList = GetCandListMgr()->GetCandList();
  416. Assert( pCandList != NULL );
  417. pCandList->SwapCandidateItem( iItemFirst, (iItemFirst + iItemLast)/2 );
  418. iItemMid = iItemFirst;
  419. for (i = iItemFirst + 1; i <= iItemLast; i++) {
  420. CCandidateItem* pCandItem1 = pCandList->GetCandidateItem( iItemFirst );
  421. CCandidateItem* pCandItem2 = pCandList->GetCandidateItem( i );
  422. int fMoveUp = FALSE;
  423. switch (m_SortType) {
  424. default:
  425. case CANDSORT_NONE:
  426. if (pCandItem1 && pCandItem2)
  427. {
  428. fMoveUp = (pCandItem2->GetICandItemOrg() < pCandItem1->GetICandItemOrg());
  429. }
  430. break;
  431. case CANDSORT_ASCENDING:
  432. case CANDSORT_DESCENDING:
  433. if (pCandItem1 && pCandItem2)
  434. {
  435. LONG lCompareResult;
  436. CCandidateStringEx *pCandStrEx1;
  437. CCandidateStringEx *pCandStrEx2;
  438. pCandStrEx1 = new CCandidateStringEx( pCandItem1 );
  439. pCandStrEx2 = new CCandidateStringEx( pCandItem2 );
  440. if ((m_pSink == NULL) || (m_pSink->CompareItem( pCandStrEx1, pCandStrEx2, &lCompareResult ) != S_OK )) {
  441. lCompareResult = wcscmp(pCandItem1->GetString(), pCandItem2->GetString());
  442. }
  443. if (pCandStrEx1)
  444. pCandStrEx1->Release();
  445. if (pCandStrEx2)
  446. pCandStrEx2->Release();
  447. if (m_SortType == CANDSORT_DESCENDING) {
  448. fMoveUp = (lCompareResult < 0);
  449. }
  450. else {
  451. fMoveUp = (lCompareResult > 0);
  452. }
  453. break;
  454. }
  455. }
  456. if (fMoveUp) {
  457. iItemMid++;
  458. pCandList->SwapCandidateItem( i, iItemMid );
  459. }
  460. }
  461. pCandList->SwapCandidateItem( iItemFirst, iItemMid );
  462. SortProc( iItemFirst, iItemMid-1 );
  463. SortProc( iItemMid+1, iItemLast );
  464. }
  465. /*============================================================================*/
  466. /* */
  467. /* C C A N D F N S O R T */
  468. /* */
  469. /*============================================================================*/
  470. /* C C A N D U I F U N C T I O N M G R */
  471. /*------------------------------------------------------------------------------
  472. ------------------------------------------------------------------------------*/
  473. CCandUIFunctionMgr::CCandUIFunctionMgr( void )
  474. {
  475. m_pCandUI = NULL;
  476. }
  477. /* ~ C C A N D U I F U N C T I O N M G R */
  478. /*------------------------------------------------------------------------------
  479. ------------------------------------------------------------------------------*/
  480. CCandUIFunctionMgr::~CCandUIFunctionMgr( void )
  481. {
  482. }
  483. /* I N I T I A L I Z E */
  484. /*------------------------------------------------------------------------------
  485. ------------------------------------------------------------------------------*/
  486. HRESULT CCandUIFunctionMgr::Initialize( CCandidateUI *pCandUI )
  487. {
  488. m_pCandUI = pCandUI;
  489. m_pFnAutoFilter = new CCandFnAutoFilter( pCandUI );
  490. if (m_pFnAutoFilter == NULL) {
  491. return E_OUTOFMEMORY;
  492. }
  493. m_pFnSort = new CCandFnSort( pCandUI );
  494. if (m_pFnSort == NULL) {
  495. return E_OUTOFMEMORY;
  496. }
  497. return S_OK;
  498. }
  499. /* U N I N I T I A L I Z E */
  500. /*------------------------------------------------------------------------------
  501. ------------------------------------------------------------------------------*/
  502. HRESULT CCandUIFunctionMgr::Uninitialize( void )
  503. {
  504. m_pCandUI = NULL;
  505. if (m_pFnAutoFilter) {
  506. delete m_pFnAutoFilter;
  507. m_pFnAutoFilter = NULL;
  508. }
  509. if (m_pFnSort) {
  510. delete m_pFnSort;
  511. m_pFnSort = NULL;
  512. }
  513. return S_OK;
  514. }
  515. /* G E T O B J E C T */
  516. /*------------------------------------------------------------------------------
  517. ------------------------------------------------------------------------------*/
  518. HRESULT CCandUIFunctionMgr::GetObject( REFIID riid, void **ppvObj )
  519. {
  520. if (ppvObj == NULL) {
  521. return E_INVALIDARG;
  522. }
  523. // create interface object
  524. if (IsEqualGUID( riid, IID_ITfCandUIFnAutoFilter )) {
  525. return m_pFnAutoFilter->CreateInterfaceObject( riid, ppvObj );
  526. }
  527. if (IsEqualGUID( riid, IID_ITfCandUIFnSort )) {
  528. return m_pFnSort->CreateInterfaceObject( riid, ppvObj );
  529. }
  530. return E_FAIL;
  531. }