2 * Message queues related functions
4 * Copyright 1993 Alexandre Julliard
8 * This code assumes that there is only one Windows task (hence
12 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
20 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
22 extern HWND
WIN_FindWinToRepaint( HWND hwnd
);
24 extern Display
* XT_display
;
25 extern Screen
* XT_screen
;
26 extern XtAppContext XT_app_context
;
28 static MESSAGEQUEUE
* msgQueue
= NULL
;
31 /***********************************************************************
35 int MSG_GetMessageType( int msg
)
37 if ((msg
>= WM_KEYFIRST
) && (msg
<= WM_KEYLAST
)) return QS_KEY
;
38 else if ((msg
>= WM_MOUSEFIRST
) && (msg
<= WM_MOUSELAST
))
40 if (msg
== WM_MOUSEMOVE
) return QS_MOUSEMOVE
;
41 else return QS_MOUSEBUTTON
;
43 else if (msg
== WM_PAINT
) return QS_PAINT
;
44 else if (msg
== WM_TIMER
) return QS_TIMER
;
45 return QS_POSTMESSAGE
;
49 /***********************************************************************
52 * Add a message to the queue. Return FALSE if queue is full.
54 int MSG_AddMsg( MSG
* msg
, DWORD extraInfo
)
58 if (!msgQueue
) return FALSE
;
59 pos
= msgQueue
->nextFreeMessage
;
61 /* No need to store WM_PAINT messages */
62 if (msg
->message
== WM_PAINT
) return TRUE
;
64 /* Check if queue is full */
65 if ((pos
== msgQueue
->nextMessage
) && (msgQueue
->msgCount
> 0))
69 msgQueue
->messages
[pos
].msg
= *msg
;
70 msgQueue
->messages
[pos
].extraInfo
= extraInfo
;
72 /* Store message type */
73 type
= MSG_GetMessageType( msg
->message
);
74 msgQueue
->status
|= type
;
75 msgQueue
->tempStatus
|= type
;
77 if (pos
< msgQueue
->queueSize
-1) pos
++;
79 msgQueue
->nextFreeMessage
= pos
;
86 /***********************************************************************
89 * Find a message matching the given parameters. Return -1 if none available.
91 int MSG_FindMsg( HWND hwnd
, int first
, int last
)
93 int i
, pos
= msgQueue
->nextMessage
;
95 if (!msgQueue
->msgCount
) return -1;
96 if (!hwnd
&& !first
&& !last
) return pos
;
98 for (i
= 0; i
< msgQueue
->msgCount
; i
++)
100 MSG
* msg
= &msgQueue
->messages
[pos
].msg
;
102 if (!hwnd
|| (msg
->hwnd
== hwnd
))
104 if (!first
&& !last
) return pos
;
105 if ((msg
->message
>= first
) && (msg
->message
<= last
)) return pos
;
107 if (pos
< msgQueue
->queueSize
-1) pos
++;
114 /***********************************************************************
117 * Remove a message from the queue (pos must be a valid position).
119 void MSG_RemoveMsg( int pos
)
124 if (!msgQueue
) return;
125 qmsg
= &msgQueue
->messages
[pos
];
127 if (pos
>= msgQueue
->nextMessage
)
129 int count
= pos
- msgQueue
->nextMessage
;
130 if (count
) memmove( &msgQueue
->messages
[msgQueue
->nextMessage
+1],
131 &msgQueue
->messages
[msgQueue
->nextMessage
],
132 count
* sizeof(QMSG
) );
133 msgQueue
->nextMessage
++;
134 if (msgQueue
->nextMessage
>= msgQueue
->queueSize
)
135 msgQueue
->nextMessage
= 0;
139 int count
= msgQueue
->nextFreeMessage
- pos
;
140 if (count
) memmove( &msgQueue
->messages
[pos
],
141 &msgQueue
->messages
[pos
+1], count
* sizeof(QMSG
) );
142 if (msgQueue
->nextFreeMessage
) msgQueue
->nextFreeMessage
--;
143 else msgQueue
->nextFreeMessage
= msgQueue
->queueSize
-1;
145 msgQueue
->msgCount
--;
149 pos
= msgQueue
->nextMessage
;
150 for (i
= 0; i
< msgQueue
->msgCount
; i
++)
152 type
|= MSG_GetMessageType( msgQueue
->messages
[pos
].msg
.message
);
153 if (++pos
>= msgQueue
->queueSize
-1) pos
= 0;
155 msgQueue
->status
= (msgQueue
->status
& QS_SENDMESSAGE
) | type
;
156 msgQueue
->tempStatus
= 0;
160 /***********************************************************************
161 * SetMessageQueue (USER.266)
163 BOOL
SetMessageQueue( int size
)
167 /* Free the old message queue */
168 if (msgQueue
) free(msgQueue
);
170 if ((size
> MAX_QUEUE_SIZE
) || (size
<= 0)) return FALSE
;
172 queueSize
= sizeof(MESSAGEQUEUE
) + size
* sizeof(QMSG
);
173 msgQueue
= (MESSAGEQUEUE
*) malloc(queueSize
);
174 if (!msgQueue
) return FALSE
;
178 msgQueue
->msgSize
= sizeof(QMSG
);
179 msgQueue
->msgCount
= 0;
180 msgQueue
->nextMessage
= 0;
181 msgQueue
->nextFreeMessage
= 0;
182 msgQueue
->queueSize
= size
;
183 msgQueue
->GetMessageTimeVal
= 0;
184 msgQueue
->GetMessagePosVal
= 0;
185 msgQueue
->GetMessageExtraInfoVal
= 0;
186 msgQueue
->lParam
= 0;
187 msgQueue
->wParam
= 0;
190 msgQueue
->wPostQMsg
= 0;
191 msgQueue
->wExitCode
= 0;
192 msgQueue
->InSendMessageHandle
= 0;
193 msgQueue
->tempStatus
= 0;
194 msgQueue
->status
= 0;
200 /***********************************************************************
201 * PostQuitMessage (USER.6)
203 void PostQuitMessage( int exitCode
)
205 if (!msgQueue
) return;
206 msgQueue
->wPostQMsg
= TRUE
;
207 msgQueue
->wExitCode
= exitCode
;
211 /***********************************************************************
212 * GetQueueStatus (USER.334)
214 DWORD
GetQueueStatus( int flags
)
216 unsigned long ret
= (msgQueue
->status
<< 16) | msgQueue
->tempStatus
;
217 if (flags
& QS_PAINT
)
219 if (WIN_FindWinToRepaint(0)) ret
|= QS_PAINT
| (QS_PAINT
<< 16);
221 msgQueue
->tempStatus
= 0;
222 return ret
& ((flags
<< 16) | flags
);
226 /***********************************************************************
227 * GetInputState (USER.335)
231 return msgQueue
->status
& (QS_KEY
| QS_MOUSEBUTTON
);
235 /***********************************************************************
238 BOOL
MSG_PeekMessage( LPMSG msg
, HWND hwnd
, WORD first
, WORD last
, WORD flags
)
242 /* First handle a WM_QUIT message */
243 if (msgQueue
->wPostQMsg
)
246 msg
->message
= WM_QUIT
;
247 msg
->wParam
= msgQueue
->wExitCode
;
252 /* Then handle a message put by SendMessage() */
253 if (msgQueue
->status
& QS_SENDMESSAGE
)
255 if (!hwnd
|| (msgQueue
->hWnd
== hwnd
))
257 if ((!first
&& !last
) ||
258 ((msgQueue
->msg
>= first
) && (msgQueue
->msg
<= last
)))
260 msg
->hwnd
= msgQueue
->hWnd
;
261 msg
->message
= msgQueue
->msg
;
262 msg
->wParam
= msgQueue
->wParam
;
263 msg
->lParam
= msgQueue
->lParam
;
264 if (flags
& PM_REMOVE
) msgQueue
->status
&= ~QS_SENDMESSAGE
;
271 /* Now find a normal message */
272 pos
= MSG_FindMsg( hwnd
, first
, last
);
275 QMSG
*qmsg
= &msgQueue
->messages
[pos
];
277 msgQueue
->GetMessageTimeVal
= msg
->time
;
278 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
279 msgQueue
->GetMessageExtraInfoVal
= qmsg
->extraInfo
;
281 if (flags
& PM_REMOVE
) MSG_RemoveMsg(pos
);
285 /* If nothing else, return a WM_PAINT message */
286 if ((!first
&& !last
) || ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)))
288 msg
->hwnd
= WIN_FindWinToRepaint( hwnd
);
289 msg
->message
= WM_PAINT
;
292 return (msg
->hwnd
!= 0);
298 /***********************************************************************
299 * PeekMessage (USER.109)
301 BOOL
PeekMessage( LPMSG msg
, HWND hwnd
, WORD first
, WORD last
, WORD flags
)
303 while (XtAppPending( XT_app_context
))
304 XtAppProcessEvent( XT_app_context
, XtIMAll
);
306 return MSG_PeekMessage( msg
, hwnd
, first
, last
, flags
);
310 /***********************************************************************
311 * GetMessage (USER.108)
313 BOOL
GetMessage( LPMSG msg
, HWND hwnd
, WORD first
, WORD last
)
317 if (MSG_PeekMessage( msg
, hwnd
, first
, last
, PM_REMOVE
)) break;
318 XtAppProcessEvent( XT_app_context
, XtIMAll
);
321 return (msg
->message
!= WM_QUIT
);
325 /***********************************************************************
326 * PostMessage (USER.110)
328 BOOL
PostMessage( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
333 msg
.message
= message
;
336 msg
.time
= GetTickCount();
340 return MSG_AddMsg( &msg
, 0 );
344 /***********************************************************************
345 * SendMessage (USER.111)
347 LONG
SendMessage( HWND hwnd
, WORD msg
, WORD wParam
, LONG lParam
)
350 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
353 retval
= CallWindowProc( wndPtr
->lpfnWndProc
, hwnd
, msg
,
355 GlobalUnlock( hwnd
);
361 /***********************************************************************
362 * TranslateMessage (USER.113)
364 BOOL
TranslateMessage( LPMSG msg
)
366 int message
= msg
->message
;
368 if ((message
== WM_KEYDOWN
) || (message
== WM_KEYUP
) ||
369 (message
== WM_SYSKEYDOWN
) || (message
== WM_SYSKEYUP
))
372 printf( "Translating key message\n" );
380 /***********************************************************************
381 * DispatchMessage (USER.114)
383 LONG
DispatchMessage( LPMSG msg
)
386 WND
* wndPtr
= WIN_FindWndPtr( msg
->hwnd
);
389 printf( "Dispatch message hwnd=%08x msg=%d w=%d l=%d time=%u pt=%d,%d\n",
390 msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
,
391 msg
->time
, msg
->pt
.x
, msg
->pt
.y
);
395 retval
= CallWindowProc(wndPtr
->lpfnWndProc
, msg
->hwnd
, msg
->message
,
396 msg
->wParam
, msg
->lParam
);
397 GlobalUnlock( msg
->hwnd
);
403 /***********************************************************************
404 * GetMessagePos (USER.119)
406 DWORD
GetMessagePos(void)
408 return msgQueue
->GetMessagePosVal
;
412 /***********************************************************************
413 * GetMessageTime (USER.120)
415 LONG
GetMessageTime(void)
417 return msgQueue
->GetMessageTimeVal
;
420 /***********************************************************************
421 * GetMessageExtraInfo (USER.288)
423 LONG
GetMessageExtraInfo(void)
425 return msgQueue
->GetMessageExtraInfoVal
;