|
|
// Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
#include "header.h"
#include "hha_strtable.h"
#include "strtable.h"
#include "hhctrl.h"
#include "resource.h"
#include "chistory.h"
#include "secwin.h"
#ifdef _DEBUG
#undef THIS_FILE
static const char THIS_FILE[] = __FILE__; #endif
#define BOX_HEIGHT 24
#define DEF_BUTTON_WIDTH 70
LRESULT WINAPI EditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); extern WNDPROC lpfnlEditWndProc;
CHistory::CHistory(PCSTR pszPastHistory) : m_hwndResizeToParent(NULL) { if (pszPastHistory) m_cszPastHistory = pszPastHistory;
m_hfont = NULL; m_fSelectionChange = FALSE; m_padding = 2; // padding to put around the Index
m_NavTabPos = HHWIN_NAVTAB_TOP; //BUGBUG: If the navpos is different this is broken.
m_fModified = FALSE; }
CHistory::~CHistory() { if (m_hfont) DeleteObject(m_hfont); }
BOOL CHistory::Create(HWND hwndParent) { RECT rcParent, rcChild;
// Save the hwndParent for ResizeWindow.
m_hwndResizeToParent = hwndParent ;
// Note: GetParentSize will return hwndNavigation if hwndParent is the
// tab ctrl.
hwndParent = GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
CopyRect(&rcChild, &rcParent); rcChild.bottom = rcChild.top + BOX_HEIGHT;
m_hwndEditBox = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "", WS_CHILD | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), hwndParent, (HMENU) IDEDIT_INDEX, _Module.GetModuleInstance(), NULL);
if (!m_hwndEditBox) return FALSE;
rcChild.bottom = rcParent.bottom - 2; rcChild.top = rcChild.bottom - BOX_HEIGHT;
m_hwndDisplayButton = CreateWindow("button", GetStringResource(IDS_ENGLISH_DISPLAY), WS_CHILD | WS_TABSTOP, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), hwndParent, (HMENU) IDBTN_DISPLAY, _Module.GetModuleInstance(), NULL);
if (!m_hwndDisplayButton) { DestroyWindow(m_hwndEditBox); return FALSE; }
// +2 for border, +BOX_HEIGHT for edit box, +5 for spacing.
rcChild.top = rcParent.top + 2 + BOX_HEIGHT + 5; rcChild.bottom = rcParent.bottom - (2 + BOX_HEIGHT + 5);
m_hwndListBox = CreateWindowEx(WS_EX_CLIENTEDGE, "listbox", "", WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), hwndParent, (HMENU) IDLB_INDEX, _Module.GetModuleInstance(), NULL);
if (!m_hwndListBox) { DestroyWindow(m_hwndDisplayButton); DestroyWindow(m_hwndEditBox); return FALSE; }
// Use a more readable font
SendMessage(m_hwndListBox, WM_SETFONT, m_hfont ? (WPARAM) m_hfont : (WPARAM) _Resource.GetUIFont(), FALSE); SendMessage(m_hwndEditBox, WM_SETFONT, m_hfont ? (WPARAM) m_hfont : (WPARAM) _Resource.GetUIFont(), FALSE); SendMessage(m_hwndDisplayButton, WM_SETFONT, m_hfont ? (WPARAM) m_hfont : (WPARAM) _Resource.GetUIFont(), FALSE);
// Sub-class the edit box
if (lpfnlEditWndProc == NULL) lpfnlEditWndProc = (WNDPROC) GetWindowLongPtr(m_hwndEditBox, GWLP_WNDPROC); SetWindowLongPtr(m_hwndEditBox, GWLP_WNDPROC, (LONG_PTR) EditProc);
FillListBox();
return TRUE; }
void CHistory::HideWindow(void) { ::ShowWindow(m_hwndEditBox, SW_HIDE); ::ShowWindow(m_hwndListBox, SW_HIDE); ::ShowWindow(m_hwndDisplayButton, SW_HIDE); }
void CHistory::ShowWindow(void) { ::ShowWindow(m_hwndEditBox, SW_SHOW); ::ShowWindow(m_hwndListBox, SW_SHOW); ::ShowWindow(m_hwndDisplayButton, SW_SHOW); }
void CHistory::ResizeWindow() { ASSERT(::IsValidWindow(m_hwndDisplayButton)) ;
// Resize to fit the client area of the parent.
HWND hwndParent = m_hwndResizeToParent ; // Use the original window.
ASSERT(::IsValidWindow(hwndParent)) ;
RECT rcParent, rcChild; GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
CopyRect(&rcChild, &rcParent); rcChild.bottom = rcChild.top + BOX_HEIGHT; MoveWindow(m_hwndEditBox, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
rcChild.bottom = rcParent.bottom - 2; rcChild.top = rcChild.bottom - BOX_HEIGHT; rcChild.left = rcChild.right - DEF_BUTTON_WIDTH; MoveWindow(m_hwndDisplayButton, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
// +2 for border, +BOX_HEIGHT for edit box, +5 for spacing.
rcChild.top = rcParent.top + 2 + BOX_HEIGHT + 5; rcChild.bottom = rcParent.bottom - (2 + BOX_HEIGHT + 5); MoveWindow(m_hwndListBox, rcParent.left, rcChild.top, RECT_WIDTH(rcParent), RECT_HEIGHT(rcChild), TRUE); }
void CHistory::FillListBox(BOOL fReset) { // BUGBUG: do we need this?
}
// This function has the lookup code, so we want it as fast as possible
LRESULT CHistory::OnCommand(HWND /*hwnd*/, UINT id, UINT uNotifiyCode, LPARAM /*lParam*/) { #if 0
CStr cszKeyword; int pos; SITEMAP_ENTRY* pSiteMapEntry; int i;
switch (id) { case IDEDIT_INDEX: { if (uNotifiyCode != EN_CHANGE) return 0; if (m_fSelectionChange) { m_fSelectionChange = FALSE; return 0; }
CStr cszKeyword(m_hwndEditBox); if (!*cszKeyword.psz) return 0;
/*
* REVIEW: This could be sped up by having a first character * lookup, ala the RTF tokens in lex.cpp (hcrtf). Putting this * in the thread would also improve user responsiveness. */
for (i = 1; i <= CountStrings(); i++) { pSiteMapEntry = GetSiteMapEntry(i); ASSERT_COMMENT(pSiteMapEntry->GetKeyword(), "Index entry added without a keyword");
/*
* Unless the user specifically requested it, we don't * allow the keyboard to be used to get to anything other * then first level entries. */
if (!g_fNonFirstKey && pSiteMapEntry->GetLevel() > 1) continue;
// BUGBUG: isSameString is not lcid aware
if (isSameString(pSiteMapEntry->GetKeyword(), cszKeyword)) { SendMessage(m_hwndListBox, LB_SETCURSEL, i - 1, 0); break; } } } return 0;
case IDLB_INDEX: switch (uNotifiyCode) { case LBN_SELCHANGE: if ((pos = SendMessage(m_hwndListBox, LB_GETCURSEL, 0, 0L)) == LB_ERR) return 0; pSiteMapEntry = GetSiteMapEntry(pos + 1);
m_fSelectionChange = TRUE; // ignore EN_CHANGE
SetWindowText(m_hwndEditBox, pSiteMapEntry->GetKeyword()); m_fSelectionChange = FALSE; // ignore EN_CHANGE
return 0;
case LBN_DBLCLK: PostMessage(FindMessageParent(m_hwndListBox), WM_COMMAND, MAKELONG(IDBTN_DISPLAY, BN_CLICKED), 0); return 0; } return 0;
case IDBTN_DISPLAY: if (uNotifiyCode == BN_CLICKED) { if ((pos = SendMessage(m_hwndListBox, LB_GETCURSEL, 0, 0L)) == LB_ERR) return 0; CStr cszKeyword(m_hwndEditBox); pSiteMapEntry = GetSiteMapEntry(pos + 1);
#ifdef _DEBUG
PCSTR pszKeyword = pSiteMapEntry->GetKeyword(); #endif
int cbKeyword = strlen(cszKeyword); if (strlen(pSiteMapEntry->GetKeyword()) < cbKeyword || CompareString(g_lcidSystem, NORM_IGNORECASE, pSiteMapEntry->GetKeyword(), cbKeyword, cszKeyword, cbKeyword) != 2) { MsgBox(IDS_NO_SUCH_KEYWORD); SetFocus(m_hwndEditBox); return 0; }
if (pSiteMapEntry->fSeeAlso) {
/*
* A See Also entry simply jumps to another location * in the Index. */
SetWindowText(m_hwndEditBox, GetUrlString(pSiteMapEntry->pUrls->urlPrimary)); return 0; }
// If we have one or more titles, then give the user
// a choice of what to jump to.
if (pSiteMapEntry->cUrls > 1) { CHistoryTopics dlgTopics( m_phhctrl ? m_phhctrl->m_hwnd : FindMessageParent(m_hwndEditBox), pSiteMapEntry, this); if (m_phhctrl) m_phhctrl->ModalDialog(TRUE); int fResult = dlgTopics.DoModal(); if (m_phhctrl) m_phhctrl->ModalDialog(FALSE); if (fResult) JumpToUrl(m_pOuter, m_hwndListBox, pSiteMapEntry, this, dlgTopics.m_pUrl); SetFocus(m_hwndEditBox); return 0; } JumpToUrl(m_pOuter, m_hwndListBox, pSiteMapEntry, this, NULL); SetFocus(m_hwndEditBox); } return 0;
case ID_VIEW_ENTRY: { if ((pos = SendMessage(m_hwndListBox, LB_GETCURSEL, 0, 0L)) == LB_ERR) return 0; pSiteMapEntry = GetSiteMapEntry(pos + 1); DisplayAuthorInfo(this, pSiteMapEntry, FindMessageParent(m_hwndListBox), m_phhctrl); } return 0;
#ifdef _DEBUG
case ID_VIEW_MEMORY: OnReportMemoryUsage(); return 0; #endif
} #endif // 0
return 0; }
void CHHWinType::CreateHistoryTab(void) { #ifdef _DEBUG
CHistory* pHistory = new CHistory(NULL); m_aNavPane[HH_TAB_HISTORY] = pHistory ; pHistory->SetPadding(10); pHistory->SetTabPos(tabpos); pHistory->Create((m_pTabCtrl ? m_pTabCtrl->hWnd() : hwndNavigation)); #endif
}
void CHHWinType::AddToHistory(PCSTR pszTitle, PCSTR pszUrl) { #ifndef _DEBUG
return; #else
if (!m_aNavPane[HH_TAB_HISTORY]) return; CHistory* pHistory = (CHistory*)m_aNavPane[HH_TAB_HISTORY]; //HACKHACK: Needs dynamic_cast.
CDlgListBox lb; lb.m_hWnd = pHistory->m_hwndListBox; int lbpos = (int)lb.FindString(pszTitle);
if (lbpos == LB_ERR) {
/*
* OnTitleChange gets called before we have the real title, so the * title may actually change. If so, we want to delete the previous * title and the new one. */
int pos = pHistory->m_tblHistory.IsStringInTable(pszUrl); if (pos > 0) { INT_PTR cbItems = lb.GetCount(); ASSERT(cbItems != LB_ERR); for (int i = 0; i < cbItems; i++) { if (pos == lb.GetItemData(i)) break; } if (i < cbItems) lb.DeleteString(i); if (IsProperty(HHWIN_PROP_CHANGE_TITLE)) SetWindowText(*this, pszTitle); } else pos = pHistory->m_tblHistory.AddString(pszUrl); int lbpos = (int)lb.AddString(pszTitle); lb.SetItemData(lbpos, pos); } else { if (IsProperty(HHWIN_PROP_CHANGE_TITLE)) SetWindowText(*this, pszTitle); } lb.SetCurSel(lbpos); #endif
}
|