Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenaccel.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
1.7.6.1
|