Release 960611
[wine/multimedia.git] / windows / message.c
blob8ff4af2688e1329eae2768b79213094a20395335
1 /*
2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/time.h>
10 #include <sys/types.h>
12 #include "message.h"
13 #include "win.h"
14 #include "gdi.h"
15 #include "sysmetrics.h"
16 #include "hook.h"
17 #include "spy.h"
18 #include "winpos.h"
19 #include "atom.h"
20 #include "dde.h"
21 #include "queue.h"
22 #include "stddebug.h"
23 /* #define DEBUG_MSG */
24 #include "debug.h"
26 #define HWND_BROADCAST16 ((HWND16)0xffff)
27 #define HWND_BROADCAST32 ((HWND32)0xffffffff)
29 extern BYTE* KeyStateTable; /* event.c */
30 extern WPARAM lastEventChar; /* event.c */
32 extern BOOL TIMER_CheckTimer( LONG *next, MSG16 *msg,
33 HWND hwnd, BOOL remove ); /* timer.c */
35 DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
37 static WORD doubleClickSpeed = 452;
39 /***********************************************************************
40 * MSG_TranslateMouseMsg
42 * Translate an mouse hardware event into a real mouse message.
43 * Return value indicates whether the translated message must be passed
44 * to the user.
45 * Actions performed:
46 * - Find the window for this message.
47 * - Translate button-down messages in double-clicks.
48 * - Send the WM_NCHITTEST message to find where the cursor is.
49 * - Activate the window if needed.
50 * - Translate the message into a non-client message, or translate
51 * the coordinates to client coordinates.
52 * - Send the WM_SETCURSOR message.
54 static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
56 WND *pWnd;
57 BOOL eatMsg = FALSE;
58 INT16 hittest;
59 static DWORD lastClickTime = 0;
60 static WORD lastClickMsg = 0;
61 static POINT16 lastClickPos = { 0, 0 };
62 POINT16 pt = msg->pt;
63 MOUSEHOOKSTRUCT16 hook = { msg->pt, 0, HTCLIENT, 0 };
65 BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
66 (msg->message == WM_RBUTTONDOWN) ||
67 (msg->message == WM_MBUTTONDOWN));
69 /* Find the window */
71 if (GetCapture())
73 msg->hwnd = GetCapture();
74 ScreenToClient16( msg->hwnd, &pt );
75 msg->lParam = MAKELONG( pt.x, pt.y );
76 /* No need to further process the message */
77 hook.hwnd = msg->hwnd;
78 return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
79 msg->message, (LPARAM)MAKE_SEGPTR(&hook));
82 hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
83 msg->hwnd = pWnd->hwndSelf;
84 if ((hittest != HTERROR) && mouseClick)
86 HWND hwndTop = WIN_GetTopParent( msg->hwnd );
88 /* Send the WM_PARENTNOTIFY message */
90 WIN_SendParentNotify( msg->hwnd, msg->message, 0,
91 MAKELONG( msg->pt.x, msg->pt.y ) );
93 /* Activate the window if needed */
95 if (msg->hwnd != GetActiveWindow() && msg->hwnd != GetDesktopWindow())
97 LONG ret = SendMessage16( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
98 MAKELONG( hittest, msg->message ) );
100 if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
101 eatMsg = TRUE;
103 if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
104 && hwndTop != GetActiveWindow() )
105 WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE );
109 /* Send the WM_SETCURSOR message */
111 SendMessage16( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
112 MAKELONG( hittest, msg->message ));
113 if (eatMsg) return FALSE;
115 /* Check for double-click */
117 if (mouseClick)
119 BOOL dbl_click = FALSE;
121 if ((msg->message == lastClickMsg) &&
122 (msg->time - lastClickTime < doubleClickSpeed) &&
123 (abs(msg->pt.x - lastClickPos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
124 (abs(msg->pt.y - lastClickPos.y) < SYSMETRICS_CYDOUBLECLK/2))
125 dbl_click = TRUE;
127 if (dbl_click && (hittest == HTCLIENT))
129 /* Check whether window wants the double click message. */
130 dbl_click = (pWnd->class->style & CS_DBLCLKS) != 0;
133 if (dbl_click) switch(msg->message)
135 case WM_LBUTTONDOWN: msg->message = WM_LBUTTONDBLCLK; break;
136 case WM_RBUTTONDOWN: msg->message = WM_RBUTTONDBLCLK; break;
137 case WM_MBUTTONDOWN: msg->message = WM_MBUTTONDBLCLK; break;
140 if (remove)
142 lastClickTime = msg->time;
143 lastClickMsg = msg->message;
144 lastClickPos = msg->pt;
148 /* Build the translated message */
150 if (hittest == HTCLIENT)
151 ScreenToClient16( msg->hwnd, &pt );
152 else
154 msg->wParam = hittest;
155 msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
157 msg->lParam = MAKELONG( pt.x, pt.y );
159 hook.hwnd = msg->hwnd;
160 hook.wHitTestCode = hittest;
161 return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
162 msg->message, (LPARAM)MAKE_SEGPTR(&hook));
166 /***********************************************************************
167 * MSG_TranslateKeyboardMsg
169 * Translate an keyboard hardware event into a real message.
170 * Return value indicates whether the translated message must be passed
171 * to the user.
173 static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
175 /* Should check Ctrl-Esc and PrintScreen here */
177 msg->hwnd = GetFocus();
178 if (!msg->hwnd)
180 /* Send the message to the active window instead, */
181 /* translating messages to their WM_SYS equivalent */
183 msg->hwnd = GetActiveWindow();
185 if( msg->message < WM_SYSKEYDOWN )
186 msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
188 return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
189 msg->wParam, msg->lParam );
193 /***********************************************************************
194 * MSG_PeekHardwareMsg
196 * Peek for a hardware message matching the hwnd and message filters.
198 static BOOL MSG_PeekHardwareMsg( MSG16 *msg, HWND hwnd, WORD first, WORD last,
199 BOOL remove )
201 MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
202 int i, pos = sysMsgQueue->nextMessage;
204 /* If the queue is empty, attempt to fill it */
205 if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( 0 );
207 for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
209 if (pos >= sysMsgQueue->queueSize) pos = 0;
210 *msg = sysMsgQueue->messages[pos].msg;
212 /* Translate message */
214 if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
216 if (!MSG_TranslateMouseMsg( msg, remove )) continue;
218 else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
220 if (!MSG_TranslateKeyboardMsg( msg, remove )) continue;
222 else /* Non-standard hardware event */
224 HARDWAREHOOKSTRUCT16 hook = { msg->hwnd, msg->message,
225 msg->wParam, msg->lParam };
226 if (HOOK_CallHooks( WH_HARDWARE, remove ? HC_ACTION : HC_NOREMOVE,
227 0, (LPARAM)MAKE_SEGPTR(&hook) )) continue;
230 /* Check message against filters */
232 if (hwnd && (msg->hwnd != hwnd)) continue;
233 if ((first || last) &&
234 ((msg->message < first) || (msg->message > last))) continue;
235 if ((msg->hwnd != GetDesktopWindow()) &&
236 (GetWindowTask(msg->hwnd) != GetCurrentTask()))
237 continue; /* Not for this task */
238 if (remove)
240 MSG16 tmpMsg = *msg; /* FIXME */
241 HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION,
242 0, (LPARAM)MAKE_SEGPTR(&tmpMsg) );
243 QUEUE_RemoveMsg( sysMsgQueue, pos );
245 return TRUE;
247 return FALSE;
251 /**********************************************************************
252 * SetDoubleClickTime (USER.20)
254 void SetDoubleClickTime( WORD interval )
256 doubleClickSpeed = interval ? interval : 500;
260 /**********************************************************************
261 * GetDoubleClickTime (USER.21)
263 WORD GetDoubleClickTime()
265 return doubleClickSpeed;
269 /***********************************************************************
270 * MSG_GetHardwareMessage
272 * Like GetMessage(), but only return mouse and keyboard events.
273 * Used internally for window moving and resizing. Mouse messages
274 * are not translated.
275 * Warning: msg->hwnd is always 0.
277 BOOL MSG_GetHardwareMessage( LPMSG16 msg )
279 #if 0
280 int pos;
281 XEvent event;
282 MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
284 while(1)
286 if ((pos = QUEUE_FindMsg( sysMsgQueue, 0, 0, 0 )) != -1)
288 *msg = sysMsgQueue->messages[pos].msg;
289 QUEUE_RemoveMsg( sysMsgQueue, pos );
290 break;
292 XNextEvent( display, &event );
293 EVENT_ProcessEvent( &event );
295 #endif
296 MSG_PeekMessage( msg, 0, WM_KEYFIRST, WM_MOUSELAST, PM_REMOVE, 0 );
297 return TRUE;
301 /***********************************************************************
302 * MSG_SendMessage
304 * Implementation of an inter-task SendMessage.
306 LRESULT MSG_SendMessage( HQUEUE hDestQueue, HWND hwnd, UINT msg,
307 WPARAM wParam, LPARAM lParam )
309 MESSAGEQUEUE *queue, *destQ;
311 if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return 0;
312 if (!(destQ = (MESSAGEQUEUE*)GlobalLock16( hDestQueue ))) return 0;
314 if (IsTaskLocked())
316 fprintf( stderr, "SendMessage: task is locked\n" );
317 return 0;
320 if (queue->hWnd)
322 fprintf( stderr, "Nested SendMessage() not supported\n" );
323 return 0;
325 queue->hWnd = hwnd;
326 queue->msg = msg;
327 queue->wParam = wParam;
328 queue->lParam = lParam;
329 queue->hPrevSendingTask = destQ->hSendingTask;
330 destQ->hSendingTask = GetTaskQueue(0);
331 QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
333 /* Wait for the result */
335 printf( "SendMessage %04x to %04x\n", msg, hDestQueue );
337 if (!(queue->wakeBits & QS_SMRESULT))
339 DirectedYield( hDestQueue );
340 QUEUE_WaitBits( QS_SMRESULT );
342 printf( "SendMessage %04x to %04x: got %08x\n",
343 msg, hDestQueue, queue->SendMessageReturn );
344 queue->wakeBits &= ~QS_SMRESULT;
345 return queue->SendMessageReturn;
349 /***********************************************************************
350 * ReplyMessage (USER.115)
352 void ReplyMessage( LRESULT result )
354 MESSAGEQUEUE *senderQ;
355 MESSAGEQUEUE *queue;
357 printf( "ReplyMessage\n " );
358 if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return;
359 if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
360 return;
361 for (;;)
363 if (queue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( queue );
364 else if (senderQ->wakeBits & QS_SMRESULT) Yield();
365 else break;
367 printf( "ReplyMessage: res = %08x\n", result );
368 senderQ->SendMessageReturn = result;
369 queue->InSendMessageHandle = 0;
370 QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
371 DirectedYield( queue->hSendingTask );
375 /***********************************************************************
376 * MSG_PeekMessage
378 static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last,
379 WORD flags, BOOL peek )
381 int pos, mask;
382 MESSAGEQUEUE *msgQueue;
383 HQUEUE hQueue;
384 LONG nextExp; /* Next timer expiration time */
386 #ifdef CONFIG_IPC
387 DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/
388 DDE_GetRemoteMessage();
389 #endif /* CONFIG_IPC */
391 mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
392 if (first || last)
394 if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
395 if ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) mask |= QS_MOUSE;
396 if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
397 if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
398 if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
400 else mask |= QS_MOUSE | QS_KEY | QS_TIMER | QS_PAINT;
402 if (IsTaskLocked()) flags |= PM_NOYIELD;
404 while(1)
406 hQueue = GetTaskQueue(0);
407 msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
408 if (!msgQueue) return FALSE;
409 msgQueue->changeBits = 0;
411 /* First handle a message put by SendMessage() */
413 if (msgQueue->wakeBits & QS_SENDMESSAGE)
414 QUEUE_ReceiveMessage( msgQueue );
416 /* Now find a normal message */
418 if (((msgQueue->wakeBits & mask) & QS_POSTMESSAGE) &&
419 ((pos = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != -1))
421 QMSG *qmsg = &msgQueue->messages[pos];
422 *msg = qmsg->msg;
423 msgQueue->GetMessageTimeVal = msg->time;
424 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
425 msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
427 if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, pos );
428 break;
431 /* Now find a hardware event */
433 if (((msgQueue->wakeBits & mask) & (QS_MOUSE | QS_KEY)) &&
434 MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
436 /* Got one */
437 msgQueue->GetMessageTimeVal = msg->time;
438 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
439 msgQueue->GetMessageExtraInfoVal = 0; /* Always 0 for now */
440 break;
443 /* Now handle a WM_QUIT message */
445 if (msgQueue->wPostQMsg)
447 msg->hwnd = hwnd;
448 msg->message = WM_QUIT;
449 msg->wParam = msgQueue->wExitCode;
450 msg->lParam = 0;
451 break;
454 /* Check again for SendMessage */
456 if (msgQueue->wakeBits & QS_SENDMESSAGE)
457 QUEUE_ReceiveMessage( msgQueue );
459 /* Now find a WM_PAINT message */
461 if ((msgQueue->wakeBits & mask) & QS_PAINT)
463 msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
464 msg->message = WM_PAINT;
465 msg->wParam = 0;
466 msg->lParam = 0;
467 if( msg->hwnd &&
468 (!hwnd || msg->hwnd == hwnd || IsChild(hwnd,msg->hwnd)) )
470 WND* wndPtr = WIN_FindWndPtr(msg->hwnd);
472 /* FIXME: WM_PAINTICON should be sent sometimes */
474 if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
476 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
477 QUEUE_DecPaintCount( hQueue );
479 break;
483 /* Check for timer messages, but yield first */
485 if (!(flags & PM_NOYIELD))
487 UserYield();
488 if (msgQueue->wakeBits & QS_SENDMESSAGE)
489 QUEUE_ReceiveMessage( msgQueue );
491 if ((msgQueue->wakeBits & mask) & QS_TIMER)
493 if (TIMER_CheckTimer( &nextExp, msg, hwnd, flags & PM_REMOVE ))
494 break; /* Got a timer msg */
496 else nextExp = -1; /* No timeout needed */
498 if (peek)
500 if (!(flags & PM_NOYIELD)) UserYield();
501 return FALSE;
503 msgQueue->wakeMask = mask;
504 QUEUE_WaitBits( mask );
507 /* We got a message */
508 if (peek) return TRUE;
509 else return (msg->message != WM_QUIT);
513 /***********************************************************************
514 * MSG_InternalGetMessage
516 * GetMessage() function for internal use. Behave like GetMessage(),
517 * but also call message filters and optionally send WM_ENTERIDLE messages.
518 * 'hwnd' must be the handle of the dialog or menu window.
519 * 'code' is the message filter value (MSGF_??? codes).
521 BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner, short code,
522 WORD flags, BOOL sendIdle )
524 for (;;)
526 if (sendIdle)
528 if (!MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
529 0, 0, 0, flags, TRUE ))
531 /* No message present -> send ENTERIDLE and wait */
532 if (IsWindow(hwndOwner))
533 SendMessage16( hwndOwner, WM_ENTERIDLE,
534 code, (LPARAM)hwnd );
535 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
536 0, 0, 0, flags, FALSE );
539 else /* Always wait for a message */
540 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
541 0, 0, 0, flags, FALSE );
543 if (!CallMsgFilter( msg, code ))
544 return (((MSG16 *)PTR_SEG_TO_LIN(msg))->message != WM_QUIT);
546 /* Message filtered -> remove it from the queue */
547 /* if it's still there. */
548 if (!(flags & PM_REMOVE))
549 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
550 0, 0, 0, PM_REMOVE, TRUE );
555 /***********************************************************************
556 * PeekMessage16 (USER.109)
558 BOOL16 PeekMessage16( LPMSG16 msg, HWND16 hwnd, UINT16 first,
559 UINT16 last, UINT16 flags )
561 return MSG_PeekMessage( msg, hwnd, first, last, flags, TRUE );
565 /***********************************************************************
566 * GetMessage (USER.108)
568 BOOL GetMessage( SEGPTR msg, HWND hwnd, UINT first, UINT last )
570 MSG16 *lpmsg = (MSG16 *)PTR_SEG_TO_LIN(msg);
571 MSG_PeekMessage( lpmsg,
572 hwnd, first, last, PM_REMOVE, FALSE );
574 dprintf_msg(stddeb,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg->message,
575 hwnd, first, last );
576 HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)msg );
577 return (lpmsg->message != WM_QUIT);
581 /***********************************************************************
582 * PostMessage (USER.110)
584 BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
586 MSG16 msg;
587 WND *wndPtr;
589 msg.hwnd = hwnd;
590 msg.message = message;
591 msg.wParam = wParam;
592 msg.lParam = lParam;
593 msg.time = GetTickCount();
594 msg.pt.x = 0;
595 msg.pt.y = 0;
597 #ifdef CONFIG_IPC
598 if (DDE_PostMessage(&msg))
599 return TRUE;
600 #endif /* CONFIG_IPC */
602 if (hwnd == HWND_BROADCAST16)
604 dprintf_msg(stddeb,"PostMessage // HWND_BROADCAST !\n");
605 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
607 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
609 dprintf_msg(stddeb,"BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
610 wndPtr->hwndSelf, message, wParam, lParam);
611 PostMessage( wndPtr->hwndSelf, message, wParam, lParam );
614 dprintf_msg(stddeb,"PostMessage // End of HWND_BROADCAST !\n");
615 return TRUE;
618 wndPtr = WIN_FindWndPtr( hwnd );
619 if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE;
621 return QUEUE_AddMsg( wndPtr->hmemTaskQ, &msg, 0 );
624 /***********************************************************************
625 * PostAppMessage (USER.116)
627 BOOL PostAppMessage( HTASK hTask, WORD message, WORD wParam, LONG lParam )
629 MSG16 msg;
631 if (GetTaskQueue(hTask) == 0) return FALSE;
632 msg.hwnd = 0;
633 msg.message = message;
634 msg.wParam = wParam;
635 msg.lParam = lParam;
636 msg.time = GetTickCount();
637 msg.pt.x = 0;
638 msg.pt.y = 0;
640 return QUEUE_AddMsg( GetTaskQueue(hTask), &msg, 0 );
644 /***********************************************************************
645 * SendMessage16 (USER.111)
647 LRESULT SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam)
649 WND * wndPtr;
650 LRESULT ret;
651 struct
653 LPARAM lParam;
654 WPARAM16 wParam;
655 UINT16 wMsg;
656 HWND16 hWnd;
657 } msgstruct = { lParam, wParam, msg, hwnd };
659 #ifdef CONFIG_IPC
660 MSG DDE_msg = { hwnd, msg, wParam, lParam };
661 if (DDE_SendMessage(&DDE_msg)) return TRUE;
662 #endif /* CONFIG_IPC */
664 if (hwnd == HWND_BROADCAST16)
666 dprintf_msg(stddeb,"SendMessage // HWND_BROADCAST !\n");
667 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
669 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
671 dprintf_msg(stddeb,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
672 wndPtr->hwndSelf, msg, (DWORD)wParam, lParam);
673 SendMessage16( wndPtr->hwndSelf, msg, wParam, lParam );
676 dprintf_msg(stddeb,"SendMessage // End of HWND_BROADCAST !\n");
677 return TRUE;
681 HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1,
682 (LPARAM)MAKE_SEGPTR(&msgstruct) );
683 hwnd = msgstruct.hWnd;
684 msg = msgstruct.wMsg;
685 wParam = msgstruct.wParam;
686 lParam = msgstruct.lParam;
688 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
690 fprintf( stderr, "SendMessage16: invalid hwnd %04x\n", hwnd );
691 return 0;
693 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
695 #if 0
696 fprintf( stderr, "SendMessage16: intertask message not supported\n" );
697 return 0;
698 #endif
699 return MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam );
702 SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
703 ret = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
704 hwnd, msg, wParam, lParam );
705 SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret );
706 return ret;
710 /***********************************************************************
711 * SendMessage32A (USER32.453)
713 LRESULT SendMessage32A(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
715 WND * wndPtr;
716 LRESULT ret;
718 if (hwnd == HWND_BROADCAST32)
720 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
722 /* FIXME: should use something like EnumWindows here */
723 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
724 SendMessage32A( wndPtr->hwndSelf, msg, wParam, lParam );
726 return TRUE;
729 /* FIXME: call hooks */
731 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
733 fprintf( stderr, "SendMessage32A: invalid hwnd %08x\n", hwnd );
734 return 0;
736 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
738 fprintf( stderr, "SendMessage32A: intertask message not supported\n" );
739 return 0;
742 SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
743 ret = CallWindowProc32A( (WNDPROC32)wndPtr->winproc,
744 hwnd, msg, wParam, lParam );
745 SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
746 return ret;
750 /***********************************************************************
751 * SendMessage32W (USER32.458)
753 LRESULT SendMessage32W(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
755 WND * wndPtr;
756 LRESULT ret;
758 if (hwnd == HWND_BROADCAST32)
760 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
762 /* FIXME: should use something like EnumWindows here */
763 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
764 SendMessage32W( wndPtr->hwndSelf, msg, wParam, lParam );
766 return TRUE;
769 /* FIXME: call hooks */
771 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
773 fprintf( stderr, "SendMessage32W: invalid hwnd %08x\n", hwnd );
774 return 0;
776 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
778 fprintf( stderr, "SendMessage32W: intertask message not supported\n" );
779 return 0;
782 SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
783 ret = CallWindowProc32W( (WNDPROC32)wndPtr->winproc,
784 hwnd, msg, wParam, lParam );
785 SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
786 return ret;
790 /***********************************************************************
791 * WaitMessage (USER.112)
793 void WaitMessage( void )
795 MSG16 msg;
796 MESSAGEQUEUE *queue;
797 LONG nextExp = -1; /* Next timer expiration time */
799 #ifdef CONFIG_IPC
800 DDE_GetRemoteMessage();
801 #endif /* CONFIG_IPC */
803 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
804 if ((queue->wPostQMsg) ||
805 (queue->wakeBits & (QS_SENDMESSAGE | QS_PAINT)) ||
806 (queue->msgCount) || (QUEUE_GetSysQueue()->msgCount) )
807 return;
808 if ((queue->wakeBits & QS_TIMER) &&
809 TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
810 return;
811 /* FIXME: (dde) must check DDE & X-events simultaneously */
812 EVENT_WaitXEvent( nextExp );
816 /***********************************************************************
817 * TranslateMessage (USER.113)
819 * This should call ToAscii but it is currently broken
822 #define ASCII_CHAR_HACK 0x0800
824 BOOL TranslateMessage( LPMSG16 msg )
826 UINT message = msg->message;
827 /* BYTE wparam[2]; */
829 if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
830 (message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
832 dprintf_msg(stddeb, "Translating key %04x, scancode %04x\n", msg->wParam,
833 HIWORD(msg->lParam) );
835 if( HIWORD(msg->lParam) & ASCII_CHAR_HACK )
837 /* if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
838 wparam, 0 ) )
841 message += 2 - (message & 0x0001);
843 PostMessage( msg->hwnd, message, lastEventChar, msg->lParam );
845 return TRUE;
848 return FALSE;
852 /***********************************************************************
853 * DispatchMessage (USER.114)
855 LONG DispatchMessage( const MSG16* msg )
857 WND * wndPtr;
858 LONG retval;
859 int painting;
861 /* Process timer messages */
862 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
864 if (msg->lParam)
866 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
867 return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
868 msg->message, msg->wParam, GetTickCount() );
872 if (!msg->hwnd) return 0;
873 if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
874 if (!wndPtr->winproc) return 0;
875 painting = (msg->message == WM_PAINT);
876 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
877 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
879 SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message,
880 msg->wParam, msg->lParam );
881 retval = CallWindowProc16( wndPtr->winproc, msg->hwnd, msg->message,
882 msg->wParam, msg->lParam );
883 SPY_ExitMessage( SPY_RESULT_OK16, msg->hwnd, msg->message, retval );
885 if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) &&
886 (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
888 fprintf(stderr, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
889 msg->hwnd);
890 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
891 /* Validate the update region to avoid infinite WM_PAINT loop */
892 ValidateRect32( msg->hwnd, NULL );
894 return retval;
898 /***********************************************************************
899 * RegisterWindowMessage16 (USER.118)
901 WORD RegisterWindowMessage16( SEGPTR str )
903 dprintf_msg(stddeb, "RegisterWindowMessage16: %08lx\n", (DWORD)str );
904 return GlobalAddAtom16( str );
908 /***********************************************************************
909 * RegisterWindowMessage32A (USER32.436)
911 WORD RegisterWindowMessage32A( LPCSTR str )
913 dprintf_msg(stddeb, "RegisterWindowMessage32A: %s\n", str );
914 return GlobalAddAtom32A( str );
918 /***********************************************************************
919 * RegisterWindowMessage32W (USER32.437)
921 WORD RegisterWindowMessage32W( LPCWSTR str )
923 dprintf_msg(stddeb, "RegisterWindowMessage32W: %p\n", str );
924 return GlobalAddAtom32W( str );
928 /***********************************************************************
929 * GetTickCount (USER.13) (KERNEL32.299)
931 DWORD GetTickCount(void)
933 struct timeval t;
934 gettimeofday( &t, NULL );
935 return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - MSG_WineStartTicks;
939 /***********************************************************************
940 * GetCurrentTime (USER.15)
942 * (effectively identical to GetTickCount)
944 DWORD GetCurrentTime(void)
946 return GetTickCount();
950 /***********************************************************************
951 * InSendMessage (USER.192)
953 BOOL InSendMessage()
955 MESSAGEQUEUE *queue;
957 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) )))
958 return 0;
959 return (BOOL)queue->InSendMessageHandle;