2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include <sys/types.h>
16 #include "sysmetrics.h"
29 #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
30 #define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
32 typedef enum { SYSQ_MSG_ABANDON
, SYSQ_MSG_SKIP
,
33 SYSQ_MSG_ACCEPT
, SYSQ_MSG_CONTINUE
} SYSQ_STATUS
;
35 extern MESSAGEQUEUE
*pCursorQueue
; /* queue.c */
36 extern MESSAGEQUEUE
*pActiveQueue
;
38 extern void joySendMessages(void);
40 DWORD MSG_WineStartTicks
; /* Ticks at Wine startup */
42 static UINT32 doubleClickSpeed
= 452;
43 static INT32 debugSMRL
= 0; /* intertask SendMessage() recursion level */
45 /***********************************************************************
48 BOOL32
MSG_CheckFilter(WORD uMsg
, DWORD filter
)
51 return (uMsg
>= LOWORD(filter
) && uMsg
<= HIWORD(filter
));
55 /***********************************************************************
56 * MSG_SendParentNotify
58 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
59 * the window has the WS_EX_NOPARENTNOTIFY style.
61 static void MSG_SendParentNotify(WND
* wndPtr
, WORD event
, WORD idChild
, LPARAM lValue
)
63 #define lppt ((LPPOINT16)&lValue)
65 /* pt has to be in the client coordinates of the parent window */
67 MapWindowPoints16( 0, wndPtr
->hwndSelf
, lppt
, 1 );
70 if (!(wndPtr
->dwStyle
& WS_CHILD
) || (wndPtr
->dwExStyle
& WS_EX_NOPARENTNOTIFY
)) break;
71 lppt
->x
+= wndPtr
->rectClient
.left
;
72 lppt
->y
+= wndPtr
->rectClient
.top
;
73 wndPtr
= wndPtr
->parent
;
74 SendMessage32A( wndPtr
->hwndSelf
, WM_PARENTNOTIFY
,
75 MAKEWPARAM( event
, idChild
), lValue
);
81 /***********************************************************************
82 * MSG_TranslateMouseMsg
84 * Translate an mouse hardware event into a real mouse message.
85 * Return value indicates whether the translated message must be passed
86 * to the user, left in the queue, or skipped entirely (in this case
87 * HIWORD contains hit test code).
89 static DWORD
MSG_TranslateMouseMsg( HWND16 hTopWnd
, DWORD filter
,
90 MSG16
*msg
, BOOL32 remove
, WND
* pWndScope
)
92 static DWORD dblclk_time_limit
= 0;
93 static UINT16 clk_message
= 0;
94 static HWND16 clk_hwnd
= 0;
95 static POINT16 clk_pos
= { 0, 0 };
99 INT16 ht
, hittest
, sendSC
= 0;
100 UINT16 message
= msg
->message
;
101 POINT16 screen_pt
, pt
;
102 HANDLE16 hQ
= GetTaskQueue(0);
103 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16(hQ
);
104 BOOL32 eatMsg
= FALSE
;
105 BOOL32 mouseClick
= ((message
== WM_LBUTTONDOWN
) ||
106 (message
== WM_RBUTTONDOWN
) ||
107 (message
== WM_MBUTTONDOWN
))?1:0;
110 /* Find the window */
112 ht
= hittest
= HTCLIENT
;
113 hWnd
= GetCapture16();
116 ht
= hittest
= WINPOS_WindowFromPoint( pWndScope
, msg
->pt
, &pWnd
);
117 if( !pWnd
) pWnd
= WIN_GetDesktop();
118 hWnd
= pWnd
->hwndSelf
;
123 pWnd
= WIN_FindWndPtr(hWnd
);
124 ht
= EVENT_GetCaptureInfo();
127 /* stop if not the right queue */
129 if (pWnd
->hmemTaskQ
!= hQ
)
131 /* Not for the current task */
132 if (queue
) QUEUE_ClearWakeBit( queue
, QS_MOUSE
);
133 /* Wake up the other task */
134 queue
= (MESSAGEQUEUE
*)GlobalLock16( pWnd
->hmemTaskQ
);
135 if (queue
) QUEUE_SetWakeBit( queue
, QS_MOUSE
);
136 return SYSQ_MSG_ABANDON
;
139 /* check if hWnd is within hWndScope */
141 if( hTopWnd
&& hWnd
!= hTopWnd
)
142 if( !IsChild16(hTopWnd
, hWnd
) ) return SYSQ_MSG_CONTINUE
;
146 /* translate double clicks -
147 * note that ...MOUSEMOVEs can slip in between
148 * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
150 if( pWnd
->class->style
& CS_DBLCLKS
|| ht
!= HTCLIENT
)
152 if ((message
== clk_message
) && (hWnd
== clk_hwnd
) &&
153 (msg
->time
- dblclk_time_limit
< doubleClickSpeed
) &&
154 (abs(msg
->pt
.x
- clk_pos
.x
) < SYSMETRICS_CXDOUBLECLK
/2) &&
155 (abs(msg
->pt
.y
- clk_pos
.y
) < SYSMETRICS_CYDOUBLECLK
/2))
157 message
+= (WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
);
158 mouseClick
++; /* == 2 */
162 screen_pt
= pt
= msg
->pt
;
164 if (hittest
!= HTCLIENT
)
166 message
+= ((INT16
)WM_NCMOUSEMOVE
- WM_MOUSEMOVE
);
167 msg
->wParam
= hittest
;
169 else ScreenToClient16( hWnd
, &pt
);
171 /* check message filter */
173 if (!MSG_CheckFilter(message
, filter
)) return SYSQ_MSG_CONTINUE
;
175 pCursorQueue
= queue
;
179 if (HOOK_IsHooked( WH_MOUSE
))
181 MOUSEHOOKSTRUCT16
*hook
= SEGPTR_NEW(MOUSEHOOKSTRUCT16
);
184 hook
->pt
= screen_pt
;
186 hook
->wHitTestCode
= hittest
;
187 hook
->dwExtraInfo
= 0;
188 ret
= HOOK_CallHooks16( WH_MOUSE
, remove
? HC_ACTION
: HC_NOREMOVE
,
189 message
, (LPARAM
)SEGPTR_GET(hook
) );
192 if( ret
) return MAKELONG((INT16
)SYSQ_MSG_SKIP
, hittest
);
195 if ((hittest
== HTERROR
) || (hittest
== HTNOWHERE
))
197 else if( remove
&& mouseClick
)
199 HWND32 hwndTop
= WIN_GetTopParent( hWnd
);
201 if( mouseClick
== 1 )
204 dblclk_time_limit
= msg
->time
;
205 clk_message
= msg
->message
;
209 /* got double click - zero them out */
210 dblclk_time_limit
= clk_hwnd
= 0;
214 /* Send the WM_PARENTNOTIFY,
215 * note that even for double/nonclient clicks
216 * notification message is still WM_L/M/RBUTTONDOWN.
219 MSG_SendParentNotify( pWnd
, msg
->message
, 0, MAKELPARAM(screen_pt
.x
, screen_pt
.y
) );
221 /* Activate the window if needed */
223 if (hWnd
!= GetActiveWindow16() && hWnd
!= GetDesktopWindow16())
225 LONG ret
= SendMessage16( hWnd
, WM_MOUSEACTIVATE
, hwndTop
,
226 MAKELONG( hittest
, message
) );
228 if ((ret
== MA_ACTIVATEANDEAT
) || (ret
== MA_NOACTIVATEANDEAT
))
231 if (((ret
== MA_ACTIVATE
) || (ret
== MA_ACTIVATEANDEAT
))
232 && hwndTop
!= GetActiveWindow16() )
233 if (!WINPOS_SetActiveWindow( hwndTop
, TRUE
, TRUE
))
237 } else sendSC
= (remove
&& sendSC
);
239 /* Send the WM_SETCURSOR message */
242 SendMessage16( hWnd
, WM_SETCURSOR
, (WPARAM16
)hWnd
,
243 MAKELONG( hittest
, message
));
244 if (eatMsg
) return MAKELONG( (UINT16
)SYSQ_MSG_SKIP
, hittest
);
247 msg
->message
= message
;
248 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
249 return SYSQ_MSG_ACCEPT
;
253 /***********************************************************************
254 * MSG_TranslateKbdMsg
256 * Translate an keyboard hardware event into a real message.
258 static DWORD
MSG_TranslateKbdMsg( HWND16 hTopWnd
, DWORD filter
,
259 MSG16
*msg
, BOOL32 remove
)
261 WORD message
= msg
->message
;
262 HWND16 hWnd
= GetFocus16();
265 /* Should check Ctrl-Esc and PrintScreen here */
269 /* Send the message to the active window instead, */
270 /* translating messages to their WM_SYS equivalent */
272 hWnd
= GetActiveWindow16();
274 if( message
< WM_SYSKEYDOWN
)
275 message
+= WM_SYSKEYDOWN
- WM_KEYDOWN
;
277 pWnd
= WIN_FindWndPtr( hWnd
);
278 if (pWnd
&& (pWnd
->hmemTaskQ
!= GetTaskQueue(0)))
280 /* Not for the current task */
281 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) );
282 if (queue
) QUEUE_ClearWakeBit( queue
, QS_KEY
);
283 /* Wake up the other task */
284 queue
= (MESSAGEQUEUE
*)GlobalLock16( pWnd
->hmemTaskQ
);
285 if (queue
) QUEUE_SetWakeBit( queue
, QS_KEY
);
286 return SYSQ_MSG_ABANDON
;
289 if (hTopWnd
&& hWnd
!= hTopWnd
)
290 if (!IsChild16(hTopWnd
, hWnd
)) return SYSQ_MSG_CONTINUE
;
291 if (!MSG_CheckFilter(message
, filter
)) return SYSQ_MSG_CONTINUE
;
294 msg
->message
= message
;
296 return (HOOK_CallHooks16( WH_KEYBOARD
, remove
? HC_ACTION
: HC_NOREMOVE
,
297 msg
->wParam
, msg
->lParam
)
298 ? SYSQ_MSG_SKIP
: SYSQ_MSG_ACCEPT
);
302 /***********************************************************************
303 * MSG_JournalRecordMsg
305 * Build an EVENTMSG structure and call JOURNALRECORD hook
307 static void MSG_JournalRecordMsg( MSG16
*msg
)
309 EVENTMSG16
*event
= SEGPTR_NEW(EVENTMSG16
);
311 event
->message
= msg
->message
;
312 event
->time
= msg
->time
;
313 if ((msg
->message
>= WM_KEYFIRST
) && (msg
->message
<= WM_KEYLAST
))
315 event
->paramL
= (msg
->wParam
& 0xFF) | (HIWORD(msg
->lParam
) << 8);
316 event
->paramH
= msg
->lParam
& 0x7FFF;
317 if (HIWORD(msg
->lParam
) & 0x0100)
318 event
->paramH
|= 0x8000; /* special_key - bit */
319 HOOK_CallHooks16( WH_JOURNALRECORD
, HC_ACTION
, 0,
320 (LPARAM
)SEGPTR_GET(event
) );
322 else if ((msg
->message
>= WM_MOUSEFIRST
) && (msg
->message
<= WM_MOUSELAST
))
324 event
->paramL
= LOWORD(msg
->lParam
); /* X pos */
325 event
->paramH
= HIWORD(msg
->lParam
); /* Y pos */
326 ClientToScreen16( msg
->hwnd
, (LPPOINT16
)&event
->paramL
);
327 HOOK_CallHooks16( WH_JOURNALRECORD
, HC_ACTION
, 0,
328 (LPARAM
)SEGPTR_GET(event
) );
330 else if ((msg
->message
>= WM_NCMOUSEFIRST
) &&
331 (msg
->message
<= WM_NCMOUSELAST
))
333 event
->paramL
= LOWORD(msg
->lParam
); /* X pos */
334 event
->paramH
= HIWORD(msg
->lParam
); /* Y pos */
335 event
->message
+= WM_MOUSEMOVE
-WM_NCMOUSEMOVE
;/* give no info about NC area */
336 HOOK_CallHooks16( WH_JOURNALRECORD
, HC_ACTION
, 0,
337 (LPARAM
)SEGPTR_GET(event
) );
342 /***********************************************************************
343 * MSG_JournalPlayBackMsg
345 * Get an EVENTMSG struct via call JOURNALPLAYBACK hook function
347 static int MSG_JournalPlayBackMsg(void)
351 WORD keyDown
,i
,wParam
,result
=0;
353 if ( HOOK_IsHooked( WH_JOURNALPLAYBACK
) )
355 tmpMsg
= SEGPTR_NEW(EVENTMSG16
);
356 wtime
=HOOK_CallHooks16( WH_JOURNALPLAYBACK
, HC_GETNEXT
, 0,
357 (LPARAM
)SEGPTR_GET(tmpMsg
));
358 /* TRACE(msg,"Playback wait time =%ld\n",wtime); */
362 if ((tmpMsg
->message
>= WM_KEYFIRST
) && (tmpMsg
->message
<= WM_KEYLAST
))
364 wParam
=tmpMsg
->paramL
& 0xFF;
365 lParam
=MAKELONG(tmpMsg
->paramH
&0x7ffff,tmpMsg
->paramL
>>8);
366 if (tmpMsg
->message
== WM_KEYDOWN
|| tmpMsg
->message
== WM_SYSKEYDOWN
)
368 for (keyDown
=i
=0; i
<256 && !keyDown
; i
++)
369 if (InputKeyStateTable
[i
] & 0x80)
372 lParam
|= 0x40000000;
373 AsyncKeyStateTable
[wParam
]=InputKeyStateTable
[wParam
] |= 0x80;
375 else /* WM_KEYUP, WM_SYSKEYUP */
377 lParam
|= 0xC0000000;
378 AsyncKeyStateTable
[wParam
]=InputKeyStateTable
[wParam
] &= ~0x80;
380 if (InputKeyStateTable
[VK_MENU
] & 0x80)
381 lParam
|= 0x20000000;
382 if (tmpMsg
->paramH
& 0x8000) /*special_key bit*/
383 lParam
|= 0x01000000;
384 hardware_event( tmpMsg
->message
, wParam
, lParam
,0, 0, tmpMsg
->time
, 0 );
388 if ((tmpMsg
->message
>= WM_MOUSEFIRST
) && (tmpMsg
->message
<= WM_MOUSELAST
))
390 switch (tmpMsg
->message
)
393 MouseButtonsStates
[0]=AsyncMouseButtonsStates
[0]=TRUE
;break;
395 MouseButtonsStates
[0]=AsyncMouseButtonsStates
[0]=FALSE
;break;
397 MouseButtonsStates
[1]=AsyncMouseButtonsStates
[1]=TRUE
;break;
399 MouseButtonsStates
[1]=AsyncMouseButtonsStates
[1]=FALSE
;break;
401 MouseButtonsStates
[2]=AsyncMouseButtonsStates
[2]=TRUE
;break;
403 MouseButtonsStates
[2]=AsyncMouseButtonsStates
[2]=FALSE
;break;
405 AsyncKeyStateTable
[VK_LBUTTON
]= InputKeyStateTable
[VK_LBUTTON
] = MouseButtonsStates
[0] ? 0x80 : 0;
406 AsyncKeyStateTable
[VK_MBUTTON
]= InputKeyStateTable
[VK_MBUTTON
] = MouseButtonsStates
[1] ? 0x80 : 0;
407 AsyncKeyStateTable
[VK_RBUTTON
]= InputKeyStateTable
[VK_RBUTTON
] = MouseButtonsStates
[2] ? 0x80 : 0;
408 SetCursorPos32(tmpMsg
->paramL
,tmpMsg
->paramH
);
409 lParam
=MAKELONG(tmpMsg
->paramL
,tmpMsg
->paramH
);
411 if (MouseButtonsStates
[0]) wParam
|= MK_LBUTTON
;
412 if (MouseButtonsStates
[1]) wParam
|= MK_MBUTTON
;
413 if (MouseButtonsStates
[2]) wParam
|= MK_RBUTTON
;
414 hardware_event( tmpMsg
->message
, wParam
, lParam
,
415 tmpMsg
->paramL
, tmpMsg
->paramH
, tmpMsg
->time
, 0 );
418 HOOK_CallHooks16( WH_JOURNALPLAYBACK
, HC_SKIP
, 0,
419 (LPARAM
)SEGPTR_GET(tmpMsg
));
423 if( tmpMsg
->message
== WM_QUEUESYNC
)
424 if (HOOK_IsHooked( WH_CBT
))
425 HOOK_CallHooks16( WH_CBT
, HCBT_QS
, 0, 0L);
427 result
= QS_MOUSE
| QS_KEY
; /* ? */
434 /***********************************************************************
435 * MSG_PeekHardwareMsg
437 * Peek for a hardware message matching the hwnd and message filters.
439 static BOOL32
MSG_PeekHardwareMsg( MSG16
*msg
, HWND16 hwnd
, DWORD filter
,
442 DWORD status
= SYSQ_MSG_ACCEPT
;
443 MESSAGEQUEUE
*sysMsgQueue
= QUEUE_GetSysQueue();
444 int i
, kbd_msg
, pos
= sysMsgQueue
->nextMessage
;
446 /* FIXME: there has to be a better way to do this */
449 /* If the queue is empty, attempt to fill it */
450 if (!sysMsgQueue
->msgCount
&& TSXPending(display
))
451 EVENT_WaitNetEvent( FALSE
, FALSE
);
453 for (i
= kbd_msg
= 0; i
< sysMsgQueue
->msgCount
; i
++, pos
++)
455 if (pos
>= sysMsgQueue
->queueSize
) pos
= 0;
456 *msg
= sysMsgQueue
->messages
[pos
].msg
;
458 /* Translate message */
460 if ((msg
->message
>= WM_MOUSEFIRST
) && (msg
->message
<= WM_MOUSELAST
))
462 HWND32 hWndScope
= (HWND32
)sysMsgQueue
->messages
[pos
].extraInfo
;
464 status
= MSG_TranslateMouseMsg(hwnd
, filter
, msg
, remove
,
465 (Options
.managed
&& IsWindow32(hWndScope
) )
466 ? WIN_FindWndPtr(hWndScope
) : WIN_GetDesktop() );
469 else if ((msg
->message
>= WM_KEYFIRST
) && (msg
->message
<= WM_KEYLAST
))
471 status
= MSG_TranslateKbdMsg(hwnd
, filter
, msg
, remove
);
474 else /* Non-standard hardware event */
476 HARDWAREHOOKSTRUCT16
*hook
;
477 if ((hook
= SEGPTR_NEW(HARDWAREHOOKSTRUCT16
)))
480 hook
->hWnd
= msg
->hwnd
;
481 hook
->wMessage
= msg
->message
;
482 hook
->wParam
= msg
->wParam
;
483 hook
->lParam
= msg
->lParam
;
484 ret
= HOOK_CallHooks16( WH_HARDWARE
,
485 remove
? HC_ACTION
: HC_NOREMOVE
,
486 0, (LPARAM
)SEGPTR_GET(hook
) );
490 QUEUE_RemoveMsg( sysMsgQueue
, pos
);
493 status
= SYSQ_MSG_ACCEPT
;
497 switch (LOWORD(status
))
499 case SYSQ_MSG_ACCEPT
:
503 if (HOOK_IsHooked( WH_CBT
))
505 HOOK_CallHooks16( WH_CBT
, HCBT_KEYSKIPPED
,
506 msg
->wParam
, msg
->lParam
);
509 MOUSEHOOKSTRUCT16
*hook
= SEGPTR_NEW(MOUSEHOOKSTRUCT16
);
513 hook
->hwnd
= msg
->hwnd
;
514 hook
->wHitTestCode
= HIWORD(status
);
515 hook
->dwExtraInfo
= 0;
516 HOOK_CallHooks16( WH_CBT
, HCBT_CLICKSKIPPED
,msg
->message
,
517 (LPARAM
)SEGPTR_GET(hook
) );
523 QUEUE_RemoveMsg( sysMsgQueue
, pos
);
526 case SYSQ_MSG_CONTINUE
:
529 case SYSQ_MSG_ABANDON
:
535 if (HOOK_IsHooked( WH_JOURNALRECORD
)) MSG_JournalRecordMsg( msg
);
536 QUEUE_RemoveMsg( sysMsgQueue
, pos
);
544 /**********************************************************************
545 * SetDoubleClickTime16 (USER.20)
547 void WINAPI
SetDoubleClickTime16( UINT16 interval
)
549 SetDoubleClickTime32( interval
);
553 /**********************************************************************
554 * SetDoubleClickTime32 (USER32.479)
556 BOOL32 WINAPI
SetDoubleClickTime32( UINT32 interval
)
558 doubleClickSpeed
= interval
? interval
: 500;
563 /**********************************************************************
564 * GetDoubleClickTime16 (USER.21)
566 UINT16 WINAPI
GetDoubleClickTime16(void)
568 return doubleClickSpeed
;
572 /**********************************************************************
573 * GetDoubleClickTime32 (USER32.238)
575 UINT32 WINAPI
GetDoubleClickTime32(void)
577 return doubleClickSpeed
;
581 /***********************************************************************
584 * Implementation of an inter-task SendMessage.
586 static LRESULT
MSG_SendMessage( HQUEUE16 hDestQueue
, HWND16 hwnd
, UINT16 msg
,
587 WPARAM32 wParam
, LPARAM lParam
, WORD flags
)
589 INT32 prevSMRL
= debugSMRL
;
590 QSMCTRL qCtrl
= { 0, 1};
591 MESSAGEQUEUE
*queue
, *destQ
;
593 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return 0;
594 if (!(destQ
= (MESSAGEQUEUE
*)GlobalLock16( hDestQueue
))) return 0;
596 if (IsTaskLocked() || !IsWindow32(hwnd
)) return 0;
599 TRACE(sendmsg
,"%*sSM: %s [%04x] (%04x -> %04x)\n",
600 prevSMRL
, "", SPY_GetMsgName(msg
), msg
, queue
->self
, hDestQueue
);
602 if( !(queue
->wakeBits
& QS_SMPARAMSFREE
) )
604 TRACE(sendmsg
,"\tIntertask SendMessage: sleeping since unreplied SendMessage pending\n");
605 queue
->changeBits
&= ~QS_SMPARAMSFREE
;
606 QUEUE_WaitBits( QS_SMPARAMSFREE
);
613 queue
->wParam
= LOWORD(wParam
);
614 queue
->wParamHigh
= HIWORD(wParam
);
615 queue
->lParam
= lParam
;
616 queue
->hPrevSendingTask
= destQ
->hSendingTask
;
617 destQ
->hSendingTask
= GetTaskQueue(0);
619 queue
->wakeBits
&= ~QS_SMPARAMSFREE
;
620 queue
->flags
= (queue
->flags
& ~(QUEUE_SM_WIN32
|QUEUE_SM_UNICODE
)) | flags
;
622 TRACE(sendmsg
,"%*ssm: smResultInit = %08x\n", prevSMRL
, "", (unsigned)&qCtrl
);
624 queue
->smResultInit
= &qCtrl
;
626 QUEUE_SetWakeBit( destQ
, QS_SENDMESSAGE
);
628 /* perform task switch and wait for the result */
630 while( qCtrl
.bPending
)
632 if (!(queue
->wakeBits
& QS_SMRESULT
))
634 queue
->changeBits
&= ~QS_SMRESULT
;
635 DirectedYield( destQ
->hTask
);
636 QUEUE_WaitBits( QS_SMRESULT
);
637 TRACE(sendmsg
,"\tsm: have result!\n");
641 TRACE(sendmsg
,"%*ssm: smResult = %08x\n", prevSMRL
, "", (unsigned)queue
->smResult
);
643 if (queue
->smResult
) { /* FIXME, smResult should always be set */
644 queue
->smResult
->lResult
= queue
->SendMessageReturn
;
645 queue
->smResult
->bPending
= FALSE
;
647 queue
->wakeBits
&= ~QS_SMRESULT
;
649 if( queue
->smResult
!= &qCtrl
)
650 ERR(sendmsg
, "%*ssm: weird scenes inside the goldmine!\n", prevSMRL
, "");
652 queue
->smResultInit
= NULL
;
654 TRACE(sendmsg
,"%*sSM: [%04x] returning %08lx\n", prevSMRL
, "", msg
, qCtrl
.lResult
);
657 return qCtrl
.lResult
;
661 /***********************************************************************
662 * ReplyMessage16 (USER.115)
664 void WINAPI
ReplyMessage16( LRESULT result
)
666 MESSAGEQUEUE
*senderQ
;
669 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return;
671 TRACE(msg
,"ReplyMessage, queue %04x\n", queue
->self
);
673 while( (senderQ
= (MESSAGEQUEUE
*)GlobalLock16( queue
->InSendMessageHandle
)))
675 TRACE(msg
,"\trpm: replying to %04x (%04x -> %04x)\n",
676 queue
->msg
, queue
->self
, senderQ
->self
);
678 if( queue
->wakeBits
& QS_SENDMESSAGE
)
680 QUEUE_ReceiveMessage( queue
);
681 continue; /* ReceiveMessage() already called us */
684 if(!(senderQ
->wakeBits
& QS_SMRESULT
) ) break;
687 if( !senderQ
) { TRACE(msg
,"\trpm: done\n"); return; }
689 senderQ
->SendMessageReturn
= result
;
690 TRACE(msg
,"\trpm: smResult = %08x, result = %08lx\n",
691 (unsigned)queue
->smResultCurrent
, result
);
693 senderQ
->smResult
= queue
->smResultCurrent
;
694 queue
->InSendMessageHandle
= 0;
696 QUEUE_SetWakeBit( senderQ
, QS_SMRESULT
);
697 DirectedYield( queue
->hSendingTask
);
701 /***********************************************************************
704 static BOOL32
MSG_PeekMessage( LPMSG16 msg
, HWND16 hwnd
, WORD first
, WORD last
,
705 WORD flags
, BOOL32 peek
)
708 MESSAGEQUEUE
*msgQueue
;
712 DDE_TestDDE(hwnd
); /* do we have dde handling in the window ?*/
713 DDE_GetRemoteMessage();
714 #endif /* CONFIG_IPC */
716 mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
719 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
720 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
721 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
722 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
723 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
724 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
726 else mask
|= QS_MOUSE
| QS_KEY
| QS_TIMER
| QS_PAINT
;
728 if (IsTaskLocked()) flags
|= PM_NOYIELD
;
732 hQueue
= GetTaskQueue(0);
733 msgQueue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
);
734 if (!msgQueue
) return FALSE
;
735 msgQueue
->changeBits
= 0;
737 /* First handle a message put by SendMessage() */
739 while (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
740 QUEUE_ReceiveMessage( msgQueue
);
742 /* Now handle a WM_QUIT message */
744 if (msgQueue
->wPostQMsg
&&
745 (!first
|| WM_QUIT
>= first
) &&
746 (!last
|| WM_QUIT
<= last
) )
749 msg
->message
= WM_QUIT
;
750 msg
->wParam
= msgQueue
->wExitCode
;
752 if (flags
& PM_REMOVE
) msgQueue
->wPostQMsg
= 0;
756 /* Now find a normal message */
758 if (((msgQueue
->wakeBits
& mask
) & QS_POSTMESSAGE
) &&
759 ((pos
= QUEUE_FindMsg( msgQueue
, hwnd
, first
, last
)) != -1))
761 QMSG
*qmsg
= &msgQueue
->messages
[pos
];
763 msgQueue
->GetMessageTimeVal
= msg
->time
;
764 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
765 msgQueue
->GetMessageExtraInfoVal
= qmsg
->extraInfo
;
767 if (flags
& PM_REMOVE
) QUEUE_RemoveMsg( msgQueue
, pos
);
771 msgQueue
->changeBits
|= MSG_JournalPlayBackMsg();
773 /* Now find a hardware event */
775 if (((msgQueue
->wakeBits
& mask
) & (QS_MOUSE
| QS_KEY
)) &&
776 MSG_PeekHardwareMsg( msg
, hwnd
, MAKELONG(first
,last
), flags
& PM_REMOVE
))
779 msgQueue
->GetMessageTimeVal
= msg
->time
;
780 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
781 msgQueue
->GetMessageExtraInfoVal
= 0; /* Always 0 for now */
785 /* Check again for SendMessage */
787 while (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
788 QUEUE_ReceiveMessage( msgQueue
);
790 /* Now find a WM_PAINT message */
792 if ((msgQueue
->wakeBits
& mask
) & QS_PAINT
)
795 msg
->hwnd
= WIN_FindWinToRepaint( hwnd
, hQueue
);
796 msg
->message
= WM_PAINT
;
800 if ((wndPtr
= WIN_FindWndPtr(msg
->hwnd
)))
802 if( wndPtr
->dwStyle
& WS_MINIMIZE
&&
803 wndPtr
->class->hIcon
)
805 msg
->message
= WM_PAINTICON
;
809 if( !hwnd
|| msg
->hwnd
== hwnd
|| IsChild16(hwnd
,msg
->hwnd
) )
811 if( wndPtr
->flags
& WIN_INTERNAL_PAINT
&& !wndPtr
->hrgnUpdate
)
813 wndPtr
->flags
&= ~WIN_INTERNAL_PAINT
;
814 QUEUE_DecPaintCount( hQueue
);
821 /* Check for timer messages, but yield first */
823 if (!(flags
& PM_NOYIELD
))
826 while (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
827 QUEUE_ReceiveMessage( msgQueue
);
829 if ((msgQueue
->wakeBits
& mask
) & QS_TIMER
)
831 if (TIMER_GetTimerMsg(msg
, hwnd
, hQueue
, flags
& PM_REMOVE
)) break;
836 if (!(flags
& PM_NOYIELD
)) UserYield();
839 msgQueue
->wakeMask
= mask
;
840 QUEUE_WaitBits( mask
);
843 /* We got a message */
844 if (flags
& PM_REMOVE
)
846 WORD message
= msg
->message
;
848 if (message
== WM_KEYDOWN
|| message
== WM_SYSKEYDOWN
)
850 BYTE
*p
= &QueueKeyStateTable
[msg
->wParam
& 0xff];
856 else if (message
== WM_KEYUP
|| message
== WM_SYSKEYUP
)
857 QueueKeyStateTable
[msg
->wParam
& 0xff] &= ~0x80;
859 if (peek
) return TRUE
;
860 else return (msg
->message
!= WM_QUIT
);
864 /***********************************************************************
865 * MSG_InternalGetMessage
867 * GetMessage() function for internal use. Behave like GetMessage(),
868 * but also call message filters and optionally send WM_ENTERIDLE messages.
869 * 'hwnd' must be the handle of the dialog or menu window.
870 * 'code' is the message filter value (MSGF_??? codes).
872 BOOL32
MSG_InternalGetMessage( MSG16
*msg
, HWND32 hwnd
, HWND32 hwndOwner
,
873 WPARAM32 code
, WORD flags
, BOOL32 sendIdle
)
879 if (!MSG_PeekMessage( msg
, 0, 0, 0, flags
, TRUE
))
881 /* No message present -> send ENTERIDLE and wait */
882 if (IsWindow32(hwndOwner
))
883 SendMessage16( hwndOwner
, WM_ENTERIDLE
,
884 code
, (LPARAM
)hwnd
);
885 MSG_PeekMessage( msg
, 0, 0, 0, flags
, FALSE
);
888 else /* Always wait for a message */
889 MSG_PeekMessage( msg
, 0, 0, 0, flags
, FALSE
);
891 /* Call message filters */
893 if (HOOK_IsHooked( WH_SYSMSGFILTER
) || HOOK_IsHooked( WH_MSGFILTER
))
895 MSG16
*pmsg
= SEGPTR_NEW(MSG16
);
900 ret
= ((BOOL16
)HOOK_CallHooks16( WH_SYSMSGFILTER
, code
, 0,
901 (LPARAM
)SEGPTR_GET(pmsg
) ) ||
902 (BOOL16
)HOOK_CallHooks16( WH_MSGFILTER
, code
, 0,
903 (LPARAM
)SEGPTR_GET(pmsg
) ));
907 /* Message filtered -> remove it from the queue */
908 /* if it's still there. */
909 if (!(flags
& PM_REMOVE
))
910 MSG_PeekMessage( msg
, 0, 0, 0, PM_REMOVE
, TRUE
);
916 return (msg
->message
!= WM_QUIT
);
921 /***********************************************************************
922 * PeekMessage16 (USER.109)
924 BOOL16 WINAPI
PeekMessage16( LPMSG16 msg
, HWND16 hwnd
, UINT16 first
,
925 UINT16 last
, UINT16 flags
)
927 return MSG_PeekMessage( msg
, hwnd
, first
, last
, flags
, TRUE
);
931 /***********************************************************************
932 * GetMessage16 (USER.108)
934 BOOL16 WINAPI
GetMessage16( SEGPTR msg
, HWND16 hwnd
, UINT16 first
, UINT16 last
)
936 MSG16
*lpmsg
= (MSG16
*)PTR_SEG_TO_LIN(msg
);
937 MSG_PeekMessage( lpmsg
,
938 hwnd
, first
, last
, PM_REMOVE
, FALSE
);
940 TRACE(msg
,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg
->message
,
942 HOOK_CallHooks16( WH_GETMESSAGE
, HC_ACTION
, 0, (LPARAM
)msg
);
943 return (lpmsg
->message
!= WM_QUIT
);
947 /***********************************************************************
948 * PostMessage16 (USER.110)
950 BOOL16 WINAPI
PostMessage16( HWND16 hwnd
, UINT16 message
, WPARAM16 wParam
,
957 msg
.message
= message
;
960 msg
.time
= GetTickCount();
965 if (DDE_PostMessage(&msg
))
967 #endif /* CONFIG_IPC */
969 if (hwnd
== HWND_BROADCAST
)
971 TRACE(msg
,"HWND_BROADCAST !\n");
972 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
974 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
976 TRACE(msg
,"BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
977 wndPtr
->hwndSelf
, message
, wParam
, lParam
);
978 PostMessage16( wndPtr
->hwndSelf
, message
, wParam
, lParam
);
981 TRACE(msg
,"End of HWND_BROADCAST !\n");
985 wndPtr
= WIN_FindWndPtr( hwnd
);
986 if (!wndPtr
|| !wndPtr
->hmemTaskQ
) return FALSE
;
988 return QUEUE_AddMsg( wndPtr
->hmemTaskQ
, &msg
, 0 );
992 /***********************************************************************
993 * PostMessage32A (USER32.418)
995 BOOL32 WINAPI
PostMessage32A( HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
,
999 return PostMessage16( hwnd
, message
, wParam
, lParam
);
1003 /***********************************************************************
1004 * PostMessage32W (USER32.419)
1006 BOOL32 WINAPI
PostMessage32W( HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
,
1010 return PostMessage16( hwnd
, message
, wParam
, lParam
);
1014 /***********************************************************************
1015 * PostAppMessage16 (USER.116)
1017 BOOL16 WINAPI
PostAppMessage16( HTASK16 hTask
, UINT16 message
, WPARAM16 wParam
,
1022 if (GetTaskQueue(hTask
) == 0) return FALSE
;
1024 msg
.message
= message
;
1025 msg
.wParam
= wParam
;
1026 msg
.lParam
= lParam
;
1027 msg
.time
= GetTickCount();
1031 return QUEUE_AddMsg( GetTaskQueue(hTask
), &msg
, 0 );
1035 /***********************************************************************
1036 * SendMessage16 (USER.111)
1038 LRESULT WINAPI
SendMessage16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
,
1042 WND
**list
, **ppWnd
;
1046 MSG16 DDE_msg
= { hwnd
, msg
, wParam
, lParam
};
1047 if (DDE_SendMessage(&DDE_msg
)) return TRUE
;
1048 #endif /* CONFIG_IPC */
1050 if (hwnd
== HWND_BROADCAST
)
1052 if (!(list
= WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL
)))
1054 TRACE(msg
,"HWND_BROADCAST !\n");
1055 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1058 if (!IsWindow32(wndPtr
->hwndSelf
)) continue;
1059 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
1061 TRACE(msg
,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
1062 wndPtr
->hwndSelf
, msg
, (DWORD
)wParam
, lParam
);
1063 SendMessage16( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
1066 HeapFree( SystemHeap
, 0, list
);
1067 TRACE(msg
,"End of HWND_BROADCAST !\n");
1071 if (HOOK_IsHooked( WH_CALLWNDPROC
))
1075 if ((pmsg
= SEGPTR_NEW(CWPSTRUCT16
)))
1079 pmsg
->wParam
= wParam
;
1080 pmsg
->lParam
= lParam
;
1081 HOOK_CallHooks16( WH_CALLWNDPROC
, HC_ACTION
, 1,
1082 (LPARAM
)SEGPTR_GET(pmsg
) );
1084 msg
= pmsg
->message
;
1085 wParam
= pmsg
->wParam
;
1086 lParam
= pmsg
->lParam
;
1087 SEGPTR_FREE( pmsg
);
1091 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
1093 WARN(msg
, "invalid hwnd %04x\n", hwnd
);
1096 if (QUEUE_IsExitingQueue(wndPtr
->hmemTaskQ
))
1097 return 0; /* Don't send anything if the task is dying */
1099 SPY_EnterMessage( SPY_SENDMESSAGE16
, hwnd
, msg
, wParam
, lParam
);
1101 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
1102 ret
= MSG_SendMessage( wndPtr
->hmemTaskQ
, hwnd
, msg
,
1103 wParam
, lParam
, 0 );
1105 ret
= CallWindowProc16( (WNDPROC16
)wndPtr
->winproc
,
1106 hwnd
, msg
, wParam
, lParam
);
1108 SPY_ExitMessage( SPY_RESULT_OK16
, hwnd
, msg
, ret
);
1112 /************************************************************************
1113 * MSG_CallWndProcHook32
1115 static void MSG_CallWndProcHook32( LPMSG32 pmsg
, BOOL32 bUnicode
)
1119 cwp
.lParam
= pmsg
->lParam
;
1120 cwp
.wParam
= pmsg
->wParam
;
1121 cwp
.message
= pmsg
->message
;
1122 cwp
.hwnd
= pmsg
->hwnd
;
1124 if (bUnicode
) HOOK_CallHooks32W(WH_CALLWNDPROC
, HC_ACTION
, 1, (LPARAM
)&cwp
);
1125 else HOOK_CallHooks32A( WH_CALLWNDPROC
, HC_ACTION
, 1, (LPARAM
)&cwp
);
1127 pmsg
->lParam
= cwp
.lParam
;
1128 pmsg
->wParam
= cwp
.wParam
;
1129 pmsg
->message
= cwp
.message
;
1130 pmsg
->hwnd
= cwp
.hwnd
;
1133 /**********************************************************************
1134 * PostThreadMessage32A (USER32.422)
1136 BOOL32 WINAPI
PostThreadMessage32A(DWORD idThread
, UINT32 message
,
1137 WPARAM32 wParam
, LPARAM lParam
)
1139 FIXME(sendmsg
, "(...): Stub\n");
1143 /***********************************************************************
1144 * SendMessage32A (USER32.453)
1146 LRESULT WINAPI
SendMessage32A( HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
,
1150 WND
**list
, **ppWnd
;
1153 if (hwnd
== HWND_BROADCAST
|| hwnd
== HWND_TOPMOST
)
1155 if (!(list
= WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL
)))
1157 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1160 if (!IsWindow32(wndPtr
->hwndSelf
)) continue;
1161 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
1162 SendMessage32A( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
1164 HeapFree( SystemHeap
, 0, list
);
1168 if (HOOK_IsHooked( WH_CALLWNDPROC
))
1169 MSG_CallWndProcHook32( (LPMSG32
)&hwnd
, FALSE
);
1171 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
1173 WARN(msg
, "invalid hwnd %08x\n", hwnd
);
1177 if (QUEUE_IsExitingQueue(wndPtr
->hmemTaskQ
))
1178 return 0; /* Don't send anything if the task is dying */
1180 SPY_EnterMessage( SPY_SENDMESSAGE32
, hwnd
, msg
, wParam
, lParam
);
1182 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
1183 ret
= MSG_SendMessage( wndPtr
->hmemTaskQ
, hwnd
, msg
, wParam
, lParam
,
1186 ret
= CallWindowProc32A( (WNDPROC32
)wndPtr
->winproc
,
1187 hwnd
, msg
, wParam
, lParam
);
1189 SPY_ExitMessage( SPY_RESULT_OK32
, hwnd
, msg
, ret
);
1194 /***********************************************************************
1195 * SendMessage32W (USER32.459)
1197 LRESULT WINAPI
SendMessage32W( HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
,
1201 WND
**list
, **ppWnd
;
1204 if (hwnd
== HWND_BROADCAST
|| hwnd
== HWND_TOPMOST
)
1206 if (!(list
= WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL
)))
1208 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1211 if (!IsWindow32(wndPtr
->hwndSelf
)) continue;
1212 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
1213 SendMessage32W( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
1215 HeapFree( SystemHeap
, 0, list
);
1219 if (HOOK_IsHooked( WH_CALLWNDPROC
))
1220 MSG_CallWndProcHook32( (LPMSG32
)&hwnd
, TRUE
);
1222 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
1224 WARN(msg
, "invalid hwnd %08x\n", hwnd
);
1227 if (QUEUE_IsExitingQueue(wndPtr
->hmemTaskQ
))
1228 return 0; /* Don't send anything if the task is dying */
1230 SPY_EnterMessage( SPY_SENDMESSAGE32
, hwnd
, msg
, wParam
, lParam
);
1232 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
1233 ret
= MSG_SendMessage( wndPtr
->hmemTaskQ
, hwnd
, msg
, wParam
, lParam
,
1234 QUEUE_SM_WIN32
| QUEUE_SM_UNICODE
);
1236 ret
= CallWindowProc32W( (WNDPROC32
)wndPtr
->winproc
,
1237 hwnd
, msg
, wParam
, lParam
);
1239 SPY_ExitMessage( SPY_RESULT_OK32
, hwnd
, msg
, ret
);
1244 /***********************************************************************
1245 * SendMessageTimeout16 (not a WINAPI)
1247 LRESULT WINAPI
SendMessageTimeout16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
,
1248 LPARAM lParam
, UINT16 flags
,
1249 UINT16 timeout
, LPWORD resultp
)
1251 FIXME(sendmsg
, "(...): semistub\n");
1252 return SendMessage16 (hwnd
, msg
, wParam
, lParam
);
1256 /***********************************************************************
1257 * SendMessageTimeout32A (USER32.457)
1259 LRESULT WINAPI
SendMessageTimeout32A( HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
,
1260 LPARAM lParam
, UINT32 flags
,
1261 UINT32 timeout
, LPDWORD resultp
)
1263 FIXME(sendmsg
, "(...): semistub\n");
1264 return SendMessage32A (hwnd
, msg
, wParam
, lParam
);
1268 /***********************************************************************
1269 * SendMessageTimeout32W (USER32.458)
1271 LRESULT WINAPI
SendMessageTimeout32W( HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
,
1272 LPARAM lParam
, UINT32 flags
,
1273 UINT32 timeout
, LPDWORD resultp
)
1275 FIXME(sendmsg
, "(...): semistub\n");
1276 return SendMessage32W (hwnd
, msg
, wParam
, lParam
);
1280 /***********************************************************************
1281 * WaitMessage (USER.112) (USER32.577)
1283 void WINAPI
WaitMessage( void )
1285 QUEUE_WaitBits( QS_ALLINPUT
);
1296 static const struct accent_char accent_chars
[] =
1298 /* A good idea should be to read /usr/X11/lib/X11/locale/iso8859-x/Compose */
1299 {'`', 'A', '\300'}, {'`', 'a', '\340'},
1300 {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
1301 {'^', 'A', '\302'}, {'^', 'a', '\342'},
1302 {'~', 'A', '\303'}, {'~', 'a', '\343'},
1303 {'"', 'A', '\304'}, {'"', 'a', '\344'},
1304 {'O', 'A', '\305'}, {'o', 'a', '\345'},
1305 {'0', 'A', '\305'}, {'0', 'a', '\345'},
1306 {'A', 'A', '\305'}, {'a', 'a', '\345'},
1307 {'A', 'E', '\306'}, {'a', 'e', '\346'},
1308 {',', 'C', '\307'}, {',', 'c', '\347'},
1309 {'`', 'E', '\310'}, {'`', 'e', '\350'},
1310 {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
1311 {'^', 'E', '\312'}, {'^', 'e', '\352'},
1312 {'"', 'E', '\313'}, {'"', 'e', '\353'},
1313 {'`', 'I', '\314'}, {'`', 'i', '\354'},
1314 {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
1315 {'^', 'I', '\316'}, {'^', 'i', '\356'},
1316 {'"', 'I', '\317'}, {'"', 'i', '\357'},
1317 {'-', 'D', '\320'}, {'-', 'd', '\360'},
1318 {'~', 'N', '\321'}, {'~', 'n', '\361'},
1319 {'`', 'O', '\322'}, {'`', 'o', '\362'},
1320 {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
1321 {'^', 'O', '\324'}, {'^', 'o', '\364'},
1322 {'~', 'O', '\325'}, {'~', 'o', '\365'},
1323 {'"', 'O', '\326'}, {'"', 'o', '\366'},
1324 {'/', 'O', '\330'}, {'/', 'o', '\370'},
1325 {'`', 'U', '\331'}, {'`', 'u', '\371'},
1326 {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
1327 {'^', 'U', '\333'}, {'^', 'u', '\373'},
1328 {'"', 'U', '\334'}, {'"', 'u', '\374'},
1329 {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
1330 {'T', 'H', '\336'}, {'t', 'h', '\376'},
1331 {'s', 's', '\337'}, {'"', 'y', '\377'},
1332 {'s', 'z', '\337'}, {'i', 'j', '\377'},
1333 /* iso-8859-2 uses this */
1334 {'<', 'L', '\245'}, {'<', 'l', '\265'}, /* caron */
1335 {'<', 'S', '\251'}, {'<', 's', '\271'},
1336 {'<', 'T', '\253'}, {'<', 't', '\273'},
1337 {'<', 'Z', '\256'}, {'<', 'z', '\276'},
1338 {'<', 'C', '\310'}, {'<', 'c', '\350'},
1339 {'<', 'E', '\314'}, {'<', 'e', '\354'},
1340 {'<', 'D', '\317'}, {'<', 'd', '\357'},
1341 {'<', 'N', '\322'}, {'<', 'n', '\362'},
1342 {'<', 'R', '\330'}, {'<', 'r', '\370'},
1343 {';', 'A', '\241'}, {';', 'a', '\261'}, /* ogonek */
1344 {';', 'E', '\312'}, {';', 'e', '\332'},
1345 {'\'', 'Z', '\254'}, {'\'', 'z', '\274'}, /* acute */
1346 {'\'', 'R', '\300'}, {'\'', 'r', '\340'},
1347 {'\'', 'L', '\305'}, {'\'', 'l', '\345'},
1348 {'\'', 'C', '\306'}, {'\'', 'c', '\346'},
1349 {'\'', 'N', '\321'}, {'\'', 'n', '\361'},
1350 /* collision whith S, from iso-8859-9 !!! */
1351 {',', 'S', '\252'}, {',', 's', '\272'}, /* cedilla */
1352 {',', 'T', '\336'}, {',', 't', '\376'},
1353 {'.', 'Z', '\257'}, {'.', 'z', '\277'}, /* dot above */
1354 {'/', 'L', '\243'}, {'/', 'l', '\263'}, /* slash */
1355 {'/', 'D', '\320'}, {'/', 'd', '\360'},
1356 {'(', 'A', '\303'}, {'(', 'a', '\343'}, /* breve */
1357 {'\275', 'O', '\325'}, {'\275', 'o', '\365'}, /* double acute */
1358 {'\275', 'U', '\334'}, {'\275', 'u', '\374'},
1359 {'0', 'U', '\332'}, {'0', 'u', '\372'}, /* ring above */
1360 /* iso-8859-3 uses this */
1361 {'/', 'H', '\241'}, {'/', 'h', '\261'}, /* slash */
1362 {'>', 'H', '\246'}, {'>', 'h', '\266'}, /* circumflex */
1363 {'>', 'J', '\254'}, {'>', 'j', '\274'},
1364 {'>', 'C', '\306'}, {'>', 'c', '\346'},
1365 {'>', 'G', '\330'}, {'>', 'g', '\370'},
1366 {'>', 'S', '\336'}, {'>', 's', '\376'},
1367 /* collision whith G( from iso-8859-9 !!! */
1368 {'(', 'G', '\253'}, {'(', 'g', '\273'}, /* breve */
1369 {'(', 'U', '\335'}, {'(', 'u', '\375'},
1370 /* collision whith I. from iso-8859-3 !!! */
1371 {'.', 'I', '\251'}, {'.', 'i', '\271'}, /* dot above */
1372 {'.', 'C', '\305'}, {'.', 'c', '\345'},
1373 {'.', 'G', '\325'}, {'.', 'g', '\365'},
1374 /* iso-8859-4 uses this */
1375 {',', 'R', '\243'}, {',', 'r', '\263'}, /* cedilla */
1376 {',', 'L', '\246'}, {',', 'l', '\266'},
1377 {',', 'G', '\253'}, {',', 'g', '\273'},
1378 {',', 'N', '\321'}, {',', 'n', '\361'},
1379 {',', 'K', '\323'}, {',', 'k', '\363'},
1380 {'~', 'I', '\245'}, {'~', 'i', '\265'}, /* tilde */
1381 {'-', 'E', '\252'}, {'-', 'e', '\272'}, /* macron */
1382 {'-', 'A', '\300'}, {'-', 'a', '\340'},
1383 {'-', 'I', '\317'}, {'-', 'i', '\357'},
1384 {'-', 'O', '\322'}, {'-', 'o', '\362'},
1385 {'-', 'U', '\336'}, {'-', 'u', '\376'},
1386 {'/', 'T', '\254'}, {'/', 't', '\274'}, /* slash */
1387 {'.', 'E', '\314'}, {'.', 'e', '\344'}, /* dot above */
1388 {';', 'I', '\307'}, {';', 'i', '\347'}, /* ogonek */
1389 {';', 'U', '\331'}, {';', 'u', '\371'},
1390 /* iso-8859-9 uses this */
1391 /* iso-8859-9 has really bad choosen G( S, and I. as they collide
1392 * whith the same letters on other iso-8859-x (that is they are on
1393 * different places :-( ), if you use turkish uncomment these and
1394 * comment out the lines in iso-8859-2 and iso-8859-3 sections
1395 * FIXME: should be dynamic according to chosen language
1396 * if/when Wine has turkish support.
1398 /* collision whith G( from iso-8859-3 !!! */
1399 /* {'(', 'G', '\320'}, {'(', 'g', '\360'}, */ /* breve */
1400 /* collision whith S, from iso-8859-2 !!! */
1401 /* {',', 'S', '\336'}, {',', 's', '\376'}, */ /* cedilla */
1402 /* collision whith I. from iso-8859-3 !!! */
1403 /* {'.', 'I', '\335'}, {'.', 'i', '\375'}, */ /* dot above */
1407 /***********************************************************************
1408 * MSG_DoTranslateMessage
1410 * Implementation of TranslateMessage.
1412 * TranslateMessage translates virtual-key messages into character-messages,
1414 * WM_KEYDOWN/WM_KEYUP combinations produce a WM_CHAR or WM_DEADCHAR message.
1415 * ditto replacing WM_* with WM_SYS*
1416 * This produces WM_CHAR messages only for keys mapped to ASCII characters
1417 * by the keyboard driver.
1419 static BOOL32
MSG_DoTranslateMessage( UINT32 message
, HWND32 hwnd
,
1420 WPARAM32 wParam
, LPARAM lParam
)
1422 static int dead_char
;
1425 if (message
!= WM_MOUSEMOVE
&& message
!= WM_TIMER
)
1426 TRACE(msg
, "(%s, %04X, %08lX)\n",
1427 SPY_GetMsgName(message
), wParam
, lParam
);
1428 if(message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
)
1429 TRACE(key
, "(%s, %04X, %08lX)\n",
1430 SPY_GetMsgName(message
), wParam
, lParam
);
1432 if ((message
!= WM_KEYDOWN
) && (message
!= WM_SYSKEYDOWN
)) return FALSE
;
1434 TRACE(key
, "Translating key %04X, scancode %04X\n",
1435 wParam
, HIWORD(lParam
) );
1437 /* FIXME : should handle ToAscii yielding 2 */
1438 switch (ToAscii32(wParam
, HIWORD(lParam
),
1439 QueueKeyStateTable
,(LPWORD
)wp
, 0))
1442 message
= (message
== WM_KEYDOWN
) ? WM_CHAR
: WM_SYSCHAR
;
1443 /* Should dead chars handling go in ToAscii ? */
1448 if (wp
[0] == ' ') wp
[0] = dead_char
;
1449 if (dead_char
== 0xa2) dead_char
= '(';
1450 else if (dead_char
== 0xa8) dead_char
= '"';
1451 else if (dead_char
== 0xb2) dead_char
= ';';
1452 else if (dead_char
== 0xb4) dead_char
= '\'';
1453 else if (dead_char
== 0xb7) dead_char
= '<';
1454 else if (dead_char
== 0xb8) dead_char
= ',';
1455 else if (dead_char
== 0xff) dead_char
= '.';
1456 for (i
= 0; i
< sizeof(accent_chars
)/sizeof(accent_chars
[0]); i
++)
1457 if ((accent_chars
[i
].ac_accent
== dead_char
) &&
1458 (accent_chars
[i
].ac_char
== wp
[0]))
1460 wp
[0] = accent_chars
[i
].ac_result
;
1465 TRACE(key
, "1 -> PostMessage(%s)\n", SPY_GetMsgName(message
));
1466 PostMessage16( hwnd
, message
, wp
[0], lParam
);
1470 message
= (message
== WM_KEYDOWN
) ? WM_DEADCHAR
: WM_SYSDEADCHAR
;
1472 TRACE(key
, "-1 -> PostMessage(%s)\n",
1473 SPY_GetMsgName(message
));
1474 PostMessage16( hwnd
, message
, wp
[0], lParam
);
1481 /***********************************************************************
1482 * TranslateMessage16 (USER.113)
1484 BOOL16 WINAPI
TranslateMessage16( const MSG16
*msg
)
1486 return MSG_DoTranslateMessage( msg
->message
, msg
->hwnd
,
1487 msg
->wParam
, msg
->lParam
);
1491 /***********************************************************************
1492 * TranslateMessage32 (USER32.555)
1494 BOOL32 WINAPI
TranslateMessage32( const MSG32
*msg
)
1496 return MSG_DoTranslateMessage( msg
->message
, msg
->hwnd
,
1497 msg
->wParam
, msg
->lParam
);
1501 /***********************************************************************
1502 * DispatchMessage16 (USER.114)
1504 LONG WINAPI
DispatchMessage16( const MSG16
* msg
)
1510 /* Process timer messages */
1511 if ((msg
->message
== WM_TIMER
) || (msg
->message
== WM_SYSTIMER
))
1515 return CallWindowProc16( (WNDPROC16
)msg
->lParam
, msg
->hwnd
,
1516 msg
->message
, msg
->wParam
, GetTickCount() );
1520 if (!msg
->hwnd
) return 0;
1521 if (!(wndPtr
= WIN_FindWndPtr( msg
->hwnd
))) return 0;
1522 if (!wndPtr
->winproc
) return 0;
1523 painting
= (msg
->message
== WM_PAINT
);
1524 if (painting
) wndPtr
->flags
|= WIN_NEEDS_BEGINPAINT
;
1526 SPY_EnterMessage( SPY_DISPATCHMESSAGE16
, msg
->hwnd
, msg
->message
,
1527 msg
->wParam
, msg
->lParam
);
1528 retval
= CallWindowProc16( (WNDPROC16
)wndPtr
->winproc
,
1529 msg
->hwnd
, msg
->message
,
1530 msg
->wParam
, msg
->lParam
);
1531 SPY_ExitMessage( SPY_RESULT_OK16
, msg
->hwnd
, msg
->message
, retval
);
1533 if (painting
&& (wndPtr
= WIN_FindWndPtr( msg
->hwnd
)) &&
1534 (wndPtr
->flags
& WIN_NEEDS_BEGINPAINT
) && wndPtr
->hrgnUpdate
)
1536 ERR(msg
, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
1538 wndPtr
->flags
&= ~WIN_NEEDS_BEGINPAINT
;
1539 /* Validate the update region to avoid infinite WM_PAINT loop */
1540 ValidateRect32( msg
->hwnd
, NULL
);
1546 /***********************************************************************
1547 * DispatchMessage32A (USER32.140)
1549 LONG WINAPI
DispatchMessage32A( const MSG32
* msg
)
1555 /* Process timer messages */
1556 if ((msg
->message
== WM_TIMER
) || (msg
->message
== WM_SYSTIMER
))
1560 /* HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
1561 return CallWindowProc32A( (WNDPROC32
)msg
->lParam
, msg
->hwnd
,
1562 msg
->message
, msg
->wParam
, GetTickCount() );
1566 if (!msg
->hwnd
) return 0;
1567 if (!(wndPtr
= WIN_FindWndPtr( msg
->hwnd
))) return 0;
1568 if (!wndPtr
->winproc
) return 0;
1569 painting
= (msg
->message
== WM_PAINT
);
1570 if (painting
) wndPtr
->flags
|= WIN_NEEDS_BEGINPAINT
;
1571 /* HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
1573 SPY_EnterMessage( SPY_DISPATCHMESSAGE32
, msg
->hwnd
, msg
->message
,
1574 msg
->wParam
, msg
->lParam
);
1575 retval
= CallWindowProc32A( (WNDPROC32
)wndPtr
->winproc
,
1576 msg
->hwnd
, msg
->message
,
1577 msg
->wParam
, msg
->lParam
);
1578 SPY_ExitMessage( SPY_RESULT_OK32
, msg
->hwnd
, msg
->message
, retval
);
1580 if (painting
&& (wndPtr
= WIN_FindWndPtr( msg
->hwnd
)) &&
1581 (wndPtr
->flags
& WIN_NEEDS_BEGINPAINT
) && wndPtr
->hrgnUpdate
)
1583 ERR(msg
, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
1585 wndPtr
->flags
&= ~WIN_NEEDS_BEGINPAINT
;
1586 /* Validate the update region to avoid infinite WM_PAINT loop */
1587 ValidateRect32( msg
->hwnd
, NULL
);
1593 /***********************************************************************
1594 * DispatchMessage32W (USER32.141)
1596 LONG WINAPI
DispatchMessage32W( const MSG32
* msg
)
1602 /* Process timer messages */
1603 if ((msg
->message
== WM_TIMER
) || (msg
->message
== WM_SYSTIMER
))
1607 /* HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
1608 return CallWindowProc32W( (WNDPROC32
)msg
->lParam
, msg
->hwnd
,
1609 msg
->message
, msg
->wParam
, GetTickCount() );
1613 if (!msg
->hwnd
) return 0;
1614 if (!(wndPtr
= WIN_FindWndPtr( msg
->hwnd
))) return 0;
1615 if (!wndPtr
->winproc
) return 0;
1616 painting
= (msg
->message
== WM_PAINT
);
1617 if (painting
) wndPtr
->flags
|= WIN_NEEDS_BEGINPAINT
;
1618 /* HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
1620 SPY_EnterMessage( SPY_DISPATCHMESSAGE32
, msg
->hwnd
, msg
->message
,
1621 msg
->wParam
, msg
->lParam
);
1622 retval
= CallWindowProc32W( (WNDPROC32
)wndPtr
->winproc
,
1623 msg
->hwnd
, msg
->message
,
1624 msg
->wParam
, msg
->lParam
);
1625 SPY_ExitMessage( SPY_RESULT_OK32
, msg
->hwnd
, msg
->message
, retval
);
1627 if (painting
&& (wndPtr
= WIN_FindWndPtr( msg
->hwnd
)) &&
1628 (wndPtr
->flags
& WIN_NEEDS_BEGINPAINT
) && wndPtr
->hrgnUpdate
)
1630 ERR(msg
, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
1632 wndPtr
->flags
&= ~WIN_NEEDS_BEGINPAINT
;
1633 /* Validate the update region to avoid infinite WM_PAINT loop */
1634 ValidateRect32( msg
->hwnd
, NULL
);
1640 /***********************************************************************
1641 * RegisterWindowMessage16 (USER.118)
1643 WORD WINAPI
RegisterWindowMessage16( SEGPTR str
)
1645 TRACE(msg
, "%08lx\n", (DWORD
)str
);
1646 return GlobalAddAtom16( str
);
1650 /***********************************************************************
1651 * RegisterWindowMessage32A (USER32.436)
1653 WORD WINAPI
RegisterWindowMessage32A( LPCSTR str
)
1655 TRACE(msg
, "%s\n", str
);
1656 return GlobalAddAtom32A( str
);
1660 /***********************************************************************
1661 * RegisterWindowMessage32W (USER32.437)
1663 WORD WINAPI
RegisterWindowMessage32W( LPCWSTR str
)
1665 TRACE(msg
, "%p\n", str
);
1666 return GlobalAddAtom32W( str
);
1670 /***********************************************************************
1671 * GetTickCount (USER.13) (KERNEL32.299)
1673 DWORD WINAPI
GetTickCount(void)
1676 gettimeofday( &t
, NULL
);
1677 return ((t
.tv_sec
* 1000) + (t
.tv_usec
/ 1000)) - MSG_WineStartTicks
;
1681 /***********************************************************************
1682 * GetCurrentTime16 (USER.15)
1684 * (effectively identical to GetTickCount)
1686 DWORD WINAPI
GetCurrentTime16(void)
1688 return GetTickCount();
1692 /***********************************************************************
1693 * InSendMessage16 (USER.192)
1695 BOOL16 WINAPI
InSendMessage16(void)
1697 return InSendMessage32();
1701 /***********************************************************************
1702 * InSendMessage32 (USER32.319)
1704 BOOL32 WINAPI
InSendMessage32(void)
1706 MESSAGEQUEUE
*queue
;
1708 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) )))
1710 return (BOOL32
)queue
->InSendMessageHandle
;
1713 /***********************************************************************
1714 * BroadcastSystemMessage (USER32.12)
1716 LONG WINAPI
BroadcastSystemMessage(
1717 DWORD dwFlags
,LPDWORD recipients
,UINT32 uMessage
,WPARAM32 wParam
,
1720 FIXME(sendmsg
,"(%08lx,%08lx,%08x,%08x,%08lx): stub!\n",
1721 dwFlags
,*recipients
,uMessage
,wParam
,lParam
1726 /***********************************************************************
1727 * SendNotifyMessageA (USER32.460)
1729 LONG WINAPI
SendNotifyMessage32A(HWND32 hwnd
,UINT32 msg
,WPARAM32 wParam
,LPARAM lParam
)
1731 FIXME(msg
,"(%04x,%08lx,%08lx,%08lx): stub!\n",
1732 hwnd
,(long)msg
,(long)wParam
,lParam