www.pudn.com > helpview.zip > Search.c, change:1997-10-15,size:35329b


/* 
  
Copyright 1997 Willows Software, Inc.  
 
This library is free software; you can redistribute it and/or 
modify it under the terms of the GNU Library General Public License as 
published by the Free Software Foundation; either version 2 of the 
License, or (at your option) any later version. 
 
This library is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
Library General Public License for more details. 
 
You should have received a copy of the GNU Library General Public 
License along with this library; see the file COPYING.LIB.  If 
not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
Cambridge, MA 02139, USA. 
 
*/ 
 
/************************************************************************* 
* 
* SEARCH.C 
* Search dialog box routines.      
* 
* Author: Paul E. Kissel 
* 
**************************************************************************/ 
 
/*********************************** 
** 
**  System Includes 
** 
***********************************/ 
#include <string.h> 
#include <ctype.h> 
 
 
/*********************************** 
** 
**  App. Includes 
** 
***********************************/ 
#include "hlpfile.h" 
#include "display.h" 
#include "wnddata.h" 
#include "globals.h" 
#include "twhlprc.h" 
#include "search.h" 
 
 
/*********************************** 
** 
**  Private Defines 
** 
***********************************/ 
 
#define EDITKEYWORDOLDPROC "EditKeywordOldProc" 
 
/*  
** Data stored for each search window 
** managed by the DLL. 
*/ 
typedef struct tagSEARCHWNDDATA 
{ 
  char       chKey;                 /* Keyword MULTIKEY character to use. */ 
  char * KeywordPtr;          /* Keyword to initially use. */ 
  HWND       hDataWnd;              /* Main help window used for storage of general data. */ 
  HGLOBAL    hHelpFileInfo;         /* Help file containing the keyword/topic data. */ 
  DWORD      dwKWDATAOffset;        /* Offset of keyword's topics in KWDATA table. */ 
  BOOL       bInTopicList;          /* Are we in the topic's list. */ 
} 
SEARCHWNDDATA; 
typedef SEARCHWNDDATA * FPSEARCHWNDDATA; 
typedef HGLOBAL HSEARCHWNDDATA; 
 
 
/*  
** Data stored for each keyword edit 
** control in the dialog box. 
*/ 
typedef struct tagEDITSEARCHWNDDATA 
{ 
  HWND    hDlgWnd;     /* Handle of dialog box containing edit control. */ 
  WNDPROC OldWndProc;  /* Edit control's old window procedure before subclassing. */ 
} 
EDITSEARCHWNDDATA; 
typedef EDITSEARCHWNDDATA * EDITSEARCHWNDDATAPTR; 
 
 
/*********************************** 
** 
**  Private Function Prototypes 
** 
***********************************/ 
 
