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";
24 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
26 extern HWND WIN_FindWinToRepaint( HWND hwnd );
28 extern Display * XT_display;
29 extern Screen * XT_screen;
30 extern XtAppContext XT_app_context;
32 static MESSAGEQUEUE * msgQueue = NULL;
35 /***********************************************************************
39 int MSG_GetMessageType( int msg )
41 if ((msg >= WM_KEYFIRST) && (msg <= WM_KEYLAST)) return QS_KEY;
42 else if ((msg >= WM_MOUSEFIRST) && (msg <= WM_MOUSELAST))
44 if (msg == WM_MOUSEMOVE) return QS_MOUSEMOVE;
45 else return QS_MOUSEBUTTON;
47 else if (msg == WM_PAINT) return QS_PAINT;
48 else if (msg == WM_TIMER) return QS_TIMER;
49 return QS_POSTMESSAGE;
53 /***********************************************************************
56 * Add a message to the queue. Return FALSE if queue is full.
58 int MSG_AddMsg( MSG * msg, DWORD extraInfo )
62 if (!msgQueue) return FALSE;
63 pos = msgQueue->nextFreeMessage;
65 /* No need to store WM_PAINT messages */
66 if (msg->message == WM_PAINT) return TRUE;
68 /* Check if queue is full */
69 if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
73 msgQueue->messages[pos].msg = *msg;
74 msgQueue->messages[pos].extraInfo = extraInfo;
76 /* Store message type */
77 type = MSG_GetMessageType( msg->message );
78 msgQueue->status |= type;
79 msgQueue->tempStatus |= type;
81 if (pos < msgQueue->queueSize-1) pos++;
83 msgQueue->nextFreeMessage = pos;
90 /***********************************************************************
93 * Find a message matching the given parameters. Return -1 if none available.
95 int MSG_FindMsg( HWND hwnd, int first, int last )
97 int i, pos = msgQueue->nextMessage;
99 if (!msgQueue->msgCount) return -1;
100 if (!hwnd && !first && !last) return pos;
102 for (i = 0; i < msgQueue->msgCount; i++)
104 MSG * msg = &msgQueue->messages[pos].msg;
106 if (!hwnd || (msg->hwnd == hwnd))
108 if (!first && !last) return pos;
109 if ((msg->message >= first) && (msg->message <= last)) return pos;
111 if (pos < msgQueue->queueSize-1) pos++;
118 /***********************************************************************
121 * Remove a message from the queue (pos must be a valid position).
123 void MSG_RemoveMsg( int pos )
128 if (!msgQueue) return;
129 qmsg = &msgQueue->messages[pos];
131 if (pos >= msgQueue->nextMessage)
133 int count = pos - msgQueue->nextMessage;
134 if (count) memmove( &msgQueue->messages[msgQueue->nextMessage+1],
135 &msgQueue->messages[msgQueue->nextMessage],
136 count * sizeof(QMSG) );
137 msgQueue->nextMessage++;
138 if (msgQueue->nextMessage >= msgQueue->queueSize)
139 msgQueue->nextMessage = 0;
143 int count = msgQueue->nextFreeMessage - pos;
144 if (count) memmove( &msgQueue->messages[pos],
145 &msgQueue->messages[pos+1], count * sizeof(QMSG) );
146 if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
147 else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
149 msgQueue->msgCount--;
153 pos = msgQueue->nextMessage;
154 for (i = 0; i < msgQueue->msgCount; i++)
156 type |= MSG_GetMessageType( msgQueue->messages[pos].msg.message );
157 if (++pos >= msgQueue->queueSize-1) pos = 0;
159 msgQueue->status = (msgQueue->status & QS_SENDMESSAGE) | type;
160 msgQueue->tempStatus = 0;
164 /***********************************************************************
165 * SetMessageQueue (USER.266)
167 BOOL SetMessageQueue( int size )
171 /* Free the old message queue */
172 if (msgQueue) free(msgQueue);
174 if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return FALSE;
176 queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
177 msgQueue = (MESSAGEQUEUE *) malloc(queueSize);
178 if (!msgQueue) return FALSE;
182 msgQueue->msgSize = sizeof(QMSG);
183 msgQueue->msgCount = 0;
184 msgQueue->nextMessage = 0;
185 msgQueue->nextFreeMessage = 0;
186 msgQueue->queueSize = size;
187 msgQueue->GetMessageTimeVal = 0;
188 msgQueue->GetMessagePosVal = 0;
189 msgQueue->GetMessageExtraInfoVal = 0;
190 msgQueue->lParam = 0;
191 msgQueue->wParam = 0;
194 msgQueue->wPostQMsg = 0;
195 msgQueue->wExitCode = 0;
196 msgQueue->InSendMessageHandle = 0;
197 msgQueue->tempStatus = 0;
198 msgQueue->status = 0;
204 /***********************************************************************
205 * PostQuitMessage (USER.6)
207 void PostQuitMessage( int exitCode )
209 if (!msgQueue) return;
210 msgQueue->wPostQMsg = TRUE;
211 msgQueue->wExitCode = exitCode;
215 /***********************************************************************
216 * GetQueueStatus (USER.334)
218 DWORD GetQueueStatus( int flags )
220 unsigned long ret = (msgQueue->status << 16) | msgQueue->tempStatus;
221 if (flags & QS_PAINT)
223 if (WIN_FindWinToRepaint(0)) ret |= QS_PAINT | (QS_PAINT << 16);
225 msgQueue->tempStatus = 0;
226 return ret & ((flags << 16) | flags);
230 /***********************************************************************
231 * GetInputState (USER.335)
235 return msgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
239 /***********************************************************************
242 BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
246 /* First handle a WM_QUIT message */
247 if (msgQueue->wPostQMsg)
250 msg->message = WM_QUIT;
251 msg->wParam = msgQueue->wExitCode;
256 /* Then handle a message put by SendMessage() */
257 if (msgQueue->status & QS_SENDMESSAGE)
259 if (!hwnd || (msgQueue->hWnd == hwnd))
261 if ((!first && !last) ||
262 ((msgQueue->msg >= first) && (msgQueue->msg <= last)))
264 msg->hwnd = msgQueue->hWnd;
265 msg->message = msgQueue->msg;
266 msg->wParam = msgQueue->wParam;
267 msg->lParam = msgQueue->lParam;
268 if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
275 /* Now find a normal message */
276 pos = MSG_FindMsg( hwnd, first, last );
279 QMSG *qmsg = &msgQueue->messages[pos];
281 msgQueue->GetMessageTimeVal = msg->time;
282 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
283 msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
285 if (flags & PM_REMOVE) MSG_RemoveMsg(pos);
289 /* If nothing else, return a WM_PAINT message */
290 if ((!first && !last) || ((first <= WM_PAINT) && (last >= WM_PAINT)))
292 msg->hwnd = WIN_FindWinToRepaint( hwnd );
293 msg->message = WM_PAINT;
296 return (msg->hwnd != 0);
302 /***********************************************************************
303 * PeekMessage (USER.109)
305 BOOL PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
307 while (XtAppPending( XT_app_context ))
308 XtAppProcessEvent( XT_app_context, XtIMAll );
310 return MSG_PeekMessage( msg, hwnd, first, last, flags );
314 /***********************************************************************
315 * GetMessage (USER.108)
317 BOOL GetMessage( LPMSG msg, HWND hwnd, WORD first, WORD last )
321 if (MSG_PeekMessage( msg, hwnd, first, last, PM_REMOVE )) break;
322 XtAppProcessEvent( XT_app_context, XtIMAll );
325 return (msg->message != WM_QUIT);
329 /***********************************************************************
330 * PostMessage (USER.110)
332 BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
337 msg.message = message;
340 msg.time = GetTickCount();
344 return MSG_AddMsg( &msg, 0 );
348 /***********************************************************************
349 * SendMessage (USER.111)
351 LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
353 WND * wndPtr = WIN_FindWndPtr( hwnd );
354 if (!wndPtr) return 0;
355 return CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg, wParam, lParam );
359 /***********************************************************************
360 * TranslateMessage (USER.113)
362 BOOL TranslateMessage( LPMSG msg )
364 int message = msg->message;
366 if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
367 (message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
370 printf( "Translating key message\n" );
378 /***********************************************************************
379 * DispatchMessage (USER.114)
381 LONG DispatchMessage( LPMSG msg )
383 WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
386 printf( "Dispatch message hwnd=%08x msg=%d w=%d l=%d time=%u pt=%d,%d\n",
387 msg->hwnd, msg->message, msg->wParam, msg->lParam,
388 msg->time, msg->pt.x, msg->pt.y );
390 if (!wndPtr) return 0;
391 return CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message,
392 msg->wParam, msg->lParam );
396 /***********************************************************************
397 * GetMessagePos (USER.119)
399 DWORD GetMessagePos(void)
401 return msgQueue->GetMessagePosVal;
405 /***********************************************************************
406 * GetMessageTime (USER.120)
408 LONG GetMessageTime(void)
410 return msgQueue->GetMessageTimeVal;
413 /***********************************************************************
414 * GetMessageExtraInfo (USER.288)
416 LONG GetMessageExtraInfo(void)
418 return msgQueue->GetMessageExtraInfoVal;