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.

2127 lines
69 KiB

  1. ///////////////////////////////////////////////////////////
  2. //
  3. //
  4. // AdSearch.cpp - Implementation of the Advanced Search UI
  5. //
  6. // This source file implements the Advanced Search Navigation
  7. // pane class.
  8. ///////////////////////////////////////////////////////////
  9. //
  10. // Include section
  11. //
  12. #include "header.h"
  13. #include "strtable.h" // These headers were copied from search.cpp. Are they all needed?
  14. #include "system.h"
  15. #include "hhctrl.h"
  16. #include "resource.h"
  17. #include "secwin.h"
  18. #include "htmlhelp.h"
  19. #include "cpaldc.h"
  20. #include "fts.h"
  21. #include "TCHAR.h"
  22. #include "parserhh.h"
  23. #include "collect.h"
  24. #include "hhtypes.h"
  25. #include "toc.h"
  26. #include "cctlww.h"
  27. // CFTSListView
  28. #include "listview.h"
  29. // Subsets dialog
  30. #include "csubset.h"
  31. // Our header file.
  32. #include "adsearch.h"
  33. // Get rid of warnings when loading the following.
  34. #undef HDS_HORZ
  35. #undef HDS_BUTTONS
  36. #undef HDS_HIDDEN
  37. //OBM_
  38. // Common Control Macros
  39. #include <windowsx.h>
  40. ///////////////////////////////////////////////////////////
  41. //
  42. // Constants
  43. //
  44. const char c_PersistFolder[] = "AdvSearchUI\\Keywords"; // Holds keyword list.
  45. const char c_PropertiesFolder[] = "AdvSearchUI\\Properties"; //Holds the properties of the dialog
  46. const wchar_t c_KeywordSeparator[] = L"\n";
  47. const int c_KeywordSeparatatorLength = (sizeof(c_KeywordSeparator)/sizeof(c_KeywordSeparator[0]));
  48. const int c_ListViewColumnPadding = 10;
  49. const int c_MaxKeywordsInCombo = 20;
  50. const int c_MaxKeywordLength = 250;
  51. const int c_MaxPersistKeywordBufferSize = c_MaxKeywordsInCombo*(c_MaxKeywordLength + c_KeywordSeparatatorLength)+1 /*Ending NULL*/;
  52. #ifdef __SUBSETS__
  53. // The following contants are the item data for the predefined subsets.
  54. const DWORD c_SubSetEntire = 0xffffffff;
  55. const DWORD c_SubSetPrevious = 0xfffffffe;
  56. const DWORD c_SubSetCurrent = 0xfffffffd;
  57. #endif
  58. // Valid State Properties --- These values are persisted in the Properties folder
  59. enum
  60. {
  61. StateProp_MatchSimilar = 0x00000001,
  62. StateProp_TitlesOnly = 0x00000002,
  63. StateProp_PrevSearch = 0x00000004
  64. };
  65. ///////////////////////////////////////////////////////////
  66. //
  67. // Static Member functions
  68. //
  69. WNDPROC CAdvancedSearchNavPane::s_lpfnlListViewWndProc = NULL;
  70. WNDPROC CAdvancedSearchNavPane::s_lpfnlKeywordComboEditProc = NULL;
  71. WNDPROC CAdvancedSearchNavPane::s_lpfnlKeywordComboProc = NULL;
  72. WNDPROC CAdvancedSearchNavPane::s_lpfnlGenericBtnProc = NULL;
  73. WNDPROC CAdvancedSearchNavPane::s_lpfnlGenericKeyboardProc = NULL;
  74. #ifdef __SUBSETS__
  75. WNDPROC CAdvancedSearchNavPane::s_lpfnlSubsetsComboProc = NULL;
  76. #endif
  77. ///////////////////////////////////////////////////////////
  78. //
  79. // Non-Member helper functions.
  80. //
  81. // Convert a rect from screen to client.
  82. void ScreenRectToClientRect(HWND hWnd, /*in/out*/ RECT* prect);
  83. BOOL WINAPI EnumListViewFont(HWND hwnd, LPARAM lval);
  84. ///////////////////////////////////////////////////////////
  85. //
  86. // Construction
  87. //
  88. ///////////////////////////////////////////////////////////
  89. //
  90. // CAdvancedSearchNavPane();
  91. //
  92. CAdvancedSearchNavPane::CAdvancedSearchNavPane(CHHWinType* pWinType)
  93. : m_hWnd(NULL),
  94. m_hfont(NULL),
  95. m_padding(2), // padding to put around the window
  96. m_hbmConj(NULL),
  97. m_plistview(NULL),
  98. m_hKeywordComboEdit(NULL),
  99. m_dwKeywordComboEditLastSel(0),
  100. m_pWinType(pWinType)
  101. {
  102. ASSERT(pWinType);
  103. m_pTitleCollection = pWinType->m_phmData->m_pTitleCollection;
  104. ASSERT(m_pTitleCollection);
  105. m_NavTabPos = pWinType->tabpos;
  106. }
  107. ///////////////////////////////////////////////////////////
  108. //
  109. // ~CAdvancedSearchNavPane
  110. //
  111. CAdvancedSearchNavPane::~CAdvancedSearchNavPane()
  112. {
  113. //--- Persist Keywords in combo
  114. SaveKeywordCombo();
  115. //--- CleanUp
  116. if (m_hfont)
  117. {
  118. ::DeleteObject(m_hfont);
  119. }
  120. if (m_hbmConj)
  121. {
  122. ::DeleteObject(m_hbmConj);
  123. }
  124. if (m_hWnd)
  125. {
  126. ::DestroyWindow(m_hWnd);
  127. }
  128. if(m_plistview)
  129. {
  130. if (m_plistview->m_pResults != NULL)
  131. {
  132. // Free the results list
  133. //
  134. m_pTitleCollection->m_pFullTextSearch->FreeResults(m_plistview->m_pResults);
  135. }
  136. delete m_plistview;
  137. }
  138. //Don't free m_pTitleCollection
  139. }
  140. ///////////////////////////////////////////////////////////
  141. //
  142. // INavUI Interface functions.
  143. //
  144. ///////////////////////////////////////////////////////////
  145. //
  146. // Create
  147. //
  148. BOOL
  149. CAdvancedSearchNavPane::Create(HWND hwndParent)
  150. {
  151. bool bReturn = false;
  152. if (m_hWnd)
  153. {
  154. return true;
  155. }
  156. // ---Create the dialog.
  157. bool bUnicode = true;
  158. m_hWnd = CreateDialogParamW(
  159. _Module.GetResourceInstance(),
  160. MAKEINTRESOURCEW(IDPAGE_TAB_ADVANCED_SEARCH),
  161. hwndParent,
  162. s_DialogProc,
  163. reinterpret_cast<LPARAM>(this)); // Pass over the this pointer.
  164. if (!m_hWnd)
  165. {
  166. bUnicode = false;
  167. m_hWnd = CreateDialogParamA(
  168. _Module.GetResourceInstance(),
  169. MAKEINTRESOURCEA(IDPAGE_TAB_ADVANCED_SEARCH),
  170. hwndParent,
  171. s_DialogProc,
  172. reinterpret_cast<LPARAM>(this)); // Pass over the this pointer.
  173. }
  174. ASSERT(m_hWnd);
  175. //--- Initialize the DlgItem Array.
  176. InitDlgItemArray();
  177. //--- Initialize the bitmap button.
  178. m_hbmConj = ::LoadBitmap(NULL, MAKEINTRESOURCE(OBM_MNARROW));
  179. ASSERT(m_hbmConj);
  180. // Set the bitmap.
  181. ::SendMessage(m_aDlgItems[c_ConjunctionBtn].m_hWnd,
  182. BM_SETIMAGE,
  183. IMAGE_BITMAP,
  184. reinterpret_cast<LONG_PTR>(m_hbmConj));
  185. // Get the size of the bitmap.
  186. BITMAP bm;
  187. GetObject(m_hbmConj, sizeof(BITMAP), &bm);
  188. // Get the width of a 3-d border.
  189. int cxEdge = GetSystemMetrics(SM_CXEDGE);
  190. int cyEdge = GetSystemMetrics(SM_CYEDGE);
  191. // Set the new size.
  192. SetWindowPos( m_aDlgItems[c_ConjunctionBtn].m_hWnd, NULL,
  193. 0,0, //Don't change position.
  194. bm.bmWidth+cxEdge, bm.bmHeight+cyEdge, // Change width and height.
  195. SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
  196. //--- Initialize the results list
  197. W_EnableUnicode(m_aDlgItems[c_ResultsList].m_hWnd, W_ListView);
  198. // W_ListView_SetExtendedListViewStyle(m_aDlgItems[c_ResultsList].m_hWnd, LVS_EX_FULLROWSELECT);
  199. W_ListView_SetExtendedListViewStyle(m_aDlgItems[c_ResultsList].m_hWnd, LVS_EX_FULLROWSELECT | g_RTL_Style);
  200. // Create the listview object which will manage the list for us.
  201. m_plistview = new CFTSListView(m_pTitleCollection, m_aDlgItems[c_ResultsList].m_hWnd, true);
  202. // Sub-class the list view
  203. if (s_lpfnlListViewWndProc == NULL)
  204. {
  205. s_lpfnlListViewWndProc = W_GetWndProc(m_aDlgItems[c_ResultsList].m_hWnd, bUnicode);
  206. }
  207. W_SubClassWindow(m_aDlgItems[c_ResultsList].m_hWnd, reinterpret_cast<LONG_PTR>(s_ListViewProc), bUnicode);
  208. SETTHIS(m_aDlgItems[c_ResultsList].m_hWnd);
  209. #ifdef __SUBSETS__
  210. //--- Initalize the Search In combo box.
  211. int index = ComboBox_AddString(m_aDlgItems[c_SubsetsCombo].m_hWnd, GetStringResource(IDS_ADVSEARCH_SEARCHIN_PREVIOUS));
  212. ComboBox_SetItemData(m_aDlgItems[c_SubsetsCombo].m_hWnd, index, c_SubSetPrevious);
  213. //--- Add other pre-defined or user defined subsets. <mc>
  214. UpdateSSCombo(true);
  215. #endif
  216. //--- Initialize the Keyword combo box.
  217. // Limit the amount of text which can be typed in.
  218. int iret = ComboBox_LimitText(m_aDlgItems[c_KeywordCombo].m_hWnd,c_MaxKeywordLength-1);
  219. // Subclass the keyword combo so that we can process the keys
  220. if (s_lpfnlKeywordComboProc == NULL)
  221. {
  222. s_lpfnlKeywordComboProc = W_GetWndProc(m_aDlgItems[c_KeywordCombo].m_hWnd, bUnicode);
  223. }
  224. W_SubClassWindow(m_aDlgItems[c_KeywordCombo].m_hWnd, reinterpret_cast<LONG_PTR>(s_KeywordComboProc), bUnicode);
  225. SETTHIS(m_aDlgItems[c_KeywordCombo].m_hWnd);
  226. // Subclass the keyword combo edit ctrl so that we can keep the current selection around.
  227. // The edit control is the child of the combobox with the id 1001.
  228. m_hKeywordComboEdit = ::GetDlgItem(m_aDlgItems[c_KeywordCombo].m_hWnd,1001);
  229. if (s_lpfnlKeywordComboEditProc == NULL)
  230. {
  231. s_lpfnlKeywordComboEditProc = W_GetWndProc(m_hKeywordComboEdit, bUnicode);
  232. }
  233. W_SubClassWindow(m_hKeywordComboEdit, reinterpret_cast<LONG_PTR>(s_KeywordComboEditProc), bUnicode);
  234. SETTHIS(m_hKeywordComboEdit);
  235. // font for the combo/EC...
  236. SendMessage(m_hKeywordComboEdit, WM_SETFONT, (WPARAM) GetFont(), FALSE);
  237. if(g_fBiDi)
  238. {
  239. SetWindowLong(m_hKeywordComboEdit, GWL_STYLE,
  240. GetWindowLong(m_hKeywordComboEdit, GWL_STYLE) & ~(ES_LEFT));
  241. SetWindowLong(m_hKeywordComboEdit, GWL_STYLE,
  242. GetWindowLong(m_hKeywordComboEdit, GWL_STYLE) | ES_RIGHT);
  243. SetWindowLong(m_hKeywordComboEdit, GWL_EXSTYLE,
  244. GetWindowLong(m_hKeywordComboEdit, GWL_EXSTYLE) | g_RTL_Style);
  245. }
  246. else
  247. {
  248. SetWindowLong(m_hKeywordComboEdit, GWL_EXSTYLE,
  249. GetWindowLong(m_hKeywordComboEdit, GWL_EXSTYLE) & ~(WS_EX_RTLREADING | WS_EX_RIGHT));
  250. SetWindowLong(m_hKeywordComboEdit, GWL_STYLE,
  251. GetWindowLong(m_hKeywordComboEdit, GWL_STYLE) & ~(ES_RIGHT));
  252. }
  253. //--- Subclass all of the buttons
  254. // Start with the StartSearch button;
  255. if (s_lpfnlGenericBtnProc == NULL)
  256. {
  257. s_lpfnlGenericBtnProc = W_GetWndProc(m_aDlgItems[c_SearchBtn].m_hWnd, bUnicode);
  258. }
  259. W_SubClassWindow(m_aDlgItems[c_SearchBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
  260. SETTHIS(m_aDlgItems[c_SearchBtn].m_hWnd);
  261. // Bitmap btn
  262. W_SubClassWindow(m_aDlgItems[c_ConjunctionBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
  263. SETTHIS(m_aDlgItems[c_ConjunctionBtn].m_hWnd);
  264. // c_DisplayBtn
  265. W_SubClassWindow(m_aDlgItems[c_DisplayBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
  266. SETTHIS(m_aDlgItems[c_DisplayBtn].m_hWnd);
  267. #ifdef __SUBSETS__
  268. // c_SubsetsBtn
  269. W_SubClassWindow(m_aDlgItems[c_SubsetsBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
  270. SETTHIS(m_aDlgItems[c_SubsetsBtn].m_hWnd);
  271. #endif
  272. //--- Subclass all of the check boxes for generic keyboard handling.
  273. //--- Init Similar Words Checkbox.
  274. // Turn on the checkbox
  275. Button_SetCheck(m_aDlgItems[c_SimilarCheck].m_hWnd, true);
  276. // Subclass c_SimilarCheck
  277. if (NULL == s_lpfnlGenericKeyboardProc)
  278. {
  279. s_lpfnlGenericKeyboardProc = W_GetWndProc(m_aDlgItems[c_SimilarCheck].m_hWnd, bUnicode);
  280. }
  281. W_SubClassWindow(m_aDlgItems[c_SimilarCheck].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericKeyboardProc), bUnicode);
  282. SETTHIS(m_aDlgItems[c_SimilarCheck].m_hWnd);
  283. // Subclass c_TitlesOnlyCheck
  284. W_SubClassWindow(m_aDlgItems[c_TitlesOnlyCheck].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericKeyboardProc), bUnicode);
  285. SETTHIS(m_aDlgItems[c_TitlesOnlyCheck].m_hWnd);
  286. #ifndef __SUBSETS__
  287. // Subclass c_TitlesOnlyCheck
  288. W_SubClassWindow(m_aDlgItems[c_PreviousCheck].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericKeyboardProc), bUnicode);
  289. SETTHIS(m_aDlgItems[c_PreviousCheck].m_hWnd);
  290. #else //__SUBSETS__
  291. //--- Subclass the edit control part of c_SubsetsCombo
  292. // The edit control is the child of the combobox with the id 1001.
  293. if (NULL == s_lpfnlSubsetsComboProc)
  294. {
  295. s_lpfnlSubsetsComboProc = W_GetWndProc(m_aDlgItems[c_SubsetsCombo].m_hWnd, bUnicode);
  296. }
  297. W_SubClassWindow(m_aDlgItems[c_SubsetsCombo].m_hWnd, reinterpret_cast<LONG_PTR>(s_SubsetsComboProc), bUnicode);
  298. SETTHIS(m_aDlgItems[c_SubsetsCombo].m_hWnd);
  299. #endif
  300. //--- Set the font. This will fix some dbcs issues.
  301. for (int i = 0; i < c_NumDlgItems; i++)
  302. {
  303. if ( m_aDlgItems[i].m_id != IDC_ADVSRC_KEYWORD_COMBO )
  304. SendMessage(m_aDlgItems[i].m_hWnd, WM_SETFONT, (WPARAM) _Resource.GetUIFont(), FALSE);
  305. }
  306. // Now set the font for the part of the UI that will come from the CHM file.
  307. SendMessage(m_plistview->m_hwndListView, WM_SETFONT, (WPARAM) GetAccessableContentFont(), FALSE);
  308. // Make sure the list header uses a normal font
  309. EnumChildWindows(m_plistview->m_hwndListView, (WNDENUMPROC) EnumListViewFont, 0);
  310. //--- Fill the combobox with persisted data.
  311. LoadKeywordCombo();
  312. //TODO: Fix
  313. return true;
  314. }
  315. BOOL WINAPI EnumListViewFont(HWND hwnd, LPARAM lParam)
  316. {
  317. char szClass[MAX_PATH];
  318. VERIFY(GetClassName(hwnd, szClass, sizeof(szClass)));
  319. if (IsSamePrefix(szClass, "SysHeader32"))
  320. SendMessage(hwnd, WM_SETFONT, (WPARAM) _Resource.GetUIFont(), FALSE);
  321. return TRUE;
  322. }
  323. ///////////////////////////////////////////////////////////
  324. //
  325. // OnCommand
  326. //
  327. LRESULT
  328. CAdvancedSearchNavPane::OnCommand(HWND hwnd, UINT id, UINT NotifyCode, LPARAM lParam)
  329. {
  330. switch(NotifyCode)
  331. {
  332. case BN_CLICKED:
  333. switch(id)
  334. {
  335. case IDC_ADVSRC_SEARCH_BTN:
  336. OnStartSearch();
  337. break;
  338. case IDC_ADVSRC_DISPLAY_BTN:
  339. OnDisplayTopic();
  340. break;
  341. #ifdef __SUBSETS__
  342. case IDC_ADVSRC_SUBSET_BTN:
  343. OnDefineSubsets();
  344. break;
  345. #endif
  346. case IDC_ADVSRC_CONJUNCTIONS_BTN:
  347. OnConjunctions();
  348. break;
  349. default:
  350. return 0;
  351. }
  352. return 1;
  353. case CBN_EDITCHANGE:
  354. if (id == IDC_ADVSRC_KEYWORD_COMBO)
  355. {
  356. // Text in keyword combo has changed. dis/enable Start Search Button.
  357. EnableDlgItem(c_SearchBtn, W_HasText(reinterpret_cast<HWND>(lParam)) ? true : false);
  358. return 1;
  359. }
  360. break;
  361. case CBN_SELENDOK:
  362. if (id == IDC_ADVSRC_KEYWORD_COMBO)
  363. {
  364. EnableDlgItem(c_SearchBtn, TRUE);
  365. return 1;
  366. }
  367. break;
  368. }
  369. return 0;
  370. }
  371. ///////////////////////////////////////////////////////////
  372. //
  373. // ResizeWindow
  374. //
  375. void
  376. CAdvancedSearchNavPane::ResizeWindow()
  377. {
  378. ASSERT(::IsValidWindow(m_hWnd));
  379. // Resize to fit the client area of the parent.
  380. HWND hwndParent = ::GetParent(m_hWnd);
  381. ASSERT(::IsValidWindow(hwndParent));
  382. //--- Get the size of the window
  383. RECT rcParent;
  384. GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
  385. //--- Move and size the dialog box itself.
  386. ::SetWindowPos( m_hWnd, NULL, rcParent.left, rcParent.top,
  387. rcParent.right-rcParent.left,
  388. rcParent.bottom-rcParent.top,
  389. SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOREDRAW);
  390. //---Fix the painting bugs. However, this is a little on the flashy side.
  391. ::InvalidateRect(m_hWnd, NULL, TRUE);
  392. RECT rcDlg;
  393. ::GetClientRect(m_hWnd, &rcDlg);
  394. //--- Now position each control within this space.
  395. for (int i = 0; i < c_NumDlgItems; i++)
  396. {
  397. // Get Current Settings.
  398. int X = m_aDlgItems[i].m_rectCur.left;
  399. int Y = m_aDlgItems[i].m_rectCur.top;
  400. int CX = m_aDlgItems[i].m_rectCur.right - m_aDlgItems[i].m_rectCur.left;
  401. int CY = m_aDlgItems[i].m_rectCur.bottom - m_aDlgItems[i].m_rectCur.top;
  402. bool bChanged = false;
  403. //--- RIGHT JUSTIFICATION
  404. if (m_aDlgItems[i].m_JustifyH == Justify::Right)
  405. {
  406. int NewX = rcDlg.right-m_aDlgItems[i].m_iOffsetH; // subtract the offset
  407. int MinX = m_aDlgItems[i].m_rectMin.left;
  408. if (NewX < MinX)
  409. {
  410. NewX = MinX; // Don't go below min.
  411. }
  412. if (X != NewX)
  413. {
  414. X = NewX; // Update the current setting.
  415. bChanged = true;
  416. }
  417. }
  418. //--- LEFT JUSTIFICATION
  419. if (m_aDlgItems[i].m_JustifyH == Justify::Left)
  420. {
  421. int MinX = m_aDlgItems[i].m_rectMin.left;
  422. int NewX = rcDlg.left;
  423. if (NewX < MinX)
  424. {
  425. NewX = MinX; // Don't go below min.
  426. }
  427. if (X != NewX)
  428. {
  429. X = NewX; // Update the current setting.
  430. bChanged = true;
  431. }
  432. }
  433. //--- BOTTOM JUSTIFICATION
  434. if (m_aDlgItems[i].m_JustifyV == Justify::Bottom)
  435. {
  436. int NewY = rcDlg.bottom - m_aDlgItems[i].m_iOffsetV;
  437. int MinY = m_aDlgItems[i].m_rectMin.top;
  438. if (NewY < MinY)
  439. {
  440. NewY = MinY;
  441. }
  442. if (Y != NewY)
  443. {
  444. Y = NewY; // Update Setting.
  445. bChanged = true;
  446. }
  447. }
  448. //--- HORIZONTAL GROWING
  449. if (m_aDlgItems[i].m_bGrowH)
  450. {
  451. int MaxCX = m_aDlgItems[i].m_rectMax.right - m_aDlgItems[i].m_rectMax.left;
  452. int MinCX = m_aDlgItems[i].m_rectMin.right - m_aDlgItems[i].m_rectMin.left;
  453. int MinCY = m_aDlgItems[i].m_rectMin.bottom - m_aDlgItems[i].m_rectMin.top;
  454. int NewRight = rcDlg.right - m_aDlgItems[i].m_iPadH;
  455. int NewCX = NewRight - m_aDlgItems[i].m_rectMin.left;
  456. if (NewCX < MinCX)
  457. {
  458. NewCX = MinCX;
  459. }
  460. else if ((!m_aDlgItems[i].m_bIgnoreMax) && NewCX > MaxCX)
  461. {
  462. NewCX = MaxCX;
  463. }
  464. if (CX != NewCX)
  465. {
  466. CX = NewCX; // Update Current;
  467. bChanged = true;
  468. }
  469. }
  470. //--- VERTICAL GROWING
  471. if (m_aDlgItems[i].m_bGrowV)
  472. {
  473. int MaxCY = m_aDlgItems[i].m_rectMax.bottom - m_aDlgItems[i].m_rectMax.top;
  474. int MinCY = m_aDlgItems[i].m_rectMin.bottom - m_aDlgItems[i].m_rectMin.top;
  475. int MinCX = m_aDlgItems[i].m_rectMin.right - m_aDlgItems[i].m_rectMin.left;
  476. int NewBottom = rcDlg.bottom - m_aDlgItems[i].m_iPadV;
  477. int NewCY = NewBottom - m_aDlgItems[i].m_rectMin.top;
  478. if (NewCY < MinCY)
  479. {
  480. NewCY = MinCY;
  481. }
  482. else if ((!m_aDlgItems[i].m_bIgnoreMax) && NewCY > MaxCY)
  483. {
  484. NewCY = MaxCY;
  485. }
  486. if (CY != NewCY)
  487. {
  488. CY = NewCY;
  489. bChanged = true;
  490. }
  491. }
  492. if (bChanged)
  493. {
  494. m_aDlgItems[i].m_rectCur.left = X;
  495. m_aDlgItems[i].m_rectCur.top = Y;
  496. m_aDlgItems[i].m_rectCur.right = X + CX;
  497. m_aDlgItems[i].m_rectCur.bottom = Y + CY;
  498. ::SetWindowPos(m_aDlgItems[i].m_hWnd, NULL,
  499. X, Y, CX, CY,
  500. SWP_NOZORDER | SWP_NOOWNERZORDER /*| SWP_NOREDRAW*/);
  501. // If we have to change the size of the results list, lets change the size of the columns.
  502. if (i == c_ResultsList)
  503. {
  504. m_plistview->SizeColumns();
  505. }
  506. }
  507. }
  508. }
  509. ///////////////////////////////////////////////////////////
  510. //
  511. // HideWindow
  512. //
  513. void
  514. CAdvancedSearchNavPane::HideWindow()
  515. {
  516. if (::IsValidWindow(m_hWnd))
  517. {
  518. ::ShowWindow(m_hWnd, SW_HIDE);
  519. }
  520. }
  521. ///////////////////////////////////////////////////////////
  522. //
  523. // ShowWindow
  524. //
  525. void
  526. CAdvancedSearchNavPane::ShowWindow()
  527. {
  528. if (::IsValidWindow(m_hWnd))
  529. {
  530. // Turn the dialog items on/off
  531. ShowDlgItemsEnabledState();
  532. // Show the dialog window.
  533. ::ShowWindow(m_hWnd, SW_SHOW);
  534. ::SetFocus(m_aDlgItems[c_KeywordCombo].m_hWnd);
  535. }
  536. }
  537. ///////////////////////////////////////////////////////////
  538. //
  539. // SetPadding
  540. //
  541. void
  542. CAdvancedSearchNavPane::SetPadding(int pad)
  543. {
  544. m_padding = pad;
  545. }
  546. ///////////////////////////////////////////////////////////
  547. //
  548. // SetTabPos
  549. //
  550. void
  551. CAdvancedSearchNavPane::SetTabPos(int tabpos)
  552. {
  553. m_NavTabPos = tabpos;
  554. }
  555. ///////////////////////////////////////////////////////////
  556. //
  557. // SetDefaultFocus --- Set focus to the most expected control, usually edit combo.
  558. //
  559. void
  560. CAdvancedSearchNavPane::SetDefaultFocus()
  561. {
  562. if (::IsValidWindow(m_aDlgItems[c_KeywordCombo].m_hWnd))
  563. {
  564. ::SetFocus(m_aDlgItems[c_KeywordCombo].m_hWnd);
  565. }
  566. }
  567. ///////////////////////////////////////////////////////////
  568. //
  569. // ProcessMenuChar --- Process accelerator keys.
  570. //
  571. bool
  572. CAdvancedSearchNavPane::ProcessMenuChar(HWND hwndParent, int ch)
  573. {
  574. return ::ProcessMenuChar(this, hwndParent, m_aDlgItems, c_NumDlgItems, ch);
  575. }
  576. ///////////////////////////////////////////////////////////
  577. //
  578. // OnNotify --- Process WM_NOTIFY messages. Used by embedded Tree and List view controls.
  579. //
  580. LRESULT
  581. CAdvancedSearchNavPane::OnNotify(HWND hwnd, WPARAM idCtrl, LPARAM lParam)
  582. {
  583. switch(idCtrl)
  584. {
  585. case IDC_ADVSRC_RESULTS_LIST:
  586. if (m_plistview && ::IsValidWindow(m_aDlgItems[c_ResultsList].m_hWnd))
  587. {
  588. return m_plistview->ListViewMsg(m_aDlgItems[c_ResultsList].m_hWnd, (NM_LISTVIEW*) lParam);
  589. }
  590. break;
  591. case IDC_ADVSRC_KEYWORD_COMBO:
  592. break;
  593. default:
  594. //return DefDlgProc(m_hWnd, WM_NOTIFY, idCtrl, lParam);
  595. return 0;
  596. }
  597. return 0;
  598. }
  599. ///////////////////////////////////////////////////////////
  600. //
  601. // OnDrawItem --- Process WM_DRAWITEM messages.
  602. //
  603. void
  604. CAdvancedSearchNavPane::OnDrawItem(UINT id, LPDRAWITEMSTRUCT pdis)
  605. {
  606. }
  607. ///////////////////////////////////////////////////////////
  608. //
  609. // Seed --- Seed the nav ui with a search term or keyword.
  610. //
  611. void
  612. CAdvancedSearchNavPane::Seed(LPCSTR pszSeed)
  613. {
  614. }
  615. ///////////////////////////////////////////////////////////
  616. //
  617. // Helper Functions.
  618. //
  619. ///////////////////////////////////////////////////////////
  620. //
  621. // InitDlgItemArray
  622. //
  623. void
  624. CAdvancedSearchNavPane::InitDlgItemArray()
  625. {
  626. RECT rectCurrent;
  627. RECT rectDlg;
  628. ::GetClientRect(m_hWnd, &rectDlg);
  629. //--- Setup the dlg array for each control.
  630. //--- Conj menu button
  631. int i = c_ConjunctionBtn;
  632. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_CONJUNCTIONS_BTN);
  633. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent); // Get screen coordinates.
  634. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  635. m_aDlgItems[i].m_id = IDC_ADVSRC_CONJUNCTIONS_BTN;
  636. m_aDlgItems[i].m_accelkey = 0; // No accelerator.
  637. m_aDlgItems[i].m_Type = ItemInfo::Button;
  638. m_aDlgItems[i].m_bIgnoreEnabled = TRUE;
  639. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  640. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  641. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  642. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  643. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  644. //m_aDlgItems[i].m_iOffsetV =; // Distance from our justification point.
  645. if(g_bArabicUi)
  646. {
  647. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  648. m_aDlgItems[i].m_iOffsetH = rectCurrent.left - rectDlg.left;
  649. }
  650. else
  651. {
  652. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  653. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  654. }
  655. //m_aDlgItems[i].m_iPadH =; // Right Horizontal Padding.
  656. //m_aDlgItems[i].m_iPadV =; // Bottom Vertical Padding.
  657. m_aDlgItems[i].m_rectMin = rectCurrent;
  658. m_aDlgItems[i].m_rectCur = rectCurrent;
  659. //m_aDlgItems[i].m_rectMax; // Max size.
  660. //--- Search Term Combo
  661. i = c_KeywordCombo;
  662. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_KEYWORD_COMBO);
  663. ::GetWindowRect(m_aDlgItems[i].m_hWnd , &rectCurrent); // Get screen coordinates.
  664. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  665. m_aDlgItems[i].m_id = IDC_ADVSRC_KEYWORD_COMBO;
  666. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hWnd, IDC_ADVSRC_KEYWORD_STATIC);
  667. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  668. m_aDlgItems[i].m_bIgnoreEnabled = TRUE;
  669. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  670. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  671. m_aDlgItems[i].m_bGrowH = TRUE; // Grow Horizontally.
  672. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  673. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  674. //m_aDlgItems[i].m_iOffsetV =; // Distance from our justification point.
  675. if(g_bBiDiUi)
  676. {
  677. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  678. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  679. m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  680. }
  681. else
  682. {
  683. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  684. //m_aDlgItems[i].m_iOffsetH;
  685. m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  686. }
  687. //m_aDlgItems[i].m_iPadV =;
  688. m_aDlgItems[i].m_rectMin = rectCurrent;
  689. m_aDlgItems[i].m_rectCur = rectCurrent;
  690. //m_aDlgItems[i].m_rectMax; // Max size.
  691. //--- Start Search Button
  692. i = c_SearchBtn;
  693. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_SEARCH_BTN);
  694. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent); // Get screen coordinates.
  695. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  696. m_aDlgItems[i].m_id = IDC_ADVSRC_SEARCH_BTN;
  697. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd);
  698. m_aDlgItems[i].m_Type = ItemInfo::Button;
  699. m_aDlgItems[i].m_bIgnoreEnabled = FALSE;
  700. m_aDlgItems[i].m_bEnabled = FALSE; // Is the control enabled?
  701. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  702. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  703. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  704. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  705. //m_aDlgItems[i].m_iOffsetV =; // Distance from our justification point.
  706. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  707. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  708. // m_aDlgItems[i].m_iPadH = rectDlg.right = rectCurrent.right;
  709. //m_aDlgItems[i].m_iPadV =;
  710. m_aDlgItems[i].m_rectMin = rectCurrent;
  711. m_aDlgItems[i].m_rectCur = rectCurrent;
  712. //m_aDlgItems[i].m_rectMax; // Max size.
  713. //--- Display Topics Button
  714. i = c_DisplayBtn;
  715. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_DISPLAY_BTN);
  716. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent); // Get screen coordinates.
  717. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  718. m_aDlgItems[i].m_id = IDC_ADVSRC_DISPLAY_BTN;
  719. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd);
  720. m_aDlgItems[i].m_Type = ItemInfo::Button;
  721. m_aDlgItems[i].m_bIgnoreEnabled = FALSE;
  722. m_aDlgItems[i].m_bEnabled = FALSE; // Is the control enabled?
  723. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  724. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  725. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  726. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  727. //m_aDlgItems[i].m_iOffsetV =; // Distance from our justification point.
  728. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  729. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  730. // m_aDlgItems[i].m_iPadH = 0;
  731. //m_aDlgItems[i].m_iPadV =;
  732. m_aDlgItems[i].m_rectMin = rectCurrent;
  733. m_aDlgItems[i].m_rectCur = rectCurrent;
  734. //m_aDlgItems[i].m_rectMax; // Max size.
  735. //--- Found Static Text
  736. i = c_FoundStatic;
  737. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_FOUND_STATIC);
  738. ::GetWindowRect(m_aDlgItems[i].m_hWnd , &rectCurrent); // Get screen coordinates.
  739. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  740. m_aDlgItems[i].m_id = IDC_ADVSRC_FOUND_STATIC;
  741. m_aDlgItems[i].m_accelkey = 0;
  742. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  743. m_aDlgItems[i].m_bIgnoreEnabled = TRUE;
  744. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  745. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  746. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  747. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  748. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  749. //m_aDlgItems[i].m_iOffsetV =; // Distance from our justification point.
  750. // if(g_bBiDiUi)
  751. // {
  752. // m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  753. // m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.right;
  754. // }
  755. // else
  756. // {
  757. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  758. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  759. // }
  760. //aDlgItems[i].m_iPadH
  761. //m_aDlgItems[i].m_iPadV =;
  762. m_aDlgItems[i].m_rectMin = rectCurrent;
  763. m_aDlgItems[i].m_rectCur = rectCurrent;
  764. //m_aDlgItems[i].m_rectMax; // Max size.
  765. //--- Results List
  766. i= c_ResultsList;
  767. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_RESULTS_LIST);
  768. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent); // Get screen coordinates.
  769. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  770. m_aDlgItems[i].m_id = IDC_ADVSRC_RESULTS_LIST;
  771. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hWnd, IDC_ADVSRC_STATIC_SELECT); // Associated static ctrl
  772. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  773. m_aDlgItems[i].m_bIgnoreEnabled = FALSE;
  774. m_aDlgItems[i].m_bEnabled = FALSE; // Is the control enabled?
  775. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  776. m_aDlgItems[i].m_bGrowH = TRUE; // Grow Horizontally.
  777. m_aDlgItems[i].m_bGrowV = TRUE; // Grow Vertically.
  778. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  779. //m_aDlgItems[i].m_iOffsetV =; // Distance from our justification point.
  780. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  781. //m_aDlgItems[i].m_iOffsetH;
  782. m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  783. m_aDlgItems[i].m_iPadV = rectDlg.bottom - rectCurrent.bottom;
  784. m_aDlgItems[i].m_rectMin = rectCurrent;
  785. m_aDlgItems[i].m_rectCur = rectCurrent;
  786. //m_aDlgItems[i].m_rectMax; // Max size.
  787. #ifdef __SUBSETS__
  788. //--- Search In Static Text
  789. i = c_SearchInStatic;
  790. m_aDlgItems[i].m_hWnd= ::GetDlgItem(m_hWnd, IDC_ADVSRC_SEARCHIN_STATIC);
  791. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent); // Get screen coordinates.
  792. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  793. m_aDlgItems[i].m_id = IDC_ADVSRC_SEARCHIN_STATIC;
  794. m_aDlgItems[i].m_accelkey = 0;
  795. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  796. m_aDlgItems[i].m_bIgnoreEnabled = TRUE;
  797. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  798. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  799. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  800. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  801. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  802. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top; // Distance from our justification point.
  803. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  804. //m_aDlgItems[i].m_iOffsetH;
  805. //m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  806. //m_aDlgItems[i].m_iPadV =;
  807. m_aDlgItems[i].m_rectMin = rectCurrent;
  808. m_aDlgItems[i].m_rectCur = rectCurrent;
  809. //m_aDlgItems[i].m_rectMax; // Max size.
  810. //--- Search In Combo
  811. i = c_SubsetsCombo;
  812. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_SUBSET_COMBO);
  813. ::GetWindowRect(m_aDlgItems[i].m_hWnd , &rectCurrent); // Get screen coordinates.
  814. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  815. m_aDlgItems[i].m_id = IDC_ADVSRC_SUBSET_COMBO;
  816. m_aDlgItems[i].m_accelkey = GetAcceleratorKey(m_hWnd, IDC_ADVSRC_SEARCHIN_STATIC); // Associated static ctrl
  817. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  818. m_aDlgItems[i].m_bIgnoreEnabled = true;
  819. m_aDlgItems[i].m_bEnabled = false; // Is the control enabled?
  820. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  821. m_aDlgItems[i].m_bGrowH = TRUE; // Grow Horizontally.
  822. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  823. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  824. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top; // Distance from our justification point.
  825. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  826. //m_aDlgItems[i].m_iOffsetH;
  827. m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  828. //m_aDlgItems[i].m_iPadV =;
  829. m_aDlgItems[i].m_rectMin = rectCurrent;
  830. m_aDlgItems[i].m_rectCur = rectCurrent;
  831. //m_aDlgItems[i].m_rectMax; // Max size.
  832. //--- Define Subset Button
  833. i = c_SubsetsBtn;
  834. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_SUBSET_BTN);
  835. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent); // Get screen coordinates.
  836. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  837. m_aDlgItems[i].m_id = IDC_ADVSRC_SUBSET_BTN;
  838. m_aDlgItems[i].m_accelkey = GetAcceleratorKey(m_aDlgItems[i].m_hWnd);
  839. m_aDlgItems[i].m_Type = ItemInfo::Button;
  840. m_aDlgItems[i].m_bIgnoreEnabled = TRUE; //TODO: Implement this control
  841. m_aDlgItems[i].m_bEnabled = false; // Is the control enabled?
  842. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  843. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  844. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  845. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  846. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top; // Distance from our justification point.
  847. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  848. m_aDlgItems[i].m_iOffsetH =rectDlg.right - rectCurrent.left;
  849. //m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  850. //m_aDlgItems[i].m_iPadV =;
  851. m_aDlgItems[i].m_rectMin = rectCurrent;
  852. m_aDlgItems[i].m_rectCur = rectCurrent;
  853. //m_aDlgItems[i].m_rectMax; // Max size.
  854. #else
  855. //--- IDC_ADVSRC_PREVIOUS_CHECK
  856. i = c_PreviousCheck;
  857. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_PREVIOUS_CHECK);
  858. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent); // Get screen coordinates.
  859. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  860. m_aDlgItems[i].m_id = IDC_ADVSRC_PREVIOUS_CHECK;
  861. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd);
  862. m_aDlgItems[i].m_Type = ItemInfo::CheckBox;
  863. m_aDlgItems[i].m_bIgnoreEnabled = TRUE;
  864. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  865. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  866. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  867. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  868. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  869. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top; // Distance from our justification point.
  870. if(g_bBiDiUi)
  871. {
  872. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left; // Maintain same distance. If someone to the right grows we are broken.
  873. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  874. }
  875. else
  876. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  877. //m_aDlgItems[i].m_iOffsetH;
  878. //m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  879. //m_aDlgItems[i].m_iPadV =;
  880. m_aDlgItems[i].m_rectMin = rectCurrent;
  881. m_aDlgItems[i].m_rectCur = rectCurrent;
  882. //m_aDlgItems[i].m_rectMax; // Max size.
  883. #endif
  884. //--- IDC_ADVSRC_SIMILAR_CHECK
  885. i = c_SimilarCheck;
  886. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_SIMILAR_CHECK);
  887. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent); // Get screen coordinates.
  888. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  889. m_aDlgItems[i].m_id = IDC_ADVSRC_SIMILAR_CHECK;
  890. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd);
  891. m_aDlgItems[i].m_Type = ItemInfo::CheckBox;
  892. m_aDlgItems[i].m_bIgnoreEnabled = TRUE;
  893. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  894. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  895. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  896. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  897. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  898. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top; // Distance from our justification point.
  899. if(g_bBiDiUi)
  900. {
  901. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left; // Maintain same distance. If someone to the right grows we are broken.
  902. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  903. }
  904. else
  905. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  906. //m_aDlgItems[i].m_iOffsetH;
  907. //m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  908. //m_aDlgItems[i].m_iPadV =;
  909. m_aDlgItems[i].m_rectMin = rectCurrent;
  910. m_aDlgItems[i].m_rectCur = rectCurrent;
  911. //m_aDlgItems[i].m_rectMax; // Max size.
  912. //--- IDC_OPTIONS_CHECK_TITLESONLY
  913. i = c_TitlesOnlyCheck;
  914. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_TITLESONLY_CHECK);
  915. ::GetWindowRect(m_aDlgItems[i].m_hWnd , &rectCurrent); // Get screen coordinates.
  916. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  917. m_aDlgItems[i].m_id = IDC_ADVSRC_TITLESONLY_CHECK;
  918. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd);
  919. m_aDlgItems[i].m_Type = ItemInfo::CheckBox;
  920. m_aDlgItems[i].m_bIgnoreEnabled = TRUE;
  921. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  922. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  923. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  924. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  925. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  926. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top; // Distance from our justification point.
  927. if(g_bBiDiUi)
  928. {
  929. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left; // Maintain same distance. If someone to the right grows we are broken.
  930. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  931. }
  932. else
  933. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  934. //m_aDlgItems[i].m_iOffsetH;
  935. //m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  936. //m_aDlgItems[i].m_iPadV =;
  937. m_aDlgItems[i].m_rectMin = rectCurrent;
  938. m_aDlgItems[i].m_rectCur = rectCurrent;
  939. //m_aDlgItems[i].m_rectMax; // Max size.
  940. //--- Type in words static text
  941. i = c_TypeInWordsStatic;
  942. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_ADVSRC_KEYWORD_STATIC);
  943. ::GetWindowRect(m_aDlgItems[i].m_hWnd , &rectCurrent); // Get screen coordinates.
  944. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  945. m_aDlgItems[i].m_id = IDC_ADVSRC_KEYWORD_STATIC;
  946. m_aDlgItems[i].m_accelkey = 0;
  947. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  948. m_aDlgItems[i].m_bIgnoreEnabled = TRUE;
  949. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  950. m_aDlgItems[i].m_bIgnoreMax = TRUE; // Ignore the Max parameter.
  951. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  952. m_aDlgItems[i].m_bGrowV = FALSE; // Grow Vertically.
  953. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  954. if(g_bBiDiUi)
  955. {
  956. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  957. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  958. }
  959. else
  960. {
  961. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  962. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.right;
  963. }
  964. //aDlgItems[i].m_iPadH
  965. //m_aDlgItems[i].m_iPadV =;
  966. m_aDlgItems[i].m_rectMin = rectCurrent;
  967. m_aDlgItems[i].m_rectCur = rectCurrent;
  968. }
  969. ///////////////////////////////////////////////////////////
  970. //
  971. // SetEnabledState
  972. //
  973. void
  974. CAdvancedSearchNavPane::ShowDlgItemsEnabledState()
  975. {
  976. // Enable/Disable all the controls
  977. for (int i = 0; i < c_NumDlgItems; i++)
  978. {
  979. if (!m_aDlgItems[i].m_bIgnoreEnabled && ::IsValidWindow(m_aDlgItems[i].m_hWnd))
  980. {
  981. EnableWindow(m_aDlgItems[i].m_hWnd, m_aDlgItems[i].m_bEnabled);
  982. }
  983. }
  984. }
  985. ///////////////////////////////////////////////////////////
  986. //
  987. // EnableDlgItem
  988. //
  989. void
  990. CAdvancedSearchNavPane::EnableDlgItem(DlgItemInfoIndex index, bool bEnable)
  991. {
  992. ASSERT(index >= 0 && index < c_NumDlgItems);
  993. if (!m_aDlgItems[index].m_bIgnoreEnabled)
  994. {
  995. // Are we enabled or not?
  996. m_aDlgItems[index].m_bEnabled = bEnable;
  997. // Do it for real.
  998. if (::IsValidWindow(m_aDlgItems[index].m_hWnd))
  999. {
  1000. EnableWindow(m_aDlgItems[index].m_hWnd, bEnable);
  1001. }
  1002. }
  1003. }
  1004. ///////////////////////////////////////////////////////////
  1005. //
  1006. // AddKeywordToCombo
  1007. //
  1008. void
  1009. CAdvancedSearchNavPane::AddKeywordToCombo(PCWSTR sz)
  1010. {
  1011. PWSTR pszQuery = NULL;
  1012. PCWSTR psz = sz;
  1013. if (psz == NULL)
  1014. {
  1015. int lenQuery = W_GetTextLengthExact(m_aDlgItems[c_KeywordCombo].m_hWnd);
  1016. if (lenQuery <=0)
  1017. {
  1018. return;
  1019. }
  1020. pszQuery = new WCHAR [++lenQuery];
  1021. W_GetWindowText(m_aDlgItems[c_KeywordCombo].m_hWnd, pszQuery, lenQuery);
  1022. psz = pszQuery;
  1023. }
  1024. if (CB_ERR == W_ComboBox_FindStringExact(m_aDlgItems[c_KeywordCombo].m_hWnd, -1, psz))
  1025. {
  1026. // Not in listbox, so add it to the begining.
  1027. W_ComboBox_InsertString(m_aDlgItems[c_KeywordCombo].m_hWnd, 0, psz);
  1028. // Limit the number of entries.
  1029. int lastindex = ComboBox_GetCount(m_aDlgItems[c_KeywordCombo].m_hWnd);
  1030. if ( lastindex > c_MaxKeywordsInCombo)
  1031. {
  1032. // remove the last one.
  1033. ComboBox_DeleteString(m_aDlgItems[c_KeywordCombo].m_hWnd, lastindex-1 );
  1034. }
  1035. }
  1036. if (pszQuery)
  1037. {
  1038. delete [] pszQuery;
  1039. }
  1040. }
  1041. ///////////////////////////////////////////////////////////
  1042. //
  1043. // SaveKeywordCombo --- Persists the keyword combo to the storage
  1044. //
  1045. void
  1046. CAdvancedSearchNavPane::SaveKeywordCombo()
  1047. {
  1048. // TODO: Implement an IsDirty flag, so that we only save when we need to.
  1049. // Are there any keywords to save?
  1050. int count = ComboBox_GetCount(m_aDlgItems[c_KeywordCombo].m_hWnd);
  1051. if (count > 0 && count != CB_ERR)
  1052. {
  1053. ASSERT(count <= c_MaxKeywordsInCombo);
  1054. WCHAR buffer[c_MaxPersistKeywordBufferSize];
  1055. int bufferlength = W_ComboBox_GetListText(m_aDlgItems[c_KeywordCombo].m_hWnd, buffer, c_MaxPersistKeywordBufferSize);
  1056. ASSERT(bufferlength > 0 );
  1057. if (bufferlength > 0)
  1058. {
  1059. // Save it
  1060. CState* pstate = m_pTitleCollection->GetState();
  1061. if (SUCCEEDED(pstate->Open(c_PersistFolder, STGM_WRITE)))
  1062. {
  1063. pstate->Write(&buffer, (bufferlength+1)*sizeof(WCHAR)); // Include the null terminating char.
  1064. pstate->Close();
  1065. }
  1066. }
  1067. }
  1068. //
  1069. //--- Save UI state.
  1070. //
  1071. // Before we can save, we need to get the state.
  1072. DWORD curstate = 0;
  1073. ASSERT(IsWindow(m_aDlgItems[c_TitlesOnlyCheck].m_hWnd));
  1074. if (Button_GetCheck(m_aDlgItems[c_TitlesOnlyCheck].m_hWnd) == BST_CHECKED)
  1075. {
  1076. curstate |= StateProp_TitlesOnly;
  1077. }
  1078. if (Button_GetCheck(m_aDlgItems[c_SimilarCheck].m_hWnd) == BST_CHECKED)
  1079. {
  1080. curstate |= StateProp_MatchSimilar;
  1081. }
  1082. if (Button_GetCheck(m_aDlgItems[c_PreviousCheck].m_hWnd) == BST_CHECKED)
  1083. {
  1084. curstate |= StateProp_PrevSearch;
  1085. }
  1086. // Now save the state.
  1087. CState* pstate = m_pTitleCollection->GetState();
  1088. if (SUCCEEDED(pstate->Open(c_PropertiesFolder, STGM_WRITE)))
  1089. {
  1090. pstate->Write(&curstate, sizeof(curstate));
  1091. pstate->Close();
  1092. }
  1093. }
  1094. ///////////////////////////////////////////////////////////
  1095. //
  1096. // LoadKeywordCombo --- Loads the keyword combo from the storage
  1097. //
  1098. void
  1099. CAdvancedSearchNavPane::LoadKeywordCombo()
  1100. {
  1101. CState* pstate = m_pTitleCollection->GetState();
  1102. if (SUCCEEDED(pstate->Open(c_PersistFolder, STGM_READ)))
  1103. {
  1104. WCHAR buffer[c_MaxPersistKeywordBufferSize];
  1105. // Read in the persisted data.
  1106. DWORD cbRead;
  1107. pstate->Read(buffer, c_MaxPersistKeywordBufferSize, &cbRead);
  1108. pstate->Close();
  1109. if (cbRead > 0)
  1110. {
  1111. int count = W_ComboBox_SetListText(m_aDlgItems[c_KeywordCombo].m_hWnd, buffer, c_MaxKeywordsInCombo);
  1112. if (count > 0)
  1113. {
  1114. ComboBox_SetCurSel(m_aDlgItems[c_KeywordCombo].m_hWnd, 0);
  1115. EnableDlgItem(c_SearchBtn, true);
  1116. }
  1117. }
  1118. }
  1119. //
  1120. //--- Load UI state.
  1121. //
  1122. // Read in the dword state value
  1123. CState* pstate2 = m_pTitleCollection->GetState(); // Don't trust CState cleanup. So use a new var.
  1124. if (SUCCEEDED(pstate2->Open(c_PropertiesFolder, STGM_READ)))
  1125. {
  1126. DWORD curstate = NULL;
  1127. DWORD cbRead = NULL;
  1128. pstate2->Read(&curstate, sizeof(curstate), &cbRead);
  1129. pstate2->Close();
  1130. if (cbRead == sizeof(curstate))
  1131. {
  1132. // Make the UI match the persisted state.
  1133. // Searching Titles Only?
  1134. ASSERT(IsWindow(m_aDlgItems[c_TitlesOnlyCheck].m_hWnd));
  1135. DWORD check = NULL;
  1136. if (curstate & StateProp_TitlesOnly)
  1137. {
  1138. check = BST_CHECKED;
  1139. }
  1140. else
  1141. {
  1142. check = BST_UNCHECKED;
  1143. }
  1144. Button_SetCheck(m_aDlgItems[c_TitlesOnlyCheck].m_hWnd, check);
  1145. // Matching similar words?
  1146. if (curstate & StateProp_MatchSimilar)
  1147. {
  1148. check = BST_CHECKED;
  1149. }
  1150. else
  1151. {
  1152. check = BST_UNCHECKED;
  1153. }
  1154. Button_SetCheck(m_aDlgItems[c_SimilarCheck].m_hWnd, check);
  1155. check = BST_UNCHECKED;
  1156. Button_SetCheck(m_aDlgItems[c_PreviousCheck].m_hWnd, check);
  1157. }
  1158. }
  1159. }
  1160. ///////////////////////////////////////////////////////////
  1161. //
  1162. // Message Handlers
  1163. //
  1164. ///////////////////////////////////////////////////////////
  1165. //
  1166. // OnStartSearch
  1167. //
  1168. void
  1169. CAdvancedSearchNavPane::OnStartSearch()
  1170. {
  1171. //---Get the word from the edit control.
  1172. int lenQuery = W_GetTextLengthExact(m_aDlgItems[c_KeywordCombo].m_hWnd);
  1173. if (lenQuery <=0)
  1174. {
  1175. return;
  1176. }
  1177. PWSTR pszQuery = new WCHAR [++lenQuery];
  1178. W_GetWindowText(m_aDlgItems[c_KeywordCombo].m_hWnd, pszQuery, lenQuery);
  1179. //--- Disable controls
  1180. // Disable Display Topic Command
  1181. EnableDlgItem(c_DisplayBtn, false);
  1182. // Disable results list
  1183. EnableDlgItem(c_ResultsList, false);
  1184. //---Set up the flags.
  1185. DWORD flags = 0;
  1186. //FTS_SIMILARITY????
  1187. // Does the user want to search titles only?
  1188. if (Button_GetCheck(m_aDlgItems[c_TitlesOnlyCheck].m_hWnd))
  1189. {
  1190. flags |= FTS_TITLE_ONLY;
  1191. }
  1192. if (Button_GetCheck(m_aDlgItems[c_SimilarCheck].m_hWnd))
  1193. {
  1194. flags |= FTS_ENABLE_STEMMING;
  1195. }
  1196. #ifndef __SUBSETS__
  1197. //--- Check the previous results checkbox.
  1198. if (Button_GetCheck(m_aDlgItems[c_PreviousCheck].m_hWnd))
  1199. {
  1200. flags |= FTS_SEARCH_PREVIOUS;
  1201. }
  1202. #else //__SUBSETS__
  1203. //--- Get the subset.
  1204. CSubSet* pS = NULL;
  1205. int iCurSel = ComboBox_GetCurSel(m_aDlgItems[c_SubsetsCombo].m_hWnd);
  1206. DWORD which = ComboBox_GetItemData(m_aDlgItems[c_SubsetsCombo].m_hWnd, iCurSel);
  1207. if (which == c_SubSetPrevious)
  1208. {
  1209. flags |= FTS_SEARCH_PREVIOUS;
  1210. }
  1211. else
  1212. pS = (CSubSet*)which;
  1213. #endif
  1214. //--- Execute the search!
  1215. int ResultCount = 0;
  1216. CHourGlass HourGlass;
  1217. SEARCH_RESULT *pTempResults;
  1218. #ifdef __SUBSETS__
  1219. HRESULT hr = m_pTitleCollection->m_pFullTextSearch->ComplexQuery(
  1220. pszQuery,
  1221. flags,
  1222. &ResultCount,
  1223. &pTempResults, pS);
  1224. #else
  1225. HRESULT hr = m_pTitleCollection->m_pFullTextSearch->ComplexQuery(
  1226. pszQuery,
  1227. flags,
  1228. &ResultCount,
  1229. &pTempResults, NULL);
  1230. #endif
  1231. //--- Check the results
  1232. bool bContinue = true;
  1233. if (FAILED(hr))
  1234. {
  1235. bContinue = false;
  1236. if (hr == FTS_NO_INDEX)
  1237. MsgBox(IDS_NO_FTS_DATA);
  1238. else if (hr == FTS_NOT_INITIALIZED)
  1239. MsgBox(IDS_BAD_ITIRCL);
  1240. else if (hr == FTS_INVALID_SYNTAX)
  1241. {
  1242. MsgBox(IDS_INCORRECT_SYNTAX);
  1243. // re-enable results list
  1244. EnableDlgItem(c_ResultsList, true);
  1245. }
  1246. /*
  1247. else if (hr == FTS_SKIP_TITLE)
  1248. bContinue = true;
  1249. else if (hr == FTS_SKIP_VOLUME)
  1250. bContinue = true;
  1251. else if (hr == FTS_SKIP_ALL)
  1252. bContinue = true;
  1253. */
  1254. else if (hr == FTS_CANCELED)
  1255. {
  1256. EnableDlgItem(c_ResultsList, true);
  1257. }
  1258. else
  1259. MsgBox(IDS_SEARCH_FAILURE);
  1260. }
  1261. if (bContinue )
  1262. {
  1263. // Make sure that we have results.
  1264. if (!ResultCount)
  1265. {
  1266. // Nothing fun to play with.
  1267. MsgBox(IDS_NO_TOPICS_FOUND);
  1268. bContinue = FALSE;
  1269. // re-enable results list
  1270. EnableDlgItem(c_ResultsList, true);
  1271. }
  1272. else
  1273. {
  1274. if(g_bWinNT5)
  1275. {
  1276. //--- Reset the previous listview.
  1277. // DOUGO: This change is to leave the previous results intact when the new query fails
  1278. //
  1279. // Display the results number:
  1280. WCHAR wszNewText[128];
  1281. // insert &LRM control character to get mixed layout correct under bidi
  1282. //
  1283. if(g_bBiDiUi)
  1284. wsprintfW(wszNewText,L"%s%c%d", GetStringResourceW(IDS_ADVSEARCH_FOUND), 0x200E, ResultCount);
  1285. else
  1286. wsprintfW(wszNewText,L"%s%d", GetStringResourceW(IDS_ADVSEARCH_FOUND), ResultCount);
  1287. SetWindowTextW(m_aDlgItems[c_FoundStatic].m_hWnd,wszNewText);
  1288. }
  1289. else
  1290. {
  1291. //--- Reset the previous listview.
  1292. // DOUGO: This change is to leave the previous results intact when the new query fails
  1293. //
  1294. // Display the results number:
  1295. char szNewText[128];
  1296. // insert &LRM control character to get mixed layout correct under bidi
  1297. //
  1298. if(g_bBiDiUi)
  1299. wsprintf(szNewText,"%s%c%d", GetStringResource(IDS_ADVSEARCH_FOUND), 0xFD, ResultCount);
  1300. else
  1301. wsprintf(szNewText,"%s%d", GetStringResource(IDS_ADVSEARCH_FOUND), ResultCount);
  1302. Static_SetText(m_aDlgItems[c_FoundStatic].m_hWnd,szNewText);
  1303. }
  1304. m_plistview->ResetQuery();
  1305. m_plistview->SetResults(ResultCount, pTempResults);
  1306. }
  1307. }
  1308. // Do we continue?
  1309. if( bContinue )
  1310. {
  1311. // Enable Display Topic Command
  1312. EnableDlgItem(c_DisplayBtn, true);
  1313. // Enable results list
  1314. EnableDlgItem(c_ResultsList, true);
  1315. // Add the results.
  1316. m_plistview->AddItems();
  1317. //--- If the word isn't already in the list control. Put it in the list control.
  1318. AddKeywordToCombo(pszQuery);
  1319. }
  1320. else
  1321. {
  1322. // We are done.
  1323. SetFocus(m_aDlgItems[c_KeywordCombo].m_hWnd);
  1324. }
  1325. // Cleanup
  1326. delete [] pszQuery;
  1327. }
  1328. ///////////////////////////////////////////////////////////
  1329. //
  1330. // OnDisplayTopic
  1331. //
  1332. void
  1333. CAdvancedSearchNavPane::OnDisplayTopic()
  1334. {
  1335. if( (m_plistview->m_pResults != NULL) && (m_plistview->m_ItemNumber!= -1))
  1336. {
  1337. DWORD dwtemp = m_plistview->m_pResults[m_plistview->m_ItemNumber].dwTopicNumber;
  1338. CExTitle* pTitle = m_plistview->m_pResults[m_plistview->m_ItemNumber].pTitle;
  1339. if ( pTitle )
  1340. {
  1341. char szURL[MAX_URL];
  1342. if ((pTitle->GetTopicURL(dwtemp, szURL, sizeof(szURL)) == S_OK))
  1343. {
  1344. ChangeHtmlTopic(szURL, GetParent(m_plistview->m_hwndListView), 1);
  1345. }
  1346. }
  1347. }
  1348. }
  1349. ///////////////////////////////////////////////////////////
  1350. //
  1351. // OnConjunctions
  1352. //
  1353. void
  1354. CAdvancedSearchNavPane::OnConjunctions()
  1355. {
  1356. const int NumMenus = 4;
  1357. // Create menu
  1358. HMENU hConjMenu = ::CreatePopupMenu();
  1359. // Get the strings
  1360. CStr MenuText[NumMenus];
  1361. MenuText[0] = GetStringResource(IDS_ADVSEARCH_CONJ_AND);
  1362. MenuText[1] = GetStringResource(IDS_ADVSEARCH_CONJ_OR);
  1363. MenuText[2] = GetStringResource(IDS_ADVSEARCH_CONJ_NEAR);
  1364. MenuText[3] = GetStringResource(IDS_ADVSEARCH_CONJ_NOT);
  1365. // Add the menu items.
  1366. for (int i = 0; i < NumMenus; i++)
  1367. {
  1368. ::HxAppendMenu(hConjMenu, MF_STRING, i+1, MenuText[i]);
  1369. }
  1370. // Get the button rect in screen coordinates for the exclusion area.
  1371. RECT rcExclude;
  1372. ::GetWindowRect(m_aDlgItems[c_ConjunctionBtn].m_hWnd, &rcExclude);
  1373. TPMPARAMS tpm;
  1374. tpm.cbSize = sizeof(tpm);
  1375. tpm.rcExclude = rcExclude;
  1376. // Track the menu.
  1377. int iCommand = TrackPopupMenuEx( hConjMenu,
  1378. TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
  1379. rcExclude.right, // Place at upper right of button.
  1380. rcExclude.top,
  1381. m_hWnd,
  1382. &tpm);
  1383. // Act on command
  1384. if (iCommand > 0)
  1385. {
  1386. //TODO:[paulde] Unicode-ize -- veeery carefully. Think about GetEditSel coords
  1387. // in MBCS text and how to map to WCHAR coords.
  1388. char text[256];
  1389. int iSelectionIndex; // Where to put the caret when we are done.
  1390. //---Get the word from the edit control.
  1391. char* pszQuery = NULL;
  1392. int len = ComboBox_GetTextLength(m_aDlgItems[c_KeywordCombo].m_hWnd);
  1393. if (len <= 0)
  1394. {
  1395. // No text in edit control. Just put our text into the control.
  1396. ComboBox_SetText(m_aDlgItems[c_KeywordCombo].m_hWnd, MenuText[iCommand-1]);
  1397. // Get length of selection.
  1398. iSelectionIndex = (int)strlen(MenuText[iCommand-1]);
  1399. }
  1400. else
  1401. {
  1402. // There is text in the edit control. Replace the selection.
  1403. // Get the existing text
  1404. pszQuery = new char[len+1];
  1405. ComboBox_GetText(m_aDlgItems[c_KeywordCombo].m_hWnd, pszQuery, len+1);
  1406. // Find out what is selected.
  1407. int end = HIWORD(m_dwKeywordComboEditLastSel);
  1408. int start = LOWORD(m_dwKeywordComboEditLastSel);
  1409. char *pszTemp = pszQuery;
  1410. int char_start = 0, count = 0;
  1411. // The above start/end values are in character offsets which
  1412. // do not correspond to byte offsets when we have DBCS chars.
  1413. //
  1414. // find out the start value in bytes:
  1415. //
  1416. while(*pszTemp && count < start)
  1417. {
  1418. char_start++;
  1419. char_start+=IsDBCSLeadByte(*pszTemp);
  1420. pszTemp = CharNext(pszTemp);
  1421. ++count;
  1422. }
  1423. int char_end = 0;
  1424. // do the same thing to compute the end offset in bytes
  1425. //
  1426. pszTemp = pszQuery;
  1427. count = 0;
  1428. while(*pszTemp && count < end)
  1429. {
  1430. char_end++;
  1431. char_end+=IsDBCSLeadByte(*pszTemp);
  1432. pszTemp = CharNext(pszTemp);
  1433. ++count;
  1434. }
  1435. // set buffer to all zeros. So we can just concat.
  1436. _strnset(text,'\0',sizeof(text));
  1437. if (start > 0)
  1438. {
  1439. // Copy the first part of the string.
  1440. strncat(text, pszQuery, char_start); // doesn't add null.
  1441. }
  1442. // Insert the conjunction surrounded by spaces.
  1443. strcat(text, " ");
  1444. strcat(text, MenuText[iCommand-1]);
  1445. strcat(text, " ");
  1446. iSelectionIndex = (int)strlen(text);
  1447. if (end>=0)
  1448. {
  1449. //Copy the last part of the string.
  1450. strcat(text,&pszQuery[char_end]);
  1451. }
  1452. // Set the text.
  1453. ComboBox_SetText(m_aDlgItems[c_KeywordCombo].m_hWnd, text);
  1454. // Cleanup
  1455. if (pszQuery)
  1456. {
  1457. delete [] pszQuery;
  1458. }
  1459. }
  1460. // Set focus to the control.
  1461. SetFocus(m_aDlgItems[c_KeywordCombo].m_hWnd);
  1462. // Put the cursor at the end of the text just added.
  1463. ComboBox_SetEditSel(m_aDlgItems[c_KeywordCombo].m_hWnd, iSelectionIndex, iSelectionIndex);
  1464. }
  1465. }
  1466. ///////////////////////////////////////////////////////////
  1467. //
  1468. // OnDefineSubsets
  1469. //
  1470. void
  1471. CAdvancedSearchNavPane::OnDefineSubsets()
  1472. {
  1473. #ifdef __SUBSETS__
  1474. CSubSet* pS;
  1475. int index;
  1476. if (! m_pTitleCollection->m_phmData->m_pInfoType )
  1477. {
  1478. m_pTitleCollection->m_phmData->m_pInfoType = new CInfoType();
  1479. m_pTitleCollection->m_phmData->m_pInfoType->CopyTo( m_pTitleCollection->m_phmData );
  1480. }
  1481. if ( ChooseInformationTypes(m_pTitleCollection->m_phmData->m_pInfoType, NULL, m_hWnd, NULL, m_pWinType) )
  1482. {
  1483. pS = m_pTitleCollection->m_pSubSets->m_cur_Set;
  1484. if ( pS && pS->m_cszSubSetName.psz )
  1485. {
  1486. if ( ComboBox_SelectString(m_aDlgItems[c_SubsetsCombo].m_hWnd, -1, pS->m_cszSubSetName.psz) == CB_ERR )
  1487. {
  1488. index = ComboBox_AddString(m_aDlgItems[c_SubsetsCombo].m_hWnd, pS->m_cszSubSetName.psz);
  1489. ComboBox_SetItemData(m_aDlgItems[c_SubsetsCombo].m_hWnd, index, pS);
  1490. ComboBox_SetCurSel(m_aDlgItems[c_KeywordCombo].m_hWnd, index );
  1491. }
  1492. }
  1493. }
  1494. #endif
  1495. }
  1496. //////////////////////////////////////////////////////////////////////////
  1497. //
  1498. // UpdateSSCombo
  1499. //
  1500. void
  1501. CAdvancedSearchNavPane::UpdateSSCombo(bool bInitialize)
  1502. {
  1503. #ifdef __SUBSETS__
  1504. if (m_pTitleCollection && m_pTitleCollection->m_pSubSets)
  1505. {
  1506. CSubSets* pSS = m_pTitleCollection->m_pSubSets;
  1507. int max = pSS->HowManySubSets();
  1508. for (int n = 0; n < max; n++ )
  1509. {
  1510. CSubSet* pS = pSS->GetSubSet(n);
  1511. if (pS)
  1512. {
  1513. // If we are initializing, add them all. If we are updating, only add the ones we don't have.
  1514. if ( bInitialize || ComboBox_FindStringExact(m_aDlgItems[c_SubsetsCombo].m_hWnd, -1, pS->m_cszSubSetName.psz) == CB_ERR )
  1515. {
  1516. int index = ComboBox_AddString(m_aDlgItems[c_SubsetsCombo].m_hWnd, pS->m_cszSubSetName.psz);
  1517. ComboBox_SetItemData(m_aDlgItems[c_SubsetsCombo].m_hWnd, index, pS);
  1518. }
  1519. }
  1520. }
  1521. //--- Set the selected line.
  1522. int bItemSelected = CB_ERR;
  1523. // Try setting it to the current subset.
  1524. if (max > 0 && pSS->m_FTS && pSS->m_FTS->m_cszSubSetName.psz )
  1525. bItemSelected = ComboBox_SelectString(m_aDlgItems[c_SubsetsCombo].m_hWnd, -1, pSS->m_FTS->m_cszSubSetName); //BUGBUG: m_cszSubSetName this is non-sense!
  1526. // Try explictly setting it to Entire Collection.
  1527. if (bItemSelected == CB_ERR)
  1528. {
  1529. bItemSelected = ComboBox_SelectString(m_aDlgItems[c_SubsetsCombo].m_hWnd, -1, GetStringResource(IDS_ADVSEARCH_SEARCHIN_ENTIRE));
  1530. }
  1531. // Okay, now just set it to the first one!.
  1532. if (bItemSelected == CB_ERR)
  1533. {
  1534. ComboBox_SetCurSel(m_aDlgItems[c_KeywordCombo].m_hWnd, 0);
  1535. }
  1536. }
  1537. #endif
  1538. }
  1539. ///////////////////////////////////////////////////////////
  1540. //
  1541. // OnTab - Handles pressing of the tab key.
  1542. //
  1543. void
  1544. CAdvancedSearchNavPane::OnTab(HWND hwndReceivedTab, DlgItemInfoIndex /*index*/)
  1545. {
  1546. //if (index == c_NumDlgItems) --- caller doesn't know the index.
  1547. ASSERT(::IsValidWindow(hwndReceivedTab));
  1548. //--- Is the shift key down?
  1549. BOOL bPrevious = (GetKeyState(VK_SHIFT) < 0);
  1550. #if 0
  1551. //---Are we the first or last control?
  1552. if ((bPrevious && hwndReceivedTab == m_hKeywordComboEdit/*m_aDlgItems[c_KeywordCombo].m_hWnd*/) || // The c_KeywordCombo control is the first control, so shift tab goes to the topic window.
  1553. (!bPrevious && hwndReceivedTab == m_aDlgItems[c_TitlesOnlyCheck].m_hWnd)) // The c_TitlesOnlyCheck is the last control, so tab goes to the topic window.
  1554. {
  1555. PostMessage(m_pWinType->GetHwnd(), WMP_HH_TAB_KEY, 0, 0);
  1556. }
  1557. else
  1558. #endif
  1559. {
  1560. //--- Move to the next control .
  1561. // Get the next tab item.
  1562. HWND hWndNext = GetNextDlgTabItem(m_hWnd, hwndReceivedTab, bPrevious);
  1563. // Set focus to it.
  1564. ::SetFocus(hWndNext);
  1565. }
  1566. }
  1567. ///////////////////////////////////////////////////////////
  1568. //
  1569. // OnArrow
  1570. //
  1571. void
  1572. CAdvancedSearchNavPane::OnArrow(HWND hwndReceivedTab, DlgItemInfoIndex /*index*/, INT_PTR key)
  1573. {
  1574. //if (index == c_NumDlgItems) --- caller doesn't know the index.
  1575. ASSERT(::IsValidWindow(hwndReceivedTab));
  1576. BOOL bPrevious = FALSE;
  1577. if (key == VK_LEFT || key == VK_UP)
  1578. {
  1579. bPrevious = TRUE;
  1580. }
  1581. // Get the next tab item.
  1582. HWND hWndNext = GetNextDlgGroupItem(m_hWnd, hwndReceivedTab, bPrevious);
  1583. // Set focus to it.
  1584. ::SetFocus(hWndNext);
  1585. }
  1586. ///////////////////////////////////////////////////////////
  1587. //
  1588. // OnReturn - Default handling of the return key.
  1589. //
  1590. bool
  1591. CAdvancedSearchNavPane::OnReturn(HWND hwndReceivedTab, DlgItemInfoIndex /*index*/)
  1592. {
  1593. //if (index == c_NumDlgItems) --- caller doesn't know the index.
  1594. // Do the default button action.
  1595. // Always do a search topic, if its enabled.
  1596. if (::IsWindowEnabled(m_aDlgItems[c_SearchBtn].m_hWnd))
  1597. {
  1598. OnStartSearch();
  1599. return true;
  1600. }
  1601. else
  1602. {
  1603. return false;
  1604. }
  1605. }
  1606. ///////////////////////////////////////////////////////////
  1607. //
  1608. // Callback Functions.
  1609. //
  1610. ///////////////////////////////////////////////////////////
  1611. //
  1612. // Static DialogProc
  1613. //
  1614. INT_PTR CALLBACK
  1615. CAdvancedSearchNavPane::s_DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1616. {
  1617. // Call member function dialog proc.
  1618. if (msg == WM_INITDIALOG)
  1619. {
  1620. // The lParam is the this pointer for this dialog box.
  1621. // Save it in the window userdata section.
  1622. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
  1623. }
  1624. // Get the this pointer and call the non-static callback function.
  1625. CAdvancedSearchNavPane* p = GETTHIS(CAdvancedSearchNavPane, hwnd);
  1626. if (p)
  1627. {
  1628. return p->DialogProc(hwnd, msg, wParam, lParam);
  1629. }
  1630. else
  1631. {
  1632. return FALSE;
  1633. }
  1634. }
  1635. ///////////////////////////////////////////////////////////
  1636. //
  1637. // ListViewProc
  1638. //
  1639. LRESULT WINAPI
  1640. CAdvancedSearchNavPane::s_ListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1641. {
  1642. switch (msg)
  1643. {
  1644. case WM_KEYDOWN:
  1645. switch (wParam)
  1646. {
  1647. case VK_RETURN:
  1648. // A return means that we want to display the currently selected topic.
  1649. GETTHIS(CAdvancedSearchNavPane, hwnd)->OnDisplayTopic();
  1650. return 0;
  1651. case VK_TAB:
  1652. GETTHIS(CAdvancedSearchNavPane, hwnd)->OnTab(hwnd, c_ResultsList);
  1653. break;
  1654. }
  1655. break;
  1656. }
  1657. return W_DelegateWindowProc(s_lpfnlListViewWndProc, hwnd, msg, wParam, lParam);
  1658. }
  1659. ///////////////////////////////////////////////////////////
  1660. //
  1661. // KeywordComboEditProc - Subclassed the Edit Control in the Keyword Combo Box
  1662. // The original reason for doing this was to save the selection location.
  1663. //
  1664. LRESULT WINAPI
  1665. CAdvancedSearchNavPane::s_KeywordComboEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1666. {
  1667. CAdvancedSearchNavPane* pThis;
  1668. switch (msg)
  1669. {
  1670. case WM_KEYDOWN:
  1671. switch (wParam)
  1672. {
  1673. case VK_RETURN:
  1674. pThis = GETTHIS(CAdvancedSearchNavPane, hwnd);
  1675. if (pThis->OnReturn(hwnd, c_KeywordCombo))
  1676. {
  1677. pThis->AddKeywordToCombo();
  1678. return 0;
  1679. }
  1680. break;
  1681. case VK_TAB:
  1682. GETTHIS(CAdvancedSearchNavPane, hwnd)->OnTab(hwnd,c_KeywordCombo);
  1683. return 0;
  1684. }
  1685. break;
  1686. case WM_CHAR:
  1687. if (wParam == VK_TAB) // The virt code is the same as the tab character.
  1688. {
  1689. // Not handling this message was causing a beep.
  1690. return 0;
  1691. }
  1692. break;
  1693. /* There is no point in handling this message, because it never gets sent.
  1694. it is sent by IsDialogMessage which never gets called...
  1695. case WM_GETDLGCODE:
  1696. return DLGC_WANTTAB;
  1697. */
  1698. case WM_KILLFOCUS:
  1699. // Save the selection so that we can use it to insert the conjunctions.
  1700. GETTHIS(CAdvancedSearchNavPane, hwnd)->m_dwKeywordComboEditLastSel = Edit_GetSel(hwnd);
  1701. break;
  1702. }
  1703. return W_DelegateWindowProc(s_lpfnlKeywordComboEditProc, hwnd, msg, wParam, lParam);
  1704. }
  1705. ///////////////////////////////////////////////////////////
  1706. //
  1707. // KeywordComboProc -
  1708. // We handle the keyboard.
  1709. //
  1710. LRESULT WINAPI
  1711. CAdvancedSearchNavPane::s_KeywordComboProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1712. {
  1713. /* We don't process any messages here.
  1714. switch (msg)
  1715. {
  1716. case WM_KEYDOWN:
  1717. if (wParam == VK_TAB)
  1718. return 0;
  1719. break;
  1720. case WM_GETDLGCODE:
  1721. return DLGC_WANTTAB;
  1722. }
  1723. */
  1724. return W_DelegateWindowProc(s_lpfnlKeywordComboProc, hwnd, msg, wParam, lParam);
  1725. }
  1726. ///////////////////////////////////////////////////////////
  1727. //
  1728. // s_SubsetsComboEditProc - Subclassed the Edit Control in the Subset Combo Box
  1729. //
  1730. #ifdef __SUBSETS__
  1731. LRESULT WINAPI
  1732. CAdvancedSearchNavPane::s_SubsetsComboProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1733. {
  1734. switch (msg)
  1735. {
  1736. case WM_KEYDOWN:
  1737. switch (wParam)
  1738. {
  1739. case VK_RETURN:
  1740. if (GETTHIS(CAdvancedSearchNavPane, hwnd)->OnReturn(hwnd, c_SubsetsCombo))
  1741. return 0;
  1742. break;
  1743. case VK_TAB:
  1744. GETTHIS(CAdvancedSearchNavPane, hwnd)->OnTab(hwnd,c_SubsetsCombo);
  1745. return 0;
  1746. }
  1747. }
  1748. return W_DelegateWindowProc(s_lpfnlSubsetsComboProc, hwnd, msg, wParam, lParam);
  1749. }
  1750. #endif
  1751. ///////////////////////////////////////////////////////////
  1752. //
  1753. // Generic keyboard handling for all btns.
  1754. //
  1755. LRESULT WINAPI
  1756. CAdvancedSearchNavPane::s_GenericBtnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1757. {
  1758. CAdvancedSearchNavPane* pThis;
  1759. switch (msg)
  1760. {
  1761. case WM_KEYDOWN:
  1762. switch (wParam)
  1763. {
  1764. case VK_RETURN:
  1765. pThis = GETTHIS(CAdvancedSearchNavPane, hwnd);
  1766. return pThis->OnCommand(pThis->m_hWnd, ::GetDlgCtrlID(hwnd), BN_CLICKED, lParam);
  1767. case VK_TAB:
  1768. GETTHIS(CAdvancedSearchNavPane, hwnd)->OnTab(hwnd,c_NumDlgItems);
  1769. return 0;
  1770. case VK_LEFT:
  1771. case VK_RIGHT:
  1772. case VK_UP:
  1773. case VK_DOWN:
  1774. GETTHIS(CAdvancedSearchNavPane, hwnd)->OnArrow(hwnd,c_NumDlgItems, wParam);
  1775. return 0;
  1776. }
  1777. }
  1778. return W_DelegateWindowProc(s_lpfnlGenericBtnProc, hwnd, msg, wParam, lParam);
  1779. }
  1780. ///////////////////////////////////////////////////////////
  1781. //
  1782. // Generic keyboard handling for other controls which aren't handled elsewhere.
  1783. //
  1784. LRESULT WINAPI
  1785. CAdvancedSearchNavPane::s_GenericKeyboardProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1786. {
  1787. switch (msg)
  1788. {
  1789. case WM_KEYDOWN:
  1790. switch (wParam)
  1791. {
  1792. case VK_RETURN:
  1793. if (GETTHIS(CAdvancedSearchNavPane, hwnd)->OnReturn(hwnd, c_NumDlgItems))
  1794. return 0;
  1795. break;
  1796. case VK_TAB:
  1797. GETTHIS(CAdvancedSearchNavPane, hwnd)->OnTab(hwnd, c_NumDlgItems);
  1798. return 0;
  1799. case VK_LEFT:
  1800. case VK_RIGHT:
  1801. case VK_UP:
  1802. case VK_DOWN:
  1803. GETTHIS(CAdvancedSearchNavPane, hwnd)->OnArrow(hwnd, c_NumDlgItems, wParam);
  1804. return 0;
  1805. }
  1806. break;
  1807. }
  1808. return W_DelegateWindowProc(s_lpfnlGenericKeyboardProc, hwnd, msg, wParam, lParam);
  1809. }
  1810. ///////////////////////////////////////////////////////////
  1811. //
  1812. // DialogProc
  1813. //
  1814. INT_PTR
  1815. CAdvancedSearchNavPane::DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1816. {
  1817. switch(msg)
  1818. {
  1819. case WM_COMMAND: return OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), lParam);
  1820. case WM_NOTIFY : return OnNotify(hwnd, wParam, lParam);
  1821. }
  1822. return FALSE;
  1823. }