BOOL CALLBACK SearchDlgProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); 
static BOOL GotoSearchTopic( FPSEARCHWNDDATA fpSearchWndData, DWORD dwTopicCharOffset ); 
static void CloseUpDialog( HWND hWnd ); 
static BOOL ShowSearchTopics( HWND hWnd,  HGLOBAL hHelpFileInfo, DWORD dwKeyWordIndex, DWORD * dwKWDATAOffset ); 
static void ShowEditKeyword( HWND hWnd, WORD wKeyWordIndex ); 
static void SelectClosestKeyword( HWND hWnd ); 
LRESULT CALLBACK EditKeywordWndProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); 
static void SelectFirstTopic( HWND hWnd ); 
static BOOL ShowTopics( HWND hWnd, DWORD dwSelected ); 
 
                             
/*********************************************************************************** 
** 
**                              Shared Functions 
** 
************************************************************************************/ 
 
 
/********************************************************** 
**   
**  HELP_KEY message 
** 
**  Looks for the specified keyword in the 'K' keyword  
**  list. 
** 
**  If the keyword is found and it only has at least one 
**  topic associated with it, the topic's character offset 
**  position in the help file is stored. 
** 
**  Returns: 
** 
**      TRUE: Success. 
**     FALSE: Failure. 
** 
***********************************************************/ 
BOOL GetKeywordOffset 
(  
  HWND hDataWnd,  
  char * szHelpFilePath,  
  char * szKeyword,  
  DWORD * dwTopicCharOffset 
) 
{ 
  HGLOBAL hHelpFileInfo;        /* Handle to the help file's general info. */ 
  WORD    wFoundTopics;         /* Number of topics associated with the keyword. */ 
 
 
  /* Open and load the help file's info. */ 
  hHelpFileInfo = OpenHelpFile( hDataWnd, szHelpFilePath ); 
  if( hHelpFileInfo == NULL ) 
  { 
    /* Failure. */ 
    return( FALSE ); 
  } 
  
  /* Load the keyword data. */ 
  if( ! LoadKeywordData( hDataWnd, 'K', hHelpFileInfo ) ) 
  { 
    /* Failed. */ 
    return( FALSE ); 
  } 
 
  /* Get the number of topics for the keyword. */ 
  wFoundTopics = GetKeyTopic( hDataWnd, hHelpFileInfo, szKeyword, dwTopicCharOffset ); 
 
  /* Free any file info. that we loaded into memory. */ 
  FreeKeywordData( hHelpFileInfo ); 
         
  /* If no topics found. */ 
  if( wFoundTopics == 0 ) 
  { 
    /* Failed. */ 
    return( FALSE ); 
  } 
     
  /* Success. */ 
  return( TRUE ); 
} 
  
 
 
 
/********************************************************** 
**   
**  HELP_KEY message 
** 
**  Looks for the specified keyword in the 'K' keyword  
**  list. 
** 
**  If the keyword is found and it only has one topic 
**  associated with it, the topic is displayed. 
** 
**  If there is more than one match, displays 
**  the Search dialog box and the the topics.  
**   
***********************************************************/ 
BOOL DoHelpKey_PartialKeyMsg( HWND hWnd, UINT SrchMsg, HGLOBAL hHelpParams, FPHELPPARAMS fpHelpParams ) 
{ 
  SEARCHWNDDATA SearchWndData; 
 
  HGLOBAL hTopicData;           /* Handle to the topic's elements list. */                 
  HGLOBAL hHelpFileInfo;        /* Handle to the help file's general info. */ 
  DWORD   dwTopicCharOffset;    /* Location of topic data. */ 
  WORD    wFoundTopics;         /* Number of topics associated with the keyword. */ 
 
  char * KeywordPtr;      /* Pointer to the keyword string. */ 
   
  short int nResult; 
 
  HWND hMainTopicWnd;           /* Window handle for the main topic window. */ 
                       
  BOOL bDlgAlreadyDisplayed;    /* Is the dialog already being displayed. */ 
   
                       
  /* Open and load the help file's info. */ 
  hHelpFileInfo = OpenHelpFile( hWnd, fpHelpParams->Path ); 
  if( hHelpFileInfo == NULL ) 
  { 
    /* Unlock handle to message stucture. */ 
    GlobalUnlock( hHelpParams ); 
         
    /* Failure. */ 
    return( FALSE ); 
  } 
  
  /* Load the keyword data. */ 
  if( ! LoadKeywordData( hWnd, 'K', hHelpFileInfo ) ) 
  { 
    /* Unlock handle to message stucture. */ 
    GlobalUnlock( hHelpParams ); 
         
    /* Failed. */ 
    return( FALSE ); 
  } 
 
  /* Get a pointer to the keyword string. */ 
  KeywordPtr =  (char *) ( (BYTE *)fpHelpParams + fpHelpParams->ExtraDataOffset ); 
 
  /* Get the number of topics for the keyword. */ 
  wFoundTopics = GetKeyTopic( hWnd, hHelpFileInfo, KeywordPtr, &dwTopicCharOffset ); 
 
  /* If no topics found and HELP_KEY. */ 
  if( wFoundTopics == 0 && SrchMsg == HELP_KEY ) 
  { 
    /* Free any file info. that we loaded into memory. */ 
    FreeKeywordData( hHelpFileInfo ); 
     
    /* Unlock handle to message stucture. */ 
    GlobalUnlock( hHelpParams ); 
         
    /* Failed. */ 
    return( FALSE ); 
  } 
     
  /* If one topic found. */ 
  else if( wFoundTopics == 1 ) 
  {  
    /* Free any file info. that we loaded into memory. */ 
    FreeKeywordData( hHelpFileInfo ); 
 
    /* Get the topic's data. */ 
    hTopicData = LockTopicData( hWnd, fpHelpParams->Path, dwTopicCharOffset ); 
    if( hTopicData == NULL ) 
    { 
      /* Unlock handle to message stucture. */ 
      GlobalUnlock( hHelpParams ); 
         
      /* Failure. */ 
      return( FALSE ); 
    } 
   
    /* Get the window handle for the main topic window. */ 
    hMainTopicWnd = (HWND) WndData( hWnd, WDM_GETMAINTOPICHWND, 0, NULL ); 
              
    /* Inform main topic window of new topic to load. */ 
    SendShowNewTopicMsg( hMainTopicWnd, hTopicData, TRUE, FALSE, 0 );  
 
    /* Unlock handle to message stucture. */ 
    GlobalUnlock( hHelpParams ); 
         
    /* Success. */ 
    return( TRUE ); 
  } 
   
 
  /* Unlock handle to message stucture - don't need it anymore. */ 
  GlobalUnlock( hHelpParams ); 
         
  /*  
  ** We are current in a SendMessage() call.  We can't open up the  
  ** Search dialog box until we reply to the call and are out of it. 
  */ 
  ReplyMessage( 0 ); 
   
  /*  
  ** More than one topic found or  
  ** 
  ** No topic's found and HELP_PARTIALKEY 
  */ 
 
  /* Is the Search dialog box already displayed. */ 
  bDlgAlreadyDisplayed = (BOOL) WndData( hWnd, WDM_GETSEARCHDLGDISPLAYED, 0, NULL ); 
              
  /* The Search dialog box is already displayed. */ 
  if( bDlgAlreadyDisplayed == TRUE ) 
  { 
    /* Free any file info. that we loaded into memory. */ 
    FreeKeywordData( hHelpFileInfo ); 
     
    /* Failed. */ 
    return( FALSE ); 
  } 
 
  /* Get the window handle for the main topic window. */ 
  hMainTopicWnd = (HWND) WndData( hWnd, WDM_GETMAINTOPICHWND, 0, NULL ); 
              
  /* Init. the window input data. */ 
  SearchWndData.hDataWnd      = hWnd; 
  SearchWndData.chKey         = 'K'; 
  SearchWndData.hHelpFileInfo = hHelpFileInfo; 
         
  /* HELP_KEY message. */ 
  if( SrchMsg == HELP_KEY ) 
  { 
    /* Use keyword initially. */ 
    SearchWndData.KeywordPtr = KeywordPtr; 
  } 
  /* HELP_PARTIALKEY message. */ 
  else 
  { 
    /* Use no keyword initially. */ 
    SearchWndData.KeywordPtr = NULL; 
  } 
 
  /* The Search dialog box is being displayed. */ 
  WndData( hWnd, WDM_SETSEARCHDLGDISPLAYED, (DWORD) TRUE, NULL ); 
              
  /* Show search dialog. */ 
  nResult = DialogBoxParam( GetLibInst(), "DLG_SEARCH", hMainTopicWnd, SearchDlgProc, (LPARAM) (FPSEARCHWNDDATA) &SearchWndData ); 
   
  /* The Search dialog box is not being displayed. */ 
  WndData( hWnd, WDM_SETSEARCHDLGDISPLAYED, (DWORD) FALSE, NULL ); 
 
  /* Free any file info. that we loaded into memory. */ 
  FreeKeywordData( hHelpFileInfo ); 
   
  /* No error. */ 
  if( nResult == TRUE ) 
  { 
    /* Success. */ 
    return( TRUE ); 
  } 
  else  /* FALSE or -1. */ 
  { 
    /* Failure. */ 
    return( FALSE ); 
  } 
} 
  
 
/********************************************************** 
**   
**  HELP_MULTKEY message 
** 
**  Looks for the specified keyword in the specified 
**  keyword list. 
** 
**  If the keyword is found, the first topic 
**  associated with it is displayed. 
** 
***********************************************************/ 
BOOL DoHelpMultiKeyMsg( HWND hWnd, FPHELPPARAMS fpHelpParams ) 
{ 
  MULTIKEYHELP * MultiKeyPtr; 
   
  HGLOBAL hTopicData;           /* Handle to the topic's elements list. */                 
  HGLOBAL hHelpFileInfo;        /* Handle to the help file's general info. */ 
  DWORD   dwTopicCharOffset;    /* Location of topic data. */ 
  WORD    wFoundTopics;         /* Number of topics associated with the keyword. */ 
  HWND hMainTopicWnd;           /* Window handle for the main topic window. */ 
                       
                       
  /* Open and load the help file's info. */ 
  hHelpFileInfo = OpenHelpFile( hWnd, fpHelpParams->Path ); 
  if( hHelpFileInfo == NULL ) 
  { 
    /* Failure. */ 
    return( FALSE ); 
  } 
  
  /* Get multikey data. */ 
  MultiKeyPtr = ( MULTIKEYHELP * ) ( ( BYTE * ) fpHelpParams + fpHelpParams->ExtraDataOffset ); 
 
  /* Load the keyword data. */ 
  if( ! LoadKeywordData( hWnd, MultiKeyPtr->mkKeylist, hHelpFileInfo ) ) 
  { 
    /* Failed. */ 
    return( FALSE ); 
  } 
 
  /* Get the number of topics for the keyword. */ 
  wFoundTopics = GetKeyTopic( hWnd, hHelpFileInfo, MultiKeyPtr->szKeyphrase, &dwTopicCharOffset ); 
 
  /* If no topics found. */ 
  if( wFoundTopics == 0 ) 
  { 
    /* Free any file info. that we loaded into memory. */ 
    FreeKeywordData( hHelpFileInfo ); 
     
    /* Failed. */ 
    return( FALSE ); 
  } 
     
  /* 
  ** If one or more topics found.  
  */ 
 
  /* Free any file info. that we loaded into memory. */ 
  FreeKeywordData( hHelpFileInfo ); 
 
  /* Get the topic's data. */ 
  hTopicData = LockTopicData( hWnd, fpHelpParams->Path, dwTopicCharOffset ); 
  if( hTopicData == NULL ) 
  { 
    /* Failure. */ 
    return( FALSE ); 
  } 
   
  /* Get the window handle for the main topic window. */ 
  hMainTopicWnd = (HWND) WndData( hWnd, WDM_GETMAINTOPICHWND, 0, NULL ); 
              
  /* Inform main topic window of new topic to load. */ 
  SendShowNewTopicMsg( hMainTopicWnd, hTopicData, TRUE, FALSE, 0 );  
 
  /* Success. */ 
  return( TRUE ); 
} 
 
 
 
