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


/* 
  
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. 
 
*/ 
 
/************************************************************************* 
* 
*	ACCEL.C 
*   Accelerator handling routines.       
* 
*	Author: Paul E. Kissel 
* 
**************************************************************************/ 
 
/*********************************** 
** 
**  System Includes 
** 
***********************************/ 
 
#include <string.h> 
#include <ctype.h> 
 
 
/*********************************** 
** 
**  App. Includes 
** 
***********************************/ 
 
#include "accel.h" 
#include "winmem.h" 
#include "globals.h" 
#include "msgbox.h" 
#include "twhlprc.h" 
#include "wnddata.h" 
#include "hlpmacro.h" 
#include "macroeng.h" 
 
 
/*********************************** 
** 
**  Private File Defines 
** 
***********************************/ 
 
 
/* 
** Information for an accelerator in the list. 
*/ 
typedef HGLOBAL HACCELINFO; 
typedef struct tagACCELINFO 
{ 
  WORD wKey; 
  WORD wShiftState; 
  HGLOBAL hMacroString; 
  HACCELINFO Next; 
}  
ACCELINFO; 
typedef ACCELINFO * FPACCELINFO; 
 
 
/* 
** Information for the accelerator system. 
*/ 
typedef HACCELINFO HACCELLIST; 
typedef struct tagACCELSYS 
{ 
  HWND       hMainWnd;        /* Main data window. */ 
  HACCELLIST hAccelList;      /* Top of the accelerator list. */ 
}  
ACCELSYS; 
typedef ACCELSYS * FPACCELSYS; 
 
 
/*  
** EnumAccelInfo() callback function.  
*/ 
typedef BOOL ( CALLBACK * ACCELINFOENUMPROC )( FPACCELINFO fpAccelInfo, LPARAM lParam ); 
 
 
/*  
** Data used by the KeyIsPressed() function.  
*/ 
typedef struct tagKEYPRESSFUNCDATA 
{ 
  BOOL bProcessed; 
  HWND hExecWnd; 
  HWND hMainWnd; 
  WORD wKey; 
  WORD wShiftState; 
} 
KEYPRESSFUNCDATA; 
typedef KEYPRESSFUNCDATA * FPKEYPRESSFUNCDATA; 
 
 
/*  
** Data used by the AccelExists() function.  
*/ 
typedef struct tagEXISTSFUNCDATA 
{ 
  BOOL bExists; 
  WORD wKey; 
  WORD wShiftState; 
} 
EXISTSFUNCDATA; 
typedef EXISTSFUNCDATA * FPEXISTSFUNCDATA; 
 
 
 
