3003 lines
89 KiB
C++
3003 lines
89 KiB
C++
|
// Copyright (C) Microsoft Corporation 1996-1997, All Rights reserved.
|
||
|
|
||
|
// Precompiled header
|
||
|
#include "header.h"
|
||
|
#include "state.h"
|
||
|
#include "cctlww.h"
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static const char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Includes
|
||
|
//
|
||
|
#include "secwin.h" // Header for this file.
|
||
|
#include "hha_strtable.h"
|
||
|
#include "contain.h"
|
||
|
#include "highlite.h"
|
||
|
#include "resource.h" // needed for subset picker combo control ID.
|
||
|
#include "subset.h" // Needed to dealing with CStructucturalSubset object.
|
||
|
// Advanced Search UI header.
|
||
|
#include "adsearch.h"
|
||
|
#include "search.h"
|
||
|
|
||
|
// Bookmarks Nav Pane
|
||
|
#include "bookmark.h"
|
||
|
|
||
|
// Custom NavPane
|
||
|
#include "custmtab.h"
|
||
|
|
||
|
// Sizebar class
|
||
|
#include "sizebar.h"
|
||
|
|
||
|
#define ACCESS_KEY '&'
|
||
|
|
||
|
static const char txtAccessKey[] = "&";
|
||
|
|
||
|
BOOL HxInsertMenuItem(HMENU, UINT, BOOL, MENUITEMINFOA *);
|
||
|
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Globals
|
||
|
//
|
||
|
// Pointer to global array of window types.
|
||
|
CHHWinType** pahwnd = NULL;
|
||
|
|
||
|
|
||
|
AUTO_CLASS_COUNT_CHECK( CHHWinType );
|
||
|
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Function Implementation
|
||
|
//
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
FUNCTION: GetCurrentCollection
|
||
|
|
||
|
PURPOSE: Returns the currect collection
|
||
|
|
||
|
PARAMETERS:
|
||
|
None.
|
||
|
|
||
|
RETURNS: Pointer to the currect collection (CExCollection)
|
||
|
|
||
|
COMMENTS:
|
||
|
This function returns the current collection based on the
|
||
|
current active window and window type. Use this function
|
||
|
anytime you need a pointer to the currect active collection
|
||
|
when you can assume that the collection is already loaded.
|
||
|
|
||
|
MODIFICATION DATES:
|
||
|
15-Sept-1997 [paulti]
|
||
|
|
||
|
29-April-1998 [mikecole]
|
||
|
As per agreement of all hhctrl devs I am adding a .CHM filespec argument
|
||
|
to this function. Since it is possible for a single task to utilize hhctrl
|
||
|
services on multiple CExCollections we will distinguish CExCollections
|
||
|
from one another by using a .CHM filespec.
|
||
|
|
||
|
***************************************************************************/
|
||
|
CExCollection* GetCurrentCollection( HWND hwnd, LPCSTR lpszChmFilespec )
|
||
|
{
|
||
|
CExCollection* pCExCol;
|
||
|
PSTR psz;
|
||
|
TCHAR szFN[MAX_PATH];
|
||
|
TCHAR szFN2[MAX_PATH];
|
||
|
int i = 0;
|
||
|
|
||
|
szFN[0] = '\0';
|
||
|
if ( lpszChmFilespec )
|
||
|
{
|
||
|
//
|
||
|
// First, we need to normalize the filespec. This thing can come to us in any number of
|
||
|
// forms, it could be a URL, it could be an unqualified filename, a fully qualified path...
|
||
|
//
|
||
|
if ( psz = stristr(lpszChmFilespec, txtDefExtension) )
|
||
|
{
|
||
|
while ( *psz != ' ' && *psz != '/' && *psz != '\\' && *psz != '@' && *psz != '\0' && *psz != ':' && (psz != lpszChmFilespec) )
|
||
|
{
|
||
|
psz = CharPrev(lpszChmFilespec, psz);
|
||
|
i++;
|
||
|
if(IsDBCSLeadByte(*CharNext(psz)))
|
||
|
i++;
|
||
|
}
|
||
|
if ( psz != lpszChmFilespec )
|
||
|
psz++;
|
||
|
else
|
||
|
i++;
|
||
|
lstrcpyn(szFN, psz, i);
|
||
|
}
|
||
|
//
|
||
|
// Next, see if the filespec matches a single title .CHM or and merged .CHMs of a single title .CHM.
|
||
|
//
|
||
|
if ( szFN[0] )
|
||
|
{
|
||
|
for (int i = 0; i < g_cHmSlots; i++)
|
||
|
{
|
||
|
if ( g_phmData[i] && g_phmData[i]->m_pTitleCollection && g_phmData[i]->m_pTitleCollection->IsSingleTitle() )
|
||
|
{
|
||
|
//
|
||
|
// Search title list for a match.
|
||
|
//
|
||
|
CExTitle* pTitle;
|
||
|
pCExCol = g_phmData[i]->m_pTitleCollection;
|
||
|
pTitle = pCExCol->GetFirstTitle();
|
||
|
while ( pTitle )
|
||
|
{
|
||
|
_splitpath((LPCSTR)pTitle->GetContentFileName(), NULL, NULL, szFN2, NULL);
|
||
|
if (! lstrcmpi(szFN, szFN2) )
|
||
|
return g_phmData[i]->m_pTitleCollection;
|
||
|
pTitle = pTitle->GetNext();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Last resort...
|
||
|
//
|
||
|
if ( g_pCurrentCollection )
|
||
|
return g_pCurrentCollection;
|
||
|
else if ( g_phmData && g_phmData[0] )
|
||
|
return g_phmData[0]->m_pTitleCollection;
|
||
|
else return NULL; // Ohhh, very bad!
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
FUNCTION: GetCurrentURL
|
||
|
|
||
|
PURPOSE: Returns the currect URL
|
||
|
|
||
|
PARAMETERS:
|
||
|
None.
|
||
|
|
||
|
RETURNS: TRUE if found with pcszCurrentURL filed in, otherwise FALSE.
|
||
|
|
||
|
COMMENTS:
|
||
|
This function returns the current URL based on the
|
||
|
current active window and window type.
|
||
|
|
||
|
MODIFICATION DATES:
|
||
|
10-Dec-1997 [paulti]
|
||
|
|
||
|
***************************************************************************/
|
||
|
BOOL GetCurrentURL( CStr* pcszCurrentURL, HWND hwnd )
|
||
|
{
|
||
|
ASSERT(pahwnd);
|
||
|
CHHWinType* phh = NULL;
|
||
|
BOOL bFound = FALSE;
|
||
|
|
||
|
// if anyone can find a guarenteed way to get the current
|
||
|
// URL please modify the code below [paulti]
|
||
|
if( !hwnd )
|
||
|
hwnd = GetActiveWindow();
|
||
|
phh = FindHHWindowIndex(hwnd);
|
||
|
if( phh && phh->m_pCIExpContainer &&
|
||
|
phh->m_pCIExpContainer->m_pWebBrowserApp ) {
|
||
|
phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL( pcszCurrentURL );
|
||
|
bFound = TRUE;
|
||
|
}
|
||
|
|
||
|
return bFound;
|
||
|
}
|
||
|
|
||
|
HFONT CHHWinType::GetContentFont()
|
||
|
{
|
||
|
if ( m_phmData )
|
||
|
{
|
||
|
CExTitle* pTitle = m_phmData->m_pTitleCollection->GetMasterTitle();
|
||
|
return (pTitle->GetInfo()->GetContentFont());
|
||
|
}
|
||
|
else
|
||
|
return _Resource.GetUIFont(); // This would be highly unusual!
|
||
|
}
|
||
|
|
||
|
HFONT CHHWinType::GetAccessableContentFont()
|
||
|
{
|
||
|
if ( m_phmData )
|
||
|
{
|
||
|
CExTitle* pTitle = m_phmData->m_pTitleCollection->GetMasterTitle();
|
||
|
return (pTitle->GetInfo()->GetAccessableContentFont());
|
||
|
}
|
||
|
else
|
||
|
return _Resource.GetUIFont(); // This would be highly unusual!
|
||
|
}
|
||
|
|
||
|
INT CHHWinType::GetContentCharset()
|
||
|
{
|
||
|
if ( m_phmData )
|
||
|
{
|
||
|
CExTitle* pTitle = m_phmData->m_pTitleCollection->GetMasterTitle();
|
||
|
return (pTitle->GetInfo()->GetTitleCharset());
|
||
|
}
|
||
|
else
|
||
|
return ANSI_CHARSET; // This would be highly unusual!
|
||
|
}
|
||
|
|
||
|
UINT CHHWinType::GetCodePage(void)
|
||
|
{
|
||
|
if ( m_phmData )
|
||
|
{
|
||
|
CExTitle* pTitle = m_phmData->m_pTitleCollection->GetMasterTitle();
|
||
|
return (pTitle->GetInfo()->GetCodePage());
|
||
|
}
|
||
|
else
|
||
|
return 0; // This would be highly unusual!
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
FUNCTION: CHHWinType::SetString
|
||
|
|
||
|
PURPOSE: Set a window type string
|
||
|
|
||
|
PARAMETERS:
|
||
|
pszSrcString
|
||
|
ppszDst
|
||
|
|
||
|
RETURNS:
|
||
|
|
||
|
COMMENTS:
|
||
|
If string is non-NULL and non-empty, frees any previous string memory
|
||
|
and allocates and copies the string.
|
||
|
|
||
|
MODIFICATION DATES:
|
||
|
09-Sep-1997 [ralphw]
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
void CHHWinType::SetString(PCSTR pszSrcString, PSTR* ppszDst)
|
||
|
{
|
||
|
if (!pszSrcString)
|
||
|
return;
|
||
|
|
||
|
CStr csz ;
|
||
|
if (IsUniCodeStrings())
|
||
|
csz = (WCHAR*) pszSrcString;
|
||
|
else
|
||
|
csz = pszSrcString;
|
||
|
if (csz.IsNonEmpty())
|
||
|
{
|
||
|
if (*ppszDst)
|
||
|
lcFree(*ppszDst);
|
||
|
csz.TransferPointer(ppszDst);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
FUNCTION: CHHWinType::SetUrl
|
||
|
|
||
|
PURPOSE: Set a window type URL
|
||
|
|
||
|
PARAMETERS:
|
||
|
pszSrcString
|
||
|
ppszDst
|
||
|
|
||
|
RETURNS:
|
||
|
|
||
|
COMMENTS:
|
||
|
If string is non-NULL and non-empty, frees any previous string memory
|
||
|
and allocates and copies the string.
|
||
|
|
||
|
If the string contains a compiled HTML filename, then the URL
|
||
|
is converted into a full path.
|
||
|
|
||
|
MODIFICATION DATES:
|
||
|
09-Sep-1997 [ralphw]
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
void CHHWinType::SetUrl(PCSTR pszSrcString, PSTR* ppszDst)
|
||
|
{
|
||
|
if (!pszSrcString)
|
||
|
return;
|
||
|
|
||
|
CStr csz;
|
||
|
if (IsUniCodeStrings())
|
||
|
csz = (WCHAR*) pszSrcString;
|
||
|
else
|
||
|
csz = pszSrcString;
|
||
|
if (csz.IsNonEmpty())
|
||
|
{
|
||
|
if (*ppszDst)
|
||
|
lcFree(*ppszDst);
|
||
|
CStr cszFull;
|
||
|
if (IsCompiledHtmlFile(csz, &cszFull))
|
||
|
cszFull.TransferPointer(ppszDst);
|
||
|
else
|
||
|
csz.TransferPointer(ppszDst);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CHHWinType::SetTypeName(HH_WINTYPE* phhWinType)
|
||
|
{
|
||
|
SetString(phhWinType->pszType, (PSTR*) &pszType);
|
||
|
if (pszType && *pszType == '>')
|
||
|
strcpy((PSTR) pszType, pszType + 1);
|
||
|
}
|
||
|
|
||
|
/**********************************************************
|
||
|
FUNCTION SetJump1
|
||
|
|
||
|
NOTES
|
||
|
The button caption pszJump1 can be empty.
|
||
|
The URL cannot.
|
||
|
***********************************************************/
|
||
|
void CHHWinType::SetJump1(HH_WINTYPE* phhWinType)
|
||
|
{
|
||
|
if (!(fsToolBarFlags & HHWIN_BUTTON_JUMP1) || (phhWinType->pszUrlJump1 == NULL))
|
||
|
return;
|
||
|
|
||
|
SetString(phhWinType->pszJump1, (PSTR*) &pszJump1);
|
||
|
SetUrl(phhWinType->pszUrlJump1, (PSTR*) &pszUrlJump1);
|
||
|
}
|
||
|
|
||
|
/**********************************************************
|
||
|
FUNCTION SetJump2
|
||
|
|
||
|
NOTES
|
||
|
The button caption pszJump1 can be empty.
|
||
|
The URL cannot.
|
||
|
***********************************************************/
|
||
|
void CHHWinType::SetJump2(HH_WINTYPE* phhWinType)
|
||
|
{
|
||
|
if (!(fsToolBarFlags & HHWIN_BUTTON_JUMP2) || (phhWinType->pszUrlJump2 == NULL))
|
||
|
return;
|
||
|
SetString(phhWinType->pszJump2, (PSTR*) &pszJump2);
|
||
|
SetUrl(phhWinType->pszUrlJump2, (PSTR*) &pszUrlJump2);
|
||
|
}
|
||
|
|
||
|
/**********************************************************
|
||
|
FUNCTION SetTabOrder
|
||
|
|
||
|
NOTES
|
||
|
***********************************************************/
|
||
|
void CHHWinType::SetTabOrder(HH_WINTYPE* phhWinType)
|
||
|
{
|
||
|
// REVIEW: We need to be able to loop true this array and find tabs.
|
||
|
// This means that we need some way to determine the upper most array entry.
|
||
|
// This is harder in the user defined case...[14 Jan 98]
|
||
|
if (IsValidMember(HHWIN_PARAM_TABORDER))
|
||
|
memcpy(tabOrder, phhWinType->tabOrder, sizeof(tabOrder));
|
||
|
else {
|
||
|
for (int j = HH_TAB_FAVORITES + 1; j < HH_TAB_CUSTOM_FIRST; j++)
|
||
|
tabOrder[j] = -1; // clear empty slots
|
||
|
|
||
|
tabOrder[HH_TAB_CONTENTS] = HH_TAB_CONTENTS;
|
||
|
tabOrder[HH_TAB_INDEX] = HH_TAB_INDEX;
|
||
|
tabOrder[HH_TAB_SEARCH] = HH_TAB_SEARCH;
|
||
|
tabOrder[HH_TAB_HISTORY] = HH_TAB_HISTORY;
|
||
|
tabOrder[HH_TAB_FAVORITES] = HH_TAB_FAVORITES;
|
||
|
#ifdef __TEST_CUSTOMTAB__
|
||
|
tabOrder[HH_TAB_AUTHOR] = HH_TAB_AUTHOR; // hha.dll supplied tab
|
||
|
#endif
|
||
|
|
||
|
// Setup the default tab order for the custom tabs.
|
||
|
|
||
|
for (int i = HH_TAB_CUSTOM_FIRST; i <= HH_TAB_CUSTOM_LAST; i++)
|
||
|
tabOrder[i] = (BYTE)i;
|
||
|
|
||
|
// This member is now valid. Mark it as such.
|
||
|
fsValidMembers |= HHWIN_PARAM_TABORDER ;
|
||
|
}
|
||
|
}
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
DWORD
|
||
|
CHHWinType::GetStyles() const
|
||
|
{
|
||
|
DWORD style = NULL ;
|
||
|
if (IsValidMember(HHWIN_PARAM_STYLES))
|
||
|
{
|
||
|
style = dwStyles ;
|
||
|
}
|
||
|
|
||
|
if (!IsProperty(HHWIN_PROP_NODEF_STYLES))
|
||
|
{
|
||
|
style |= DEFAULT_STYLE ;
|
||
|
}
|
||
|
|
||
|
if (!IsProperty(HHWIN_PROP_NOTITLEBAR))
|
||
|
{
|
||
|
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ;
|
||
|
}
|
||
|
|
||
|
return style ;
|
||
|
}
|
||
|
|
||
|
void CHHWinType::GetClientRect(RECT* prc)
|
||
|
{
|
||
|
::GetClientRect(hwndHelp, prc);
|
||
|
|
||
|
if (IsValidWindow(hwndToolBar)) {
|
||
|
RECT rc;
|
||
|
::GetWindowRect(hwndToolBar, &rc);
|
||
|
prc->top += RECT_HEIGHT(rc);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CHHWinType::CalcHtmlPaneRect(void)
|
||
|
{
|
||
|
::GetClientRect(hwndHelp, &rcHTML); // the total size of the help window
|
||
|
|
||
|
if (IsValidWindow(hwndToolBar))
|
||
|
{
|
||
|
::GetWindowRect(hwndToolBar, &rcToolBar);
|
||
|
rcHTML.top += RECT_HEIGHT(rcToolBar);
|
||
|
if (m_fNotesWindow)
|
||
|
{
|
||
|
int height = RECT_HEIGHT(rcNotes);
|
||
|
CopyRect(&rcNotes, &rcHTML);
|
||
|
if (!height)
|
||
|
height = DEFAULT_NOTES_HEIGHT;
|
||
|
rcNotes.bottom = rcNotes.top + height;
|
||
|
rcHTML.top = rcNotes.bottom;
|
||
|
if (IsExpandedNavPane())
|
||
|
rcNotes.left += RECT_WIDTH(rcNav);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (IsExpandedNavPane() && !IsProperty(HHWIN_PROP_NAV_ONLY_WIN))
|
||
|
{
|
||
|
if( hwndNavigation )
|
||
|
::GetClientRect(hwndNavigation, &rcNav);
|
||
|
if (m_pSizeBar)
|
||
|
{
|
||
|
rcHTML.left += m_pSizeBar->Width() + RECT_WIDTH(rcNav);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rcHTML.left += RECT_WIDTH(rcNav);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
rcNav.top = m_fNotesWindow ? rcNotes.top : rcHTML.top;
|
||
|
|
||
|
if ( m_hWndSSCB )
|
||
|
rcNav.top += m_iSSCBHeight;
|
||
|
|
||
|
rcNav.bottom = rcHTML.bottom;
|
||
|
}
|
||
|
|
||
|
// Wrap the toolbar
|
||
|
void CHHWinType::WrapTB()
|
||
|
{
|
||
|
extern SHORT g_tbRightMargin;
|
||
|
extern SHORT g_tbLeftMargin;
|
||
|
int cRows, cButtons;
|
||
|
RECT btnRc;
|
||
|
int btnWidth=0;
|
||
|
int btnspace;
|
||
|
int btnsperrow;
|
||
|
|
||
|
cButtons = (int)SendMessage(hwndToolBar, TB_BUTTONCOUNT, 0, 0);
|
||
|
if (cButtons == 0)
|
||
|
{
|
||
|
ASSERT(cButtons != 0) ; // Should never happen.
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_EXPAND)
|
||
|
cButtons--;
|
||
|
::GetWindowRect(hwndHelp, &rcWindowPos);
|
||
|
|
||
|
for ( int i=0; (btnWidth==0)&&(i<cButtons); i++)
|
||
|
{
|
||
|
if ( SendMessage(hwndToolBar, TB_GETITEMRECT, (WPARAM)i, (LPARAM)&btnRc) )
|
||
|
btnWidth = RECT_WIDTH(btnRc);
|
||
|
}
|
||
|
if ( btnWidth == 0 )
|
||
|
btnWidth = TB_BTN_CX;
|
||
|
|
||
|
// How many buttons per row??
|
||
|
btnspace = RECT_WIDTH(rcWindowPos) -(g_tbLeftMargin+g_tbRightMargin);
|
||
|
btnsperrow = btnspace / btnWidth;
|
||
|
if( btnsperrow == 0 )
|
||
|
btnsperrow = 1;
|
||
|
cRows = cButtons / btnsperrow;
|
||
|
if ( cButtons % btnsperrow )
|
||
|
cRows++;
|
||
|
|
||
|
if (RECT_HEIGHT(btnRc) == 0)
|
||
|
{
|
||
|
ASSERT(RECT_HEIGHT(btnRc) != 0) ;
|
||
|
return ; // Avoid divide by zero.
|
||
|
}
|
||
|
|
||
|
if ( cRows < RECT_HEIGHT(rcToolBar)/RECT_HEIGHT(btnRc))
|
||
|
{
|
||
|
WPARAM wParam = MAKEWPARAM( cRows, FALSE);
|
||
|
SendMessage(hwndToolBar, TB_SETROWS, wParam, (LPARAM)&rcToolBar);
|
||
|
}
|
||
|
else if ( cRows > RECT_HEIGHT(rcToolBar)/RECT_HEIGHT(btnRc) )
|
||
|
{
|
||
|
WPARAM wParam = MAKEWPARAM( cRows, TRUE);
|
||
|
SendMessage(hwndToolBar, TB_SETROWS, wParam, (LPARAM)&rcToolBar);
|
||
|
}
|
||
|
|
||
|
::GetClientRect(hwndToolBar, &rcToolBar);
|
||
|
rcToolBar.bottom = rcToolBar.top + cRows*RECT_HEIGHT(btnRc);
|
||
|
rcToolBar.right = RECT_WIDTH(rcWindowPos);
|
||
|
MoveWindow(hwndToolBar, rcToolBar.top+g_tbLeftMargin, rcToolBar.left, RECT_WIDTH(rcToolBar)-(g_tbLeftMargin+g_tbRightMargin), RECT_HEIGHT(rcToolBar), TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void CHHWinType::ToggleExpansion(bool bNotify /*=true*/)
|
||
|
{
|
||
|
if (!IsValidWindow(GetHwnd()))
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if (bNotify)
|
||
|
{
|
||
|
// Review: Should we check the return value? [dalero: 21 Sep 98]
|
||
|
OnTrackNotifyCaller(IsExpandedNavPane() ? HHACT_CONTRACT : HHACT_EXPAND) ;
|
||
|
}
|
||
|
|
||
|
RECT rc;
|
||
|
if (RECT_WIDTH(rcNav) <= 0)
|
||
|
{
|
||
|
rcNav.right = (iNavWidth ? iNavWidth : DEFAULT_NAV_WIDTH);
|
||
|
}
|
||
|
|
||
|
if (fNotExpanded)
|
||
|
{
|
||
|
fNotExpanded = FALSE; // now expanding
|
||
|
if (IsProperty(HHWIN_PROP_NAV_ONLY_WIN))
|
||
|
{
|
||
|
if (IsValidWindow(hwndHTML) )
|
||
|
{
|
||
|
ShowWindow(hwndHTML, SW_HIDE);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{ // normal tri-pane window
|
||
|
// Expand the window to the left to make room
|
||
|
|
||
|
::GetWindowRect(GetHwnd(), &rc);
|
||
|
rc.left -= RECT_WIDTH(rcNav) + m_pSizeBar->Width() ;
|
||
|
GetWorkArea(); // Multiple Monitor support.
|
||
|
if (rc.left < g_rcWorkArea.left)
|
||
|
{
|
||
|
rc.left = g_rcWorkArea.left;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
BUG 3463 --- the MoveWindow call below was not sending a WM_SIZE message, when
|
||
|
RECT_WIDTH(rc) > the width of the screen. Adjusting the width fixes this issue.nn
|
||
|
*/
|
||
|
// Don't make the window wider than the screen width.
|
||
|
if (rc.right > g_rcWorkArea.right)
|
||
|
{
|
||
|
rc.right = g_rcWorkArea.right;
|
||
|
}
|
||
|
|
||
|
// create a size bar window between the Nav pane and the HTML pane
|
||
|
CreateSizeBar(); // Moved because the function below resizes...
|
||
|
|
||
|
if (!m_fLockSize)
|
||
|
{
|
||
|
MoveWindow(GetHwnd(), rc.left, rc.top, RECT_WIDTH(rc), RECT_HEIGHT(rc), TRUE);
|
||
|
}
|
||
|
}
|
||
|
CreateOrShowNavPane();
|
||
|
if (GetToolBarHwnd())
|
||
|
{
|
||
|
SendMessage(GetToolBarHwnd(), TB_HIDEBUTTON, IDTB_EXPAND, TRUE);
|
||
|
SendMessage(GetToolBarHwnd(), TB_HIDEBUTTON, IDTB_CONTRACT, FALSE);
|
||
|
SendMessage(GetToolBarHwnd(), TB_ENABLEBUTTON, IDTB_CONTRACT, TRUE);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fNotExpanded = TRUE;
|
||
|
|
||
|
DestroySizeBar();
|
||
|
|
||
|
if ( m_hWndST )
|
||
|
ShowWindow(m_hWndST, SW_HIDE);
|
||
|
|
||
|
if ( m_hWndSSCB )
|
||
|
ShowWindow(m_hWndSSCB, SW_HIDE);
|
||
|
|
||
|
if (IsValidWindow(hwndNavigation))
|
||
|
{
|
||
|
ShowWindow(hwndNavigation, SW_HIDE);
|
||
|
}
|
||
|
if (IsProperty(HHWIN_PROP_NAV_ONLY_WIN))
|
||
|
{
|
||
|
ShowWindow(hwndHTML, SW_SHOW);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::GetWindowRect(GetHwnd(), &rc);
|
||
|
if (!m_fLockSize)
|
||
|
rc.left += RECT_WIDTH(rcNav) + m_pSizeBar->Width() ;
|
||
|
|
||
|
// make sure we are not going off the screen Bug 6611
|
||
|
GetWorkArea(); // Multiple Monitor support.
|
||
|
if (rc.left > g_rcWorkArea.right)
|
||
|
{
|
||
|
int min = GetSystemMetrics(SM_CXHTHUMB);
|
||
|
rc.left = g_rcWorkArea.right - min*2;
|
||
|
}
|
||
|
|
||
|
MoveWindow(GetHwnd(), rc.left, rc.top, RECT_WIDTH(rc), RECT_HEIGHT(rc), TRUE);
|
||
|
}
|
||
|
|
||
|
if (GetToolBarHwnd())
|
||
|
{
|
||
|
SendMessage(GetToolBarHwnd(), TB_HIDEBUTTON, IDTB_CONTRACT, TRUE);
|
||
|
SendMessage(GetToolBarHwnd(), TB_HIDEBUTTON, IDTB_EXPAND, FALSE);
|
||
|
SendMessage(GetToolBarHwnd(), TB_ENABLEBUTTON, IDTB_EXPAND, TRUE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CHHWinType::CreateSizeBar( void )
|
||
|
{
|
||
|
if (!m_pSizeBar && IsValidWindow(GetHTMLHwnd()))
|
||
|
{
|
||
|
m_pSizeBar = new CSizeBar ;
|
||
|
ASSERT(m_pSizeBar) ;
|
||
|
m_pSizeBar->Create(this) ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CHHWinType::DestroySizeBar( void )
|
||
|
{
|
||
|
if (m_pSizeBar)
|
||
|
{
|
||
|
delete m_pSizeBar ;
|
||
|
m_pSizeBar = NULL ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CHHWinType::CreateOrShowNavPane(void)
|
||
|
{
|
||
|
if (IsProperty(HHWIN_PROP_NAV_ONLY_WIN))
|
||
|
rcNav.right = rcHTML.right;
|
||
|
|
||
|
if (!IsValidWindow(hwndNavigation)/* && !IsProperty(HHWIN_PROP_NO_TOOLBAR)*/) {
|
||
|
rcNav.left = 0;
|
||
|
if (RECT_WIDTH(rcNav) <= 0)
|
||
|
{
|
||
|
rcNav.right = (iNavWidth ? iNavWidth : DEFAULT_NAV_WIDTH);
|
||
|
}
|
||
|
CalcHtmlPaneRect();
|
||
|
//
|
||
|
// Create the structural subset picker combo if necessary.
|
||
|
//
|
||
|
|
||
|
if (m_phmData && // BUG 5214
|
||
|
m_phmData->m_sysflags.fDoSS && !
|
||
|
m_phmData->m_pTitleCollection->IsSingleTitle() )
|
||
|
{
|
||
|
HFONT hFont, hFontOld;
|
||
|
TEXTMETRIC tm;
|
||
|
HDC hDC;
|
||
|
RECT rc;
|
||
|
|
||
|
hFont = _Resource.GetAccessableUIFont(); // GetUIFont();
|
||
|
hDC = GetDC(NULL);
|
||
|
hFontOld = (HFONT)SelectObject(hDC, hFont);
|
||
|
GetTextMetrics(hDC, &tm);
|
||
|
SelectObject(hDC, hFontOld);
|
||
|
ReleaseDC(NULL, hDC);
|
||
|
rcNav.top += 5;
|
||
|
m_iSSCBHeight = 5;
|
||
|
if ( (m_hWndST = CreateWindow("STATIC", GetStringResource(IDS_SUBSET_UI), WS_CHILD , rcNav.left + 6, rcNav.top,
|
||
|
RECT_WIDTH(rcNav) - 8, tm.tmHeight, GetHwnd(), NULL, _Module.GetModuleInstance(), NULL)) )
|
||
|
{
|
||
|
SendMessage(m_hWndST, WM_SETFONT, (WPARAM)hFont, 0L);
|
||
|
rcNav.top += tm.tmHeight + 2;
|
||
|
m_iSSCBHeight += tm.tmHeight + 2;
|
||
|
rc.left = rcNav.left + 6;
|
||
|
rc.top = rcNav.top;
|
||
|
rc.right = rcNav.right - 10;
|
||
|
rc.bottom = rcNav.top + tm.tmHeight + 10;
|
||
|
|
||
|
if(g_bWinNT5)
|
||
|
{
|
||
|
SetWindowTextW(m_hWndST,GetStringResourceW(IDS_SUBSET_UI));
|
||
|
}
|
||
|
|
||
|
|
||
|
m_hWndSSCB = CreateWindow("COMBOBOX", NULL, (WS_CHILD | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL), rc.left, rc.top,
|
||
|
RECT_WIDTH(rc), RECT_HEIGHT(rc) + 80, GetHwnd(), (HMENU)IDC_SS_PICKER,
|
||
|
_Module.GetModuleInstance(), NULL);
|
||
|
|
||
|
SendMessage(m_hWndSSCB, WM_SETFONT, (WPARAM)GetAccessableContentFont(), 0L);
|
||
|
rcNav.top += tm.tmHeight + 11;
|
||
|
m_iSSCBHeight += tm.tmHeight + 11;
|
||
|
ShowWindow(m_hWndST, SW_SHOW);
|
||
|
ShowWindow(m_hWndSSCB, SW_SHOW);
|
||
|
//
|
||
|
// Populate the combo.
|
||
|
//
|
||
|
if ( m_phmData->m_pTitleCollection->m_pSSList )
|
||
|
{
|
||
|
CStructuralSubset* pSSSel = NULL, *pSS = NULL;
|
||
|
while ( pSS = m_phmData->m_pTitleCollection->m_pSSList->GetNextSubset(pSS) )
|
||
|
{
|
||
|
if (! pSS->IsEmpty() ) // Don't put "new" here.
|
||
|
{
|
||
|
if(g_bWinNT5)
|
||
|
{
|
||
|
CExTitle *pTitle = m_phmData->m_pTitleCollection->GetFirstTitle();
|
||
|
|
||
|
DWORD cp;
|
||
|
|
||
|
if(pSS->IsEntire() == TRUE)
|
||
|
cp = CodePageFromLCID(MAKELCID(_Module.m_Language.GetUiLanguage(),SORT_DEFAULT));
|
||
|
else
|
||
|
cp = CodePageFromLCID((pTitle->GetInfo())->GetLanguage());
|
||
|
|
||
|
DWORD dwSize = (DWORD)(sizeof(WCHAR) * strlen(pSS->GetName())) + 4;
|
||
|
WCHAR *pwcString = (WCHAR *) lcMalloc(dwSize);
|
||
|
|
||
|
if(pwcString)
|
||
|
{
|
||
|
MultiByteToWideChar(cp, MB_PRECOMPOSED, pSS->GetName(), -1, pwcString, dwSize);
|
||
|
|
||
|
SendMessageW(m_hWndSSCB, CB_ADDSTRING, 0, (LPARAM)pwcString);
|
||
|
|
||
|
lcFree(pwcString);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SendMessage(m_hWndSSCB, CB_ADDSTRING, 0, (LPARAM)pSS->GetName());
|
||
|
}
|
||
|
}
|
||
|
if ( pSS->IsTOC() )
|
||
|
pSSSel = pSS;
|
||
|
}
|
||
|
// Select as appropiate...
|
||
|
//
|
||
|
if (! pSSSel )
|
||
|
pSSSel = m_phmData->m_pTitleCollection->m_pSSList->GetEC();
|
||
|
|
||
|
if(g_bWinNT5 && pSSSel->IsEntire())
|
||
|
{
|
||
|
// This code special cases the selection of the "Entire Collection" subset in the combobox.
|
||
|
//
|
||
|
WCHAR pszUnicodeSubsetName[MAX_SS_NAME_LEN];
|
||
|
|
||
|
pszUnicodeSubsetName[0] = 0;
|
||
|
|
||
|
// Get the UI language codepage
|
||
|
//
|
||
|
DWORD cp = CodePageFromLCID(MAKELCID(_Module.m_Language.GetUiLanguage(),SORT_DEFAULT));
|
||
|
|
||
|
// convert subset name to Unicode using UI codepage
|
||
|
//
|
||
|
MultiByteToWideChar(cp, MB_PRECOMPOSED, pSSSel->GetName(), -1, pszUnicodeSubsetName, sizeof(pszUnicodeSubsetName));
|
||
|
|
||
|
// select the subset in the combobox
|
||
|
//
|
||
|
SendMessageW(m_hWndSSCB, CB_SELECTSTRING, -1, (LPARAM)pszUnicodeSubsetName);
|
||
|
}
|
||
|
else
|
||
|
SendMessage(m_hWndSSCB, CB_SELECTSTRING, -1, (LPARAM)pSSSel->GetName());
|
||
|
|
||
|
|
||
|
m_phmData->m_pTitleCollection->m_pSSList->SetFTS(pSSSel);
|
||
|
m_phmData->m_pTitleCollection->m_pSSList->SetF1(pSSSel);
|
||
|
m_phmData->m_pTitleCollection->m_pSSList->SetTOC(pSSSel);
|
||
|
pSSSel->SelectAsTOCSubset(m_phmData->m_pTitleCollection);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Create the HH CHILD window on which the SysTabCtrl32 window will sit.
|
||
|
//txtHtmlHelpChildWindowClass
|
||
|
hwndNavigation = W_CreateWindow(L"HH Child", NULL, WS_CHILD, rcNav.left, rcNav.top, RECT_WIDTH(rcNav),
|
||
|
RECT_HEIGHT(rcNav), GetHwnd(), NULL, _Module.GetModuleInstance(), NULL);
|
||
|
|
||
|
// How many tabs do we have?
|
||
|
int cTabs = GetValidNavPaneCount();
|
||
|
if (cTabs > 1)
|
||
|
{
|
||
|
// Remove the non-existant tabs from the tab order.
|
||
|
|
||
|
int max = HH_MAX_TABS ;
|
||
|
for (int i = 0; i < max; i++) // Don't have to move last if invalid So don't add 1 to HH_MAX_TABS
|
||
|
{
|
||
|
if (!IsValidNavPane(tabOrder[i]))
|
||
|
{
|
||
|
// Collapse the array.
|
||
|
MemMove(&tabOrder[i], &tabOrder[i + 1], max - i);
|
||
|
// Decrement the count so we do this index again.
|
||
|
i-- ;
|
||
|
max-- ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now create the tab.
|
||
|
m_pTabCtrl = new CTabControl(hwndNavigation, tabpos, this);
|
||
|
}
|
||
|
ResizeWindow(this);
|
||
|
}
|
||
|
if (!IsProperty(HHWIN_PROP_NO_TOOLBAR))
|
||
|
ShowWindow(hwndNavigation, SW_SHOW);
|
||
|
if (m_pTabCtrl)
|
||
|
ShowWindow(m_pTabCtrl->hWnd(), SW_SHOW);
|
||
|
if ( m_hWndST )
|
||
|
ShowWindow(m_hWndST, SW_SHOW);
|
||
|
if ( m_hWndSSCB )
|
||
|
ShowWindow(m_hWndSSCB, SW_SHOW);
|
||
|
|
||
|
//Validate the current nav pane.
|
||
|
if (!IsValidNavPane(curNavType))
|
||
|
{
|
||
|
// The current nav pane doesn't exist. Pick another.
|
||
|
curNavType = GetValidNavPane() ;
|
||
|
if (curNavType < 0)
|
||
|
{
|
||
|
ASSERT(0) ; // Should never happen.
|
||
|
return; // hopeless...
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create the nav pane if needed.
|
||
|
CreateNavPane(curNavType) ;
|
||
|
|
||
|
// Show the pane.
|
||
|
if (m_aNavPane[curNavType])
|
||
|
{
|
||
|
if (curNavType != 0 && m_pTabCtrl)
|
||
|
TabCtrl_SetCurSel(m_pTabCtrl->hWnd(), GetTabIndexFromNavPaneIndex(curNavType));
|
||
|
m_aNavPane[curNavType]->ShowWindow() ;
|
||
|
|
||
|
// BUG HH 16685 - The current tab is now persisted. So we come along and
|
||
|
// create this new tab. However, resize is never called. So, we will call
|
||
|
// resize here to make sure that we resize the window.
|
||
|
m_aNavPane[curNavType]->ResizeWindow() ;
|
||
|
}
|
||
|
if ( m_pSizeBar )
|
||
|
m_pSizeBar->ResizeWindow();
|
||
|
}
|
||
|
|
||
|
void CHHWinType::CreateOrShowHTMLPane(void)
|
||
|
{
|
||
|
if (!IsValidWindow(hwndNavigation))
|
||
|
hwndHTML = CreateWindow(txtHtmlHelpChildWindowClass, NULL,
|
||
|
WS_CHILD | WS_CLIPCHILDREN, rcHTML.left, rcHTML.top,
|
||
|
RECT_WIDTH(rcHTML), RECT_HEIGHT(rcHTML), GetHwnd(), NULL,
|
||
|
_Module.GetModuleInstance(), NULL);
|
||
|
ShowWindow(hwndHTML, SW_SHOW);
|
||
|
}
|
||
|
|
||
|
void CHHWinType::CreateToc(void)
|
||
|
{
|
||
|
if (IsEmptyString(pszToc))
|
||
|
return;
|
||
|
TCHAR szPath[MAX_URL];
|
||
|
if (!ConvertToCacheFile(pszToc, szPath)) {
|
||
|
AuthorMsg(IDS_CANT_OPEN, pszToc);
|
||
|
strcpy(szPath, pszToc);
|
||
|
}
|
||
|
|
||
|
CToc* ptoc = new CToc(NULL, NULL, this);
|
||
|
m_aNavPane[HH_TAB_CONTENTS] = ptoc ;
|
||
|
ptoc->SetTabPos(tabpos);
|
||
|
ptoc->SetPadding(TAB_PADDING);
|
||
|
ptoc->ReadFile(szPath);
|
||
|
|
||
|
// populate the InfoType member object of the CToc
|
||
|
if ( !ptoc->m_pInfoType )
|
||
|
{
|
||
|
if (ptoc->m_phh && ptoc->m_phh->m_phmData && ptoc->m_phh->m_phmData->m_pdInfoTypes )
|
||
|
{ // load from the global IT store
|
||
|
ptoc->m_pInfoType = new CInfoType;
|
||
|
ptoc->m_pInfoType->CopyTo( ptoc->m_phh->m_phmData );
|
||
|
#if 0 // for subset testing purposes
|
||
|
#include "csubset.h"
|
||
|
CSubSets *pSubSets = new CSubSets( ptoc->m_pInfoType->InfoTypeSize(), ptoc->m_pInfoType, TRUE );
|
||
|
pSubSets->CopyTo( ptoc->m_phh->m_phmData );
|
||
|
#endif
|
||
|
}
|
||
|
else {
|
||
|
// no global IT's; load from the .hhc IT store
|
||
|
ptoc->m_pInfoType = new CInfoType;
|
||
|
*ptoc->m_pInfoType = ptoc->m_sitemap;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ptoc->SetStyles(WS_EX_CLIENTEDGE,
|
||
|
ptoc->m_sitemap.m_tvStyles == (DWORD) -1 ?
|
||
|
DEFAULT_TOC_STYLES : ptoc->m_sitemap.m_tvStyles);
|
||
|
ptoc->Create((m_pTabCtrl ? m_pTabCtrl->hWnd() :
|
||
|
(IsValidWindow(hwndNavigation) ? hwndNavigation : hwndHelp)));
|
||
|
ptoc->m_fHack = FALSE;
|
||
|
|
||
|
ptoc->InitTreeView();
|
||
|
|
||
|
}
|
||
|
|
||
|
void CHHWinType::UpdateInformationTypes(void)
|
||
|
{
|
||
|
if ( m_aNavPane[HH_TAB_CONTENTS] )
|
||
|
{
|
||
|
m_aNavPane[HH_TAB_CONTENTS]->Refresh();
|
||
|
if (IsProperty(HHWIN_PROP_AUTO_SYNC) && IsExpandedNavPane())
|
||
|
{
|
||
|
CStr cszUrl;
|
||
|
m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
|
||
|
m_aNavPane[HH_TAB_CONTENTS]->Synchronize(cszUrl);
|
||
|
}
|
||
|
// Next/Prev command UI updates...
|
||
|
//
|
||
|
UpdateCmdUI();
|
||
|
}
|
||
|
if ( m_aNavPane[HH_TAB_INDEX] && curNavType == HHWIN_NAVTYPE_INDEX )
|
||
|
m_aNavPane[HH_TAB_INDEX]->Refresh();
|
||
|
}
|
||
|
|
||
|
void CHHWinType::UpdateCmdUI(void)
|
||
|
{
|
||
|
HMENU hMenu;
|
||
|
BOOL bEnable, ptoc;
|
||
|
|
||
|
ptoc = (m_aNavPane[HH_TAB_CONTENTS] != NULL);
|
||
|
if ( IsValidWindow(hwndToolBar) )
|
||
|
{
|
||
|
if ( hwndHelp )
|
||
|
hMenu = GetMenu(hwndHelp);
|
||
|
//
|
||
|
// Does TOCNext or TOCPrev need to be enabled/disabled ?
|
||
|
//
|
||
|
if ( (fsToolBarFlags & HHWIN_BUTTON_TOC_PREV) || (fsToolBarFlags & HHWIN_BUTTON_TOC_NEXT) || hMenu )
|
||
|
{
|
||
|
bEnable = ptoc ? OnTocPrev(FALSE) : FALSE ; // If no TOC, disable.
|
||
|
if ( fsToolBarFlags & HHWIN_BUTTON_TOC_PREV )
|
||
|
SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDTB_TOC_PREV, bEnable);
|
||
|
if ( hMenu )
|
||
|
EnableMenuItem(hMenu, IDTB_TOC_PREV, (MF_BYCOMMAND | (bEnable?MF_ENABLED:MF_GRAYED)));
|
||
|
|
||
|
bEnable = ptoc ? OnTocNext(FALSE) : FALSE; // If no TOC, disable.
|
||
|
if ( fsToolBarFlags & HHWIN_BUTTON_TOC_NEXT )
|
||
|
SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDTB_TOC_NEXT, bEnable);
|
||
|
if ( hMenu )
|
||
|
EnableMenuItem(hMenu, IDTB_TOC_NEXT, (MF_BYCOMMAND | (bEnable?MF_ENABLED:MF_GRAYED)));
|
||
|
}
|
||
|
if (NoRun() == TRUE)
|
||
|
{
|
||
|
if (hMenu)
|
||
|
EnableMenuItem(hMenu, HHM_JUMP_URL, MF_BYCOMMAND|MF_GRAYED);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CreateIndex
|
||
|
//
|
||
|
void CHHWinType::CreateIndex(void)
|
||
|
{
|
||
|
if (IsEmptyString(pszIndex))
|
||
|
return;
|
||
|
TCHAR szPath[MAX_URL];
|
||
|
if (!ConvertToCacheFile(pszIndex, szPath)) {
|
||
|
AuthorMsg(IDS_CANT_OPEN, pszIndex);
|
||
|
strcpy(szPath, pszIndex);
|
||
|
}
|
||
|
|
||
|
if (!m_aNavPane[HH_TAB_INDEX])
|
||
|
{
|
||
|
CIndex* pIndex = new CIndex(NULL, NULL, this);
|
||
|
m_aNavPane[HH_TAB_INDEX] = pIndex ;
|
||
|
pIndex->SetPadding(TAB_PADDING);
|
||
|
pIndex->SetTabPos(tabpos);
|
||
|
pIndex->ReadIndexFile(szPath); // A CIndex function, but not a INavUI function.
|
||
|
}
|
||
|
m_aNavPane[HH_TAB_INDEX]->Create(GetTabCtrlHwnd());
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CreateSearchTab
|
||
|
//
|
||
|
void CHHWinType::CreateSearchTab(void)
|
||
|
{
|
||
|
if (!
|
||
|
m_phmData || !m_phmData->m_pTitleCollection->m_pFullTextSearch)
|
||
|
return; // no compiled information
|
||
|
|
||
|
if (!m_aNavPane[HH_TAB_SEARCH])
|
||
|
{
|
||
|
if (IsProperty(HHWIN_PROP_TAB_ADVSEARCH))
|
||
|
{
|
||
|
//---Create the Advanced Search Navigation Pane.
|
||
|
m_aNavPane[HH_TAB_SEARCH] = new CAdvancedSearchNavPane(this);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//---Create the simple Search Navigation Pane.
|
||
|
m_aNavPane[HH_TAB_SEARCH] = new CSearch(this);
|
||
|
}
|
||
|
m_aNavPane[HH_TAB_SEARCH]->SetPadding(TAB_PADDING);
|
||
|
m_aNavPane[HH_TAB_SEARCH]->SetTabPos(tabpos);
|
||
|
}
|
||
|
|
||
|
m_aNavPane[HH_TAB_SEARCH]->Create(GetTabCtrlHwnd());
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CreateBookmarksTab
|
||
|
//
|
||
|
void
|
||
|
CHHWinType::CreateBookmarksTab()
|
||
|
{
|
||
|
if (!m_aNavPane[HH_TAB_FAVORITES])
|
||
|
{
|
||
|
CBookmarksNavPane* p= new CBookmarksNavPane(this);
|
||
|
m_aNavPane[HH_TAB_FAVORITES] = p;
|
||
|
p->SetPadding(TAB_PADDING);
|
||
|
p->SetTabPos(tabpos);
|
||
|
}
|
||
|
m_aNavPane[HH_TAB_FAVORITES]->Create(GetTabCtrlHwnd());
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CreatesCustomTab - Creates a tab defined by the client.
|
||
|
//
|
||
|
void
|
||
|
CHHWinType::CreateCustomTab(int iPane, LPCOLESTR pszProgId)
|
||
|
{
|
||
|
// REVIEW: The lines marked with [chm] assume that the information can be found in the chm file.
|
||
|
if (!m_aNavPane[iPane])
|
||
|
{
|
||
|
CCustomNavPane* p= new CCustomNavPane(this);
|
||
|
m_aNavPane[iPane] = p;
|
||
|
p->SetPadding(TAB_PADDING);
|
||
|
p->SetTabPos(tabpos);
|
||
|
|
||
|
p->SetControlProgId(pszProgId); //[chm] We could also use the GUID instead/in addition.
|
||
|
}
|
||
|
m_aNavPane[iPane]->Create(GetTabCtrlHwnd());
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Destructor
|
||
|
//
|
||
|
CHHWinType::~CHHWinType()
|
||
|
{
|
||
|
CloseWindow();
|
||
|
}
|
||
|
|
||
|
extern BOOL g_fThreadCall;
|
||
|
extern HWND g_hwndApi;
|
||
|
|
||
|
//
|
||
|
// This member can be called from DllMain at process detach time. Note that this is only a partial cleanup but
|
||
|
// it's the best we can do at process detach time.
|
||
|
//
|
||
|
//
|
||
|
void CHHWinType::ProcessDetachSafeCleanup()
|
||
|
{
|
||
|
if (m_pTabCtrl) {
|
||
|
delete m_pTabCtrl;
|
||
|
m_pTabCtrl = NULL;
|
||
|
}
|
||
|
|
||
|
// Get rid of the sizebar.
|
||
|
DestroySizeBar() ;
|
||
|
|
||
|
if (m_ptblBtnStrings) {
|
||
|
delete m_ptblBtnStrings;
|
||
|
m_ptblBtnStrings = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CHHWinType::CloseWindow()
|
||
|
{
|
||
|
// Save the state..
|
||
|
SaveState() ;
|
||
|
|
||
|
// Things we can cleanup a process shutdown.
|
||
|
ProcessDetachSafeCleanup() ;
|
||
|
|
||
|
// Things we cleanup when we are reloading the nav panes.
|
||
|
ReloadCleanup() ;
|
||
|
|
||
|
// Free here and not in ReloadCleanup.
|
||
|
CHECK_AND_FREE( pszHome );
|
||
|
CHECK_AND_FREE( pszCustomTabs );
|
||
|
CHECK_AND_FREE( pszType );
|
||
|
CHECK_AND_FREE( pszCaption );
|
||
|
|
||
|
if (m_pCIExpContainer)
|
||
|
{
|
||
|
m_pCIExpContainer->ShutDown(); // This call WILL end up doing the delete m_pCIExpContainer;
|
||
|
m_pCIExpContainer = NULL;
|
||
|
}
|
||
|
|
||
|
if ( m_phmData && !m_phmData->Release() ) // Cleanup ChmData
|
||
|
{
|
||
|
//
|
||
|
// Find this instance of the ChmData in the global array, null out it's entry and clean this one up.
|
||
|
//
|
||
|
for (int n = 0; n < g_cHmSlots; n++)
|
||
|
{
|
||
|
if ( g_phmData && (g_phmData[n] == m_phmData) )
|
||
|
{
|
||
|
g_phmData[n] = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
m_phmData = NULL;
|
||
|
|
||
|
if (IsProperty(HHWIN_PROP_POST_QUIT))
|
||
|
{
|
||
|
PostQuitMessage(0);
|
||
|
}
|
||
|
|
||
|
// Null out our window from the window list.
|
||
|
for (int i = 0; i < g_cWindowSlots; i++)
|
||
|
{
|
||
|
if (pahwnd[i] != NULL && pahwnd[i]->hwndHelp == hwndHelp)
|
||
|
{
|
||
|
pahwnd[i] = NULL ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
curNavType = 0;
|
||
|
hwndHelp = NULL;
|
||
|
|
||
|
// Do other windows exist?
|
||
|
for (i = 0; i < g_cWindowSlots; i++)
|
||
|
{
|
||
|
if (pahwnd[i] != NULL && pahwnd[i]->hwndHelp != NULL)
|
||
|
{
|
||
|
// If other windows exist exit.
|
||
|
return ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for(int j=0; i< c_NUMNAVPANES; i++)
|
||
|
{
|
||
|
if ( m_aNavPane[j] )
|
||
|
{
|
||
|
delete m_aNavPane[j];
|
||
|
m_aNavPane[j] = NULL;
|
||
|
}
|
||
|
}
|
||
|
if ( m_pTabCtrl )
|
||
|
{
|
||
|
delete m_pTabCtrl;
|
||
|
m_pTabCtrl = NULL;
|
||
|
}
|
||
|
if ( m_pSizeBar )
|
||
|
{
|
||
|
delete m_pSizeBar;
|
||
|
m_pSizeBar = NULL;
|
||
|
}
|
||
|
|
||
|
if (m_hAccel)
|
||
|
{
|
||
|
DestroyAcceleratorTable(m_hAccel) ;
|
||
|
m_hAccel = NULL ;
|
||
|
}
|
||
|
|
||
|
if( m_hMenuOptions ) {
|
||
|
DestroyMenu( m_hMenuOptions );
|
||
|
m_hMenuOptions = NULL;
|
||
|
}
|
||
|
|
||
|
if( m_hImageListGray ) {
|
||
|
ImageList_Destroy( m_hImageListGray );
|
||
|
m_hImageListGray = NULL;
|
||
|
}
|
||
|
|
||
|
if( m_hImageList ) {
|
||
|
ImageList_Destroy( m_hImageList );
|
||
|
m_hImageList = NULL;
|
||
|
}
|
||
|
|
||
|
if( hwndToolBar ) {
|
||
|
DestroyWindow( hwndToolBar );
|
||
|
hwndToolBar = NULL;
|
||
|
}
|
||
|
|
||
|
// If we got here, all windows have been closed
|
||
|
|
||
|
DeleteAllHmData();
|
||
|
|
||
|
#ifdef _CHECKMEM_ON_CLOSEWINDOW_
|
||
|
_CrtMemDumpAllObjectsSince(&m_MemState) ;
|
||
|
#endif
|
||
|
|
||
|
if (g_fThreadCall && g_hwndApi)
|
||
|
PostQuitMessage(0);
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// ReloadCleanUp --- This is the things we have to clean up before we reload the nav pane.
|
||
|
//
|
||
|
void
|
||
|
CHHWinType::ReloadCleanup()
|
||
|
{
|
||
|
// Delete all of the navigation panes.
|
||
|
for(int j = 0 ; j < c_NUMNAVPANES ; j++)
|
||
|
{
|
||
|
if (m_aNavPane[j])
|
||
|
{
|
||
|
delete m_aNavPane[j] ;
|
||
|
m_aNavPane[j] = NULL ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CHECK_AND_FREE( pszToc );
|
||
|
CHECK_AND_FREE( pszIndex );
|
||
|
CHECK_AND_FREE( pszFile );
|
||
|
CHECK_AND_FREE( pszJump1 );
|
||
|
CHECK_AND_FREE( pszJump2 );
|
||
|
CHECK_AND_FREE( pszUrlJump1 );
|
||
|
CHECK_AND_FREE( pszUrlJump2 );
|
||
|
|
||
|
// Don't free this here. Because we need to keep this around.
|
||
|
// CHECK_AND_FREE( pszHome );
|
||
|
//CHECK_AND_FREE( pszCustomTabs );
|
||
|
//CHECK_AND_FREE( pszType );
|
||
|
//CHECK_AND_FREE( pszCaption );
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CHHWinType::SaveState()
|
||
|
{
|
||
|
WINDOW_STATE wstate;
|
||
|
WINDOWPLACEMENT winPlace;
|
||
|
|
||
|
wstate.cbStruct = sizeof(wstate);
|
||
|
|
||
|
winPlace.length = sizeof(WINDOWPLACEMENT);
|
||
|
GetWindowPlacement(GetHwnd(), &winPlace);
|
||
|
|
||
|
if (winPlace.showCmd == SW_SHOWMINIMIZED)
|
||
|
{
|
||
|
wstate.rcPos = winPlace.rcNormalPosition;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::GetWindowRect(GetHwnd(), &wstate.rcPos);
|
||
|
}
|
||
|
wstate.iNavWidth = rcNav.right;
|
||
|
wstate.fHighlight = (m_phmData&&m_phmData->m_pTitleCollection->m_pSearchHighlight)?m_phmData->m_pTitleCollection->m_pSearchHighlight->m_bHighlightEnabled:TRUE;
|
||
|
wstate.fLockSize = m_fLockSize;
|
||
|
wstate.fNoToolBarText = m_fNoToolBarText;
|
||
|
wstate.curNavType = curNavType;
|
||
|
wstate.fNotExpanded = fNotExpanded;
|
||
|
|
||
|
if( m_phmData ) {
|
||
|
CState* pstate = m_phmData->m_pTitleCollection->GetState();
|
||
|
if (SUCCEEDED(pstate->Open(GetTypeName(), STGM_WRITE))) {
|
||
|
pstate->Write(&wstate, sizeof(wstate));
|
||
|
pstate->Close();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int CHHWinType::CreateToolBar(TBBUTTON* pabtn)
|
||
|
{
|
||
|
// create a dropdown menu for the options button to display
|
||
|
int cMenuItems=0;
|
||
|
const int MENUITEMSTRINGLEN = 80;
|
||
|
CStr cszMenuItem;
|
||
|
m_hMenuOptions = CreatePopupMenu();
|
||
|
cszMenuItem.ReSize(MENUITEMSTRINGLEN);
|
||
|
|
||
|
ASSERT(!IsProperty(HHWIN_PROP_NO_TOOLBAR));
|
||
|
if (m_ptblBtnStrings)
|
||
|
delete m_ptblBtnStrings;
|
||
|
m_ptblBtnStrings = new CTable(256); // room for 256 bytes
|
||
|
|
||
|
int cButtons = 0;
|
||
|
|
||
|
MENUITEMINFO mii;
|
||
|
ZERO_STRUCTURE ( mii );
|
||
|
mii.cbSize = sizeof(MENUITEMINFO);
|
||
|
mii.fMask = MIIM_TYPE|MIIM_STATE|MIIM_ID|MIIM_SUBMENU|MIIM_CHECKMARKS;
|
||
|
mii.fType = MFT_STRING;
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_EXPAND) {
|
||
|
pabtn[cButtons].iBitmap = 12;
|
||
|
pabtn[cButtons].idCommand = IDTB_EXPAND;
|
||
|
pabtn[cButtons].fsState = (IsExpandedNavPane() ? TBSTATE_HIDDEN : TBSTATE_ENABLED);
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_EXPAND));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_EXPAND) {
|
||
|
pabtn[cButtons].iBitmap = 13;
|
||
|
pabtn[cButtons].idCommand = IDTB_CONTRACT;
|
||
|
pabtn[cButtons].fsState = (IsExpandedNavPane() ? TBSTATE_ENABLED : TBSTATE_HIDDEN);
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_CONTRACT));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_SYNC) {
|
||
|
if (!IsEmptyString(pszToc)) {
|
||
|
pabtn[cButtons].iBitmap = 9;
|
||
|
pabtn[cButtons].idCommand = IDTB_SYNC;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_SYNC));
|
||
|
cButtons++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_TOC_PREV) {
|
||
|
pabtn[cButtons].iBitmap = 14;
|
||
|
pabtn[cButtons].idCommand = IDTB_TOC_PREV;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_TOC_PREV));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_TOC_NEXT) {
|
||
|
pabtn[cButtons].iBitmap = 8;
|
||
|
pabtn[cButtons].idCommand = IDTB_TOC_NEXT;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_TOC_NEXT));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (g_fBiDi)
|
||
|
{
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_FORWARD) {
|
||
|
pabtn[cButtons].iBitmap = 0;
|
||
|
pabtn[cButtons].idCommand = IDTB_FORWARD;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_FORWARD));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_BACK) {
|
||
|
pabtn[cButtons].iBitmap = 1;
|
||
|
pabtn[cButtons].idCommand = IDTB_BACK;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_BACK));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_BACK) {
|
||
|
pabtn[cButtons].iBitmap = 0;
|
||
|
pabtn[cButtons].idCommand = IDTB_BACK;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_BACK));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_FORWARD) {
|
||
|
pabtn[cButtons].iBitmap = 1;
|
||
|
pabtn[cButtons].idCommand = IDTB_FORWARD;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_FORWARD));
|
||
|
cButtons++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_STOP) {
|
||
|
pabtn[cButtons].iBitmap = 2;
|
||
|
pabtn[cButtons].idCommand = IDTB_STOP;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_STOP));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if ( fsToolBarFlags & HHWIN_BUTTON_REFRESH) {
|
||
|
pabtn[cButtons].iBitmap = 3;
|
||
|
pabtn[cButtons].idCommand = IDTB_REFRESH;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_REFRESH));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_HOME) {
|
||
|
if (pszHome) {
|
||
|
pabtn[cButtons].iBitmap = 4;
|
||
|
pabtn[cButtons].idCommand = IDTB_HOME;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_HOME));
|
||
|
cButtons++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_BROWSE_FWD) {
|
||
|
if (pszHome) {
|
||
|
pabtn[cButtons].iBitmap = 14;
|
||
|
pabtn[cButtons].idCommand = IDTB_BROWSE_FWD;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_BROWSE_FWD));
|
||
|
cButtons++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_BROWSE_BCK) {
|
||
|
if (pszHome) {
|
||
|
pabtn[cButtons].iBitmap = 8;
|
||
|
pabtn[cButtons].idCommand = IDTB_BROWSE_BACK;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_BROWSE_BACK));
|
||
|
cButtons++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_ZOOM) {
|
||
|
pabtn[cButtons].iBitmap = 16; // BUGBUG: We need a zoom glyph in toolb16g.bmp
|
||
|
pabtn[cButtons].idCommand = IDTB_ZOOM;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_ZOOM));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if ( fsToolBarFlags & HHWIN_BUTTON_PRINT) {
|
||
|
pabtn[cButtons].iBitmap = 7;
|
||
|
pabtn[cButtons].idCommand = IDTB_PRINT;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_PRINT));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
//--- hard-coded menu
|
||
|
CTable tblMenus(8 * 1024);
|
||
|
|
||
|
mii.cbSize = sizeof(MENUITEMINFO);
|
||
|
mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
|
||
|
mii.fType = MFT_STRING;
|
||
|
mii.fState = MFS_ENABLED;
|
||
|
|
||
|
mii.hSubMenu = NULL;
|
||
|
mii.hbmpChecked = NULL; // bitmap tp display when checked
|
||
|
mii.hbmpUnchecked = NULL; // bitmap to display when not checked
|
||
|
mii.dwItemData = NULL; // data associated with the menu item
|
||
|
|
||
|
mii.wID = IDTB_CONTRACT; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_HIDE); // the string to display for the menu item
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen(mii.dwTypeData); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_SYNC)
|
||
|
{
|
||
|
if (!IsEmptyString(pszToc))
|
||
|
{
|
||
|
mii.wID = IDTB_SYNC; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_SYNC); // the string to display for the menu item
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen(mii.dwTypeData); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mii.wID = IDTB_BACK; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_BACK); // the string to display for the menu item
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen(mii.dwTypeData); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
|
||
|
mii.wID = IDTB_FORWARD; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_FORWARD); // the string to display for the menu item
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
|
||
|
if (pszHome) {
|
||
|
mii.wID = IDTB_HOME; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_HOME); // the string to display for the menu item
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
}
|
||
|
|
||
|
mii.wID = IDTB_STOP; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_STOP); // the string to display for the menu item
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
|
||
|
mii.wID = IDTB_REFRESH; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_REFRESH); // the string to display for the menu item
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
|
||
|
mii.wID = HHM_OPTIONS; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_IE_OPTIONS); // the string to display for the menu item
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
|
||
|
mii.fMask = MIIM_TYPE;
|
||
|
mii.fType = MFT_SEPARATOR;
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
|
||
|
// Now restore the mast and type
|
||
|
|
||
|
mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
|
||
|
mii.fType = MFT_STRING;
|
||
|
BOOL fSeperatorNeeded = FALSE;
|
||
|
|
||
|
/*
|
||
|
* At this point, we need to add any custom Jump buttons, and to do
|
||
|
* that we need to know all of the hard-coded menu items so that we can
|
||
|
* adjust the accelerators as needed.
|
||
|
*/
|
||
|
|
||
|
if ((fsToolBarFlags & HHWIN_BUTTON_JUMP1 && pszJump1) ||
|
||
|
(fsToolBarFlags & HHWIN_BUTTON_JUMP2 && pszJump2)) {
|
||
|
tblMenus.AddString(GetStringResource(IDS_OPTION_CUSTOMIZE));
|
||
|
tblMenus.AddString(GetStringResource(IDS_OPTION_PRINT));
|
||
|
if (!g_fIE3 && m_phmData && m_phmData->m_pTitleCollection && m_phmData->m_pTitleCollection->m_pSearchHighlight)
|
||
|
tblMenus.AddString(GetStringResource(IDS_OPTION_HILITING_OFF));
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_JUMP1 && pszJump1) {
|
||
|
mii.wID = IDTB_JUMP1; // Menu Item ID
|
||
|
cszMenuItem = "&1 ";
|
||
|
cszMenuItem += pszJump1;
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
fSeperatorNeeded = TRUE;
|
||
|
}
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_JUMP2 && pszJump2) {
|
||
|
mii.wID = IDTB_JUMP2; // Menu Item ID
|
||
|
cszMenuItem = "&2 ";
|
||
|
cszMenuItem += pszJump2;
|
||
|
tblMenus.AddString(cszMenuItem.psz);
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
fSeperatorNeeded = TRUE;
|
||
|
}
|
||
|
|
||
|
if (fSeperatorNeeded) {
|
||
|
mii.fMask = MIIM_TYPE;
|
||
|
mii.fType = MFT_SEPARATOR;
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
|
||
|
// Now restore the mast and type
|
||
|
|
||
|
mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
|
||
|
mii.fType = MFT_STRING;
|
||
|
}
|
||
|
|
||
|
if (m_phmData && m_phmData->m_pInfoType && m_phmData->m_pInfoType->HowManyInfoTypes() > 0)
|
||
|
{
|
||
|
mii.wID = IDTB_CUSTOMIZE; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_CUSTOMIZE); // the string to display for the menu item
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
}
|
||
|
|
||
|
mii.wID = IDTB_PRINT; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_PRINT); // the string to display for the menu item
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
// --- end fixed menu
|
||
|
|
||
|
if (!g_fIE3 && m_phmData && m_phmData->m_pTitleCollection && m_phmData->m_pTitleCollection->m_pSearchHighlight) {
|
||
|
|
||
|
// Add search term hiliting to the options menu.
|
||
|
|
||
|
mii.wID = IDTB_HILITE; // Menu Item ID
|
||
|
cszMenuItem = GetStringResource(IDS_OPTION_HILITING_OFF); // the string to display for the menu item
|
||
|
mii.dwTypeData = cszMenuItem.psz;
|
||
|
mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
|
||
|
|
||
|
HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
|
||
|
}
|
||
|
|
||
|
if ( fsToolBarFlags & HHWIN_BUTTON_OPTIONS && cMenuItems) {
|
||
|
pabtn[cButtons].iBitmap = 10;
|
||
|
pabtn[cButtons].idCommand = IDTB_OPTIONS;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].fsStyle = TBSTYLE_DROPDOWN;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_OPTIONS));
|
||
|
|
||
|
if ( cMenuItems )
|
||
|
pabtn[cButtons].dwData = (DWORD_PTR)m_hMenuOptions;
|
||
|
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_NOTES) {
|
||
|
pabtn[cButtons].iBitmap = 11;
|
||
|
pabtn[cButtons].idCommand = IDTB_NOTES;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_NOTES));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_CONTENTS) {
|
||
|
pabtn[cButtons].iBitmap = 15;
|
||
|
pabtn[cButtons].idCommand = IDTB_CONTENTS;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_CONTENTS));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_INDEX) {
|
||
|
pabtn[cButtons].iBitmap = 16;
|
||
|
pabtn[cButtons].idCommand = IDTB_INDEX;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_INDEX));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_SEARCH) {
|
||
|
pabtn[cButtons].iBitmap = 5;
|
||
|
pabtn[cButtons].idCommand = IDTB_SEARCH;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_SEARCH));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_HISTORY) {
|
||
|
pabtn[cButtons].iBitmap = 19;
|
||
|
pabtn[cButtons].idCommand = IDTB_HISTORY;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_HISTORY));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_FAVORITES) {
|
||
|
pabtn[cButtons].iBitmap = 6;
|
||
|
pabtn[cButtons].idCommand = IDTB_FAVORITES;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(GetStringResource(IDTB_FAVORITES));
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if ((fsToolBarFlags & HHWIN_BUTTON_JUMP1) && !(IsProperty(HHWIN_PROP_MENU))) {
|
||
|
pabtn[cButtons].iBitmap = 17;
|
||
|
pabtn[cButtons].idCommand = IDTB_JUMP1;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(pszJump1 ? pszJump1 : "");
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
if ((fsToolBarFlags & HHWIN_BUTTON_JUMP2) && !(IsProperty(HHWIN_PROP_MENU))) {
|
||
|
pabtn[cButtons].iBitmap = 18;
|
||
|
pabtn[cButtons].idCommand = IDTB_JUMP2;
|
||
|
pabtn[cButtons].fsState = TBSTATE_ENABLED;
|
||
|
pabtn[cButtons].iString = cButtons;
|
||
|
m_ptblBtnStrings->AddString(pszJump2 ? pszJump2 : "");
|
||
|
cButtons++;
|
||
|
}
|
||
|
|
||
|
return cButtons;
|
||
|
}
|
||
|
|
||
|
// No longer used, but we'll keep in around awhile just in case
|
||
|
|
||
|
/*
|
||
|
static void FixDupMenuAccelerator(const CTable* ptbl, PSTR pszMenu)
|
||
|
{
|
||
|
int i;
|
||
|
PSTR pszOrg;
|
||
|
PSTR pszTmp = StrChr(pszMenu, ACCESS_KEY);
|
||
|
|
||
|
if (!pszTmp) {
|
||
|
MoveMemory(pszMenu + 1, pszMenu, strlen(pszMenu) + 1);
|
||
|
*pszMenu = ACCESS_KEY;
|
||
|
pszTmp = pszMenu;
|
||
|
}
|
||
|
pszOrg = pszTmp;
|
||
|
|
||
|
SHORT ch = VkKeyScan((BYTE) CharLower((LPSTR) pszTmp[1]));
|
||
|
|
||
|
for (i = 1; i <= ptbl->CountStrings(); i++) {
|
||
|
|
||
|
// check for a duplicate accelerator key
|
||
|
|
||
|
PCSTR psz = StrChr(ptbl->GetPointer(i), ACCESS_KEY);
|
||
|
if (VkKeyScan((BYTE) CharLower((LPSTR) psz[1])) == ch) {
|
||
|
strcpy(pszTmp, pszTmp + 1); // remove the accelerator
|
||
|
pszTmp++;
|
||
|
if (!*pszTmp) {
|
||
|
|
||
|
// End of string, nothing we can do
|
||
|
|
||
|
MoveMemory(pszOrg + 1, pszOrg, strlen(pszOrg) + 1);
|
||
|
*pszOrg = ACCESS_KEY;
|
||
|
return;
|
||
|
}
|
||
|
else {
|
||
|
MoveMemory(pszTmp + 1, pszTmp, strlen(pszTmp) + 1);
|
||
|
*pszTmp = ACCESS_KEY;
|
||
|
ch = VkKeyScan((BYTE) CharLower((LPSTR) pszTmp[1]));
|
||
|
i = 0; // start over
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
#ifndef TCS_FLATBUTTONS
|
||
|
#define TCS_FLATBUTTONS 0x0008
|
||
|
#endif
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// IsValidTab(int iTab) --- Index returned from tabOrder.
|
||
|
//
|
||
|
BOOL
|
||
|
CHHWinType::IsValidNavPane(int iTab)
|
||
|
{
|
||
|
|
||
|
//REVIEW:: Assumes that the tabs have not been re-ordered!
|
||
|
|
||
|
BOOL bResult = FALSE ;
|
||
|
|
||
|
// We only have valid tabs if we are a TRI_PANE.
|
||
|
if (IsProperty(HHWIN_PROP_TRI_PANE))
|
||
|
{
|
||
|
switch(iTab)
|
||
|
{
|
||
|
|
||
|
case HH_TAB_CONTENTS:
|
||
|
if (!IsEmptyString(pszToc) && tabOrder[HH_TAB_CONTENTS] != 255)
|
||
|
bResult = TRUE ;
|
||
|
break;
|
||
|
|
||
|
case HH_TAB_INDEX:
|
||
|
if (!IsEmptyString(pszIndex) && tabOrder[HH_TAB_INDEX] != 255)
|
||
|
bResult = TRUE ;
|
||
|
break;
|
||
|
|
||
|
case HH_TAB_SEARCH:
|
||
|
if ((fsWinProperties & HHWIN_PROP_TAB_SEARCH) /*&& m_phmData && m_phmData->m_sysflags.fFTI*/)
|
||
|
{
|
||
|
//BUGBUG: m_phmdata isn't always valid when we are getting called. See HH_SET_WIN_TYPE
|
||
|
bResult = TRUE ;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case HH_TAB_HISTORY:
|
||
|
if (fsWinProperties & HHWIN_PROP_TAB_HISTORY)
|
||
|
bResult = TRUE ;
|
||
|
break;
|
||
|
|
||
|
case HH_TAB_FAVORITES:
|
||
|
if (fsWinProperties & HHWIN_PROP_TAB_FAVORITES)
|
||
|
bResult = TRUE ;
|
||
|
break;
|
||
|
|
||
|
#ifdef __TEST_CUSTOMTAB__
|
||
|
case HH_TAB_AUTHOR:
|
||
|
return IsHelpAuthor(GetHwnd());
|
||
|
#endif
|
||
|
|
||
|
default:
|
||
|
if (iTab >= HH_TAB_CUSTOM_FIRST && iTab <= HH_TAB_CUSTOM_LAST)
|
||
|
{
|
||
|
if (fsWinProperties & (HHWIN_PROP_TAB_CUSTOM1 << (iTab - HH_TAB_CUSTOM_FIRST)))
|
||
|
{
|
||
|
bResult = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// GetValidNavPane --- Returns the index of the first valid tab it finds. -1 if no valid tabs.
|
||
|
//
|
||
|
int
|
||
|
CHHWinType::GetValidNavPane()
|
||
|
{
|
||
|
for (int i = 0 ; i < HH_MAX_TABS+1 ; i++)
|
||
|
{
|
||
|
if (IsValidNavPane(i))
|
||
|
{
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1 ;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// GetNavPaneCount --- Counts the number of valid navigation panes
|
||
|
//
|
||
|
int CHHWinType::GetValidNavPaneCount()
|
||
|
{
|
||
|
|
||
|
int count = 0 ;
|
||
|
for (int i = 0 ; i < HH_MAX_TABS+1 ; i++)
|
||
|
{
|
||
|
if (IsValidNavPane(i))
|
||
|
{
|
||
|
count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return count;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void CHHWinType::OnNavigateComplete(LPCTSTR pszUrl)
|
||
|
{
|
||
|
// Update the Bookmark pane if it exists.
|
||
|
if (curNavType == HH_TAB_FAVORITES && m_aNavPane[HH_TAB_FAVORITES])
|
||
|
{
|
||
|
// Here we are synchronizing the current topic edit control in the bookmarks pane
|
||
|
// witht he current topic.
|
||
|
m_aNavPane[HH_TAB_FAVORITES]->Synchronize(NULL) ;
|
||
|
}
|
||
|
|
||
|
// Get a pointer to the toc if it exists.
|
||
|
CToc* ptoc = NULL ;
|
||
|
if (m_aNavPane[HH_TAB_CONTENTS])
|
||
|
{
|
||
|
ptoc = reinterpret_cast<CToc*>(m_aNavPane[HH_TAB_CONTENTS]) ; // HACKHACK: Should use dynamic cast, but no RTTI.
|
||
|
}
|
||
|
//
|
||
|
// Check if zooming is supported on this page.
|
||
|
//
|
||
|
if ( IsValidWindow(hwndToolBar) )
|
||
|
{
|
||
|
if ( IsProperty(HHWIN_PROP_MENU) || fsToolBarFlags & HHWIN_BUTTON_ZOOM )
|
||
|
{
|
||
|
HRESULT hr = GetZoomMinMax();
|
||
|
if( fsToolBarFlags & HHWIN_BUTTON_ZOOM ) {
|
||
|
if ( hr == S_OK )
|
||
|
SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDTB_ZOOM, TRUE);
|
||
|
else
|
||
|
SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDTB_ZOOM, FALSE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (idNotify) {
|
||
|
HHN_NOTIFY hhcomp;
|
||
|
hhcomp.hdr.hwndFrom = hwndHelp;
|
||
|
hhcomp.hdr.idFrom = idNotify;
|
||
|
hhcomp.hdr.code = HHN_NAVCOMPLETE;
|
||
|
hhcomp.pszUrl = pszUrl;
|
||
|
if (IsWindow(hwndCaller))
|
||
|
{
|
||
|
SendMessage(hwndCaller, WM_NOTIFY, idNotify, (LPARAM) &hhcomp);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// NOTE - call the following in your OnNavigateComplete event handler to update the minmax. Do not do
|
||
|
// it when you navigate, do it when the control fires the OnNavigate event - by then you
|
||
|
// should be able to get the minmax stuff.
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// Member: CHHWinType:::GetZoomMinMax
|
||
|
//
|
||
|
// Synopsis: sets m_iZoomMin, and Most - gets called whenever we
|
||
|
// navigate to a document. Note that many document types
|
||
|
// do not support Zoom, and so this fails. This is OK,
|
||
|
// and expected.
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
HRESULT CHHWinType::GetZoomMinMax(void)
|
||
|
{
|
||
|
VARIANT vararg;
|
||
|
HRESULT hr;
|
||
|
|
||
|
::VariantInit(&vararg);
|
||
|
V_VT(&vararg) = VT_I4;
|
||
|
V_I4(&vararg) = 0;
|
||
|
|
||
|
m_iZoom = m_iZoomMin = m_iZoomMax = 0;
|
||
|
hr = m_pCIExpContainer->m_pIE3CmdTarget->Exec(0, OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
|
||
|
0, &vararg);
|
||
|
#if 0
|
||
|
if (hr)
|
||
|
{
|
||
|
OLECMDTEXT oct;
|
||
|
OLECMD olecmd;
|
||
|
olecmd.cmdID = OLECMDID_ZOOM;
|
||
|
olecmd.cmdf = 0;
|
||
|
hr = m_pCIExpContainer->m_pIE3CmdTarget->QueryStatus(NULL, 1, &olecmd, &oct);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (hr)
|
||
|
return hr;
|
||
|
|
||
|
if (VT_I4 == V_VT(&vararg))
|
||
|
m_iZoom = V_I4(&vararg);
|
||
|
|
||
|
::VariantClear(&vararg);
|
||
|
V_VT(&vararg) = VT_I4;
|
||
|
V_I4(&vararg) = 0;
|
||
|
|
||
|
hr = m_pCIExpContainer->m_pIE3CmdTarget->Exec(0, OLECMDID_GETZOOMRANGE, OLECMDEXECOPT_DONTPROMPTUSER,
|
||
|
0, &vararg);
|
||
|
if (hr)
|
||
|
return hr;
|
||
|
|
||
|
if (VT_I4 == V_VT(&vararg))
|
||
|
{
|
||
|
// I looked at the IE code for this - this cast is necessary.
|
||
|
m_iZoomMin = (INT)(SHORT)LOWORD(V_I4(&vararg));
|
||
|
m_iZoomMax = (INT)(SHORT)HIWORD(V_I4(&vararg));
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// Member: CHHWinType::ZoomIn
|
||
|
//
|
||
|
// Synopsis: Zooms in one - whenever we navigate to a new document,
|
||
|
// we get the zoom range for that document. ZoomIn will
|
||
|
// cycle thru that zoom range, from small to large, wrapping
|
||
|
// back to smallest again.
|
||
|
//
|
||
|
// Returns: nothing, fails quietly (by design).
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
void CHHWinType::ZoomIn(void)
|
||
|
{
|
||
|
INT iZoomNew = m_iZoom + 1;
|
||
|
|
||
|
if (iZoomNew > m_iZoomMax)
|
||
|
iZoomNew = m_iZoomMin;
|
||
|
|
||
|
Zoom(iZoomNew);
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// Member: CHHWinType::ZoomOut
|
||
|
//
|
||
|
// Synopsis: Zooms out one - whenever we navigate to a new document,
|
||
|
// we get the zoom range for that document. ZoomOut will
|
||
|
// cycle thru that zoom range, from large to small, wrapping
|
||
|
// back to largest again.
|
||
|
//
|
||
|
// Returns: nothing, fails quietly (by design).
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
void CHHWinType::ZoomOut(void)
|
||
|
{
|
||
|
INT iZoomNew = m_iZoom - 1;
|
||
|
|
||
|
if (iZoomNew < m_iZoomMin)
|
||
|
iZoomNew = m_iZoomMax;
|
||
|
|
||
|
Zoom(iZoomNew);
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// Member: CHHWinType::_Zoom
|
||
|
//
|
||
|
// Synopsis: helper function that manages zoomin and zoomout.
|
||
|
//
|
||
|
// Arguments: [iZoom] -- value for new zoom.
|
||
|
//
|
||
|
// Requires: iZoom needs to be in a valid range for the current docobj.
|
||
|
// current docobj must support IOleCommandTarget
|
||
|
// it will fail if current docobj doesn't respond to
|
||
|
// OLECMDID_ZOOM.
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
HRESULT CHHWinType::Zoom(int iZoom)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
VARIANTARG varIn;
|
||
|
VARIANTARG varOut;
|
||
|
|
||
|
// initialize the argument to Exec.
|
||
|
::VariantInit(&varIn);
|
||
|
V_VT(&varIn) = VT_I4;
|
||
|
V_I4(&varIn) = iZoom;
|
||
|
|
||
|
// init the out variant. This probably isn't necessary, but
|
||
|
// doesn't hurt - it's defensive as opposed to passing 0.
|
||
|
//
|
||
|
::VariantInit(&varOut);
|
||
|
hr = m_pCIExpContainer->m_pIE3CmdTarget->Exec(0, OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
|
||
|
&varIn, &varOut);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
m_iZoom = iZoom;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// Member: CHHWinType::OnNext
|
||
|
//
|
||
|
// Synopsis: Executes a next in TOC navigation.
|
||
|
//
|
||
|
// Arguments: bDoJump - BOOL value indicates weather to execute a jump or not.
|
||
|
//
|
||
|
// Returns: BOOL - TRUE on success, FALSE on failure.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
BOOL CHHWinType::OnTocNext(BOOL bDoJump)
|
||
|
{
|
||
|
CExTitle *pTitle= NULL;
|
||
|
CStr cszUrl;
|
||
|
char szURL[MAX_URL];
|
||
|
CTreeNode* pTreeNode = NULL, *pTocNext = NULL, *pTocKid = NULL;
|
||
|
CToc* pToc = NULL;
|
||
|
DWORD dwSlot;
|
||
|
BOOL bReturn = FALSE;
|
||
|
|
||
|
if ( !m_phmData || !m_phmData->m_pTitleCollection )
|
||
|
return FALSE;
|
||
|
|
||
|
if (! SUCCEEDED(m_phmData->m_pTitleCollection->GetCurrentTocNode(&pTreeNode)) )
|
||
|
{
|
||
|
m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
|
||
|
if (cszUrl.psz != NULL)
|
||
|
{
|
||
|
strcpy(szURL, cszUrl);
|
||
|
if ( SUCCEEDED(m_phmData->m_pTitleCollection->URL2ExTitle(szURL, &pTitle)) )
|
||
|
pTitle->GetURLTreeNode(szURL, &pTreeNode);
|
||
|
}
|
||
|
}
|
||
|
if ( pTreeNode )
|
||
|
{
|
||
|
if ( pTocNext = m_phmData->m_pTitleCollection->GetNextTopicNode(pTreeNode, &dwSlot) )
|
||
|
{
|
||
|
// Ok now we can execute the jump and sync!
|
||
|
//
|
||
|
if ( bDoJump )
|
||
|
{
|
||
|
pTocNext->GetURL(szURL, sizeof(szURL));
|
||
|
m_phmData->m_pTitleCollection->URL2ExTitle(szURL, &pTitle);
|
||
|
m_phmData->m_pTitleCollection->SetTopicSlot(dwSlot, ((CExNode*)pTocNext)->m_Node.dwOffsTopic, pTitle);
|
||
|
ChangeHtmlTopic(szURL, *this);
|
||
|
if (! IsProperty(HHWIN_PROP_AUTO_SYNC) && (pToc = (CToc*)m_aNavPane[HH_TAB_CONTENTS]) )
|
||
|
pToc->Synchronize(szURL);
|
||
|
}
|
||
|
delete pTocNext;
|
||
|
bReturn = TRUE;
|
||
|
}
|
||
|
delete pTreeNode;
|
||
|
}
|
||
|
return bReturn;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// Member: CHHWinType::OnPrev
|
||
|
//
|
||
|
// Synopsis: Executes a previous in TOC navigation.
|
||
|
//
|
||
|
// Arguments: bDoJump - BOOL value indicates weather to execute a jump or not.
|
||
|
//
|
||
|
// Returns: BOOL - TRUE on success, FALSE on failure.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
BOOL CHHWinType::OnTocPrev(BOOL bDoJump)
|
||
|
{
|
||
|
CExTitle *pTitle = NULL;
|
||
|
CStr cszUrl;
|
||
|
char szURL[MAX_URL];
|
||
|
CTreeNode* pTreeNode = NULL, *pTocPrev = NULL;
|
||
|
CToc* pToc = NULL;
|
||
|
DWORD dwSlot;
|
||
|
BOOL bReturn = FALSE;
|
||
|
|
||
|
if ( !m_phmData || !m_phmData->m_pTitleCollection )
|
||
|
return FALSE;
|
||
|
|
||
|
if (! SUCCEEDED(m_phmData->m_pTitleCollection->GetCurrentTocNode(&pTreeNode)) )
|
||
|
{
|
||
|
m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
|
||
|
if (cszUrl.psz != NULL)
|
||
|
{
|
||
|
strcpy(szURL, cszUrl);
|
||
|
if ( SUCCEEDED(m_phmData->m_pTitleCollection->URL2ExTitle(szURL, &pTitle)) )
|
||
|
pTitle->GetURLTreeNode(szURL, &pTreeNode);
|
||
|
}
|
||
|
}
|
||
|
if ( pTreeNode )
|
||
|
{
|
||
|
// We have the TOC node, now get it's next.
|
||
|
//
|
||
|
if ( pTocPrev = m_phmData->m_pTitleCollection->GetPrev(pTreeNode, &dwSlot) )
|
||
|
{
|
||
|
//
|
||
|
// Ok now, we can execute the jump and sync!
|
||
|
//
|
||
|
if ( bDoJump )
|
||
|
{
|
||
|
pTocPrev->GetURL(szURL, sizeof(szURL));
|
||
|
m_phmData->m_pTitleCollection->URL2ExTitle(szURL, &pTitle);
|
||
|
m_phmData->m_pTitleCollection->SetTopicSlot(dwSlot, ((CExNode*)pTocPrev)->m_Node.dwOffsTopic, pTitle);
|
||
|
ChangeHtmlTopic(szURL, *this);
|
||
|
if (! IsProperty(HHWIN_PROP_AUTO_SYNC) && (pToc = (CToc*)m_aNavPane[HH_TAB_CONTENTS]) )
|
||
|
pToc->Synchronize(szURL);
|
||
|
}
|
||
|
bReturn = TRUE;
|
||
|
delete pTocPrev;
|
||
|
}
|
||
|
delete pTreeNode;
|
||
|
}
|
||
|
return bReturn;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
FUNCTION: FindWindowType
|
||
|
|
||
|
PURPOSE: Find whether the window type exists and has already created
|
||
|
a window
|
||
|
|
||
|
PARAMETERS:
|
||
|
pszType -- window type to look for.
|
||
|
hwndCaller -- who the caller is
|
||
|
pszOwnerFile -- CHM file which defines this window type.
|
||
|
|
||
|
RETURNS:
|
||
|
-1 if window type not found, or found but no window created
|
||
|
position in pahwnd if window found
|
||
|
|
||
|
COMMENTS:
|
||
|
|
||
|
MODIFICATION DATES:
|
||
|
27-Feb-1996 [ralphw]
|
||
|
27-Apr-1998 [dalero] Added pszOwnerFile parameter
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
CHHWinType* FindWindowType(PCSTR pszType, HWND hwndCaller, LPCTSTR pszOwnerFile)
|
||
|
{
|
||
|
if (IsEmptyString(pszType))
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// Skip window separator if present.
|
||
|
if (*pszType == WINDOW_SEPARATOR)
|
||
|
{
|
||
|
pszType++;
|
||
|
if (IsEmptyString(pszType))
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// We ignore the owner file if the file is URL or the window type is global.
|
||
|
bool bIgnoreOwnerFile = IsGlobalWinType(pszType) || IsHttp(pszOwnerFile) ;
|
||
|
if (!bIgnoreOwnerFile )
|
||
|
{
|
||
|
// If its not global, we need a filename.
|
||
|
if (IsEmptyString(pszOwnerFile))
|
||
|
{
|
||
|
return NULL ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < g_cWindowSlots; i++)
|
||
|
{
|
||
|
if (pahwnd[i] && pahwnd[i]->pszType != NULL
|
||
|
&& lstrcmpi(pszType, pahwnd[i]->pszType) == 0)
|
||
|
{
|
||
|
// Found the window type.
|
||
|
|
||
|
// If its a global window type, we are done.
|
||
|
if (bIgnoreOwnerFile)
|
||
|
{
|
||
|
break ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Call IsCompiledHtmlFile to get the filename into a consistant format.
|
||
|
CStr cszCompiled(pszOwnerFile);
|
||
|
if (NormalizeFileName(cszCompiled))
|
||
|
{
|
||
|
// Is this window type in the correct CHM file.
|
||
|
ASSERT(pahwnd[i]->GetOwnerFile());
|
||
|
if (pahwnd[i]->GetOwnerFile()
|
||
|
&& lstrcmpi(cszCompiled, pahwnd[i]->GetOwnerFile()) == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (i >= g_cWindowSlots)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//REVIEW: 28-Apr-98 [dalero] This seems dangerous...
|
||
|
if (hwndCaller)
|
||
|
{
|
||
|
pahwnd[i]->hwndCaller = hwndCaller; // In case it changed
|
||
|
}
|
||
|
return pahwnd[i];
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
FUNCTION: FindOrCreateWindowSlot
|
||
|
|
||
|
PURPOSE: Find whether the window type exists and create it if not.
|
||
|
|
||
|
PARAMETERS:
|
||
|
pszType -- window type to look for.
|
||
|
hwndCaller -- who the caller is
|
||
|
pszOwnerFile -- the file which defines this window type.
|
||
|
|
||
|
if pszType has the GLOBAL_WINDOWTYPE_PREFIX, the pszOwnerFile is not used.
|
||
|
|
||
|
RETURNS:
|
||
|
Return a pointer to the window type. May be an empty one just created.
|
||
|
|
||
|
COMMENTS:
|
||
|
|
||
|
MODIFICATION DATES:
|
||
|
27 Apr 98 [DaleRo] Added pszOwnerFile parameter
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
CHHWinType* FindOrCreateWindowSlot(LPCTSTR pszType, LPCTSTR pszOwnerFile)
|
||
|
{
|
||
|
ASSERT(pahwnd != NULL) ;
|
||
|
|
||
|
// pszType cannot be NULL or emptry.
|
||
|
if (IsEmptyString(pszType))
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// Skip window type pointer if present.
|
||
|
if (*pszType == WINDOW_SEPARATOR)
|
||
|
{
|
||
|
pszType++;
|
||
|
if (IsEmptyString(pszType))
|
||
|
{
|
||
|
return NULL ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// We ignore the owning file if...
|
||
|
bool bIgnoreOwnerFile = IsGlobalWinType(pszType) // Its a global window type
|
||
|
|| IsHttp(pszOwnerFile); // or an Http address. Ideally, the window type has been registered to a particular chm...
|
||
|
const char* pOwner = ""; // Empty string is stored in the cases where we ignore wintypes... CHHWinType will copy...
|
||
|
CStr cszOwner(pszOwnerFile);
|
||
|
if (!bIgnoreOwnerFile)
|
||
|
{
|
||
|
// If its not a global window type, it must have a valid file.
|
||
|
if (!NormalizeFileName(cszOwner))
|
||
|
{
|
||
|
return NULL ;
|
||
|
}
|
||
|
|
||
|
// pOwner is NULL if its a global wintype. Its non-null otherwise.
|
||
|
pOwner = cszOwner;
|
||
|
}
|
||
|
|
||
|
// Check to see if this window type already exists.
|
||
|
CHHWinType* phh = FindWindowType(pszType, NULL, cszOwner);
|
||
|
if (phh)
|
||
|
{
|
||
|
return phh;
|
||
|
}
|
||
|
|
||
|
// The window type did not exist. So, find an empty slot to put it in.
|
||
|
for (int i = 0; i < g_cWindowSlots; i++)
|
||
|
{
|
||
|
if (pahwnd[i] == NULL)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Allocate more space for the array if we are out of room.
|
||
|
if (i >= g_cWindowSlots)
|
||
|
{
|
||
|
g_cWindowSlots += 5;
|
||
|
|
||
|
CHHWinType** paNew = (CHHWinType**) lcReAlloc(pahwnd,
|
||
|
g_cWindowSlots * sizeof(CHHWinType*));
|
||
|
memset( paNew + (g_cWindowSlots-5), 0, 5 * sizeof(CHHWinType*) );
|
||
|
if (paNew == NULL)
|
||
|
{
|
||
|
OOM();
|
||
|
return FALSE;
|
||
|
}
|
||
|
pahwnd = paNew;
|
||
|
}
|
||
|
|
||
|
// Create the new window type object. Note that it is not initialized.
|
||
|
pahwnd[i] = new CHHWinType(pOwner);
|
||
|
return pahwnd[i];
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
FUNCTION: FindCurWindow
|
||
|
|
||
|
PURPOSE: Find a current window displayed
|
||
|
|
||
|
PARAMETERS:
|
||
|
|
||
|
RETURNS:
|
||
|
|
||
|
COMMENTS:
|
||
|
|
||
|
This function is random. It picks the first window displayed.
|
||
|
Depending on how HHCTRL has been called any window could be first.
|
||
|
|
||
|
MODIFICATION DATES:
|
||
|
09-Nov-1997 [ralphw]
|
||
|
03-Mar-1998 [dalero]
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
CHHWinType* FindCurWindow()
|
||
|
{
|
||
|
ASSERT(pahwnd != NULL) ;
|
||
|
|
||
|
for (int i = 0; i < g_cWindowSlots; i++)
|
||
|
{
|
||
|
if (pahwnd[i] != NULL)
|
||
|
{
|
||
|
return pahwnd[i];
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Delete all of the CHHWinType structures for this process.
|
||
|
//
|
||
|
void DeleteWindows()
|
||
|
{
|
||
|
ASSERT(pahwnd != NULL) ;
|
||
|
|
||
|
for (int i = 0; i < g_cWindowSlots; i++)
|
||
|
{
|
||
|
if (pahwnd[i] != NULL)
|
||
|
{
|
||
|
CHHWinType* phh = pahwnd[i] ;
|
||
|
//pahwnd[i] = NULL ; --- Set to null in the destructor...
|
||
|
if (IsWindow(phh->hwndHelp))
|
||
|
{
|
||
|
DestroyWindow(phh->hwndHelp) ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
delete phh ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Functions which operate on the m_aNavPane array.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CreateNavPane
|
||
|
//
|
||
|
|
||
|
static const WCHAR txtAuthorTab[] = L"HHAuthorTab.CustPane";
|
||
|
|
||
|
void
|
||
|
CHHWinType::CreateNavPane(int iPane)
|
||
|
{
|
||
|
|
||
|
// Is this a valid pane number?
|
||
|
if (iPane > c_NUMNAVPANES || iPane < 0)
|
||
|
{
|
||
|
ASSERT(0) ;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
// Has pane already been created?
|
||
|
if (m_aNavPane[iPane])
|
||
|
{
|
||
|
return ; // Already created.
|
||
|
}
|
||
|
|
||
|
// Create the pane.
|
||
|
switch(iPane)
|
||
|
{
|
||
|
case HHWIN_NAVTYPE_TOC:
|
||
|
CreateToc();
|
||
|
break ;
|
||
|
case HHWIN_NAVTYPE_INDEX:
|
||
|
CreateIndex();
|
||
|
break ;
|
||
|
case HHWIN_NAVTYPE_SEARCH:
|
||
|
CreateSearchTab();
|
||
|
break;
|
||
|
case HHWIN_NAVTYPE_FAVORITES:
|
||
|
CreateBookmarksTab() ;
|
||
|
break ;
|
||
|
|
||
|
#if 0
|
||
|
case HHWIN_NAVTYPE_HISTORY:
|
||
|
//CreateHistoryTab();
|
||
|
ItDoesntWork() ;
|
||
|
break ;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#ifdef __TEST_CUSTOMTAB__
|
||
|
case HHWIN_NAVTYPE_AUTHOR:
|
||
|
CreateCustomTab(iPane, txtAuthorTab);
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
default:
|
||
|
if (iPane < HH_MAX_TABS+1 && iPane >= HHWIN_NAVTYPE_CUSTOM_FIRST)
|
||
|
{
|
||
|
// We have a custom tab.
|
||
|
EXTENSIBLE_TAB* pExtTab = GetExtTab(iPane - HH_TAB_CUSTOM_FIRST);
|
||
|
if (pExtTab)
|
||
|
{
|
||
|
CWStr cwsz(pExtTab->pszProgId);
|
||
|
CreateCustomTab(iPane, cwsz);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT_COMMENT(0, "illegal tab index");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
FUNCTION: doSelectTab
|
||
|
|
||
|
PURPOSE: changes the current navigation tab
|
||
|
|
||
|
PARAMETERS:
|
||
|
|
||
|
RETURNS:
|
||
|
TODO
|
||
|
|
||
|
|
||
|
COMMENTS:
|
||
|
|
||
|
MODIFICATION DATES:
|
||
|
27-Feb-1996 [ralphw]
|
||
|
09-Nov-1997 [ralphw] Moved to CHHWinType
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
void
|
||
|
CHHWinType::doSelectTab(int newTabIndex)
|
||
|
{
|
||
|
if ( newTabIndex < 0 )
|
||
|
return ;
|
||
|
|
||
|
// Make sure we have tabs before we switch or toggle.
|
||
|
if (!IsValidNavPane(curNavType))
|
||
|
return ;
|
||
|
|
||
|
// make sure the nav pane is shown
|
||
|
if (IsExpandedNavPane() == FALSE)
|
||
|
ToggleExpansion();
|
||
|
//
|
||
|
// <mc> 4/10/98 Bug 4701 - I've moved the m_pTabCtrl == NULL check to after the ToggleExpansion() call
|
||
|
// done above because it's legitimate to have a NULL m_pTabCtrl pointer if we get to this code and the
|
||
|
// nav pane has never been shown. The ToggleExpansion() call will instantiate m_pTabCtrl if the nav
|
||
|
// pane is hidden and has never been shown.
|
||
|
//
|
||
|
if ( m_pTabCtrl == NULL )
|
||
|
return; // REVIEW: This is null when there isn't an FTS. See BUG 462 in RAID database.
|
||
|
|
||
|
// Get the index of the currently selected tab.
|
||
|
int oldTabIndex = GetCurrentNavPaneIndex() ;
|
||
|
|
||
|
// Only change the tab if its not the current one.
|
||
|
if (oldTabIndex != newTabIndex)
|
||
|
{
|
||
|
// This code was copied from WM_NOTIFY in wndproc.cpp. This should become common.
|
||
|
|
||
|
ASSERT(curNavType >= 0 && curNavType < c_NUMNAVPANES) ;
|
||
|
|
||
|
// Hide the current tab.
|
||
|
if (m_aNavPane[curNavType])
|
||
|
{
|
||
|
m_aNavPane[curNavType]->HideWindow();
|
||
|
}
|
||
|
|
||
|
// Code throughout HHCtrl assumes that HH_NAVTYPE_* == HH_TAB_*.
|
||
|
// but doesn't assert it anywhere. So I'm going to assert it here.
|
||
|
ASSERT(HHWIN_NAVTYPE_SEARCH == HH_TAB_SEARCH) ;
|
||
|
ASSERT(HHWIN_NAVTYPE_TOC == HH_TAB_CONTENTS) ;
|
||
|
ASSERT(HHWIN_NAVTYPE_INDEX == HH_TAB_INDEX);
|
||
|
ASSERT(HHWIN_NAVTYPE_FAVORITES == HH_TAB_FAVORITES);
|
||
|
#ifdef _INTERNAL
|
||
|
ASSERT(HHWIN_NAVTYPE_HISTORY == HH_TAB_HISTORY);
|
||
|
#endif
|
||
|
|
||
|
// Select the new navigation method.
|
||
|
curNavType = newTabIndex;
|
||
|
|
||
|
// Select the new current tab.
|
||
|
int iNewTabCtrlIndex = GetTabIndexFromNavPaneIndex(newTabIndex) ;
|
||
|
ASSERT(iNewTabCtrlIndex >= 0) ;
|
||
|
int iRet = TabCtrl_SetCurSel(m_pTabCtrl->hWnd(), iNewTabCtrlIndex) ;
|
||
|
ASSERT(iRet >= 0) ;
|
||
|
ASSERT(tabOrder[iRet] == oldTabIndex) ;
|
||
|
|
||
|
//REVIEW: If I've ever seen a use for virtual functions...
|
||
|
|
||
|
// Create the new pane for the new current tab if necessary.
|
||
|
CreateNavPane(newTabIndex) ;
|
||
|
if (m_aNavPane[newTabIndex])
|
||
|
{
|
||
|
m_aNavPane[newTabIndex]->ResizeWindow();
|
||
|
m_aNavPane[newTabIndex]->ShowWindow();
|
||
|
}
|
||
|
|
||
|
// Update the tab window
|
||
|
::UpdateWindow(m_pTabCtrl->hWnd()) ;
|
||
|
} //if
|
||
|
if (m_aNavPane[newTabIndex]) m_aNavPane[newTabIndex]->SetDefaultFocus();
|
||
|
if ( m_pCIExpContainer )
|
||
|
m_pCIExpContainer->UIDeactivateIE(); // shdocvw is loosing focus need to uideactivate here.
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Restore if minimzied window, and set focus to the window
|
||
|
//
|
||
|
void CHHWinType::SetActiveHelpWindow(void)
|
||
|
{
|
||
|
if (IsIconic(*this))
|
||
|
ShowWindow(*this, SW_RESTORE);
|
||
|
SetForegroundWindow(*this);
|
||
|
// SetFocus(*this);
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Finds the currently selected tab in the tab control. It then looks in the
|
||
|
// tabOrder array to find out the index into the array of nav panes for this control.
|
||
|
//
|
||
|
int
|
||
|
CHHWinType::GetCurrentNavPaneIndex()
|
||
|
{
|
||
|
if( !m_pTabCtrl )
|
||
|
return -1;
|
||
|
|
||
|
// REVIEW: All of this mapping between tabctrl index and nav pane index should be
|
||
|
// hidden inside of the tabctrl...
|
||
|
int index = -1 ;
|
||
|
if (m_pTabCtrl && IsWindow(m_pTabCtrl->hWnd()))
|
||
|
{
|
||
|
index = (int)::SendMessage(m_pTabCtrl->hWnd(), TCM_GETCURSEL, 0, 0);
|
||
|
index = tabOrder[index] ;
|
||
|
}
|
||
|
|
||
|
return index ;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Finds the index of the tab on the tabctrl which co-responds to a particular
|
||
|
// nav pane.
|
||
|
//
|
||
|
int
|
||
|
CHHWinType::GetTabIndexFromNavPaneIndex(int iNavPaneIndex)
|
||
|
{
|
||
|
for(int i = 0 ; i < HH_MAX_TABS+1 ; i++)
|
||
|
{
|
||
|
//REVIEW: Not all of these entries are valid. Possible to get a bogus hit. See reorder tab.
|
||
|
if( tabOrder[i] == iNavPaneIndex)
|
||
|
{
|
||
|
return i ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1 ;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Translate the accelerators for the tabs. These are not in the global accelerator table.
|
||
|
//
|
||
|
bool
|
||
|
CHHWinType::ManualTranslateAccelerator(char iChar)
|
||
|
{
|
||
|
CHAR ch = ToLower(iChar) ;
|
||
|
|
||
|
// The Options menu button.
|
||
|
if (ch == _Resource.TabCtrlKeys(ACCEL_KEY_OPTIONS)
|
||
|
&& GetToolBarHwnd())
|
||
|
{
|
||
|
PostMessage( GetHwnd(), WM_COMMAND, IDTB_OPTIONS, 0);
|
||
|
return true;
|
||
|
}
|
||
|
/*
|
||
|
else if()
|
||
|
// When adding in new cases, make sure not to eat a key. If you UI doesn't exist.
|
||
|
// Let someone else have the key.
|
||
|
*/
|
||
|
else
|
||
|
{
|
||
|
// Handle the tab accelerator keys
|
||
|
for (int i= 0 ; i < HH_MAX_TABS+1 ; i++)
|
||
|
{
|
||
|
if (ch == _Resource.TabCtrlKeys(i) && IsValidNavPane(i))
|
||
|
{
|
||
|
doSelectTab(i) ;
|
||
|
return true ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Handle the nav panes accelerator keys
|
||
|
if (m_aNavPane[curNavType])
|
||
|
{
|
||
|
if (m_aNavPane[curNavType]->ProcessMenuChar(GetHwnd(),ch) )
|
||
|
{
|
||
|
if ( m_pCIExpContainer )
|
||
|
m_pCIExpContainer->UIDeactivateIE(); // shdocvw is loosing focus need to uideactivate here.
|
||
|
return true ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return false ;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Dynamically build an accelerator table for this window...
|
||
|
//
|
||
|
bool
|
||
|
CHHWinType::DynamicTranslateAccelerator(MSG* pMsg)
|
||
|
{
|
||
|
bool bReturn = false ;
|
||
|
if (IsWindow(GetHwnd()))
|
||
|
{
|
||
|
if (!m_hAccel)
|
||
|
{
|
||
|
|
||
|
// Get the static accelerators table;
|
||
|
HACCEL hAccelStatic = _Resource.AcceleratorTable() ;
|
||
|
// Get number of accelerator table entries.
|
||
|
int cStaticAccelEntries = CopyAcceleratorTable(hAccelStatic, NULL, 0);
|
||
|
|
||
|
// Add on the options menu and the tabs...
|
||
|
int cAccelEntries = cStaticAccelEntries + HH_MAX_TABS + 2 ;
|
||
|
|
||
|
// Allocate structure to hold accelerator table.
|
||
|
ACCEL* accel = new ACCEL[cAccelEntries] ;
|
||
|
if (!accel)
|
||
|
return false ;
|
||
|
|
||
|
// Copy the table into the structure:
|
||
|
CopyAcceleratorTable(hAccelStatic, accel, cStaticAccelEntries ) ;
|
||
|
|
||
|
// Add on dynamic accelerators.
|
||
|
int index = cStaticAccelEntries;
|
||
|
|
||
|
// Add on options menu.
|
||
|
if (fsToolBarFlags & HHWIN_BUTTON_OPTIONS)
|
||
|
{
|
||
|
accel[index].fVirt = FALT | FNOINVERT | FVIRTKEY ;
|
||
|
accel[index].key = (WORD)ToUpper(_Resource.TabCtrlKeys(ACCEL_KEY_OPTIONS)) ;
|
||
|
accel[index].cmd = IDTB_OPTIONS ;
|
||
|
index++ ;
|
||
|
}
|
||
|
|
||
|
// Add on accelerators for each tab.
|
||
|
for (int i= 0 ; i < HH_MAX_TABS+1 ; i++)
|
||
|
{
|
||
|
if (IsValidNavPane(i))
|
||
|
{
|
||
|
accel[index].fVirt = FALT | FNOINVERT | FVIRTKEY;
|
||
|
accel[index].key = (WORD)ToUpper(_Resource.TabCtrlKeys(i)) ;
|
||
|
accel[index].cmd = IDC_SELECT_TAB_FIRST + i ;
|
||
|
index++ ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create the accelerator table.
|
||
|
m_hAccel = CreateAcceleratorTable(accel, index) ;
|
||
|
|
||
|
|
||
|
// Cleanup
|
||
|
delete [] accel ;
|
||
|
}
|
||
|
|
||
|
bReturn = (TranslateAccelerator(GetHwnd(), m_hAccel, pMsg) != 0 ) ;
|
||
|
|
||
|
}
|
||
|
if (bReturn)
|
||
|
{
|
||
|
DBWIN("--- Translated Accelerator ---") ;
|
||
|
}
|
||
|
return bReturn ;
|
||
|
}
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Stolen from System.cpp...readsystemfiles. Should be shared.
|
||
|
//
|
||
|
LPSTR _MakeItFullPath(LPCTSTR name, CHmData* phmData)
|
||
|
{
|
||
|
LPSTR pszReturn = NULL ;
|
||
|
CStr csz(name) ;
|
||
|
if (csz.IsNonEmpty())
|
||
|
{
|
||
|
if (!stristr(csz, txtDoubleColonSep) &&
|
||
|
!stristr(csz, txtFileHeader) && !stristr(csz, txtHttpHeader))
|
||
|
{
|
||
|
CStr cszCompiledFile ;
|
||
|
cszCompiledFile = phmData->GetCompiledFile();
|
||
|
cszCompiledFile += txtSepBack;
|
||
|
cszCompiledFile += csz.psz;
|
||
|
|
||
|
//Transfer pointer.
|
||
|
pszReturn = cszCompiledFile.psz ;
|
||
|
cszCompiledFile.psz = NULL ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Transfer pointer.
|
||
|
pszReturn = csz.psz ;
|
||
|
csz.psz = NULL ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pszReturn ;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Kills all of the nav panes and then re-fills them with the new CHM data.
|
||
|
//
|
||
|
bool
|
||
|
CHHWinType::ReloadNavData(CHmData* phmdata)
|
||
|
{
|
||
|
if (!phmdata)
|
||
|
return false;
|
||
|
|
||
|
//--- Do we have valid data?
|
||
|
char* pszTocNew = NULL ;
|
||
|
char* pszIndexNew = NULL ;
|
||
|
|
||
|
// Only if we currently have a TOC, will we get the new toc.
|
||
|
if (IsNonEmptyString(pszToc))
|
||
|
{
|
||
|
pszTocNew = _MakeItFullPath(phmdata->GetDefaultToc(), phmdata) ;
|
||
|
}
|
||
|
|
||
|
// Only if we currently have an INDEX, will we get the new index.
|
||
|
if (IsNonEmptyString(pszIndex))
|
||
|
{
|
||
|
pszIndexNew = _MakeItFullPath(phmdata->GetDefaultIndex(), phmdata) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
// CHM doesn't have a default TOC or CHM which we need. So look up one in the default window type.
|
||
|
if ((IsNonEmptyString(pszToc) && IsEmptyString(pszTocNew)) ||
|
||
|
(IsNonEmptyString(pszIndex) && IsEmptyString(pszIndexNew)))
|
||
|
{
|
||
|
CHECK_AND_FREE(pszTocNew) ;
|
||
|
CHECK_AND_FREE(pszIndexNew) ;
|
||
|
|
||
|
// Office Beta work around: Less attempt looking in the default window type.
|
||
|
if (IsNonEmptyString(phmdata->GetDefaultWindow()))
|
||
|
{
|
||
|
CHHWinType* pDefWinTypeNew = FindWindowType(phmdata->GetDefaultWindow(), NULL, phmdata->GetCompiledFile()) ;
|
||
|
if (pDefWinTypeNew)
|
||
|
{
|
||
|
if (IsNonEmptyString(pszToc))
|
||
|
{
|
||
|
pszTocNew = _MakeItFullPath(pDefWinTypeNew->pszToc, phmdata) ;
|
||
|
}
|
||
|
|
||
|
if (IsNonEmptyString(pszIndex))
|
||
|
{
|
||
|
pszIndexNew = _MakeItFullPath(pDefWinTypeNew->pszIndex, phmdata) ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If we still aren't in sync, fail.
|
||
|
if ((IsNonEmptyString(pszToc) && IsEmptyString(pszTocNew)) ||
|
||
|
(IsNonEmptyString(pszIndex) && IsEmptyString(pszIndexNew)))
|
||
|
{
|
||
|
CHECK_AND_FREE(pszTocNew) ;
|
||
|
CHECK_AND_FREE(pszIndexNew) ;
|
||
|
|
||
|
return false ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//--- Kill all nav panes and cleanup other infomation
|
||
|
ReloadCleanup() ;
|
||
|
|
||
|
//--- Clean up some more stuff...
|
||
|
|
||
|
//--- Start re-initializing...
|
||
|
m_phmData = phmdata;
|
||
|
pszToc = pszTocNew ;
|
||
|
pszIndex = pszIndexNew ;
|
||
|
pszFile = lcStrDup(phmdata->GetDefaultHtml()); //_MakeItFullPath(phmdata->m_pszDefHtml, phmdata);
|
||
|
|
||
|
//TODO: I think we need to get a window name to read from....ick
|
||
|
pszJump1 = NULL;
|
||
|
pszJump2 = NULL;
|
||
|
pszUrlJump1 = NULL;
|
||
|
pszUrlJump2 = NULL;
|
||
|
|
||
|
|
||
|
//--- Okay, lets start up the first current tab...
|
||
|
if (IsExpandedNavPane())
|
||
|
{
|
||
|
// We have a naviation pane which we need to re-create.
|
||
|
fNotExpanded = TRUE ; // Force a re-creation.
|
||
|
ToggleExpansion(false) ;
|
||
|
}
|
||
|
|
||
|
return true ;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Restores the focus to the ctrl which had it focus during the last WM_ACTIVATE.
|
||
|
//
|
||
|
bool
|
||
|
CHHWinType::RestoreCtrlWithFocus()
|
||
|
{
|
||
|
if (m_hwndLastFocus)
|
||
|
{
|
||
|
SetFocus(m_hwndLastFocus) ;
|
||
|
m_hwndLastFocus = NULL ;
|
||
|
return true ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Saves hwnd of ctrl with focus during WM_ACTVIATE (INACTIVATE).
|
||
|
//
|
||
|
void
|
||
|
CHHWinType::SaveCtrlWithFocus()
|
||
|
{
|
||
|
m_hwndLastFocus = GetFocus() ;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// GetExtTabCount
|
||
|
//
|
||
|
int
|
||
|
CHHWinType::GetExtTabCount()
|
||
|
{
|
||
|
// If we have an original, pre-reload navdata ChmData. Use that to get the custom tab information.
|
||
|
if (m_phmDataOrg)
|
||
|
return m_phmDataOrg->GetExtTabCount();
|
||
|
else if (m_phmData)
|
||
|
return m_phmData->GetExtTabCount(); // Review: Will this ever happen?
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// GetExtTab
|
||
|
//
|
||
|
EXTENSIBLE_TAB*
|
||
|
CHHWinType::GetExtTab(int pos)
|
||
|
{
|
||
|
if (m_phmDataOrg)
|
||
|
return m_phmDataOrg->GetExtTab(pos);
|
||
|
else if (m_phmData)
|
||
|
return m_phmData->GetExtTab(pos); // Review:: will this ever happen?
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// MUI support
|
||
|
//
|
||
|
// This InsertMenuItem wrapper will translate the MENUITEMINFOA structure
|
||
|
// to a MENUITEMINFOW and call InsertMenuItemW when running under Windows 2000.
|
||
|
//
|
||
|
BOOL HxInsertMenuItem(HMENU hMenu, UINT uItem, BOOL fByPosition, MENUITEMINFOA *lpmii)
|
||
|
{
|
||
|
if(g_bWinNT5 && (lpmii->fMask | MIIM_TYPE) && lpmii->fType == MFT_STRING)
|
||
|
{
|
||
|
|
||
|
DWORD cp = CodePageFromLCID(MAKELCID(_Module.m_Language.GetUiLanguage(),SORT_DEFAULT));
|
||
|
|
||
|
DWORD dwSize = (sizeof(WCHAR) * lpmii->cch) + 4;
|
||
|
WCHAR *pwcString = (WCHAR *) lcMalloc(dwSize);
|
||
|
|
||
|
if(!pwcString || !(lpmii->cch))
|
||
|
return FALSE;
|
||
|
|
||
|
MultiByteToWideChar(cp, MB_PRECOMPOSED, lpmii->dwTypeData, -1, pwcString, dwSize);
|
||
|
|
||
|
lpmii->dwTypeData = (CHAR *) pwcString;
|
||
|
lpmii->cch = wcslen((WCHAR *)lpmii->dwTypeData);
|
||
|
|
||
|
BOOL ret = InsertMenuItemW(hMenu, uItem, fByPosition, (LPMENUITEMINFOW) lpmii);
|
||
|
|
||
|
lcFree(pwcString);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return InsertMenuItem(hMenu, uItem, fByPosition, lpmii);
|
||
|
}
|
||
|
}
|