/********************************************************** 
**   
**  Load in the appropriate keyword table and displays 
**  the Search dialog box.  
**   
***********************************************************/ 
BOOL ShowCurrHelpFilesKeywords( HWND hDataWnd, HWND hParentWnd ) 
{ 
  HGLOBAL hDisplayInfo;         /* Handle to the topic window's display info. */ 
  FPDISPLAYINFO fpDisplayInfo;  /* Pointer to the topic window's display info. */ 
  FPTOPICDATA fpTopicData;      /* Pointer to the topic's window's topic data. */ 
   
  HWND    hMainTopicWnd; 
  SEARCHWNDDATA SearchWndData; 
   
  BOOL bDlgAlreadyDisplayed; 
   
   
  /* Is the Search dialog box already displayed. */ 
  bDlgAlreadyDisplayed = (BOOL) WndData( hDataWnd, WDM_GETSEARCHDLGDISPLAYED, 0, NULL ); 
              
  /* The Search dialog box is already displayed. */ 
  if( bDlgAlreadyDisplayed == TRUE ) 
  { 
    /* Failed. */ 
    return( FALSE ); 
  } 
 
  /* Get the window handle for the main topic window. */ 
  hMainTopicWnd = (HWND) WndData( hDataWnd, WDM_GETMAINTOPICHWND, 0, NULL ); 
 
  /* Get the handle display info. from the window data. */ 
  hDisplayInfo = (HGLOBAL) WndData( hMainTopicWnd, WDM_GETDISPLAYINFO, 0L, NULL ); 
 
  /* Lock the display info. */ 
  fpDisplayInfo = (FPDISPLAYINFO) GlobalLock( hDisplayInfo ); 
   
  /* No file info loaded. */ 
  if( fpDisplayInfo->hTopicData == NULL )  
  { 
    /* Unlock the display info. */ 
    GlobalUnlock( hDisplayInfo ); 
 
    /* Failed but not due to error. */ 
    return TRUE; 
  } 
            
  /* Lock the topic info. */ 
  fpTopicData = (FPTOPICDATA) GlobalLock( fpDisplayInfo->hTopicData ); 
 
  /* Load the keyword data. */ 
  if( ! LoadKeywordData( hMainTopicWnd, 'K', fpTopicData->hHelpFileInfo ) ) 
  { 
    /* Unlock the topic info. */ 
    GlobalUnlock( fpDisplayInfo->hTopicData ); 
     
    /* Unlock the display info. */ 
    GlobalUnlock( hDisplayInfo ); 
   
    /* Failed but not due to error. */ 
    return TRUE; 
  } 
 
  /* Init. the window input data. */ 
  SearchWndData.hDataWnd      = hDataWnd; 
  SearchWndData.chKey         = 'K'; 
  SearchWndData.KeywordPtr    = NULL; 
  SearchWndData.hHelpFileInfo = fpTopicData->hHelpFileInfo; 
       
  /* Unlock the topic info. */ 
  GlobalUnlock( fpDisplayInfo->hTopicData ); 
     
  /* Unlock the display info. */ 
  GlobalUnlock( hDisplayInfo ); 
     
  /* The Search dialog box is being displayed. */ 
  WndData( hDataWnd, WDM_SETSEARCHDLGDISPLAYED, (DWORD) TRUE, NULL ); 
              
  /* Show search dialog. */ 
  DialogBoxParam( GetLibInst(), "DLG_SEARCH", hParentWnd, SearchDlgProc, (LPARAM) (FPSEARCHWNDDATA) &SearchWndData ); 
 
  /* The Search dialog box is not being displayed. */ 
  WndData( hDataWnd, WDM_SETSEARCHDLGDISPLAYED, (DWORD) FALSE, NULL ); 
              
  /* Free any file info. that we loaded into memory. */ 
  FreeKeywordData( SearchWndData.hHelpFileInfo ); 
 
  /* Success. */ 
  return( TRUE ); 
} 
 
 
 