/*********************************** 
** 
**  Private Function Prototypes 
** 
***********************************/ 
static void EnumAccelInfo( HACCELLIST hAccelList, ACCELINFOENUMPROC AccelInfoEnumProc, LPARAM lParam ); 
static HACCELINFO GetNextAccelInfo( HACCELINFO hAccelInfo );                                            
static void FreeAccelList( HACCELLIST * hAccelList ); 
static void InsertAccelInfo( HACCELLIST * hAccelList, HACCELINFO hNewAccelInfo ); 
static void FreeAccelInfo( HACCELINFO hAccelInfo ); 
static HACCELINFO NewAccelInfo( HWND hErrorWnd, FPACCELINFO fpAccelInfo ); 
static BOOL SaveAccelInfo( HWND hErrorWnd, HACCELLIST * hAccelList, FPACCELINFO fpAccelInfo ); 
static BOOL CALLBACK KeyIsPressedProc( FPACCELINFO fpAccelInfo, LPARAM lParam ); 
static BOOL DeleteAccelInfo( HACCELLIST * hAccelList, FPACCELINFO fpDelAccelInfo ); 
static BOOL CALLBACK AccelExistsProc( FPACCELINFO fpAccelInfo, LPARAM lParam ); 
 
 
/*********************************************************************************** 
** 
**                              Shared Functions 
** 
************************************************************************************/ 
 
                                                                  
/*********************************** 
** 
**  Starts accelerator support system.  
** 
**  Returns: 
** 
**     Success - TRUE. 
**     Failure - FALSE. 
** 
***********************************/ 
BOOL StartAccelSupport( HWND hWnd, HWND hMainWnd ) 
{ 
  HACCELSYS  hAccelSys; 
  FPACCELSYS AccelSysPtr; 
   
  /* Allocate memory for accel. support data. */ 
  if( !GlobalAllocMem( hWnd, &hAccelSys, sizeof(ACCELSYS) ) ) 
  { 
    /* Error. */  
    MsgBox( GetLibInst(), hWnd, IDS_ERRORTITLE, CANTSTARTACCELSYS, MB_ICONHAND | MB_OK ); 
 
    /* Set the accel. sys. data to NULL. */ 
    WndData( hWnd, WDM_SETACCELSYS, (DWORD) NULL, NULL ); 
 
    /* Failure. */ 
    return( FALSE ); 
  } 
   
  /* Lock data. */ 
  AccelSysPtr = ( FPACCELSYS ) GlobalLock( hAccelSys ); 
       
  /* Init. structure. */ 
  AccelSysPtr->hMainWnd   = hMainWnd; 
  AccelSysPtr->hAccelList = 0; 
 
  /* Unlock data. */ 
  GlobalUnlock( hAccelSys ); 
 
    /* Set the accel. sys. data. */ 
  WndData( hWnd, WDM_SETACCELSYS, (DWORD) hAccelSys, NULL ); 
             
  /* Success. */ 
  return( TRUE );   
} 
 
 
/*********************************** 
** 
**  Stops accelerator support system.  
** 
**  Returns: None 
** 
***********************************/ 
void StopAccelSupport( HWND hWnd ) 
{ 
  HACCELSYS  hAccelSys; 
  FPACCELSYS AccelSysPtr; 
             
  /* Get the accel. sys. data */ 
  hAccelSys = (HACCELSYS) WndData( hWnd, WDM_GETACCELSYS, 0, NULL ); 
   
  /* If we have a accel. support. */ 
  if( hAccelSys != NULL ) 
  { 
    /* Lock accel. support data. */ 
    AccelSysPtr = ( FPACCELSYS ) GlobalLock( hAccelSys ); 
         
    /* Free accel. list. */ 
    FreeAccelList( &(AccelSysPtr)->hAccelList ); 
   
    /* Free accel. support data. */ 
    GlobalUnlock( hAccelSys ); 
    MyGlobalFree( hAccelSys ); 
  } 
 
  /* Set the accel. sys. data to NULL. */ 
  WndData( hWnd, WDM_SETACCELSYS,  0, NULL ); 
} 
 
 
 
