Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

354 lines
10 KiB

/****************************** Module Header ******************************\
* Module Name: imehotky.c
*
* Copyright (c) Microsoft Corp. 1995-1996 All Rights Reserved
*
* Contents: Manage IME hotkey
*
* There are the following two kind of hotkeys defined in the IME specification.
*
* 1) IME hotkeys that changes the mode/status of current IME
* 2) IME hotkeys that causes IME (keyboard layout) change
*
* History:
* 10-Sep-1995 takaok Created for NT 3.51.
* 15-Mar-1996 takaok Ported to NT 4.0
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
#ifdef FE_IME
typedef struct _tagIMEHOTKEYOBJ {
struct _tagIMEHOTKEYOBJ *pNext;
IMEHOTKEY hk;
} IMEHOTKEYOBJ, *PIMEHOTKEYOBJ;
PIMEHOTKEYOBJ gpImeHotKeyListHeader = NULL;
PIMEHOTKEYOBJ DeleteImeHotKey( PIMEHOTKEYOBJ *ppHead, PIMEHOTKEYOBJ pDelete );
VOID AddImeHotKey( PIMEHOTKEYOBJ *ppHead, PIMEHOTKEYOBJ pAdd );
PIMEHOTKEYOBJ FindImeHotKeyByKey( PIMEHOTKEYOBJ pHead, UINT uModifyKeys, UINT uRL, UINT uVKey);
PIMEHOTKEYOBJ FindImeHotKeyByID( PIMEHOTKEYOBJ pHead, DWORD dwHotKeyID );
BOOL
GetImeHotKey(
DWORD dwHotKeyID,
PUINT puModifiers,
PUINT puVKey,
HKL *phKL )
{
PIMEHOTKEYOBJ ph;
ph = FindImeHotKeyByID( gpImeHotKeyListHeader, dwHotKeyID );
if ( ph == NULL ) {
RIPERR0(ERROR_HOTKEY_NOT_REGISTERED, RIP_WARNING, "No such IME hotkey");
return (FALSE);
}
//
// it is OK for NULL phKL, if the target hKL is NULL
//
if ( phKL ) {
*phKL = ph->hk.hKL;
} else if ( ph->hk.hKL != NULL ) {
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "phKL is null");
return (FALSE);
}
*puModifiers = ph->hk.uModifiers;
*puVKey = ph->hk.uVKey;
return (TRUE);
}
//
// Insert/remove the specified IME hotkey into/from
// the IME hotkey list (gpImeHotKeyListHeader).
//
BOOL
SetImeHotKey(
DWORD dwHotKeyID,
UINT uModifiers,
UINT uVKey,
HKL hKL,
DWORD dwAction )
{
PIMEHOTKEYOBJ ph;
switch ( dwAction ) {
case ISHK_REMOVE:
ph = FindImeHotKeyByID( gpImeHotKeyListHeader, dwHotKeyID );
if ( ph != NULL ) {
if ( DeleteImeHotKey( &gpImeHotKeyListHeader, ph ) == ph ) {
UserFreePool( ph );
return ( TRUE );
} else {
RIPMSG0( RIP_ERROR, "IME hotkey list is messed up" );
return ( FALSE );
}
} else {
RIPERR0( ERROR_INVALID_PARAMETER,
RIP_WARNING,
"no such IME hotkey registered");
return ( FALSE );
}
break;
case ISHK_INITIALIZE:
ph = gpImeHotKeyListHeader;
while ( ph != NULL ) {
PIMEHOTKEYOBJ phNext;
phNext = ph->pNext;
UserFreePool( ph );
ph = phNext;
}
gpImeHotKeyListHeader = NULL;
return TRUE;
case ISHK_ADD:
ph = FindImeHotKeyByKey( gpImeHotKeyListHeader,
uModifiers & MOD_MODIFY_KEYS,
uModifiers & MOD_BOTH_SIDES,
uVKey );
if ( ph != NULL ) {
if ( ph->hk.dwHotKeyID != dwHotKeyID ) {
RIPERR0( ERROR_HOTKEY_ALREADY_REGISTERED,
RIP_WARNING,
"There is an IME hotkey that has the same vkey/modifiers");
return ( FALSE );
}
// So far we found a hotkey that has the
// same vkey and same ID.
// But because modifiers may be slightly
// different, so go ahead and change it.
} else {
//
// the specified vkey/modifiers combination cound not be found
// in the hotkey list. The caller may want to change the key
// assignment of an existing hotkey or add a new hotkey.
//
ph = FindImeHotKeyByID( gpImeHotKeyListHeader, dwHotKeyID );
}
if ( ph == NULL ) {
//
// adding a new hotkey
//
ph = (PIMEHOTKEYOBJ)UserAllocPool( sizeof(IMEHOTKEY), TAG_IMEHOTKEY );
if ( ph == NULL ) {
RIPERR0( ERROR_OUTOFMEMORY,
RIP_WARNING,
"Memory allocation failed in SetImeHotKey");
return ( FALSE );
}
ph->hk.dwHotKeyID = dwHotKeyID;
ph->hk.uModifiers = uModifiers;
ph->hk.uVKey = uVKey;
ph->hk.hKL = hKL;
ph->pNext = NULL;
AddImeHotKey( &gpImeHotKeyListHeader, ph );
} else {
//
// changing an existing hotkey
//
ph->hk.uModifiers = uModifiers;
ph->hk.uVKey = uVKey;
ph->hk.hKL = hKL;
}
return ( TRUE );
break;
};
}
PIMEHOTKEYOBJ DeleteImeHotKey( PIMEHOTKEYOBJ *ppHead, PIMEHOTKEYOBJ pDelete )
{
PIMEHOTKEYOBJ ph;
if ( pDelete == *ppHead ) {
*ppHead = pDelete->pNext;
return pDelete;
}
for ( ph = *ppHead; ph != NULL; ph = ph->pNext ) {
if ( ph->pNext == pDelete ) {
ph->pNext = pDelete->pNext;
return pDelete;
}
}
return NULL;
}
VOID AddImeHotKey( PIMEHOTKEYOBJ *ppHead, PIMEHOTKEYOBJ pAdd )
{
PIMEHOTKEYOBJ ph;
if ( *ppHead == NULL ) {
*ppHead = pAdd;
} else {
ph = *ppHead;
while( ph->pNext != NULL )
ph = ph->pNext;
ph->pNext = pAdd;
}
return;
}
/**********************************************************************/
/* FindImeHotKeyByKey() */
/* Return Value: */
/* pHotKey - IMEHOTKEY pointer with the key, */
/* else NULL - failure */
/**********************************************************************/
PIMEHOTKEYOBJ FindImeHotKeyByKey( // Finds pHotKey with this input key
PIMEHOTKEYOBJ pHead,
UINT uModifyKeys, // the modify keys of this input key
UINT uRL, // the right and left hand side
UINT uVKey) // the input key
{
PIMEHOTKEYOBJ ph;
for (ph = pHead; ph != NULL; ph = ph->pNext) {
if (ph->hk.uVKey != uVKey) {
//
// vkey is different. Not need to see this any more
//
continue;
}
//
// vkey is same. Let's see the modifiers
//
if (ph->hk.uModifiers & MOD_IGNORE_ALL_MODIFIER) {
//
// doesn't care for modifiers.
//
return ph;
}
if ((ph->hk.uModifiers & MOD_MODIFY_KEYS) != uModifyKeys) {
continue;
}
//
// If both MOD_RIGHT and MOD_LEFT is set, it means that
// either key will work. For example, if we have a modifier
// like (MOD_ALT | MOD_RIGHT | MOD_LEFT), this means:
//
// ( [left alt key] OR [right alt key] ) AND vkey
//
if ( ((ph->hk.uModifiers & MOD_BOTH_SIDES) == uRL) ||
((ph->hk.uModifiers & MOD_BOTH_SIDES ) & uRL) ) {
return ph;
}
}
return (NULL);
}
/**********************************************************************/
/* FindImeHotKeyByID() */
/* Return Value: */
/* pHotKey - IMEHOTKEY pointer with the dwHotKeyID, */
/* else NULL - failure */
/**********************************************************************/
PIMEHOTKEYOBJ FindImeHotKeyByID( PIMEHOTKEYOBJ pHead, DWORD dwHotKeyID )
{
PIMEHOTKEYOBJ ph;
for ( ph = pHead; ph != NULL; ph = ph->pNext ) {
if ( ph->hk.dwHotKeyID == dwHotKeyID )
return (ph);
}
return (PIMEHOTKEYOBJ)NULL;
}
DWORD
CheckImeHotKey(
PQ pq, // input queue
UINT uVKey, // virtual key
LPARAM lParam // lparam of WM_KEYxxx message
)
{
static UINT uVKeySaved = 0;
PIMEHOTKEYOBJ ph;
UINT uModifiers = 0;
BOOL fKeyUp;
//
// early return for key up message
//
fKeyUp = ( lParam & 0x80000000 ) ? TRUE : FALSE;
if ( fKeyUp ) {
//
// if the uVKey is not same as the vkey
// we previously saved, there is no chance
// that this is a hotkey.
//
if ( uVKeySaved != uVKey ) {
uVKeySaved = 0;
return IME_INVALID_HOTKEY;
}
uVKeySaved = 0;
//
// If it's same, we still need to check
// the hotkey list because there is a
// chance that the hotkey list is modified
// between the key make and break.
//
}
//
// Current specification doesn't allow us to use a complex
// hotkey such as LSHIFT+RMENU+SPACE
//
if ( uVKey != VK_SHIFT ) {
uModifiers |= TestKeyStateDown( pq, VK_LSHIFT ) ? (MOD_SHIFT | MOD_LEFT) : 0;
uModifiers |= TestKeyStateDown( pq, VK_RSHIFT ) ? (MOD_SHIFT | MOD_RIGHT) : 0;
}
if ( uVKey != VK_CONTROL ) {
uModifiers |= TestKeyStateDown( pq, VK_LCONTROL ) ? (MOD_CONTROL | MOD_LEFT) : 0;
uModifiers |= TestKeyStateDown( pq, VK_RCONTROL ) ? (MOD_CONTROL | MOD_RIGHT) : 0;
}
if ( uVKey != VK_MENU ) {
uModifiers |= TestKeyStateDown( pq, VK_LMENU ) ? (MOD_ALT | MOD_LEFT) : 0;
uModifiers |= TestKeyStateDown( pq, VK_RMENU ) ? (MOD_ALT | MOD_RIGHT) : 0;
}
ph = FindImeHotKeyByKey( gpImeHotKeyListHeader,
uModifiers & MOD_MODIFY_KEYS,
uModifiers & MOD_BOTH_SIDES,
uVKey );
if ( ph != NULL ) {
if ( fKeyUp ) {
if ( ph->hk.uModifiers & MOD_ON_KEYUP ) {
return ph->hk.dwHotKeyID;
}
} else {
if ( ph->hk.uModifiers & MOD_ON_KEYUP ) {
//
// save vkey for next keyup message time
//
// when ALT+Z is a hotkey, we don't want
// to handle #2 as the hotkey sequence.
// 1) ALT make -> 'Z' make -> 'Z' break
// 2) 'Z' make -> ALT make -> 'Z' break
//
uVKeySaved = uVKey;
} else {
return ph->hk.dwHotKeyID;
}
}
}
return IME_INVALID_HOTKEY;
}
#endif