Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

winaccel.cpp

Go to the documentation of this file.
00001 /* $Id: winaccel.cpp,v 1.10 2001/11/21 11:51:39 sandervl Exp $ */
00002 /*
00003  * Win32 accelerator key functions for OS/2
00004  *
00005  * Based on Wine: (windows\input.c; loader\resource.c) (20000130)
00006  * Copyright 1993 Bob Amstadt
00007  * Copyright 1996 Albrecht Kleine
00008  * Copyright 1997 David Faure
00009  * Copyright 1998 Morten Welinder
00010  * Copyright 1998 Ulrich Weigand
00011  * Copyright 1993 Robert J. Amstadt
00012  * Copyright 1995 Alexandre Julliard
00013  *
00014  * Project Odin Software License can be found in LICENSE.TXT
00015  *
00016  */
00017 #include <os2win.h>
00018 #include <misc.h>
00019 #include <heapstring.h>
00020 #include "win32wbase.h"
00021 #include <win\winnls.h>
00022 
00023 #define DBG_LOCALLOG    DBG_winaccel
00024 #include "dbglocal.h"
00025 
00026 /**********************************************************************
00027  *           KBD_translate_accelerator
00028  *
00029  * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP  -messages
00030  */
00031 static BOOL KBD_translate_accelerator(HWND hWnd,LPMSG msg,
00032                                       BYTE fVirt,WORD key,WORD cmd)
00033 {
00034     BOOL sendmsg = FALSE;
00035 
00036     if(msg->wParam == key)
00037     {
00038         if (msg->message == WM_CHAR) {
00039             if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
00040             {
00041                 dprintf(("TranslateAccelerator: found accel for WM_CHAR: ('%c')\n", msg->wParam&0xff));
00042                 sendmsg=TRUE;
00043             }
00044         }
00045         else
00046         {
00047             if(fVirt & FVIRTKEY) {
00048                 INT mask = 0;
00049                 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
00050                 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
00051                 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
00052 
00053                 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
00054                         sendmsg=TRUE;
00055                 else    dprintf(("TranslateAccelerator: but incorrect SHIFT/CTRL/ALT-state %x != %x", mask, fVirt));
00056             }
00057             else
00058             {
00059                 if (!(msg->lParam & 0x01000000))  /* no special_key */
00060                 {
00061                     if ((fVirt & FALT) && (msg->lParam & 0x20000000))
00062                     {                                                   /* ^^ ALT pressed */
00063                         dprintf(("TranslateAccelerator: found accel for Alt-%c\n", msg->wParam&0xff));
00064                         sendmsg=TRUE;
00065                     }
00066                 }
00067             }
00068         }
00069 
00070         if (sendmsg)      /* found an accelerator, but send a message... ? */
00071         {
00072             INT  iSysStat,iStat,mesg=0;
00073             HMENU hMenu;
00074 
00075             if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP) {
00076                 mesg=1;
00077             }
00078             else
00079                 if (GetCapture())
00080                     mesg=2;
00081                 else
00082                 if (!IsWindowEnabled(hWnd))
00083                     mesg=3;
00084                 else
00085                 {
00086                     Win32BaseWindow *window;
00087 
00088                     window = Win32BaseWindow::GetWindowFromHandle(hWnd);
00089                     if(!window) {
00090                         return FALSE; //should never happen! (already checked)
00091                     }
00092 
00093                     hMenu = GetMenu(hWnd);
00094 
00095                     iSysStat = (window->GetSysMenu()) ? GetMenuState(GetSubMenu(window->GetSysMenu(), 0),
00096                                                                      cmd, MF_BYCOMMAND) : -1 ;
00097                     iStat = (hMenu) ? GetMenuState(hMenu, cmd, MF_BYCOMMAND) : -1 ;
00098 
00099                     if (iSysStat!=-1)
00100                     {
00101                         if (iSysStat & (MF_DISABLED|MF_GRAYED))
00102                             mesg=4;
00103                         else
00104                             mesg=WM_SYSCOMMAND;
00105                     }
00106                     else
00107                     {
00108                         if (iStat!=-1)
00109                         {
00110                             if (IsIconic(hWnd)) {
00111                                 mesg=5;
00112                             }
00113                             else
00114                             {
00115                                 if (iStat & (MF_DISABLED|MF_GRAYED))
00116                                     mesg=6;
00117                                 else
00118                                     mesg=WM_COMMAND;
00119                             }
00120                         }
00121                         else
00122                             mesg=WM_COMMAND;
00123                     }
00124                     RELEASE_WNDOBJ(window);
00125                 }
00126                 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
00127                 {
00128                     SendMessageA(hWnd, mesg, cmd, 0x00010000L);
00129                 }
00130                 else
00131                 {
00132                     /*  some reasons for NOT sending the WM_{SYS}COMMAND message:
00133                      *   #0: unknown (please report!)
00134                      *   #1: for WM_KEYUP,WM_SYSKEYUP
00135                      *   #2: mouse is captured
00136                      *   #3: window is disabled
00137                      *   #4: it's a disabled system menu option
00138                      *   #5: it's a menu option, but window is iconic
00139                      *   #6: it's a menu option, but disabled
00140                      */
00141                     if(mesg==0)
00142                             dprintf(("ERROR: unknown reason - please report!"));
00143                     else    dprintf(("but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg));
00144 
00145                 }
00146                 return TRUE;
00147             }
00148             dprintf(("TranslateAccelerator: not match for %x %x %x", fVirt, key, cmd));
00149     }
00150     return FALSE;
00151 }
00152 /*****************************************************************************
00153  * Name      : int WIN32API TranslateAcceleratorA
00154  * Purpose   : Translate WM_*KEYDOWN messages to WM_COMMAND messages
00155  *             according to Accelerator table
00156  * Parameters: HWND hwnd, HACCEL haccel, LPMSG lpmsg
00157  * Variables :
00158  * Result    : int FALSE (no accelerator found) TRUE (accelerator found)
00159  * Remark    : if a accelerator is found it is not neccesarely executed
00160  *             depends on window stat
00161  *
00162  *****************************************************************************/
00163 INT WINAPI TranslateAcceleratorA(HWND hWnd, HACCEL hAccel, LPMSG msg)
00164 {
00165     /* YES, Accel16! */
00166     LPACCEL lpAccelTbl;
00167     int i;
00168 
00169     SetLastError(ERROR_SUCCESS);
00170     if (msg == NULL)
00171     {
00172           dprintf(("TranslateAcceleratorAmsg null; should hang here to be win compatible"));
00173           SetLastError(ERROR_INVALID_PARAMETER);
00174           return 0;
00175     }
00176     if (!hAccel || !(lpAccelTbl = (LPACCEL)GlobalLock(hAccel)))
00177     {
00178           dprintf(("TranslateAcceleratorA: invalid accel handle=%x", hAccel));
00179           SetLastError(ERROR_INVALID_PARAMETER);
00180           return 0;
00181     }
00182     if(!IsWindow(hWnd)) {
00183           dprintf(("TranslateAccelerator, window %x not found", hWnd));
00184           SetLastError(ERROR_INVALID_WINDOW_HANDLE);
00185           return 0;
00186     }
00187     if ((msg->message != WM_KEYDOWN &&
00188          msg->message != WM_KEYUP &&
00189          msg->message != WM_SYSKEYDOWN &&
00190          msg->message != WM_SYSKEYUP &&
00191          msg->message != WM_CHAR))
00192     {
00193           return 0;
00194     }
00195 
00196 /*    TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
00197       "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%lx\n",
00198       hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam); */
00199 
00200     i = 0;
00201     do
00202     {
00203         if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
00204                                       lpAccelTbl[i].key,lpAccelTbl[i].cmd))
00205         {
00206             return 1;
00207         }
00208     }
00209     while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
00210 
00211 //    WARN_(accel)("couldn't translate accelerator key\n");
00212     return 0;
00213 }
00214 /**********************************************************************
00215  *                      LoadAccelerators32W     [USER.177]
00216  * The image layout seems to look like this (not 100% sure):
00217  * 00:  BYTE    type            type of accelerator
00218  * 01:  BYTE    pad             (to WORD boundary)
00219  * 02:  WORD    event
00220  * 04:  WORD    IDval           
00221  * 06:  WORD    pad             (to DWORD boundary)
00222  */
00223 HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
00224 {
00225     HRSRC hRsrc;
00226     HACCEL hMem,hRetval=0;
00227     DWORD size;
00228 
00229     if (!(hRsrc = FindResourceW( instance, lpTableName, RT_ACCELERATORW )))
00230     {
00231         dprintf(("LoadAcceleratorsW couldn't find accelerator table resource %x %x", instance, lpTableName));
00232         return 0;
00233     }
00234     else {
00235         hMem = LoadResource( instance, hRsrc );
00236         size = SizeofResource( instance, hRsrc );
00237         if(size >= sizeof(PE_ACCEL))
00238         {
00239                 LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
00240                 LPACCEL accel;
00241                 int i,nrofaccells = size/sizeof(PE_ACCEL);
00242 
00243                 hRetval = GlobalAlloc(0,sizeof(ACCEL)*nrofaccells);
00244                 accel   = (LPACCEL)GlobalLock(hRetval);
00245         
00246                 for (i=0;i<nrofaccells;i++) {
00247                         accel[i].fVirt = accel_table[i].fVirt;
00248                         accel[i].key = accel_table[i].key;
00249                         accel[i].cmd = accel_table[i].cmd;
00250                 }
00251                 accel[i-1].fVirt |= 0x80;
00252         }
00253     }
00254     dprintf(("LoadAcceleratorsW returned %x %x %x\n", instance, lpTableName, hRetval));
00255     return hRetval;
00256 }
00257 
00258 HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
00259 {
00260         LPWSTR   uni;
00261         HACCEL result;
00262         if (HIWORD(lpTableName))
00263                 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
00264         else
00265                 uni = (LPWSTR)lpTableName;
00266         result = LoadAcceleratorsW(instance,uni);
00267         if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
00268         return result;
00269 }
00270 
00271 /**********************************************************************
00272  *             CopyAcceleratorTable32A   (USER32.58)
00273  */
00274 INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
00275 {
00276   return CopyAcceleratorTableW(src, dst, entries);
00277 }
00278 
00279 /**********************************************************************
00280  *             CopyAcceleratorTable32W   (USER32.59)
00281  *
00282  * By mortene@pvv.org 980321
00283  */
00284 INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT entries)
00285 {
00286   int i,xsize;
00287   LPACCEL accel = (LPACCEL)GlobalLock(src);
00288   BOOL done = FALSE;
00289 
00290   /* Do parameter checking to avoid the explosions and the screaming
00291      as far as possible. */
00292   if((dst && (entries < 1)) || (src == (HACCEL)NULL) || !accel)
00293   {
00294         dprintf(("CopyAcceleratorTableW: Application sent invalid parameters (%p %p %d).\n", (LPVOID)src, (LPVOID)dst, entries));
00295         SetLastError(ERROR_INVALID_PARAMETER);
00296         return 0;
00297   }
00298   xsize = GlobalSize(src)/sizeof(ACCEL);
00299   if (xsize>entries) entries=xsize;
00300 
00301   i=0;
00302   while(!done) {
00303     /* Spit out some debugging information. */
00304 //    TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
00305 //        i, accel[i].fVirt, accel[i].key, accel[i].cmd);
00306 
00307     /* Copy data to the destination structure array (if dst == NULL,
00308        we're just supposed to count the number of entries). */
00309     if(dst) {
00310         dst[i].fVirt = accel[i].fVirt;
00311         dst[i].key = accel[i].key;
00312         dst[i].cmd = accel[i].cmd;
00313 
00314         /* Check if we've reached the end of the application supplied
00315            accelerator table. */
00316         if(i+1 == entries) {
00317                 /* Turn off the high order bit, just in case. */
00318                 dst[i].fVirt &= 0x7f;
00319                 done = TRUE;
00320         }
00321     }
00322 
00323     /* The highest order bit seems to mark the end of the accelerator
00324        resource table, but not always. Use GlobalSize() check too. */
00325     if((accel[i].fVirt & 0x80) != 0) done = TRUE;
00326 
00327     i++;
00328   }
00329 
00330   return i;
00331 }
00332 
00333 /*********************************************************************
00334  *                    CreateAcceleratorTable   (USER32.64)
00335  *
00336  * By mortene@pvv.org 980321
00337  */
00338 HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
00339 {
00340   HACCEL        hAccel;
00341   LPACCEL       accel;
00342   int           i;
00343 
00344   /* Do parameter checking just in case someone's trying to be
00345      funny. */
00346   if(cEntries < 1) {
00347         dprintf(("CreateAcceleratorTableA: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries));
00348         SetLastError(ERROR_INVALID_PARAMETER);
00349         return NULL;
00350   }
00351   dprintf(("FIXME: CreateAcceleratorTableA: should check that the accelerator descriptions are valid return NULL and SetLastError() if not"));
00352 
00353   /* Allocate memory and copy the table. */
00354   hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL));
00355 
00356   if(!hAccel) {
00357         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00358         return (HACCEL)NULL;
00359   }
00360   accel = (LPACCEL)GlobalLock(hAccel);
00361   for (i=0;i<cEntries;i++) {
00362             accel[i].fVirt = lpaccel[i].fVirt;
00363             accel[i].key = lpaccel[i].key;
00364             accel[i].cmd = lpaccel[i].cmd;
00365   }
00366   /* Set the end-of-table terminator. */
00367   accel[cEntries-1].fVirt |= 0x80;
00368 
00369   dprintf(("CreateAcceleratorTableA %x %x returned %x\n", lpaccel, cEntries, hAccel));
00370   return hAccel;
00371 }
00372 
00373 /*********************************************************************
00374  *                    CreateAcceleratorTableW   (USER32.64)
00375  *
00376  *
00377  */
00378 HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
00379 {
00380   HACCEL        hAccel;
00381   LPACCEL       accel;
00382   int           i;
00383   char          ckey;
00384 
00385   /* Do parameter checking just in case someone's trying to be
00386      funny. */
00387   if(cEntries < 1) {
00388         dprintf(("CreateAcceleratorTableW: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries));
00389         SetLastError(ERROR_INVALID_PARAMETER);
00390         return NULL;
00391   }
00392   dprintf(("FIXME: CreateAcceleratorTableW: should check that the accelerator descriptions are valid return NULL and SetLastError() if not"));
00393 
00394   /* Allocate memory and copy the table. */
00395   hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL));
00396 
00397   if(!hAccel) {
00398         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00399         return (HACCEL)NULL;
00400   }
00401   accel = (LPACCEL)GlobalLock(hAccel);
00402 
00403   for (i=0;i<cEntries;i++) {
00404        accel[i].fVirt = lpaccel[i].fVirt;
00405        if( !(accel[i].fVirt & FVIRTKEY) ) {
00406             ckey = (char) lpaccel[i].key;
00407             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1);
00408        }
00409        else  accel[i].key = lpaccel[i].key;
00410        accel[i].cmd = lpaccel[i].cmd;
00411   }
00412 
00413   /* Set the end-of-table terminator. */
00414   accel[cEntries-1].fVirt |= 0x80;
00415 
00416   dprintf(("CreateAcceleratorTableW %x %x returned %x\n", lpaccel, cEntries, hAccel));
00417   return hAccel;
00418 }
00419 
00420 /******************************************************************************
00421  * DestroyAcceleratorTable [USER32.130]
00422  * Destroys an accelerator table
00423  *
00424  * NOTES
00425  *    By mortene@pvv.org 980321
00426  *
00427  * PARAMS
00428  *    handle [I] Handle to accelerator table
00429  *
00430  * RETURNS STD
00431  */
00432 BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
00433 {
00434     return GlobalFree(handle);
00435 }
00436 

Generated on Wed Jan 23 23:17:49 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001