/********************************************************************* 
** 
**  Process key as if its an accelerator. 
** 
**  Returns: 
** 
**      TRUE: Processed key. 
**     FALSE: Not Processed key. 
** 
**********************************************************************/ 
BOOL KeyIsPressed( HWND hWnd, WORD wKey ) 
{ 
  KEYPRESSFUNCDATA KeyPressData; 
  HACCELLIST hAccelList; 
  HACCELSYS hAccelSys; 
  FPACCELSYS AccelSysPtr; 
   
  BOOL bShiftPressed, 
       bCtrlPressed, 
       bAltPressed;           
 
 
  /* Get the accel. sys. data */ 
  hAccelSys = (HACCELSYS) WndData( hWnd, WDM_GETACCELSYS, 0, NULL ); 
   
  /* If we have a accel. support. */ 
  if( hAccelSys != NULL ) 
  { 
    /* Lock data. */ 
    AccelSysPtr = ( FPACCELSYS ) GlobalLock( hAccelSys ); 
     
    /* Get handle to the accelerator list. */     
    hAccelList =  AccelSysPtr->hAccelList; 
 
    /* Unlock data. */ 
    GlobalUnlock( hAccelSys ); 
     
    /* Init. data struct. */ 
    KeyPressData.bProcessed  = FALSE; 
    KeyPressData.hExecWnd    = hWnd; 
    KeyPressData.hMainWnd    = AccelSysPtr->hMainWnd; 
 
    /* Get key. */ 
    if( isalpha( wKey ) ) 
    { 
      /* Convert the key to uppercase if its an alpha character key. */ 
      KeyPressData.wKey = toupper( wKey ); 
    } 
    else 
    { 
      KeyPressData.wKey = wKey; 
    } 
   
    /* Get current shift key states. */ 
    if( GetKeyState( VK_SHIFT ) < 0 ) 
    { 
      bShiftPressed = TRUE; 
    }  
    else 
    { 
      bShiftPressed = FALSE; 
    }  
    if( GetKeyState( VK_CONTROL ) < 0 ) 
    { 
      bCtrlPressed = TRUE; 
    }  
    else 
    { 
      bCtrlPressed = FALSE; 
    }  
    if( GetKeyState( VK_MENU ) < 0 ) 
    { 
      bAltPressed = TRUE; 
    }  
    else 
    { 
      bAltPressed = FALSE; 
    }  
 
    /* Set the shift state. */ 
    if( bShiftPressed == FALSE && bCtrlPressed == FALSE && bAltPressed == FALSE ) 
    { 
      KeyPressData.wShiftState = 0; 
    } 
    else if( bShiftPressed == TRUE && bCtrlPressed == FALSE && bAltPressed == FALSE ) 
    { 
      KeyPressData.wShiftState = 1; 
    } 
    else if( bShiftPressed == FALSE && bCtrlPressed == TRUE && bAltPressed == FALSE ) 
    { 
      KeyPressData.wShiftState = 2; 
    } 
    else if( bShiftPressed == TRUE && bCtrlPressed == TRUE && bAltPressed == FALSE ) 
    { 
      KeyPressData.wShiftState = 3; 
    } 
    else if( bShiftPressed == FALSE && bCtrlPressed == FALSE && bAltPressed == TRUE ) 
    { 
      KeyPressData.wShiftState = 4; 
    } 
    else if( bShiftPressed == TRUE && bCtrlPressed == FALSE && bAltPressed == TRUE ) 
    { 
      KeyPressData.wShiftState = 5; 
    } 
    else if( bShiftPressed == FALSE && bCtrlPressed == TRUE && bAltPressed == TRUE ) 
    { 
      KeyPressData.wShiftState = 6; 
    } 
    else if( bShiftPressed == TRUE && bCtrlPressed == TRUE && bAltPressed == TRUE ) 
    { 
      KeyPressData.wShiftState = 7; 
    } 
         
    /* Find accelerator and run macro. */ 
    EnumAccelInfo( hAccelList, (ACCELINFOENUMPROC) KeyIsPressedProc, (LPARAM) (FPKEYPRESSFUNCDATA) &KeyPressData ); 
  } 
 
  /* Processed? */ 
  return( KeyPressData.bProcessed ); 
} 
 
 
 
