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.

1752 lines
53 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 "TCHAR.h"
  21. #include "parserhh.h"
  22. #include "collect.h"
  23. #include "hhtypes.h"
  24. #include "toc.h"
  25. #include "contain.h"
  26. #include "cctlww.h"
  27. // Our header file.
  28. #include "bookmark.h"
  29. // Common Control Macros
  30. #include <windowsx.h>
  31. #define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
  32. ///////////////////////////////////////////////////////////
  33. //
  34. // Constants
  35. //
  36. const char c_PersistFolder[] = "Bookmarks\\v1" ;
  37. const char c_TopicFolder[] = "Topic" ;
  38. const char c_UrlFolder[] = "Url" ;
  39. const char c_CountFolder[] = "Bookmarks\\v1\\Count" ;
  40. const wchar_t c_KeywordSeparator[] = L"\n" ;
  41. // This is the maximum bookmarks we store.
  42. // The main reason for this is to ensure that we have a reasonable value
  43. // when we read the collection in.
  44. const int c_MaxBookmarks = 1024;
  45. extern BOOL g_fUnicodeListView;
  46. ///////////////////////////////////////////////////////////
  47. //
  48. // Static Member functions
  49. //
  50. WNDPROC CBookmarksNavPane::s_lpfnlListViewWndProc = NULL;
  51. WNDPROC CBookmarksNavPane::s_lpfnlCurrentTopicEditProc = NULL;
  52. WNDPROC CBookmarksNavPane::s_lpfnlGenericBtnProc = NULL;
  53. //WNDPROC CBookmarksNavPane::s_lpfnlGenericKeyboardProc = NULL ;
  54. ///////////////////////////////////////////////////////////
  55. //
  56. // Non-Member helper functions.
  57. //
  58. // Convert a rect from screen to client.
  59. void ScreenRectToClientRect(HWND hWnd, /*in/out*/ RECT* prect) ;
  60. ///////////////////////////////////////////////////////////
  61. //
  62. // Construction
  63. //
  64. ///////////////////////////////////////////////////////////
  65. //
  66. // CBookmarksNavPane();
  67. //
  68. CBookmarksNavPane::CBookmarksNavPane(CHHWinType* pWinType)
  69. : m_hWnd(NULL),
  70. m_hfont(NULL),
  71. m_padding(2), // padding to put around the window
  72. m_pWinType(pWinType),
  73. m_pszCurrentUrl(NULL),
  74. m_bChanged(false)
  75. {
  76. ASSERT(pWinType) ;
  77. m_pTitleCollection = pWinType->m_phmData->m_pTitleCollection;
  78. ASSERT(m_pTitleCollection);
  79. m_NavTabPos = pWinType->tabpos ;
  80. }
  81. ///////////////////////////////////////////////////////////
  82. //
  83. // ~CBookmarksNavPane
  84. //
  85. CBookmarksNavPane::~CBookmarksNavPane()
  86. {
  87. //--- Persist Keywords in combo
  88. SaveBookmarks() ;
  89. //--- Empty the listview.
  90. int items = ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
  91. if (items > 0)
  92. {
  93. // Iterate through each item get its size.
  94. for (int i = 0 ; i < items ; i++)
  95. {
  96. TCHAR* pUrl = GetUrl(i) ;
  97. ASSERT(pUrl) ;
  98. if (pUrl)
  99. {
  100. // Delete the attached url.
  101. delete [] pUrl ;
  102. }
  103. }
  104. // Delete all of the items
  105. W_ListView_DeleteAllItems(m_aDlgItems[c_TopicsList].m_hWnd) ;
  106. }
  107. //--- CleanUp
  108. if (m_hfont)
  109. {
  110. ::DeleteObject(m_hfont);
  111. }
  112. if (m_hWnd)
  113. {
  114. ::DestroyWindow(m_hWnd) ;
  115. }
  116. if (m_pszCurrentUrl)
  117. {
  118. delete m_pszCurrentUrl ;
  119. }
  120. //Don't free m_pTitleCollection
  121. }
  122. ///////////////////////////////////////////////////////////
  123. //
  124. // INavUI Interface functions.
  125. //
  126. ///////////////////////////////////////////////////////////
  127. //
  128. // Create
  129. //
  130. BOOL
  131. CBookmarksNavPane::Create(HWND hwndParent)
  132. {
  133. bool bReturn = false ;
  134. if (m_hWnd)
  135. {
  136. return true ;
  137. }
  138. // ---Create the dialog.
  139. bool bUnicode = true;
  140. if (! (m_hWnd = CreateDialogParamW(
  141. _Module.GetResourceInstance(),
  142. MAKEINTRESOURCEW(IDPAGE_TAB_BOOKMARKS),
  143. hwndParent,
  144. s_DialogProc,
  145. reinterpret_cast<LPARAM>(this))) ) // Pass over the this pointer.
  146. {
  147. bUnicode = FALSE;
  148. if (! (m_hWnd = CreateDialogParamA(
  149. _Module.GetResourceInstance(),
  150. MAKEINTRESOURCEA(IDPAGE_TAB_BOOKMARKS),
  151. hwndParent,
  152. s_DialogProc,
  153. reinterpret_cast<LPARAM>(this))) ) // Pass over the this pointer.
  154. return FALSE;
  155. }
  156. //--- Initialize the DlgItem Array.
  157. InitDlgItemArray() ;
  158. //--- Initialize the bookmarks list
  159. // Setup the columnsin the listview ;
  160. LV_COLUMNW column;
  161. column.mask = LVCF_FMT | LVCF_WIDTH;
  162. column.cx = 1500; //TODO FIX
  163. column.fmt = LVCFMT_LEFT;
  164. //column.iSubItem = 0;
  165. W_EnableUnicode(m_aDlgItems[c_TopicsList].m_hWnd, W_ListView);
  166. W_ListView_InsertColumn(m_aDlgItems[c_TopicsList].m_hWnd, 0, &column );
  167. // Sub-class the list view
  168. if (s_lpfnlListViewWndProc == NULL)
  169. {
  170. s_lpfnlListViewWndProc = W_GetWndProc(m_aDlgItems[c_TopicsList].m_hWnd, bUnicode);
  171. }
  172. W_SubClassWindow(m_aDlgItems[c_TopicsList].m_hWnd, reinterpret_cast<LONG_PTR>(s_ListViewProc), bUnicode);
  173. SETTHIS(m_aDlgItems[c_TopicsList].m_hWnd);
  174. //--- Initialize the Current Topic Edit Control
  175. // Limit the amount of text which can be typed in.
  176. Edit_LimitText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, MAX_PATH-1) ;
  177. // Subclass the keyword combo so that we can process the keys
  178. if (s_lpfnlCurrentTopicEditProc == NULL)
  179. {
  180. s_lpfnlCurrentTopicEditProc = W_GetWndProc(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, bUnicode);
  181. }
  182. W_SubClassWindow(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, reinterpret_cast<LONG_PTR>(s_CurrentTopicEditProc), bUnicode);
  183. SETTHIS(m_aDlgItems[c_CurrentTopicEdit].m_hWnd);
  184. //--- Subclass all of the buttons
  185. // Start with the StartSearch button ;
  186. if (s_lpfnlGenericBtnProc == NULL)
  187. {
  188. s_lpfnlGenericBtnProc = W_GetWndProc(m_aDlgItems[c_DeleteBtn].m_hWnd, bUnicode);
  189. }
  190. W_SubClassWindow(m_aDlgItems[c_DeleteBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
  191. SETTHIS(m_aDlgItems[c_DeleteBtn].m_hWnd);
  192. // Bitmap btn
  193. W_SubClassWindow(m_aDlgItems[c_DisplayBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
  194. SETTHIS(m_aDlgItems[c_DisplayBtn].m_hWnd);
  195. // c_DisplayBtn
  196. W_SubClassWindow(m_aDlgItems[c_AddBookmarkBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
  197. SETTHIS(m_aDlgItems[c_AddBookmarkBtn].m_hWnd);
  198. #if 0
  199. //--- Set the font. This will fix some dbcs issues.
  200. for (int i = 0 ; i < c_NumDlgItems ; i++)
  201. {
  202. SendMessage(m_aDlgItems[i].m_hWnd, WM_SETFONT, (WPARAM) GetFont(), FALSE);
  203. }
  204. #endif
  205. SendMessage(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, WM_SETFONT, (WPARAM) GetFont(), FALSE);
  206. SendMessage(m_aDlgItems[c_TopicsList].m_hWnd, WM_SETFONT, (WPARAM) GetAccessableContentFont(), FALSE);
  207. //--- Fill the combobox with persisted data.
  208. LoadBookmarks() ;
  209. // Set the focus to the appropriate control.
  210. SetDefaultFocus() ;
  211. //TODO: Fix
  212. return true;
  213. }
  214. ///////////////////////////////////////////////////////////
  215. //
  216. // OnCommand
  217. //
  218. LRESULT
  219. CBookmarksNavPane::OnCommand(HWND hwnd, UINT id, UINT NotifyCode, LPARAM lParam)
  220. {
  221. switch(NotifyCode)
  222. {
  223. case BN_CLICKED:
  224. switch(id)
  225. {
  226. case IDC_BOOKMARKS_DELETE_BTN:
  227. OnDelete() ;
  228. break;
  229. case IDC_BOOKMARKS_DISPLAY_BTN:
  230. OnDisplay() ;
  231. break ;
  232. case IDC_BOOKMARKS_ADDBOOKMARK_BTN:
  233. OnAddBookmark();
  234. break;
  235. case IDC_BOOKMARKS_EDIT_BTN:
  236. OnEdit() ;
  237. break;
  238. default:
  239. return 0 ;
  240. }
  241. return 1 ;
  242. }
  243. return 0 ;
  244. }
  245. ///////////////////////////////////////////////////////////
  246. //
  247. // ResizeWindow
  248. //
  249. void
  250. CBookmarksNavPane::ResizeWindow()
  251. {
  252. ASSERT(::IsValidWindow(m_hWnd)) ;
  253. // Resize to fit the client area of the parent.
  254. HWND hwndParent = GetParent(m_hWnd) ;
  255. ASSERT(::IsValidWindow(hwndParent)) ;
  256. //--- Get the size of the window
  257. RECT rcParent;
  258. GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
  259. //--- Move and size the dialog box itself.
  260. ::SetWindowPos( m_hWnd, NULL, rcParent.left, rcParent.top,
  261. rcParent.right-rcParent.left,
  262. rcParent.bottom-rcParent.top,
  263. SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOREDRAW);
  264. //---Fix the painting bugs. However, this is a little on the flashy side.
  265. ::InvalidateRect(m_hWnd, NULL, TRUE) ;
  266. RECT rcDlg;
  267. ::GetClientRect(m_hWnd, &rcDlg) ;
  268. //--- Now position each control within this space.
  269. for (int i = 0 ; i < c_NumDlgItems ; i++)
  270. {
  271. // Get Current Settings.
  272. int X = m_aDlgItems[i].m_rectCur.left;
  273. int Y = m_aDlgItems[i].m_rectCur.top;
  274. int CX = m_aDlgItems[i].m_rectCur.right - m_aDlgItems[i].m_rectCur.left;
  275. int CY = m_aDlgItems[i].m_rectCur.bottom - m_aDlgItems[i].m_rectCur.top;
  276. bool bChanged = false ;
  277. //--- RIGHT JUSTIFICATION
  278. if (m_aDlgItems[i].m_JustifyH == Justify::Right)
  279. {
  280. int NewX = rcDlg.right-m_aDlgItems[i].m_iOffsetH ; // subtract the offset
  281. int MinX = m_aDlgItems[i].m_rectMin.left;
  282. if (NewX < MinX)
  283. {
  284. NewX = MinX; // Don't go below min.
  285. }
  286. if (X != NewX)
  287. {
  288. X = NewX ; // Update the current setting.
  289. bChanged = true ;
  290. }
  291. }
  292. //--- BOTTOM JUSTIFICATION
  293. if (m_aDlgItems[i].m_JustifyV == Justify::Bottom)
  294. {
  295. int NewY = rcDlg.bottom - m_aDlgItems[i].m_iOffsetV;
  296. int MinY = m_aDlgItems[i].m_rectMin.top ;
  297. if (NewY < MinY)
  298. {
  299. NewY = MinY ;
  300. }
  301. if (Y != NewY)
  302. {
  303. Y = NewY ; // Update Setting.
  304. bChanged = true ;
  305. }
  306. }
  307. //--- HORIZONTAL GROWING
  308. if (m_aDlgItems[i].m_bGrowH)
  309. {
  310. int MaxCX = m_aDlgItems[i].m_rectMax.right - m_aDlgItems[i].m_rectMax.left ;
  311. int MinCX = m_aDlgItems[i].m_rectMin.right - m_aDlgItems[i].m_rectMin.left ;
  312. int MinCY = m_aDlgItems[i].m_rectMin.bottom - m_aDlgItems[i].m_rectMin.top ;
  313. int NewRight = rcDlg.right - m_aDlgItems[i].m_iPadH ;
  314. int NewCX = NewRight - m_aDlgItems[i].m_rectMin.left;
  315. if (NewCX < MinCX)
  316. {
  317. NewCX = MinCX;
  318. }
  319. else if ((!m_aDlgItems[i].m_bIgnoreMax) && NewCX > MaxCX)
  320. {
  321. NewCX = MaxCX ;
  322. }
  323. if (CX != NewCX)
  324. {
  325. CX = NewCX ; // Update Current ;
  326. bChanged = true ;
  327. }
  328. }
  329. //--- VERTICAL GROWING
  330. if (m_aDlgItems[i].m_bGrowV)
  331. {
  332. int MaxCY = m_aDlgItems[i].m_rectMax.bottom - m_aDlgItems[i].m_rectMax.top;
  333. int MinCY = m_aDlgItems[i].m_rectMin.bottom - m_aDlgItems[i].m_rectMin.top ;
  334. int MinCX = m_aDlgItems[i].m_rectMin.right - m_aDlgItems[i].m_rectMin.left;
  335. int NewBottom = rcDlg.bottom - m_aDlgItems[i].m_iPadV ;
  336. int NewCY = NewBottom - m_aDlgItems[i].m_rectMin.top;
  337. if (NewCY < MinCY)
  338. {
  339. NewCY = MinCY;
  340. }
  341. else if ((!m_aDlgItems[i].m_bIgnoreMax) && NewCY > MaxCY)
  342. {
  343. NewCY = MaxCY ;
  344. }
  345. if (CY != NewCY)
  346. {
  347. CY = NewCY ;
  348. bChanged = true ;
  349. }
  350. }
  351. if (bChanged)
  352. {
  353. m_aDlgItems[i].m_rectCur.left = X ;
  354. m_aDlgItems[i].m_rectCur.top = Y ;
  355. m_aDlgItems[i].m_rectCur.right = X + CX ;
  356. m_aDlgItems[i].m_rectCur.bottom = Y + CY ;
  357. ::SetWindowPos(m_aDlgItems[i].m_hWnd, NULL,
  358. X, Y, CX, CY,
  359. SWP_NOZORDER | SWP_NOOWNERZORDER /*| SWP_NOREDRAW*/);
  360. // If we have to change the size of the results list, lets change the size of the columns.
  361. /*
  362. if (i == c_ResultsList)
  363. {
  364. m_plistview->SizeColumns() ;
  365. }
  366. */
  367. }
  368. }
  369. }
  370. ///////////////////////////////////////////////////////////
  371. //
  372. // HideWindow
  373. //
  374. void
  375. CBookmarksNavPane::HideWindow()
  376. {
  377. if (::IsValidWindow(m_hWnd))
  378. {
  379. ::ShowWindow(m_hWnd, SW_HIDE) ;
  380. }
  381. }
  382. ///////////////////////////////////////////////////////////
  383. //
  384. // ShowWindow
  385. //
  386. void
  387. CBookmarksNavPane::ShowWindow()
  388. {
  389. if (::IsValidWindow(m_hWnd))
  390. {
  391. // Turn the dialog items on/off
  392. ShowDlgItemsEnabledState() ;
  393. // Show the dialog window.
  394. ::ShowWindow(m_hWnd, SW_SHOW) ;
  395. }
  396. }
  397. ///////////////////////////////////////////////////////////
  398. //
  399. // SetPadding
  400. //
  401. void
  402. CBookmarksNavPane::SetPadding(int pad)
  403. {
  404. m_padding = pad;
  405. }
  406. ///////////////////////////////////////////////////////////
  407. //
  408. // SetTabPos
  409. //
  410. void
  411. CBookmarksNavPane::SetTabPos(int tabpos)
  412. {
  413. m_NavTabPos = tabpos;
  414. }
  415. ///////////////////////////////////////////////////////////
  416. //
  417. // SetDefaultFocus --- Set focus to the most expected control, usually edit combo.
  418. //
  419. void
  420. CBookmarksNavPane::SetDefaultFocus()
  421. {
  422. if (::IsValidWindow(m_aDlgItems[c_TopicsList].m_hWnd))
  423. {
  424. BookmarkDlgItemInfoIndex ctrl ;
  425. int items = W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
  426. if (items > 0)
  427. {
  428. // Set focus to the topics list if we have any entries in it.
  429. ctrl = c_TopicsList ;
  430. // Set the focus if nothing selected.
  431. if (GetSelectedItem() < 0)
  432. {
  433. W_ListView_SetItemState(m_aDlgItems[c_TopicsList].m_hWnd, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED) ;
  434. }
  435. }
  436. else
  437. {
  438. // Set focus to the edit control if the topic listis empty.
  439. ctrl = c_CurrentTopicEdit ;
  440. }
  441. SetFocus(m_aDlgItems[ctrl].m_hWnd) ;
  442. }
  443. }
  444. ///////////////////////////////////////////////////////////
  445. //
  446. // ProcessMenuChar --- Process accelerator keys.
  447. //
  448. bool
  449. CBookmarksNavPane::ProcessMenuChar(HWND hwndParent, int ch)
  450. {
  451. return ::ProcessMenuChar(this, hwndParent, m_aDlgItems, c_NumDlgItems, ch) ;
  452. }
  453. ///////////////////////////////////////////////////////////
  454. //
  455. // OnNotify --- Process WM_NOTIFY messages. Used by embedded Tree and List view controls.
  456. //
  457. LRESULT
  458. CBookmarksNavPane::OnNotify(HWND hwnd, WPARAM idCtrl, LPARAM lParam)
  459. {
  460. switch(idCtrl)
  461. {
  462. case IDC_BOOKMARKS_TOPICS_LISTVIEW:
  463. if (::IsValidWindow(m_aDlgItems[c_TopicsList].m_hWnd))
  464. {
  465. return ListViewMsg(m_aDlgItems[c_TopicsList].m_hWnd, (NM_LISTVIEW*) lParam);
  466. }
  467. break ;
  468. default:
  469. //return DefDlgProc(m_hWnd, WM_NOTIFY, idCtrl, lParam);
  470. return 0 ;
  471. }
  472. return 0 ;
  473. }
  474. ///////////////////////////////////////////////////////////
  475. //
  476. // OnDrawItem --- Process WM_DRAWITEM messages.
  477. //
  478. void
  479. CBookmarksNavPane::OnDrawItem(UINT id, LPDRAWITEMSTRUCT pdis)
  480. {
  481. }
  482. ///////////////////////////////////////////////////////////
  483. //
  484. // Seed --- Seed the nav ui with a search term or keyword.
  485. //
  486. void
  487. CBookmarksNavPane::Seed(LPCSTR pszSeed)
  488. {
  489. }
  490. ///////////////////////////////////////////////////////////
  491. //
  492. // Synchronize
  493. //
  494. BOOL
  495. CBookmarksNavPane::Synchronize(PSTR pNotUsed, CTreeNode* pNotUsed2)
  496. {
  497. if (pNotUsed == NULL && pNotUsed2 == NULL)
  498. {
  499. FillCurrentTopicEdit() ;
  500. return TRUE ;
  501. }
  502. else
  503. {
  504. return FALSE ;
  505. }
  506. }
  507. ///////////////////////////////////////////////////////////
  508. //
  509. // Helper Functions.
  510. //
  511. ///////////////////////////////////////////////////////////
  512. //
  513. // InitDlgItemArray
  514. //
  515. void
  516. CBookmarksNavPane::InitDlgItemArray()
  517. {
  518. RECT rectCurrent ;
  519. RECT rectDlg ;
  520. ::GetClientRect(m_hWnd, &rectDlg) ;
  521. //--- Setup the dlg array for each control.
  522. //--- Topics ListView
  523. int i = c_TopicsList;
  524. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_TOPICS_LISTVIEW) ;
  525. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  526. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  527. DWORD_PTR dwCurrentExtendedStyles = GetWindowLongPtr(m_aDlgItems[i].m_hWnd, GWL_EXSTYLE);
  528. SetWindowLongPtr(m_aDlgItems[i].m_hWnd, GWL_EXSTYLE, dwCurrentExtendedStyles | g_RTL_Mirror_Style);
  529. m_aDlgItems[i].m_id = IDC_BOOKMARKS_TOPICS_LISTVIEW;
  530. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hWnd, IDC_BOOKMARKS_TOPICS_STATIC); // No accelerator.
  531. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  532. m_aDlgItems[i].m_bIgnoreEnabled = TRUE ;
  533. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  534. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  535. m_aDlgItems[i].m_bGrowH = TRUE; // Grow Horizontally.
  536. m_aDlgItems[i].m_bGrowV = TRUE ; // Grow Vertically.
  537. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  538. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point.
  539. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  540. //m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  541. m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  542. m_aDlgItems[i].m_iPadV = rectDlg.bottom - rectCurrent.bottom;
  543. m_aDlgItems[i].m_rectMin = rectCurrent;
  544. m_aDlgItems[i].m_rectCur = rectCurrent;
  545. //m_aDlgItems[i].m_rectMax ; // Max size.
  546. //--- Delete Button
  547. i = c_DeleteBtn;
  548. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_DELETE_BTN) ;
  549. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  550. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  551. m_aDlgItems[i].m_id = IDC_BOOKMARKS_DELETE_BTN;
  552. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd) ;
  553. m_aDlgItems[i].m_Type = ItemInfo::Button;
  554. m_aDlgItems[i].m_bIgnoreEnabled = FALSE;
  555. m_aDlgItems[i].m_bEnabled = FALSE; // Is the control enabled?
  556. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  557. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  558. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  559. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  560. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // Distance from our justification point.
  561. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  562. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  563. //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding.
  564. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  565. m_aDlgItems[i].m_rectMin = rectCurrent;
  566. m_aDlgItems[i].m_rectCur = rectCurrent;
  567. //m_aDlgItems[i].m_rectMax ; // Max size.
  568. //--- Display Button
  569. i = c_DisplayBtn;
  570. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_DISPLAY_BTN) ;
  571. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  572. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  573. m_aDlgItems[i].m_id = IDC_BOOKMARKS_DISPLAY_BTN;
  574. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd) ;
  575. m_aDlgItems[i].m_Type = ItemInfo::Button;
  576. m_aDlgItems[i].m_bIgnoreEnabled = FALSE;
  577. m_aDlgItems[i].m_bEnabled = FALSE; // Is the control enabled?
  578. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  579. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  580. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  581. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  582. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // Distance from our justification point.
  583. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  584. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  585. //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding.
  586. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  587. m_aDlgItems[i].m_rectMin = rectCurrent;
  588. m_aDlgItems[i].m_rectCur = rectCurrent;
  589. //m_aDlgItems[i].m_rectMax ; // Max size.
  590. //--- Current Topics Static
  591. i = c_CurrentTopicStatic;
  592. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_CURRENTTOPIC_STATIC) ;
  593. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  594. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  595. m_aDlgItems[i].m_id = IDC_BOOKMARKS_CURRENTTOPIC_STATIC;
  596. m_aDlgItems[i].m_accelkey = 0 ;
  597. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  598. m_aDlgItems[i].m_bIgnoreEnabled = TRUE ;
  599. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  600. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  601. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  602. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  603. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  604. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // Distance from our justification point.
  605. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  606. //m_aDlgItems[i].m_iOffsetH =
  607. //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding.
  608. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  609. m_aDlgItems[i].m_rectMin = rectCurrent;
  610. m_aDlgItems[i].m_rectCur = rectCurrent;
  611. //m_aDlgItems[i].m_rectMax ; // Max size.
  612. //--- Current Topics Edit control
  613. i = c_CurrentTopicEdit;
  614. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_CURRENTTOPIC_EDIT) ;
  615. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  616. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  617. dwCurrentExtendedStyles = GetWindowLongPtr(m_aDlgItems[i].m_hWnd, GWL_EXSTYLE);
  618. SetWindowLongPtr(m_aDlgItems[i].m_hWnd, GWL_EXSTYLE, dwCurrentExtendedStyles | g_RTL_Style);
  619. m_aDlgItems[i].m_id = IDC_BOOKMARKS_CURRENTTOPIC_EDIT;
  620. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hWnd, IDC_BOOKMARKS_CURRENTTOPIC_STATIC);
  621. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  622. m_aDlgItems[i].m_bIgnoreEnabled = TRUE ;
  623. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  624. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  625. m_aDlgItems[i].m_bGrowH = TRUE; // Grow Horizontally.
  626. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  627. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  628. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // Distance from our justification point.
  629. m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
  630. //m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  631. m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
  632. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  633. m_aDlgItems[i].m_rectMin = rectCurrent;
  634. m_aDlgItems[i].m_rectCur = rectCurrent;
  635. //m_aDlgItems[i].m_rectMax ; // Max size.
  636. //--- Add Button
  637. i = c_AddBookmarkBtn ;
  638. m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_ADDBOOKMARK_BTN) ;
  639. ::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  640. ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  641. m_aDlgItems[i].m_id = IDC_BOOKMARKS_ADDBOOKMARK_BTN;
  642. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd) ;
  643. m_aDlgItems[i].m_Type = ItemInfo::Button;
  644. m_aDlgItems[i].m_bIgnoreEnabled = TRUE ;
  645. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  646. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  647. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  648. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  649. m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
  650. m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // Distance from our justification point.
  651. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  652. m_aDlgItems[i].m_iOffsetH =rectDlg.right - rectCurrent.left;
  653. //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding.
  654. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  655. m_aDlgItems[i].m_rectMin = rectCurrent;
  656. m_aDlgItems[i].m_rectCur = rectCurrent;
  657. //m_aDlgItems[i].m_rectMax ; // Max size.
  658. }
  659. ///////////////////////////////////////////////////////////
  660. //
  661. // SetEnabledState
  662. //
  663. void
  664. CBookmarksNavPane::ShowDlgItemsEnabledState()
  665. {
  666. // Enable/Disable all the controls
  667. for (int i = 0 ; i < c_NumDlgItems ; i++)
  668. {
  669. if (!m_aDlgItems[i].m_bIgnoreEnabled && ::IsValidWindow(m_aDlgItems[i].m_hWnd))
  670. {
  671. EnableWindow(m_aDlgItems[i].m_hWnd, m_aDlgItems[i].m_bEnabled) ;
  672. }
  673. }
  674. }
  675. ///////////////////////////////////////////////////////////
  676. //
  677. // EnableDlgItem
  678. //
  679. void
  680. CBookmarksNavPane::EnableDlgItem(BookmarkDlgItemInfoIndex index, bool bEnable)
  681. {
  682. ASSERT(index >= 0 && index < c_NumDlgItems) ;
  683. if (!m_aDlgItems[index].m_bIgnoreEnabled)
  684. {
  685. // Are we enabled or not?
  686. m_aDlgItems[index].m_bEnabled = bEnable ;
  687. // Do it for real.
  688. if (::IsValidWindow(m_aDlgItems[index].m_hWnd))
  689. {
  690. EnableWindow(m_aDlgItems[index].m_hWnd, bEnable) ;
  691. }
  692. }
  693. }
  694. ///////////////////////////////////////////////////////////
  695. //
  696. // SaveBookmarks --- Persists the bookmars to the storage
  697. //
  698. // The bookmarks are stored using the following format:
  699. // Bookmarks
  700. // \v1 - Version.
  701. // \Count - Number of bookmarks written.
  702. // \0 - First bookmark.
  703. // \Topic - Topic Unicode String
  704. // \Url - Url Unicode String
  705. // \1 - Second bookmark.
  706. // ...
  707. // \(count-1)
  708. //
  709. void
  710. CBookmarksNavPane::SaveBookmarks()
  711. {
  712. // Also save the bookmarks, if they have changed.
  713. if (!Changed())
  714. {
  715. return ;
  716. }
  717. // Keep track of the number of bookmarks written.
  718. int cWritten = 0 ;
  719. // Buffer for path to the state folder.
  720. char statepath[64] ;
  721. // Get the state pointer.
  722. CState* pstate = m_pTitleCollection->GetState();
  723. ASSERT(pstate) ;
  724. // Are there any keywords to save.
  725. int items = W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
  726. if (items > 0)
  727. {
  728. // Limit the number. I hate limiting the number, but its much more robust.
  729. if (items > c_MaxBookmarks)
  730. {
  731. items = c_MaxBookmarks ;
  732. }
  733. // Buffer for retrieving the text.
  734. WCHAR Topic[MAX_URL] ;
  735. // Iterate through the items.
  736. for (int i = 0 ; i < items ; i++)
  737. {
  738. TCHAR* pUrl = NULL ;
  739. if (GetTopicAndUrl(i, Topic, sizeof(Topic), &pUrl))
  740. {
  741. //--- Write out topic.
  742. // Construct the path.
  743. wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, cWritten, c_TopicFolder);
  744. if (SUCCEEDED(pstate->Open(statepath, STGM_WRITE)))
  745. {
  746. DWORD cb = (wcslen(Topic)+1)*sizeof(wchar_t) ;
  747. DWORD dwResult = pstate->Write(Topic, cb);
  748. pstate->Close();
  749. // Is result okay?
  750. if (cb == dwResult)
  751. {
  752. //--- Write out the URL.
  753. // Convert to unicode.
  754. CWStr url(pUrl) ;
  755. ASSERT(url.pw) ;
  756. // Construt the path.
  757. wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, cWritten, c_UrlFolder);
  758. // Write out.
  759. if (SUCCEEDED(pstate->Open(statepath, STGM_WRITE)))
  760. {
  761. cb = (wcslen(url.pw)+1)*sizeof(wchar_t) ;
  762. dwResult = pstate->Write(url.pw, cb);
  763. pstate->Close();
  764. // Check result.
  765. if (cb == dwResult)
  766. {
  767. // We have been successful. So Increment the count.
  768. cWritten++ ;
  769. }
  770. }
  771. }
  772. }
  773. } //if
  774. } // for
  775. } // if items
  776. // How many entries are currently stored.
  777. int StoredCount = 0;
  778. if (SUCCEEDED(pstate->Open(c_CountFolder, STGM_READ)))
  779. {
  780. DWORD cbReadIn = 0 ;
  781. pstate->Read(&StoredCount , sizeof(StoredCount), &cbReadIn) ;
  782. pstate->Close() ;
  783. if (cbReadIn != sizeof(StoredCount))
  784. {
  785. // Assume that we don't have any stored.
  786. StoredCount = 0 ;
  787. }
  788. }
  789. // Delete the extra entries.
  790. if (StoredCount > cWritten)
  791. {
  792. // Delete extra entries.
  793. for(int j = cWritten ; j < StoredCount ; j++)
  794. {
  795. // Remove the URL folder.
  796. wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, j, c_UrlFolder);
  797. if (SUCCEEDED(pstate->Open(statepath, STGM_READ)))
  798. {
  799. HRESULT hr = pstate->Delete() ;
  800. ASSERT(SUCCEEDED(hr)) ;
  801. pstate->Close() ;
  802. }
  803. // Remove the topic folder.
  804. wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, j, c_TopicFolder);
  805. if (SUCCEEDED(pstate->Open(statepath, STGM_WRITE)))
  806. {
  807. HRESULT hr = pstate->Delete() ;
  808. ASSERT(SUCCEEDED(hr)) ;
  809. pstate->Close() ;
  810. }
  811. // Remove branch.
  812. wsprintf(statepath, "%s\\%d", c_PersistFolder, j);
  813. if (SUCCEEDED(pstate->Open(statepath, STGM_WRITE)))
  814. {
  815. HRESULT hr = pstate->Delete() ;
  816. ASSERT(SUCCEEDED(hr)) ;
  817. pstate->Close() ;
  818. }
  819. }
  820. }
  821. // Write out the count.
  822. if (cWritten >= 0) // We may have deleted everything, so count can be zero.
  823. {
  824. // Write out the new count.
  825. if (SUCCEEDED(pstate->Open(c_CountFolder, STGM_WRITE)))
  826. {
  827. DWORD cb = pstate->Write(&cWritten, sizeof(cWritten));
  828. ASSERT(cb == sizeof(cWritten)) ; // TODO: Handle error.
  829. pstate->Close() ;
  830. // Reset dirty flag ;
  831. SetChanged(false) ;
  832. }
  833. }
  834. else
  835. {
  836. //TODO: Erase everything. That is there.
  837. }
  838. }
  839. ///////////////////////////////////////////////////////////
  840. //
  841. // LoadBookmarks - Loads the results list from the storage
  842. //
  843. void
  844. CBookmarksNavPane::LoadBookmarks()
  845. {
  846. CState* pstate = m_pTitleCollection->GetState();
  847. if (SUCCEEDED(pstate->Open(c_CountFolder, STGM_READ)))
  848. {
  849. // Read in the topics stored.
  850. DWORD cbReadIn = 0 ;
  851. int StoredCount = 0;
  852. pstate->Read(&StoredCount , sizeof(StoredCount), &cbReadIn) ;
  853. pstate->Close() ;
  854. // Did we get a reasonable number?
  855. if (cbReadIn == sizeof(StoredCount) &&
  856. StoredCount > 0 &&
  857. StoredCount < c_MaxBookmarks) // We check the max here just to sure we have reasonable numbers.
  858. {
  859. // Buffer for path to the state folder.
  860. char statepath[64] ;
  861. WCHAR buffer[MAX_URL] ;
  862. // Now let's read them in.
  863. for (int i=0 ; i < StoredCount ; i++)
  864. {
  865. //--- Read in the URL.
  866. TCHAR* pUrl = NULL ;
  867. // Construct the path.
  868. wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, i, c_UrlFolder);
  869. // Open Topic in.
  870. if (SUCCEEDED(pstate->Open(statepath, STGM_READ)))
  871. {
  872. // Read it into the buffer.
  873. DWORD cb = NULL ;
  874. HRESULT hr = pstate->Read(&buffer, sizeof(buffer), &cb);
  875. pstate->Close();
  876. // Check result.
  877. if (SUCCEEDED(hr))
  878. {
  879. // Convert from unicode.
  880. CStr strUrl(buffer) ;
  881. ASSERT(strUrl.psz) ;
  882. //--- Read in the topic.
  883. // Construct the path.
  884. wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, i, c_TopicFolder);
  885. if (SUCCEEDED(pstate->Open(statepath, STGM_READ)))
  886. {
  887. cb = NULL;
  888. hr = pstate->Read(&buffer, sizeof(buffer), &cb);
  889. pstate->Close();
  890. if (SUCCEEDED(hr))
  891. {
  892. //--- Save the URL.
  893. TCHAR* pszUrl = new TCHAR[strUrl.strlen()+1] ;
  894. _tcscpy(pszUrl, strUrl.psz) ;
  895. //--- Add the string to the listview.
  896. LV_ITEMW item;
  897. item.mask = LVIF_TEXT | LVIF_PARAM ; //| LVIF_STATE;
  898. item.iImage = 0;
  899. //item.state = LVIS_FOCUSED | LVIS_SELECTED;
  900. //item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  901. item.iItem = 0 ;
  902. item.iSubItem = 0;
  903. item.lParam = (LPARAM)pszUrl;
  904. item.pszText = buffer;
  905. W_ListView_InsertItem( m_aDlgItems[c_TopicsList].m_hWnd, &item );
  906. }
  907. }
  908. }
  909. } // if --- opened topic.
  910. } // for
  911. // We haven't changed.
  912. SetChanged(false) ;
  913. } //if --- count valid
  914. } //if --- Can read count
  915. }
  916. ///////////////////////////////////////////////////////////
  917. //
  918. // FillCurrentTopicEdit
  919. //
  920. void
  921. CBookmarksNavPane::FillCurrentTopicEdit()
  922. {
  923. ASSERT(m_pWinType && m_pWinType->m_pCIExpContainer && m_pWinType->m_pCIExpContainer->m_pWebBrowserApp) ;
  924. ASSERT(m_pTitleCollection) ;
  925. //--- Prepare to be re-entered!
  926. // Delete the current URL.
  927. if (m_pszCurrentUrl)
  928. {
  929. delete m_pszCurrentUrl ;
  930. m_pszCurrentUrl = NULL ;
  931. }
  932. // Clear out the edit control.
  933. W_SetWindowText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, L"") ;
  934. //--- Get to work.
  935. CStr url ;
  936. if (m_pWinType && m_pWinType->m_pCIExpContainer && m_pWinType->m_pCIExpContainer->m_pWebBrowserApp)
  937. {
  938. // Get the URL of the current topic.
  939. m_pWinType->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&url); //Urg there is no error return!!!
  940. if (!url.IsEmpty())
  941. {
  942. //--- Save the URL before we normalize it.
  943. m_pszCurrentUrl = new TCHAR[url.strlen()+1] ;
  944. _tcscpy(m_pszCurrentUrl,url.psz) ;
  945. // Nomalize the URL
  946. NormalizeUrlInPlace(url) ;
  947. // Use the url to get a CExTitle pointer.
  948. bool bFoundTitle = false; // Did we find a title?
  949. CExTitle *pTitle = NULL ;
  950. HRESULT hr = m_pTitleCollection->URL2ExTitle(m_pszCurrentUrl, &pTitle);
  951. if (SUCCEEDED(hr) && pTitle)
  952. {
  953. // Use the pTitle to get the topic number.
  954. //TOC_TOPIC topic ; // Don't need
  955. DWORD topicnumber;
  956. hr = pTitle->URL2Topic(url, NULL/*&topic*/, &topicnumber);
  957. if (SUCCEEDED(hr))
  958. {
  959. // Now that we have a topic number we can get the location string.
  960. WCHAR wszCurrentTopic[MAX_PATH] ;
  961. hr = pTitle->GetTopicName(topicnumber, wszCurrentTopic, (MAX_PATH/2)) ;
  962. if (SUCCEEDED(hr))
  963. {
  964. // Yea, we finally have a location
  965. W_SetWindowText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, wszCurrentTopic) ;
  966. // We have found the title!
  967. bFoundTitle = true ;
  968. }
  969. }
  970. }
  971. // We have not found the title. Maybe its a web site.
  972. if (!bFoundTitle)
  973. {
  974. ASSERT(m_pszCurrentUrl) ;
  975. // convert URL to wide...
  976. CWStr wurl(url) ;
  977. ASSERT(wurl.pw) ;
  978. // So put he normalized URL into the edit control.
  979. W_SetWindowText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, wurl.pw) ;
  980. }
  981. }
  982. }
  983. }
  984. ///////////////////////////////////////////////////////////
  985. //
  986. // Get the selected item
  987. //
  988. CBookmarksNavPane::GetSelectedItem() const
  989. {
  990. int indexSelected = -1 ;
  991. int selections = W_ListView_GetSelectedCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
  992. if (selections > 0)
  993. {
  994. ASSERT(selections == 1) ;
  995. indexSelected = W_ListView_GetNextItem(m_aDlgItems[c_TopicsList].m_hWnd, -1, LVNI_SELECTED) ;
  996. }
  997. return indexSelected ;
  998. }
  999. ///////////////////////////////////////////////////////////
  1000. //
  1001. // Get the Url for the item
  1002. //
  1003. TCHAR*
  1004. CBookmarksNavPane::GetUrl(int index) const
  1005. {
  1006. TCHAR* pReturn = NULL ;
  1007. if ((index >= 0) && (index < W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd)))
  1008. {
  1009. LV_ITEMW item ;
  1010. item.mask = LVIF_PARAM;
  1011. item.iItem = index;
  1012. item.iSubItem = 0;
  1013. item.lParam = NULL;
  1014. W_ListView_GetItem(m_aDlgItems[c_TopicsList].m_hWnd, &item) ;
  1015. pReturn = (TCHAR*)item.lParam ;
  1016. }
  1017. return pReturn ;
  1018. }
  1019. ///////////////////////////////////////////////////////////
  1020. //
  1021. // Get the URL and the Topic name.
  1022. //
  1023. bool
  1024. CBookmarksNavPane::GetTopicAndUrl(
  1025. int index, //[in] Index
  1026. WCHAR* pTopicBuffer, //[in] Buffer for the topic.
  1027. int TopicBufferSize, //[in] Size of the topic buffer.
  1028. TCHAR** pUrl //[out] Pointer to Url.
  1029. ) const
  1030. {
  1031. bool bReturn = false ;
  1032. if ((index >= 0) && (index < W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd)))
  1033. {
  1034. LV_ITEMW item ;
  1035. item.mask = LVIF_PARAM | LVIF_TEXT ;
  1036. item.iItem = index;
  1037. item.iSubItem = 0;
  1038. item.lParam = NULL ;
  1039. item.pszText = pTopicBuffer;
  1040. item.cchTextMax = TopicBufferSize ;
  1041. if (W_ListView_GetItem(m_aDlgItems[c_TopicsList].m_hWnd, &item))
  1042. {
  1043. *pUrl = (TCHAR*)item.lParam ;
  1044. ASSERT(*pUrl) ;
  1045. if (*pUrl) //TODO: Validate pTopicBuffer ;
  1046. {
  1047. bReturn = true;
  1048. }
  1049. }
  1050. else
  1051. {
  1052. bReturn = false ;
  1053. }
  1054. }
  1055. return bReturn ;
  1056. }
  1057. ///////////////////////////////////////////////////////////
  1058. //
  1059. // ContextMenu
  1060. //
  1061. void
  1062. CBookmarksNavPane::ContextMenu(bool bUseCursor)
  1063. {
  1064. // Create the menu.
  1065. HMENU hMenu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDM_BOOKMARKS_OPTIONS_MENU)) ;
  1066. ASSERT(hMenu) ;
  1067. // Get the Popup Menu
  1068. HMENU hPopupMenu = GetSubMenu(hMenu, 0) ;
  1069. // Is an item selected?
  1070. int bState ;
  1071. int selection = GetSelectedItem() ;
  1072. if (selection < 0)
  1073. {
  1074. // Nothing selected.
  1075. bState = MF_GRAYED ;
  1076. }
  1077. else
  1078. {
  1079. bState = MF_ENABLED ;
  1080. }
  1081. // Set state of menu items.
  1082. EnableMenuItem(hPopupMenu, IDC_BOOKMARKS_DELETE_BTN, MF_BYCOMMAND | bState) ;
  1083. EnableMenuItem(hPopupMenu, IDC_BOOKMARKS_DISPLAY_BTN, MF_BYCOMMAND | bState ) ;
  1084. EnableMenuItem(hPopupMenu, IDC_BOOKMARKS_EDIT_BTN, MF_BYCOMMAND | bState) ;
  1085. // Always enabled.
  1086. EnableMenuItem(hPopupMenu, IDC_BOOKMARKS_ADDBOOKMARK_BTN, MF_BYCOMMAND | MF_ENABLED) ;
  1087. // Set the style of the menu.
  1088. DWORD style = TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_RIGHTBUTTON;
  1089. //--- Get the location to display the menu
  1090. POINT pt ;
  1091. if (bUseCursor)
  1092. {
  1093. // Use the mouse cursor position.
  1094. GetCursorPos(&pt) ;
  1095. }
  1096. else
  1097. {
  1098. // Use the upper right of the client area. Probably invoked by shift-F10
  1099. RECT rc;
  1100. GetClientRect(m_aDlgItems[c_TopicsList].m_hWnd, &rc) ; //REVIEW: Upper corner should always be 0,0. Remove?
  1101. pt.x = rc.left;
  1102. pt.y = rc.top ;
  1103. ClientToScreen(m_aDlgItems[c_TopicsList].m_hWnd, &pt);
  1104. }
  1105. // Display the menu.
  1106. int iCmd = TrackPopupMenuEx(hPopupMenu,
  1107. style ,
  1108. pt.x, pt.y,
  1109. m_hWnd,
  1110. NULL) ;
  1111. // Act on the item.
  1112. if (iCmd != 0)
  1113. {
  1114. OnCommand(m_hWnd, iCmd, BN_CLICKED, NULL);
  1115. }
  1116. // Cleanup
  1117. DestroyMenu(hMenu) ;
  1118. }
  1119. ///////////////////////////////////////////////////////////
  1120. //
  1121. // Message Handlers
  1122. //
  1123. ///////////////////////////////////////////////////////////
  1124. //
  1125. // OnDelete
  1126. //
  1127. void
  1128. CBookmarksNavPane::OnDelete()
  1129. {
  1130. int indexSelected = GetSelectedItem() ;
  1131. HWND hwndFocus = ::GetFocus();
  1132. BOOL bDeletedLast = FALSE;
  1133. if (indexSelected >= 0)
  1134. {
  1135. TCHAR* pUrl = GetUrl(indexSelected) ;
  1136. ASSERT(pUrl) ;
  1137. if (pUrl)
  1138. {
  1139. // Delete the attached url.
  1140. delete [] pUrl ;
  1141. }
  1142. // Delete the item
  1143. BOOL b = W_ListView_DeleteItem(m_aDlgItems[c_TopicsList].m_hWnd, indexSelected) ;
  1144. ASSERT(b) ;
  1145. // Set changed flag.
  1146. SetChanged() ;
  1147. // Select the item below the one we just deleted.
  1148. int items = W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
  1149. if (items > 0)
  1150. {
  1151. if (indexSelected >= items)
  1152. {
  1153. indexSelected = items-1 ;
  1154. }
  1155. // The following should never happen, but its better safe in beta2...
  1156. if (indexSelected < 0)
  1157. {
  1158. ASSERT(indexSelected < 0) ;
  1159. indexSelected = 0 ;
  1160. }
  1161. W_ListView_SetItemState(m_aDlgItems[c_TopicsList].m_hWnd, indexSelected, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED) ;
  1162. }
  1163. else
  1164. bDeletedLast = TRUE;
  1165. }
  1166. if (bDeletedLast == TRUE)
  1167. ::SetFocus(m_aDlgItems[c_AddBookmarkBtn].m_hWnd);
  1168. else
  1169. if (hwndFocus != m_aDlgItems[c_TopicsList].m_hWnd)
  1170. ::SetFocus(hwndFocus);
  1171. }
  1172. ///////////////////////////////////////////////////////////
  1173. //
  1174. // OnDisplay
  1175. //
  1176. void
  1177. CBookmarksNavPane::OnDisplay()
  1178. {
  1179. // Get the selected URL.
  1180. TCHAR* pUrl = GetSelectedUrl() ;
  1181. if (pUrl)
  1182. {
  1183. // Change to this URL.
  1184. ChangeHtmlTopic(pUrl, m_hWnd, 0);
  1185. }
  1186. }
  1187. ///////////////////////////////////////////////////////////
  1188. //
  1189. // OnAddBookmark
  1190. //
  1191. void
  1192. CBookmarksNavPane::OnAddBookmark()
  1193. {
  1194. int len = W_GetTextLengthExact(m_aDlgItems[c_CurrentTopicEdit].m_hWnd) ;
  1195. if (len > 0)
  1196. {
  1197. // Get the string from the edit control
  1198. WCHAR* pCurrentTopicTitle = new WCHAR[len+1] ;
  1199. W_GetWindowText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, pCurrentTopicTitle, len+1) ;
  1200. //--- Copy the URL.
  1201. ASSERT(m_pszCurrentUrl) ;
  1202. TCHAR* pszUrl = new TCHAR[_tcslen(m_pszCurrentUrl)+1] ;
  1203. _tcscpy(pszUrl, m_pszCurrentUrl) ;
  1204. //--- Add the string to the listview.
  1205. LV_ITEMW item;
  1206. item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  1207. item.iImage = 0;
  1208. item.state = LVIS_FOCUSED | LVIS_SELECTED;
  1209. item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  1210. item.iItem = 0 ;
  1211. item.iSubItem = 0;
  1212. item.lParam = (LPARAM)pszUrl;
  1213. item.pszText = pCurrentTopicTitle ;
  1214. int i = W_ListView_InsertItem( m_aDlgItems[c_TopicsList].m_hWnd, &item );
  1215. //Setfocus to list view
  1216. SetFocus(m_aDlgItems[c_TopicsList].m_hWnd) ;
  1217. // Cleanup
  1218. delete [] pCurrentTopicTitle ;
  1219. // Set changed flag.
  1220. SetChanged() ;
  1221. }
  1222. }
  1223. ///////////////////////////////////////////////////////////
  1224. //
  1225. // OnEdit - Handles the edit menu item.
  1226. //
  1227. void
  1228. CBookmarksNavPane::OnEdit()
  1229. {
  1230. // Edit the currently selected item.
  1231. int selection = GetSelectedItem() ;
  1232. if (selection >=0)
  1233. {
  1234. W_ListView_EditLabel(m_aDlgItems[c_TopicsList].m_hWnd, selection) ;
  1235. // Set changed flag.
  1236. SetChanged() ;
  1237. }
  1238. }
  1239. ///////////////////////////////////////////////////////////
  1240. //
  1241. // OnTab - Handles pressing of the tab key.
  1242. //
  1243. void
  1244. CBookmarksNavPane::OnTab(HWND hwndReceivedTab, BookmarkDlgItemInfoIndex /*index*/)
  1245. {
  1246. //if (index == c_NumDlgItems) --- caller doesn't know the index.
  1247. ASSERT(::IsValidWindow(hwndReceivedTab)) ;
  1248. //--- Is the shift key down?
  1249. BOOL bPrevious = (GetKeyState(VK_SHIFT) < 0) ;
  1250. {
  1251. //--- Move to the next control .
  1252. // Get the next tab item.
  1253. HWND hWndNext = GetNextDlgTabItem(m_hWnd, hwndReceivedTab, bPrevious) ;
  1254. // Set focus to it.
  1255. ::SetFocus(hWndNext) ;
  1256. }
  1257. }
  1258. ///////////////////////////////////////////////////////////
  1259. //
  1260. // OnArrow
  1261. //
  1262. void
  1263. CBookmarksNavPane::OnArrow(HWND hwndReceivedTab, BookmarkDlgItemInfoIndex /*index*/, INT_PTR key)
  1264. {
  1265. //if (index == c_NumDlgItems) --- caller doesn't know the index.
  1266. ASSERT(::IsValidWindow(hwndReceivedTab)) ;
  1267. BOOL bPrevious = FALSE ;
  1268. if (key == VK_LEFT || key == VK_UP)
  1269. {
  1270. bPrevious = TRUE ;
  1271. }
  1272. // Get the next tab item.
  1273. HWND hWndNext = GetNextDlgGroupItem(m_hWnd, hwndReceivedTab, bPrevious) ;
  1274. // Set focus to it.
  1275. ::SetFocus(hWndNext) ;
  1276. }
  1277. ///////////////////////////////////////////////////////////
  1278. //
  1279. // OnReturn - Default handling of the return key.
  1280. //
  1281. bool
  1282. CBookmarksNavPane::OnReturn(HWND hwndReceivedTab, BookmarkDlgItemInfoIndex /*index*/)
  1283. {
  1284. //if (index == c_NumDlgItems) --- caller doesn't know the index.
  1285. // Do the default button action.
  1286. // Always do a search topic, if its enabled.
  1287. if (::IsWindowEnabled(m_aDlgItems[c_DisplayBtn].m_hWnd))
  1288. {
  1289. OnDisplay();
  1290. return true ;
  1291. }
  1292. else
  1293. {
  1294. return false ;
  1295. }
  1296. }
  1297. ///////////////////////////////////////////////////////////
  1298. //
  1299. // ListViewMsg
  1300. //
  1301. LRESULT
  1302. CBookmarksNavPane::ListViewMsg(HWND hwnd, NM_LISTVIEW* lParam)
  1303. {
  1304. switch(lParam->hdr.code)
  1305. {
  1306. case NM_DBLCLK:
  1307. case NM_RETURN:
  1308. OnDisplay() ;
  1309. break;
  1310. case NM_RCLICK:
  1311. ContextMenu() ;
  1312. break ;
  1313. case LVN_ITEMCHANGED:
  1314. {
  1315. bool bEnable = GetSelectedItem() >= 0 ;
  1316. EnableDlgItem(c_DisplayBtn, bEnable) ;
  1317. EnableDlgItem(c_DeleteBtn, bEnable) ;
  1318. }
  1319. break ;
  1320. case LVN_BEGINLABELEDITA:
  1321. case LVN_BEGINLABELEDITW:
  1322. /*
  1323. //ListView_GetEditControl();
  1324. //LimitText;
  1325. */
  1326. return FALSE ;
  1327. case LVN_ENDLABELEDITA:
  1328. case LVN_ENDLABELEDITW:
  1329. {
  1330. LV_DISPINFOW* pDispInfo = (LV_DISPINFOW*)lParam ;
  1331. if (pDispInfo->item.iItem != -1 &&
  1332. pDispInfo->item.pszText &&
  1333. lstrlenW(pDispInfo->item.pszText) > 0)
  1334. {
  1335. if(g_fUnicodeListView)
  1336. {
  1337. W_ListView_SetItemText(m_aDlgItems[c_TopicsList].m_hWnd,
  1338. pDispInfo->item.iItem,
  1339. 0,
  1340. pDispInfo->item.pszText) ;
  1341. }
  1342. else
  1343. {
  1344. ListView_SetItemText(m_aDlgItems[c_TopicsList].m_hWnd,
  1345. pDispInfo->item.iItem,
  1346. 0,
  1347. (char *)pDispInfo->item.pszText) ;
  1348. }
  1349. // Set changed flag.
  1350. SetChanged() ;
  1351. return TRUE ; // Accept Edit
  1352. }
  1353. }
  1354. break ;
  1355. }
  1356. return 0;
  1357. }
  1358. ///////////////////////////////////////////////////////////
  1359. //
  1360. // Callback Functions.
  1361. //
  1362. ///////////////////////////////////////////////////////////
  1363. //
  1364. // Static DialogProc
  1365. //
  1366. INT_PTR CALLBACK
  1367. CBookmarksNavPane::s_DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1368. {
  1369. // Call member function dialog proc.
  1370. if (msg == WM_INITDIALOG)
  1371. {
  1372. // The lParam is the this pointer for this dialog box.
  1373. // Save it in the window userdata section.
  1374. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
  1375. }
  1376. // Get the this pointer and call the non-static callback function.
  1377. CBookmarksNavPane* p = reinterpret_cast<CBookmarksNavPane*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA)) ;
  1378. if (p)
  1379. {
  1380. return p->DialogProc(hwnd, msg, wParam, lParam) ;
  1381. }
  1382. else
  1383. {
  1384. return FALSE ;
  1385. }
  1386. }
  1387. ///////////////////////////////////////////////////////////
  1388. //
  1389. // ListViewProc
  1390. //
  1391. LRESULT WINAPI
  1392. CBookmarksNavPane::s_ListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1393. {
  1394. CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
  1395. switch (msg)
  1396. {
  1397. case WM_KEYDOWN:
  1398. if (wParam == VK_RETURN)
  1399. {
  1400. // A return means that we want to display the currently selected topic.
  1401. pThis->OnDisplay() ; //Todo: Should this be a send message?
  1402. return 0 ;
  1403. }
  1404. else if (wParam == VK_TAB)
  1405. {
  1406. pThis->OnTab(hwnd, c_TopicsList) ;
  1407. }
  1408. else if (wParam == VK_F2)
  1409. {
  1410. pThis->OnEdit() ;
  1411. return 0 ;
  1412. }
  1413. break ;
  1414. case WM_SYSKEYDOWN:
  1415. if (wParam == VK_F10 && (GetKeyState(VK_SHIFT) < 0)) // SHIFT-F10
  1416. {
  1417. pThis->ContextMenu(false) ;
  1418. return 0 ;
  1419. }
  1420. break;
  1421. }
  1422. return W_DelegateWindowProc(s_lpfnlListViewWndProc, hwnd, msg, wParam, lParam);
  1423. }
  1424. ///////////////////////////////////////////////////////////
  1425. //
  1426. // KeywordComboEditProc - Subclassed the Edit Control in the Keyword Combo Box
  1427. // The original reason for doing this was to save the selection location.
  1428. //
  1429. LRESULT WINAPI
  1430. CBookmarksNavPane::s_CurrentTopicEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1431. {
  1432. CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
  1433. switch (msg)
  1434. {
  1435. case WM_KEYDOWN:
  1436. if (wParam == VK_TAB)
  1437. {
  1438. pThis->OnTab(hwnd,c_CurrentTopicEdit) ;
  1439. return 0 ;
  1440. }
  1441. else if (wParam == VK_RETURN)
  1442. {
  1443. pThis->OnAddBookmark();
  1444. }
  1445. break;
  1446. case WM_CHAR:
  1447. if (wParam == VK_TAB)
  1448. {
  1449. //Stops the beep!
  1450. return 0 ;
  1451. }
  1452. }
  1453. return W_DelegateWindowProc(s_lpfnlCurrentTopicEditProc, hwnd, msg, wParam, lParam);
  1454. }
  1455. ///////////////////////////////////////////////////////////
  1456. //
  1457. // Generic keyboard handling for all btns.
  1458. //
  1459. LRESULT WINAPI
  1460. CBookmarksNavPane::s_GenericBtnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1461. {
  1462. switch (msg)
  1463. {
  1464. case WM_KEYDOWN:
  1465. if (wParam == VK_RETURN)
  1466. {
  1467. // Do the command associated with this btn.
  1468. CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
  1469. return pThis->OnCommand(pThis->m_hWnd, ::GetDlgCtrlID(hwnd), BN_CLICKED, lParam) ; // TODO: Should this be a sendmessage?
  1470. }
  1471. else if (wParam == VK_TAB)
  1472. {
  1473. CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
  1474. pThis->OnTab(hwnd,c_NumDlgItems) ;
  1475. return 0 ;
  1476. }
  1477. else if (wParam == VK_LEFT ||
  1478. wParam == VK_RIGHT ||
  1479. wParam == VK_UP ||
  1480. wParam == VK_DOWN)
  1481. {
  1482. CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
  1483. pThis->OnArrow(hwnd,c_NumDlgItems, wParam) ;
  1484. return 0 ;
  1485. }
  1486. break;
  1487. }
  1488. return W_DelegateWindowProc(s_lpfnlGenericBtnProc, hwnd, msg, wParam, lParam);
  1489. }
  1490. ///////////////////////////////////////////////////////////
  1491. //
  1492. // DialogProc
  1493. //
  1494. INT_PTR
  1495. CBookmarksNavPane::DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1496. {
  1497. switch(msg)
  1498. {
  1499. case WM_COMMAND:
  1500. return OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), lParam) ;
  1501. break ;
  1502. case WM_NOTIFY:
  1503. return OnNotify(hwnd, wParam, lParam) ;
  1504. case WM_INITDIALOG:
  1505. break;
  1506. case WM_SHOWWINDOW:
  1507. {
  1508. BOOL bActive = (BOOL) wParam ;
  1509. if (bActive)
  1510. {
  1511. FillCurrentTopicEdit() ;
  1512. }
  1513. }
  1514. break ;
  1515. case WM_ACTIVATE:
  1516. {
  1517. int active = LOWORD(wParam) ;
  1518. if (active != WA_INACTIVE)
  1519. {
  1520. FillCurrentTopicEdit() ;
  1521. }
  1522. }
  1523. break ;
  1524. }
  1525. return FALSE;
  1526. }