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.

369 lines
11 KiB

  1. // Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
  2. #include "header.h"
  3. #include "hha_strtable.h"
  4. #include "strtable.h"
  5. #include "hhctrl.h"
  6. #include "resource.h"
  7. #include "chistory.h"
  8. #include "secwin.h"
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static const char THIS_FILE[] = __FILE__;
  12. #endif
  13. #define BOX_HEIGHT 24
  14. #define DEF_BUTTON_WIDTH 70
  15. LRESULT WINAPI EditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  16. extern WNDPROC lpfnlEditWndProc;
  17. CHistory::CHistory(PCSTR pszPastHistory)
  18. : m_hwndResizeToParent(NULL)
  19. {
  20. if (pszPastHistory)
  21. m_cszPastHistory = pszPastHistory;
  22. m_hfont = NULL;
  23. m_fSelectionChange = FALSE;
  24. m_padding = 2; // padding to put around the Index
  25. m_NavTabPos = HHWIN_NAVTAB_TOP; //BUGBUG: If the navpos is different this is broken.
  26. m_fModified = FALSE;
  27. }
  28. CHistory::~CHistory()
  29. {
  30. if (m_hfont)
  31. DeleteObject(m_hfont);
  32. }
  33. BOOL CHistory::Create(HWND hwndParent)
  34. {
  35. RECT rcParent, rcChild;
  36. // Save the hwndParent for ResizeWindow.
  37. m_hwndResizeToParent = hwndParent ;
  38. // Note: GetParentSize will return hwndNavigation if hwndParent is the
  39. // tab ctrl.
  40. hwndParent = GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
  41. CopyRect(&rcChild, &rcParent);
  42. rcChild.bottom = rcChild.top + BOX_HEIGHT;
  43. m_hwndEditBox = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",
  44. WS_CHILD | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, rcChild.left, rcChild.top,
  45. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), hwndParent,
  46. (HMENU) IDEDIT_INDEX, _Module.GetModuleInstance(), NULL);
  47. if (!m_hwndEditBox)
  48. return FALSE;
  49. rcChild.bottom = rcParent.bottom - 2;
  50. rcChild.top = rcChild.bottom - BOX_HEIGHT;
  51. m_hwndDisplayButton = CreateWindow("button",
  52. GetStringResource(IDS_ENGLISH_DISPLAY),
  53. WS_CHILD | WS_TABSTOP, rcChild.left, rcChild.top,
  54. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), hwndParent,
  55. (HMENU) IDBTN_DISPLAY, _Module.GetModuleInstance(), NULL);
  56. if (!m_hwndDisplayButton) {
  57. DestroyWindow(m_hwndEditBox);
  58. return FALSE;
  59. }
  60. // +2 for border, +BOX_HEIGHT for edit box, +5 for spacing.
  61. rcChild.top = rcParent.top + 2 + BOX_HEIGHT + 5;
  62. rcChild.bottom = rcParent.bottom - (2 + BOX_HEIGHT + 5);
  63. m_hwndListBox = CreateWindowEx(WS_EX_CLIENTEDGE, "listbox",
  64. "", WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VSCROLL |
  65. LBS_NOTIFY,
  66. rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild),
  67. hwndParent, (HMENU) IDLB_INDEX, _Module.GetModuleInstance(), NULL);
  68. if (!m_hwndListBox) {
  69. DestroyWindow(m_hwndDisplayButton);
  70. DestroyWindow(m_hwndEditBox);
  71. return FALSE;
  72. }
  73. // Use a more readable font
  74. SendMessage(m_hwndListBox, WM_SETFONT,
  75. m_hfont ? (WPARAM) m_hfont : (WPARAM) _Resource.GetUIFont(), FALSE);
  76. SendMessage(m_hwndEditBox, WM_SETFONT,
  77. m_hfont ? (WPARAM) m_hfont : (WPARAM) _Resource.GetUIFont(), FALSE);
  78. SendMessage(m_hwndDisplayButton, WM_SETFONT,
  79. m_hfont ? (WPARAM) m_hfont : (WPARAM) _Resource.GetUIFont(), FALSE);
  80. // Sub-class the edit box
  81. if (lpfnlEditWndProc == NULL)
  82. lpfnlEditWndProc = (WNDPROC) GetWindowLongPtr(m_hwndEditBox, GWLP_WNDPROC);
  83. SetWindowLongPtr(m_hwndEditBox, GWLP_WNDPROC, (LONG_PTR) EditProc);
  84. FillListBox();
  85. return TRUE;
  86. }
  87. void CHistory::HideWindow(void)
  88. {
  89. ::ShowWindow(m_hwndEditBox, SW_HIDE);
  90. ::ShowWindow(m_hwndListBox, SW_HIDE);
  91. ::ShowWindow(m_hwndDisplayButton, SW_HIDE);
  92. }
  93. void CHistory::ShowWindow(void)
  94. {
  95. ::ShowWindow(m_hwndEditBox, SW_SHOW);
  96. ::ShowWindow(m_hwndListBox, SW_SHOW);
  97. ::ShowWindow(m_hwndDisplayButton, SW_SHOW);
  98. }
  99. void CHistory::ResizeWindow()
  100. {
  101. ASSERT(::IsValidWindow(m_hwndDisplayButton)) ;
  102. // Resize to fit the client area of the parent.
  103. HWND hwndParent = m_hwndResizeToParent ; // Use the original window.
  104. ASSERT(::IsValidWindow(hwndParent)) ;
  105. RECT rcParent, rcChild;
  106. GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
  107. CopyRect(&rcChild, &rcParent);
  108. rcChild.bottom = rcChild.top + BOX_HEIGHT;
  109. MoveWindow(m_hwndEditBox, rcChild.left,
  110. rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
  111. rcChild.bottom = rcParent.bottom - 2;
  112. rcChild.top = rcChild.bottom - BOX_HEIGHT;
  113. rcChild.left = rcChild.right - DEF_BUTTON_WIDTH;
  114. MoveWindow(m_hwndDisplayButton, rcChild.left,
  115. rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
  116. // +2 for border, +BOX_HEIGHT for edit box, +5 for spacing.
  117. rcChild.top = rcParent.top + 2 + BOX_HEIGHT + 5;
  118. rcChild.bottom = rcParent.bottom - (2 + BOX_HEIGHT + 5);
  119. MoveWindow(m_hwndListBox, rcParent.left,
  120. rcChild.top, RECT_WIDTH(rcParent), RECT_HEIGHT(rcChild), TRUE);
  121. }
  122. void CHistory::FillListBox(BOOL fReset)
  123. {
  124. // BUGBUG: do we need this?
  125. }
  126. // This function has the lookup code, so we want it as fast as possible
  127. LRESULT CHistory::OnCommand(HWND /*hwnd*/, UINT id, UINT uNotifiyCode, LPARAM /*lParam*/)
  128. {
  129. #if 0
  130. CStr cszKeyword;
  131. int pos;
  132. SITEMAP_ENTRY* pSiteMapEntry;
  133. int i;
  134. switch (id) {
  135. case IDEDIT_INDEX:
  136. {
  137. if (uNotifiyCode != EN_CHANGE)
  138. return 0;
  139. if (m_fSelectionChange) {
  140. m_fSelectionChange = FALSE;
  141. return 0;
  142. }
  143. CStr cszKeyword(m_hwndEditBox);
  144. if (!*cszKeyword.psz)
  145. return 0;
  146. /*
  147. * REVIEW: This could be sped up by having a first character
  148. * lookup, ala the RTF tokens in lex.cpp (hcrtf). Putting this
  149. * in the thread would also improve user responsiveness.
  150. */
  151. for (i = 1; i <= CountStrings(); i++) {
  152. pSiteMapEntry = GetSiteMapEntry(i);
  153. ASSERT_COMMENT(pSiteMapEntry->GetKeyword(), "Index entry added without a keyword");
  154. /*
  155. * Unless the user specifically requested it, we don't
  156. * allow the keyboard to be used to get to anything other
  157. * then first level entries.
  158. */
  159. if (!g_fNonFirstKey && pSiteMapEntry->GetLevel() > 1)
  160. continue;
  161. // BUGBUG: isSameString is not lcid aware
  162. if (isSameString(pSiteMapEntry->GetKeyword(), cszKeyword)) {
  163. SendMessage(m_hwndListBox, LB_SETCURSEL, i - 1, 0);
  164. break;
  165. }
  166. }
  167. }
  168. return 0;
  169. case IDLB_INDEX:
  170. switch (uNotifiyCode) {
  171. case LBN_SELCHANGE:
  172. if ((pos = SendMessage(m_hwndListBox,
  173. LB_GETCURSEL, 0, 0L)) == LB_ERR)
  174. return 0;
  175. pSiteMapEntry = GetSiteMapEntry(pos + 1);
  176. m_fSelectionChange = TRUE; // ignore EN_CHANGE
  177. SetWindowText(m_hwndEditBox, pSiteMapEntry->GetKeyword());
  178. m_fSelectionChange = FALSE; // ignore EN_CHANGE
  179. return 0;
  180. case LBN_DBLCLK:
  181. PostMessage(FindMessageParent(m_hwndListBox), WM_COMMAND,
  182. MAKELONG(IDBTN_DISPLAY, BN_CLICKED), 0);
  183. return 0;
  184. }
  185. return 0;
  186. case IDBTN_DISPLAY:
  187. if (uNotifiyCode == BN_CLICKED) {
  188. if ((pos = SendMessage(m_hwndListBox,
  189. LB_GETCURSEL, 0, 0L)) == LB_ERR)
  190. return 0;
  191. CStr cszKeyword(m_hwndEditBox);
  192. pSiteMapEntry = GetSiteMapEntry(pos + 1);
  193. #ifdef _DEBUG
  194. PCSTR pszKeyword = pSiteMapEntry->GetKeyword();
  195. #endif
  196. int cbKeyword = strlen(cszKeyword);
  197. if (strlen(pSiteMapEntry->GetKeyword()) < cbKeyword ||
  198. CompareString(g_lcidSystem, NORM_IGNORECASE,
  199. pSiteMapEntry->GetKeyword(), cbKeyword,
  200. cszKeyword, cbKeyword) != 2) {
  201. MsgBox(IDS_NO_SUCH_KEYWORD);
  202. SetFocus(m_hwndEditBox);
  203. return 0;
  204. }
  205. if (pSiteMapEntry->fSeeAlso) {
  206. /*
  207. * A See Also entry simply jumps to another location
  208. * in the Index.
  209. */
  210. SetWindowText(m_hwndEditBox,
  211. GetUrlString(pSiteMapEntry->pUrls->urlPrimary));
  212. return 0;
  213. }
  214. // If we have one or more titles, then give the user
  215. // a choice of what to jump to.
  216. if (pSiteMapEntry->cUrls > 1) {
  217. CHistoryTopics dlgTopics(
  218. m_phhctrl ? m_phhctrl->m_hwnd : FindMessageParent(m_hwndEditBox),
  219. pSiteMapEntry, this);
  220. if (m_phhctrl)
  221. m_phhctrl->ModalDialog(TRUE);
  222. int fResult = dlgTopics.DoModal();
  223. if (m_phhctrl)
  224. m_phhctrl->ModalDialog(FALSE);
  225. if (fResult)
  226. JumpToUrl(m_pOuter, m_hwndListBox, pSiteMapEntry, this, dlgTopics.m_pUrl);
  227. SetFocus(m_hwndEditBox);
  228. return 0;
  229. }
  230. JumpToUrl(m_pOuter, m_hwndListBox, pSiteMapEntry, this, NULL);
  231. SetFocus(m_hwndEditBox);
  232. }
  233. return 0;
  234. case ID_VIEW_ENTRY:
  235. {
  236. if ((pos = SendMessage(m_hwndListBox,
  237. LB_GETCURSEL, 0, 0L)) == LB_ERR)
  238. return 0;
  239. pSiteMapEntry = GetSiteMapEntry(pos + 1);
  240. DisplayAuthorInfo(this, pSiteMapEntry, FindMessageParent(m_hwndListBox), m_phhctrl);
  241. }
  242. return 0;
  243. #ifdef _DEBUG
  244. case ID_VIEW_MEMORY:
  245. OnReportMemoryUsage();
  246. return 0;
  247. #endif
  248. }
  249. #endif // 0
  250. return 0;
  251. }
  252. void CHHWinType::CreateHistoryTab(void)
  253. {
  254. #ifdef _DEBUG
  255. CHistory* pHistory = new CHistory(NULL);
  256. m_aNavPane[HH_TAB_HISTORY] = pHistory ;
  257. pHistory->SetPadding(10);
  258. pHistory->SetTabPos(tabpos);
  259. pHistory->Create((m_pTabCtrl ? m_pTabCtrl->hWnd() : hwndNavigation));
  260. #endif
  261. }
  262. void CHHWinType::AddToHistory(PCSTR pszTitle, PCSTR pszUrl)
  263. {
  264. #ifndef _DEBUG
  265. return;
  266. #else
  267. if (!m_aNavPane[HH_TAB_HISTORY])
  268. return;
  269. CHistory* pHistory = (CHistory*)m_aNavPane[HH_TAB_HISTORY]; //HACKHACK: Needs dynamic_cast.
  270. CDlgListBox lb;
  271. lb.m_hWnd = pHistory->m_hwndListBox;
  272. int lbpos = (int)lb.FindString(pszTitle);
  273. if (lbpos == LB_ERR) {
  274. /*
  275. * OnTitleChange gets called before we have the real title, so the
  276. * title may actually change. If so, we want to delete the previous
  277. * title and the new one.
  278. */
  279. int pos = pHistory->m_tblHistory.IsStringInTable(pszUrl);
  280. if (pos > 0) {
  281. INT_PTR cbItems = lb.GetCount();
  282. ASSERT(cbItems != LB_ERR);
  283. for (int i = 0; i < cbItems; i++) {
  284. if (pos == lb.GetItemData(i))
  285. break;
  286. }
  287. if (i < cbItems)
  288. lb.DeleteString(i);
  289. if (IsProperty(HHWIN_PROP_CHANGE_TITLE))
  290. SetWindowText(*this, pszTitle);
  291. }
  292. else
  293. pos = pHistory->m_tblHistory.AddString(pszUrl);
  294. int lbpos = (int)lb.AddString(pszTitle);
  295. lb.SetItemData(lbpos, pos);
  296. }
  297. else {
  298. if (IsProperty(HHWIN_PROP_CHANGE_TITLE))
  299. SetWindowText(*this, pszTitle);
  300. }
  301. lb.SetCurSel(lbpos);
  302. #endif
  303. }