/*********************************************************************************** 
** 
**                              Private Functions 
** 
************************************************************************************/ 
 
BOOL CALLBACK SearchDlgProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) 
{ 
  HSEARCHWNDDATA  hSearchWndData; 
  FPSEARCHWNDDATA fpSearchWndData; 
   
  FPSEARCHWNDDATA fpWndDataIn; 
   
  DWORD dwSelected; 
  DWORD dwTopicOffset; 
   
  BOOL  bSuccess; 
   
  HGLOBAL hEditSearchWndData; 
  EDITSEARCHWNDDATAPTR EditSearchWndDataPtr; 
 
  switch( Msg )  
  { 
    /* Window initialization. */ 
    case WM_INITDIALOG: 
    {   
      /* Allocate memory for edit control window proc. pointer. */ 
      if( !GlobalAllocMem( hWnd, &hEditSearchWndData, sizeof(EDITSEARCHWNDDATA) ) ) 
      { 
        /* Failure. */ 
        return( -1 ); 
      } 
   
      /* Subclass edit control and store the dialog box's window handle. */ 
      EditSearchWndDataPtr = ( EDITSEARCHWNDDATAPTR ) GlobalLock( hEditSearchWndData ); 
      EditSearchWndDataPtr->OldWndProc = (WNDPROC) GetWindowLong( GetDlgItem( hWnd, IDC_EDITKEYWORD ), GWL_WNDPROC ); 
      EditSearchWndDataPtr->hDlgWnd = hWnd; 
      GlobalUnlock( hEditSearchWndData ); 
      SetProp( GetDlgItem( hWnd, IDC_EDITKEYWORD ), EDITKEYWORDOLDPROC, hEditSearchWndData ); 
      SetWindowLong( GetDlgItem( hWnd, IDC_EDITKEYWORD ), GWL_WNDPROC, (LONG) EditKeywordWndProc ); 
 
      /* Allocate memory for window data. */ 
      if( !GlobalAllocMem( hWnd, &hSearchWndData, sizeof(SEARCHWNDDATA) ) ) 
      { 
        /* Free edit control data. */ 
        MyGlobalFree( hEditSearchWndData ); 
         
        /* Failure. */ 
        return( -1 ); 
      } 
   
      /* Lock window data. */ 
      fpSearchWndData = ( FPSEARCHWNDDATA ) GlobalLock( hSearchWndData ); 
       
      /* Save topic window data passed in. */ 
      fpWndDataIn = ( FPSEARCHWNDDATA ) lParam; 
      fpSearchWndData->chKey         = fpWndDataIn->chKey; 
      fpSearchWndData->KeywordPtr    = fpWndDataIn->KeywordPtr; 
      fpSearchWndData->hDataWnd      = fpWndDataIn->hDataWnd; 
      fpSearchWndData->hHelpFileInfo = fpWndDataIn->hHelpFileInfo; 
       
      /* Not in the topic's list box by default. */ 
      fpSearchWndData->bInTopicList = FALSE; 
       
      /* Show keywords. */ 
      if( !ShowKeywords( GetDlgItem( hWnd, IDC_KEYWORDS ), fpSearchWndData->chKey, fpSearchWndData->hHelpFileInfo ) ) 
      { 
        /* Unlock window data. */ 
        GlobalUnlock( hSearchWndData ); 
       
        /* Perform closing operations. */ 
        CloseUpDialog( hWnd ); 
 
        /* Failure. */ 
        return( -1 ); 
      } 
       
      /* If we do have a keyword we're looking for. */ 
      if( fpSearchWndData->KeywordPtr != NULL ) 
      { 
        /* Select the keyword in list. */ 
        dwSelected = SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_SELECTSTRING,  
                     (WPARAM) -1, (LPARAM) (LPCSTR) fpSearchWndData->KeywordPtr ); 
 
        /* If we failed to find a match. */ 
        if( dwSelected == LB_ERR ) 
        {   
          /* Which keyword to select first? */ 
          if( fpSearchWndData->chKey == 'K' ) 
          { 
            /*  
            ** If we are displaying the default keyword list, 
            ** get last index.  
            */ 
            dwSelected = GetLastKeywordIndex( fpSearchWndData->hHelpFileInfo ); 
          } 
          else 
          { 
            /* Select first item in combo box. */ 
            dwSelected = 0; 
          } 
   
          /* Select keyword in list. */ 
          dwSelected = SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_SETCURSEL, (WPARAM) dwSelected, 0L ); 
        } 
      } 
       
      /* If we don't have a keyword. */ 
      else 
      {       
        /* Which keyword to select first? */ 
        if( fpSearchWndData->chKey == 'K' ) 
        { 
          /*  
          ** If we are displaying the default keyword list, 
          ** get last index.  
          */ 
          dwSelected = GetLastKeywordIndex( fpSearchWndData->hHelpFileInfo ); 
        } 
        else 
        { 
          /* Select first item in combo box. */ 
          dwSelected = 0; 
        } 
 
        /* Select keyword in list. */ 
        dwSelected = SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_SETCURSEL, (WPARAM) dwSelected, 0L ); 
      } 
       
      /* If there is an item, show item's topics. */ 
      if( dwSelected != LB_ERR ) 
      {   
        /* Show selected keyword in edit control. */ 
        ShowEditKeyword( hWnd, (WORD) dwSelected ); 
 
        /* Select all the text in the edit control. */ 
        SendMessage( GetDlgItem( hWnd, IDC_EDITKEYWORD ), EM_SETSEL, 0, -1 ); 
         
        /* Show the topics assoicated with the keyword. */ 
        if( !ShowSearchTopics( hWnd, fpSearchWndData->hHelpFileInfo, dwSelected, &(fpSearchWndData)->dwKWDATAOffset ) ) 
        { 
          /* Perform closing operations. */ 
          CloseUpDialog( hWnd ); 
                   
          /* Close dialog box window. */ 
          return( -1 ); 
        } 
      } 
       
      /* Unlock window data. */ 
      GlobalUnlock( hSearchWndData ); 
       
      /* Save handle to the window data. */ 
      SetWindowLong( hWnd, DWL_USER, (LONG) hSearchWndData );  
 
      /* Success. */ 
      return( TRUE ); 
    } 
     
 
    case WM_COMMAND: 
    { 
      switch( LOWORD(wParam) )  
      { 
        case IDC_DEFBUTTON: 
        { 
          /* Save handle to the window data. */ 
          hSearchWndData = ( HSEARCHWNDDATA ) GetWindowLong( hWnd, DWL_USER );  
         
          /* Lock window data. */ 
          fpSearchWndData = ( FPSEARCHWNDDATA ) GlobalLock( hSearchWndData ); 
 
          /* If we are in the topic's list box. */ 
          if( fpSearchWndData->bInTopicList == TRUE ) 
          { 
            /* Unlock window data. */ 
            GlobalUnlock( hSearchWndData ); 
 
            /* Act as if the GOTO button was pressed. */ 
            PostMessage( hWnd, WM_COMMAND, MAKELONG(IDC_SEARCHGOTO,0), 0L ); 
          } 
          else 
          { 
            /* Unlock window data. */ 
            GlobalUnlock( hSearchWndData ); 
 
            /* Select first topic. */ 
            SelectFirstTopic( hWnd ); 
          } 
           
          /* Processed message. */ 
          return TRUE; 
        } 
         
 
        case IDCANCEL: 
        { 
          /* Perform closing operations. */ 
          CloseUpDialog( hWnd ); 
     
          /* Close dialog box window. */ 
          EndDialog( hWnd, FALSE ); 
        } 
         
 
        case IDC_KEYWORDS: 
        { 
          /* New keyword selected. */ 
          if( HIWORD(wParam) == LBN_SELCHANGE )  
          {  
            /* Get selected keyword. */ 
            dwSelected = SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_GETCURSEL, 0, 0L ); 
 
            /* If there is a keyword to show. */ 
            if( dwSelected != LB_ERR ) 
            { 
              /* Show the topics for the seelcted keyword. */ 
              if( ! ShowTopics( hWnd, dwSelected ) ) 
              { 
                /* Perform closing operations. */ 
                CloseUpDialog( hWnd ); 
                           
                /* Close dialog box window. */ 
                EndDialog( hWnd, FALSE ); 
              } 
 
              /* Show selected keyword in edit control. */ 
              ShowEditKeyword( hWnd, (WORD) dwSelected ); 
            } 
          } 
           
          else if( HIWORD(wParam) == LBN_DBLCLK )  
          { 
            /* Select first topic. */ 
            SelectFirstTopic( hWnd ); 
          } 
 
          /* Processed message. */ 
          return TRUE; 
        } 
 
 
 
        case IDC_SEARCHTOPIC: 
        { 
          switch( HIWORD(wParam) ) 
          { 
            /* Getting focus. */ 
            case LBN_SETFOCUS: 
            { 
              /* Save handle to the window data. */ 
              hSearchWndData = ( HSEARCHWNDDATA ) GetWindowLong( hWnd, DWL_USER );  
         
              /* Lock window data. */ 
              fpSearchWndData = ( FPSEARCHWNDDATA ) GlobalLock( hSearchWndData ); 
 
              /* In the topic's list box by default. */ 
              fpSearchWndData->bInTopicList = TRUE; 
               
              /* Unlock window data. */ 
              GlobalUnlock( hSearchWndData ); 
 
              break; 
            } 
 
            /* Losing focus. */ 
            case LBN_KILLFOCUS: 
            { 
              /* Save handle to the window data. */ 
              hSearchWndData = ( HSEARCHWNDDATA ) GetWindowLong( hWnd, DWL_USER );  
         
              /* No window data - probably exiting. */ 
              if( hSearchWndData == 0 )  
              { 
                /* Processed message. */ 
                return TRUE; 
              } 
           
              /* Lock window data. */ 
              fpSearchWndData = ( FPSEARCHWNDDATA ) GlobalLock( hSearchWndData ); 
 
              /* Not the topic's list box by default. */ 
              fpSearchWndData->bInTopicList = FALSE; 
               
              /* Unlock window data. */ 
              GlobalUnlock( hSearchWndData ); 
 
              break; 
            } 
 
            case LBN_DBLCLK: 
            { 
              /* Goto topic. */ 
              PostMessage( hWnd, WM_COMMAND, MAKELONG(IDC_SEARCHGOTO,0), 0L ); 
               
              break; 
            } 
 
            case LBN_SELCHANGE: 
            { 
              /* Enable goto button. */ 
              EnableWindow( GetDlgItem( hWnd, IDC_SEARCHGOTO ), TRUE ); 
               
              break; 
            } 
          } 
 
          /* Processed message. */ 
          return TRUE; 
        } 
 
 
        case IDC_SEARCHGOTO: 
        { 
          dwSelected = SendMessage( GetDlgItem( hWnd, IDC_SEARCHTOPIC ), LB_GETCURSEL, 0, 0L ); 
          if( dwSelected != LB_ERR ) 
          { 
            /* Save handle to the window data. */ 
            hSearchWndData = ( HSEARCHWNDDATA ) GetWindowLong( hWnd, DWL_USER );  
         
            /* Lock window data. */ 
            fpSearchWndData = ( FPSEARCHWNDDATA ) GlobalLock( hSearchWndData ); 
         
            /* Get topic's offset. */ 
            dwTopicOffset = GetKeywordTopicOffset( fpSearchWndData->hHelpFileInfo, fpSearchWndData->dwKWDATAOffset, dwSelected ); 
 
            /* Goto topic. */ 
            bSuccess = GotoSearchTopic( fpSearchWndData, dwTopicOffset ); 
             
            /* Unlock window data. */ 
            GlobalUnlock( hSearchWndData ); 
 
            /* If move to new topic is OK. */ 
            if( bSuccess ) 
            { 
              /* Perform closing operations. */ 
              CloseUpDialog( hWnd ); 
         
              /* Close dialog box window. */ 
              EndDialog( hWnd, TRUE ); 
            } 
          } 
 
          /* Processed message. */ 
          return TRUE; 
        } 
      } 
       
      /* Processed message. */ 
      return TRUE; 
    } 
  } 
 
  /* Message not processed. */ 
  return FALSE; 
} 
 
 
static void SelectFirstTopic( HWND hWnd ) 
{ 
  DWORD dwReturn; 
   
  /* Select first topic associated with keyword. */ 
  dwReturn = SendMessage( GetDlgItem( hWnd, IDC_SEARCHTOPIC ), LB_SETCURSEL, (WPARAM) 0, 0L ); 
 
  /* No items in the list box. */ 
  if( dwReturn != LB_ERR ) 
  {   
    /* Enable goto button. */ 
    EnableWindow( GetDlgItem( hWnd, IDC_SEARCHGOTO ), TRUE ); 
     
    /* SetFocus to list box. */ 
    SetFocus( GetDlgItem( hWnd, IDC_SEARCHTOPIC ) ); 
  } 
} 
 
 
LRESULT CALLBACK EditKeywordWndProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) 
{ 
  HGLOBAL hEditSearchWndData; 
  EDITSEARCHWNDDATAPTR EditSearchWndDataPtr; 
  WNDPROC OldEditWndProc; 
   
  HWND hDlgWnd; 
   
  LRESULT lResult; 
   
   
  switch( Msg )  
  { 
    /* Receive all input. */ 
    case WM_GETDLGCODE: 
    { 
      return( DLGC_WANTCHARS ); 
    } 
     
    /* Character input. */ 
    case WM_CHAR: 
    { 
      /* Get window of dialog box containing the edit control. */ 
      hEditSearchWndData = (HGLOBAL) GetProp( hWnd, EDITKEYWORDOLDPROC ); 
      EditSearchWndDataPtr = ( EDITSEARCHWNDDATAPTR ) GlobalLock( hEditSearchWndData ); 
      hDlgWnd = EditSearchWndDataPtr->hDlgWnd; 
      OldEditWndProc = EditSearchWndDataPtr->OldWndProc; 
      GlobalUnlock( hEditSearchWndData ); 
 
      /* Pass to edit control's old WndProc(). */ 
      lResult = CallWindowProc( OldEditWndProc, hWnd, Msg, wParam, lParam ); 
   
      /* Show selected keyword in edit control. */ 
      SelectClosestKeyword( hDlgWnd ); 
         
      /* Return returned value. */ 
      return( lResult ); 
    } 
  } 
  
  /* Get edit control's old WndProc(). */ 
  hEditSearchWndData = (HGLOBAL) GetProp( hWnd, EDITKEYWORDOLDPROC ); 
  EditSearchWndDataPtr = ( EDITSEARCHWNDDATAPTR ) GlobalLock( hEditSearchWndData ); 
  OldEditWndProc = EditSearchWndDataPtr->OldWndProc; 
  GlobalUnlock( hEditSearchWndData ); 
 
  /* Pass to edit control's old WndProc(). */ 
  lResult = CallWindowProc( OldEditWndProc, hWnd, Msg, wParam, lParam ); 
   
  /* Return returned value. */ 
  return( lResult ); 
}                                                                                   
 
 
static void SelectClosestKeyword( HWND hWnd ) 
{ 
  char szKeyWord[MAX_KEYWORD_STRING]; 
  char szLBString[MAX_KEYWORD_STRING]; 
  DWORD dwCurrSel, dwReturn; 
  short int nChars, nCompareVal; 
   
 
  /* Get text from edit control. */ 
  SendMessage( GetDlgItem( hWnd, IDC_EDITKEYWORD ), WM_GETTEXT, MAX_KEYWORD_STRING, (LPARAM) szKeyWord ); 
 
  /* Default index. */ 
  dwCurrSel = 0; 
   
  /* Get first text from list box. */ 
  dwReturn = SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_GETTEXT, (WPARAM) dwCurrSel, (LPARAM) szLBString ); 
   
  /* No items in the list box. */ 
  if( dwReturn == LB_ERR ) return; 
 
  /* Find correct item in list box to highlight. */ 
  while( dwReturn != LB_ERR ) 
  { 
    /* Compare strings. */ 
    nChars = strlen(szKeyWord) / sizeof(char); 
    nCompareVal = strnicmp( szLBString, szKeyWord, nChars ); 
   
    /* Found string or past where string could be. */ 
    if( nCompareVal == 0 || nCompareVal > 0 ) break;  
     
    /* Get next string in list box. */ 
    dwCurrSel++; 
     
    /* Get next text from list box. */ 
    dwReturn = SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_GETTEXT, (WPARAM) dwCurrSel, (LPARAM) szLBString ); 
  } 
   
  /* Past the last selection - use last selection. */ 
  if( dwReturn == LB_ERR ) dwCurrSel--; 
   
  /* Select keyword. */ 
  SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_SETCURSEL, (WPARAM) dwCurrSel, 0L ); 
 
  /* Scroll list so current selection is at top. */ 
  SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_SETTOPINDEX, (WPARAM) dwCurrSel, 0L ); 
 
  /*  
  ** Show the topics for the seelcted keyword.  
  ** Don't update the edit control. 
  */ 
  ShowTopics( hWnd, dwCurrSel ); 
} 
 
 
static BOOL ShowTopics( HWND hWnd, DWORD dwSelected ) 
{ 
  HSEARCHWNDDATA  hSearchWndData; 
  FPSEARCHWNDDATA fpSearchWndData; 
 
  BOOL bReturn; 
   
   
  /* Save handle to the window data. */ 
  hSearchWndData = ( HSEARCHWNDDATA ) GetWindowLong( hWnd, DWL_USER );  
         
  /* Lock window data. */ 
  fpSearchWndData = ( FPSEARCHWNDDATA ) GlobalLock( hSearchWndData ); 
 
  /* Show the topics assoicated with the keyword. */ 
  bReturn = ShowSearchTopics( hWnd, fpSearchWndData->hHelpFileInfo, dwSelected, &(fpSearchWndData)->dwKWDATAOffset ); 
 
  /* Unlock window data. */ 
  GlobalUnlock( hSearchWndData ); 
 
  /* Return success or failure. */ 
  return( bReturn ); 
} 
 
 
static void ShowEditKeyword( HWND hWnd, WORD wKeyWordIndex ) 
{ 
  char szKeyWord[MAX_KEYWORD_STRING]; 
   
  /* If there is a selection. */ 
  if( wKeyWordIndex != LB_ERR ) 
  { 
    /* Get text from list box selection. */ 
    SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_GETTEXT, wKeyWordIndex, (LPARAM) szKeyWord ); 
 
    /* Set text in edit control. */ 
    SendMessage( GetDlgItem( hWnd, IDC_EDITKEYWORD ), WM_SETTEXT, 0, (LPARAM) szKeyWord ); 
  } 
} 
 
 
static BOOL ShowSearchTopics( HWND hWnd,  HGLOBAL hHelpFileInfo, DWORD dwKeyWordIndex, DWORD * dwKWDATAOffset ) 
{ 
  /* Clear items in the topics list box. */ 
  SendMessage( GetDlgItem( hWnd, IDC_SEARCHTOPIC ), LB_RESETCONTENT, 0, 0L ); 
                 
  /* Show the topics for the selected keyword. */ 
  if( !ShowKeywordTopics( GetDlgItem( hWnd, IDC_SEARCHTOPIC ), dwKeyWordIndex, hHelpFileInfo, dwKWDATAOffset ) ) 
  { 
    /* Failure. */ 
    return( FALSE ); 
  } 
     
  /* Disable goto button. */ 
  EnableWindow( GetDlgItem( hWnd, IDC_SEARCHGOTO ), FALSE ); 
 
  /* Success. */ 
  return( TRUE ); 
} 
 
 
 
