| 1 | /* $Id: winaccel.cpp,v 1.12 2003-07-31 15:56:47 sandervl Exp $ */ | 
|---|
| 2 | /* | 
|---|
| 3 | * Win32 accelerator key functions for OS/2 | 
|---|
| 4 | * | 
|---|
| 5 | * Based on Wine: (windows\input.c; loader\resource.c) (20000130) | 
|---|
| 6 | * Copyright 1993 Bob Amstadt | 
|---|
| 7 | * Copyright 1996 Albrecht Kleine | 
|---|
| 8 | * Copyright 1997 David Faure | 
|---|
| 9 | * Copyright 1998 Morten Welinder | 
|---|
| 10 | * Copyright 1998 Ulrich Weigand | 
|---|
| 11 | * Copyright 1993 Robert J. Amstadt | 
|---|
| 12 | * Copyright 1995 Alexandre Julliard | 
|---|
| 13 | * | 
|---|
| 14 | * Project Odin Software License can be found in LICENSE.TXT | 
|---|
| 15 | * | 
|---|
| 16 | */ | 
|---|
| 17 | #include <os2win.h> | 
|---|
| 18 | #include <misc.h> | 
|---|
| 19 | #include <heapstring.h> | 
|---|
| 20 | #include <win\winnls.h> | 
|---|
| 21 |  | 
|---|
| 22 | #define DBG_LOCALLOG    DBG_winaccel | 
|---|
| 23 | #include "dbglocal.h" | 
|---|
| 24 |  | 
|---|
| 25 | /********************************************************************** | 
|---|
| 26 | *                      LoadAccelerators32W     [USER.177] | 
|---|
| 27 | * The image layout seems to look like this (not 100% sure): | 
|---|
| 28 | * 00:  BYTE    type            type of accelerator | 
|---|
| 29 | * 01:  BYTE    pad             (to WORD boundary) | 
|---|
| 30 | * 02:  WORD    event | 
|---|
| 31 | * 04:  WORD    IDval | 
|---|
| 32 | * 06:  WORD    pad             (to DWORD boundary) | 
|---|
| 33 | */ | 
|---|
| 34 | HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName) | 
|---|
| 35 | { | 
|---|
| 36 | HRSRC hRsrc; | 
|---|
| 37 | HACCEL hMem,hRetval=0; | 
|---|
| 38 | DWORD size; | 
|---|
| 39 |  | 
|---|
| 40 | if (!(hRsrc = FindResourceW( instance, lpTableName, RT_ACCELERATORW ))) | 
|---|
| 41 | { | 
|---|
| 42 | dprintf(("LoadAcceleratorsW couldn't find accelerator table resource %x %x", instance, lpTableName)); | 
|---|
| 43 | return 0; | 
|---|
| 44 | } | 
|---|
| 45 | else { | 
|---|
| 46 | hMem = LoadResource( instance, hRsrc ); | 
|---|
| 47 | size = SizeofResource( instance, hRsrc ); | 
|---|
| 48 | if(size >= sizeof(PE_ACCEL)) | 
|---|
| 49 | { | 
|---|
| 50 | LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem; | 
|---|
| 51 | LPACCEL accel; | 
|---|
| 52 | int i,nrofaccells = size/sizeof(PE_ACCEL); | 
|---|
| 53 |  | 
|---|
| 54 | hRetval = GlobalAlloc(0,sizeof(ACCEL)*nrofaccells); | 
|---|
| 55 | accel   = (LPACCEL)GlobalLock(hRetval); | 
|---|
| 56 |  | 
|---|
| 57 | for (i=0;i<nrofaccells;i++) { | 
|---|
| 58 | accel[i].fVirt = accel_table[i].fVirt; | 
|---|
| 59 | accel[i].key = accel_table[i].key; | 
|---|
| 60 | accel[i].cmd = accel_table[i].cmd; | 
|---|
| 61 | } | 
|---|
| 62 | accel[i-1].fVirt |= 0x80; | 
|---|
| 63 | } | 
|---|
| 64 | } | 
|---|
| 65 | dprintf(("LoadAcceleratorsW returned %x %x %x\n", instance, lpTableName, hRetval)); | 
|---|
| 66 | return hRetval; | 
|---|
| 67 | } | 
|---|
| 68 |  | 
|---|
| 69 | HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName) | 
|---|
| 70 | { | 
|---|
| 71 | LPWSTR   uni; | 
|---|
| 72 | HACCEL result; | 
|---|
| 73 | if (HIWORD(lpTableName)) | 
|---|
| 74 | uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName ); | 
|---|
| 75 | else | 
|---|
| 76 | uni = (LPWSTR)lpTableName; | 
|---|
| 77 | result = LoadAcceleratorsW(instance,uni); | 
|---|
| 78 | if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni); | 
|---|
| 79 | return result; | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | /********************************************************************** | 
|---|
| 83 | *             CopyAcceleratorTable32A   (USER32.58) | 
|---|
| 84 | */ | 
|---|
| 85 | INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries) | 
|---|
| 86 | { | 
|---|
| 87 | return CopyAcceleratorTableW(src, dst, entries); | 
|---|
| 88 | } | 
|---|
| 89 |  | 
|---|
| 90 | /********************************************************************** | 
|---|
| 91 | *             CopyAcceleratorTable32W   (USER32.59) | 
|---|
| 92 | * | 
|---|
| 93 | * By mortene@pvv.org 980321 | 
|---|
| 94 | */ | 
|---|
| 95 | INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT entries) | 
|---|
| 96 | { | 
|---|
| 97 | int i,xsize; | 
|---|
| 98 | LPACCEL accel = (LPACCEL)GlobalLock(src); | 
|---|
| 99 | BOOL done = FALSE; | 
|---|
| 100 |  | 
|---|
| 101 | /* Do parameter checking to avoid the explosions and the screaming | 
|---|
| 102 | as far as possible. */ | 
|---|
| 103 | if((dst && (entries < 1)) || (src == (HACCEL)NULL) || !accel) | 
|---|
| 104 | { | 
|---|
| 105 | dprintf(("CopyAcceleratorTableW: Application sent invalid parameters (%p %p %d).\n", (LPVOID)src, (LPVOID)dst, entries)); | 
|---|
| 106 | SetLastError(ERROR_INVALID_PARAMETER); | 
|---|
| 107 | return 0; | 
|---|
| 108 | } | 
|---|
| 109 | xsize = GlobalSize(src)/sizeof(ACCEL); | 
|---|
| 110 | if (xsize>entries) entries=xsize; | 
|---|
| 111 |  | 
|---|
| 112 | i=0; | 
|---|
| 113 | while(!done) { | 
|---|
| 114 | /* Spit out some debugging information. */ | 
|---|
| 115 | //    TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n", | 
|---|
| 116 | //        i, accel[i].fVirt, accel[i].key, accel[i].cmd); | 
|---|
| 117 |  | 
|---|
| 118 | /* Copy data to the destination structure array (if dst == NULL, | 
|---|
| 119 | we're just supposed to count the number of entries). */ | 
|---|
| 120 | if(dst) { | 
|---|
| 121 | dst[i].fVirt = accel[i].fVirt; | 
|---|
| 122 | dst[i].key = accel[i].key; | 
|---|
| 123 | dst[i].cmd = accel[i].cmd; | 
|---|
| 124 |  | 
|---|
| 125 | /* Check if we've reached the end of the application supplied | 
|---|
| 126 | accelerator table. */ | 
|---|
| 127 | if(i+1 == entries) { | 
|---|
| 128 | /* Turn off the high order bit, just in case. */ | 
|---|
| 129 | dst[i].fVirt &= 0x7f; | 
|---|
| 130 | done = TRUE; | 
|---|
| 131 | } | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|
| 134 | /* The highest order bit seems to mark the end of the accelerator | 
|---|
| 135 | resource table, but not always. Use GlobalSize() check too. */ | 
|---|
| 136 | if((accel[i].fVirt & 0x80) != 0) done = TRUE; | 
|---|
| 137 |  | 
|---|
| 138 | i++; | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | return i; | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 | /********************************************************************* | 
|---|
| 145 | *                    CreateAcceleratorTable   (USER32.64) | 
|---|
| 146 | * | 
|---|
| 147 | * By mortene@pvv.org 980321 | 
|---|
| 148 | */ | 
|---|
| 149 | HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries) | 
|---|
| 150 | { | 
|---|
| 151 | HACCEL        hAccel; | 
|---|
| 152 | LPACCEL       accel; | 
|---|
| 153 | int           i; | 
|---|
| 154 |  | 
|---|
| 155 | /* Do parameter checking just in case someone's trying to be | 
|---|
| 156 | funny. */ | 
|---|
| 157 | if(cEntries < 1) { | 
|---|
| 158 | dprintf(("CreateAcceleratorTableA: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries)); | 
|---|
| 159 | SetLastError(ERROR_INVALID_PARAMETER); | 
|---|
| 160 | return NULL; | 
|---|
| 161 | } | 
|---|
| 162 | dprintf(("FIXME: CreateAcceleratorTableA: should check that the accelerator descriptions are valid return NULL and SetLastError() if not")); | 
|---|
| 163 |  | 
|---|
| 164 | /* Allocate memory and copy the table. */ | 
|---|
| 165 | hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL)); | 
|---|
| 166 |  | 
|---|
| 167 | if(!hAccel) { | 
|---|
| 168 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); | 
|---|
| 169 | return (HACCEL)NULL; | 
|---|
| 170 | } | 
|---|
| 171 | accel = (LPACCEL)GlobalLock(hAccel); | 
|---|
| 172 | for (i=0;i<cEntries;i++) { | 
|---|
| 173 | accel[i].fVirt = lpaccel[i].fVirt; | 
|---|
| 174 | accel[i].key = lpaccel[i].key; | 
|---|
| 175 | accel[i].cmd = lpaccel[i].cmd; | 
|---|
| 176 | } | 
|---|
| 177 | /* Set the end-of-table terminator. */ | 
|---|
| 178 | accel[cEntries-1].fVirt |= 0x80; | 
|---|
| 179 |  | 
|---|
| 180 | dprintf(("CreateAcceleratorTableA %x %x returned %x\n", lpaccel, cEntries, hAccel)); | 
|---|
| 181 | return hAccel; | 
|---|
| 182 | } | 
|---|
| 183 |  | 
|---|
| 184 | /********************************************************************* | 
|---|
| 185 | *                    CreateAcceleratorTableW   (USER32.64) | 
|---|
| 186 | * | 
|---|
| 187 | * | 
|---|
| 188 | */ | 
|---|
| 189 | HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries) | 
|---|
| 190 | { | 
|---|
| 191 | HACCEL        hAccel; | 
|---|
| 192 | LPACCEL       accel; | 
|---|
| 193 | int           i; | 
|---|
| 194 | char          ckey; | 
|---|
| 195 |  | 
|---|
| 196 | /* Do parameter checking just in case someone's trying to be | 
|---|
| 197 | funny. */ | 
|---|
| 198 | if(cEntries < 1) { | 
|---|
| 199 | dprintf(("CreateAcceleratorTableW: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries)); | 
|---|
| 200 | SetLastError(ERROR_INVALID_PARAMETER); | 
|---|
| 201 | return NULL; | 
|---|
| 202 | } | 
|---|
| 203 | dprintf(("FIXME: CreateAcceleratorTableW: should check that the accelerator descriptions are valid return NULL and SetLastError() if not")); | 
|---|
| 204 |  | 
|---|
| 205 | /* Allocate memory and copy the table. */ | 
|---|
| 206 | hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL)); | 
|---|
| 207 |  | 
|---|
| 208 | if(!hAccel) { | 
|---|
| 209 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); | 
|---|
| 210 | return (HACCEL)NULL; | 
|---|
| 211 | } | 
|---|
| 212 | accel = (LPACCEL)GlobalLock(hAccel); | 
|---|
| 213 |  | 
|---|
| 214 | for (i=0;i<cEntries;i++) { | 
|---|
| 215 | accel[i].fVirt = lpaccel[i].fVirt; | 
|---|
| 216 | if( !(accel[i].fVirt & FVIRTKEY) ) { | 
|---|
| 217 | ckey = (char) lpaccel[i].key; | 
|---|
| 218 | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, (LPWSTR)&accel[i].key, 1); | 
|---|
| 219 | } | 
|---|
| 220 | else  accel[i].key = lpaccel[i].key; | 
|---|
| 221 | accel[i].cmd = lpaccel[i].cmd; | 
|---|
| 222 | } | 
|---|
| 223 |  | 
|---|
| 224 | /* Set the end-of-table terminator. */ | 
|---|
| 225 | accel[cEntries-1].fVirt |= 0x80; | 
|---|
| 226 |  | 
|---|
| 227 | dprintf(("CreateAcceleratorTableW %x %x returned %x\n", lpaccel, cEntries, hAccel)); | 
|---|
| 228 | return hAccel; | 
|---|
| 229 | } | 
|---|
| 230 |  | 
|---|
| 231 | /****************************************************************************** | 
|---|
| 232 | * DestroyAcceleratorTable [USER32.130] | 
|---|
| 233 | * Destroys an accelerator table | 
|---|
| 234 | * | 
|---|
| 235 | * NOTES | 
|---|
| 236 | *    By mortene@pvv.org 980321 | 
|---|
| 237 | * | 
|---|
| 238 | * PARAMS | 
|---|
| 239 | *    handle [I] Handle to accelerator table | 
|---|
| 240 | * | 
|---|
| 241 | * RETURNS STD | 
|---|
| 242 | */ | 
|---|
| 243 | BOOL WINAPI DestroyAcceleratorTable( HACCEL handle ) | 
|---|
| 244 | { | 
|---|
| 245 | return GlobalFree(handle); | 
|---|
| 246 | } | 
|---|
| 247 |  | 
|---|