/********************************************************************* 
** 
**  Adds a new accelerator to the list. 
** 
**********************************************************************/ 
BOOL AddAccelerator 
(  
  HWND hWnd,  
  WORD wKey,  
  WORD wShiftState,  
  LPSTR lpMacro  
) 
{ 
  HACCELSYS hAccelSys; 
  FPACCELSYS AccelSysPtr; 
 
  /* Pointer to macro string. */ 
  char * MacroStringPtr; 
 
  /* Accel. info. to store in accel. info. list. */ 
  ACCELINFO AccelInfo; 
   
  BOOL bReturn; 
     
  EXISTSFUNCDATA AccelExistsData; 
   
   
  /* Get the accel. sys. data */ 
  hAccelSys = (HACCELSYS) WndData( hWnd, WDM_GETACCELSYS, 0, NULL ); 
   
  /* Lock accel. sys. data. */ 
  AccelSysPtr = ( FPACCELSYS ) GlobalLock( hAccelSys ); 
     
  /* See if accelerator already exists. */ 
  AccelExistsData.bExists = FALSE; 
  AccelExistsData.wShiftState = wShiftState; 
  if( isalpha( wKey ) ) 
  { 
    /* Convert the key to uppercase if its an alpha character key. */ 
    AccelExistsData.wKey = toupper( wKey ); 
  } 
  else 
  { 
    AccelExistsData.wKey = wKey; 
  } 
 
  EnumAccelInfo( AccelSysPtr->hAccelList, (ACCELINFOENUMPROC) AccelExistsProc, (LPARAM) (FPEXISTSFUNCDATA) &AccelExistsData ); 
  if( AccelExistsData.bExists == TRUE ) 
  { 
    /* Unlock accel. sys. data. */ 
    GlobalUnlock( hAccelSys ); 
     
    /* Error. */  
    MsgBox( GetLibInst(), hWnd, IDS_ERRORTITLE, ACCELALREADYEXISTS, MB_ICONHAND | MB_OK ); 
 
    /* Success. */ 
    return( FALSE ); 
  } 
   
  /* Allocate memory for storage of macro string. */ 
  if( !GlobalAllocMem( hWnd, &(AccelInfo).hMacroString, strlen( lpMacro ) + sizeof(char) ) ) 
  { 
    /* Unlock accel. sys. data. */ 
    GlobalUnlock( hAccelSys ); 
     
    /* Failure. */ 
    return( FALSE ); 
  } 
   
  /* Copy macro string storage area. */ 
  MacroStringPtr = (char *) GlobalLock( AccelInfo.hMacroString ); 
  strcpy( MacroStringPtr, lpMacro ); 
  GlobalUnlock( AccelInfo.hMacroString ); 
   
  /* Init. the key and shift state. */ 
  if( isalpha( wKey ) ) 
  { 
    /* Convert the key to uppercase if its an alpha character key. */ 
    AccelInfo.wKey = toupper( wKey ); 
  } 
  else 
  { 
    AccelInfo.wKey = wKey; 
  } 
  AccelInfo.wShiftState = wShiftState;    
       
  /* Save accel. info. */ 
  bReturn = SaveAccelInfo( hWnd, &(AccelSysPtr)->hAccelList, (FPACCELINFO) &AccelInfo ); 
  if( bReturn == FALSE ) 
  { 
    /* Unlock accel. sys. data. */ 
    GlobalUnlock( hAccelSys ); 
     
    /* Delete allocated info. */ 
    MyGlobalFree( AccelInfo.hMacroString );  
     
    /* Failure. */ 
    return FALSE; 
  } 
       
  /* Unlock accel. sys. data. */ 
  GlobalUnlock( hAccelSys ); 
     
  /* Success. */ 
  return( TRUE ); 
} 
 
 
 
 
/********************************************************************* 
** 
**  Delete an accelerator to the list. 
** 
**********************************************************************/ 
BOOL RemoveAccelerator 
(  
  HWND hWnd,  
  WORD wKey,  
  WORD wShiftState 
) 
{ 
  HACCELSYS hAccelSys; 
  FPACCELSYS AccelSysPtr; 
 
  ACCELINFO AccelInfo; 
 
  BOOL bReturn; 
   
   
  /* The key and shift state to remove. */ 
  if( isalpha( wKey ) ) 
  { 
    /* Convert the key to uppercase if its an alpha character key. */ 
    AccelInfo.wKey = toupper( wKey ); 
  } 
  else 
  { 
    AccelInfo.wKey = wKey; 
  } 
  AccelInfo.wShiftState = wShiftState;    
       
  /* Get the accel. sys. data */ 
  hAccelSys = (HACCELSYS) WndData( hWnd, WDM_GETACCELSYS, 0, NULL ); 
   
  /* Lock accel. sys. data. */ 
  AccelSysPtr = ( FPACCELSYS ) GlobalLock( hAccelSys ); 
 
  /* Find the accel. and delete it. */ 
  bReturn = DeleteAccelInfo( &(AccelSysPtr)->hAccelList, (FPACCELINFO) &AccelInfo ); 
 
  /* Unlock accel. sys. data. */ 
  GlobalUnlock( hAccelSys ); 
     
  /* Success/Failure. */ 
  return( bReturn ); 
} 
 
 
/********************************************************************* 
** 
**  Remove all of the accelerators. 
** 
**********************************************************************/ 
void RemoveAllAccelerators( HWND hWnd ) 
{ 
  HACCELSYS hAccelSys; 
  FPACCELSYS AccelSysPtr; 
 
  /* Get the accel. sys. data */ 
  hAccelSys = (HACCELSYS) WndData( hWnd, WDM_GETACCELSYS, 0, NULL ); 
   
  /* Lock accel. sys. data. */ 
  AccelSysPtr = ( FPACCELSYS ) GlobalLock( hAccelSys ); 
 
  /* Free accel. list. */ 
  FreeAccelList( &(AccelSysPtr)->hAccelList ); 
 
  /* Unlock accel. sys. data. */ 
  GlobalUnlock( hAccelSys ); 
} 
 
 
 
 
/*********************************************************************************** 
** 
**                              Private Functions 
** 
************************************************************************************/ 
 
 
/********************************************************************* 
** 
**  Does an accelerator already exist? 
** 
**********************************************************************/ 
static BOOL CALLBACK AccelExistsProc( FPACCELINFO fpAccelInfo, LPARAM lParam ) 
{ 
  FPEXISTSFUNCDATA FuncDataPtr; 
 
  /* Get key pressed data. */ 
  FuncDataPtr = ( FPEXISTSFUNCDATA ) lParam; 
   
  /* If this is the correct accel. */ 
  if( FuncDataPtr->wKey == fpAccelInfo->wKey &&   
      FuncDataPtr->wShiftState == fpAccelInfo->wShiftState ) 
  { 
    /* Processed key input. */ 
    FuncDataPtr->bExists = TRUE; 
     
    /* Found it - stop enumerating. */ 
    return FALSE; 
  } 
 
  /* Get next accel.'s info. */ 
  return TRUE; 
} 
 
 
 
