2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/class.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
31 * Copyright 1993 Martin Ayotte
32 * Copyright 1994 Alexandre Julliard
33 * Copyright 1997 Morten Welinder
35 * This library is free software; you can redistribute it and/or
36 * modify it under the terms of the GNU Lesser General Public
37 * License as published by the Free Software Foundation; either
38 * version 2.1 of the License, or (at your option) any later version.
40 * This library is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43 * Lesser General Public License for more details.
45 * You should have received a copy of the GNU Lesser General Public
46 * License along with this library; if not, write to the Free Software
47 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
50 /* INCLUDES ******************************************************************/
57 /* FUNCTIONS *****************************************************************/
62 InitAcceleratorImpl(VOID
)
64 return(STATUS_SUCCESS
);
68 CleanupAcceleratorImpl(VOID
)
70 return(STATUS_SUCCESS
);
74 PACCELERATOR_TABLE FASTCALL
UserGetAccelObject(HACCEL hAccel
)
76 PACCELERATOR_TABLE Accel
;
80 SetLastWin32Error(ERROR_INVALID_ACCEL_HANDLE
);
84 Accel
= UserGetObject(gHandleTable
, hAccel
, otAccel
);
87 SetLastWin32Error(ERROR_INVALID_ACCEL_HANDLE
);
91 ASSERT(Accel
->head
.cLockObj
>= 0);
99 co_IntTranslateAccelerator(
110 ASSERT_REFS_CO(Window
);
112 DPRINT("IntTranslateAccelerator(hwnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x)\n",
113 Window
->head
.h
, message
, wParam
, lParam
, fVirt
, key
, cmd
);
120 if (message
== WM_CHAR
)
122 if (!(fVirt
& FALT
) && !(fVirt
& FVIRTKEY
))
124 DPRINT("found accel for WM_CHAR: ('%c')\n", wParam
& 0xff);
130 if ((fVirt
& FVIRTKEY
) > 0)
133 DPRINT("found accel for virt_key %04x (scan %04x)\n",
134 wParam
, 0xff & HIWORD(lParam
));
136 DPRINT("NtUserGetKeyState(VK_SHIFT) = 0x%x\n",
137 UserGetKeyState(VK_SHIFT
));
138 DPRINT("NtUserGetKeyState(VK_CONTROL) = 0x%x\n",
139 UserGetKeyState(VK_CONTROL
));
140 DPRINT("NtUserGetKeyState(VK_MENU) = 0x%x\n",
141 UserGetKeyState(VK_MENU
));
143 if (UserGetKeyState(VK_SHIFT
) & 0x8000)
145 if (UserGetKeyState(VK_CONTROL
) & 0x8000)
147 if (UserGetKeyState(VK_MENU
) & 0x8000)
149 if (mask
== (fVirt
& (FSHIFT
| FCONTROL
| FALT
)))
151 DPRINT("but incorrect SHIFT/CTRL/ALT-state\n");
155 if (!(lParam
& 0x01000000)) /* no special_key */
157 if ((fVirt
& FALT
) && (lParam
& 0x20000000))
158 { /* ^^ ALT pressed */
159 DPRINT("found accel for Alt-%c\n", wParam
& 0xff);
166 DPRINT("IntTranslateAccelerator(hwnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x) = FALSE\n",
167 Window
->head
.h
, message
, wParam
, lParam
, fVirt
, key
, cmd
);
172 if (message
== WM_KEYUP
|| message
== WM_SYSKEYUP
)
174 else if (IntGetCaptureWindow())
176 else if (!IntIsWindowVisible(Window
)) /* FIXME: WINE IsWindowEnabled == IntIsWindowVisible? */
181 HMENU hMenu
, hSubMenu
, hSysMenu
;
182 UINT uSysStat
= (UINT
)-1, uStat
= (UINT
)-1, nPos
;
184 hMenu
= (UserGetWindowLongW(hWnd
, GWL_STYLE
) & WS_CHILD
) ? 0 : GetMenu(hWnd
);
185 hSysMenu
= get_win_sys_menu(hWnd
);
187 /* find menu item and ask application to initialize it */
188 /* 1. in the system menu */
191 if(MENU_FindItem(&hSubMenu
, &nPos
, MF_BYCOMMAND
))
193 co_IntSendMessage(hWnd
, WM_INITMENU
, (WPARAM
)hSysMenu
, 0L);
194 if(hSubMenu
!= hSysMenu
)
196 nPos
= MENU_FindSubMenu(&hSysMenu
, hSubMenu
);
197 TRACE_(accel
)("hSysMenu = %p, hSubMenu = %p, nPos = %d\n", hSysMenu
, hSubMenu
, nPos
);
198 co_IntSendMessage(hWnd
, WM_INITMENUPOPUP
, (WPARAM
)hSubMenu
, MAKELPARAM(nPos
, TRUE
));
200 uSysStat
= GetMenuState(GetSubMenu(hSysMenu
, 0), cmd
, MF_BYCOMMAND
);
202 else /* 2. in the window's menu */
206 if(MENU_FindItem(&hSubMenu
, &nPos
, MF_BYCOMMAND
))
208 co_IntSendMessage(hWnd
, WM_INITMENU
, (WPARAM
)hMenu
, 0L);
209 if(hSubMenu
!= hMenu
)
211 nPos
= MENU_FindSubMenu(&hMenu
, hSubMenu
);
212 TRACE_(accel
)("hMenu = %p, hSubMenu = %p, nPos = %d\n", hMenu
, hSubMenu
, nPos
);
213 co_IntSendMessage(hWnd
, WM_INITMENUPOPUP
, (WPARAM
)hSubMenu
, MAKELPARAM(nPos
, FALSE
));
215 uStat
= GetMenuState(hMenu
, cmd
, MF_BYCOMMAND
);
219 if (uSysStat
!= (UINT
)-1)
221 if (uSysStat
& (MF_DISABLED
|MF_GRAYED
))
228 if (uStat
!= (UINT
)-1)
234 if (uStat
& (MF_DISABLED
|MF_GRAYED
))
246 DPRINT1("Menu search not implemented\n");
252 if (mesg
== WM_COMMAND
)
254 DPRINT(", sending WM_COMMAND, wParam=%0x\n", 0x10000 | cmd
);
255 co_IntSendMessage(Window
->head
.h
, mesg
, 0x10000 | cmd
, 0L);
257 else if (mesg
== WM_SYSCOMMAND
)
259 DPRINT(", sending WM_SYSCOMMAND, wParam=%0x\n", cmd
);
260 co_IntSendMessage(Window
->head
.h
, mesg
, cmd
, 0x00010000L
);
264 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
265 * #0: unknown (please report!)
266 * #1: for WM_KEYUP,WM_SYSKEYUP
267 * #2: mouse is captured
268 * #3: window is disabled
269 * #4: it's a disabled system menu option
270 * #5: it's a menu option, but window is iconic
271 * #6: it's a menu option, but disabled
273 DPRINT(", but won't send WM_{SYS}COMMAND, reason is #%d\n", mesg
);
276 DPRINT1(" unknown reason - please report!");
280 DPRINT("IntTranslateAccelerator(hWnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x) = TRUE\n",
281 Window
->head
.h
, message
, wParam
, lParam
, fVirt
, key
, cmd
);
287 /* SYSCALLS *****************************************************************/
292 NtUserCopyAcceleratorTable(
297 PACCELERATOR_TABLE Accel
;
302 DPRINT("Enter NtUserCopyAcceleratorTable\n");
305 Accel
= UserGetAccelObject(hAccel
);
307 if ((Entries
&& (EntriesCount
< 1)) || ((hAccel
== NULL
) || (!Accel
)))
312 if (Accel
->Count
< EntriesCount
)
313 EntriesCount
= Accel
->Count
;
321 Entries
[Ret
].fVirt
= Accel
->Table
[Ret
].fVirt
& 0x7f;
322 Entries
[Ret
].key
= Accel
->Table
[Ret
].key
;
323 Entries
[Ret
].cmd
= Accel
->Table
[Ret
].cmd
;
325 if(Ret
+ 1 == EntriesCount
) Done
= TRUE
;
328 if((Accel
->Table
[Ret
].fVirt
& 0x80) != 0) Done
= TRUE
;
336 DPRINT("Leave NtUserCopyAcceleratorTable, ret=%i\n",_ret_
);
343 NtUserCreateAcceleratorTable(
347 PACCELERATOR_TABLE Accel
;
350 DECLARE_RETURN(HACCEL
);
352 DPRINT("Enter NtUserCreateAcceleratorTable(Entries %p, EntriesCount %d)\n",
353 Entries
, EntriesCount
);
354 UserEnterExclusive();
356 if (!Entries
|| EntriesCount
< 1)
358 SetLastNtError(STATUS_INVALID_PARAMETER
);
359 RETURN( (HACCEL
) NULL
);
362 Accel
= UserCreateObject(gHandleTable
, NULL
, (PHANDLE
)&hAccel
, otAccel
, sizeof(ACCELERATOR_TABLE
));
366 SetLastNtError(STATUS_NO_MEMORY
);
367 RETURN( (HACCEL
) NULL
);
370 Accel
->Count
= EntriesCount
;
371 if (Accel
->Count
> 0)
373 Accel
->Table
= ExAllocatePoolWithTag(PagedPool
, EntriesCount
* sizeof(ACCEL
), TAG_ACCEL
);
374 if (Accel
->Table
== NULL
)
376 UserDereferenceObject(Accel
);
377 UserDeleteObject(hAccel
, otAccel
);
378 SetLastNtError(STATUS_NO_MEMORY
);
379 RETURN( (HACCEL
) NULL
);
382 for (Index
= 0; Index
< EntriesCount
; Index
++)
384 Accel
->Table
[Index
].fVirt
= Entries
[Index
].fVirt
&0x7f;
385 if(Accel
->Table
[Index
].fVirt
& FVIRTKEY
)
387 Accel
->Table
[Index
].key
= Entries
[Index
].key
;
391 RtlMultiByteToUnicodeN(&Accel
->Table
[Index
].key
,
394 (PCSTR
)&Entries
[Index
].key
,
398 Accel
->Table
[Index
].cmd
= Entries
[Index
].cmd
;
401 /* Set the end-of-table terminator. */
402 Accel
->Table
[EntriesCount
- 1].fVirt
|= 0x80;
405 /* FIXME: Save HandleTable in a list somewhere so we can clean it up again */
410 DPRINT("Leave NtUserCreateAcceleratorTable(Entries %p, EntriesCount %d) = %x\n",
411 Entries
, EntriesCount
,_ret_
);
420 NtUserDestroyAcceleratorTable(
423 PACCELERATOR_TABLE Accel
;
424 DECLARE_RETURN(BOOLEAN
);
426 /* FIXME: If the handle table is from a call to LoadAcceleratorTable, decrement it's
427 usage count (and return TRUE).
428 FIXME: Destroy only tables created using CreateAcceleratorTable.
431 DPRINT("NtUserDestroyAcceleratorTable(Table %x)\n", hAccel
);
432 UserEnterExclusive();
434 if (!(Accel
= UserGetAccelObject(hAccel
)))
439 if (Accel
->Table
!= NULL
)
441 ExFreePoolWithTag(Accel
->Table
, TAG_ACCEL
);
445 UserDeleteObject(hAccel
, otAccel
);
450 DPRINT("Leave NtUserDestroyAcceleratorTable(Table %x) = %i\n", hAccel
,_ret_
);
458 NtUserTranslateAccelerator(
464 PACCELERATOR_TABLE Accel
= NULL
;
466 USER_REFERENCE_ENTRY AccelRef
, WindowRef
;
469 DPRINT("NtUserTranslateAccelerator(hWnd %x, Table %x, Message %p)\n",
470 hWnd
, hAccel
, Message
);
475 SetLastNtError(STATUS_INVALID_PARAMETER
);
479 if ((Message
->message
!= WM_KEYDOWN
) &&
480 (Message
->message
!= WM_SYSKEYDOWN
) &&
481 (Message
->message
!= WM_SYSCHAR
) &&
482 (Message
->message
!= WM_CHAR
))
487 if (!(Accel
= UserGetAccelObject(hAccel
)))
492 UserRefObjectCo(Accel
, &AccelRef
);
494 if (!(Window
= UserGetWindowObject(hWnd
)))
499 UserRefObjectCo(Window
, &WindowRef
);
502 /* FIXME: Associate AcceleratorTable with the current thread */
504 for (i
= 0; i
< Accel
->Count
; i
++)
506 if (co_IntTranslateAccelerator(Window
, Message
->message
, Message
->wParam
, Message
->lParam
,
507 Accel
->Table
[i
].fVirt
, Accel
->Table
[i
].key
,
508 Accel
->Table
[i
].cmd
))
510 DPRINT("NtUserTranslateAccelerator(hWnd %x, Table %x, Message %p) = %i end\n",
511 hWnd
, hAccel
, Message
, 1);
514 if (((Accel
->Table
[i
].fVirt
& 0x80) > 0))
523 if (Window
) UserDerefObjectCo(Window
);
524 if (Accel
) UserDerefObjectCo(Accel
);
526 DPRINT("NtUserTranslateAccelerator(hWnd %x, Table %x, Message %p) = %i end\n",
527 hWnd
, hAccel
, Message
, 0);