test: dmmnem.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# dmmnem.c

Go to the documentation of this file.

    00001 /***************************************************************************\
    00002 *
    00003 *  DMMNEM.C -
    00004 *
    00005 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00006 *
    00007 *      Mnemonic Character Processing Routines
    00008 *
    00009 * ??-???-???? mikeke    Ported from Win 3.0 sources
    00010 * 12-Feb-1991 mikeke    Added Revalidation code
    00011 \***************************************************************************/
    00012
    00013 #include "precomp.h"
    00014 #pragma hdrstop
    00015
    00016 /***************************************************************************\
    00017 * FindMnemChar
    00018 *
    00019 * Returns: 0x00 if no matching char,
    00020 *          0x01 if menmonic char is matching,
    00021 *          0x80 if first char is matching
    00022 *
    00023 * History:
    00024 *   11-18-90 JimA       Created.
    00025 \***************************************************************************/
    00026
    00027 int FindMnemChar(
    00028     LPWSTR lpstr,
    00029     WCHAR ch,
    00030     BOOL fFirst,
    00031     BOOL fPrefix)
    00032 {
    00033     WCHAR chc;
    00034     WCHAR chnext;
    00035     WCHAR chFirst;
    00036
    00037     while (*lpstr == TEXT(' '))
    00038         lpstr++;
    00039
    00040     ch = (WCHAR)(ULONG_PTR)CharLowerW((LPWSTR)ULongToPtr( (DWORD)(UTCHAR)ch ));
    00041     chFirst = (WCHAR)(ULONG_PTR)CharLowerW((LPWSTR)ULongToPtr( (DWORD)(UTCHAR)(*lpstr) ));
    00042
    00043 #ifdef FE_SB // FindMnemChar()
    00044     //
    00045     // HIRO: LATER: CH_ENGLISHPREFIX is obsolete, so entire FE_SB can be removed ?
    00046     //
    00047     if (fPrefix) {
    00048         SHORT wvch, xvkey;
    00049         //
    00050         // get OEM-dependent virtual key code
    00051         //
    00052         if ((wvch = VkKeyScanW(ch)) != -1)
    00053             wvch &= 0x00FF;
    00054
    00055         while (chc = *lpstr++) {
    00056             //
    00057             // This should think about KOREA & TAIWAN case. But probably OK.
    00058             //
    00059             if ((chc == CH_PREFIX) || (chc == CH_ENGLISHPREFIX)) {
    00060                 chnext = (WCHAR)(ULONG_PTR)CharLowerW((LPWSTR)ULongToPtr( (DWORD)(UTCHAR)*lpstr ));
    00061
    00062                 if (chnext == CH_PREFIX)
    00063                     lpstr++;
    00064                 else if (chnext == ch)
    00065                     return(0x01);
    00066                 else {
    00067                     //
    00068                     // Compare should be done with virtual key in Kanji menu mode
    00069                     // in order to accept Digit shortcut key and save English
    00070                     // windows applications!
    00071                     //
    00072                     xvkey = VkKeyScanW(chnext);
    00073                     if (xvkey != 0xFFFF && ((xvkey & 0x00FF) == wvch))
    00074                         return(0x01);
    00075                     else
    00076                         return(0x00);
    00077                }
    00078             }
    00079         }
    00080     }
    00081 #else
    00082     if (fPrefix) {
    00083         while (chc = *lpstr++) {
    00084             if (((WCHAR)CharLower((LPWSTR)(DWORD)(UTCHAR)chc) == CH_PREFIX)) {
    00085                 chnext = (WCHAR)CharLowerW((LPWSTR)(DWORD)(UTCHAR)*lpstr);
    00086
    00087                 if (chnext == CH_PREFIX)
    00088                     lpstr++;
    00089                 else if (chnext == ch)
    00090                     return 0x01;
    00091                 else {
    00092                     return 0x00;
    00093                 }
    00094             }
    00095         }
    00096     }
    00097 #endif // FE_SB
    00098
    00099     if (fFirst && (ch == chFirst))
    00100         return 0x80;
    00101
    00102     return 0x00;
    00103 }
    00104
    00105
    00106 /***************************************************************************\
    00107 * xxxFindNextMnem
    00108 *
    00109 * This function returns NULL if no control with the specified mnemonic
    00110 * can be found.
    00111 *
    00112 * History:
    00113 \***************************************************************************/
    00114
    00115 PWND xxxGNM_FindNextMnem(
    00116     PWND pwndDlg,
    00117     PWND pwnd,
    00118     WCHAR ch)
    00119 {
    00120     PWND pwndStart;
    00121     PWND pwndT;
    00122     WCHAR rgchText[256];
    00123     int i = 0;
    00124     TL tlpwndStart;
    00125     TL tlpwnd;
    00126     DWORD dwDlgCode;
    00127
    00128     CheckLock(pwndDlg);
    00129     CheckLock(pwnd);
    00130
    00131     /*
    00132      * Check if we are in a group box so we can find local mnemonics.
    00133      */
    00134
    00135     pwndStart = _GetChildControl(pwndDlg, pwnd);
    00136     ThreadLock(pwndStart, &tlpwndStart);
    00137
    00138     while (TRUE) {
    00139
    00140         pwndT = _GetNextDlgGroupItem(pwndDlg, pwndStart, FALSE);
    00141
    00142         ThreadUnlock(&tlpwndStart);
    00143
    00144         i++;
    00145         if (pwndT == NULL || pwndT == pwnd || i > 60) {
    00146
    00147             /*
    00148              * If we have returned to our starting window or if we have gone
    00149              * through 60 iterations, let's exit.  There are no local mnemonics
    00150              * that match.  We have to check for 60 iterations (or so) because
    00151              * we run into problems with WS_GROUP not being properly defined in
    00152              * rc files that we never reach this same starting window again....
    00153              */
    00154             break;
    00155         }
    00156
    00157         pwndStart = pwndT;
    00158
    00159         /*
    00160          * Only check for matching mnemonic if control doesn't want characters
    00161          * and control isn't a static control with SS_NOPREFIX
    00162          */
    00163         ThreadLock(pwndStart, &tlpwndStart);
    00164
    00165         dwDlgCode = (DWORD)SendMessage(HWq(pwndT), WM_GETDLGCODE, 0, 0L);
    00166         if (!(dwDlgCode & DLGC_WANTCHARS) &&
    00167                 (!(dwDlgCode & DLGC_STATIC) || !(pwndT->style & SS_NOPREFIX))) {
    00168             GetWindowText(HWq(pwndT), rgchText, sizeof(rgchText)/sizeof(WCHAR));
    00169             if (FindMnemChar(rgchText, ch, FALSE, TRUE) != 0) {
    00170                 ThreadUnlock(&tlpwndStart);
    00171                 return pwndT;
    00172             }
    00173         }
    00174     }
    00175
    00176     pwnd = pwndStart = _GetChildControl(pwndDlg, pwnd);
    00177
    00178     ThreadLock(pwnd, &tlpwnd);
    00179     while (TRUE) {
    00180
    00181         /*
    00182          * Start with next so we see multiples of same mnemonic.
    00183          */
    00184         pwnd = _NextControl(pwndDlg, pwnd, TRUE);
    00185
    00186         ThreadUnlock(&tlpwnd);
    00187         ThreadLock(pwnd, &tlpwnd);
    00188
    00189
    00190
    00191         /*
    00192          * Only check for matching mnemonic if control doesn't want characters
    00193          * and control isn't a static control with SS_NOPREFIX
    00194          */
    00195         dwDlgCode = (DWORD)SendMessage(HW(pwnd), WM_GETDLGCODE, 0, 0L);
    00196         if (!(dwDlgCode & DLGC_WANTCHARS) &&
    00197                 (!(dwDlgCode & DLGC_STATIC) || !(pwnd->style & SS_NOPREFIX))) {
    00198             GetWindowText(HW(pwnd), rgchText, sizeof(rgchText)/sizeof(WCHAR));
    00199             if (FindMnemChar(rgchText, ch, FALSE, TRUE) != 0)
    00200                 break;
    00201         }
    00202
    00203         if (pwnd == pwndStart) {
    00204             pwnd = NULL;
    00205             break;
    00206         }
    00207     }
    00208     ThreadUnlock(&tlpwnd);
    00209
    00210     return pwnd;
    00211 }
    00212
    00213 /***************************************************************************\
    00214 * xxxGotoNextMnem
    00215 *
    00216 * History:
    00217 \***************************************************************************/
    00218
    00219 PWND xxxGotoNextMnem(
    00220     PWND pwndDlg,
    00221     PWND pwnd,
    00222     WCHAR ch)
    00223 {
    00224     UINT code;
    00225     PWND pwndFirstFound = NULL;
    00226     int count = 0;
    00227     TL tlpwnd;
    00228     PWND pwndT;
    00229     HWND hwnd;
    00230
    00231     CheckLock(pwndDlg);
    00232     CheckLock(pwnd);
    00233
    00234     ThreadLock(pwnd, &tlpwnd);
    00235
    00236     /*
    00237      * Loop for a long time but not long enough so we hang...
    00238      */
    00239     while (count < 256 * 2) {
    00240
    00241         /*
    00242          * If the dialog box doesn't has the mnemonic specified, return NULL.
    00243          */
    00244         if ((pwnd = xxxGNM_FindNextMnem(pwndDlg, pwnd, ch)) == NULL) {
    00245             ThreadUnlock(&tlpwnd);
    00246             return NULL;
    00247         }
    00248         hwnd = HWq(pwnd);
    00249
    00250         ThreadUnlock(&tlpwnd);
    00251         ThreadLock(pwnd, &tlpwnd);
    00252
    00253         code = (UINT)SendMessage(hwnd, WM_GETDLGCODE, 0, 0L);
    00254
    00255         /*
    00256          * If a non-disabled static item, then jump ahead to nearest tabstop.
    00257          */
    00258         if (code & DLGC_STATIC && !TestWF(pwnd, WFDISABLED)) {
    00259             pwndT = _GetNextDlgTabItem(pwndDlg, pwnd, FALSE);
    00260
    00261             /*
    00262              * If there is no other tab item, keep looking
    00263              */
    00264             if (pwndT == NULL)
    00265                 continue;
    00266             pwnd = pwndT;
    00267             hwnd = HWq(pwnd);
    00268
    00269             ThreadUnlock(&tlpwnd);
    00270             ThreadLock(pwnd, &tlpwnd);
    00271
    00272             /*
    00273              * I suppose we should do a getdlgcode here, but who is going to
    00274              * label a button with a static control?  The setup guys, that's
    00275              * who...  Also, generally useful for ownerdraw buttons which are
    00276              * labeled with a static text item.
    00277              */
    00278             code = (UINT)SendMessage(hwnd, WM_GETDLGCODE, 0, 0L);
    00279         }
    00280
    00281         if (!TestWF(pwnd, WFDISABLED)) {
    00282
    00283             /*
    00284              * Is it a Pushbutton?
    00285              */
    00286             if (!(code & DLGC_BUTTON)) {
    00287
    00288                 /*
    00289                  * No, simply give it the focus.
    00290                  */
    00291                 DlgSetFocus(hwnd);
    00292             } else {
    00293
    00294                 /*
    00295                  * Yes, click it, but don't give it the focus.
    00296                  */
    00297                 if ((code & DLGC_DEFPUSHBUTTON) || (code & DLGC_UNDEFPUSHBUTTON)) {
    00298
    00299                     /*
    00300                      * Flash the button.
    00301                      */
    00302                     SendMessage(hwnd, BM_SETSTATE, TRUE, 0L);
    00303
    00304                     /*
    00305                      * Delay
    00306                      */
    00307 #ifdef LATER
    00308 // JimA - 2/19/92
    00309 // There oughta be a better way of doing this...
    00310                     for (i = 0; i < 10000; i++)
    00311                         ;
    00312 #else
    00313                     Sleep(1);
    00314 #endif
    00315
    00316                     /*
    00317                      * Un-Flash it.
    00318                      */
    00319                     SendMessage(hwnd, BM_SETSTATE, FALSE, 0L);
    00320
    00321                     /*
    00322                      * Send the WM_COMMAND message.
    00323                      */
    00324                     pwndT = REBASEPWND(pwnd, spwndParent);
    00325                     SendMessage(HW(pwndT), WM_COMMAND,
    00326                             MAKELONG(PTR_TO_ID(pwnd->spmenu), BN_CLICKED), (LPARAM)hwnd);
    00327                     ThreadUnlock(&tlpwnd);
    00328                     return (PWND)1;
    00329                 } else {
    00330
    00331                     /*
    00332                      * Because BM_CLICK processing will result in BN_CLICK msg,
    00333                      * xxxSetFocus must be prevented from sending the same msg;
    00334                      * Otherwise, it will notify parent twice!
    00335                      * Fix for Bug #3024 -- SANKAR -- 09-22-89 --
    00336                      */
    00337                     BOOL fIsNTButton;
    00338                     PBUTN pbutn;
    00339
    00340                     fIsNTButton = (pwnd->fnid == FNID_BUTTON);
    00341                     if (fIsNTButton) {
    00342                       pbutn = ((PBUTNWND)pwnd)->pbutn;
    00343                       BUTTONSTATE(pbutn) |= BST_DONTCLICK;
    00344                     } else {
    00345                      RIPMSG0(RIP_WARNING, "xxxGotoNextMnem: fnid != FNID_BUTTON");
    00346                     }
    00347
    00348                     DlgSetFocus(hwnd);
    00349
    00350                     if (fIsNTButton) {
    00351                       BUTTONSTATE(pbutn) &= ~BST_DONTCLICK;
    00352                     }
    00353
    00354                     /*
    00355                      * Send click message if button has a UNIQUE mnemonic
    00356                      */
    00357                     if (xxxGNM_FindNextMnem(pwndDlg, pwnd, ch) == pwnd) {
    00358                         SendMessage(hwnd, BM_CLICK, TRUE, 0L);
    00359                     }
    00360                 }
    00361             }
    00362
    00363             ThreadUnlock(&tlpwnd);
    00364             return pwnd;
    00365         } else {
    00366
    00367             /*
    00368              * Stop if we've looped back to the first item we checked
    00369              */
    00370             if (pwnd == pwndFirstFound) {
    00371                 ThreadUnlock(&tlpwnd);
    00372                 return NULL;
    00373             }
    00374
    00375             if (pwndFirstFound == NULL)
    00376                 pwndFirstFound = pwnd;
    00377         }
    00378
    00379         count++;
    00380
    00381     }  /* Loop for a long time */
    00382
    00383     ThreadUnlock(&tlpwnd);
    00384     return NULL;
    00385 }