/********************************************************************* 
** 
**  Callback function when the accel. bar is notified that an accelerator  
*   is pressed. Runs the macro associated with the pressed accel. 
** 
**********************************************************************/ 
static BOOL CALLBACK KeyIsPressedProc( FPACCELINFO fpAccelInfo, LPARAM lParam ) 
{ 
  char * MacroStringPtr; 
  FPKEYPRESSFUNCDATA FuncDataPtr; 
  char szMacro[MAX_MACRO_STRING]; 
   
  /* Get key pressed data. */ 
  FuncDataPtr = ( FPKEYPRESSFUNCDATA ) lParam; 
   
  /* If this is the correct accel. */ 
  if( FuncDataPtr->wKey == fpAccelInfo->wKey ) 
  { 
    if( FuncDataPtr->wShiftState == fpAccelInfo->wShiftState ||  
        fpAccelInfo->wShiftState == ANY_KEYSTATESTATE ) 
    { 
      /* Get the macro string. */ 
      MacroStringPtr = (char *) GlobalLock( fpAccelInfo->hMacroString ); 
       
      /* Copy the macro string. */ 
      strcpy( szMacro, MacroStringPtr ); 
       
      /* Unlock macro string. */ 
      GlobalUnlock( fpAccelInfo->hMacroString ); 
     
      /* Run the macro. */ 
      RunHelpMacro( FuncDataPtr->hExecWnd, FuncDataPtr->hMainWnd, szMacro ); 
   
      /* Processed key input. */ 
      FuncDataPtr->bProcessed = TRUE; 
       
      /* Found it - stop enumerating. */ 
      return FALSE; 
    } 
  } 
   
  /* Get next accel.'s info. */ 
  return TRUE; 
} 
 
 
/*************************************************************************************** 
** 
** 
**                              Button List Management Functions 
** 
** 
***************************************************************************************/ 
 
 
/************************************* 
* 
*  Add info for an accelerator to the list. 
*                   
**************************************/ 
static BOOL SaveAccelInfo( HWND hErrorWnd, HACCELLIST * hAccelList, FPACCELINFO fpAccelInfo ) 
{ 
  HACCELINFO hNewAccelInfo; 
 
   
  /* Create new ACCELINFO structure. */ 
  hNewAccelInfo = NewAccelInfo( hErrorWnd, fpAccelInfo ); 
  if( hNewAccelInfo == 0 ) return FALSE;  
   
  /* 
  ** Insert the ACCELINFO structure into the accel. List. 
  */ 
  InsertAccelInfo( hAccelList, hNewAccelInfo ); 
   
  /* Return success. */ 
  return TRUE; 
} 
 
 
 
