blob: bcf022844f53c8178b88a402f86cc9e4515e2f0f [file] [log] [blame]
Alexandre Julliard75a839a1993-07-15 11:13:45 +00001/*
2 * Message queues related functions
3 *
Alexandre Julliardaca05781994-10-17 18:12:41 +00004 * Copyright 1993, 1994 Alexandre Julliard
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliard75a839a1993-07-15 11:13:45 +000019 */
20
Patrik Stridvalld016f812002-08-17 00:43:16 +000021#include "config.h"
22
Alexandre Julliard401710d1993-09-04 10:09:32 +000023#include <stdlib.h>
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000024#include <string.h>
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +000025#include <ctype.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000026#ifdef HAVE_SYS_TIME_H
27# include <sys/time.h>
28#endif
Alexandre Julliard5f721f81994-01-04 20:14:34 +000029#include <sys/types.h>
Alexandre Julliardf41aeca1993-09-14 16:47:10 +000030
Alexandre Julliardd253c582001-08-07 19:19:08 +000031#include "winbase.h"
32#include "wingdi.h"
33#include "winuser.h"
Alexandre Julliard75a839a1993-07-15 11:13:45 +000034#include "message.h"
Alexandre Julliarddbf2bf01999-01-01 17:05:53 +000035#include "winerror.h"
Alexandre Julliard37e95032001-07-19 00:39:09 +000036#include "wine/server.h"
Alexandre Julliard75a839a1993-07-15 11:13:45 +000037#include "win.h"
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000038#include "heap.h"
Alexandre Julliard58199531994-04-21 01:20:00 +000039#include "hook.h"
Ulrich Weiganda11ce321998-11-08 12:27:26 +000040#include "input.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000041#include "spy.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000042#include "winpos.h"
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000043#include "dde.h"
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000044#include "queue.h"
Alexandre Julliard3051b641996-07-05 17:14:13 +000045#include "winproc.h"
Alexandre Julliard43230042001-05-16 19:52:29 +000046#include "user.h"
Alexandre Julliarddadf78f1998-05-17 17:13:43 +000047#include "thread.h"
Alexandre Julliard51ab43b2001-05-18 22:51:56 +000048#include "task.h"
Alexandre Julliard91222da2000-12-10 23:01:33 +000049#include "controls.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000050#include "wine/debug.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000051
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000052WINE_DEFAULT_DEBUG_CHANNEL(msg);
53WINE_DECLARE_DEBUG_CHANNEL(key);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000054
Alexandre Julliardac9c9b01996-07-28 18:50:11 +000055#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
56#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
57
Alexandre Julliarda21672e2001-10-02 18:53:59 +000058static BYTE QueueKeyStateTable[256];
Stephane Lussier2c86dab1999-02-18 17:34:09 +000059
Alexandre Julliard838d65a2001-06-19 19:16:41 +000060
Alexandre Julliard75a839a1993-07-15 11:13:45 +000061/***********************************************************************
Alexandre Julliard838d65a2001-06-19 19:16:41 +000062 * is_keyboard_message
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000063 */
Alexandre Julliard838d65a2001-06-19 19:16:41 +000064inline static BOOL is_keyboard_message( UINT message )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000065{
Alexandre Julliard838d65a2001-06-19 19:16:41 +000066 return (message >= WM_KEYFIRST && message <= WM_KEYLAST);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000067}
68
Alexandre Julliard838d65a2001-06-19 19:16:41 +000069
70/***********************************************************************
71 * is_mouse_message
72 */
73inline static BOOL is_mouse_message( UINT message )
74{
75 return ((message >= WM_NCMOUSEFIRST && message <= WM_NCMOUSELAST) ||
76 (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST));
77}
78
79
80/***********************************************************************
81 * check_message_filter
82 */
83inline static BOOL check_message_filter( const MSG *msg, HWND hwnd, UINT first, UINT last )
84{
85 if (hwnd)
86 {
87 if (msg->hwnd != hwnd && !IsChild( hwnd, msg->hwnd )) return FALSE;
88 }
89 if (first || last)
90 {
91 return (msg->message >= first && msg->message <= last);
92 }
93 return TRUE;
94}
95
96
97/***********************************************************************
Alexandre Julliardd253c582001-08-07 19:19:08 +000098 * process_sent_messages
Alexandre Julliard9f55ae62001-06-28 04:37:22 +000099 *
Alexandre Julliardd253c582001-08-07 19:19:08 +0000100 * Process all pending sent messages.
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000101 */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000102inline static void process_sent_messages(void)
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000103{
Alexandre Julliardd253c582001-08-07 19:19:08 +0000104 MSG msg;
105 MSG_peek_message( &msg, 0, 0, 0, GET_MSG_REMOVE | GET_MSG_SENT_ONLY );
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000106}
107
108
109/***********************************************************************
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000110 * queue_hardware_message
111 *
112 * store a hardware message in the thread queue
113 */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000114static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message_type type )
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000115{
116 SERVER_START_REQ( send_message )
117 {
Alexandre Julliardd253c582001-08-07 19:19:08 +0000118 req->type = type;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000119 req->id = (void *)GetWindowThreadProcessId( msg->hwnd, NULL );
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000120 req->win = msg->hwnd;
121 req->msg = msg->message;
122 req->wparam = msg->wParam;
123 req->lparam = msg->lParam;
124 req->x = msg->pt.x;
125 req->y = msg->pt.y;
126 req->time = msg->time;
127 req->info = extra_info;
Alexandre Julliardd253c582001-08-07 19:19:08 +0000128 req->timeout = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000129 wine_server_call( req );
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000130 }
131 SERVER_END_REQ;
132}
133
134
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000135/***********************************************************************
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000136 * update_queue_key_state
137 */
138static void update_queue_key_state( UINT msg, WPARAM wp )
139{
140 BOOL down = FALSE;
141
142 switch (msg)
143 {
144 case WM_LBUTTONDOWN:
145 down = TRUE;
146 /* fall through */
147 case WM_LBUTTONUP:
148 wp = VK_LBUTTON;
149 break;
150 case WM_MBUTTONDOWN:
151 down = TRUE;
152 /* fall through */
153 case WM_MBUTTONUP:
154 wp = VK_MBUTTON;
155 break;
156 case WM_RBUTTONDOWN:
157 down = TRUE;
158 /* fall through */
159 case WM_RBUTTONUP:
160 wp = VK_RBUTTON;
161 break;
162 case WM_KEYDOWN:
163 case WM_SYSKEYDOWN:
164 down = TRUE;
165 /* fall through */
166 case WM_KEYUP:
167 case WM_SYSKEYUP:
168 wp = wp & 0xff;
169 break;
170 }
171 if (down)
172 {
173 BYTE *p = &QueueKeyStateTable[wp];
174 if (!(*p & 0x80)) *p ^= 0x01;
175 *p |= 0x80;
176 }
177 else QueueKeyStateTable[wp] &= ~0x80;
178}
179
180
181/***********************************************************************
Alexandre Julliard77b99181997-09-14 17:17:23 +0000182 * MSG_SendParentNotify
183 *
184 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
185 * the window has the WS_EX_NOPARENTNOTIFY style.
186 */
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000187static void MSG_SendParentNotify( HWND hwnd, WORD event, WORD idChild, POINT pt )
Alexandre Julliard77b99181997-09-14 17:17:23 +0000188{
Alexandre Julliard77b99181997-09-14 17:17:23 +0000189 /* pt has to be in the client coordinates of the parent window */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +0000190 MapWindowPoints( 0, hwnd, &pt, 1 );
191 for (;;)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000192 {
Alexandre Julliard4ff32c82001-08-18 18:08:26 +0000193 HWND parent;
194
195 if (!(GetWindowLongA( hwnd, GWL_STYLE ) & WS_CHILD)) break;
196 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) break;
197 if (!(parent = GetParent(hwnd))) break;
198 MapWindowPoints( hwnd, parent, &pt, 1 );
199 hwnd = parent;
200 SendMessageA( hwnd, WM_PARENTNOTIFY,
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000201 MAKEWPARAM( event, idChild ), MAKELPARAM( pt.x, pt.y ) );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000202 }
Alexandre Julliard77b99181997-09-14 17:17:23 +0000203}
204
205
206/***********************************************************************
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +0000207 * MSG_JournalPlayBackMsg
208 *
Vincent Béron9a624912002-05-31 23:06:46 +0000209 * Get an EVENTMSG struct via call JOURNALPLAYBACK hook function
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +0000210 */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000211void MSG_JournalPlayBackMsg(void)
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +0000212{
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000213 EVENTMSG tmpMsg;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000214 MSG msg;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000215 LRESULT wtime;
216 int keyDown,i;
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +0000217
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000218 if (!HOOK_IsHooked( WH_JOURNALPLAYBACK )) return;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000219
220 wtime=HOOK_CallHooksA( WH_JOURNALPLAYBACK, HC_GETNEXT, 0, (LPARAM)&tmpMsg );
221 /* TRACE(msg,"Playback wait time =%ld\n",wtime); */
222 if (wtime<=0)
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +0000223 {
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000224 wtime=0;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000225 msg.message = tmpMsg.message;
226 msg.hwnd = tmpMsg.hwnd;
227 msg.time = tmpMsg.time;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000228 if ((tmpMsg.message >= WM_KEYFIRST) && (tmpMsg.message <= WM_KEYLAST))
229 {
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000230 msg.wParam = tmpMsg.paramL & 0xFF;
231 msg.lParam = MAKELONG(tmpMsg.paramH&0x7ffff,tmpMsg.paramL>>8);
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000232 if (tmpMsg.message == WM_KEYDOWN || tmpMsg.message == WM_SYSKEYDOWN)
233 {
234 for (keyDown=i=0; i<256 && !keyDown; i++)
235 if (InputKeyStateTable[i] & 0x80)
236 keyDown++;
237 if (!keyDown)
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000238 msg.lParam |= 0x40000000;
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000239 InputKeyStateTable[msg.wParam] |= 0x80;
240 AsyncKeyStateTable[msg.wParam] |= 0x80;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000241 }
242 else /* WM_KEYUP, WM_SYSKEYUP */
243 {
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000244 msg.lParam |= 0xC0000000;
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000245 InputKeyStateTable[msg.wParam] &= ~0x80;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000246 }
247 if (InputKeyStateTable[VK_MENU] & 0x80)
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000248 msg.lParam |= 0x20000000;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000249 if (tmpMsg.paramH & 0x8000) /*special_key bit*/
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000250 msg.lParam |= 0x01000000;
251
252 msg.pt.x = msg.pt.y = 0;
Alexandre Julliardd253c582001-08-07 19:19:08 +0000253 queue_hardware_message( &msg, 0, MSG_HARDWARE_RAW );
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000254 }
255 else if ((tmpMsg.message>= WM_MOUSEFIRST) && (tmpMsg.message <= WM_MOUSELAST))
256 {
257 switch (tmpMsg.message)
258 {
259 case WM_LBUTTONDOWN:
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000260 InputKeyStateTable[VK_LBUTTON] |= 0x80;
261 AsyncKeyStateTable[VK_LBUTTON] |= 0x80;
262 break;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000263 case WM_LBUTTONUP:
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000264 InputKeyStateTable[VK_LBUTTON] &= ~0x80;
265 break;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000266 case WM_MBUTTONDOWN:
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000267 InputKeyStateTable[VK_MBUTTON] |= 0x80;
268 AsyncKeyStateTable[VK_MBUTTON] |= 0x80;
269 break;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000270 case WM_MBUTTONUP:
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000271 InputKeyStateTable[VK_MBUTTON] &= ~0x80;
272 break;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000273 case WM_RBUTTONDOWN:
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000274 InputKeyStateTable[VK_RBUTTON] |= 0x80;
275 AsyncKeyStateTable[VK_RBUTTON] |= 0x80;
276 break;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000277 case WM_RBUTTONUP:
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000278 InputKeyStateTable[VK_RBUTTON] &= ~0x80;
279 break;
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000280 }
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000281 SetCursorPos(tmpMsg.paramL,tmpMsg.paramH);
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000282 msg.lParam=MAKELONG(tmpMsg.paramL,tmpMsg.paramH);
283 msg.wParam=0;
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000284 if (InputKeyStateTable[VK_LBUTTON] & 0x80) msg.wParam |= MK_LBUTTON;
285 if (InputKeyStateTable[VK_MBUTTON] & 0x80) msg.wParam |= MK_MBUTTON;
286 if (InputKeyStateTable[VK_RBUTTON] & 0x80) msg.wParam |= MK_RBUTTON;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000287
288 msg.pt.x = tmpMsg.paramL;
289 msg.pt.y = tmpMsg.paramH;
Alexandre Julliardd253c582001-08-07 19:19:08 +0000290 queue_hardware_message( &msg, 0, MSG_HARDWARE_RAW );
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000291 }
292 HOOK_CallHooksA( WH_JOURNALPLAYBACK, HC_SKIP, 0, (LPARAM)&tmpMsg);
Alexandre Julliardd1ce8b21996-09-02 16:46:30 +0000293 }
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000294 else
295 {
296 if( tmpMsg.message == WM_QUEUESYNC )
297 if (HOOK_IsHooked( WH_CBT ))
298 HOOK_CallHooksA( WH_CBT, HCBT_QS, 0, 0L);
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000299 }
300}
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000301
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000302
Alexandre Julliardaca05781994-10-17 18:12:41 +0000303/***********************************************************************
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000304 * process_raw_keyboard_message
Alexandre Julliardaca05781994-10-17 18:12:41 +0000305 *
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000306 * returns TRUE if the contents of 'msg' should be passed to the application
Alexandre Julliardaca05781994-10-17 18:12:41 +0000307 */
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000308static BOOL process_raw_keyboard_message( MSG *msg, ULONG_PTR extra_info )
Alexandre Julliardaca05781994-10-17 18:12:41 +0000309{
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000310 if (!(msg->hwnd = GetFocus()))
Alexandre Julliardaca05781994-10-17 18:12:41 +0000311 {
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000312 /* Send the message to the active window instead, */
313 /* translating messages to their WM_SYS equivalent */
314 msg->hwnd = GetActiveWindow();
315 if (msg->message < WM_SYSKEYDOWN) msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000316 }
Noel Borthwickc90243b1999-05-14 08:09:13 +0000317
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000318 if (HOOK_IsHooked( WH_JOURNALRECORD ))
319 {
320 EVENTMSG event;
321
322 event.message = msg->message;
323 event.hwnd = msg->hwnd;
324 event.time = msg->time;
325 event.paramL = (msg->wParam & 0xFF) | (HIWORD(msg->lParam) << 8);
326 event.paramH = msg->lParam & 0x7FFF;
327 if (HIWORD(msg->lParam) & 0x0100) event.paramH |= 0x8000; /* special_key - bit */
328 HOOK_CallHooksA( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event );
329 }
330
Alexandre Julliard605cba32002-04-26 18:36:06 +0000331 /* if we are going to throw away the message, update the queue state now */
332 if (!msg->hwnd) update_queue_key_state( msg->message, msg->wParam );
333
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000334 return (msg->hwnd != 0);
335}
336
337
338/***********************************************************************
339 * process_cooked_keyboard_message
340 *
341 * returns TRUE if the contents of 'msg' should be passed to the application
342 */
343static BOOL process_cooked_keyboard_message( MSG *msg, BOOL remove )
344{
345 if (remove)
346 {
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000347 update_queue_key_state( msg->message, msg->wParam );
348
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000349 /* Handle F1 key by sending out WM_HELP message */
350 if ((msg->message == WM_KEYUP) &&
351 (msg->wParam == VK_F1) &&
352 (msg->hwnd != GetDesktopWindow()) &&
353 !MENU_IsMenuActive())
354 {
355 HELPINFO hi;
356 hi.cbSize = sizeof(HELPINFO);
357 hi.iContextType = HELPINFO_WINDOW;
358 hi.iCtrlId = GetWindowLongA( msg->hwnd, GWL_ID );
359 hi.hItemHandle = msg->hwnd;
360 hi.dwContextId = GetWindowContextHelpId( msg->hwnd );
361 hi.MousePos = msg->pt;
362 SendMessageA(msg->hwnd, WM_HELP, 0, (LPARAM)&hi);
363 }
364 }
365
366 if (HOOK_CallHooksA( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
367 LOWORD(msg->wParam), msg->lParam ))
368 {
369 /* skip this message */
370 HOOK_CallHooksA( WH_CBT, HCBT_KEYSKIPPED, LOWORD(msg->wParam), msg->lParam );
371 return FALSE;
372 }
373 return TRUE;
374}
375
376
377/***********************************************************************
378 * process_raw_mouse_message
379 *
380 * returns TRUE if the contents of 'msg' should be passed to the application
381 */
382static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info )
383{
384 static MSG clk_msg;
385
386 POINT pt;
387 INT ht, hittest;
388
389 /* find the window to dispatch this mouse message to */
390
Alexandre Julliardee8ab7a2001-06-20 23:16:34 +0000391 hittest = HTCLIENT;
392 if (!(msg->hwnd = PERQDATA_GetCaptureWnd( &ht )))
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000393 {
394 /* If no capture HWND, find window which contains the mouse position.
395 * Also find the position of the cursor hot spot (hittest) */
396 HWND hWndScope = (HWND)extra_info;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000397
Alexandre Julliardee8ab7a2001-06-20 23:16:34 +0000398 if (!IsWindow(hWndScope)) hWndScope = 0;
399 if (!(msg->hwnd = WINPOS_WindowFromPoint( hWndScope, msg->pt, &hittest )))
400 msg->hwnd = GetDesktopWindow();
401 ht = hittest;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000402 }
403
404 if (HOOK_IsHooked( WH_JOURNALRECORD ))
405 {
406 EVENTMSG event;
407 event.message = msg->message;
408 event.time = msg->time;
409 event.hwnd = msg->hwnd;
410 event.paramL = msg->pt.x;
411 event.paramH = msg->pt.y;
412 HOOK_CallHooksA( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event );
413 }
414
415 /* translate double clicks */
416
417 if ((msg->message == WM_LBUTTONDOWN) ||
418 (msg->message == WM_RBUTTONDOWN) ||
419 (msg->message == WM_MBUTTONDOWN))
420 {
421 BOOL update = TRUE;
422 /* translate double clicks -
423 * note that ...MOUSEMOVEs can slip in between
424 * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
425
426 if (GetClassLongA( msg->hwnd, GCL_STYLE ) & CS_DBLCLKS || ht != HTCLIENT )
427 {
428 if ((msg->message == clk_msg.message) &&
429 (msg->hwnd == clk_msg.hwnd) &&
Andriy Palamarchuk2489dc92001-12-06 22:28:43 +0000430 (msg->time - clk_msg.time < GetDoubleClickTime()) &&
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000431 (abs(msg->pt.x - clk_msg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK)/2) &&
432 (abs(msg->pt.y - clk_msg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK)/2))
433 {
434 msg->message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
435 clk_msg.message = 0;
436 update = FALSE;
437 }
438 }
439 /* update static double click conditions */
440 if (update) clk_msg = *msg;
441 }
442
443 pt = msg->pt;
Travis Michielsenb9bd3f82001-06-29 01:17:55 +0000444 /* Note: windows has no concept of a non-client wheel message */
445 if (hittest != HTCLIENT && msg->message != WM_MOUSEWHEEL)
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000446 {
447 msg->message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
448 msg->wParam = hittest;
449 }
450 else ScreenToClient( msg->hwnd, &pt );
451 msg->lParam = MAKELONG( pt.x, pt.y );
452 return TRUE;
453}
454
455
456/***********************************************************************
457 * process_cooked_mouse_message
458 *
459 * returns TRUE if the contents of 'msg' should be passed to the application
460 */
Alexandre Julliard516e40e2001-10-17 17:48:49 +0000461static BOOL process_cooked_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL remove )
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000462{
463 INT hittest = HTCLIENT;
464 UINT raw_message = msg->message;
465 BOOL eatMsg;
466
467 if (msg->message >= WM_NCMOUSEFIRST && msg->message <= WM_NCMOUSELAST)
468 {
469 raw_message += WM_MOUSEFIRST - WM_NCMOUSEFIRST;
470 hittest = msg->wParam;
471 }
472 if (raw_message == WM_LBUTTONDBLCLK ||
473 raw_message == WM_RBUTTONDBLCLK ||
474 raw_message == WM_MBUTTONDBLCLK)
475 {
476 raw_message += WM_LBUTTONDOWN - WM_LBUTTONDBLCLK;
477 }
478
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000479 if (remove) update_queue_key_state( raw_message, 0 );
480
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000481 if (HOOK_IsHooked( WH_MOUSE ))
482 {
483 MOUSEHOOKSTRUCT hook;
484 hook.pt = msg->pt;
485 hook.hwnd = msg->hwnd;
486 hook.wHitTestCode = hittest;
Alexandre Julliard516e40e2001-10-17 17:48:49 +0000487 hook.dwExtraInfo = extra_info;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000488 if (HOOK_CallHooksA( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
489 msg->message, (LPARAM)&hook ))
490 {
491 hook.pt = msg->pt;
492 hook.hwnd = msg->hwnd;
493 hook.wHitTestCode = hittest;
Alexandre Julliard516e40e2001-10-17 17:48:49 +0000494 hook.dwExtraInfo = extra_info;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000495 HOOK_CallHooksA( WH_CBT, HCBT_CLICKSKIPPED, msg->message, (LPARAM)&hook );
496 return FALSE;
497 }
498 }
499
500 if ((hittest == HTERROR) || (hittest == HTNOWHERE))
501 {
Michael Stefaniuc2247af32002-09-04 19:37:01 +0000502 SendMessageA( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
503 MAKELONG( hittest, raw_message ));
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000504 return FALSE;
505 }
506
507 if (!remove || GetCapture()) return TRUE;
508
509 eatMsg = FALSE;
510
511 if ((raw_message == WM_LBUTTONDOWN) ||
512 (raw_message == WM_RBUTTONDOWN) ||
513 (raw_message == WM_MBUTTONDOWN))
514 {
Alexandre Julliard0801ffc2001-08-24 00:26:59 +0000515 HWND hwndTop = GetAncestor( msg->hwnd, GA_ROOT );
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000516
517 /* Send the WM_PARENTNOTIFY,
518 * note that even for double/nonclient clicks
519 * notification message is still WM_L/M/RBUTTONDOWN.
520 */
521 MSG_SendParentNotify( msg->hwnd, raw_message, 0, msg->pt );
522
523 /* Activate the window if needed */
524
525 if (msg->hwnd != GetActiveWindow() && hwndTop != GetDesktopWindow())
526 {
Michael Stefaniuc2247af32002-09-04 19:37:01 +0000527 LONG ret = SendMessageA( msg->hwnd, WM_MOUSEACTIVATE, (WPARAM)hwndTop,
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000528 MAKELONG( hittest, raw_message ) );
529
530 switch(ret)
531 {
532 case MA_NOACTIVATEANDEAT:
533 eatMsg = TRUE;
534 /* fall through */
535 case MA_NOACTIVATE:
536 break;
537 case MA_ACTIVATEANDEAT:
538 eatMsg = TRUE;
539 /* fall through */
540 case MA_ACTIVATE:
Alexandre Julliard03e07b52001-11-06 22:28:18 +0000541 case 0:
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000542 if (hwndTop != GetForegroundWindow() )
543 {
544 if (!WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE ))
545 eatMsg = TRUE;
546 }
547 break;
548 default:
549 WARN( "unknown WM_MOUSEACTIVATE code %ld\n", ret );
550 break;
551 }
552 }
553 }
554
555 /* send the WM_SETCURSOR message */
556
557 /* Windows sends the normal mouse message as the message parameter
558 in the WM_SETCURSOR message even if it's non-client mouse message */
Michael Stefaniuc2247af32002-09-04 19:37:01 +0000559 SendMessageA( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
560 MAKELONG( hittest, raw_message ));
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000561
562 return !eatMsg;
563}
564
565
566/***********************************************************************
567 * process_hardware_message
568 *
569 * returns TRUE if the contents of 'msg' should be passed to the application
570 */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000571BOOL MSG_process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd_filter,
572 UINT first, UINT last, BOOL remove )
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000573{
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000574 if (is_keyboard_message( msg->message ))
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000575 {
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000576 if (!process_raw_keyboard_message( msg, extra_info )) return FALSE;
577 }
578 else if (is_mouse_message( msg->message ))
579 {
580 if (!process_raw_mouse_message( msg, extra_info )) return FALSE;
581 }
582 else
583 {
584 ERR( "unknown message type %x\n", msg->message );
585 return FALSE;
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000586 }
587
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000588 /* check destination thread and filters */
589 if (!check_message_filter( msg, hwnd_filter, first, last ) ||
Alexandre Julliard7695d692001-09-24 01:19:59 +0000590 !WIN_IsCurrentThread( msg->hwnd ))
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000591 {
592 /* queue it for later, or for another thread */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000593 queue_hardware_message( msg, extra_info, MSG_HARDWARE_COOKED );
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000594 return FALSE;
595 }
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000596
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000597 /* save the message in the cooked queue if we didn't want to remove it */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000598 if (!remove) queue_hardware_message( msg, extra_info, MSG_HARDWARE_COOKED );
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000599 return TRUE;
600}
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000601
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000602
603/***********************************************************************
Alexandre Julliardd253c582001-08-07 19:19:08 +0000604 * MSG_process_cooked_hardware_message
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000605 *
606 * returns TRUE if the contents of 'msg' should be passed to the application
607 */
Alexandre Julliard516e40e2001-10-17 17:48:49 +0000608BOOL MSG_process_cooked_hardware_message( MSG *msg, ULONG_PTR extra_info, BOOL remove )
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000609{
610 if (is_keyboard_message( msg->message ))
611 return process_cooked_keyboard_message( msg, remove );
612
613 if (is_mouse_message( msg->message ))
Alexandre Julliard516e40e2001-10-17 17:48:49 +0000614 return process_cooked_mouse_message( msg, extra_info, remove );
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000615
616 ERR( "unknown message type %x\n", msg->message );
Alexandre Julliard838d65a2001-06-19 19:16:41 +0000617 return FALSE;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000618}
619
620
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000621/**********************************************************************
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000622 * GetKeyState (USER.106)
623 */
624INT16 WINAPI GetKeyState16(INT16 vkey)
625{
626 return GetKeyState(vkey);
627}
628
629
630/**********************************************************************
631 * GetKeyState (USER32.@)
632 *
633 * An application calls the GetKeyState function in response to a
634 * keyboard-input message. This function retrieves the state of the key
635 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
636 */
637SHORT WINAPI GetKeyState(INT vkey)
638{
639 INT retval;
640
641 if (vkey >= 'a' && vkey <= 'z') vkey += 'A' - 'a';
Alexandre Julliard01ecb572002-06-10 23:02:19 +0000642 retval = ((WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
643 (QueueKeyStateTable[vkey] & 0x80) |
644 (QueueKeyStateTable[vkey] & 0x01);
645 TRACE("key (0x%x) -> %x\n", vkey, retval);
Alexandre Julliarda21672e2001-10-02 18:53:59 +0000646 return retval;
647}
648
649
650/**********************************************************************
651 * GetKeyboardState (USER.222)
652 * GetKeyboardState (USER32.@)
653 *
654 * An application calls the GetKeyboardState function in response to a
655 * keyboard-input message. This function retrieves the state of the keyboard
656 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
657 */
658BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState)
659{
660 TRACE_(key)("(%p)\n", lpKeyState);
661 if (lpKeyState) memcpy(lpKeyState, QueueKeyStateTable, 256);
662 return TRUE;
663}
664
665
666/**********************************************************************
667 * SetKeyboardState (USER.223)
668 * SetKeyboardState (USER32.@)
669 */
670BOOL WINAPI SetKeyboardState(LPBYTE lpKeyState)
671{
672 TRACE_(key)("(%p)\n", lpKeyState);
673 if (lpKeyState) memcpy(QueueKeyStateTable, lpKeyState, 256);
674 return TRUE;
675}
676
677
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000678/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000679 * WaitMessage (USER.112) Suspend thread pending messages
680 * WaitMessage (USER32.@) Suspend thread pending messages
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000681 *
682 * WaitMessage() suspends a thread until events appear in the thread's
683 * queue.
Alexandre Julliard7e50df31994-08-06 11:22:41 +0000684 */
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000685BOOL WINAPI WaitMessage(void)
Alexandre Julliard7e50df31994-08-06 11:22:41 +0000686{
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000687 return (MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, QS_ALLINPUT, 0 ) != WAIT_FAILED);
Alexandre Julliard7e50df31994-08-06 11:22:41 +0000688}
689
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000690
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000691/***********************************************************************
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000692 * MsgWaitForMultipleObjectsEx (USER32.@)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000693 */
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000694DWORD WINAPI MsgWaitForMultipleObjectsEx( DWORD count, CONST HANDLE *pHandles,
695 DWORD timeout, DWORD mask, DWORD flags )
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000696{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000697 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
Alexandre Julliard3c43df82002-07-01 18:20:16 +0000698 DWORD i, ret, lock;
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000699 MESSAGEQUEUE *msgQueue;
Alexandre Julliarddbf2bf01999-01-01 17:05:53 +0000700
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000701 if (count > MAXIMUM_WAIT_OBJECTS-1)
Alexandre Julliarddbf2bf01999-01-01 17:05:53 +0000702 {
703 SetLastError( ERROR_INVALID_PARAMETER );
704 return WAIT_FAILED;
705 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000706
Alexandre Julliard8afe6622001-07-26 20:12:22 +0000707 if (!(msgQueue = QUEUE_Current())) return WAIT_FAILED;
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000708
709 /* set the queue mask */
710 SERVER_START_REQ( set_queue_mask )
711 {
712 req->wake_mask = (flags & MWMO_INPUTAVAILABLE) ? mask : 0;
713 req->changed_mask = mask;
714 req->skip_wait = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000715 wine_server_call( req );
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000716 }
717 SERVER_END_REQ;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000718
Alexandre Julliarddbf2bf01999-01-01 17:05:53 +0000719 /* Add the thread event to the handle list */
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000720 for (i = 0; i < count; i++) handles[i] = pHandles[i];
721 handles[count] = msgQueue->server_queue;
722
Alexandre Julliard3c43df82002-07-01 18:20:16 +0000723 ReleaseThunkLock( &lock );
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000724 if (USER_Driver.pMsgWaitForMultipleObjectsEx)
Alexandre Julliard43230042001-05-16 19:52:29 +0000725 {
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000726 ret = USER_Driver.pMsgWaitForMultipleObjectsEx( count+1, handles, timeout, mask, flags );
727 if (ret == count+1) ret = count; /* pretend the msg queue is ready */
Alexandre Julliard43230042001-05-16 19:52:29 +0000728 }
729 else
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000730 ret = WaitForMultipleObjectsEx( count+1, handles, flags & MWMO_WAITALL,
731 timeout, flags & MWMO_ALERTABLE );
Alexandre Julliard3c43df82002-07-01 18:20:16 +0000732 if (lock) RestoreThunkLock( lock );
Stephane Lussierb3a99de1999-02-09 15:35:12 +0000733 return ret;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000734}
735
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000736
Eric Pouech982e0ce2001-01-28 23:44:56 +0000737/***********************************************************************
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000738 * MsgWaitForMultipleObjects (USER32.@)
Eric Pouech982e0ce2001-01-28 23:44:56 +0000739 */
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000740DWORD WINAPI MsgWaitForMultipleObjects( DWORD count, CONST HANDLE *handles,
741 BOOL wait_all, DWORD timeout, DWORD mask )
Eric Pouech982e0ce2001-01-28 23:44:56 +0000742{
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000743 return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
744 wait_all ? MWMO_WAITALL : 0 );
Eric Pouech982e0ce2001-01-28 23:44:56 +0000745}
Alexandre Julliard7e50df31994-08-06 11:22:41 +0000746
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000747
748/***********************************************************************
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000749 * WaitForInputIdle (USER32.@)
750 */
751DWORD WINAPI WaitForInputIdle( HANDLE hProcess, DWORD dwTimeOut )
752{
Francois Gouget671a2ee2001-10-08 20:28:12 +0000753 DWORD start_time, elapsed, ret;
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000754 HANDLE idle_event = -1;
755
756 SERVER_START_REQ( wait_input_idle )
757 {
758 req->handle = hProcess;
759 req->timeout = dwTimeOut;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000760 if (!(ret = wine_server_call_err( req ))) idle_event = reply->event;
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000761 }
762 SERVER_END_REQ;
Francois Gouget671a2ee2001-10-08 20:28:12 +0000763 if (ret) return WAIT_FAILED; /* error */
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000764 if (!idle_event) return 0; /* no event to wait on */
765
Francois Gouget671a2ee2001-10-08 20:28:12 +0000766 start_time = GetTickCount();
767 elapsed = 0;
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000768
769 TRACE("waiting for %x\n", idle_event );
Francois Gouget671a2ee2001-10-08 20:28:12 +0000770 do
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000771 {
Francois Gouget671a2ee2001-10-08 20:28:12 +0000772 ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut - elapsed, QS_SENDMESSAGE );
773 switch (ret)
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000774 {
Francois Gouget671a2ee2001-10-08 20:28:12 +0000775 case WAIT_OBJECT_0+1:
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000776 process_sent_messages();
Francois Gouget671a2ee2001-10-08 20:28:12 +0000777 break;
778 case WAIT_TIMEOUT:
779 case WAIT_FAILED:
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000780 TRACE("timeout or error\n");
781 return ret;
Francois Gouget671a2ee2001-10-08 20:28:12 +0000782 default:
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000783 TRACE("finished\n");
784 return 0;
785 }
Francois Gouget671a2ee2001-10-08 20:28:12 +0000786 if (dwTimeOut != INFINITE)
787 {
788 elapsed = GetTickCount() - start_time;
789 if (elapsed > dwTimeOut)
790 break;
791 }
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000792 }
Francois Gouget671a2ee2001-10-08 20:28:12 +0000793 while (1);
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000794
795 return WAIT_TIMEOUT;
796}
797
798
799/***********************************************************************
800 * UserYield (USER.332)
801 * UserYield16 (USER32.@)
802 */
803void WINAPI UserYield16(void)
804{
Alexandre Julliardd253c582001-08-07 19:19:08 +0000805 DWORD count;
806
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000807 /* Handle sent messages */
808 process_sent_messages();
809
810 /* Yield */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000811 ReleaseThunkLock(&count);
812 if (count)
813 {
814 RestoreThunkLock(count);
815 /* Handle sent messages again */
816 process_sent_messages();
817 }
Alexandre Julliard9f55ae62001-06-28 04:37:22 +0000818}
819
820
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000821struct accent_char
822{
823 BYTE ac_accent;
824 BYTE ac_char;
825 BYTE ac_result;
826};
827
828static const struct accent_char accent_chars[] =
829{
Alexandre Julliard21979011997-03-05 08:22:35 +0000830/* A good idea should be to read /usr/X11/lib/X11/locale/iso8859-x/Compose */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000831 {'`', 'A', '\300'}, {'`', 'a', '\340'},
832 {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
833 {'^', 'A', '\302'}, {'^', 'a', '\342'},
834 {'~', 'A', '\303'}, {'~', 'a', '\343'},
835 {'"', 'A', '\304'}, {'"', 'a', '\344'},
836 {'O', 'A', '\305'}, {'o', 'a', '\345'},
837 {'0', 'A', '\305'}, {'0', 'a', '\345'},
838 {'A', 'A', '\305'}, {'a', 'a', '\345'},
839 {'A', 'E', '\306'}, {'a', 'e', '\346'},
840 {',', 'C', '\307'}, {',', 'c', '\347'},
841 {'`', 'E', '\310'}, {'`', 'e', '\350'},
842 {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
843 {'^', 'E', '\312'}, {'^', 'e', '\352'},
844 {'"', 'E', '\313'}, {'"', 'e', '\353'},
845 {'`', 'I', '\314'}, {'`', 'i', '\354'},
846 {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
847 {'^', 'I', '\316'}, {'^', 'i', '\356'},
848 {'"', 'I', '\317'}, {'"', 'i', '\357'},
849 {'-', 'D', '\320'}, {'-', 'd', '\360'},
850 {'~', 'N', '\321'}, {'~', 'n', '\361'},
851 {'`', 'O', '\322'}, {'`', 'o', '\362'},
852 {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
853 {'^', 'O', '\324'}, {'^', 'o', '\364'},
854 {'~', 'O', '\325'}, {'~', 'o', '\365'},
855 {'"', 'O', '\326'}, {'"', 'o', '\366'},
856 {'/', 'O', '\330'}, {'/', 'o', '\370'},
857 {'`', 'U', '\331'}, {'`', 'u', '\371'},
858 {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
859 {'^', 'U', '\333'}, {'^', 'u', '\373'},
860 {'"', 'U', '\334'}, {'"', 'u', '\374'},
861 {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
862 {'T', 'H', '\336'}, {'t', 'h', '\376'},
863 {'s', 's', '\337'}, {'"', 'y', '\377'},
864 {'s', 'z', '\337'}, {'i', 'j', '\377'},
Alexandre Julliard21979011997-03-05 08:22:35 +0000865 /* iso-8859-2 uses this */
866 {'<', 'L', '\245'}, {'<', 'l', '\265'}, /* caron */
867 {'<', 'S', '\251'}, {'<', 's', '\271'},
868 {'<', 'T', '\253'}, {'<', 't', '\273'},
869 {'<', 'Z', '\256'}, {'<', 'z', '\276'},
870 {'<', 'C', '\310'}, {'<', 'c', '\350'},
871 {'<', 'E', '\314'}, {'<', 'e', '\354'},
872 {'<', 'D', '\317'}, {'<', 'd', '\357'},
873 {'<', 'N', '\322'}, {'<', 'n', '\362'},
874 {'<', 'R', '\330'}, {'<', 'r', '\370'},
875 {';', 'A', '\241'}, {';', 'a', '\261'}, /* ogonek */
876 {';', 'E', '\312'}, {';', 'e', '\332'},
877 {'\'', 'Z', '\254'}, {'\'', 'z', '\274'}, /* acute */
878 {'\'', 'R', '\300'}, {'\'', 'r', '\340'},
879 {'\'', 'L', '\305'}, {'\'', 'l', '\345'},
880 {'\'', 'C', '\306'}, {'\'', 'c', '\346'},
881 {'\'', 'N', '\321'}, {'\'', 'n', '\361'},
882/* collision whith S, from iso-8859-9 !!! */
883 {',', 'S', '\252'}, {',', 's', '\272'}, /* cedilla */
884 {',', 'T', '\336'}, {',', 't', '\376'},
885 {'.', 'Z', '\257'}, {'.', 'z', '\277'}, /* dot above */
886 {'/', 'L', '\243'}, {'/', 'l', '\263'}, /* slash */
887 {'/', 'D', '\320'}, {'/', 'd', '\360'},
888 {'(', 'A', '\303'}, {'(', 'a', '\343'}, /* breve */
889 {'\275', 'O', '\325'}, {'\275', 'o', '\365'}, /* double acute */
890 {'\275', 'U', '\334'}, {'\275', 'u', '\374'},
891 {'0', 'U', '\332'}, {'0', 'u', '\372'}, /* ring above */
892 /* iso-8859-3 uses this */
893 {'/', 'H', '\241'}, {'/', 'h', '\261'}, /* slash */
894 {'>', 'H', '\246'}, {'>', 'h', '\266'}, /* circumflex */
895 {'>', 'J', '\254'}, {'>', 'j', '\274'},
896 {'>', 'C', '\306'}, {'>', 'c', '\346'},
897 {'>', 'G', '\330'}, {'>', 'g', '\370'},
898 {'>', 'S', '\336'}, {'>', 's', '\376'},
899/* collision whith G( from iso-8859-9 !!! */
900 {'(', 'G', '\253'}, {'(', 'g', '\273'}, /* breve */
901 {'(', 'U', '\335'}, {'(', 'u', '\375'},
902/* collision whith I. from iso-8859-3 !!! */
903 {'.', 'I', '\251'}, {'.', 'i', '\271'}, /* dot above */
904 {'.', 'C', '\305'}, {'.', 'c', '\345'},
905 {'.', 'G', '\325'}, {'.', 'g', '\365'},
906 /* iso-8859-4 uses this */
907 {',', 'R', '\243'}, {',', 'r', '\263'}, /* cedilla */
908 {',', 'L', '\246'}, {',', 'l', '\266'},
909 {',', 'G', '\253'}, {',', 'g', '\273'},
910 {',', 'N', '\321'}, {',', 'n', '\361'},
911 {',', 'K', '\323'}, {',', 'k', '\363'},
912 {'~', 'I', '\245'}, {'~', 'i', '\265'}, /* tilde */
913 {'-', 'E', '\252'}, {'-', 'e', '\272'}, /* macron */
914 {'-', 'A', '\300'}, {'-', 'a', '\340'},
915 {'-', 'I', '\317'}, {'-', 'i', '\357'},
916 {'-', 'O', '\322'}, {'-', 'o', '\362'},
917 {'-', 'U', '\336'}, {'-', 'u', '\376'},
918 {'/', 'T', '\254'}, {'/', 't', '\274'}, /* slash */
919 {'.', 'E', '\314'}, {'.', 'e', '\344'}, /* dot above */
920 {';', 'I', '\307'}, {';', 'i', '\347'}, /* ogonek */
921 {';', 'U', '\331'}, {';', 'u', '\371'},
922 /* iso-8859-9 uses this */
923 /* iso-8859-9 has really bad choosen G( S, and I. as they collide
924 * whith the same letters on other iso-8859-x (that is they are on
925 * different places :-( ), if you use turkish uncomment these and
926 * comment out the lines in iso-8859-2 and iso-8859-3 sections
927 * FIXME: should be dynamic according to chosen language
Vincent Béron9a624912002-05-31 23:06:46 +0000928 * if/when Wine has turkish support.
929 */
Alexandre Julliard21979011997-03-05 08:22:35 +0000930/* collision whith G( from iso-8859-3 !!! */
931/* {'(', 'G', '\320'}, {'(', 'g', '\360'}, */ /* breve */
932/* collision whith S, from iso-8859-2 !!! */
933/* {',', 'S', '\336'}, {',', 's', '\376'}, */ /* cedilla */
934/* collision whith I. from iso-8859-3 !!! */
935/* {'.', 'I', '\335'}, {'.', 'i', '\375'}, */ /* dot above */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000936};
937
938
Alexandre Julliard7e50df31994-08-06 11:22:41 +0000939/***********************************************************************
Alexandre Julliardd253c582001-08-07 19:19:08 +0000940 * TranslateMessage (USER32.@)
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000941 *
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000942 * Implementation of TranslateMessage.
943 *
944 * TranslateMessage translates virtual-key messages into character-messages,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000945 * as follows :
946 * WM_KEYDOWN/WM_KEYUP combinations produce a WM_CHAR or WM_DEADCHAR message.
947 * ditto replacing WM_* with WM_SYS*
948 * This produces WM_CHAR messages only for keys mapped to ASCII characters
949 * by the keyboard driver.
Alexandre Julliard01ecb572002-06-10 23:02:19 +0000950 *
951 * If the message is WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP, the
952 * return value is nonzero, regardless of the translation.
953 *
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000954 */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000955BOOL WINAPI TranslateMessage( const MSG *msg )
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000956{
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000957 static int dead_char;
Alexandre Julliardd253c582001-08-07 19:19:08 +0000958 UINT message;
Dmitry Timoshkov2fa0c662000-11-25 02:09:45 +0000959 WCHAR wp[2];
Alexandre Julliard01ecb572002-06-10 23:02:19 +0000960 BOOL rc = FALSE;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000961
Alexandre Julliardd253c582001-08-07 19:19:08 +0000962 if (msg->message >= WM_KEYFIRST && msg->message <= WM_KEYLAST)
Alexandre Julliard01ecb572002-06-10 23:02:19 +0000963 {
Alexandre Julliardd253c582001-08-07 19:19:08 +0000964 TRACE_(key)("(%s, %04X, %08lX)\n",
Guy L. Albertellidb9b5492001-09-07 18:38:57 +0000965 SPY_GetMsgName(msg->message, msg->hwnd), msg->wParam, msg->lParam );
Alexandre Julliardd253c582001-08-07 19:19:08 +0000966
Alexandre Julliard01ecb572002-06-10 23:02:19 +0000967 /* Return code must be TRUE no matter what! */
968 rc = TRUE;
969 }
970
971 if ((msg->message != WM_KEYDOWN) && (msg->message != WM_SYSKEYDOWN)) return rc;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000972
Dmitry Timoshkov740bb922000-11-05 20:07:59 +0000973 TRACE_(key)("Translating key %s (%04x), scancode %02x\n",
Alexandre Julliardd253c582001-08-07 19:19:08 +0000974 SPY_GetVKeyName(msg->wParam), msg->wParam, LOBYTE(HIWORD(msg->lParam)));
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000975
Dmitry Timoshkov2fa0c662000-11-25 02:09:45 +0000976 /* FIXME : should handle ToUnicode yielding 2 */
Alexandre Julliardd253c582001-08-07 19:19:08 +0000977 switch (ToUnicode(msg->wParam, HIWORD(msg->lParam), QueueKeyStateTable, wp, 2, 0))
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000978 {
Andreas Mohr1af53cb2000-12-09 03:15:32 +0000979 case 1:
Alexandre Julliardd253c582001-08-07 19:19:08 +0000980 message = (msg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000981 /* Should dead chars handling go in ToAscii ? */
982 if (dead_char)
983 {
984 int i;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000985
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000986 if (wp[0] == ' ') wp[0] = dead_char;
Alexandre Julliard21979011997-03-05 08:22:35 +0000987 if (dead_char == 0xa2) dead_char = '(';
988 else if (dead_char == 0xa8) dead_char = '"';
989 else if (dead_char == 0xb2) dead_char = ';';
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000990 else if (dead_char == 0xb4) dead_char = '\'';
Alexandre Julliard21979011997-03-05 08:22:35 +0000991 else if (dead_char == 0xb7) dead_char = '<';
992 else if (dead_char == 0xb8) dead_char = ',';
993 else if (dead_char == 0xff) dead_char = '.';
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000994 for (i = 0; i < sizeof(accent_chars)/sizeof(accent_chars[0]); i++)
995 if ((accent_chars[i].ac_accent == dead_char) &&
996 (accent_chars[i].ac_char == wp[0]))
997 {
998 wp[0] = accent_chars[i].ac_result;
999 break;
1000 }
1001 dead_char = 0;
1002 }
Guy L. Albertellidb9b5492001-09-07 18:38:57 +00001003 TRACE_(key)("1 -> PostMessage(%s)\n", SPY_GetMsgName(message, msg->hwnd));
Alexandre Julliardd253c582001-08-07 19:19:08 +00001004 PostMessageW( msg->hwnd, message, wp[0], msg->lParam );
Alexandre Julliard01ecb572002-06-10 23:02:19 +00001005 break;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001006
Andreas Mohr1af53cb2000-12-09 03:15:32 +00001007 case -1:
Alexandre Julliardd253c582001-08-07 19:19:08 +00001008 message = (msg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001009 dead_char = wp[0];
Guy L. Albertellidb9b5492001-09-07 18:38:57 +00001010 TRACE_(key)("-1 -> PostMessage(%s)\n", SPY_GetMsgName(message, msg->hwnd));
Alexandre Julliardd253c582001-08-07 19:19:08 +00001011 PostMessageW( msg->hwnd, message, wp[0], msg->lParam );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001012 return TRUE;
Alexandre Julliard75a839a1993-07-15 11:13:45 +00001013 }
Alexandre Julliard01ecb572002-06-10 23:02:19 +00001014 return rc;
Alexandre Julliard75a839a1993-07-15 11:13:45 +00001015}
1016
1017
1018/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001019 * DispatchMessageA (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001020 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001021LONG WINAPI DispatchMessageA( const MSG* msg )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001022{
1023 WND * wndPtr;
1024 LONG retval;
1025 int painting;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001026 WNDPROC winproc;
1027
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001028 /* Process timer messages */
1029 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
1030 {
1031 if (msg->lParam)
1032 {
1033/* HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
Stephane Lussier6bac4f22000-09-29 00:56:05 +00001034
Andreas Mohr1af53cb2000-12-09 03:15:32 +00001035 /* before calling window proc, verify whether timer is still valid;
1036 there's a slim chance that the application kills the timer
1037 between GetMessage and DispatchMessage API calls */
Stephane Lussier6bac4f22000-09-29 00:56:05 +00001038 if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
1039 return 0; /* invalid winproc */
1040
Alexandre Julliarda3960291999-02-26 11:11:13 +00001041 return CallWindowProcA( (WNDPROC)msg->lParam, msg->hwnd,
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001042 msg->message, msg->wParam, GetTickCount() );
1043 }
1044 }
1045
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001046 if (!(wndPtr = WIN_GetPtr( msg->hwnd )))
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00001047 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001048 if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1049 return 0;
1050 }
1051 if (wndPtr == WND_OTHER_PROCESS)
1052 {
1053 if (IsWindow( msg->hwnd ))
1054 ERR( "cannot dispatch msg to other process window %x\n", msg->hwnd );
1055 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1056 return 0;
1057 }
1058 if (!(winproc = wndPtr->winproc))
1059 {
1060 WIN_ReleasePtr( wndPtr );
1061 return 0;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00001062 }
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001063 painting = (msg->message == WM_PAINT);
1064 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001065 WIN_ReleasePtr( wndPtr );
1066/* hook_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001067
Alexandre Julliarda3960291999-02-26 11:11:13 +00001068 SPY_EnterMessage( SPY_DISPATCHMESSAGE, msg->hwnd, msg->message,
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001069 msg->wParam, msg->lParam );
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001070 retval = CallWindowProcA( winproc, msg->hwnd, msg->message,
1071 msg->wParam, msg->lParam );
Guy L. Albertelli936c6c42000-10-22 23:52:47 +00001072 SPY_ExitMessage( SPY_RESULT_OK, msg->hwnd, msg->message, retval,
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001073 msg->wParam, msg->lParam );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001074
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001075 if (painting && (wndPtr = WIN_GetPtr( msg->hwnd )) && (wndPtr != WND_OTHER_PROCESS))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001076 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001077 BOOL validate = ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate);
1078 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
1079 WIN_ReleasePtr( wndPtr );
1080 if (validate)
1081 {
1082 ERR( "BeginPaint not called on WM_PAINT for hwnd %04x!\n", msg->hwnd );
1083 /* Validate the update region to avoid infinite WM_PAINT loop */
1084 RedrawWindow( msg->hwnd, NULL, 0,
1085 RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
1086 }
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001087 }
1088 return retval;
1089}
1090
1091
1092/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001093 * DispatchMessageW (USER32.@) Process Message
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001094 *
1095 * Process the message specified in the structure *_msg_.
1096 *
1097 * If the lpMsg parameter points to a WM_TIMER message and the
1098 * parameter of the WM_TIMER message is not NULL, the lParam parameter
1099 * points to the function that is called instead of the window
1100 * procedure.
Vincent Béron9a624912002-05-31 23:06:46 +00001101 *
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001102 * The message must be valid.
1103 *
1104 * RETURNS
1105 *
1106 * DispatchMessage() returns the result of the window procedure invoked.
1107 *
1108 * CONFORMANCE
1109 *
Vincent Béron9a624912002-05-31 23:06:46 +00001110 * ECMA-234, Win32
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001111 *
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001112 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001113LONG WINAPI DispatchMessageW( const MSG* msg )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001114{
1115 WND * wndPtr;
1116 LONG retval;
1117 int painting;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001118 WNDPROC winproc;
1119
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001120 /* Process timer messages */
1121 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
1122 {
1123 if (msg->lParam)
1124 {
1125/* HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
Stephane Lussier6bac4f22000-09-29 00:56:05 +00001126
Andreas Mohr1af53cb2000-12-09 03:15:32 +00001127 /* before calling window proc, verify whether timer is still valid;
1128 there's a slim chance that the application kills the timer
1129 between GetMessage and DispatchMessage API calls */
Stephane Lussier6bac4f22000-09-29 00:56:05 +00001130 if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
1131 return 0; /* invalid winproc */
1132
Alexandre Julliarda3960291999-02-26 11:11:13 +00001133 return CallWindowProcW( (WNDPROC)msg->lParam, msg->hwnd,
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001134 msg->message, msg->wParam, GetTickCount() );
1135 }
1136 }
1137
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001138 if (!(wndPtr = WIN_GetPtr( msg->hwnd )))
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00001139 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001140 if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1141 return 0;
1142 }
1143 if (wndPtr == WND_OTHER_PROCESS)
1144 {
1145 if (IsWindow( msg->hwnd ))
1146 ERR( "cannot dispatch msg to other process window %x\n", msg->hwnd );
1147 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1148 return 0;
1149 }
1150 if (!(winproc = wndPtr->winproc))
1151 {
1152 WIN_ReleasePtr( wndPtr );
1153 return 0;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00001154 }
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001155 painting = (msg->message == WM_PAINT);
1156 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001157 WIN_ReleasePtr( wndPtr );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001158/* HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
1159
Alexandre Julliarda3960291999-02-26 11:11:13 +00001160 SPY_EnterMessage( SPY_DISPATCHMESSAGE, msg->hwnd, msg->message,
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001161 msg->wParam, msg->lParam );
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001162 retval = CallWindowProcW( winproc, msg->hwnd, msg->message,
1163 msg->wParam, msg->lParam );
Guy L. Albertelli936c6c42000-10-22 23:52:47 +00001164 SPY_ExitMessage( SPY_RESULT_OK, msg->hwnd, msg->message, retval,
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001165 msg->wParam, msg->lParam );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001166
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001167 if (painting && (wndPtr = WIN_GetPtr( msg->hwnd )) && (wndPtr != WND_OTHER_PROCESS))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001168 {
Alexandre Julliard8fd26b92001-10-15 17:56:45 +00001169 BOOL validate = ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate);
1170 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
1171 WIN_ReleasePtr( wndPtr );
1172 if (validate)
1173 {
1174 ERR( "BeginPaint not called on WM_PAINT for hwnd %04x!\n", msg->hwnd );
1175 /* Validate the update region to avoid infinite WM_PAINT loop */
1176 RedrawWindow( msg->hwnd, NULL, 0,
1177 RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
1178 }
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001179 }
1180 return retval;
1181}
1182
1183
1184/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001185 * RegisterWindowMessage (USER.118)
1186 * RegisterWindowMessageA (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001187 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001188WORD WINAPI RegisterWindowMessageA( LPCSTR str )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001189{
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001190 TRACE("%s\n", str );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001191 return GlobalAddAtomA( str );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001192}
Alexandre Julliard86a8d0f1994-01-18 23:04:40 +00001193
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001194
1195/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001196 * RegisterWindowMessageW (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001197 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001198WORD WINAPI RegisterWindowMessageW( LPCWSTR str )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001199{
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001200 TRACE("%p\n", str );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001201 return GlobalAddAtomW( str );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001202}
1203
1204
Alexandre Julliard86a8d0f1994-01-18 23:04:40 +00001205/***********************************************************************
Patrik Stridvallfc343442002-08-20 00:20:43 +00001206 * BroadcastSystemMessage (USER32.@)
1207 * BroadcastSystemMessageA (USER32.@)
Alexandre Julliarde658d821997-11-30 17:45:40 +00001208 */
1209LONG WINAPI BroadcastSystemMessage(
Alexandre Julliarda3960291999-02-26 11:11:13 +00001210 DWORD dwFlags,LPDWORD recipients,UINT uMessage,WPARAM wParam,
Aric Stewart5501f122002-08-16 23:29:48 +00001211 LPARAM lParam )
1212{
1213 if ((*recipients & BSM_APPLICATIONS)||
1214 (*recipients == BSM_ALLCOMPONENTS))
1215 {
1216 FIXME("(%08lx,%08lx,%08x,%08x,%08lx): semi-stub!\n",
1217 dwFlags,*recipients,uMessage,wParam,lParam);
1218 PostMessageA(HWND_BROADCAST,uMessage,wParam,lParam);
1219 return 1;
1220 }
1221 else
1222 {
1223 FIXME("(%08lx,%08lx,%08x,%08x,%08lx): stub!\n",
1224 dwFlags,*recipients,uMessage,wParam,lParam);
1225 return -1;
1226 }
Alexandre Julliarde658d821997-11-30 17:45:40 +00001227}