static void CloseUpDialog( HWND hWnd ) 
{ 
  HSEARCHWNDDATA  hSearchWndData; 
  FPSEARCHWNDDATA fpSearchWndData; 
 
  HGLOBAL hEditSearchWndData; 
  EDITSEARCHWNDDATAPTR EditSearchWndDataPtr; 
   
  DWORD dwSelected; 
 
  /* Save handle to the window data. */ 
  hSearchWndData = ( HSEARCHWNDDATA ) GetWindowLong( hWnd, DWL_USER );  
 
  /* Lock window data. */ 
  fpSearchWndData = ( FPSEARCHWNDDATA ) GlobalLock( hSearchWndData ); 
       
  /* If we are displaying the default keyword list. */ 
  if( fpSearchWndData->chKey == 'K' ) 
  { 
    /* Get selected keyword. */ 
    dwSelected = SendMessage( GetDlgItem( hWnd, IDC_KEYWORDS ), LB_GETCURSEL, 0, 0L ); 
 
    if( dwSelected != LB_ERR ) 
    { 
      /* Save last index. */ 
      SetLastKeywordIndex( fpSearchWndData->hHelpFileInfo, dwSelected ); 
    } 
  } 
 
  /* Unlock window data. */ 
  GlobalUnlock( hSearchWndData ); 
       
  /* Free window data. */ 
  MyGlobalFree( hSearchWndData ); 
       
  /* Save handle to the window data. */ 
  SetWindowLong( hWnd, DWL_USER, 0 );  
 
  /* Restore the edit control's window procedure. */ 
  hEditSearchWndData = (HGLOBAL) GetProp( GetDlgItem( hWnd, IDC_EDITKEYWORD ), EDITKEYWORDOLDPROC ); 
  EditSearchWndDataPtr = ( EDITSEARCHWNDDATAPTR ) GlobalLock( hEditSearchWndData ); 
  SetWindowLong( GetDlgItem( hWnd, IDC_EDITKEYWORD ), GWL_WNDPROC, (LONG) EditSearchWndDataPtr->OldWndProc ); 
  GlobalUnlock( hEditSearchWndData ); 
  MyGlobalFree( hEditSearchWndData ); 
} 
 
 
static BOOL GotoSearchTopic( FPSEARCHWNDDATA fpSearchWndData, DWORD dwTopicCharOffset ) 
{ 
  FPHLPFILEINFO fpHelpFileInfo;    /* Pointer to new help file info.      */ 
  HGLOBAL hTopicData;              /* Handle to the topic's elements list. */                 
  HWND   hMainTopicWnd;            /* Window handle for the main topic window. */ 
   
  /* Lock help info. */ 
  fpHelpFileInfo = (FPHLPFILEINFO) GlobalLock( fpSearchWndData->hHelpFileInfo ); 
 
  /*  
  ** Get the topic's data.  
  */ 
 
  hTopicData = LockTopicData( fpSearchWndData->hDataWnd, fpHelpFileInfo->szFilePath, dwTopicCharOffset ); 
  if( hTopicData == NULL ) 
  { 
    /* Unlock help file info. */ 
    GlobalUnlock( fpSearchWndData->hHelpFileInfo ); 
 
    /* Failure. */ 
    return FALSE; 
  } 
 
  /* Unlock help file info. */ 
  GlobalUnlock( fpSearchWndData->hHelpFileInfo ); 
   
  /* Get the window handle for the main topic window. */ 
  hMainTopicWnd = (HWND) WndData( fpSearchWndData->hDataWnd, WDM_GETMAINTOPICHWND, 0, NULL ); 
 
  /* Inform main topic window of new topic to load. */ 
  SendShowNewTopicMsg( hMainTopicWnd, hTopicData, TRUE, FALSE, 0 );  
 
  /* Success. */ 
  return TRUE; 
}