/************************************* 
* 
*  Create a new accel. info. structure. 
*                   
**************************************/ 
static HACCELINFO NewAccelInfo( HWND hErrorWnd, FPACCELINFO fpAccelInfo ) 
{ 
  HACCELINFO hNewAccelInfo; 
  FPACCELINFO fpNewButtonInfo; 
 
   
  /* Allocate the new accel. info. */ 
  if( ! GlobalAllocMem( hErrorWnd, &hNewAccelInfo, sizeof(ACCELINFO) ) ) return NULL; 
   
  /* Lock it. */ 
  fpNewButtonInfo = (FPACCELINFO) GlobalLock( hNewAccelInfo ) ; 
 
  /* Initialize general elements in the structure. */ 
  fpNewButtonInfo->wKey         = fpAccelInfo->wKey; 
  fpNewButtonInfo->wShiftState  = fpAccelInfo->wShiftState; 
  fpNewButtonInfo->hMacroString = fpAccelInfo->hMacroString; 
  fpNewButtonInfo->Next         = 0; 
 
  /* Unlock it. */ 
  GlobalUnlock( hNewAccelInfo ) ; 
 
  /* Return it. */ 
  return hNewAccelInfo; 
} 
 
 
 
/************************************* 
* 
*  Free an accelerator info. structure. 
*                   
**************************************/ 
static void FreeAccelInfo( HACCELINFO hAccelInfo ) 
{ 
  FPACCELINFO fpAccelInfo; 
   
  /* Lock it. */ 
  fpAccelInfo = (FPACCELINFO) GlobalLock( hAccelInfo ) ; 
 
  /* Delete allocated info. */ 
  MyGlobalFree( fpAccelInfo->hMacroString );  
     
  /* Unlock it. */ 
  GlobalUnlock( hAccelInfo ) ; 
 
  /* Free it. */ 
  MyGlobalFree( hAccelInfo ) ; 
} 
 
 
 
/************************************* 
* 
*  Insert a new accel. info. structure 
*  at the top of the accel. info. list. 
*                   
**************************************/ 
static void InsertAccelInfo( HACCELLIST * hAccelList, HACCELINFO hNewAccelInfo ) 
{ 
  FPACCELINFO fpNew; 
   
  /* Already existing nodes. */ 
  if( *hAccelList != 0 )  
  { 
    /* Lock new node. */ 
    fpNew = (FPACCELINFO) GlobalLock( hNewAccelInfo ) ; 
     
    /* Next node is the old top node. */ 
    fpNew->Next = *hAccelList; 
 
    /* Unlock new node. */ 
    GlobalUnlock( hNewAccelInfo ) ; 
  } 
 
  /* New node is the top node. */ 
  *hAccelList = hNewAccelInfo; 
} 
 
 
/************************************* 
* 
*  Delete/Free accel. info. list.  
*                   
**************************************/ 
static void FreeAccelList( HACCELLIST * hAccelList ) 
{ 
  FPACCELINFO fpAccelInfo; 
  HACCELINFO  hTmpAccelInfo; 
 
  while( *hAccelList != 0 ) 
  { 
    /* Lock current node. */ 
    fpAccelInfo = (FPACCELINFO) GlobalLock( *hAccelList ) ; 
   
    /* Next node is to be new top node. */ 
    hTmpAccelInfo = fpAccelInfo->Next;  
     
    /* Unlock top handle. */ 
    GlobalUnlock( *hAccelList ); 
         
    /* Free top. */ 
    FreeAccelInfo( *hAccelList );  
 
    /* Assign new top. */ 
    *hAccelList = hTmpAccelInfo;  
  } 
} 
 
 
 
/************************************* 
* 
*  Get the next accel. info. structure 
*  after the given hAccelInfo. 
*                   
**************************************/ 
static HACCELINFO GetNextAccelInfo( HACCELINFO hAccelInfo ) 
{ 
  HACCELINFO hNextAccelInfo; 
  FPACCELINFO fpAccelInfo; 
   
  /* Handle bad. */ 
  if( hAccelInfo == 0 ) return 0; 
 
  /* Lock it. */ 
  fpAccelInfo = (FPACCELINFO) GlobalLock( hAccelInfo ) ; 
   
  /* Point new node to existing top node. */ 
  hNextAccelInfo = fpAccelInfo->Next; 
 
  /* Unlock it. */ 
  GlobalUnlock( hAccelInfo ) ; 
 
  /* Return next accel. info's handle. */ 
  return hNextAccelInfo; 
} 
 
 
 
