2882 lines
98 KiB
C
2882 lines
98 KiB
C
#ifdef HEADER
|
||
/******************************************************************************\
|
||
* Copyright: (c) Microsoft Corporation - 1993 - All Rights Reserved
|
||
********************************************************************************
|
||
*
|
||
* Filename: HDXDLL.C
|
||
* Purpose: Help Index Outline Custom Control
|
||
*
|
||
* Notes: The dialog editor interface has changed since Win 3.0.
|
||
* Examine NT CUSTCNTL.H to get an idea of the new interface.
|
||
*
|
||
* History:
|
||
* Date by description
|
||
* ---- -- -----------
|
||
* 11/08/93 chauv added GetRegistryString() - this should be identical to
|
||
* the same function in contents.c
|
||
* 10/20/93 chauv added CallHelp() to support Viewer/WinHelp switching.
|
||
* This functionality is only for 16-bit platform.
|
||
* 32-bit platform will be supported when Viewer is 32-bit.
|
||
* 10/18/93 chauv added ExpandUptoLevel()
|
||
* 10/13/93 chauv used HDXFILEINFO to fix *.hdx data size bug
|
||
* 10/06/93 chauv added tchar.h and DBC-enable code
|
||
* 04/25/93 v-tkback created
|
||
*
|
||
\******************************************************************************/
|
||
#endif
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* Include Files
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
#define ALLOCATE
|
||
#include "hdxdll.h"
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <windowsx.h>
|
||
#include <lzexpand.h>
|
||
#ifndef _WIN32
|
||
#include "viewer.h"
|
||
#endif
|
||
#include "resource.h"
|
||
#include "..\contents.h"
|
||
|
||
|
||
// ****************************************************************************
|
||
// local variables
|
||
//
|
||
static nWinHelp = 1; // default to WinHelp system
|
||
#ifdef _WIN32
|
||
#define VWR HANDLE
|
||
#endif
|
||
static VWR Vwr = NULL;
|
||
static HWND hWndHelpDlg = NULL;
|
||
|
||
static TCHAR szProduct[_MAX_FNAME] = _T("Product");
|
||
static TCHAR szBookset[_MAX_FNAME] = _T("");
|
||
static TCHAR szHelpPath[_MAX_PATH] = _T("");
|
||
static TCHAR szLocalHelpPath[_MAX_PATH] = _T("");
|
||
static TCHAR szRemoteHelpPath[_MAX_PATH] = _T("");
|
||
static TCHAR szHelpFile[_MAX_FNAME] = _T("");
|
||
static TCHAR szEmpty[] = _T("");
|
||
static BOOL bTroubleshoot = FALSE;
|
||
static HELPINDEXITEM LastHelpItem = {0};
|
||
static int nBitmapResource = IDB_OUTLINE;
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* Function Declarations
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
DWORD GetRegistryString(LPCTSTR lpszSection, LPCTSTR lpszKey, LPCTSTR lpszDefault,
|
||
LPTSTR lpszReturnBuffer, DWORD cchReturnBuffer, LPCTSTR lpszFile);
|
||
|
||
static BOOL GetHelpItemData (HELPINDEXITEM FAR *, HELPINDEX FAR *, LONG, BOOL);
|
||
static BOOL GetHelpItemExpanFlag (HELPINDEX FAR *, LONG);
|
||
static void SetHelpItemExpanFlag (HELPINDEX FAR *, LONG, BOOL);
|
||
static LONG GetHelpItemLinesMap (HELPINDEX FAR *, LONG);
|
||
static void SetHelpItemLinesMap (HELPINDEX FAR *, LONG, LONG);
|
||
static HELPINDEXITEM FAR * GetCachedHelpItem (HELPINDEX FAR *, LONG);
|
||
static ITEM_RW_OVERLAY FAR * GetHelpItemRWOverlay (HELPINDEX FAR *, LONG);
|
||
static void FAR * GAllocLock (DWORD, BOOL);
|
||
static BOOL ExpandHelpTopic(LPHELPINDEX lpHelpIndex, LPHELPINDEXITEM lpHelpItem);
|
||
BOOL WriteRegistryString(LPCTSTR lpszSection, LPCTSTR lpszKey, LPCTSTR lpszString, LPCTSTR lpszFile);
|
||
void ProcessHelpSearch(HWND hWnd, LPHELPINDEX lpHelpIndex, LONG nFilePos, UINT nListPos );
|
||
static long GetValidHelpFilePos(HELPINDEXITEM FAR * lphelpitem, LPHELPINDEX lpHelpIndex, long pos);
|
||
static BOOL IsQuickReference(void);
|
||
static void ChangeBitmap(LPHELPINDEX lpHelpIndex, int nBitmapResource);
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* mprintf() - printfs out formatted text to a message box.
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
int
|
||
mprintf( UINT uStyle, UINT id, const TCHAR *pszFormat, ... )
|
||
{
|
||
TCHAR szBuffer[512];
|
||
TCHAR szFormat[512];
|
||
va_list marker; // this is added to make it work with ALPHA
|
||
|
||
// if id is zero, use first char string as format
|
||
if ( id && LoadString(hInstance, id, szFormat, sizeof(szFormat)) )
|
||
{
|
||
va_start(marker,id);
|
||
_vstprintf(szBuffer, szFormat, marker );
|
||
//_vstprintf(szBuffer, szFormat, (va_list)(&pszFormat) );
|
||
}
|
||
else
|
||
{
|
||
va_start(marker,pszFormat);
|
||
_vstprintf(szBuffer, pszFormat, marker );
|
||
//_vstprintf(szBuffer, pszFormat, (va_list)(&pszFormat+1) );
|
||
}
|
||
va_end(marker);
|
||
|
||
// the following messagebox must use NULL as the handle or it's going to bomb
|
||
// when GetFocus() happens to return a handle to a timer app which shuts down
|
||
// after a while and in turn destroys this messagebox with it.
|
||
return MessageBox( NULL, szBuffer, szHelpIndexClass, uStyle );
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
*
|
||
* FUNCTION: HelpIndexDlgProc (standard dialog procedure INPUTS/RETURNS)
|
||
*
|
||
* COMMENTS: This dialog comes up in response to a user requesting to
|
||
* modify the control style. This sample allows for changing
|
||
* the control's text, and this is done by modifying the
|
||
* CCSTYLE (32-bit) or CTLSTYLE (16-bit) structure pointed at by "gpccs"
|
||
* (a pointer that was passed to us by dlgedit).
|
||
*
|
||
\******************************************************************************/
|
||
|
||
PC_WNDPROCRV CALLBACK PC_EXPORT
|
||
HelpIndexDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
|
||
{
|
||
|
||
switch (msg)
|
||
{
|
||
case WM_INITDIALOG :
|
||
{
|
||
Vwr = NULL; // clear Viewer handle
|
||
|
||
#ifdef _WIN32
|
||
if (gpccs->flStyle & HS_LINES)
|
||
#else
|
||
if (gpccs->dwStyle & HS_LINES)
|
||
#endif
|
||
CheckDlgButton( hDlg, IDD_LINES, TRUE );
|
||
break;
|
||
}
|
||
|
||
case WM_COMMAND:
|
||
{
|
||
switch( LOWORD(wParam) )
|
||
{
|
||
case IDD_LINES:
|
||
{
|
||
#ifdef _WIN32
|
||
if ( IsDlgButtonChecked( hDlg, IDD_LINES ) )
|
||
gpccs->flStyle |= HS_LINES;
|
||
else
|
||
gpccs->flStyle &= ~HS_LINES;
|
||
#else
|
||
if ( IsDlgButtonChecked( hDlg, IDD_LINES ) )
|
||
gpccs->dwStyle |= HS_LINES;
|
||
else
|
||
gpccs->dwStyle &= ~HS_LINES;
|
||
#endif
|
||
break;
|
||
}
|
||
|
||
case IDOK:
|
||
case IDCANCEL:
|
||
{
|
||
EndDialog( hDlg, LOWORD(wParam) == IDOK );
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
void CALLBACK PC_EXPORT SetViewerHandle(VWR vwr)
|
||
{
|
||
Vwr = vwr;
|
||
}
|
||
|
||
void CALLBACK PC_EXPORT GetViewerHandle(VWR FAR *pvwr)
|
||
{
|
||
*pvwr = Vwr;
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
*
|
||
* FUNCTION: HelpIndexStyle
|
||
*
|
||
* INPUTS: hWndParent - handle of parent window (dialog editor)
|
||
* pccs - pointer to a CCSTYLE structure
|
||
*
|
||
* RETURNS: TRUE if success,
|
||
* FALSE if error occured
|
||
*
|
||
* LOCAL VARS: rc - return code from DialogBox
|
||
*
|
||
\******************************************************************************/
|
||
|
||
BOOL CALLBACK PC_EXPORT
|
||
#ifdef _WIN32
|
||
HelpIndexStyle( HWND hWndParent, HANDLE hCtlStyle )
|
||
#else
|
||
HelpIndexStyle( HWND hWndParent, HANDLE hCtlStyle, LPFNSTRTOID lpfnStrToId,
|
||
LPFNIDTOSTR lpfnIdToStr )
|
||
#endif
|
||
{
|
||
/*******************/
|
||
/* Local Variables */
|
||
/*******************/
|
||
|
||
BOOL bComplete = FALSE;
|
||
DLGPROC dlgprocInst = NULL;
|
||
|
||
/**************************************************************/
|
||
/* Save the pointer to custom control style passed by DLGEDIT */
|
||
/**************************************************************/
|
||
|
||
gpccs = (PC_LPCCSTYLE) GlobalLock( hCtlStyle );
|
||
|
||
/********************************/
|
||
/* Try to create the Dialog Box */
|
||
/********************************/
|
||
|
||
dlgprocInst = (DLGPROC)MakeProcInstance( HelpIndexDlgProc, hInstance );
|
||
if ((gpccs == NULL) || hWndParent)
|
||
{
|
||
if ((bComplete = DialogBox( hInstance, _TEXT("HelpIndexStyle"), hWndParent, dlgprocInst)) == -1)
|
||
{
|
||
/***********************************/
|
||
/* Could not create the dialog box */
|
||
/***********************************/
|
||
|
||
mprintf( MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL, IDS_ERROR_HELPINDEXDLG, szNull);
|
||
//_TEXT("HelpIndexStyle(): DialogBox() failed = %d"), bComplete );
|
||
bComplete = FALSE;
|
||
}
|
||
}
|
||
FreeProcInstance( dlgprocInst );
|
||
if (gpccs != NULL)
|
||
{
|
||
GlobalUnlock( hCtlStyle );
|
||
}
|
||
|
||
/*********************/
|
||
/* Return completion */
|
||
/*********************/
|
||
|
||
return bComplete;
|
||
}
|
||
|
||
/******************************************************************************\
|
||
*
|
||
* FUNCTION: HelpIndexFlags
|
||
*
|
||
* INPUTS: dwFlags - style flag combo to be xlated to .rc text
|
||
* lpStyle - buffer to receive the translated text
|
||
* wMaxString - size of the destination buffer in bytes
|
||
*
|
||
* RETURNS: length of string copied to caller's buffer
|
||
* zero if error occured
|
||
*
|
||
\******************************************************************************/
|
||
|
||
WORD CALLBACK PC_EXPORT
|
||
HelpIndexFlags( DWORD dwFlags, LPSTR lpStyle, WORD wMaxString )
|
||
{
|
||
WORD wRet = 0;
|
||
WORD wStrLen;
|
||
LPSTR szLines = _TEXT("HS_LINES");
|
||
LPSTR szNoLines = _TEXT(" ");
|
||
if ( (dwFlags & HS_LINES) && ( ( wStrLen = _ftcslen( szLines ) ) < wMaxString ) )
|
||
{
|
||
_ftcscpy( lpStyle, szLines );
|
||
wRet = wStrLen;
|
||
}
|
||
else if ( !(dwFlags & HS_LINES )
|
||
&& ( ( wStrLen = _ftcslen( szNoLines ) ) < wMaxString ) )
|
||
{
|
||
_ftcscpy( lpStyle, szLines );
|
||
wRet = wStrLen;
|
||
}
|
||
return( wRet );
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* RGBtoBGR
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
DWORD
|
||
RGBtoBGR( DWORD rgb )
|
||
{
|
||
return( RGB( GetBValue(rgb), GetGValue(rgb), GetRValue(rgb) ) );
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* FindBitmap
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
HBITMAP FindBitmap(LPHELPINDEX lpHelpIndex, int nResource)
|
||
{
|
||
HBITMAP hBitmap = NULL;
|
||
HRSRC hRes = NULL;
|
||
LPBITMAPINFOHEADER lptr, lpBitmapInfo = NULL;
|
||
HGLOBAL hMem = NULL;
|
||
DWORD dw;
|
||
|
||
#ifdef _WIN32
|
||
while (1)
|
||
{
|
||
if ( hRes = FindResource(hInstance, MAKEINTRESOURCE(nResource), RT_BITMAP) )
|
||
{
|
||
dw = SizeofResource(hInstance, hRes);
|
||
if ( hRes = LoadResource(hInstance, hRes) )
|
||
{
|
||
// for 32-bit, we have to copy the loaded resource to a temp memory block
|
||
// so we can write to it. LockResource() is readonly memory.
|
||
if ( hMem = GlobalAlloc(GMEM_FIXED, dw) )
|
||
{
|
||
if ( lpBitmapInfo = GlobalLock(hMem) )
|
||
{
|
||
if ( lptr = (LPBITMAPINFOHEADER)LockResource(hRes) )
|
||
{
|
||
if ( memcpy(lpBitmapInfo, lptr, dw) )
|
||
{
|
||
// make sure to unlock and free hMem before this function returns to caller.
|
||
UnlockResource(hRes);
|
||
FreeResource(hRes);
|
||
hRes = NULL;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
lpBitmapInfo = NULL;
|
||
GlobalUnlock(hMem);
|
||
GlobalFree(hMem);
|
||
hMem = NULL;
|
||
UnlockResource(hRes);
|
||
FreeResource(hRes);
|
||
hRes = 0;
|
||
OutputDebugString("FindBitmap(): failed memcpy()\n");
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
UnlockResource(hRes);
|
||
FreeResource(hRes);
|
||
hRes = NULL;
|
||
GlobalUnlock(hMem);
|
||
GlobalFree(hMem);
|
||
hMem = NULL;
|
||
OutputDebugString("FindBitmap(): Can't lock bitmap resource\n");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
UnlockResource(hRes);
|
||
FreeResource(hRes);
|
||
hRes = NULL;
|
||
GlobalFree(hMem);
|
||
hMem = NULL;
|
||
OutputDebugString("FindBitmap(): Can't lock global memory to copy bitmap resource.\n");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
UnlockResource(hRes);
|
||
FreeResource(hRes);
|
||
hRes = NULL;
|
||
OutputDebugString("FindBitmap(): Can't allocate tmp memory to copy bitmap resource.\n");
|
||
}
|
||
}
|
||
else
|
||
OutputDebugString("FindBitmap(): Can't load bitmap resource.\n");
|
||
}
|
||
else
|
||
OutputDebugString("FindBitmap(): Can't find bitmap resource.\n");
|
||
|
||
// used while(1) loop so I only have to issue error messagebox once here.
|
||
mprintf(MB_OK, IDS_ERROR_FINDBITMAP, szNull);
|
||
break;
|
||
}
|
||
|
||
if (lpBitmapInfo)
|
||
{
|
||
HDC hDC;
|
||
DWORD *lpColorTable = (DWORD *)(lpBitmapInfo + 1);
|
||
LPBYTE lpPixels = (LPSTR)( lpColorTable + 16 ); // 16 Color Bitmap!!
|
||
int nBackgroundColor = (*lpPixels & 0xF0) >> 4; // 16 Color Bitmap!!
|
||
|
||
lpColorTable[nBackgroundColor] = RGBtoBGR(GetSysColor(COLOR_WINDOW));
|
||
|
||
if ( hDC = GetDC(NULL) )
|
||
{
|
||
hBitmap = CreateDIBitmap(hDC, lpBitmapInfo, (DWORD)CBM_INIT, lpPixels,
|
||
(LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS);
|
||
if (hBitmap)
|
||
{
|
||
lpHelpIndex->nBitmapHeight = (int)lpBitmapInfo->biHeight / BITMAP_ROWS;
|
||
lpHelpIndex->nBitmapWidth = (int)lpBitmapInfo->biWidth / BITMAP_COLS;
|
||
}
|
||
else
|
||
{
|
||
OutputDebugString("FindBitmap(): failed CreateDIBitmap().\n");
|
||
mprintf(MB_OK, IDS_ERROR_FINDBITMAP, szNull);
|
||
}
|
||
ReleaseDC( NULL, hDC );
|
||
}
|
||
else
|
||
{
|
||
OutputDebugString("FindBitmap(): Failed GetDC().\n");
|
||
mprintf(MB_OK, IDS_ERROR_FINDBITMAP, szNull);
|
||
}
|
||
|
||
// unlock Temporary memory and free it
|
||
if (hMem)
|
||
{
|
||
GlobalUnlock(hMem);
|
||
GlobalFree(hMem);
|
||
hMem = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
#else
|
||
if ( hRes = LoadResource( hInstance,
|
||
FindResource( hInstance, MAKEINTRESOURCE( nResource ), RT_BITMAP ) ) )
|
||
{
|
||
LPBITMAPFILEHEADER lpBitmapFileHeader;
|
||
LPBITMAPINFOHEADER lpBitmapInfo;
|
||
if ( lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource( hRes ) )
|
||
//if ( lpBitmapFileHeader = (LPBITMAPFILEHEADER)LockResource( hRes ) )
|
||
{
|
||
HDC hDC;
|
||
//LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)(lpBitmapFileHeader + sizeof(BITMAPFILEHEADER));
|
||
DWORD *lpColorTable = (DWORD *)(lpBitmapInfo + 1);
|
||
LPBYTE lpPixels = (LPSTR)( lpColorTable + 16 ); // 16 Color Bitmap!!
|
||
int nBackgroundColor = (*lpPixels & 0xF0) >> 4; // 16 Color Bitmap!!
|
||
|
||
lpColorTable[nBackgroundColor] = RGBtoBGR( GetSysColor(COLOR_WINDOW) );
|
||
|
||
if ( hDC = GetDC(NULL) )
|
||
{
|
||
hBitmap = CreateDIBitmap(hDC, lpBitmapInfo, (DWORD)CBM_INIT, lpPixels,
|
||
(LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS);
|
||
if (hBitmap)
|
||
{
|
||
lpHelpIndex->nBitmapHeight = (int)lpBitmapInfo->biHeight / BITMAP_ROWS;
|
||
lpHelpIndex->nBitmapWidth = (int)lpBitmapInfo->biWidth / BITMAP_COLS;
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_DRAWBITMAP, szNull);
|
||
//_TEXT("FindBitmap(%d): CreateDIBitmap() Failed!"), nResource );
|
||
ReleaseDC( NULL, hDC );
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_GETDC, szNull);
|
||
//_TEXT("FindBitmap(%d): GetDC(NULL) Failed!"), nResource );
|
||
|
||
UnlockResource( hRes );
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_LOCKRESOURCE, szNull);
|
||
//_TEXT("FindBitmap(): LoadResource( %d, RT_BITMAP ) Failed!"), nResource );
|
||
|
||
FreeResource( hRes );
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_LOADBITMAP, szNull);
|
||
//_TEXT("FindBitmap(): LoadResource( %d, RT_BITMAP ) Failed!"), nResource );
|
||
#endif
|
||
return hBitmap;
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* DestroyHelpIndex()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
LPHELPINDEX DestroyHelpIndex( LPHELPINDEX lpHelpIndex )
|
||
{
|
||
HGLOBAL hGlobal;
|
||
|
||
if ( lpHelpIndex )
|
||
{
|
||
if ( lpHelpIndex->hfileIndex )
|
||
{
|
||
LZClose( lpHelpIndex->hfileIndex );
|
||
lpHelpIndex->hfileIndex = (HFILE)NULL;
|
||
}
|
||
|
||
if ( lpHelpIndex->pIndexItemCache )
|
||
{
|
||
if (hGlobal = GlobalPtrHandle(lpHelpIndex->pIndexItemCache))
|
||
{
|
||
GlobalUnlock(hGlobal);
|
||
GlobalFree(hGlobal);
|
||
lpHelpIndex->pIndexItemCache = NULL;
|
||
}
|
||
}
|
||
|
||
if ( lpHelpIndex->pIndexRWOverlay )
|
||
{
|
||
if (hGlobal = GlobalPtrHandle(lpHelpIndex->pIndexRWOverlay))
|
||
{
|
||
GlobalUnlock(hGlobal);
|
||
GlobalFree(hGlobal);
|
||
lpHelpIndex->pIndexRWOverlay = NULL;
|
||
}
|
||
}
|
||
lpHelpIndex->nHdrBytesCt = 0;
|
||
lpHelpIndex->nHelpItemCt = 0;
|
||
|
||
if (lpHelpIndex->hdcBitmaps)
|
||
{
|
||
if (lpHelpIndex->hbmDefault)
|
||
SelectObject(lpHelpIndex->hdcBitmaps, lpHelpIndex->hbmDefault);
|
||
DeleteDC(lpHelpIndex->hdcBitmaps);
|
||
lpHelpIndex->hdcBitmaps = NULL;
|
||
}
|
||
|
||
if ( lpHelpIndex->hbmBitmaps )
|
||
{
|
||
DeleteObject( lpHelpIndex->hbmBitmaps );
|
||
lpHelpIndex->hbmBitmaps = NULL;
|
||
}
|
||
|
||
if ( lpHelpIndex->hListbox )
|
||
{
|
||
DestroyWindow( (HWND)lpHelpIndex->hListbox );
|
||
lpHelpIndex->hListbox = NULL;
|
||
}
|
||
|
||
if (hGlobal = GlobalPtrHandle(lpHelpIndex))
|
||
{
|
||
GlobalUnlock(hGlobal);
|
||
GlobalFree(hGlobal);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
//******************************************************************************
|
||
static void ChangeBitmap(LPHELPINDEX lpHelpIndex, int nBitmapResource)
|
||
{
|
||
HDC hDC;
|
||
if ( hDC = GetDC(NULL) )
|
||
{
|
||
if ( lpHelpIndex->hdcBitmaps)
|
||
{
|
||
HBITMAP hBitmap;
|
||
if ( hBitmap = FindBitmap(lpHelpIndex, nBitmapResource) )
|
||
{
|
||
DeleteObject((HBITMAP)lpHelpIndex->hbmBitmaps);
|
||
lpHelpIndex->hbmBitmaps = hBitmap;
|
||
lpHelpIndex->hbmDefault = SelectObject(lpHelpIndex->hdcBitmaps, lpHelpIndex->hbmBitmaps);
|
||
// force redraw just to make sure
|
||
//InvalidateRect(lpHelpIndex->hListbox, NULL, TRUE);
|
||
}
|
||
}
|
||
else
|
||
mprintf(MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL, IDS_ERROR_DRAWBITMAP, szNull);
|
||
ReleaseDC(NULL, hDC);
|
||
}
|
||
else
|
||
mprintf(MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL, IDS_ERROR_GETDC, szNull);
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* BuildHelpIndex()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
LPHELPINDEX BuildHelpIndex( HWND hWnd )
|
||
{
|
||
BOOL bComplete = FALSE;
|
||
LPHELPINDEX lpHelpIndex = NULL;
|
||
HINSTANCE hinstClient = NULL;
|
||
|
||
if (hWnd)
|
||
{
|
||
#ifdef _WIN32
|
||
hinstClient = (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE );
|
||
#else
|
||
hinstClient = (HINSTANCE) GetWindowWord( hWnd, GWW_HINSTANCE );
|
||
#endif
|
||
if ( lpHelpIndex = (LPHELPINDEX)GAllocLock( sizeof(HELPINDEX), TRUE ) )
|
||
{
|
||
// [chauv] fixed uninitialize memory problem by calling GAllocLock(..,TRUE) to do zeroinit
|
||
lpHelpIndex->pIndexRWOverlay = (ITEM_RW_OVERLAY FAR *)GAllocLock(MAX_ITEM_OVERLAY_CT * sizeof(ITEM_RW_OVERLAY), TRUE);
|
||
if ( ( lpHelpIndex->pIndexRWOverlay )
|
||
&&
|
||
( lpHelpIndex->hListbox = CreateWindow( _TEXT("LISTBOX"), NULL,
|
||
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL |
|
||
LBS_OWNERDRAWFIXED | LBS_WANTKEYBOARDINPUT |
|
||
LBS_NOTIFY | LBS_NOINTEGRALHEIGHT,
|
||
0, 0, 0, 0, hWnd, (HMENU)1, hinstClient, NULL ) )
|
||
)
|
||
{
|
||
HDC hDC;
|
||
if ( hDC = GetDC(NULL) )
|
||
{
|
||
if ( lpHelpIndex->hdcBitmaps = CreateCompatibleDC(hDC) )
|
||
{
|
||
lpHelpIndex->hbmDefault = 0;
|
||
if ( lpHelpIndex->hbmBitmaps = FindBitmap(lpHelpIndex, IDB_OUTLINE) )
|
||
{
|
||
lpHelpIndex->hbmDefault = SelectObject(lpHelpIndex->hdcBitmaps, lpHelpIndex->hbmBitmaps);
|
||
bComplete = TRUE;
|
||
}
|
||
}
|
||
else
|
||
mprintf(MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL, IDS_ERROR_DRAWBITMAP, szNull);
|
||
//_TEXT("HelpIndexWndProc(): GetCompatibleDC(\"ListBox\") failed!") );
|
||
ReleaseDC(NULL, hDC);
|
||
}
|
||
else
|
||
mprintf(MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL, IDS_ERROR_GETDC, szNull);
|
||
//_TEXT("HelpIndexWndProc(): GetDC(\"ListBox\") failed!") );
|
||
}
|
||
else
|
||
mprintf(MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL, IDS_ERROR_CREATELISTBOX, szNull);
|
||
//_TEXT("HelpIndexWndProc(): CreateWindow(\"ListBox\") failed!") );
|
||
}
|
||
else
|
||
mprintf(MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL, IDS_ERROR_LOCKHELPINDEX, szNull);
|
||
//_TEXT("HelpIndexWndProc(): GlobalAlloc() failed!") );
|
||
|
||
if ( !bComplete )
|
||
lpHelpIndex = DestroyHelpIndex( lpHelpIndex );
|
||
}
|
||
return lpHelpIndex;
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* FixupHelpIndexLines()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
void
|
||
FixupHelpIndexLines( LPHELPINDEX lpHelpIndex )
|
||
{
|
||
HCURSOR hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
|
||
|
||
LONG nCurrPos;
|
||
HELPINDEXITEM helpitemCurr;
|
||
LONG nHelpLinesCurr;
|
||
LONG nHelpDepthNext;
|
||
LONG nHelpLinesNext;
|
||
|
||
nCurrPos = lpHelpIndex->nHelpItemCt - 1;
|
||
if (GetHelpItemData (&helpitemCurr, lpHelpIndex, nCurrPos, FALSE))
|
||
{
|
||
nHelpLinesCurr = 0;
|
||
SetHelpItemLinesMap( lpHelpIndex, nCurrPos, nHelpLinesCurr );
|
||
while ( --nCurrPos >= 0 )
|
||
{
|
||
nHelpDepthNext = helpitemCurr.nHelpDepth;
|
||
nHelpLinesNext = nHelpLinesCurr;
|
||
if (GetHelpItemData (&helpitemCurr, lpHelpIndex, nCurrPos, FALSE))
|
||
{
|
||
if ( helpitemCurr.nHelpDepth )
|
||
{
|
||
if ( helpitemCurr.nHelpDepth >= nHelpDepthNext )
|
||
nHelpLinesCurr |= (0x1 << (nHelpDepthNext-1));
|
||
else
|
||
nHelpLinesCurr &= ((0x1 << (helpitemCurr.nHelpDepth))-1);
|
||
}
|
||
else
|
||
nHelpLinesCurr = 0;
|
||
SetHelpItemLinesMap( lpHelpIndex, nCurrPos, nHelpLinesCurr );
|
||
}
|
||
else break;
|
||
}
|
||
}
|
||
SetCursor( hOldCursor );
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* LoadHelpIndexFile()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
BOOL
|
||
LoadHelpIndexFile( LPHELPINDEX lpHelpIndex, LPSTR lpszHelpIndexFile )
|
||
{
|
||
BOOL bComplete = FALSE;
|
||
HCURSOR hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
|
||
HDXFILEINFO hdxFileInfo;
|
||
|
||
if ( ( lpHelpIndex->hfileIndex == (HFILE)NULL ) && EXISTS( lpszHelpIndexFile ) )
|
||
{
|
||
OFSTRUCT of;
|
||
UINT hInput;
|
||
if ( ( hInput = LZOpenFile(lpszHelpIndexFile, &of, OF_READ) ) != (UINT)-1)
|
||
{
|
||
if ( LZRead(hInput, (LPSTR)&hdxFileInfo, sizeof(hdxFileInfo)) )
|
||
{
|
||
if ( hdxFileInfo.size == (LONG)sizeof(HELPINDEXITEM) )
|
||
{
|
||
LONG nHelpIndex = LZSeek( hInput, 0, 2 ) - sizeof(HDXFILEINFO);
|
||
if ( nHelpIndex > 0 && !(nHelpIndex % sizeof(HELPINDEXITEM) ) )
|
||
{
|
||
lpHelpIndex->hfileIndex = hInput;
|
||
lpHelpIndex->nHdrBytesCt = sizeof (HDXFILEINFO);
|
||
lpHelpIndex->nHelpItemCt = nHelpIndex
|
||
/ sizeof(HELPINDEXITEM);
|
||
FixupHelpIndexLines( lpHelpIndex );
|
||
bComplete = TRUE;
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_BADDATASIZE,
|
||
//_TEXT("LoadHelpIndexFile(%s): Bad Data Size=%ld!"),
|
||
lpszHelpIndexFile, nHelpIndex);
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_BADRECORDSIZE,
|
||
//_TEXT("LoadHelpIndexFile(rsize=%d, %s): Bad Record Size=%d!"),
|
||
//sizeof(HELPINDEXITEM), lpszHelpIndexFile,
|
||
lpszHelpIndexFile, hdxFileInfo.size);
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_TRUNCATEINDEX,
|
||
//_TEXT("LoadHelpIndexFile(%s): Truncated Index File!"),
|
||
lpszHelpIndexFile );
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_OPENINDEXFILE,
|
||
// _TEXT("LoadHelpFile(%s): Cannot Open File!"),
|
||
lpszHelpIndexFile);
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_INDEXFILEMISSING,
|
||
//_TEXT("LoadHelpIndexFile(): File <%s> is missing!"),
|
||
lpszHelpIndexFile );
|
||
|
||
SetCursor( hOldCursor );
|
||
return bComplete;
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* SetFont()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
void SetFont(HFONT hFont, LPHELPINDEX lpHelpIndex)
|
||
{
|
||
HDC hDC;
|
||
|
||
if (lpHelpIndex->hListbox)
|
||
{
|
||
if ( hDC = GetDC(lpHelpIndex->hListbox) )
|
||
{
|
||
HFONT hFontOld;
|
||
|
||
if ( hFontOld = SelectObject(hDC, hFont) )
|
||
{
|
||
TEXTMETRIC tm;
|
||
GetTextMetrics(hDC, &tm);
|
||
|
||
lpHelpIndex->nTextHeight = tm.tmHeight;
|
||
lpHelpIndex->nLineHeight = max( lpHelpIndex->nTextHeight,
|
||
lpHelpIndex->nBitmapHeight );
|
||
SelectObject(hDC, hFontOld);
|
||
|
||
ListBox_SetItemHeight( lpHelpIndex->hListbox, 0,
|
||
lpHelpIndex->nLineHeight );
|
||
SetWindowFont(lpHelpIndex->hListbox, hFont, TRUE);
|
||
}
|
||
|
||
ReleaseDC(lpHelpIndex->hListbox, hDC);
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_GETDC, szNull);
|
||
//_TEXT("SetFont: GetDC(hListBox=%d) Failed!"), lpHelpIndex->hListbox );
|
||
}
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* FastRect()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
void
|
||
FastRect( HDC hDC, int x, int y, int cx, int cy )
|
||
{
|
||
RECT rc;
|
||
if (hDC)
|
||
{
|
||
rc.left = x;
|
||
rc.right = x+cx;
|
||
rc.top = y;
|
||
rc.bottom = y+cy;
|
||
ExtTextOut( hDC, x, y, ETO_OPAQUE, &rc, NULL, 0, NULL );
|
||
}
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* DrawItem()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
void DrawItem(LPHELPINDEX lpHelpIndex, LPDRAWITEMSTRUCT lpDrawItem)
|
||
{
|
||
HDC hDC;
|
||
/***************************************/
|
||
/* Make sure we have something to draw */
|
||
/***************************************/
|
||
|
||
if ( lpHelpIndex && lpDrawItem && ( lpDrawItem->itemID != (LONG)-1 ) &&
|
||
( (LONG) (lpDrawItem->itemData) < lpHelpIndex->nHelpItemCt ) )
|
||
{
|
||
LONG nFilePos = (LONG)lpDrawItem->itemData;
|
||
RECT rcDraw;
|
||
UINT xOrigin, yBitmap, xText, yText, yDrawing;
|
||
HELPINDEXITEM helpitem;
|
||
BOOL bExpandedItem = GetHelpItemExpanFlag (lpHelpIndex, nFilePos);
|
||
LONG nItemLinesMap = GetHelpItemLinesMap (lpHelpIndex, nFilePos);
|
||
|
||
if (GetHelpItemData (&helpitem, lpHelpIndex, nFilePos, TRUE))
|
||
{
|
||
if (hDC = lpDrawItem->hDC)
|
||
{
|
||
CopyRect( &rcDraw, &lpDrawItem->rcItem );
|
||
yDrawing = rcDraw.bottom - rcDraw.top;
|
||
|
||
xOrigin = rcDraw.left + (int)(helpitem.nHelpDepth * lpHelpIndex->nBitmapWidth) + LEFTMARGIN;
|
||
rcDraw.left = xOrigin + lpHelpIndex->nBitmapWidth;
|
||
yBitmap = rcDraw.top + yDrawing/2 - lpHelpIndex->nBitmapHeight/2;
|
||
yText = rcDraw.top + yDrawing/2 - lpHelpIndex->nTextHeight/2;
|
||
|
||
// don't need to check for ODA_FOCUS because we want to always draw
|
||
// the background and DrawFocusRect() to keep them in sync. This also
|
||
// cured the listbox scrolling problem.
|
||
//if ( lpDrawItem->itemAction != ODA_FOCUS )
|
||
if ( lpDrawItem->itemAction != ODA_SELECT )
|
||
{
|
||
int nRow = (int)(helpitem.nHelpDepth % BITMAP_ROWS);
|
||
int nColumn = helpitem.nHelpTopic ? SINGLE_PAGE : (bExpandedItem ? OPENED_BOOK : CLOSED_BOOK );
|
||
|
||
if ( helpitem.nHelpDepth &&
|
||
HAS_LINES( GetParent( lpHelpIndex->hListbox ) ) )
|
||
{
|
||
int nTempLevel, x, y;
|
||
DWORD dwBitMask = 0x00000001;
|
||
SetBkColor( hDC, GetSysColor( COLOR_WINDOWTEXT ) );
|
||
|
||
x = lpHelpIndex->nBitmapWidth/2 + LEFTMARGIN;
|
||
for( nTempLevel = 0;
|
||
nTempLevel < (int)helpitem.nHelpDepth;
|
||
nTempLevel++ )
|
||
{
|
||
if ( nItemLinesMap & dwBitMask )
|
||
FastRect( hDC, x, rcDraw.top, 1, yDrawing );
|
||
x += (int)(lpHelpIndex->nBitmapWidth);
|
||
dwBitMask <<= 1;
|
||
}
|
||
|
||
nTempLevel = (int)(helpitem.nHelpDepth)-1;
|
||
dwBitMask <<= 1;
|
||
x = (int)(nTempLevel * lpHelpIndex->nBitmapWidth +
|
||
lpHelpIndex->nBitmapWidth/2 + LEFTMARGIN);
|
||
y = rcDraw.bottom;
|
||
if ( !(nItemLinesMap & dwBitMask ) )
|
||
y -= lpHelpIndex->nLineHeight/2;
|
||
|
||
FastRect( hDC, x, rcDraw.top, 1, y - rcDraw.top );
|
||
FastRect( hDC, x, rcDraw.bottom - lpHelpIndex->nLineHeight/2,
|
||
lpHelpIndex->nBitmapWidth/2, 1 );
|
||
}
|
||
|
||
BitBlt( hDC, xOrigin, yBitmap,
|
||
(int)(lpHelpIndex->nBitmapWidth),
|
||
(int)(lpHelpIndex->nBitmapHeight),
|
||
lpHelpIndex->hdcBitmaps,
|
||
nColumn * (int)(lpHelpIndex->nBitmapWidth),
|
||
nRow * (int)(lpHelpIndex->nBitmapHeight),
|
||
SRCCOPY );
|
||
}
|
||
|
||
SetBkColor( hDC, GetSysColor( lpDrawItem->itemState & ODS_SELECTED ? COLOR_HIGHLIGHT : COLOR_WINDOW ) );
|
||
SetTextColor( hDC, GetSysColor( lpDrawItem->itemState & ODS_SELECTED ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT ) );
|
||
xText = rcDraw.left + 1;
|
||
if ( ExtTextOut( hDC, xText, yText, ETO_CLIPPED | ETO_OPAQUE,
|
||
&rcDraw, helpitem.szHelpTopic,
|
||
_ftcslen( helpitem.szHelpTopic ), NULL ) )
|
||
{
|
||
SIZE textsize;
|
||
if ( GetTextExtentPoint( hDC, helpitem.szHelpTopic,
|
||
_ftcslen( helpitem.szHelpTopic ),
|
||
&textsize ) &&
|
||
(xText + textsize.cx > lpHelpIndex->nMaxTextWidth) )
|
||
{
|
||
lpHelpIndex->nMaxTextWidth = xText + textsize.cx;
|
||
ListBox_SetHorizontalExtent( lpHelpIndex->hListbox,
|
||
lpHelpIndex->nMaxTextWidth );
|
||
}
|
||
}
|
||
|
||
if ( (lpDrawItem->itemState & ODS_FOCUS) &&
|
||
(lpDrawItem->itemAction != ODA_SELECT) )
|
||
DrawFocusRect( hDC, &rcDraw );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* ShowExpanded()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
void ShowExpanded( LPHELPINDEX lpHelpIndex, UINT nMaxLevel )
|
||
{
|
||
HCURSOR hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
|
||
if ( lpHelpIndex )
|
||
{
|
||
HWND hListbox = lpHelpIndex->hListbox;
|
||
LONG nPos = 0;
|
||
HELPINDEXITEM helpitem;
|
||
|
||
if (hListbox)
|
||
{
|
||
ListBox_ResetContent(hListbox);
|
||
|
||
if ( lpHelpIndex->nHelpItemCt > 0 )
|
||
{
|
||
SendMessage( hListbox, WM_SETREDRAW, 0, 0 );
|
||
do
|
||
{
|
||
if (GetHelpItemData(&helpitem, lpHelpIndex, nPos, FALSE))
|
||
{
|
||
SetHelpItemExpanFlag (lpHelpIndex, nPos, FALSE);
|
||
if ( (UINT)(helpitem.nHelpDepth) <= nMaxLevel )
|
||
{
|
||
if ( !helpitem.nHelpTopic && (UINT)(helpitem.nHelpDepth) < nMaxLevel )
|
||
SetHelpItemExpanFlag( lpHelpIndex, nPos, TRUE );
|
||
ListBox_AddString( hListbox, (LPVOID)nPos );
|
||
}
|
||
}
|
||
else break;
|
||
}
|
||
while( ++nPos < lpHelpIndex->nHelpItemCt );
|
||
SendMessage( hListbox, WM_SETREDRAW, 1, 0 );
|
||
InvalidateRect(hListbox, NULL, TRUE);
|
||
ListBox_SetCurSel( hListbox, 0 );
|
||
}
|
||
}
|
||
}
|
||
SetCursor( hOldCursor );
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* ExpandOneLevel()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
void ExpandOneLevel( LPHELPINDEX lpHelpIndex, LONG nFilePos, UINT nListPos )
|
||
{
|
||
HCURSOR hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
|
||
HWND hListbox = lpHelpIndex->hListbox;
|
||
HELPINDEXITEM helpitem;
|
||
LONG nOrigDepth;
|
||
|
||
if (hListbox)
|
||
{
|
||
if (GetHelpItemData( &helpitem, lpHelpIndex, nFilePos, FALSE ))
|
||
{
|
||
SetHelpItemExpanFlag( lpHelpIndex, nFilePos, TRUE );
|
||
nOrigDepth = helpitem.nHelpDepth;
|
||
|
||
SendMessage( hListbox, WM_SETREDRAW, 0, 0 );
|
||
|
||
while( ++nFilePos < lpHelpIndex->nHelpItemCt )
|
||
{
|
||
if (GetHelpItemData( &helpitem, lpHelpIndex, nFilePos, FALSE ))
|
||
{
|
||
if ( helpitem.nHelpDepth > nOrigDepth )
|
||
{
|
||
if ( helpitem.nHelpDepth-1 == nOrigDepth )
|
||
ListBox_InsertString( hListbox, ++nListPos, (LPVOID)nFilePos );
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
else break;
|
||
}
|
||
SendMessage( hListbox, WM_SETREDRAW, 1, 0 );
|
||
InvalidateRect(hListbox, NULL, FALSE);
|
||
}
|
||
}
|
||
SetCursor( hOldCursor );
|
||
}
|
||
|
||
|
||
// ***************************************************************************
|
||
// ExpandUptoLevel(lpHelpIndex, nLevel)
|
||
//
|
||
// purpose: call this function to expand content listbox to a certain level.
|
||
// Level must be greater than 1 to be effective since level 1 is
|
||
// the lowest and is the default level. One can do an expand ALL
|
||
// by calling this function with a very high level number.
|
||
void ExpandUptoLevel(LPHELPINDEX lpHelpIndex, LONG nLevel)
|
||
{
|
||
HCURSOR hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
|
||
HWND hListbox = lpHelpIndex->hListbox;
|
||
HELPINDEXITEM helpitem;
|
||
LONG nCount = 0;
|
||
UINT nListPos = 0;
|
||
|
||
// just make sure and don't waste time here.
|
||
if (nLevel < 1)
|
||
return;
|
||
|
||
if (hListbox)
|
||
{
|
||
// reset listbox content first
|
||
ListBox_ResetContent( hListbox );
|
||
|
||
SendMessage( hListbox, WM_SETREDRAW, 0, 0 );
|
||
|
||
while( nCount <= lpHelpIndex->nHelpItemCt )
|
||
{
|
||
if (GetHelpItemData( &helpitem, lpHelpIndex, nCount, FALSE ))
|
||
{
|
||
// only expand if file position is less than or equal to the desired level
|
||
if ( helpitem.nHelpDepth < nLevel )
|
||
{
|
||
ListBox_InsertString( hListbox, nListPos++, (LPVOID)nCount );
|
||
|
||
// set expansion flag if it's level is one higher than the lowest expanded level
|
||
if (helpitem.nHelpDepth < nLevel-1)
|
||
SetHelpItemExpanFlag( lpHelpIndex, nCount, TRUE );
|
||
}
|
||
|
||
// next position
|
||
nCount++;
|
||
}
|
||
else break;
|
||
}
|
||
SendMessage( hListbox, WM_SETREDRAW, 1, 0 );
|
||
InvalidateRect(hListbox, NULL, FALSE);
|
||
ListBox_SetCurSel( hListbox, 0 );
|
||
}
|
||
SetCursor( hOldCursor );
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* CollapseOneLevel()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
void
|
||
CollapseOneLevel( LPHELPINDEX lpHelpIndex, LONG nFilePos, UINT nListPos )
|
||
{
|
||
HCURSOR hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
|
||
HWND hListbox = lpHelpIndex->hListbox;
|
||
HELPINDEXITEM helpitem;
|
||
LONG nOrigDepth;
|
||
|
||
if (hListbox)
|
||
{
|
||
if (GetHelpItemData( &helpitem, lpHelpIndex, nFilePos, FALSE ))
|
||
{
|
||
nOrigDepth = helpitem.nHelpDepth;
|
||
SetHelpItemExpanFlag ( lpHelpIndex, nFilePos, FALSE );
|
||
|
||
++nListPos;
|
||
|
||
SendMessage( hListbox, WM_SETREDRAW, 0, 0 );
|
||
while( (nFilePos = (LONG)ListBox_GetItemData( hListbox, nListPos )) != LB_ERR )
|
||
{
|
||
if (GetHelpItemData( &helpitem, lpHelpIndex, nFilePos, FALSE ))
|
||
{
|
||
if ( helpitem.nHelpDepth > nOrigDepth )
|
||
{
|
||
if ( helpitem.nHelpTopic == 0 )
|
||
SetHelpItemExpanFlag( lpHelpIndex, nFilePos, FALSE );
|
||
ListBox_DeleteString( hListbox, nListPos );
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
else break;
|
||
}
|
||
SendMessage( hListbox, WM_SETREDRAW, 1, 0 );
|
||
InvalidateRect(hListbox, NULL, TRUE);
|
||
}
|
||
}
|
||
SetCursor( hOldCursor );
|
||
}
|
||
|
||
|
||
// *****************************************************************************
|
||
LRESULT CALLBACK PC_EXPORT
|
||
HelpDirDlgProc(HWND hDlg, UINT message, WPARAM uParam, LPARAM lParam)
|
||
{
|
||
TCHAR szTemp[MAX_PATH];
|
||
TCHAR szBuf[MAX_PATH];
|
||
switch (message)
|
||
{
|
||
case WM_INITDIALOG:
|
||
hWndHelpDlg = hDlg;
|
||
GetDlgItemText(hDlg, IDC_HELPDLG_MSG, szTemp, sizeof(szTemp));
|
||
wsprintf(szBuf, szTemp, szHelpFile);
|
||
SetDlgItemText(hDlg, IDC_HELPDLG_MSG, szBuf);
|
||
SetDlgItemText(hDlg, IDC_LOCALHELP, szLocalHelpPath);
|
||
SetDlgItemText(hDlg, IDC_REMOTEHELP, szRemoteHelpPath);
|
||
SetFocus(GetDlgItem(hDlg, IDC_LOCALHELP));
|
||
return (TRUE);
|
||
|
||
case WM_COMMAND:
|
||
switch (LOWORD(uParam))
|
||
{
|
||
case IDOK:
|
||
GetDlgItemText(hDlg, IDC_LOCALHELP, szLocalHelpPath, sizeof(szLocalHelpPath));
|
||
GetDlgItemText(hDlg, IDC_REMOTEHELP, szRemoteHelpPath, sizeof(szRemoteHelpPath));
|
||
EndDialog(hDlg, TRUE);
|
||
hWndHelpDlg = NULL;
|
||
return (TRUE);
|
||
|
||
case IDCANCEL:
|
||
EndDialog(hDlg, FALSE);
|
||
hWndHelpDlg = NULL;
|
||
return (TRUE);
|
||
}
|
||
return TRUE;
|
||
}
|
||
return (FALSE); // Didn't process the message
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
*
|
||
* FUNCTION: HelpLookup
|
||
*
|
||
* COMMENTS: This function performs the lookup of a help / contents file
|
||
* in the specified profile section (see the WM_SETTEXT handler)
|
||
* to locate the actual path to the file.
|
||
*
|
||
* NOTE: Filename is being retrieved from the registry only if lpName is empty.
|
||
* If it's not empty, just do the path search.
|
||
*
|
||
* RETURN: pointer to NULL if helpfile is not found in the registry
|
||
* or NULL if user cancels HelpDir dialog.
|
||
*
|
||
\******************************************************************************/
|
||
|
||
LPSTR
|
||
HelpLookup(HWND hWnd, LPHELPINDEX lpHelpIndex, LPCSTR lpName, LPCSTR lpKeyword )
|
||
{
|
||
TCHAR szSection[_MAX_FNAME];
|
||
TCHAR szBuf[_MAX_FNAME];
|
||
TCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR];
|
||
TCHAR szPname[_MAX_FNAME], szExt[_MAX_EXT];
|
||
HWND hWndTmp;
|
||
|
||
//_splitpath( lpName, NULL, NULL, szSection, NULL );
|
||
// [chauv] can no longer use lpName here because we switched over to
|
||
// using Registry instead of private profile. Now, szProfile contains
|
||
// the section key name.
|
||
|
||
// ******** this block gets help filename
|
||
// NOTE: Filename is being retrieved from the registry only if lpName is empty.
|
||
// If it's not empty, just do the path search.
|
||
if ( *lpName == _T('\0') )
|
||
{
|
||
#ifdef _WIN32
|
||
wsprintf(szSection, "%s\\%s\\%s\\%s", szRegistryKey, szProduct, szContentsSection, lpHelpIndex->szProfile);
|
||
#else
|
||
wsprintf(szSection, "%s", szProduct);
|
||
#endif
|
||
GetRegistryString(szSection, lpKeyword, lpName, szHelpFile, sizeof(szHelpFile), lpHelpIndex->szProfile );
|
||
if (_tcscmp(szHelpFile, _TEXT("")) == 0)
|
||
{
|
||
#ifdef _WIN32
|
||
mprintf(MB_OK, IDS_ERROR_SECTION,
|
||
// _TEXT("Could not find section [%s], key \"%s\"."),
|
||
szSection, lpKeyword);
|
||
#else
|
||
mprintf( MB_OK, _TEXT("Could not find section [%s], key \"%s\", in %s."),
|
||
szSection, lpKeyword, lpHelpIndex->szProfile );
|
||
#endif
|
||
return szEmpty;
|
||
}
|
||
}
|
||
else
|
||
_tcscpy(szHelpFile, lpName);
|
||
|
||
// ******** this block gets help path
|
||
wsprintf(szSection, "%s\\%s\\%s", szRegistryKey, szProduct, szDirectoriesSection);
|
||
while (1)
|
||
{
|
||
FARPROC lpProcHelpDir;
|
||
BOOL rb;
|
||
int i;
|
||
DWORD dw;
|
||
|
||
// check for local help path first
|
||
i = 1;
|
||
if ( szLocalHelpPath[0] == _T('\0') )
|
||
{
|
||
wsprintf(szBuf, "%s%u", szLocalHelpKey, i++);
|
||
GetRegistryString(szSection, szBuf, szNull, szLocalHelpPath, sizeof(szPname), lpHelpIndex->szProfile);
|
||
}
|
||
_tcscpy(szPname, szLocalHelpPath);
|
||
while (1)
|
||
{
|
||
// see if the last occurance is a '\' and do appropriate appending.
|
||
// this code prevents the next line from stripping "c:\dir\subdir" to "c:\dir"
|
||
if (_tcsrchr(szPname, _T('\\')) == (szPname + _tcslen(szPname) - 1))
|
||
_tcscat(szPname, _T("x"));
|
||
else
|
||
_tcscat(szPname, _T("\\x"));
|
||
|
||
_splitpath(szPname, szDrive, szDir, NULL, NULL);
|
||
_splitpath(szHelpFile, NULL, NULL, szPname, szExt);
|
||
_makepath(szHelpPath, szDrive, szDir, szPname, szExt);
|
||
if (EXISTS(szHelpPath))
|
||
{
|
||
// when we write, we always write to "LocalHelp1" and "RemoteHelp1"
|
||
if (szLocalHelpPath[0])
|
||
WriteRegistryString(szSection, szLocalHelpKey1, szLocalHelpPath, lpHelpIndex->szProfile);
|
||
if (szRemoteHelpPath[0])
|
||
WriteRegistryString(szSection, szRemoteHelpKey1, szRemoteHelpPath, lpHelpIndex->szProfile);
|
||
return szHelpPath;
|
||
}
|
||
|
||
// loop thru "LocalHelp1", "LocalHelp2", etc...
|
||
wsprintf(szBuf, "%s%u", szLocalHelpKey, i++);
|
||
dw = GetRegistryString(szSection, szBuf, szNull, szPname, sizeof(szPname), lpHelpIndex->szProfile);
|
||
if ( dw != ERROR_SUCCESS )
|
||
break;
|
||
}
|
||
|
||
// failed local help path, now check for remote help path
|
||
i = 1;
|
||
if ( szRemoteHelpPath[0] == _T('\0') )
|
||
{
|
||
wsprintf(szBuf, "%s%u", szRemoteHelpKey, i++);
|
||
GetRegistryString(szSection, szBuf, szNull, szRemoteHelpPath, sizeof(szPname), lpHelpIndex->szProfile);
|
||
}
|
||
_tcscpy(szPname, szRemoteHelpPath);
|
||
while (1)
|
||
{
|
||
// see if the last occurance is a '\' and do appropriate appending.
|
||
// this code prevents the next line from stripping "c:\dir\subdir" to "c:\dir"
|
||
if (_tcsrchr(szPname, _T('\\')) == (szPname + _tcslen(szPname) - 1))
|
||
_tcscat(szPname, _T("x"));
|
||
else
|
||
_tcscat(szPname, _T("\\x"));
|
||
|
||
_splitpath(szPname, szDrive, szDir, NULL, NULL);
|
||
_splitpath(szHelpFile, NULL, NULL, szPname, szExt);
|
||
_makepath(szHelpPath, szDrive, szDir, szPname, szExt);
|
||
if (EXISTS(szHelpPath))
|
||
{
|
||
// when we write, we always write to "LocalHelp1" and "RemoteHelp1"
|
||
if (szLocalHelpPath[0])
|
||
WriteRegistryString(szSection, szLocalHelpKey1, szLocalHelpPath, lpHelpIndex->szProfile);
|
||
if (szRemoteHelpPath[0])
|
||
WriteRegistryString(szSection, szRemoteHelpKey1, szRemoteHelpPath, lpHelpIndex->szProfile);
|
||
return szHelpPath;
|
||
}
|
||
|
||
// now loop thru "RemoteHelp1", "RemoteHelp2", etc...
|
||
wsprintf(szBuf, "%s%u", szRemoteHelpKey, i++);
|
||
dw = GetRegistryString(szSection, szBuf, szNull, szPname, sizeof(szPname), lpHelpIndex->szProfile);
|
||
if ( dw != ERROR_SUCCESS )
|
||
break;
|
||
}
|
||
|
||
// **** if the dialogbox is already there, skip it.
|
||
if ( (hWndTmp = FindWindow(szDlgClass, szHelpDirDlgCaption)) && IsWindow(hWndTmp) )
|
||
return NULL;
|
||
|
||
// Always send parent a close last session message so last session and
|
||
// new session can't fight each other while Help Directory dialogbox is up.
|
||
if ((hWndTmp = GetParent(hWnd)) == NULL)
|
||
hWndTmp = hWnd;
|
||
else
|
||
SendMessage(hWndTmp, WM_COMMAND, IDW_CLOSELASTSESSION, 0L);
|
||
|
||
// none of above work ? ask thru dialogbox
|
||
if (hWndTmp)
|
||
{
|
||
lpProcHelpDir = MakeProcInstance((FARPROC)HelpDirDlgProc, hInstance);
|
||
rb = DialogBox(hInstance, MAKEINTRESOURCE(IDD_HELPDIRECTORY), hWndTmp, (DLGPROC)lpProcHelpDir);
|
||
FreeProcInstance(lpProcHelpDir);
|
||
if (rb == FALSE)
|
||
break;
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
|
||
// *****************************************************************************
|
||
// CallHelp() is used to substitute for original WinHelp() so it can determine if
|
||
// WinHelp or Viewer is to be used. See help on WinHelp() for parameters details.
|
||
//
|
||
static BOOL CallHelp(HWND hWnd, LPSTR lpszHelpFile, UINT fuCommand, DWORD dwData)
|
||
{
|
||
TCHAR szCommand[_MAX_FNAME];
|
||
|
||
if (hWnd == NULL)
|
||
return FALSE;
|
||
|
||
#ifdef _WIN32
|
||
wsprintf(szCommand, _TEXT("JumpHash(qchPath, %u)"), dwData);
|
||
if (bTroubleshoot)
|
||
mprintf(MB_OK, 0, "%s - %s", szCommand, lpszHelpFile);
|
||
//return WinHelp(hWnd, (LPCSTR)lpszHelpFile, fuCommand, dwData);
|
||
WinHelp(hWnd, (LPCSTR)lpszHelpFile, HELP_FORCEFILE, 0L);
|
||
//WinHelp(hWnd, (LPCSTR)lpszHelpFile, HELP_CONTEXTPOPUP, 7L);
|
||
if (!WinHelp(hWnd, (LPCSTR)lpszHelpFile, HELP_COMMAND, (DWORD)((LPSTR)szCommand)))
|
||
{
|
||
// in case the help file is not opened or correct help file is loaded,
|
||
// we force that help file to be opened/loaded then try to jump to help topic again.
|
||
WinHelp(hWnd, (LPCSTR)lpszHelpFile, HELP_FORCEFILE, 0L);
|
||
WinHelp(hWnd, (LPCSTR)lpszHelpFile, HELP_COMMAND, (DWORD)((LPSTR)szCommand));
|
||
}
|
||
switch(fuCommand)
|
||
{
|
||
case HELP_SEARCH:
|
||
WinHelp(hWnd, (LPCSTR)lpszHelpFile, HELP_COMMAND, (DWORD)(LPSTR)("Search()"));
|
||
break;
|
||
case HELP_FTSEARCH:
|
||
WinHelp(hWnd, (LPCSTR)lpszHelpFile, HELP_COMMAND, (DWORD)(LPSTR)("ExecFullTextSearch(hwndApp,qchPath,`',`')"));
|
||
break;
|
||
}
|
||
return TRUE;
|
||
#else
|
||
|
||
if (nWinHelp)
|
||
return WinHelp(hWnd, (LPCSTR)lpszHelpFile, fuCommand, dwData);
|
||
else
|
||
{
|
||
//wsprintf(szCommand, _TEXT("JumpID(`%s',`%u')"), lpszHelpFile, dwData);
|
||
wsprintf(szCommand, _TEXT("JumpID(qchPath,`%u')"), dwData);
|
||
if ((Vwr = VwrCommand(Vwr, lpszHelpFile, szCommand, cmdoptNONE)) == NULL)
|
||
Vwr = VwrCommand(Vwr, lpszHelpFile, szCommand, cmdoptNONE);
|
||
return (BOOL)Vwr;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* ProcessItem()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
void ProcessItem(HWND hWnd, LPHELPINDEX lpHelpIndex, LONG nFilePos, UINT nListPos )
|
||
{
|
||
HELPINDEXITEM helpitem;
|
||
if ( hWnd && lpHelpIndex && (nFilePos >= 0) && (nFilePos < lpHelpIndex->nHelpItemCt) && (nListPos >= 0) )
|
||
{
|
||
if (GetHelpItemData (&helpitem, lpHelpIndex, nFilePos, TRUE))
|
||
{
|
||
// update help topic for restore last topic feature
|
||
LastHelpItem = helpitem;
|
||
if ( helpitem.nHelpTopic )
|
||
{
|
||
LPSTR lpHelpFile;
|
||
lpHelpFile = HelpLookup(hWnd, lpHelpIndex, helpitem.szHelpFile, cszHLPKey);
|
||
// if lpHelpFile is NULL, the user cancelled the help lookup
|
||
// if lpHelpFile is pointed to a null string, can't find registry value but don't
|
||
// need to report error here because HelpLookup() already done so.
|
||
if (lpHelpFile && *lpHelpFile)
|
||
CallHelp( lpHelpIndex->hListbox, lpHelpFile, HELP_CONTEXT, helpitem.nHelpTopic);
|
||
//else if (*lpHelpFile == _T('\0'))
|
||
// mprintf( MB_OK, _TEXT("No Help Available on '%s'!"), helpitem.szHelpTopic );
|
||
}
|
||
else
|
||
{
|
||
if ( !GetHelpItemExpanFlag( lpHelpIndex, nFilePos ) )
|
||
ExpandOneLevel( lpHelpIndex, nFilePos, nListPos );
|
||
else
|
||
CollapseOneLevel( lpHelpIndex, nFilePos, nListPos );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
*
|
||
* FUNCTION: HelpIndexWndProc (standard window procedure INPUTS/RETURNS)
|
||
*
|
||
* COMMENTS: This is the window procedure for our custom control. At
|
||
* creation we alloc a HELPINDEX struct, initialize it,
|
||
* and associate it with this particular control.
|
||
*
|
||
\******************************************************************************/
|
||
|
||
LRESULT CALLBACK PC_EXPORT
|
||
HelpIndexWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||
{
|
||
/*******************/
|
||
/* Local Variables */
|
||
/*******************/
|
||
|
||
long lResult = 0;
|
||
LPHELPINDEX lpHelpIndex = GETHELPINDEX( hWnd );
|
||
|
||
/************************************/
|
||
/* Switch Based on the Message Type */
|
||
/************************************/
|
||
|
||
switch ( uMsg )
|
||
{
|
||
/****************************/
|
||
/* Window is being created! */
|
||
/****************************/
|
||
|
||
case WM_CREATE:
|
||
{
|
||
LPCREATESTRUCT lpCreate = (LPCREATESTRUCT)lParam;
|
||
|
||
/******************************************************/
|
||
/* WM_MEASUREITEM should have created this structure! */
|
||
/******************************************************/
|
||
|
||
if ( lpHelpIndex || ( lpHelpIndex = BuildHelpIndex( hWnd ) ) )
|
||
{
|
||
/*********************************/
|
||
/* Save the help index structure */
|
||
/*********************************/
|
||
|
||
SETHELPINDEX( hWnd, lpHelpIndex );
|
||
|
||
/****************************************/
|
||
/* Initialize the font to be something! */
|
||
/****************************************/
|
||
|
||
SetFont( GetStockObject(SYSTEM_FONT), lpHelpIndex );
|
||
|
||
/***********************************/
|
||
/* See if we got a index file name */
|
||
/***********************************/
|
||
|
||
//if ( lpCreate->lpszName && *lpCreate->lpszName )
|
||
if (0)
|
||
{
|
||
/****************************************/
|
||
/* Force the outline file to be loaded. */
|
||
/****************************************/
|
||
|
||
SetWindowText( hWnd, lpCreate->lpszName );
|
||
}
|
||
}
|
||
else
|
||
lResult = -1;
|
||
break;
|
||
}
|
||
|
||
|
||
/***********************************************************/
|
||
/* Set the invisible window title(VIEWER.INI Help Section) */
|
||
/***********************************************************/
|
||
|
||
case WM_SETTEXT:
|
||
{
|
||
BOOL bLoadedIndex = FALSE;
|
||
// mprintf( MB_OK, _TEXT("Got a WM_SETTEXT( %s )"), (LPSTR)lParam );
|
||
if ( lpHelpIndex && (LPSTR)lParam )
|
||
{
|
||
LPSTR lpszToken;
|
||
LPSTR lPtr;
|
||
if ( lpszToken = _ftcstok( (LPSTR)lParam, _TEXT("|") ) )
|
||
{
|
||
_ftcsnccpy( lpHelpIndex->szProfile, lpszToken,
|
||
sizeof(lpHelpIndex->szProfile) );
|
||
//if (lpszToken = _ftcstok( NULL, _TEXT("|") ) )
|
||
// bLoadedIndex = LoadHelpIndexFile( lpHelpIndex, HelpLookup( lpHelpIndex, lpszToken, _TEXT("Contents File") ) );
|
||
//else
|
||
// [chauv] it just doesn't make sense to have this "book|contents" argument
|
||
// If you can't find the book, warn the user the book is invalid.
|
||
lPtr = HelpLookup(hWnd, lpHelpIndex, szNull, cszHDXKey);
|
||
if ( lPtr && (*lPtr != _T('\0')) )
|
||
bLoadedIndex = LoadHelpIndexFile( lpHelpIndex, lPtr);
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_COMMAND, (LPSTR)lParam);
|
||
//_TEXT("Invalid command argument \"%s\"."), (LPSTR)lParam);
|
||
}
|
||
else
|
||
mprintf(MB_OK, IDS_ERROR_COMMAND, (LPSTR)lParam);
|
||
// _TEXT("Invalid command argument \"%s\"."), (LPSTR)lParam);
|
||
|
||
// check LastTopic... from registry
|
||
if ( bLoadedIndex )
|
||
{
|
||
TCHAR szSection[_MAX_FNAME];
|
||
TCHAR szBuffer[_MAX_FNAME];
|
||
|
||
wsprintf(szSection, _T("%s\\%s\\%s\\%s"), szRegistryKey, szProduct, szContentsSection, szBookset);
|
||
GetRegistryString(szSection, szTopicUse, _T("1"), szBuffer, sizeof(szBuffer), lpHelpIndex->szProfile);
|
||
if (szBuffer[0] == _T('1'))
|
||
{
|
||
GetRegistryString(szSection, szTopicID, szNull, szBuffer, sizeof(szBuffer), lpHelpIndex->szProfile);
|
||
LastHelpItem.nHelpTopic = atol(szBuffer);
|
||
GetRegistryString(szSection, szTopicHelpfile, szNull, LastHelpItem.szHelpFile, sizeof(LastHelpItem.szHelpFile), lpHelpIndex->szProfile);
|
||
GetRegistryString(szSection, szTopicTitle, szNull, LastHelpItem.szHelpTopic, sizeof(LastHelpItem.szHelpTopic), lpHelpIndex->szProfile);
|
||
if (!ExpandHelpTopic(lpHelpIndex, &LastHelpItem))
|
||
ShowExpanded(lpHelpIndex, 0);
|
||
}
|
||
else
|
||
ShowExpanded(lpHelpIndex, 0);
|
||
}
|
||
|
||
DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||
break;
|
||
}
|
||
|
||
/********************************************/
|
||
/* Define which font to use in drawing text */
|
||
/********************************************/
|
||
|
||
case WM_SETFONT:
|
||
{
|
||
if ( lpHelpIndex && lpHelpIndex->hListbox )
|
||
SetFont( (HFONT)wParam, lpHelpIndex );
|
||
break;
|
||
}
|
||
|
||
|
||
/*************************************************/
|
||
/* Return the current height of each lisbox line */
|
||
/*************************************************/
|
||
|
||
case WM_MEASUREITEM:
|
||
{
|
||
LPMEASUREITEMSTRUCT lpMeasureItem = (LPMEASUREITEMSTRUCT)lParam;
|
||
|
||
/******************************************/
|
||
/* See if we have built a help index yet. */
|
||
/******************************************/
|
||
|
||
if ( lpHelpIndex )
|
||
{
|
||
/**********************************/
|
||
/* Return the listbox line height */
|
||
/**********************************/
|
||
|
||
lpMeasureItem->itemHeight = max( lpHelpIndex->nBitmapHeight,
|
||
lpHelpIndex->nTextHeight );
|
||
}
|
||
break;
|
||
}
|
||
|
||
/***********************************************/
|
||
/* Draw the requested item in the listbox line */
|
||
/***********************************************/
|
||
|
||
case WM_DRAWITEM:
|
||
{
|
||
if ( lpHelpIndex )
|
||
DrawItem( lpHelpIndex, (LPDRAWITEMSTRUCT)lParam );
|
||
break;
|
||
}
|
||
|
||
|
||
/***************************************/
|
||
/* Someone hit a key on a listbox item */
|
||
/***************************************/
|
||
|
||
case WM_VKEYTOITEM:
|
||
{
|
||
/******************************************************/
|
||
/* Pass the keystroke up a level for processing first */
|
||
/******************************************************/
|
||
|
||
if ( ( lResult = SendMessage( GetParent( hWnd ), uMsg,
|
||
wParam, lParam ) ) != -2 )
|
||
|
||
{
|
||
/*****************************************/
|
||
/* See if we have a help index structure */
|
||
/*****************************************/
|
||
|
||
if ( lpHelpIndex )
|
||
{
|
||
/*******************************************/
|
||
/* Get the current selection and item data */
|
||
/*******************************************/
|
||
|
||
UINT nItem = (UINT)(lResult >= 0 ? lResult :
|
||
ListBox_GetCurSel( lpHelpIndex->hListbox ));
|
||
LONG nPos = (LONG)
|
||
ListBox_GetItemData( lpHelpIndex->hListbox, nItem );
|
||
|
||
/***********************************************/
|
||
/* If we have item data, process the keystroke */
|
||
/***********************************************/
|
||
|
||
if ( nPos >= 0 )
|
||
{
|
||
|
||
HELPINDEXITEM helpitem;
|
||
if (!GetHelpItemData (&helpitem, lpHelpIndex, nPos, FALSE))
|
||
break;
|
||
|
||
/********************************************/
|
||
/* If a special keystroke, process the item */
|
||
/********************************************/
|
||
|
||
switch( LOWORD(wParam) )
|
||
{
|
||
/*******************************/
|
||
/* Was the left arrow pressed? */
|
||
/*******************************/
|
||
|
||
case VK_LEFT:
|
||
{
|
||
/********************************/
|
||
/* Find the parent of this item */
|
||
/********************************/
|
||
|
||
LONG nPosParent = 0;
|
||
LONG nPosCand = nPos - 1;
|
||
HELPINDEXITEM helpitemParent;
|
||
|
||
while ((nPosParent == 0) && ( nPosCand > 0 ))
|
||
{
|
||
if (GetHelpItemData(&helpitemParent, lpHelpIndex, nPosCand, FALSE))
|
||
{
|
||
if ( helpitemParent.nHelpDepth < helpitem.nHelpDepth )
|
||
nPosParent = nPosCand;
|
||
nPosCand--;
|
||
}
|
||
else break;
|
||
}
|
||
if (nPosParent == 0)
|
||
if (!GetHelpItemData (&helpitemParent, lpHelpIndex, 0, FALSE))
|
||
break;
|
||
|
||
/*******************************/
|
||
/* If open, collapse one level */
|
||
/*******************************/
|
||
|
||
if (GetHelpItemExpanFlag(lpHelpIndex, nPosParent ))
|
||
{
|
||
UINT nParent = ListBox_FindString(
|
||
lpHelpIndex->hListbox, 0,
|
||
(LPVOID)nPosParent );
|
||
if ( nParent != LB_ERR )
|
||
{
|
||
CollapseOneLevel( lpHelpIndex, nPosParent,
|
||
nParent );
|
||
ListBox_SetCurSel( lpHelpIndex->hListbox,
|
||
nParent );
|
||
}
|
||
}
|
||
lResult = -2; // We ate this keystroke!
|
||
break;
|
||
}
|
||
|
||
/************************************/
|
||
/* Was the right arrow key pressed? */
|
||
/************************************/
|
||
|
||
case VK_RIGHT:
|
||
{
|
||
/*********************************/
|
||
/* If not open, expand one level */
|
||
/*********************************/
|
||
|
||
if ( !helpitem.nHelpTopic &&
|
||
( !GetHelpItemExpanFlag(lpHelpIndex, nPos) ) )
|
||
{
|
||
ExpandOneLevel( lpHelpIndex, nPos, nItem );
|
||
ListBox_SetCurSel( lpHelpIndex->hListbox,
|
||
nItem + 1 );
|
||
}
|
||
lResult = -2; // We ate this keystroke!
|
||
break;
|
||
}
|
||
|
||
/*******************************/
|
||
/* Was the return key pressed? */
|
||
/*******************************/
|
||
|
||
case VK_SPACE:
|
||
case VK_RETURN:
|
||
{
|
||
/**********************************************/
|
||
/* Process the item like a mouse double click */
|
||
/**********************************************/
|
||
|
||
ProcessItem(hWnd, lpHelpIndex, nPos, nItem );
|
||
lResult = -2; // We ate this keystroke!
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
// expand level needs to reset last topic Use flag
|
||
{
|
||
TCHAR szSection[_MAX_FNAME];
|
||
|
||
wsprintf(szSection, "%s\\%s\\%s\\%s", szRegistryKey, szProduct, szContentsSection, szBookset);
|
||
WriteRegistryString(szSection, szTopicUse, _T("1"), lpHelpIndex->szProfile);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
|
||
/***********************************/
|
||
/* Pass the focus onto the listbox */
|
||
/***********************************/
|
||
|
||
case WM_SETFOCUS:
|
||
{
|
||
if ( lpHelpIndex && IsWindow( lpHelpIndex->hListbox ) )
|
||
SetFocus( lpHelpIndex->hListbox );
|
||
break;
|
||
}
|
||
|
||
/********************************/
|
||
/* Paint the default background */
|
||
/********************************/
|
||
|
||
case WM_PAINT:
|
||
{
|
||
PAINTSTRUCT ps;
|
||
HDC hDC = BeginPaint( hWnd, &ps );
|
||
EndPaint( hWnd, &ps );
|
||
break;
|
||
}
|
||
|
||
/*************************/
|
||
/* Window is being sized */
|
||
/*************************/
|
||
|
||
case WM_SIZE:
|
||
{
|
||
if ( lpHelpIndex && IsWindow(lpHelpIndex->hListbox) )
|
||
MoveWindow( lpHelpIndex->hListbox, 0, 0,
|
||
LOWORD(lParam), HIWORD(lParam), TRUE );
|
||
break;
|
||
}
|
||
|
||
/**********************************/
|
||
/* Did someone send us a command? */
|
||
/**********************************/
|
||
|
||
case WM_COMMAND:
|
||
{
|
||
#ifdef _WIN32
|
||
switch (LOWORD(wParam))
|
||
#else
|
||
switch (wParam)
|
||
#endif
|
||
{
|
||
// [chauv 6/10/94]
|
||
case IDD_CHANGEBITMAP:
|
||
{
|
||
if (lParam)
|
||
ChangeBitmap(lpHelpIndex, IDB_QUICKREFERENCE);
|
||
else
|
||
ChangeBitmap(lpHelpIndex, IDB_OUTLINE);
|
||
break;
|
||
}
|
||
|
||
case IDD_TROUBLESHOOT:
|
||
bTroubleshoot = TRUE;
|
||
break;
|
||
|
||
case IDD_SETHELPPATH:
|
||
_tcscpy(szLocalHelpPath, (TCHAR FAR *)(lParam));
|
||
break;
|
||
|
||
case VK_RIGHT:
|
||
{ // [chauv 10/18/93]
|
||
// added for expand up to a level feature
|
||
// lParam = level to expand up to
|
||
ExpandUptoLevel(lpHelpIndex, lParam);
|
||
// expand level needs to reset last topic Use flag
|
||
{
|
||
TCHAR szSection[_MAX_FNAME];
|
||
|
||
wsprintf(szSection, "%s\\%s\\%s\\%s", szRegistryKey, szProduct, szContentsSection, szBookset);
|
||
WriteRegistryString(szSection, szTopicUse, _T("1"), lpHelpIndex->szProfile);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case IDD_SEARCH:
|
||
{
|
||
|
||
if (lpHelpIndex)
|
||
{
|
||
UINT nItem = (UINT)ListBox_GetCurSel(lpHelpIndex->hListbox);
|
||
LONG nPos = (LONG)ListBox_GetItemData(lpHelpIndex->hListbox, nItem);
|
||
if( nPos >= 0 )
|
||
ProcessHelpSearch(hWnd, lpHelpIndex, nPos, nItem);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case IDD_VIEWER:
|
||
{
|
||
nWinHelp = LOWORD(lParam);
|
||
break;
|
||
}
|
||
|
||
case IDD_PRODUCTKEY:
|
||
{
|
||
_tcscpy(szProduct, (TCHAR FAR *)(lParam));
|
||
break;
|
||
}
|
||
|
||
case IDD_BOOKSETKEY:
|
||
{
|
||
_ftcscpy(szBookset, (TCHAR FAR *)(lParam));
|
||
break;
|
||
}
|
||
|
||
case IDD_JUMPID:
|
||
{
|
||
TCHAR szBuffer[_MAX_FNAME];
|
||
HELPINDEXITEM tmphelpitem;
|
||
|
||
_tcscpy(szBuffer, _tcstok((TCHAR FAR *)(lParam), _T(":")));
|
||
//if (bTroubleshoot)
|
||
// mprintf(MB_OK, 0, szBuffer);
|
||
tmphelpitem.nHelpTopic = atol(szBuffer);
|
||
_tcscpy(tmphelpitem.szHelpFile, _tcstok(NULL, _T(":")));
|
||
if (ExpandHelpTopic(lpHelpIndex, &tmphelpitem))
|
||
LastHelpItem = tmphelpitem;
|
||
//else
|
||
// ShowExpanded(lpHelpIndex, 0);
|
||
// jump topic needs to reset last topic Use flag
|
||
{
|
||
TCHAR szSection[_MAX_FNAME];
|
||
|
||
wsprintf(szSection, "%s\\%s\\%s\\%s", szRegistryKey, szProduct, szContentsSection, szBookset);
|
||
WriteRegistryString(szSection, szTopicUse, _T("1"), lpHelpIndex->szProfile);
|
||
}
|
||
break;
|
||
}
|
||
|
||
default:
|
||
{
|
||
#ifdef _WIN32
|
||
switch (GET_WM_COMMAND_CMD( wParam, lParam ))
|
||
#else
|
||
switch (HIWORD(lParam))
|
||
#endif // #ifdef _WIN32
|
||
{
|
||
case LBN_DBLCLK:
|
||
if (lpHelpIndex)
|
||
{
|
||
UINT nItem = (UINT)
|
||
ListBox_GetCurSel( lpHelpIndex->hListbox );
|
||
LONG nPos = (LONG)
|
||
ListBox_GetItemData( lpHelpIndex->hListbox, nItem );
|
||
if( nPos >= 0 )
|
||
ProcessItem(hWnd, lpHelpIndex, nPos, nItem );
|
||
// reset last topic Use flag when a topic is selected
|
||
{
|
||
TCHAR szSection[_MAX_FNAME];
|
||
|
||
wsprintf(szSection, "%s\\%s\\%s\\%s", szRegistryKey, szProduct, szContentsSection, szBookset);
|
||
WriteRegistryString(szSection, szTopicUse, _T("1"), lpHelpIndex->szProfile);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
case WM_CLOSE:
|
||
DestroyWindow(hWnd);
|
||
break;
|
||
|
||
/*****************************/
|
||
/* Window is being destroyed */
|
||
/*****************************/
|
||
|
||
case WM_DESTROY:
|
||
{
|
||
// save last help index topic
|
||
{
|
||
TCHAR szSection[_MAX_FNAME];
|
||
TCHAR szBuffer[_MAX_FNAME];
|
||
|
||
wsprintf(szSection, "%s\\%s\\%s\\%s", szRegistryKey, szProduct, szContentsSection, szBookset);
|
||
wsprintf(szBuffer, _TEXT("%u"), LastHelpItem.nHelpTopic);
|
||
WriteRegistryString(szSection, szTopicID, szBuffer, lpHelpIndex->szProfile);
|
||
WriteRegistryString(szSection, szTopicHelpfile, LastHelpItem.szHelpFile, lpHelpIndex->szProfile);
|
||
WriteRegistryString(szSection, szTopicTitle, LastHelpItem.szHelpTopic, lpHelpIndex->szProfile);
|
||
}
|
||
|
||
if (hWndHelpDlg)
|
||
SendMessage(hWndHelpDlg, WM_COMMAND, IDCANCEL, 0L);
|
||
SETHELPINDEX( hWnd, lpHelpIndex = DestroyHelpIndex( lpHelpIndex ) );
|
||
break;
|
||
}
|
||
|
||
/*********************************/
|
||
/* Some other event is happening */
|
||
/*********************************/
|
||
|
||
default:
|
||
{
|
||
lResult = DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||
break;
|
||
}
|
||
}
|
||
|
||
/**************************/
|
||
/* Return the result code */
|
||
/**************************/
|
||
|
||
return lResult;
|
||
}
|
||
|
||
|
||
|
||
#ifdef _WIN32
|
||
/******************************************************************************\
|
||
*
|
||
* FUNCTION: HelpIndexSizeToText
|
||
*
|
||
* INPUTS: flStyle - control style
|
||
* flExtStyle - control extended style
|
||
* hFont - handle of font used to draw text
|
||
* pszText - control text
|
||
*
|
||
* RETURNS: Width (in pixels) control must be to accomodate text, or
|
||
* -1 if an error occurs.
|
||
*
|
||
* COMMENTS: Just no-op here
|
||
*
|
||
\******************************************************************************/
|
||
|
||
INT CALLBACK
|
||
HelpIndexSizeToText(DWORD flStyle, DWORD flExtStyle, HFONT hFont, LPSTR pszText)
|
||
{
|
||
/*******************************/
|
||
/* Return unsupported function */
|
||
/*******************************/
|
||
|
||
return -1;
|
||
}
|
||
|
||
/******************************************************************************\
|
||
*
|
||
* FUNCTION: CustomControlInfoA
|
||
*
|
||
* INPUTS: acci - pointer to an array od CCINFOA structures
|
||
*
|
||
* RETURNS: Number of controls supported by this DLL
|
||
*
|
||
* COMMENTS: See CUSTCNTL.H for more info
|
||
*
|
||
\******************************************************************************/
|
||
|
||
UINT CALLBACK
|
||
CustomControlInfoA (LPCCINFOA acci)
|
||
{
|
||
/***********************************************/
|
||
/* Are we being asked to fill out a structure? */
|
||
/***********************************************/
|
||
|
||
if ( acci )
|
||
{
|
||
/***********************/
|
||
/* Setup the structure */
|
||
/***********************/
|
||
|
||
acci->flOptions = 0;
|
||
acci->cxDefault = 40; // default width (dialog units)
|
||
acci->cyDefault = 60; // default height (dialog units)
|
||
acci->flStyleDefault = WS_CHILD | WS_VISIBLE;
|
||
acci->flExtStyleDefault = 0;
|
||
acci->flCtrlTypeMask = 0;
|
||
acci->cStyleFlags = nHelpIndexStyleFlags;
|
||
acci->aStyleFlags = aHelpIndexStyleFlags;
|
||
acci->lpfnStyle = HelpIndexStyle;
|
||
acci->lpfnSizeToText = HelpIndexSizeToText;
|
||
acci->dwReserved1 = 0;
|
||
acci->dwReserved2 = 0;
|
||
|
||
/********************/
|
||
/* Copy the strings */
|
||
/********************/
|
||
|
||
_ftcsnccpy( acci->szClass, szHelpIndexClass, sizeof(acci->szClass)-1 );
|
||
_ftcsnccpy( acci->szDesc, szHelpIndexDesc, sizeof(acci->szDesc)-1 );
|
||
_ftcsnccpy( acci->szTextDefault, szHelpIndexDefault,
|
||
sizeof(acci->szTextDefault)-1 );
|
||
}
|
||
|
||
/*******************************************************/
|
||
/* Return the number of controls that the DLL supports */
|
||
/*******************************************************/
|
||
|
||
return 1;
|
||
}
|
||
#else
|
||
/******************************************************************************\
|
||
*
|
||
* CustomControlInfo() -- see CUSTCNTL.H for more info
|
||
*
|
||
\******************************************************************************/
|
||
|
||
HANDLE CALLBACK __export
|
||
CustomControlInfo ()
|
||
{
|
||
HANDLE hMem;
|
||
LPCTLINFO pctlinfo;
|
||
|
||
//Allocate a CTLINFO struct
|
||
hMem=GlobalAlloc(GMEM_MOVEABLE, sizeof(CTLINFO));
|
||
|
||
if (hMem==NULL)
|
||
return NULL;
|
||
|
||
//Get the pointers we need.
|
||
pctlinfo=(LPCTLINFO)GlobalLock(hMem);
|
||
|
||
if (pctlinfo==NULL)
|
||
{
|
||
GlobalFree(hMem);
|
||
return NULL;
|
||
}
|
||
|
||
//Set the overall control info.
|
||
pctlinfo->wVersion=0100;
|
||
pctlinfo->wCtlTypes=1;
|
||
_ftcsnccpy( pctlinfo->szClass, szHelpIndexClass, sizeof (pctlinfo->szClass) );
|
||
pctlinfo->szClass[sizeof (pctlinfo->szClass) - 1] = 0;
|
||
_ftcsnccpy( pctlinfo->szTitle, _TEXT("profile.ini|helpfile.hlp"), sizeof (pctlinfo->szTitle) );
|
||
pctlinfo->szTitle[sizeof (pctlinfo->szTitle) - 1] = 0;
|
||
|
||
//Set the types
|
||
pctlinfo->Type[0].wType = 0;
|
||
pctlinfo->Type[0].wWidth = 40;
|
||
pctlinfo->Type[0].wHeight = 60;
|
||
pctlinfo->Type[0].dwStyle = WS_CHILD | WS_VISIBLE | HS_LINES;
|
||
_ftcsnccpy( pctlinfo->Type[0].szDescr, szHelpIndexDesc,
|
||
sizeof (pctlinfo->Type[0].szDescr) );
|
||
pctlinfo->Type[0].szDescr[sizeof (pctlinfo->Type[0].szDescr) - 1] = 0;
|
||
|
||
//Give the memory to the Dialog Editor.
|
||
GlobalUnlock(hMem);
|
||
return hMem;
|
||
}
|
||
#endif // #ifdef _WIN32
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* RegisterWindowClass()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
BOOL
|
||
RegisterWindowClass()
|
||
{
|
||
BOOL bSuccess = TRUE;
|
||
|
||
if ( !nRegistered++ )
|
||
{
|
||
WNDCLASS wndclass;
|
||
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
|
||
wndclass.lpfnWndProc = HelpIndexWndProc;
|
||
wndclass.cbClsExtra = 0;
|
||
wndclass.cbWndExtra = sizeof(LPHELPINDEX);
|
||
wndclass.hInstance = hInstance;
|
||
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW );
|
||
wndclass.hbrBackground = GetStockObject( LTGRAY_BRUSH );
|
||
wndclass.lpszMenuName = NULL;
|
||
wndclass.lpszClassName = szHelpIndexClass;
|
||
|
||
#ifdef _WIN32
|
||
bSuccess = RegisterClass( &wndclass ) != INVALID_ATOM;
|
||
#else
|
||
bSuccess = RegisterClass( &wndclass ) != NULL;
|
||
#endif // #ifdef _WIN32
|
||
}
|
||
|
||
return( bSuccess );
|
||
}
|
||
|
||
|
||
/******************************************************************************\
|
||
* *
|
||
* UnregisterWindowClass()
|
||
* *
|
||
\******************************************************************************/
|
||
|
||
BOOL
|
||
UnregisterWindowClass()
|
||
{
|
||
BOOL bSuccess = TRUE;
|
||
|
||
if ( !--nRegistered )
|
||
bSuccess = UnregisterClass( szHelpIndexClass, hInstance );
|
||
|
||
return( bSuccess );
|
||
}
|
||
|
||
|
||
#ifdef _WIN32
|
||
/******************************************************************************\
|
||
*
|
||
* FUNCTION: DLLEntryPoint
|
||
*
|
||
* INPUTS: hDLL - DLL module handle
|
||
* dwReason - reason being called (e.g. process attaching)
|
||
* lpReserved - reserved
|
||
*
|
||
* RETURNS: TRUE if initialization passed, or
|
||
* FALSE if initialization failed.
|
||
*
|
||
* COMMENTS: On DLL_PROCESS_ATTACH registers the HelpIndex class
|
||
*
|
||
* DLL initialization serialization is guaranteed within a
|
||
* process (if multiple threads then DLL entry points are
|
||
* serialized), but is not guaranteed across processes.
|
||
*
|
||
* When synchronization objects are created, it is necesaary
|
||
* to check the return code of GetLastError even if the create
|
||
* call succeeded. If the object existed, ERROR_ALREADY_EXISTED
|
||
* will be returned.
|
||
*
|
||
* If your DLL uses any C runtime functions then you should
|
||
* always call _CRT_INIT so that the C runtime can initialize
|
||
* itself appropriately. Failure to do this may result in
|
||
* indeterminate behavior. When the DLL entry point is called
|
||
* for DLL_PROCESS_ATTACH & DLL_THREAD_ATTACH circumstances,
|
||
* _CRT_INIT should be called before any other initilization
|
||
* is performed. When the DLL entry point is called for
|
||
* DLL_PROCESS_DETACH & DLL_THREAD_DETACH circumstances,
|
||
* _CRT_INIT should be called after all cleanup has been
|
||
* performed, i.e. right before the function returns.
|
||
*
|
||
\******************************************************************************/
|
||
|
||
/******************************************************/
|
||
/* BOOL WINAPI DLLEntryPoint( HANDLE, DWORD, LPVOID ) */
|
||
/******************************************************/
|
||
|
||
BOOL WINAPI _CRT_INIT (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved);
|
||
|
||
BOOL WINAPI
|
||
DLLEntryPoint( HANDLE hDLL, DWORD dwReason, LPVOID lpReserved )
|
||
{
|
||
BOOL bStatus = TRUE;
|
||
hInstance = (HINSTANCE)hDLL; // Save the DLL module handle.
|
||
|
||
|
||
switch ( dwReason )
|
||
{
|
||
case DLL_PROCESS_ATTACH:
|
||
{
|
||
if ( bStatus = _CRT_INIT(hDLL, dwReason, lpReserved) )
|
||
{
|
||
if ( !RegisterWindowClass() )
|
||
{
|
||
mprintf(MB_OK, IDS_ERROR_REGISTERCLASS, szNull);
|
||
//_TEXT("Failed to register Window Class!") );
|
||
bStatus = FALSE;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
case DLL_PROCESS_DETACH:
|
||
{
|
||
if ( !UnregisterWindowClass() )
|
||
{
|
||
mprintf(MB_OK, IDS_ERROR_UNREGISTERCLASS, szNull);
|
||
// _TEXT("Failed to unregister Window Class!") );
|
||
bStatus = FALSE;
|
||
}
|
||
bStatus = _CRT_INIT(hDLL, dwReason, lpReserved);
|
||
break;
|
||
}
|
||
|
||
default:
|
||
{
|
||
bStatus = _CRT_INIT(hDLL, dwReason, lpReserved);
|
||
break;
|
||
}
|
||
}
|
||
|
||
return bStatus;
|
||
}
|
||
#else
|
||
/*
|
||
* LibMain
|
||
*
|
||
* Purpose:
|
||
* DLL-specific entry point called from LibEntry. Initializes
|
||
* the DLL's heap and registers the HelpIndex custom control
|
||
* class.
|
||
*
|
||
* Parameters:
|
||
* hInstance HANDLE instance of the DLL.
|
||
* wDataSeg WORD segment selector of the DLL's data segment.
|
||
* wHeapSize WORD byte count of the heap.
|
||
* lpCmdLine LPSTR to command line used to start the module.
|
||
*
|
||
* Return Value:
|
||
* HANDLE Instance handle of the DLL.
|
||
*
|
||
*/
|
||
|
||
HANDLE FAR PASCAL LibMain(HANDLE hDLL, WORD wDataSeg,
|
||
WORD cbHeapSize, LPSTR lpCmdLine)
|
||
{
|
||
hInstance = (HINSTANCE)hDLL; // Save the DLL module handle.
|
||
if ( !RegisterWindowClass() )
|
||
{
|
||
mprintf( MB_OK, _TEXT("Failed to register Window Class!") );
|
||
hInstance = NULL;
|
||
}
|
||
if (hInstance && (0!=cbHeapSize))
|
||
UnlockData(0);
|
||
return hInstance;
|
||
}
|
||
#endif // #ifdef _WIN32
|
||
|
||
|
||
/* ===========================================================================
|
||
FUNCTIONS THAT VIRTUALIZE THE INDEX FILE FOR 16-BIT IMPLEMENTATIONS
|
||
=========================================================================== */
|
||
|
||
|
||
/* ===========================================================================
|
||
GetHelpItemData
|
||
|
||
Copies the read-only fields of an index file record to a buffer supplied by
|
||
the caller. Writable fields cannot be accessed through this function, which
|
||
does not modify these fields in the destination buffer. The writable fields
|
||
have their own read/write interfaces in the form of
|
||
GetHelpItemXxxx()/SetHelpItemXxxx() function pairs.
|
||
--------------------------------------------------------------------------- */
|
||
|
||
static BOOL // spec'd data was copied to dest buf
|
||
GetHelpItemData (
|
||
HELPINDEXITEM FAR * phelpitem, // ptr struct to fill with item data
|
||
HELPINDEX FAR * phdx, // browse context obj for curr window
|
||
LONG nFilePos, // 0-rel item index within index file
|
||
BOOL bStringsToo // T:get scalars, strings F:not strings
|
||
)
|
||
{
|
||
|
||
// request transient copy of index file rec; have data and good dest buf?
|
||
BOOL bRet = FALSE;
|
||
HELPINDEXITEM FAR * phelpitemCached = GetCachedHelpItem (phdx, nFilePos);
|
||
if (phelpitemCached && phelpitem)
|
||
{
|
||
|
||
// yes: success; copy read-only scalars to buf; strings requested too?
|
||
bRet = TRUE;
|
||
phelpitem->nHelpDepth = phelpitemCached->nHelpDepth;
|
||
phelpitem->nHelpTopic = phelpitemCached->nHelpTopic;
|
||
if (bStringsToo)
|
||
{
|
||
|
||
// yes: copy read-only strings to caller's buf
|
||
phelpitemCached->szHelpFile
|
||
[sizeof (phelpitemCached->szHelpFile) - 1] = 0;
|
||
_ftcscpy (phelpitem->szHelpFile, phelpitemCached->szHelpFile);
|
||
phelpitemCached->szHelpTopic
|
||
[sizeof (phelpitemCached->szHelpTopic) - 1] = 0;
|
||
_ftcscpy (phelpitem->szHelpTopic, phelpitemCached->szHelpTopic);
|
||
|
||
}
|
||
|
||
}
|
||
else if (! phelpitemCached)
|
||
{
|
||
mprintf(MB_OK, IDS_ERROR_READINDEX, szNull);
|
||
//_TEXT("Error reading index file!") );
|
||
}
|
||
|
||
// return success/failure code
|
||
return (bRet);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/* ===========================================================================
|
||
GetHelpItemExpanFlag
|
||
SetHelpItemExpanFlag
|
||
GetHelpItemLinesMap
|
||
SetHelpItemLinesMap
|
||
|
||
These functions retrieve and set data elements that -- in the original 32-bit
|
||
version of this program -- were read/write fields in the index file record.
|
||
In this 16-bit implementation, the read/write fields have been "mapped" to a
|
||
memory-resident "overlay"; see the definition of ITEM_RW_OVERLAY for more
|
||
information.
|
||
|
||
[chauv 10/18/93] 16 and 32-bit are now using the same overlay scheme
|
||
--------------------------------------------------------------------------- */
|
||
|
||
static BOOL // spec'd index file item is expanded
|
||
GetHelpItemExpanFlag (
|
||
HELPINDEX FAR * phdx, // browse context obj for curr window
|
||
LONG nFilePos // 0-rel item index within index file
|
||
) {
|
||
|
||
BOOL bRet = FALSE;
|
||
ITEM_RW_OVERLAY FAR * pitemrw = GetHelpItemRWOverlay (phdx, nFilePos);
|
||
if (pitemrw) {
|
||
bRet = ((*pitemrw & ITEMRW_EXPANDED) != 0);
|
||
}
|
||
return (bRet);
|
||
|
||
}
|
||
|
||
static void
|
||
SetHelpItemExpanFlag (
|
||
HELPINDEX FAR * phdx, // browse context obj for curr window
|
||
LONG nFilePos, // 0-rel item index within index file
|
||
BOOL bNewExpandFlag // T:mark item as currently expanded
|
||
) {
|
||
|
||
ITEM_RW_OVERLAY FAR * pitemrw = GetHelpItemRWOverlay (phdx, nFilePos);
|
||
if (pitemrw) {
|
||
if (bNewExpandFlag) {
|
||
*pitemrw |= ITEMRW_EXPANDED;
|
||
} else {
|
||
*pitemrw &= (~ITEMRW_EXPANDED);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
static LONG // maps connec lines through item disp
|
||
GetHelpItemLinesMap (
|
||
HELPINDEX FAR * phdx, // browse context obj for curr window
|
||
LONG nFilePos // 0-rel item index within index file
|
||
) {
|
||
|
||
LONG lRet = 0;
|
||
ITEM_RW_OVERLAY FAR * pitemrw = GetHelpItemRWOverlay (phdx, nFilePos);
|
||
if (pitemrw) {
|
||
lRet = *pitemrw & ITEMRW_LINESMAP;
|
||
}
|
||
return (lRet);
|
||
|
||
}
|
||
|
||
static void
|
||
SetHelpItemLinesMap (
|
||
HELPINDEX FAR * phdx, // browse context obj for curr window
|
||
LONG nFilePos, // 0-rel item index within index file
|
||
LONG lNewLinesMap // columns where vert outline connecs go
|
||
) {
|
||
|
||
ITEM_RW_OVERLAY FAR * pitemrw = GetHelpItemRWOverlay (phdx, nFilePos);
|
||
if (pitemrw) {
|
||
*pitemrw &= (~ITEMRW_LINESMAP);
|
||
*pitemrw |= (lNewLinesMap & ITEMRW_LINESMAP);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/* ===========================================================================
|
||
GetCachedHelpItem
|
||
|
||
Returns a pointer to a buffer which contains a copy of the index file record
|
||
for the specified item. The returned buffer is subject to being recycled
|
||
without notice, so the caller should use or copy the data immediately after
|
||
regaining control.
|
||
--------------------------------------------------------------------------- */
|
||
|
||
// 1-item minicache for use if regular cache can't be allocated
|
||
static HELPINDEXITEM helpitemCacheDegen;
|
||
|
||
static HELPINDEXITEM FAR * // ptr index record; NULL if failed
|
||
GetCachedHelpItem (
|
||
HELPINDEX FAR * phdx, // browse context obj for curr window
|
||
LONG nFilePos // 0-rel item index within index file
|
||
) {
|
||
|
||
// initialize buffer ptr ("none"), cache ptr; has cache been constructed?
|
||
HELPINDEXITEM FAR * pitemRet = NULL;
|
||
HELPINDEXITEM FAR * pitemCache = phdx->pIndexItemCache;
|
||
if (pitemCache == NULL) {
|
||
|
||
// no: try to alloc cache memory; success?
|
||
// [chauv] fixed uninitialize memory problem by calling GAllocLock(..,TRUE) to do zeroinit
|
||
pitemCache = GAllocLock (BYTES_PER_CACHE, TRUE);
|
||
phdx->pIndexItemCache = pitemCache;
|
||
if (pitemCache != NULL) {
|
||
|
||
// yes: mark pages unmapped, set up arbitrary recency ordering
|
||
int nPage = 0;
|
||
while (nPage < PAGES_PER_CACHE) {
|
||
PAGEINFO FAR * ppginfo = &phdx->pageinfo[nPage];
|
||
ppginfo->nBasePos = -1;
|
||
ppginfo->nNewerPage = (nPage == 0)
|
||
? PAGES_PER_CACHE - 1 : nPage - 1;
|
||
ppginfo->nOlderPage = (nPage == PAGES_PER_CACHE - 1)
|
||
? 0 : nPage + 1;
|
||
nPage++;
|
||
}
|
||
phdx->nNewestPage = 0;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
// was cache available or is it now?
|
||
if (pitemCache != NULL) {
|
||
|
||
// initiate walk of recency chain starting with most-recently-used page
|
||
int nTry = phdx->nNewestPage;
|
||
PAGEINFO FAR * ppginfo;
|
||
while ((pitemRet == NULL) && (nTry >= 0)
|
||
&& ((ppginfo = &phdx->pageinfo[nTry])->nBasePos >= 0)) {
|
||
|
||
// have mapped page; does desired rec fall in mapped area of file?
|
||
int nPosInTryPage = (int)nFilePos - ppginfo->nBasePos;
|
||
if ((0 <= nPosInTryPage) && (nPosInTryPage < ITEMS_PER_PAGE)) {
|
||
|
||
// yes: save buf ptr; was found page already most recent page?
|
||
pitemRet = &pitemCache[nTry * ITEMS_PER_PAGE + nPosInTryPage];
|
||
if (nTry != phdx->nNewestPage) {
|
||
|
||
// no: unlink it from current place in recency chain
|
||
PAGEINFO FAR * ppginfoNewer
|
||
= &phdx->pageinfo[ppginfo->nNewerPage];
|
||
PAGEINFO FAR * ppginfoOlder
|
||
= &phdx->pageinfo[ppginfo->nOlderPage];
|
||
ppginfoNewer->nOlderPage = ppginfo->nOlderPage;
|
||
ppginfoOlder->nNewerPage = ppginfo->nNewerPage;
|
||
|
||
// relink found page as most recent
|
||
ppginfo->nOlderPage = phdx->nNewestPage;
|
||
ppginfoOlder = &phdx->pageinfo[ppginfo->nOlderPage];
|
||
ppginfo->nNewerPage = ppginfoOlder->nNewerPage;
|
||
ppginfoNewer = &phdx->pageinfo[ppginfo->nNewerPage];
|
||
ppginfoOlder->nNewerPage = nTry;
|
||
ppginfoNewer->nOlderPage = nTry;
|
||
|
||
// record new most recent page in browse context object
|
||
phdx->nNewestPage = nTry;
|
||
|
||
}
|
||
} else {
|
||
|
||
// if have now searched all pages in cache, stop trying
|
||
if ((nTry = ppginfo->nOlderPage) == phdx->nNewestPage) {
|
||
nTry = -1;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
// was the desired entry mapped into any cache page?
|
||
if (pitemRet == NULL) {
|
||
|
||
// no: remap oldest page, make it newest (chain need not change)
|
||
int nPage = phdx->pageinfo[phdx->nNewestPage].nNewerPage;
|
||
int nPosInPage = (int)nFilePos % ITEMS_PER_PAGE;
|
||
int nBasePos = (int)nFilePos - nPosInPage;
|
||
ppginfo = &phdx->pageinfo[nPage];
|
||
ppginfo->nBasePos = -1;
|
||
if (LZSeek (phdx->hfileIndex, phdx->nHdrBytesCt
|
||
+ ((LONG)nBasePos * sizeof(HELPINDEXITEM)), 0) >= 0) {
|
||
int nReadCt = LZRead (phdx->hfileIndex
|
||
, (LPSTR)(&(pitemCache[nPage * ITEMS_PER_PAGE])), BYTES_PER_PAGE);
|
||
if (nReadCt >= (nPosInPage + 1) * (int)sizeof(HELPINDEXITEM)) {
|
||
ppginfo->nBasePos = nBasePos;
|
||
phdx->nNewestPage = nPage;
|
||
pitemRet= &pitemCache[nPage * ITEMS_PER_PAGE + nPosInPage];
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
// if desired page wasn't and could not be mapped, try read into minicache
|
||
if (pitemRet == NULL) {
|
||
if (LZSeek (phdx->hfileIndex, phdx->nHdrBytesCt
|
||
+ (nFilePos * sizeof (HELPINDEXITEM)), 0) >= 0) {
|
||
if (LZRead (phdx->hfileIndex, (LPSTR)(&helpitemCacheDegen)
|
||
, sizeof (HELPINDEXITEM)) == sizeof (HELPINDEXITEM)) {
|
||
pitemRet = &helpitemCacheDegen;
|
||
}
|
||
}
|
||
}
|
||
|
||
// return buf ptr or NULL for failure
|
||
return (pitemRet);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/* ===========================================================================
|
||
GetHelpItemRWOverlay
|
||
|
||
Returns a pointer to the specified index item's entry in the index file's
|
||
read/write overlay. See ITEM_RW_OVERLAY for more information.
|
||
--------------------------------------------------------------------------- */
|
||
|
||
static ITEM_RW_OVERLAY FAR * // ptr overlay entry; NULL if out of rg
|
||
GetHelpItemRWOverlay (
|
||
HELPINDEX FAR * phdx, // browse context obj for curr window
|
||
LONG nFilePos // 0-rel item index within index file
|
||
) {
|
||
|
||
ITEM_RW_OVERLAY FAR * pitemrwRet = NULL;
|
||
if ((0 <= nFilePos) && (nFilePos < phdx->nHelpItemCt)) {
|
||
pitemrwRet = phdx->pIndexRWOverlay + nFilePos;
|
||
}
|
||
return (pitemrwRet);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/* ===========================================================================
|
||
GAllocLock
|
||
|
||
Encapsulates a GlobalAlloc()/GlobalLock() sequence.
|
||
--------------------------------------------------------------------------- */
|
||
|
||
static void FAR *
|
||
GAllocLock (DWORD dwByteCt, BOOL bInitToZero)
|
||
{
|
||
|
||
void FAR * pvRet = NULL;
|
||
HANDLE h = GlobalAlloc((bInitToZero ? (GHND) : (GMEM_MOVEABLE)), dwByteCt);
|
||
if (h)
|
||
{
|
||
if ((pvRet = GlobalLock (h)) == NULL)
|
||
GlobalFree (h);
|
||
}
|
||
return (pvRet);
|
||
|
||
}
|
||
|
||
// ****************************************************************************
|
||
// Get Registry string stub function
|
||
//
|
||
// Return value is the return value of RegOpenKeyEx() or RegQueryValueEx().
|
||
// except for when lpszDefault is valid and lpszSection is NULL, it returns
|
||
// ERROR_SUCCESS.
|
||
//
|
||
DWORD GetRegistryString(LPCTSTR lpszSection, LPCTSTR lpszKey, LPCTSTR lpszDefault,
|
||
LPTSTR lpszReturnBuffer, DWORD cchReturnBuffer, LPCTSTR lpszFile)
|
||
{
|
||
#ifdef _WIN32
|
||
DWORD dw = (DWORD)(~ERROR_SUCCESS);
|
||
DWORD dwType = REG_SZ;
|
||
HKEY hKey;
|
||
|
||
dw = RegOpenKeyEx(HKEY_CURRENT_USER, lpszSection, 0, KEY_ALL_ACCESS, &hKey);
|
||
if (dw == ERROR_SUCCESS)
|
||
{
|
||
dw = (DWORD)RegQueryValueEx(hKey, (LPTSTR)lpszKey, NULL, &dwType, lpszReturnBuffer, &cchReturnBuffer);
|
||
RegCloseKey(hKey);
|
||
}
|
||
if ( (dw != ERROR_SUCCESS) && (lpszDefault) )
|
||
_tcsncpy(lpszReturnBuffer, lpszDefault, cchReturnBuffer);
|
||
return dw;
|
||
#else
|
||
return (DWORD)GetPrivateProfileString(lpszSection, lpszKey, lpszDefault,
|
||
lpszReturnBuffer, cchReturnBuffer, lpszFile);
|
||
#endif
|
||
}
|
||
|
||
// ****************************************************************************
|
||
// Write Registry string stub function
|
||
BOOL WriteRegistryString(LPCTSTR lpszSection, LPCTSTR lpszKey,
|
||
LPCTSTR lpszString, LPCTSTR lpszFile)
|
||
{
|
||
#ifdef _WIN32
|
||
LONG l = ~ERROR_SUCCESS;
|
||
HKEY hKey;
|
||
|
||
if (lpszSection && *lpszSection)
|
||
{
|
||
if (RegCreateKey(HKEY_CURRENT_USER, lpszSection, &hKey) == ERROR_SUCCESS)
|
||
{
|
||
if (lpszKey && *lpszKey && lpszString)
|
||
l = RegSetValueEx(hKey, (LPTSTR)lpszKey, 0, REG_SZ, lpszString, _ftcslen(lpszString) + sizeof(TCHAR));
|
||
}
|
||
RegCloseKey(hKey);
|
||
}
|
||
return (BOOL)(l == ERROR_SUCCESS);
|
||
#else
|
||
return WritePrivateProfileString(lpszSection, lpszKey, lpszString, lpszFile);
|
||
#endif
|
||
}
|
||
|
||
// ****************************************************************************
|
||
static BOOL ExpandHelpTopic(LPHELPINDEX lpHelpIndex, LPHELPINDEXITEM lpHelpItem)
|
||
{
|
||
HCURSOR hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
||
BOOL bSkip = TRUE;
|
||
HWND hListbox = lpHelpIndex->hListbox;
|
||
|
||
if (hListbox)
|
||
{
|
||
if ( lpHelpIndex && (lpHelpIndex->nHelpItemCt > 0) && (lpHelpItem->szHelpFile[0] || lpHelpItem->szHelpTopic[0]) )
|
||
{
|
||
LONG nPos, pos, ndepth, opened;
|
||
HELPINDEXITEM helpitem;
|
||
|
||
// ******** find matching help topic/help file
|
||
bSkip = FALSE;
|
||
pos = 0;
|
||
while ((pos < lpHelpIndex->nHelpItemCt) && !bSkip)
|
||
{
|
||
if (GetHelpItemData (&helpitem, lpHelpIndex, pos, TRUE))
|
||
{
|
||
// if topic id is not zero try to match JumpHashID(). Otherwise, try to match
|
||
// topic title
|
||
if (lpHelpItem->nHelpTopic)
|
||
{
|
||
if (helpitem.nHelpTopic == lpHelpItem->nHelpTopic) // matched topic
|
||
{
|
||
if (_tcsicmp(helpitem.szHelpFile, lpHelpItem->szHelpFile) == 0) // matched helpfile
|
||
break; // found them both
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (_tcsicmp(helpitem.szHelpTopic, lpHelpItem->szHelpTopic) == 0)
|
||
break;
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
else
|
||
bSkip = TRUE;
|
||
}
|
||
if (pos == lpHelpIndex->nHelpItemCt) // didn't find a match in the list.
|
||
bSkip = TRUE;
|
||
// ******** ====> impotant note !!!!!!!!
|
||
// dependencies for next loop - DON'T CHANGE in the middle
|
||
// pos, helpitem,...
|
||
ndepth = helpitem.nHelpDepth;
|
||
|
||
// ******** found topic, refresh the listbox
|
||
if ((pos < lpHelpIndex->nHelpItemCt) && !bSkip)
|
||
{
|
||
LONG d;
|
||
ListBox_ResetContent(hListbox);
|
||
SendMessage(hListbox, WM_SETREDRAW, 0, 0);
|
||
|
||
// ******** start at pos and go backward
|
||
nPos = pos;
|
||
d = ndepth;
|
||
// there should be only one book/chapter that's expanded and it should be one level
|
||
// above the search topic.
|
||
opened = ndepth - 1;
|
||
while ((nPos >= 0) && !bSkip)
|
||
{
|
||
if (GetHelpItemData (&helpitem, lpHelpIndex, nPos, FALSE))
|
||
{
|
||
if (helpitem.nHelpDepth <= d)
|
||
{
|
||
if (helpitem.nHelpDepth == opened)
|
||
{
|
||
opened--;
|
||
SetHelpItemExpanFlag(lpHelpIndex, nPos, TRUE);
|
||
}
|
||
else if (helpitem.nHelpTopic == 0)
|
||
SetHelpItemExpanFlag(lpHelpIndex, nPos, FALSE);
|
||
// since we are going backward, always insert string at the beginning.
|
||
ListBox_InsertString(hListbox, 0, (LPVOID)nPos);
|
||
d = helpitem.nHelpDepth;
|
||
}
|
||
nPos--;
|
||
}
|
||
else bSkip = TRUE;
|
||
}
|
||
// ******** start at pos (not including pos) and go foward
|
||
nPos = pos + 1;
|
||
d = ndepth;
|
||
// get the count so we can select this item when appropriate items have been expanded.
|
||
pos = ListBox_GetCount(hListbox) - 1; // subtract 1 because it's zero base
|
||
while ((nPos < lpHelpIndex->nHelpItemCt) && !bSkip)
|
||
{
|
||
if (GetHelpItemData (&helpitem, lpHelpIndex, nPos, FALSE))
|
||
{
|
||
if (helpitem.nHelpDepth <= d)
|
||
{
|
||
if (helpitem.nHelpTopic == 0)
|
||
SetHelpItemExpanFlag(lpHelpIndex, nPos, FALSE);
|
||
// since we are going forward, always insert string at the end.
|
||
ListBox_InsertString(hListbox, -1, (LPVOID)nPos);
|
||
d = helpitem.nHelpDepth;
|
||
}
|
||
nPos++;
|
||
}
|
||
else bSkip = TRUE;
|
||
}
|
||
SendMessage(hListbox, WM_SETREDRAW, 1, 0);
|
||
InvalidateRect(hListbox, NULL, TRUE);
|
||
if (!bSkip)
|
||
ListBox_SetCurSel(hListbox, pos );
|
||
}
|
||
}
|
||
}
|
||
SetCursor( hOldCursor );
|
||
return (BOOL)(!bSkip);
|
||
}
|
||
|
||
|
||
//******************************************************************************
|
||
void ProcessHelpSearch(HWND hWnd, LPHELPINDEX lpHelpIndex, LONG nFilePos, UINT nListPos )
|
||
{
|
||
HELPINDEXITEM helpitem;
|
||
LPSTR lpHelpFile;
|
||
UINT fuCommand = HELP_SEARCH;
|
||
|
||
if ( hWnd && lpHelpIndex && (nFilePos >= 0) && (nFilePos < lpHelpIndex->nHelpItemCt) && (nListPos >= 0) )
|
||
{
|
||
if ( GetValidHelpFilePos((HELPINDEXITEM FAR *)&helpitem, lpHelpIndex, nFilePos) >= 0 )
|
||
{
|
||
TCHAR szSection[_MAX_FNAME];
|
||
TCHAR szBuf[_MAX_FNAME];
|
||
|
||
// check to see if the help file has full text search capability
|
||
wsprintf(szSection, "%s\\%s\\%s", szRegistryKey, szProduct, szContentsSection);
|
||
GetRegistryString(szSection, cszFTSFiles, szNull, szBuf, sizeof(szBuf), lpHelpIndex->szProfile );
|
||
if (_tcsstr(_tcslwr(szBuf), _tcslwr(helpitem.szHelpFile)) )
|
||
fuCommand = HELP_FTSEARCH;
|
||
|
||
lpHelpFile = HelpLookup(hWnd, lpHelpIndex, helpitem.szHelpFile, cszHLPKey);
|
||
// if lpHelpFile is NULL, the user cancelled the help lookup
|
||
// if lpHelpFile is pointed to a null string, can't find registry value but don't
|
||
// need to report error here because HelpLookup() has already done so.
|
||
if (lpHelpFile == NULL)
|
||
return;
|
||
if (*lpHelpFile)
|
||
{
|
||
CallHelp(lpHelpIndex->hListbox, lpHelpFile, fuCommand, helpitem.nHelpTopic);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
// if it gets here, we must do default search
|
||
lpHelpFile = HelpLookup(hWnd, lpHelpIndex, "contents.hlp", cszHLPKey);
|
||
// if lpHelpFile is NULL, the user cancelled the help lookup
|
||
// if lpHelpFile is pointed to a null string, can't find registry value but don't
|
||
// need to report error here because HelpLookup() has already done so.
|
||
if (lpHelpFile && *lpHelpFile)
|
||
{
|
||
CallHelp(lpHelpIndex->hListbox, lpHelpFile, fuCommand, helpitem.nHelpTopic);
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
// ****************************************************************************
|
||
// returns -1 if failed
|
||
static long GetValidHelpFilePos(HELPINDEXITEM FAR * lphelpitem, LPHELPINDEX lpHelpIndex, long pos)
|
||
{
|
||
HCURSOR hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
||
|
||
if ( lpHelpIndex && (lpHelpIndex->nHelpItemCt > 0) )
|
||
{
|
||
// ******** find next valid help filename
|
||
while (pos < lpHelpIndex->nHelpItemCt)
|
||
{
|
||
if (GetHelpItemData (lphelpitem, lpHelpIndex, pos, TRUE))
|
||
{
|
||
if (_tcslen(lphelpitem->szHelpFile) > 1)
|
||
break;
|
||
pos++;
|
||
}
|
||
else
|
||
{
|
||
pos = -1;
|
||
break;
|
||
}
|
||
}
|
||
if (pos >= lpHelpIndex->nHelpItemCt)
|
||
pos = -1;
|
||
}
|
||
else
|
||
pos = -1;
|
||
SetCursor( hOldCursor );
|
||
return pos;
|
||
}
|
||
|
||
// ****************************************************************************
|
||
BOOL IsQuickReference(void)
|
||
{
|
||
TCHAR szReg[MAX_PATH+2];
|
||
TCHAR szReturn[MAX_PATH+2];
|
||
|
||
wsprintf(szReg, _T("%s\\%s\\%s"), szRegistryKey, szProduct, szContentsSection);
|
||
GetRegistryString(szReg, szCurrentBookset, _TEXT("0"), szReturn, sizeof(szReturn), szNull);
|
||
wsprintf(szReg, _T("%s\\%s\\%s\\%s"), szRegistryKey, szProduct, szContentsSection, szReturn);
|
||
GetRegistryString(szReg, _TEXT("QuickReference"), _TEXT("0"), szReturn, sizeof(szReturn), szNull);
|
||
// don't really need to call atol() here. This is quicker...
|
||
if (szReturn[0] == _TEXT('1'))
|
||
return TRUE;
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
/*EOF*/
|