2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <sys/types.h>
15 #include "sysmetrics.h"
18 #include "stackframe.h"
25 /* #define DEBUG_MSG */
28 #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
29 #define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
31 #define HWND_BROADCAST16 ((HWND16)0xffff)
32 #define HWND_BROADCAST32 ((HWND32)0xffffffff)
34 extern BYTE* KeyStateTable; /* event.c */
35 extern WPARAM lastEventChar; /* event.c */
37 DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
39 static WORD doubleClickSpeed = 452;
41 /***********************************************************************
42 * MSG_TranslateMouseMsg
44 * Translate an mouse hardware event into a real mouse message.
45 * Return value indicates whether the translated message must be passed
48 * - Find the window for this message.
49 * - Translate button-down messages in double-clicks.
50 * - Send the WM_NCHITTEST message to find where the cursor is.
51 * - Activate the window if needed.
52 * - Translate the message into a non-client message, or translate
53 * the coordinates to client coordinates.
54 * - Send the WM_SETCURSOR message.
56 static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
61 static DWORD lastClickTime = 0;
62 static WORD lastClickMsg = 0;
63 static POINT16 lastClickPos = { 0, 0 };
65 MOUSEHOOKSTRUCT16 hook = { msg->pt, 0, HTCLIENT, 0 };
67 BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
68 (msg->message == WM_RBUTTONDOWN) ||
69 (msg->message == WM_MBUTTONDOWN));
73 if ((msg->hwnd = GetCapture()) != 0)
75 ScreenToClient16( msg->hwnd, &pt );
76 msg->lParam = MAKELONG( pt.x, pt.y );
77 /* No need to further process the message */
78 hook.hwnd = msg->hwnd;
79 return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
80 msg->message, (LPARAM)MAKE_SEGPTR(&hook));
83 hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
84 if (pWnd->hmemTaskQ != GetTaskQueue(0))
86 /* Not for the current task */
87 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
88 if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
89 /* Wake up the other task */
90 queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
91 if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
94 msg->hwnd = pWnd->hwndSelf;
95 if ((hittest != HTERROR) && mouseClick)
97 HWND hwndTop = WIN_GetTopParent( msg->hwnd );
99 /* Send the WM_PARENTNOTIFY message */
101 WIN_SendParentNotify( msg->hwnd, msg->message, 0,
102 MAKELONG( msg->pt.x, msg->pt.y ) );
104 /* Activate the window if needed */
106 if (msg->hwnd != GetActiveWindow() && msg->hwnd != GetDesktopWindow())
108 LONG ret = SendMessage16( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
109 MAKELONG( hittest, msg->message ) );
111 if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
114 if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
115 && hwndTop != GetActiveWindow() )
116 WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE );
120 /* Send the WM_SETCURSOR message */
122 SendMessage16( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
123 MAKELONG( hittest, msg->message ));
124 if (eatMsg) return FALSE;
126 /* Check for double-click */
130 BOOL dbl_click = FALSE;
132 if ((msg->message == lastClickMsg) &&
133 (msg->time - lastClickTime < doubleClickSpeed) &&
134 (abs(msg->pt.x - lastClickPos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
135 (abs(msg->pt.y - lastClickPos.y) < SYSMETRICS_CYDOUBLECLK/2))
138 if (dbl_click && (hittest == HTCLIENT))
140 /* Check whether window wants the double click message. */
141 dbl_click = (pWnd->class->style & CS_DBLCLKS) != 0;
144 if (dbl_click) switch(msg->message)
146 case WM_LBUTTONDOWN: msg->message = WM_LBUTTONDBLCLK; break;
147 case WM_RBUTTONDOWN: msg->message = WM_RBUTTONDBLCLK; break;
148 case WM_MBUTTONDOWN: msg->message = WM_MBUTTONDBLCLK; break;
153 lastClickTime = msg->time;
154 lastClickMsg = msg->message;
155 lastClickPos = msg->pt;
159 /* Build the translated message */
161 if (hittest == HTCLIENT)
162 ScreenToClient16( msg->hwnd, &pt );
165 msg->wParam = hittest;
166 msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
168 msg->lParam = MAKELONG( pt.x, pt.y );
170 hook.hwnd = msg->hwnd;
171 hook.wHitTestCode = hittest;
172 return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
173 msg->message, (LPARAM)MAKE_SEGPTR(&hook));
177 /***********************************************************************
178 * MSG_TranslateKeyboardMsg
180 * Translate an keyboard hardware event into a real message.
181 * Return value indicates whether the translated message must be passed
184 static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
188 /* Should check Ctrl-Esc and PrintScreen here */
190 msg->hwnd = GetFocus();
193 /* Send the message to the active window instead, */
194 /* translating messages to their WM_SYS equivalent */
196 msg->hwnd = GetActiveWindow();
198 if( msg->message < WM_SYSKEYDOWN )
199 msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
201 pWnd = WIN_FindWndPtr( msg->hwnd );
202 if (pWnd && (pWnd->hmemTaskQ != GetTaskQueue(0)))
204 /* Not for the current task */
205 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
206 if (queue) QUEUE_ClearWakeBit( queue, QS_KEY );
207 /* Wake up the other task */
208 queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
209 if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
212 return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
213 msg->wParam, msg->lParam );
217 /***********************************************************************
218 * MSG_PeekHardwareMsg
220 * Peek for a hardware message matching the hwnd and message filters.
222 static BOOL MSG_PeekHardwareMsg( MSG16 *msg, HWND hwnd, WORD first, WORD last,
225 MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
226 int i, pos = sysMsgQueue->nextMessage;
228 /* If the queue is empty, attempt to fill it */
229 if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( FALSE );
231 for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
233 if (pos >= sysMsgQueue->queueSize) pos = 0;
234 *msg = sysMsgQueue->messages[pos].msg;
236 /* Translate message */
238 if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
240 if (!MSG_TranslateMouseMsg( msg, remove )) continue;
242 else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
244 if (!MSG_TranslateKeyboardMsg( msg, remove )) continue;
246 else /* Non-standard hardware event */
248 HARDWAREHOOKSTRUCT16 hook = { msg->hwnd, msg->message,
249 msg->wParam, msg->lParam };
250 if (HOOK_CallHooks( WH_HARDWARE, remove ? HC_ACTION : HC_NOREMOVE,
251 0, (LPARAM)MAKE_SEGPTR(&hook) )) continue;
254 /* Check message against filters */
256 if (hwnd && (msg->hwnd != hwnd)) continue;
257 if ((first || last) &&
258 ((msg->message < first) || (msg->message > last))) continue;
259 if ((msg->hwnd != GetDesktopWindow()) &&
260 (GetWindowTask16(msg->hwnd) != GetCurrentTask()))
261 continue; /* Not for this task */
264 MSG16 tmpMsg = *msg; /* FIXME */
265 HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION,
266 0, (LPARAM)MAKE_SEGPTR(&tmpMsg) );
267 QUEUE_RemoveMsg( sysMsgQueue, pos );
275 /**********************************************************************
276 * SetDoubleClickTime (USER.20)
278 void SetDoubleClickTime( WORD interval )
280 doubleClickSpeed = interval ? interval : 500;
284 /**********************************************************************
285 * GetDoubleClickTime (USER.21)
287 WORD GetDoubleClickTime()
289 return doubleClickSpeed;
293 /***********************************************************************
296 * Implementation of an inter-task SendMessage.
298 static LRESULT MSG_SendMessage( HQUEUE hDestQueue, HWND hwnd, UINT msg,
299 WPARAM wParam, LPARAM lParam )
301 MESSAGEQUEUE *queue, *destQ;
303 if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return 0;
304 if (!(destQ = (MESSAGEQUEUE*)GlobalLock16( hDestQueue ))) return 0;
308 fprintf( stderr, "SendMessage: task is locked\n" );
314 fprintf( stderr, "Nested SendMessage() not supported\n" );
319 queue->wParam = wParam;
320 queue->lParam = lParam;
321 queue->hPrevSendingTask = destQ->hSendingTask;
322 destQ->hSendingTask = GetTaskQueue(0);
323 QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
325 /* Wait for the result */
327 printf( "SendMessage %04x to %04x\n", msg, hDestQueue );
329 if (!(queue->wakeBits & QS_SMRESULT))
331 DirectedYield( destQ->hTask );
332 QUEUE_WaitBits( QS_SMRESULT );
334 printf( "SendMessage %04x to %04x: got %08lx\n",
335 msg, hDestQueue, queue->SendMessageReturn );
336 queue->wakeBits &= ~QS_SMRESULT;
337 return queue->SendMessageReturn;
341 /***********************************************************************
342 * ReplyMessage (USER.115)
344 void ReplyMessage( LRESULT result )
346 MESSAGEQUEUE *senderQ;
349 printf( "ReplyMessage\n " );
350 if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return;
351 if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
355 if (queue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( queue );
356 else if (senderQ->wakeBits & QS_SMRESULT) Yield();
359 printf( "ReplyMessage: res = %08lx\n", result );
360 senderQ->SendMessageReturn = result;
361 queue->InSendMessageHandle = 0;
362 QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
363 DirectedYield( queue->hSendingTask );
367 /***********************************************************************
370 static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last,
371 WORD flags, BOOL peek )
374 MESSAGEQUEUE *msgQueue;
378 DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/
379 DDE_GetRemoteMessage();
380 #endif /* CONFIG_IPC */
382 mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
385 /* MSWord gets stuck if we do not check for nonclient mouse messages */
387 if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
388 if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) ||
389 ((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE;
390 if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
391 if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
392 if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
394 else mask |= QS_MOUSE | QS_KEY | QS_TIMER | QS_PAINT;
396 if (IsTaskLocked()) flags |= PM_NOYIELD;
400 hQueue = GetTaskQueue(0);
401 msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
402 if (!msgQueue) return FALSE;
403 msgQueue->changeBits = 0;
405 /* First handle a message put by SendMessage() */
407 if (msgQueue->wakeBits & QS_SENDMESSAGE)
408 QUEUE_ReceiveMessage( msgQueue );
410 /* Now find a normal message */
412 if (((msgQueue->wakeBits & mask) & QS_POSTMESSAGE) &&
413 ((pos = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != -1))
415 QMSG *qmsg = &msgQueue->messages[pos];
417 msgQueue->GetMessageTimeVal = msg->time;
418 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
419 msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
421 if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, pos );
425 /* Now find a hardware event */
427 if (((msgQueue->wakeBits & mask) & (QS_MOUSE | QS_KEY)) &&
428 MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
431 msgQueue->GetMessageTimeVal = msg->time;
432 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
433 msgQueue->GetMessageExtraInfoVal = 0; /* Always 0 for now */
437 /* Now handle a WM_QUIT message */
439 if (msgQueue->wPostQMsg)
442 msg->message = WM_QUIT;
443 msg->wParam = msgQueue->wExitCode;
448 /* Check again for SendMessage */
450 if (msgQueue->wakeBits & QS_SENDMESSAGE)
451 QUEUE_ReceiveMessage( msgQueue );
453 /* Now find a WM_PAINT message */
455 if ((msgQueue->wakeBits & mask) & QS_PAINT)
457 msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
458 msg->message = WM_PAINT;
462 (!hwnd || msg->hwnd == hwnd || IsChild(hwnd,msg->hwnd)) )
464 WND* wndPtr = WIN_FindWndPtr(msg->hwnd);
466 /* FIXME: WM_PAINTICON should be sent sometimes */
468 if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
470 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
471 QUEUE_DecPaintCount( hQueue );
477 /* Check for timer messages, but yield first */
479 if (!(flags & PM_NOYIELD))
482 if (msgQueue->wakeBits & QS_SENDMESSAGE)
483 QUEUE_ReceiveMessage( msgQueue );
485 if ((msgQueue->wakeBits & mask) & QS_TIMER)
487 if (TIMER_GetTimerMsg(msg, hwnd, hQueue, flags & PM_REMOVE)) break;
492 if (!(flags & PM_NOYIELD)) UserYield();
495 msgQueue->wakeMask = mask;
496 QUEUE_WaitBits( mask );
499 /* We got a message */
500 if (peek) return TRUE;
501 else return (msg->message != WM_QUIT);
505 /***********************************************************************
506 * MSG_InternalGetMessage
508 * GetMessage() function for internal use. Behave like GetMessage(),
509 * but also call message filters and optionally send WM_ENTERIDLE messages.
510 * 'hwnd' must be the handle of the dialog or menu window.
511 * 'code' is the message filter value (MSGF_??? codes).
513 BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner, short code,
514 WORD flags, BOOL sendIdle )
520 if (!MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
521 0, 0, 0, flags, TRUE ))
523 /* No message present -> send ENTERIDLE and wait */
524 if (IsWindow(hwndOwner))
525 SendMessage16( hwndOwner, WM_ENTERIDLE,
526 code, (LPARAM)hwnd );
527 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
528 0, 0, 0, flags, FALSE );
531 else /* Always wait for a message */
532 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
533 0, 0, 0, flags, FALSE );
535 if (!CallMsgFilter( msg, code ))
536 return (((MSG16 *)PTR_SEG_TO_LIN(msg))->message != WM_QUIT);
538 /* Message filtered -> remove it from the queue */
539 /* if it's still there. */
540 if (!(flags & PM_REMOVE))
541 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
542 0, 0, 0, PM_REMOVE, TRUE );
547 /***********************************************************************
548 * PeekMessage16 (USER.109)
550 BOOL16 PeekMessage16( LPMSG16 msg, HWND16 hwnd, UINT16 first,
551 UINT16 last, UINT16 flags )
553 return MSG_PeekMessage( msg, hwnd, first, last, flags, TRUE );
557 /***********************************************************************
558 * GetMessage (USER.108)
560 BOOL GetMessage( SEGPTR msg, HWND hwnd, UINT first, UINT last )
562 MSG16 *lpmsg = (MSG16 *)PTR_SEG_TO_LIN(msg);
563 MSG_PeekMessage( lpmsg,
564 hwnd, first, last, PM_REMOVE, FALSE );
566 dprintf_msg(stddeb,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg->message,
568 HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)msg );
569 return (lpmsg->message != WM_QUIT);
573 /***********************************************************************
574 * PostMessage (USER.110)
576 BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
582 msg.message = message;
585 msg.time = GetTickCount();
590 if (DDE_PostMessage(&msg))
592 #endif /* CONFIG_IPC */
594 if (hwnd == HWND_BROADCAST16)
596 dprintf_msg(stddeb,"PostMessage // HWND_BROADCAST !\n");
597 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
599 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
601 dprintf_msg(stddeb,"BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
602 wndPtr->hwndSelf, message, wParam, lParam);
603 PostMessage( wndPtr->hwndSelf, message, wParam, lParam );
606 dprintf_msg(stddeb,"PostMessage // End of HWND_BROADCAST !\n");
610 wndPtr = WIN_FindWndPtr( hwnd );
611 if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE;
613 return QUEUE_AddMsg( wndPtr->hmemTaskQ, &msg, 0 );
616 /***********************************************************************
617 * PostAppMessage (USER.116)
619 BOOL PostAppMessage( HTASK hTask, WORD message, WORD wParam, LONG lParam )
623 if (GetTaskQueue(hTask) == 0) return FALSE;
625 msg.message = message;
628 msg.time = GetTickCount();
632 return QUEUE_AddMsg( GetTaskQueue(hTask), &msg, 0 );
636 /***********************************************************************
637 * SendMessage16 (USER.111)
639 LRESULT SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam)
649 } msgstruct = { lParam, wParam, msg, hwnd };
652 MSG16 DDE_msg = { hwnd, msg, wParam, lParam };
653 if (DDE_SendMessage(&DDE_msg)) return TRUE;
654 #endif /* CONFIG_IPC */
656 if (hwnd == HWND_BROADCAST16)
658 dprintf_msg(stddeb,"SendMessage // HWND_BROADCAST !\n");
659 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
661 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
663 dprintf_msg(stddeb,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
664 wndPtr->hwndSelf, msg, (DWORD)wParam, lParam);
665 SendMessage16( wndPtr->hwndSelf, msg, wParam, lParam );
668 dprintf_msg(stddeb,"SendMessage // End of HWND_BROADCAST !\n");
672 HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1,
673 (LPARAM)MAKE_SEGPTR(&msgstruct) );
674 hwnd = msgstruct.hWnd;
675 msg = msgstruct.wMsg;
676 wParam = msgstruct.wParam;
677 lParam = msgstruct.lParam;
679 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
681 fprintf( stderr, "SendMessage16: invalid hwnd %04x\n", hwnd );
684 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
685 return MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam );
687 SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
688 ret = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
689 hwnd, msg, wParam, lParam );
690 SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret );
695 /***********************************************************************
696 * SendMessage32A (USER32.453)
698 LRESULT SendMessage32A(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
703 if (hwnd == HWND_BROADCAST32)
705 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
707 /* FIXME: should use something like EnumWindows here */
708 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
709 SendMessage32A( wndPtr->hwndSelf, msg, wParam, lParam );
714 /* FIXME: call hooks */
716 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
718 fprintf( stderr, "SendMessage32A: invalid hwnd %08x\n", hwnd );
722 if (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_16)
724 /* Use SendMessage16 for now to get hooks right */
727 if (WINPROC_MapMsg32ATo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1)
729 ret = SendMessage16( hwnd, msg16, wParam16, lParam );
730 WINPROC_UnmapMsg32ATo16( msg16, wParam16, lParam );
734 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
736 fprintf( stderr, "SendMessage32A: intertask message not supported\n" );
740 SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
741 ret = CallWindowProc32A( (WNDPROC32)wndPtr->winproc,
742 hwnd, msg, wParam, lParam );
743 SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
748 /***********************************************************************
749 * SendMessage32W (USER32.458)
751 LRESULT SendMessage32W(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
756 if (hwnd == HWND_BROADCAST32)
758 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
760 /* FIXME: should use something like EnumWindows here */
761 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
762 SendMessage32W( wndPtr->hwndSelf, msg, wParam, lParam );
767 /* FIXME: call hooks */
769 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
771 fprintf( stderr, "SendMessage32W: invalid hwnd %08x\n", hwnd );
774 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
776 fprintf( stderr, "SendMessage32W: intertask message not supported\n" );
780 SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
781 ret = CallWindowProc32W( (WNDPROC32)wndPtr->winproc,
782 hwnd, msg, wParam, lParam );
783 SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
788 /***********************************************************************
789 * WaitMessage (USER.112)
791 void WaitMessage( void )
793 QUEUE_WaitBits( QS_ALLINPUT );
797 /***********************************************************************
798 * TranslateMessage (USER.113)
800 * This should call ToAscii but it is currently broken
803 #define ASCII_CHAR_HACK 0x0800
805 BOOL TranslateMessage( LPMSG16 msg )
807 UINT message = msg->message;
808 /* BYTE wparam[2]; */
810 if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
811 (message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
813 dprintf_msg(stddeb, "Translating key %04x, scancode %04x\n", msg->wParam,
814 HIWORD(msg->lParam) );
816 if( HIWORD(msg->lParam) & ASCII_CHAR_HACK )
818 /* if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
822 message += 2 - (message & 0x0001);
824 PostMessage( msg->hwnd, message, lastEventChar, msg->lParam );
833 /***********************************************************************
834 * DispatchMessage (USER.114)
836 LONG DispatchMessage( const MSG16* msg )
842 /* Process timer messages */
843 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
847 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
848 return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
849 msg->message, msg->wParam, GetTickCount() );
853 if (!msg->hwnd) return 0;
854 if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
855 if (!wndPtr->winproc) return 0;
856 painting = (msg->message == WM_PAINT);
857 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
858 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
860 SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message,
861 msg->wParam, msg->lParam );
862 retval = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
863 msg->hwnd, msg->message,
864 msg->wParam, msg->lParam );
865 SPY_ExitMessage( SPY_RESULT_OK16, msg->hwnd, msg->message, retval );
867 if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) &&
868 (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
870 fprintf(stderr, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
872 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
873 /* Validate the update region to avoid infinite WM_PAINT loop */
874 ValidateRect32( msg->hwnd, NULL );
880 /***********************************************************************
881 * RegisterWindowMessage16 (USER.118)
883 WORD RegisterWindowMessage16( SEGPTR str )
885 dprintf_msg(stddeb, "RegisterWindowMessage16: %08lx\n", (DWORD)str );
886 return GlobalAddAtom16( str );
890 /***********************************************************************
891 * RegisterWindowMessage32A (USER32.436)
893 WORD RegisterWindowMessage32A( LPCSTR str )
895 dprintf_msg(stddeb, "RegisterWindowMessage32A: %s\n", str );
896 return GlobalAddAtom32A( str );
900 /***********************************************************************
901 * RegisterWindowMessage32W (USER32.437)
903 WORD RegisterWindowMessage32W( LPCWSTR str )
905 dprintf_msg(stddeb, "RegisterWindowMessage32W: %p\n", str );
906 return GlobalAddAtom32W( str );
910 /***********************************************************************
911 * GetTickCount (USER.13) (KERNEL32.299)
913 DWORD GetTickCount(void)
916 gettimeofday( &t, NULL );
917 return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - MSG_WineStartTicks;
921 /***********************************************************************
922 * GetCurrentTime (USER.15)
924 * (effectively identical to GetTickCount)
926 DWORD GetCurrentTime(void)
928 return GetTickCount();
932 /***********************************************************************
933 * InSendMessage (USER.192)
939 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) )))
941 return (BOOL)queue->InSendMessageHandle;