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

Last change on this file since 2846 was 2846, checked in by sandervl, 26 years ago

Ported Wine accelerator apis

File size: 15.9 KB
Line 
1/* $Id: winaccel.cpp,v 1.7 2000-02-21 14:25:23 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 "win32wmdiclient.h"
22#include <win\winnls.h>
23
24#define DBG_LOCALLOG DBG_winaccel
25#include "dbglocal.h"
26
27/**********************************************************************
28 * KBD_translate_accelerator
29 *
30 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
31 */
32static BOOL KBD_translate_accelerator(HWND hWnd,LPMSG msg,
33 BYTE fVirt,WORD key,WORD cmd)
34{
35 BOOL sendmsg = FALSE;
36
37 if(msg->wParam == key)
38 {
39 if (msg->message == WM_CHAR) {
40 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
41 {
42 dprintf(("TranslateAccelerator: found accel for WM_CHAR: ('%c')\n", msg->wParam&0xff));
43 sendmsg=TRUE;
44 }
45 }
46 else
47 {
48 if(fVirt & FVIRTKEY) {
49 INT mask = 0;
50 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
51 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
52 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
53
54 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
55 sendmsg=TRUE;
56 else dprintf(("TranslateAccelerator: but incorrect SHIFT/CTRL/ALT-state %x != %x", mask, fVirt));
57 }
58 else
59 {
60 if (!(msg->lParam & 0x01000000)) /* no special_key */
61 {
62 if ((fVirt & FALT) && (msg->lParam & 0x20000000))
63 { /* ^^ ALT pressed */
64 dprintf(("TranslateAccelerator: found accel for Alt-%c\n", msg->wParam&0xff));
65 sendmsg=TRUE;
66 }
67 }
68 }
69 }
70
71 if (sendmsg) /* found an accelerator, but send a message... ? */
72 {
73 INT iSysStat,iStat,mesg=0;
74 HMENU hMenu;
75
76 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP) {
77 mesg=1;
78 }
79 else
80 if (GetCapture())
81 mesg=2;
82 else
83 if (!IsWindowEnabled(hWnd))
84 mesg=3;
85 else
86 {
87 Win32BaseWindow *window;
88
89 window = Win32BaseWindow::GetWindowFromHandle(hWnd);
90 if(!window) {
91 return FALSE; //should never happen! (already checked)
92 }
93
94 hMenu = (window->getStyle() & WS_CHILD) ? 0 : (HMENU)window->GetMenu();
95
96 iSysStat = (window->GetSysMenu()) ? GetMenuState(GetSubMenu(window->GetSysMenu(), 0),
97 cmd, MF_BYCOMMAND) : -1 ;
98 iStat = (hMenu) ? GetMenuState(hMenu, cmd, MF_BYCOMMAND) : -1 ;
99
100 if (iSysStat!=-1)
101 {
102 if (iSysStat & (MF_DISABLED|MF_GRAYED))
103 mesg=4;
104 else
105 mesg=WM_SYSCOMMAND;
106 }
107 else
108 {
109 if (iStat!=-1)
110 {
111 if (IsIconic(hWnd)) {
112 mesg=5;
113 }
114 else
115 {
116 if (iStat & (MF_DISABLED|MF_GRAYED))
117 mesg=6;
118 else
119 mesg=WM_COMMAND;
120 }
121 }
122 else
123 mesg=WM_COMMAND;
124 }
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 Win32BaseWindow *window;
168 int i;
169
170 SetLastError(ERROR_SUCCESS);
171 if (msg == NULL)
172 {
173 dprintf(("TranslateAcceleratorAmsg null; should hang here to be win compatible"));
174 SetLastError(ERROR_INVALID_PARAMETER);
175 return 0;
176 }
177 if (!hAccel || !(lpAccelTbl = (LPACCEL)GlobalLock(hAccel)))
178 {
179 dprintf(("TranslateAcceleratorA: invalid accel handle=%x", hAccel));
180 SetLastError(ERROR_INVALID_PARAMETER);
181 return 0;
182 }
183 window = Win32BaseWindow::GetWindowFromHandle(hWnd);
184 if(!window) {
185 dprintf(("TranslateAccelerator, window %x not found", hWnd));
186 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
187 return 0;
188 }
189 if ((msg->message != WM_KEYDOWN &&
190 msg->message != WM_KEYUP &&
191 msg->message != WM_SYSKEYDOWN &&
192 msg->message != WM_SYSKEYUP &&
193 msg->message != WM_CHAR))
194 {
195 return 0;
196 }
197
198/* TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
199 "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%lx\n",
200 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam); */
201
202 i = 0;
203 do
204 {
205 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
206 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
207 {
208 return 1;
209 }
210 }
211 while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
212
213// WARN_(accel)("couldn't translate accelerator key\n");
214 return 0;
215}
216//******************************************************************************
217//******************************************************************************
218BOOL WIN32API TranslateMDISysAccel(HWND hwndClient, LPMSG msg)
219{
220 SetLastError(ERROR_SUCCESS);
221
222 if(IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
223 {
224 Win32MDIClientWindow *clientWnd;
225 Win32MDIChildWindow *mdichild;
226 HWND hwndChild;
227
228 clientWnd = (Win32MDIClientWindow *)Win32BaseWindow::GetWindowFromHandle(hwndClient);
229 if(!clientWnd) {
230 dprintf(("TranslateMDISysAccel window %x not found", hwndClient));
231 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
232 return FALSE;
233 }
234
235 mdichild = clientWnd->getActiveChild();
236 if(!mdichild) {
237 dprintf(("TranslateMDISysAccel NO active MDI child!!"));
238 return FALSE;
239 }
240 hwndChild = mdichild->getWindowHandle();
241
242 if(IsWindow(hwndChild) && !(GetWindowLongA(hwndChild,GWL_STYLE) & WS_DISABLED) )
243 {
244 WPARAM wParam = 0;
245
246 /* translate if the Ctrl key is down and Alt not. */
247 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
248 !(GetKeyState(VK_MENU) & 0x8000))
249 {
250 switch( msg->wParam )
251 {
252 case VK_F6:
253 case VK_TAB:
254 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
255 ? SC_NEXTWINDOW : SC_PREVWINDOW;
256 break;
257 case VK_F4:
258 case VK_RBUTTON:
259 wParam = SC_CLOSE;
260 break;
261 default:
262 return 0;
263 }
264 SendMessageA(hwndChild, WM_SYSCOMMAND, wParam, (LPARAM)msg->wParam);
265 return 1;
266 }
267 }
268 }
269 return 0; /* failure */
270}
271/**********************************************************************
272 * LoadAccelerators32W [USER.177]
273 * The image layout seems to look like this (not 100% sure):
274 * 00: BYTE type type of accelerator
275 * 01: BYTE pad (to WORD boundary)
276 * 02: WORD event
277 * 04: WORD IDval
278 * 06: WORD pad (to DWORD boundary)
279 */
280HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
281{
282 HRSRC hRsrc;
283 HACCEL hMem,hRetval=0;
284 DWORD size;
285
286 if (!(hRsrc = FindResourceW( instance, lpTableName, RT_ACCELERATORW )))
287 {
288 dprintf(("LoadAcceleratorsW couldn't find accelerator table resource %x %x", instance, lpTableName));
289 return 0;
290 }
291 else {
292 hMem = LoadResource( instance, hRsrc );
293 size = SizeofResource( instance, hRsrc );
294 if(size >= sizeof(PE_ACCEL))
295 {
296 LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
297 LPACCEL accel;
298 int i,nrofaccells = size/sizeof(PE_ACCEL);
299
300 hRetval = GlobalAlloc(0,sizeof(ACCEL)*nrofaccells);
301 accel = (LPACCEL)GlobalLock(hRetval);
302
303 for (i=0;i<nrofaccells;i++) {
304 accel[i].fVirt = accel_table[i].fVirt;
305 accel[i].key = accel_table[i].key;
306 accel[i].cmd = accel_table[i].cmd;
307 }
308 accel[i-1].fVirt |= 0x80;
309 }
310 }
311 dprintf(("LoadAcceleratorsW returned %x %x %x\n", instance, lpTableName, hRetval));
312 return hRetval;
313}
314
315HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
316{
317 LPWSTR uni;
318 HACCEL result;
319 if (HIWORD(lpTableName))
320 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
321 else
322 uni = (LPWSTR)lpTableName;
323 result = LoadAcceleratorsW(instance,uni);
324 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
325 return result;
326}
327
328/**********************************************************************
329 * CopyAcceleratorTable32A (USER32.58)
330 */
331INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
332{
333 return CopyAcceleratorTableW(src, dst, entries);
334}
335
336/**********************************************************************
337 * CopyAcceleratorTable32W (USER32.59)
338 *
339 * By mortene@pvv.org 980321
340 */
341INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT entries)
342{
343 int i,xsize;
344 LPACCEL accel = (LPACCEL)GlobalLock(src);
345 BOOL done = FALSE;
346
347 /* Do parameter checking to avoid the explosions and the screaming
348 as far as possible. */
349 if((dst && (entries < 1)) || (src == (HACCEL)NULL) || !accel)
350 {
351 dprintf(("CopyAcceleratorTableW: Application sent invalid parameters (%p %p %d).\n", (LPVOID)src, (LPVOID)dst, entries));
352 SetLastError(ERROR_INVALID_PARAMETER);
353 return 0;
354 }
355 xsize = GlobalSize(src)/sizeof(ACCEL);
356 if (xsize>entries) entries=xsize;
357
358 i=0;
359 while(!done) {
360 /* Spit out some debugging information. */
361// TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
362// i, accel[i].fVirt, accel[i].key, accel[i].cmd);
363
364 /* Copy data to the destination structure array (if dst == NULL,
365 we're just supposed to count the number of entries). */
366 if(dst) {
367 dst[i].fVirt = accel[i].fVirt;
368 dst[i].key = accel[i].key;
369 dst[i].cmd = accel[i].cmd;
370
371 /* Check if we've reached the end of the application supplied
372 accelerator table. */
373 if(i+1 == entries) {
374 /* Turn off the high order bit, just in case. */
375 dst[i].fVirt &= 0x7f;
376 done = TRUE;
377 }
378 }
379
380 /* The highest order bit seems to mark the end of the accelerator
381 resource table, but not always. Use GlobalSize() check too. */
382 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
383
384 i++;
385 }
386
387 return i;
388}
389
390/*********************************************************************
391 * CreateAcceleratorTable (USER32.64)
392 *
393 * By mortene@pvv.org 980321
394 */
395HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
396{
397 HACCEL hAccel;
398 LPACCEL accel;
399 int i;
400
401 /* Do parameter checking just in case someone's trying to be
402 funny. */
403 if(cEntries < 1) {
404 dprintf(("CreateAcceleratorTableA: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries));
405 SetLastError(ERROR_INVALID_PARAMETER);
406 return NULL;
407 }
408 dprintf(("FIXME: CreateAcceleratorTableA: should check that the accelerator descriptions are valid return NULL and SetLastError() if not"));
409
410 /* Allocate memory and copy the table. */
411 hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL));
412
413 if(!hAccel) {
414 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
415 return (HACCEL)NULL;
416 }
417 accel = (LPACCEL)GlobalLock(hAccel);
418 for (i=0;i<cEntries;i++) {
419 accel[i].fVirt = lpaccel[i].fVirt;
420 accel[i].key = lpaccel[i].key;
421 accel[i].cmd = lpaccel[i].cmd;
422 }
423 /* Set the end-of-table terminator. */
424 accel[cEntries-1].fVirt |= 0x80;
425
426 dprintf(("CreateAcceleratorTableA %x %x returned %x\n", lpaccel, cEntries, hAccel));
427 return hAccel;
428}
429
430/*********************************************************************
431 * CreateAcceleratorTableW (USER32.64)
432 *
433 *
434 */
435HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
436{
437 HACCEL hAccel;
438 LPACCEL accel;
439 int i;
440 char ckey;
441
442 /* Do parameter checking just in case someone's trying to be
443 funny. */
444 if(cEntries < 1) {
445 dprintf(("CreateAcceleratorTableW: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries));
446 SetLastError(ERROR_INVALID_PARAMETER);
447 return NULL;
448 }
449 dprintf(("FIXME: CreateAcceleratorTableW: should check that the accelerator descriptions are valid return NULL and SetLastError() if not"));
450
451 /* Allocate memory and copy the table. */
452 hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL));
453
454 if(!hAccel) {
455 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
456 return (HACCEL)NULL;
457 }
458 accel = (LPACCEL)GlobalLock(hAccel);
459
460 for (i=0;i<cEntries;i++) {
461 accel[i].fVirt = lpaccel[i].fVirt;
462 if( !(accel[i].fVirt & FVIRTKEY) ) {
463 ckey = (char) lpaccel[i].key;
464 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1);
465 }
466 else accel[i].key = lpaccel[i].key;
467 accel[i].cmd = lpaccel[i].cmd;
468 }
469
470 /* Set the end-of-table terminator. */
471 accel[cEntries-1].fVirt |= 0x80;
472
473 dprintf(("CreateAcceleratorTableW %x %x returned %x\n", lpaccel, cEntries, hAccel));
474 return hAccel;
475}
476
477/******************************************************************************
478 * DestroyAcceleratorTable [USER32.130]
479 * Destroys an accelerator table
480 *
481 * NOTES
482 * By mortene@pvv.org 980321
483 *
484 * PARAMS
485 * handle [I] Handle to accelerator table
486 *
487 * RETURNS STD
488 */
489BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
490{
491 return GlobalFree(handle);
492}
493
Note: See TracBrowser for help on using the repository browser.