/************************************* 
* 
*  Enumerates all ACCELINFO structures 
*  contained in the accel. info. list. 
*                   
**************************************/ 
static void EnumAccelInfo( HACCELLIST hAccelList, ACCELINFOENUMPROC AccelInfoEnumProc, LPARAM lParam ) 
{ 
  FPACCELINFO fpAccelInfo; 
  HACCELINFO hAccelInfo; 
  BOOL bReturn; 
   
   
  /* Get first accel. info's handle. */ 
  hAccelInfo = hAccelList; 
   
  while( hAccelInfo != 0 ) 
  { 
    /* Lock it. */ 
    fpAccelInfo = (FPACCELINFO) GlobalLock( hAccelInfo ) ; 
   
    /* Call callback function. */ 
    bReturn = (*AccelInfoEnumProc)( fpAccelInfo, lParam ); 
     
    /* Stop enumerating. */ 
    if( bReturn == FALSE ) 
    { 
      /* Unlock it. */ 
      GlobalUnlock( hAccelInfo ); 
 
      /* Stop enumerating. */ 
      return; 
    } 
     
    /* Unlock it. */ 
    GlobalUnlock( hAccelInfo ); 
 
    /* Get the next in the list. */ 
    hAccelInfo = GetNextAccelInfo( hAccelInfo ); 
  } 
} 
 
 
 
/************************************* 
* 
*  Remove and free an accelerator info. 
*  from the accel. info. list based on 
*  its wButtonID value. 
*                   
**************************************/ 
static BOOL DeleteAccelInfo( HACCELLIST * hAccelList, FPACCELINFO fpDelAccelInfo ) 
{ 
  FPACCELINFO fpAccelInfo, fpTmpAccelInfo; 
  HACCELINFO hAccelInfo, hTmpAccelInfo; 
   
 
  /* Existing first node. */ 
  if( *hAccelList == 0 ) return FALSE; 
 
  /* Lock top handle. */ 
  fpAccelInfo = (FPACCELINFO) GlobalLock( *hAccelList ) ; 
   
  /* If deleting top node. */ 
  if( fpAccelInfo->wKey == fpDelAccelInfo->wKey && 
      fpAccelInfo->wShiftState == fpDelAccelInfo->wShiftState ) 
  { 
    /* Next node is to be new top node. */ 
    hTmpAccelInfo = fpAccelInfo->Next;  
 
    /* Unlock top handle. */ 
    GlobalUnlock( *hAccelList ); 
     
    /* Free top. */ 
    FreeAccelInfo( *hAccelList );  
   
    /* Assign new top. */ 
    *hAccelList = hTmpAccelInfo; 
 
    /* Success. */ 
    return TRUE; 
  } 
 
  /* Unlock top handle. */ 
  GlobalUnlock( *hAccelList ); 
     
  /* Find correct node and remove. */ 
  hTmpAccelInfo = *hAccelList; 
  hAccelInfo = GetNextAccelInfo( *hAccelList ); 
 
  while( hAccelInfo != 0 ) 
  { 
    /* Lock current node. */ 
    fpAccelInfo = (FPACCELINFO) GlobalLock( hAccelInfo ) ; 
   
    /* If deleting current node. */ 
    if( fpAccelInfo->wKey == fpDelAccelInfo->wKey && 
        fpAccelInfo->wShiftState == fpDelAccelInfo->wShiftState ) 
    { 
      /* Lock previous node. */ 
      fpTmpAccelInfo = (FPACCELINFO) GlobalLock( hTmpAccelInfo ) ; 
 
      /* Previous node's "next node" is deleted node's "next node". */ 
      fpTmpAccelInfo->Next = fpAccelInfo->Next;  
   
      /* Unlock previous node. */ 
      GlobalUnlock( hTmpAccelInfo ); 
 
      /* Unlock current node. */ 
      GlobalUnlock( hAccelInfo ); 
       
      /* Free top. */ 
      FreeAccelInfo( hAccelInfo );  
   
      /* Success. */ 
      return TRUE; 
    } 
     
    /* Unlock it. */ 
    GlobalUnlock( hAccelInfo ) ; 
 
    /* Get next node. */ 
    hTmpAccelInfo = hAccelInfo; 
    hAccelInfo = GetNextAccelInfo( hAccelInfo ); 
  } 
 
  /* Did not find accel.. */ 
  return FALSE; 
}