source: trunk/src/user32/winaccel.cpp@ 9974

Last change on this file since 9974 was 9974, checked in by sandervl, 22 years ago

YD: Changes for header updates + WM_SETTEXT button fix

File size: 14.0 KB
Line 
1/* $Id: winaccel.cpp,v 1.11 2003-04-02 12:58:02 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 "win32wbase.h"
21#include <win\winnls.h>
22
23#define DBG_LOCALLOG DBG_winaccel
24#include "dbglocal.h"
25
26/**********************************************************************
27 * KBD_translate_accelerator
28 *
29 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
30 */
31static BOOL KBD_translate_accelerator(HWND hWnd,LPMSG msg,
32 BYTE fVirt,WORD key,WORD cmd)
33{
34 BOOL sendmsg = FALSE;
35
36 if(msg->wParam == key)
37 {
38 if (msg->message == WM_CHAR) {
39 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
40 {
41 dprintf(("TranslateAccelerator: found accel for WM_CHAR: ('%c')\n", msg->wParam&0xff));
42 sendmsg=TRUE;
43 }
44 }
45 else
46 {
47 if(fVirt & FVIRTKEY) {
48 INT mask = 0;
49 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
50 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
51 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
52
53 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
54 sendmsg=TRUE;
55 else dprintf(("TranslateAccelerator: but incorrect SHIFT/CTRL/ALT-state %x != %x", mask, fVirt));
56 }
57 else
58 {
59 if (!(msg->lParam & 0x01000000)) /* no special_key */
60 {
61 if ((fVirt & FALT) && (msg->lParam & 0x20000000))
62 { /* ^^ ALT pressed */
63 dprintf(("TranslateAccelerator: found accel for Alt-%c\n", msg->wParam&0xff));
64 sendmsg=TRUE;
65 }
66 }
67 }
68 }
69
70 if (sendmsg) /* found an accelerator, but send a message... ? */
71 {
72 INT iSysStat,iStat,mesg=0;
73 HMENU hMenu;
74
75 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP) {
76 mesg=1;
77 }
78 else
79 if (GetCapture())
80 mesg=2;
81 else
82 if (!IsWindowEnabled(hWnd))
83 mesg=3;
84 else
85 {
86 Win32BaseWindow *window;
87
88 window = Win32BaseWindow::GetWindowFromHandle(hWnd);
89 if(!window) {
90 return FALSE; //should never happen! (already checked)
91 }
92
93 hMenu = GetMenu(hWnd);
94
95 iSysStat = (window->GetSysMenu()) ? GetMenuState(GetSubMenu(window->GetSysMenu(), 0),
96 cmd, MF_BYCOMMAND) : -1 ;
97 iStat = (hMenu) ? GetMenuState(hMenu, cmd, MF_BYCOMMAND) : -1 ;
98
99 if (iSysStat!=-1)
100 {
101 if (iSysStat & (MF_DISABLED|MF_GRAYED))
102 mesg=4;
103 else
104 mesg=WM_SYSCOMMAND;
105 }
106 else
107 {
108 if (iStat!=-1)
109 {
110 if (IsIconic(hWnd)) {
111 mesg=5;
112 }
113 else
114 {
115 if (iStat & (MF_DISABLED|MF_GRAYED))
116 mesg=6;
117 else
118 mesg=WM_COMMAND;
119 }
120 }
121 else
122 mesg=WM_COMMAND;
123 }
124 RELEASE_WNDOBJ(window);
125 }
126 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
127 {
128 SendMessageA(hWnd, mesg, cmd, 0x00010000L);
129 }
130 else
131 {
132 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
133 * #0: unknown (please report!)
134 * #1: for WM_KEYUP,WM_SYSKEYUP
135 * #2: mouse is captured
136 * #3: window is disabled
137 * #4: it's a disabled system menu option
138 * #5: it's a menu option, but window is iconic
139 * #6: it's a menu option, but disabled
140 */
141 if(mesg==0)
142 dprintf(("ERROR: unknown reason - please report!"));
143 else dprintf(("but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg));
144
145 }
146 return TRUE;
147 }
148 dprintf(("TranslateAccelerator: not match for %x %x %x", fVirt, key, cmd));
149 }
150 return FALSE;
151}
152/*****************************************************************************
153 * Name : int WIN32API TranslateAcceleratorA
154 * Purpose : Translate WM_*KEYDOWN messages to WM_COMMAND messages
155 * according to Accelerator table
156 * Parameters: HWND hwnd, HACCEL haccel, LPMSG lpmsg
157 * Variables :
158 * Result : int FALSE (no accelerator found) TRUE (accelerator found)
159 * Remark : if a accelerator is found it is not neccesarely executed
160 * depends on window stat
161 *
162 *****************************************************************************/
163INT WINAPI TranslateAcceleratorA(HWND hWnd, HACCEL hAccel, LPMSG msg)
164{
165 /* YES, Accel16! */
166 LPACCEL lpAccelTbl;
167 int i;
168
169 SetLastError(ERROR_SUCCESS);
170 if (msg == NULL)
171 {
172 dprintf(("TranslateAcceleratorAmsg null; should hang here to be win compatible"));
173 SetLastError(ERROR_INVALID_PARAMETER);
174 return 0;
175 }
176 if (!hAccel || !(lpAccelTbl = (LPACCEL)GlobalLock(hAccel)))
177 {
178 dprintf(("TranslateAcceleratorA: invalid accel handle=%x", hAccel));
179 SetLastError(ERROR_INVALID_PARAMETER);
180 return 0;
181 }
182 if(!IsWindow(hWnd)) {
183 dprintf(("TranslateAccelerator, window %x not found", hWnd));
184 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
185 return 0;
186 }
187 if ((msg->message != WM_KEYDOWN &&
188 msg->message != WM_KEYUP &&
189 msg->message != WM_SYSKEYDOWN &&
190 msg->message != WM_SYSKEYUP &&
191 msg->message != WM_CHAR))
192 {
193 return 0;
194 }
195
196/* TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
197 "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%lx\n",
198 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam); */
199
200 i = 0;
201 do
202 {
203 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
204 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
205 {
206 return 1;
207 }
208 }
209 while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
210
211// WARN_(accel)("couldn't translate accelerator key\n");
212 return 0;
213}
214/**********************************************************************
215 * LoadAccelerators32W [USER.177]
216 * The image layout seems to look like this (not 100% sure):
217 * 00: BYTE type type of accelerator
218 * 01: BYTE pad (to WORD boundary)
219 * 02: WORD event
220 * 04: WORD IDval
221 * 06: WORD pad (to DWORD boundary)
222 */
223HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
224{
225 HRSRC hRsrc;
226 HACCEL hMem,hRetval=0;
227 DWORD size;
228
229 if (!(hRsrc = FindResourceW( instance, lpTableName, RT_ACCELERATORW )))
230 {
231 dprintf(("LoadAcceleratorsW couldn't find accelerator table resource %x %x", instance, lpTableName));
232 return 0;
233 }
234 else {
235 hMem = LoadResource( instance, hRsrc );
236 size = SizeofResource( instance, hRsrc );
237 if(size >= sizeof(PE_ACCEL))
238 {
239 LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
240 LPACCEL accel;
241 int i,nrofaccells = size/sizeof(PE_ACCEL);
242
243 hRetval = GlobalAlloc(0,sizeof(ACCEL)*nrofaccells);
244 accel = (LPACCEL)GlobalLock(hRetval);
245
246 for (i=0;i<nrofaccells;i++) {
247 accel[i].fVirt = accel_table[i].fVirt;
248 accel[i].key = accel_table[i].key;
249 accel[i].cmd = accel_table[i].cmd;
250 }
251 accel[i-1].fVirt |= 0x80;
252 }
253 }
254 dprintf(("LoadAcceleratorsW returned %x %x %x\n", instance, lpTableName, hRetval));
255 return hRetval;
256}
257
258HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
259{
260 LPWSTR uni;
261 HACCEL result;
262 if (HIWORD(lpTableName))
263 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
264 else
265 uni = (LPWSTR)lpTableName;
266 result = LoadAcceleratorsW(instance,uni);
267 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
268 return result;
269}
270
271/**********************************************************************
272 * CopyAcceleratorTable32A (USER32.58)
273 */
274INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
275{
276 return CopyAcceleratorTableW(src, dst, entries);
277}
278
279/**********************************************************************
280 * CopyAcceleratorTable32W (USER32.59)
281 *
282 * By mortene@pvv.org 980321
283 */
284INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT entries)
285{
286 int i,xsize;
287 LPACCEL accel = (LPACCEL)GlobalLock(src);
288 BOOL done = FALSE;
289
290 /* Do parameter checking to avoid the explosions and the screaming
291 as far as possible. */
292 if((dst && (entries < 1)) || (src == (HACCEL)NULL) || !accel)
293 {
294 dprintf(("CopyAcceleratorTableW: Application sent invalid parameters (%p %p %d).\n", (LPVOID)src, (LPVOID)dst, entries));
295 SetLastError(ERROR_INVALID_PARAMETER);
296 return 0;
297 }
298 xsize = GlobalSize(src)/sizeof(ACCEL);
299 if (xsize>entries) entries=xsize;
300
301 i=0;
302 while(!done) {
303 /* Spit out some debugging information. */
304// TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
305// i, accel[i].fVirt, accel[i].key, accel[i].cmd);
306
307 /* Copy data to the destination structure array (if dst == NULL,
308 we're just supposed to count the number of entries). */
309 if(dst) {
310 dst[i].fVirt = accel[i].fVirt;
311 dst[i].key = accel[i].key;
312 dst[i].cmd = accel[i].cmd;
313
314 /* Check if we've reached the end of the application supplied
315 accelerator table. */
316 if(i+1 == entries) {
317 /* Turn off the high order bit, just in case. */
318 dst[i].fVirt &= 0x7f;
319 done = TRUE;
320 }
321 }
322
323 /* The highest order bit seems to mark the end of the accelerator
324 resource table, but not always. Use GlobalSize() check too. */
325 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
326
327 i++;
328 }
329
330 return i;
331}
332
333/*********************************************************************
334 * CreateAcceleratorTable (USER32.64)
335 *
336 * By mortene@pvv.org 980321
337 */
338HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
339{
340 HACCEL hAccel;
341 LPACCEL accel;
342 int i;
343
344 /* Do parameter checking just in case someone's trying to be
345 funny. */
346 if(cEntries < 1) {
347 dprintf(("CreateAcceleratorTableA: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries));
348 SetLastError(ERROR_INVALID_PARAMETER);
349 return NULL;
350 }
351 dprintf(("FIXME: CreateAcceleratorTableA: should check that the accelerator descriptions are valid return NULL and SetLastError() if not"));
352
353 /* Allocate memory and copy the table. */
354 hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL));
355
356 if(!hAccel) {
357 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
358 return (HACCEL)NULL;
359 }
360 accel = (LPACCEL)GlobalLock(hAccel);
361 for (i=0;i<cEntries;i++) {
362 accel[i].fVirt = lpaccel[i].fVirt;
363 accel[i].key = lpaccel[i].key;
364 accel[i].cmd = lpaccel[i].cmd;
365 }
366 /* Set the end-of-table terminator. */
367 accel[cEntries-1].fVirt |= 0x80;
368
369 dprintf(("CreateAcceleratorTableA %x %x returned %x\n", lpaccel, cEntries, hAccel));
370 return hAccel;
371}
372
373/*********************************************************************
374 * CreateAcceleratorTableW (USER32.64)
375 *
376 *
377 */
378HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
379{
380 HACCEL hAccel;
381 LPACCEL accel;
382 int i;
383 char ckey;
384
385 /* Do parameter checking just in case someone's trying to be
386 funny. */
387 if(cEntries < 1) {
388 dprintf(("CreateAcceleratorTableW: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries));
389 SetLastError(ERROR_INVALID_PARAMETER);
390 return NULL;
391 }
392 dprintf(("FIXME: CreateAcceleratorTableW: should check that the accelerator descriptions are valid return NULL and SetLastError() if not"));
393
394 /* Allocate memory and copy the table. */
395 hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL));
396
397 if(!hAccel) {
398 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
399 return (HACCEL)NULL;
400 }
401 accel = (LPACCEL)GlobalLock(hAccel);
402
403 for (i=0;i<cEntries;i++) {
404 accel[i].fVirt = lpaccel[i].fVirt;
405 if( !(accel[i].fVirt & FVIRTKEY) ) {
406 ckey = (char) lpaccel[i].key;
407 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, (LPWSTR)&accel[i].key, 1);
408 }
409 else accel[i].key = lpaccel[i].key;
410 accel[i].cmd = lpaccel[i].cmd;
411 }
412
413 /* Set the end-of-table terminator. */
414 accel[cEntries-1].fVirt |= 0x80;
415
416 dprintf(("CreateAcceleratorTableW %x %x returned %x\n", lpaccel, cEntries, hAccel));
417 return hAccel;
418}
419
420/******************************************************************************
421 * DestroyAcceleratorTable [USER32.130]
422 * Destroys an accelerator table
423 *
424 * NOTES
425 * By mortene@pvv.org 980321
426 *
427 * PARAMS
428 * handle [I] Handle to accelerator table
429 *
430 * RETURNS STD
431 */
432BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
433{
434 return GlobalFree(handle);
435}
436
Note: See TracBrowser for help on using the repository browser.