Leaked source code of windows server 2003
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.
 
 
 
 
 
 

394 lines
12 KiB

/***************************************************************************\
*
* DMMNEM.C -
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* Mnemonic Character Processing Routines
*
* ??-???-???? mikeke Ported from Win 3.0 sources
* 12-Feb-1991 mikeke Added Revalidation code
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/*
* There are several loops that we could get stuck in that we just forcibly
* break by a max iteration count. Ugly, but its legacy DialogManager
* issues.
*/
#define INFINITE_LOOP_CURE 1024
/***************************************************************************\
* FindMnemChar
*
* Returns: 0x00 if no matching char,
* 0x01 if menmonic char is matching,
* 0x80 if first char is matching
*
* History:
* 11-18-90 JimA Created.
\***************************************************************************/
int FindMnemChar(
LPWSTR lpstr,
WCHAR ch,
BOOL fFirst,
BOOL fPrefix)
{
WCHAR chc;
WCHAR chFirst;
while (*lpstr == TEXT(' '))
lpstr++;
ch = (WCHAR)(ULONG_PTR)CharLowerW((LPWSTR)ULongToPtr( (DWORD)(UTCHAR)ch ));
chFirst = (WCHAR)(ULONG_PTR)CharLowerW((LPWSTR)ULongToPtr( (DWORD)(UTCHAR)(*lpstr) ));
if (fPrefix) {
WORD wvch, xvkey;
//
// get OEM-dependent virtual key code
//
if (IS_DBCS_ENABLED() && (wvch = VkKeyScanW(ch)) != -1)
wvch &= 0x00FF;
while (chc = *lpstr++) {
//
// This should think about KOREA & TAIWAN case. But probably OK.
//
if ((chc == CH_PREFIX) || (chc == CH_ENGLISHPREFIX && IS_DBCS_ENABLED())) {
WORD chnext = (WCHAR)(ULONG_PTR)CharLowerW((LPWSTR)ULongToPtr( (DWORD)(UTCHAR)*lpstr ));
if (chnext == CH_PREFIX) {
//
// Two CH_PREFIX in the resrc string results in one "&" in the text displayed
//
lpstr++;
} else {
if (chnext == ch) {
return 0x01;
}
if (IS_DBCS_ENABLED()) {
//
// Compare should be done with virtual key in Kanji menu mode
// in order to accept Digit shortcut key and save English
// windows applications!
//
xvkey = VkKeyScanW(chnext);
if (xvkey != 0xFFFF && ((xvkey & 0x00FF) == wvch)) {
return 0x01;
}
}
return 0x00;
}
}
}
}
#if 0 // the original US code on NT4
if (fPrefix) {
while (chc = *lpstr++) {
if (((WCHAR)CharLower((LPWSTR)(DWORD)(UTCHAR)chc) == CH_PREFIX)) {
chnext = (WCHAR)CharLowerW((LPWSTR)(DWORD)(UTCHAR)*lpstr);
if (chnext == CH_PREFIX)
lpstr++;
else if (chnext == ch)
return 0x01;
else {
return 0x00;
}
}
}
}
#endif // FE_SB
if (fFirst && (ch == chFirst))
return 0x80;
return 0x00;
}
/***************************************************************************\
* xxxFindNextMnem
*
* This function returns NULL if no control with the specified mnemonic
* can be found.
*
* History:
\***************************************************************************/
PWND xxxGNM_FindNextMnem(
PWND pwndDlg,
PWND pwnd,
WCHAR ch)
{
PWND pwndStart;
PWND pwndT;
WCHAR rgchText[256];
int i = 0;
TL tlpwndStart;
TL tlpwnd;
DWORD dwDlgCode;
CheckLock(pwndDlg);
CheckLock(pwnd);
/*
* Check if we are in a group box so we can find local mnemonics.
*/
pwndStart = _GetChildControl(pwndDlg, pwnd);
ThreadLock(pwndStart, &tlpwndStart);
while (TRUE) {
pwndT = _GetNextDlgGroupItem(pwndDlg, pwndStart, FALSE);
ThreadUnlock(&tlpwndStart);
i++;
if (pwndT == NULL || pwndT == pwnd || i > INFINITE_LOOP_CURE) {
/*
* If we have returned to our starting window or if we have gone
* through INFINITE_LOOP_CURE iterations, let's exit. There are
* no local mnemonics that match. We have to check for
* INFINITE_LOOP_CURE iterations (or so) because we run into
* problems with WS_GROUP not being properly defined in rc files
* that we never reach this same starting window again....
*/
break;
}
pwndStart = pwndT;
/*
* Only check for matching mnemonic if control doesn't want characters
* and control isn't a static control with SS_NOPREFIX
*/
ThreadLock(pwndStart, &tlpwndStart);
dwDlgCode = (DWORD)SendMessage(HWq(pwndT), WM_GETDLGCODE, 0, 0L);
if (!(dwDlgCode & DLGC_WANTCHARS) &&
(!(dwDlgCode & DLGC_STATIC) || !(pwndT->style & SS_NOPREFIX))) {
GetWindowText(HWq(pwndT), rgchText, sizeof(rgchText)/sizeof(WCHAR));
if (FindMnemChar(rgchText, ch, FALSE, TRUE) != 0) {
ThreadUnlock(&tlpwndStart);
return pwndT;
}
}
}
pwnd = pwndStart = _GetChildControl(pwndDlg, pwnd);
i = 0;
ThreadLock(pwnd, &tlpwnd);
while (TRUE) {
/*
* Start with next so we see multiples of same mnemonic.
*/
pwnd = _NextControl(pwndDlg, pwnd, TRUE);
ThreadUnlock(&tlpwnd);
ThreadLock(pwnd, &tlpwnd);
/*
* Only check for matching mnemonic if control doesn't want characters
* and control isn't a static control with SS_NOPREFIX
*/
dwDlgCode = (DWORD)SendMessage(HW(pwnd), WM_GETDLGCODE, 0, 0L);
if (!(dwDlgCode & DLGC_WANTCHARS) &&
(!(dwDlgCode & DLGC_STATIC) || !(pwnd->style & SS_NOPREFIX))) {
GetWindowText(HW(pwnd), rgchText, sizeof(rgchText)/sizeof(WCHAR));
if (FindMnemChar(rgchText, ch, FALSE, TRUE) != 0)
break;
}
i++;
if (pwnd == pwndStart || i > INFINITE_LOOP_CURE) {
pwnd = NULL;
break;
}
}
ThreadUnlock(&tlpwnd);
return pwnd;
}
/***************************************************************************\
* xxxGotoNextMnem
*
* History:
\***************************************************************************/
PWND xxxGotoNextMnem(
PWND pwndDlg,
PWND pwnd,
WCHAR ch)
{
UINT code;
PWND pwndFirstFound = NULL;
int count = 0;
TL tlpwnd;
PWND pwndT;
HWND hwnd;
CheckLock(pwndDlg);
CheckLock(pwnd);
ThreadLock(pwnd, &tlpwnd);
/*
* Loop for a long time but not long enough so we hang...
*/
while (count < INFINITE_LOOP_CURE) {
/*
* If the dialog box doesn't has the mnemonic specified, return NULL.
*/
if ((pwnd = xxxGNM_FindNextMnem(pwndDlg, pwnd, ch)) == NULL) {
ThreadUnlock(&tlpwnd);
return NULL;
}
hwnd = HWq(pwnd);
ThreadUnlock(&tlpwnd);
ThreadLock(pwnd, &tlpwnd);
code = (UINT)SendMessage(hwnd, WM_GETDLGCODE, 0, 0L);
/*
* If a non-disabled static item, then jump ahead to nearest tabstop.
*/
if (code & DLGC_STATIC && !TestWF(pwnd, WFDISABLED)) {
pwndT = _GetNextDlgTabItem(pwndDlg, pwnd, FALSE);
/*
* If there is no other tab item, keep looking
*/
if (pwndT == NULL)
continue;
pwnd = pwndT;
hwnd = HWq(pwnd);
ThreadUnlock(&tlpwnd);
ThreadLock(pwnd, &tlpwnd);
/*
* I suppose we should do a getdlgcode here, but who is going to
* label a button with a static control? The setup guys, that's
* who... Also, generally useful for ownerdraw buttons which are
* labeled with a static text item.
*/
code = (UINT)SendMessage(hwnd, WM_GETDLGCODE, 0, 0L);
}
if (!TestWF(pwnd, WFDISABLED)) {
/*
* Is it a Pushbutton?
*/
if (!(code & DLGC_BUTTON)) {
/*
* No, simply give it the focus.
*/
DlgSetFocus(hwnd);
} else {
/*
* Yes, click it, but don't give it the focus.
*/
if ((code & DLGC_DEFPUSHBUTTON) || (code & DLGC_UNDEFPUSHBUTTON)) {
/*
* Flash the button.
*/
SendMessage(hwnd, BM_SETSTATE, TRUE, 0L);
/*
* Delay
*/
#ifdef LATER
// JimA - 2/19/92
// There oughta be a better way of doing this...
for (i = 0; i < 10000; i++)
;
#else
Sleep(1);
#endif
/*
* Un-Flash it.
*/
SendMessage(hwnd, BM_SETSTATE, FALSE, 0L);
/*
* Send the WM_COMMAND message.
*/
pwndT = REBASEPWND(pwnd, spwndParent);
SendMessage(HW(pwndT), WM_COMMAND,
MAKELONG(PTR_TO_ID(pwnd->spmenu), BN_CLICKED), (LPARAM)hwnd);
ThreadUnlock(&tlpwnd);
return (PWND)1;
} else {
/*
* Because BM_CLICK processing will result in BN_CLICK msg,
* xxxSetFocus must be prevented from sending the same msg;
* Otherwise, it will notify parent twice!
* Fix for Bug #3024 -- SANKAR -- 09-22-89 --
*/
BOOL fIsNTButton;
PBUTN pbutn;
fIsNTButton = IS_BUTTON(pwnd);
if (fIsNTButton) {
pbutn = ((PBUTNWND)pwnd)->pbutn;
BUTTONSTATE(pbutn) |= BST_DONTCLICK;
} else {
RIPMSG0(RIP_WARNING, "xxxGotoNextMnem: fnid != FNID_BUTTON");
}
DlgSetFocus(hwnd);
if (fIsNTButton) {
BUTTONSTATE(pbutn) &= ~BST_DONTCLICK;
}
/*
* Send click message if button has a UNIQUE mnemonic
*/
if (xxxGNM_FindNextMnem(pwndDlg, pwnd, ch) == pwnd) {
SendMessage(hwnd, BM_CLICK, TRUE, 0L);
}
}
}
ThreadUnlock(&tlpwnd);
return pwnd;
} else {
/*
* Stop if we've looped back to the first item we checked
*/
if (pwnd == pwndFirstFound) {
ThreadUnlock(&tlpwnd);
return NULL;
}
if (pwndFirstFound == NULL)
pwndFirstFound = pwnd;
}
count++;
} /* Loop for a long time */
ThreadUnlock(&tlpwnd);
return NULL;
}