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

Last change on this file since 5935 was 5935, checked in by sandervl, 24 years ago

reference count (window + class objects) rewrite

File size: 15.9 KB
Line 
1/* $Id: winaccel.cpp,v 1.8 2001-06-09 14:50:24 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 RELEASE_WNDOBJ(window);
126 }
127 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
128 {
129 SendMessageA(hWnd, mesg, cmd, 0x00010000L);
130 }
131 else
132 {
133 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
134 * #0: unknown (please report!)
135 * #1: for WM_KEYUP,WM_SYSKEYUP
136 * #2: mouse is captured
137 * #3: window is disabled
138 * #4: it's a disabled system menu option
139 * #5: it's a menu option, but window is iconic
140 * #6: it's a menu option, but disabled
141 */
142 if(mesg==0)
143 dprintf(("ERROR: unknown reason - please report!"));
144 else dprintf(("but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg));
145
146 }
147 return TRUE;
148 }
149 dprintf(("TranslateAccelerator: not match for %x %x %x", fVirt, key, cmd));
150 }
151 return FALSE;
152}
153/*****************************************************************************
154 * Name : int WIN32API TranslateAcceleratorA
155 * Purpose : Translate WM_*KEYDOWN messages to WM_COMMAND messages
156 * according to Accelerator table
157 * Parameters: HWND hwnd, HACCEL haccel, LPMSG lpmsg
158 * Variables :
159 * Result : int FALSE (no accelerator found) TRUE (accelerator found)
160 * Remark : if a accelerator is found it is not neccesarely executed
161 * depends on window stat
162 *
163 *****************************************************************************/
164INT WINAPI TranslateAcceleratorA(HWND hWnd, HACCEL hAccel, LPMSG msg)
165{
166 /* YES, Accel16! */
167 LPACCEL lpAccelTbl;
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 if(!IsWindow(hWnd)) {
184 dprintf(("TranslateAccelerator, window %x not found", hWnd));
185 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
186 return 0;
187 }
188 if ((msg->message != WM_KEYDOWN &&
189 msg->message != WM_KEYUP &&
190 msg->message != WM_SYSKEYDOWN &&
191 msg->message != WM_SYSKEYUP &&
192 msg->message != WM_CHAR))
193 {
194 return 0;
195 }
196
197/* TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
198 "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%lx\n",
199 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam); */
200
201 i = 0;
202 do
203 {
204 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
205 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
206 {
207 return 1;
208 }
209 }
210 while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
211
212// WARN_(accel)("couldn't translate accelerator key\n");
213 return 0;
214}
215//******************************************************************************
216//******************************************************************************
217BOOL WIN32API TranslateMDISysAccel(HWND hwndClient, LPMSG msg)
218{
219 SetLastError(ERROR_SUCCESS);
220
221 if(IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
222 {
223 Win32MDIClientWindow *clientWnd;
224 Win32MDIChildWindow *mdichild;
225 HWND hwndChild;
226
227 clientWnd = (Win32MDIClientWindow *)Win32BaseWindow::GetWindowFromHandle(hwndClient);
228 if(!clientWnd) {
229 dprintf(("TranslateMDISysAccel window %x not found", hwndClient));
230 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
231 return FALSE;
232 }
233
234 hwndChild = clientWnd->getActiveChild();
235 RELEASE_WNDOBJ(clientWnd);
236 if(!hwndChild) {
237 dprintf(("TranslateMDISysAccel NO active MDI child!!"));
238 return FALSE;
239 }
240
241 if(IsWindow(hwndChild) && !(GetWindowLongA(hwndChild,GWL_STYLE) & WS_DISABLED) )
242 {
243 WPARAM wParam = 0;
244
245 /* translate if the Ctrl key is down and Alt not. */
246 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
247 !(GetKeyState(VK_MENU) & 0x8000))
248 {
249 switch( msg->wParam )
250 {
251 case VK_F6:
252 case VK_TAB:
253 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
254 ? SC_NEXTWINDOW : SC_PREVWINDOW;
255 break;
256 case VK_F4:
257 case VK_RBUTTON:
258 wParam = SC_CLOSE;
259 break;
260 default:
261 return 0;
262 }
263 SendMessageA(hwndChild, WM_SYSCOMMAND, wParam, (LPARAM)msg->wParam);
264 return 1;
265 }
266 }
267 }
268 return 0; /* failure */
269}
270/**********************************************************************
271 * LoadAccelerators32W [USER.177]
272 * The image layout seems to look like this (not 100% sure):
273 * 00: BYTE type type of accelerator
274 * 01: BYTE pad (to WORD boundary)
275 * 02: WORD event
276 * 04: WORD IDval
277 * 06: WORD pad (to DWORD boundary)
278 */
279HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
280{
281 HRSRC hRsrc;
282 HACCEL hMem,hRetval=0;
283 DWORD size;
284
285 if (!(hRsrc = FindResourceW( instance, lpTableName, RT_ACCELERATORW )))
286 {
287 dprintf(("LoadAcceleratorsW couldn't find accelerator table resource %x %x", instance, lpTableName));
288 return 0;
289 }
290 else {
291 hMem = LoadResource( instance, hRsrc );
292 size = SizeofResource( instance, hRsrc );
293 if(size >= sizeof(PE_ACCEL))
294 {
295 LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
296 LPACCEL accel;
297 int i,nrofaccells = size/sizeof(PE_ACCEL);
298
299 hRetval = GlobalAlloc(0,sizeof(ACCEL)*nrofaccells);
300 accel = (LPACCEL)GlobalLock(hRetval);
301
302 for (i=0;i<nrofaccells;i++) {
303 accel[i].fVirt = accel_table[i].fVirt;
304 accel[i].key = accel_table[i].key;
305 accel[i].cmd = accel_table[i].cmd;
306 }
307 accel[i-1].fVirt |= 0x80;
308 }
309 }
310 dprintf(("LoadAcceleratorsW returned %x %x %x\n", instance, lpTableName, hRetval));
311 return hRetval;
312}
313
314HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
315{
316 LPWSTR uni;
317 HACCEL result;
318 if (HIWORD(lpTableName))
319 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
320 else
321 uni = (LPWSTR)lpTableName;
322 result = LoadAcceleratorsW(instance,uni);
323 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
324 return result;
325}
326
327/**********************************************************************
328 * CopyAcceleratorTable32A (USER32.58)
329 */
330INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
331{
332 return CopyAcceleratorTableW(src, dst, entries);
333}
334
335/**********************************************************************
336 * CopyAcceleratorTable32W (USER32.59)
337 *
338 * By mortene@pvv.org 980321
339 */
340INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT entries)
341{
342 int i,xsize;
343 LPACCEL accel = (LPACCEL)GlobalLock(src);
344 BOOL done = FALSE;
345
346 /* Do parameter checking to avoid the explosions and the screaming
347 as far as possible. */
348 if((dst && (entries < 1)) || (src == (HACCEL)NULL) || !accel)
349 {
350 dprintf(("CopyAcceleratorTableW: Application sent invalid parameters (%p %p %d).\n", (LPVOID)src, (LPVOID)dst, entries));
351 SetLastError(ERROR_INVALID_PARAMETER);
352 return 0;
353 }
354 xsize = GlobalSize(src)/sizeof(ACCEL);
355 if (xsize>entries) entries=xsize;
356
357 i=0;
358 while(!done) {
359 /* Spit out some debugging information. */
360// TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
361// i, accel[i].fVirt, accel[i].key, accel[i].cmd);
362
363 /* Copy data to the destination structure array (if dst == NULL,
364 we're just supposed to count the number of entries). */
365 if(dst) {
366 dst[i].fVirt = accel[i].fVirt;
367 dst[i].key = accel[i].key;
368 dst[i].cmd = accel[i].cmd;
369
370 /* Check if we've reached the end of the application supplied
371 accelerator table. */
372 if(i+1 == entries) {
373 /* Turn off the high order bit, just in case. */
374 dst[i].fVirt &= 0x7f;
375 done = TRUE;
376 }
377 }
378
379 /* The highest order bit seems to mark the end of the accelerator
380 resource table, but not always. Use GlobalSize() check too. */
381 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
382
383 i++;
384 }
385
386 return i;
387}
388
389/*********************************************************************
390 * CreateAcceleratorTable (USER32.64)
391 *
392 * By mortene@pvv.org 980321
393 */
394HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
395{
396 HACCEL hAccel;
397 LPACCEL accel;
398 int i;
399
400 /* Do parameter checking just in case someone's trying to be
401 funny. */
402 if(cEntries < 1) {
403 dprintf(("CreateAcceleratorTableA: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries));
404 SetLastError(ERROR_INVALID_PARAMETER);
405 return NULL;
406 }
407 dprintf(("FIXME: CreateAcceleratorTableA: should check that the accelerator descriptions are valid return NULL and SetLastError() if not"));
408
409 /* Allocate memory and copy the table. */
410 hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL));
411
412 if(!hAccel) {
413 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
414 return (HACCEL)NULL;
415 }
416 accel = (LPACCEL)GlobalLock(hAccel);
417 for (i=0;i<cEntries;i++) {
418 accel[i].fVirt = lpaccel[i].fVirt;
419 accel[i].key = lpaccel[i].key;
420 accel[i].cmd = lpaccel[i].cmd;
421 }
422 /* Set the end-of-table terminator. */
423 accel[cEntries-1].fVirt |= 0x80;
424
425 dprintf(("CreateAcceleratorTableA %x %x returned %x\n", lpaccel, cEntries, hAccel));
426 return hAccel;
427}
428
429/*********************************************************************
430 * CreateAcceleratorTableW (USER32.64)
431 *
432 *
433 */
434HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
435{
436 HACCEL hAccel;
437 LPACCEL accel;
438 int i;
439 char ckey;
440
441 /* Do parameter checking just in case someone's trying to be
442 funny. */
443 if(cEntries < 1) {
444 dprintf(("CreateAcceleratorTableW: Application sent invalid parameters (%p %d).\n", lpaccel, cEntries));
445 SetLastError(ERROR_INVALID_PARAMETER);
446 return NULL;
447 }
448 dprintf(("FIXME: CreateAcceleratorTableW: should check that the accelerator descriptions are valid return NULL and SetLastError() if not"));
449
450 /* Allocate memory and copy the table. */
451 hAccel = GlobalAlloc(0,cEntries*sizeof(ACCEL));
452
453 if(!hAccel) {
454 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
455 return (HACCEL)NULL;
456 }
457 accel = (LPACCEL)GlobalLock(hAccel);
458
459 for (i=0;i<cEntries;i++) {
460 accel[i].fVirt = lpaccel[i].fVirt;
461 if( !(accel[i].fVirt & FVIRTKEY) ) {
462 ckey = (char) lpaccel[i].key;
463 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1);
464 }
465 else accel[i].key = lpaccel[i].key;
466 accel[i].cmd = lpaccel[i].cmd;
467 }
468
469 /* Set the end-of-table terminator. */
470 accel[cEntries-1].fVirt |= 0x80;
471
472 dprintf(("CreateAcceleratorTableW %x %x returned %x\n", lpaccel, cEntries, hAccel));
473 return hAccel;
474}
475
476/******************************************************************************
477 * DestroyAcceleratorTable [USER32.130]
478 * Destroys an accelerator table
479 *
480 * NOTES
481 * By mortene@pvv.org 980321
482 *
483 * PARAMS
484 * handle [I] Handle to accelerator table
485 *
486 * RETURNS STD
487 */
488BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
489{
490 return GlobalFree(handle);
491}
492
Note: See TracBrowser for help on using the repository browser.