Release 960623
[wine.git] / windows / message.c
blobc777683f1439b965d74bd48cb1f0698a40ce9fe8
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 DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
34 static WORD doubleClickSpeed = 452;
36 /***********************************************************************
37 * MSG_TranslateMouseMsg
39 * Translate an mouse hardware event into a real mouse message.
40 * Return value indicates whether the translated message must be passed
41 * to the user.
42 * Actions performed:
43 * - Find the window for this message.
44 * - Translate button-down messages in double-clicks.
45 * - Send the WM_NCHITTEST message to find where the cursor is.
46 * - Activate the window if needed.
47 * - Translate the message into a non-client message, or translate
48 * the coordinates to client coordinates.
49 * - Send the WM_SETCURSOR message.
51 static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
53 WND *pWnd;
54 BOOL eatMsg = FALSE;
55 INT16 hittest;
56 static DWORD lastClickTime = 0;
57 static WORD lastClickMsg = 0;
58 static POINT16 lastClickPos = { 0, 0 };
59 POINT16 pt = msg->pt;
60 MOUSEHOOKSTRUCT16 hook = { msg->pt, 0, HTCLIENT, 0 };
62 BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
63 (msg->message == WM_RBUTTONDOWN) ||
64 (msg->message == WM_MBUTTONDOWN));
66 /* Find the window */
68 if ((msg->hwnd = GetCapture()) != 0)
70 ScreenToClient16( msg->hwnd, &pt );
71 msg->lParam = MAKELONG( pt.x, pt.y );
72 /* No need to further process the message */
73 hook.hwnd = msg->hwnd;
74 return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
75 msg->message, (LPARAM)MAKE_SEGPTR(&hook));
78 hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
79 if (pWnd->hmemTaskQ != GetTaskQueue(0))
81 /* Not for the current task */
82 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
83 if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
84 /* Wake up the other task */
85 queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
86 if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
87 return FALSE;
89 msg->hwnd = pWnd->hwndSelf;
90 if ((hittest != HTERROR) && mouseClick)
92 HWND hwndTop = WIN_GetTopParent( msg->hwnd );
94 /* Send the WM_PARENTNOTIFY message */
96 WIN_SendParentNotify( msg->hwnd, msg->message, 0,
97 MAKELONG( msg->pt.x, msg->pt.y ) );
99 /* Activate the window if needed */
101 if (msg->hwnd != GetActiveWindow() && msg->hwnd != GetDesktopWindow())
103 LONG ret = SendMessage16( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
104 MAKELONG( hittest, msg->message ) );
106 if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
107 eatMsg = TRUE;
109 if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
110 && hwndTop != GetActiveWindow() )
111 WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE );
115 /* Send the WM_SETCURSOR message */
117 SendMessage16( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
118 MAKELONG( hittest, msg->message ));
119 if (eatMsg) return FALSE;
121 /* Check for double-click */
123 if (mouseClick)
125 BOOL dbl_click = FALSE;
127 if ((msg->message == lastClickMsg) &&
128 (msg->time - lastClickTime < doubleClickSpeed) &&
129 (abs(msg->pt.x - lastClickPos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
130 (abs(msg->pt.y - lastClickPos.y) < SYSMETRICS_CYDOUBLECLK/2))
131 dbl_click = TRUE;
133 if (dbl_click && (hittest == HTCLIENT))
135 /* Check whether window wants the double click message. */
136 dbl_click = (pWnd->class->style & CS_DBLCLKS) != 0;
139 if (dbl_click) switch(msg->message)
141 case WM_LBUTTONDOWN: msg->message = WM_LBUTTONDBLCLK; break;
142 case WM_RBUTTONDOWN: msg->message = WM_RBUTTONDBLCLK; break;
143 case WM_MBUTTONDOWN: msg->message = WM_MBUTTONDBLCLK; break;
146 if (remove)
148 lastClickTime = msg->time;
149 lastClickMsg = msg->message;
150 lastClickPos = msg->pt;
154 /* Build the translated message */
156 if (hittest == HTCLIENT)
157 ScreenToClient16( msg->hwnd, &pt );
158 else
160 msg->wParam = hittest;
161 msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
163 msg->lParam = MAKELONG( pt.x, pt.y );
165 hook.hwnd = msg->hwnd;
166 hook.wHitTestCode = hittest;
167 return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
168 msg->message, (LPARAM)MAKE_SEGPTR(&hook));
172 /***********************************************************************
173 * MSG_TranslateKeyboardMsg
175 * Translate an keyboard hardware event into a real message.
176 * Return value indicates whether the translated message must be passed
177 * to the user.
179 static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
181 WND *pWnd;
183 /* Should check Ctrl-Esc and PrintScreen here */
185 msg->hwnd = GetFocus();
186 if (!msg->hwnd)
188 /* Send the message to the active window instead, */
189 /* translating messages to their WM_SYS equivalent */
191 msg->hwnd = GetActiveWindow();
193 if( msg->message < WM_SYSKEYDOWN )
194 msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
196 pWnd = WIN_FindWndPtr( msg->hwnd );
197 if (pWnd && (pWnd->hmemTaskQ != GetTaskQueue(0)))
199 /* Not for the current task */
200 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
201 if (queue) QUEUE_ClearWakeBit( queue, QS_KEY );
202 /* Wake up the other task */
203 queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
204 if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
205 return FALSE;
207 return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
208 msg->wParam, msg->lParam );
212 /***********************************************************************
213 * MSG_PeekHardwareMsg
215 * Peek for a hardware message matching the hwnd and message filters.
217 static BOOL MSG_PeekHardwareMsg( MSG16 *msg, HWND hwnd, WORD first, WORD last,
218 BOOL remove )
220 MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
221 int i, pos = sysMsgQueue->nextMessage;
223 /* If the queue is empty, attempt to fill it */
224 if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( FALSE );
226 for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
228 if (pos >= sysMsgQueue->queueSize) pos = 0;
229 *msg = sysMsgQueue->messages[pos].msg;
231 /* Translate message */
233 if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
235 if (!MSG_TranslateMouseMsg( msg, remove )) continue;
237 else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
239 if (!MSG_TranslateKeyboardMsg( msg, remove )) continue;
241 else /* Non-standard hardware event */
243 HARDWAREHOOKSTRUCT16 hook = { msg->hwnd, msg->message,
244 msg->wParam, msg->lParam };
245 if (HOOK_CallHooks( WH_HARDWARE, remove ? HC_ACTION : HC_NOREMOVE,
246 0, (LPARAM)MAKE_SEGPTR(&hook) )) continue;
249 /* Check message against filters */
251 if (hwnd && (msg->hwnd != hwnd)) continue;
252 if ((first || last) &&
253 ((msg->message < first) || (msg->message > last))) continue;
254 if ((msg->hwnd != GetDesktopWindow()) &&
255 (GetWindowTask(msg->hwnd) != GetCurrentTask()))
256 continue; /* Not for this task */
257 if (remove)
259 MSG16 tmpMsg = *msg; /* FIXME */
260 HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION,
261 0, (LPARAM)MAKE_SEGPTR(&tmpMsg) );
262 QUEUE_RemoveMsg( sysMsgQueue, pos );
264 return TRUE;
266 return FALSE;
270 /**********************************************************************
271 * SetDoubleClickTime (USER.20)
273 void SetDoubleClickTime( WORD interval )
275 doubleClickSpeed = interval ? interval : 500;
279 /**********************************************************************
280 * GetDoubleClickTime (USER.21)
282 WORD GetDoubleClickTime()
284 return doubleClickSpeed;
288 /***********************************************************************
289 * MSG_SendMessage
291 * Implementation of an inter-task SendMessage.
293 LRESULT MSG_SendMessage( HQUEUE hDestQueue, HWND hwnd, UINT msg,
294 WPARAM wParam, LPARAM lParam )
296 MESSAGEQUEUE *queue, *destQ;
298 if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return 0;
299 if (!(destQ = (MESSAGEQUEUE*)GlobalLock16( hDestQueue ))) return 0;
301 if (IsTaskLocked())
303 fprintf( stderr, "SendMessage: task is locked\n" );
304 return 0;
307 if (queue->hWnd)
309 fprintf( stderr, "Nested SendMessage() not supported\n" );
310 return 0;
312 queue->hWnd = hwnd;
313 queue->msg = msg;
314 queue->wParam = wParam;
315 queue->lParam = lParam;
316 queue->hPrevSendingTask = destQ->hSendingTask;
317 destQ->hSendingTask = GetTaskQueue(0);
318 QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
320 /* Wait for the result */
322 printf( "SendMessage %04x to %04x\n", msg, hDestQueue );
324 if (!(queue->wakeBits & QS_SMRESULT))
326 DirectedYield( hDestQueue );
327 QUEUE_WaitBits( QS_SMRESULT );
329 printf( "SendMessage %04x to %04x: got %08x\n",
330 msg, hDestQueue, queue->SendMessageReturn );
331 queue->wakeBits &= ~QS_SMRESULT;
332 return queue->SendMessageReturn;
336 /***********************************************************************
337 * ReplyMessage (USER.115)
339 void ReplyMessage( LRESULT result )
341 MESSAGEQUEUE *senderQ;
342 MESSAGEQUEUE *queue;
344 printf( "ReplyMessage\n " );
345 if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return;
346 if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
347 return;
348 for (;;)
350 if (queue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( queue );
351 else if (senderQ->wakeBits & QS_SMRESULT) Yield();
352 else break;
354 printf( "ReplyMessage: res = %08x\n", result );
355 senderQ->SendMessageReturn = result;
356 queue->InSendMessageHandle = 0;
357 QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
358 DirectedYield( queue->hSendingTask );
362 /***********************************************************************
363 * MSG_PeekMessage
365 static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last,
366 WORD flags, BOOL peek )
368 int pos, mask;
369 MESSAGEQUEUE *msgQueue;
370 HQUEUE hQueue;
372 #ifdef CONFIG_IPC
373 DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/
374 DDE_GetRemoteMessage();
375 #endif /* CONFIG_IPC */
377 mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
378 if (first || last)
380 if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
381 if ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) mask |= QS_MOUSE;
382 if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
383 if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
384 if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
386 else mask |= QS_MOUSE | QS_KEY | QS_TIMER | QS_PAINT;
388 if (IsTaskLocked()) flags |= PM_NOYIELD;
390 while(1)
392 hQueue = GetTaskQueue(0);
393 msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
394 if (!msgQueue) return FALSE;
395 msgQueue->changeBits = 0;
397 /* First handle a message put by SendMessage() */
399 if (msgQueue->wakeBits & QS_SENDMESSAGE)
400 QUEUE_ReceiveMessage( msgQueue );
402 /* Now find a normal message */
404 if (((msgQueue->wakeBits & mask) & QS_POSTMESSAGE) &&
405 ((pos = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != -1))
407 QMSG *qmsg = &msgQueue->messages[pos];
408 *msg = qmsg->msg;
409 msgQueue->GetMessageTimeVal = msg->time;
410 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
411 msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
413 if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, pos );
414 break;
417 /* Now find a hardware event */
419 if (((msgQueue->wakeBits & mask) & (QS_MOUSE | QS_KEY)) &&
420 MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
422 /* Got one */
423 msgQueue->GetMessageTimeVal = msg->time;
424 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
425 msgQueue->GetMessageExtraInfoVal = 0; /* Always 0 for now */
426 break;
429 /* Now handle a WM_QUIT message */
431 if (msgQueue->wPostQMsg)
433 msg->hwnd = hwnd;
434 msg->message = WM_QUIT;
435 msg->wParam = msgQueue->wExitCode;
436 msg->lParam = 0;
437 break;
440 /* Check again for SendMessage */
442 if (msgQueue->wakeBits & QS_SENDMESSAGE)
443 QUEUE_ReceiveMessage( msgQueue );
445 /* Now find a WM_PAINT message */
447 if ((msgQueue->wakeBits & mask) & QS_PAINT)
449 msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
450 msg->message = WM_PAINT;
451 msg->wParam = 0;
452 msg->lParam = 0;
453 if( msg->hwnd &&
454 (!hwnd || msg->hwnd == hwnd || IsChild(hwnd,msg->hwnd)) )
456 WND* wndPtr = WIN_FindWndPtr(msg->hwnd);
458 /* FIXME: WM_PAINTICON should be sent sometimes */
460 if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
462 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
463 QUEUE_DecPaintCount( hQueue );
465 break;
469 /* Check for timer messages, but yield first */
471 if (!(flags & PM_NOYIELD))
473 UserYield();
474 if (msgQueue->wakeBits & QS_SENDMESSAGE)
475 QUEUE_ReceiveMessage( msgQueue );
477 if ((msgQueue->wakeBits & mask) & QS_TIMER)
479 if (TIMER_GetTimerMsg(msg, hwnd, hQueue, flags & PM_REMOVE)) break;
482 if (peek)
484 if (!(flags & PM_NOYIELD)) UserYield();
485 return FALSE;
487 msgQueue->wakeMask = mask;
488 QUEUE_WaitBits( mask );
491 /* We got a message */
492 if (peek) return TRUE;
493 else return (msg->message != WM_QUIT);
497 /***********************************************************************
498 * MSG_InternalGetMessage
500 * GetMessage() function for internal use. Behave like GetMessage(),
501 * but also call message filters and optionally send WM_ENTERIDLE messages.
502 * 'hwnd' must be the handle of the dialog or menu window.
503 * 'code' is the message filter value (MSGF_??? codes).
505 BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner, short code,
506 WORD flags, BOOL sendIdle )
508 for (;;)
510 if (sendIdle)
512 if (!MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
513 0, 0, 0, flags, TRUE ))
515 /* No message present -> send ENTERIDLE and wait */
516 if (IsWindow(hwndOwner))
517 SendMessage16( hwndOwner, WM_ENTERIDLE,
518 code, (LPARAM)hwnd );
519 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
520 0, 0, 0, flags, FALSE );
523 else /* Always wait for a message */
524 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
525 0, 0, 0, flags, FALSE );
527 if (!CallMsgFilter( msg, code ))
528 return (((MSG16 *)PTR_SEG_TO_LIN(msg))->message != WM_QUIT);
530 /* Message filtered -> remove it from the queue */
531 /* if it's still there. */
532 if (!(flags & PM_REMOVE))
533 MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
534 0, 0, 0, PM_REMOVE, TRUE );
539 /***********************************************************************
540 * PeekMessage16 (USER.109)
542 BOOL16 PeekMessage16( LPMSG16 msg, HWND16 hwnd, UINT16 first,
543 UINT16 last, UINT16 flags )
545 return MSG_PeekMessage( msg, hwnd, first, last, flags, TRUE );
549 /***********************************************************************
550 * GetMessage (USER.108)
552 BOOL GetMessage( SEGPTR msg, HWND hwnd, UINT first, UINT last )
554 MSG16 *lpmsg = (MSG16 *)PTR_SEG_TO_LIN(msg);
555 MSG_PeekMessage( lpmsg,
556 hwnd, first, last, PM_REMOVE, FALSE );
558 dprintf_msg(stddeb,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg->message,
559 hwnd, first, last );
560 HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)msg );
561 return (lpmsg->message != WM_QUIT);
565 /***********************************************************************
566 * PostMessage (USER.110)
568 BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
570 MSG16 msg;
571 WND *wndPtr;
573 msg.hwnd = hwnd;
574 msg.message = message;
575 msg.wParam = wParam;
576 msg.lParam = lParam;
577 msg.time = GetTickCount();
578 msg.pt.x = 0;
579 msg.pt.y = 0;
581 #ifdef CONFIG_IPC
582 if (DDE_PostMessage(&msg))
583 return TRUE;
584 #endif /* CONFIG_IPC */
586 if (hwnd == HWND_BROADCAST16)
588 dprintf_msg(stddeb,"PostMessage // HWND_BROADCAST !\n");
589 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
591 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
593 dprintf_msg(stddeb,"BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
594 wndPtr->hwndSelf, message, wParam, lParam);
595 PostMessage( wndPtr->hwndSelf, message, wParam, lParam );
598 dprintf_msg(stddeb,"PostMessage // End of HWND_BROADCAST !\n");
599 return TRUE;
602 wndPtr = WIN_FindWndPtr( hwnd );
603 if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE;
605 return QUEUE_AddMsg( wndPtr->hmemTaskQ, &msg, 0 );
608 /***********************************************************************
609 * PostAppMessage (USER.116)
611 BOOL PostAppMessage( HTASK hTask, WORD message, WORD wParam, LONG lParam )
613 MSG16 msg;
615 if (GetTaskQueue(hTask) == 0) return FALSE;
616 msg.hwnd = 0;
617 msg.message = message;
618 msg.wParam = wParam;
619 msg.lParam = lParam;
620 msg.time = GetTickCount();
621 msg.pt.x = 0;
622 msg.pt.y = 0;
624 return QUEUE_AddMsg( GetTaskQueue(hTask), &msg, 0 );
628 /***********************************************************************
629 * SendMessage16 (USER.111)
631 LRESULT SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam)
633 WND * wndPtr;
634 LRESULT ret;
635 struct
637 LPARAM lParam;
638 WPARAM16 wParam;
639 UINT16 wMsg;
640 HWND16 hWnd;
641 } msgstruct = { lParam, wParam, msg, hwnd };
643 #ifdef CONFIG_IPC
644 MSG DDE_msg = { hwnd, msg, wParam, lParam };
645 if (DDE_SendMessage(&DDE_msg)) return TRUE;
646 #endif /* CONFIG_IPC */
648 if (hwnd == HWND_BROADCAST16)
650 dprintf_msg(stddeb,"SendMessage // HWND_BROADCAST !\n");
651 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
653 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
655 dprintf_msg(stddeb,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
656 wndPtr->hwndSelf, msg, (DWORD)wParam, lParam);
657 SendMessage16( wndPtr->hwndSelf, msg, wParam, lParam );
660 dprintf_msg(stddeb,"SendMessage // End of HWND_BROADCAST !\n");
661 return TRUE;
665 HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1,
666 (LPARAM)MAKE_SEGPTR(&msgstruct) );
667 hwnd = msgstruct.hWnd;
668 msg = msgstruct.wMsg;
669 wParam = msgstruct.wParam;
670 lParam = msgstruct.lParam;
672 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
674 fprintf( stderr, "SendMessage16: invalid hwnd %04x\n", hwnd );
675 return 0;
677 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
679 #if 0
680 fprintf( stderr, "SendMessage16: intertask message not supported\n" );
681 return 0;
682 #endif
683 return MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam );
686 SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
687 ret = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
688 hwnd, msg, wParam, lParam );
689 SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret );
690 return ret;
694 /***********************************************************************
695 * SendMessage32A (USER32.453)
697 LRESULT SendMessage32A(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
699 WND * wndPtr;
700 LRESULT ret;
702 if (hwnd == HWND_BROADCAST32)
704 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
706 /* FIXME: should use something like EnumWindows here */
707 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
708 SendMessage32A( wndPtr->hwndSelf, msg, wParam, lParam );
710 return TRUE;
713 /* FIXME: call hooks */
715 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
717 fprintf( stderr, "SendMessage32A: invalid hwnd %08x\n", hwnd );
718 return 0;
720 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
722 fprintf( stderr, "SendMessage32A: intertask message not supported\n" );
723 return 0;
726 SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
727 ret = CallWindowProc32A( (WNDPROC32)wndPtr->winproc,
728 hwnd, msg, wParam, lParam );
729 SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
730 return ret;
734 /***********************************************************************
735 * SendMessage32W (USER32.458)
737 LRESULT SendMessage32W(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
739 WND * wndPtr;
740 LRESULT ret;
742 if (hwnd == HWND_BROADCAST32)
744 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
746 /* FIXME: should use something like EnumWindows here */
747 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
748 SendMessage32W( wndPtr->hwndSelf, msg, wParam, lParam );
750 return TRUE;
753 /* FIXME: call hooks */
755 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
757 fprintf( stderr, "SendMessage32W: invalid hwnd %08x\n", hwnd );
758 return 0;
760 if (wndPtr->hmemTaskQ != GetTaskQueue(0))
762 fprintf( stderr, "SendMessage32W: intertask message not supported\n" );
763 return 0;
766 SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
767 ret = CallWindowProc32W( (WNDPROC32)wndPtr->winproc,
768 hwnd, msg, wParam, lParam );
769 SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
770 return ret;
774 /***********************************************************************
775 * WaitMessage (USER.112)
777 void WaitMessage( void )
779 QUEUE_WaitBits( QS_ALLINPUT );
783 /***********************************************************************
784 * TranslateMessage (USER.113)
786 * This should call ToAscii but it is currently broken
789 #define ASCII_CHAR_HACK 0x0800
791 BOOL TranslateMessage( LPMSG16 msg )
793 UINT message = msg->message;
794 /* BYTE wparam[2]; */
796 if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
797 (message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
799 dprintf_msg(stddeb, "Translating key %04x, scancode %04x\n", msg->wParam,
800 HIWORD(msg->lParam) );
802 if( HIWORD(msg->lParam) & ASCII_CHAR_HACK )
804 /* if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
805 wparam, 0 ) )
808 message += 2 - (message & 0x0001);
810 PostMessage( msg->hwnd, message, lastEventChar, msg->lParam );
812 return TRUE;
815 return FALSE;
819 /***********************************************************************
820 * DispatchMessage (USER.114)
822 LONG DispatchMessage( const MSG16* msg )
824 WND * wndPtr;
825 LONG retval;
826 int painting;
828 /* Process timer messages */
829 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
831 if (msg->lParam)
833 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
834 return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
835 msg->message, msg->wParam, GetTickCount() );
839 if (!msg->hwnd) return 0;
840 if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
841 if (!wndPtr->winproc) return 0;
842 painting = (msg->message == WM_PAINT);
843 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
844 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
846 SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message,
847 msg->wParam, msg->lParam );
848 retval = CallWindowProc16( wndPtr->winproc, msg->hwnd, msg->message,
849 msg->wParam, msg->lParam );
850 SPY_ExitMessage( SPY_RESULT_OK16, msg->hwnd, msg->message, retval );
852 if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) &&
853 (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
855 fprintf(stderr, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
856 msg->hwnd);
857 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
858 /* Validate the update region to avoid infinite WM_PAINT loop */
859 ValidateRect32( msg->hwnd, NULL );
861 return retval;
865 /***********************************************************************
866 * RegisterWindowMessage16 (USER.118)
868 WORD RegisterWindowMessage16( SEGPTR str )
870 dprintf_msg(stddeb, "RegisterWindowMessage16: %08lx\n", (DWORD)str );
871 return GlobalAddAtom16( str );
875 /***********************************************************************
876 * RegisterWindowMessage32A (USER32.436)
878 WORD RegisterWindowMessage32A( LPCSTR str )
880 dprintf_msg(stddeb, "RegisterWindowMessage32A: %s\n", str );
881 return GlobalAddAtom32A( str );
885 /***********************************************************************
886 * RegisterWindowMessage32W (USER32.437)
888 WORD RegisterWindowMessage32W( LPCWSTR str )
890 dprintf_msg(stddeb, "RegisterWindowMessage32W: %p\n", str );
891 return GlobalAddAtom32W( str );
895 /***********************************************************************
896 * GetTickCount (USER.13) (KERNEL32.299)
898 DWORD GetTickCount(void)
900 struct timeval t;
901 gettimeofday( &t, NULL );
902 return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - MSG_WineStartTicks;
906 /***********************************************************************
907 * GetCurrentTime (USER.15)
909 * (effectively identical to GetTickCount)
911 DWORD GetCurrentTime(void)
913 return GetTickCount();
917 /***********************************************************************
918 * InSendMessage (USER.192)
920 BOOL InSendMessage()
922 MESSAGEQUEUE *queue;
924 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) )))
925 return 0;
926 return (BOOL)queue->InSendMessageHandle;