ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

accel.c
Go to the documentation of this file.
00001 /*
00002  *  ReactOS kernel
00003  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  */
00019 /* $Id: accel.c 53436 2011-08-25 08:51:26Z gadamopoulos $
00020  *
00021  * PROJECT:         ReactOS user32.dll
00022  * FILE:            lib/user32/windows/input.c
00023  * PURPOSE:         Accelerator tables
00024  * PROGRAMMER:      KJK::Hyperion <noog@libero.it>
00025  * UPDATE HISTORY:
00026  *      09/05/2001  CSH  Created
00027  *      08/07/2003  KJK  Fully implemented
00028  */
00029 
00030 /* INCLUDES ******************************************************************/
00031 
00032 #include <user32.h>
00033 
00034 #include <wine/debug.h>
00035 
00036 /* this is the 8 byte accel struct used in Win32 resources (internal only) */
00037 typedef struct
00038 {
00039     BYTE   fVirt;
00040     BYTE   pad0;
00041     WORD   key;
00042     WORD   cmd;
00043     WORD   pad1;
00044 } PE_ACCEL, *LPPE_ACCEL;
00045 
00046 /* Cache entry */
00047 typedef struct _USER_ACCEL_CACHE_ENTRY
00048 {
00049  struct _USER_ACCEL_CACHE_ENTRY * Next;
00050  ULONG_PTR Usage; /* how many times the table has been loaded */
00051  HACCEL Object;   /* handle to the NtUser accelerator table object */
00052  HGLOBAL Data;    /* base address of the resource data */
00053 }
00054 U32_ACCEL_CACHE_ENTRY;
00055 
00056 /* FUNCTIONS *****************************************************************/
00057 
00058 /* Lock guarding the cache */
00059 CRITICAL_SECTION U32AccelCacheLock;
00060 
00061 /* Cache */
00062 U32_ACCEL_CACHE_ENTRY * U32AccelCache = NULL;
00063 
00064 /* Look up a handle or resource address in the cache */
00065 U32_ACCEL_CACHE_ENTRY ** WINAPI U32AccelCacheFind(HANDLE Object, HGLOBAL Data)
00066 {
00067  /*
00068   to avoid using a double-link list and still allow elements to be removed,
00069   return a pointer to the list link that points to the desired entry
00070  */
00071  U32_ACCEL_CACHE_ENTRY ** ppEntry = &U32AccelCache;
00072 
00073  for(; *ppEntry; ppEntry = &((*ppEntry)->Next))
00074   if((*ppEntry)->Object == Object || (*ppEntry)->Data == Data) break;
00075 
00076  return ppEntry;
00077 }
00078 
00079 /* Allocate an entry and insert it into the cache */
00080 void WINAPI U32AccelCacheAdd(HACCEL Object, HGLOBAL Data)
00081 {
00082  U32_ACCEL_CACHE_ENTRY * pEntry =
00083   LocalAlloc(LMEM_FIXED, sizeof(U32_ACCEL_CACHE_ENTRY));
00084 
00085  /* failed to allocate an entry - not critical */
00086  if(pEntry == NULL) return;
00087 
00088  /* initialize the entry */
00089  pEntry->Usage = 1;
00090  pEntry->Object = Object;
00091  pEntry->Data = Data;
00092 
00093  /* insert the entry into the cache */
00094  pEntry->Next = U32AccelCache;
00095  U32AccelCache = pEntry;
00096 }
00097 
00098 /* Create an accelerator table from a loaded resource */
00099 HACCEL WINAPI U32LoadAccelerators(HINSTANCE hInstance, HRSRC hTableRes)
00100 {
00101  HGLOBAL hAccTableData;
00102  HACCEL hAccTable = NULL;
00103  U32_ACCEL_CACHE_ENTRY * pEntry;
00104  PE_ACCEL * pAccTableResData;
00105  SIZE_T i = 0;
00106  SIZE_T j = 0;
00107  ACCEL * pAccTableData;
00108 
00109  /* load the accelerator table */
00110  hAccTableData = LoadResource(hInstance, hTableRes);
00111 
00112  /* failure */
00113  if(hAccTableData == NULL) return NULL;
00114 
00115  EnterCriticalSection(&U32AccelCacheLock);
00116 
00117  /* see if this accelerator table has already been loaded */
00118  pEntry = *U32AccelCacheFind(NULL, hAccTableData);
00119 
00120  /* accelerator table already loaded */
00121  if(pEntry)
00122  {
00123   /* increment the reference count */
00124   ++ pEntry->Usage;
00125 
00126   /* return the existing object */
00127   hAccTable = pEntry->Object;
00128 
00129   /* success */
00130   goto l_Leave;
00131  }
00132 
00133  /* determine the number of entries in the table */
00134  i = SizeofResource(hInstance, hTableRes) / sizeof(PE_ACCEL);
00135 
00136  /* allocate the buffer for the table to be passed to Win32K */
00137  pAccTableData = LocalAlloc(LMEM_FIXED, i * sizeof(ACCEL));
00138 
00139  /* failure */
00140  if(pAccTableData == NULL) goto l_Leave;
00141 
00142  pAccTableResData = (PE_ACCEL *)hAccTableData;
00143 
00144  /* copy the table */
00145  for(j = 0; j < i; ++ j)
00146  {
00147   pAccTableData[j].fVirt = pAccTableResData[j].fVirt;
00148   pAccTableData[j].key = pAccTableResData[j].key;
00149   pAccTableData[j].cmd = pAccTableResData[j].cmd;
00150  }
00151  pAccTableData[i - 1].fVirt |= 0x80;
00152 
00153  /* create a new accelerator table object */
00154  hAccTable = NtUserCreateAcceleratorTable(pAccTableData, i);
00155 
00156  /* free the buffer */
00157  LocalFree(pAccTableData);
00158 
00159  /* failure */
00160  if(hAccTable == NULL) goto l_Leave;
00161 
00162  /* success - cache the object */
00163  U32AccelCacheAdd(hAccTable, pAccTableResData);
00164 
00165 l_Leave:
00166  LeaveCriticalSection(&U32AccelCacheLock);
00167  return hAccTable;
00168 }
00169 
00170 /* Checks if a message can be translated through an accelerator table */
00171 BOOL WINAPI U32IsValidAccelMessage(UINT uMsg)
00172 {
00173  switch(uMsg)
00174  {
00175   case WM_KEYDOWN:
00176   case WM_KEYUP:
00177   case WM_CHAR:
00178   case WM_SYSCHAR:
00179   case WM_SYSKEYDOWN:
00180   case WM_SYSKEYUP:
00181    return TRUE;
00182 
00183   default:
00184    return FALSE;
00185  }
00186 }
00187 
00188 /* WIN32 FUNCTIONS ***********************************************************/
00189 
00190 /*
00191  * Dereference the specified accelerator table, removing it from the cache and
00192  * deleting the associated NtUser object as appropriate
00193  *
00194  * @implemented
00195  */
00196 BOOL WINAPI DestroyAcceleratorTable(HACCEL hAccel)
00197 {
00198  U32_ACCEL_CACHE_ENTRY ** ppEntry;
00199  ULONG_PTR nUsage = 0;
00200 
00201  if (!hAccel)
00202   return FALSE;
00203 
00204  EnterCriticalSection(&U32AccelCacheLock);
00205 
00206  /* see if this accelerator table has been cached */
00207  ppEntry = U32AccelCacheFind(hAccel, NULL);
00208 
00209  /* accelerator table cached */
00210  if(*ppEntry)
00211  {
00212   U32_ACCEL_CACHE_ENTRY * pEntry = *ppEntry;
00213 
00214   /* decrement the reference count */
00215   nUsage = pEntry->Usage = pEntry->Usage - 1;
00216 
00217   /* reference count now zero: destroy the cache entry */
00218   if(nUsage == 0)
00219   {
00220    /* unlink the cache entry */
00221    *ppEntry = pEntry->Next;
00222 
00223    /* free the cache entry */
00224    LocalFree(pEntry);
00225   }
00226  }
00227 
00228  LeaveCriticalSection(&U32AccelCacheLock);
00229 
00230  if(nUsage > 0) return FALSE;
00231 
00232  /* destroy the object */
00233  return NtUserDestroyAcceleratorTable(hAccel);
00234 }
00235 
00236 
00237 /*
00238  * Create an accelerator table from a named resource
00239  *
00240  * @implemented
00241  */
00242 HACCEL WINAPI LoadAcceleratorsW(HINSTANCE hInstance, LPCWSTR lpTableName)
00243 {
00244  return U32LoadAccelerators
00245  (
00246   hInstance,
00247   FindResourceExW(hInstance, (LPCWSTR) RT_ACCELERATOR, lpTableName, 0)
00248  );
00249 }
00250 
00251 
00252 /*
00253  * @implemented
00254  */
00255 HACCEL WINAPI LoadAcceleratorsA(HINSTANCE hInstance, LPCSTR lpTableName)
00256 {
00257   HRSRC Accel;
00258 
00259   Accel = FindResourceExA(hInstance, (LPCSTR) RT_ACCELERATOR, lpTableName, 0);
00260   if (NULL == Accel)
00261     {
00262       return NULL;
00263     }
00264 
00265   return U32LoadAccelerators(hInstance, Accel);
00266 }
00267 
00268 /*
00269  * Translate a key press into a WM_COMMAND message
00270  *
00271  * @implemented
00272  */
00273 int WINAPI TranslateAcceleratorW(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg)
00274 {
00275  if(!U32IsValidAccelMessage(lpMsg->message)) return 0;
00276 
00277  return NtUserTranslateAccelerator(hWnd, hAccTable, lpMsg);
00278 }
00279 
00280 
00281 /*
00282  * @implemented
00283  */
00284 int WINAPI CopyAcceleratorTableA
00285 (
00286  HACCEL hAccelSrc,
00287  LPACCEL lpAccelDst, /* can be NULL */
00288  int cAccelEntries
00289 )
00290 {
00291    int i;
00292 
00293    cAccelEntries = CopyAcceleratorTableW(hAccelSrc, lpAccelDst, cAccelEntries);
00294 
00295    if (lpAccelDst == NULL) return cAccelEntries;
00296 
00297    for(i = 0; i < cAccelEntries; ++ i)
00298    if(!(lpAccelDst[i].fVirt & FVIRTKEY))
00299    {
00300       NTSTATUS nErrCode = RtlUnicodeToMultiByteN(
00301          (PCHAR)&lpAccelDst[i].key,
00302          sizeof(lpAccelDst[i].key),
00303          NULL,
00304          (PWCHAR)&lpAccelDst[i].key,
00305          sizeof(lpAccelDst[i].key)
00306          );
00307 
00308       if(!NT_SUCCESS(nErrCode)) lpAccelDst[i].key = 0;
00309    }
00310 
00311    return cAccelEntries;
00312 }
00313 
00314 
00315 /*
00316  * @implemented
00317  */
00318 HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccl, int cEntries)
00319 {
00320  int i;
00321 
00322  if (!cEntries || !lpaccl) return (HACCEL)0;
00323 
00324  for(i = 0; i < cEntries; ++ i)
00325   if(!lpaccl[i].fVirt)
00326   {
00327    NTSTATUS nErrCode = RtlMultiByteToUnicodeN
00328    (
00329     (PWCHAR)&lpaccl[i].key,
00330     sizeof(lpaccl[i].key),
00331     NULL,
00332     (PCHAR)&lpaccl[i].key,
00333     sizeof(lpaccl[i].key)
00334    );
00335 
00336    if(!NT_SUCCESS(nErrCode)) lpaccl[i].key = -1;
00337   }
00338 
00339  return CreateAcceleratorTableW(lpaccl, cEntries);
00340 }
00341 
00342 
00343 /*
00344  * @implemented
00345  */
00346 int WINAPI TranslateAcceleratorA(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg)
00347 {
00348  MSG mCopy = *lpMsg;
00349  CHAR cChar;
00350  WCHAR wChar;
00351  NTSTATUS Status;
00352 
00353  if(!U32IsValidAccelMessage(lpMsg->message)) return 0;
00354 
00355  Status = RtlMultiByteToUnicodeN(&wChar, sizeof(wChar), NULL, &cChar, sizeof(cChar));
00356  if(!NT_SUCCESS(Status))
00357  {
00358   SetLastError(RtlNtStatusToDosError(Status));
00359   return 0;
00360  }
00361 
00362  return TranslateAcceleratorW(hWnd, hAccTable, &mCopy);
00363 }
00364 
00365 /* EOF */

Generated on Sun May 27 2012 04:38:43 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.