Release 0.3.0
[wine/multimedia.git] / windows / message.c
blob45cca4a1013b97c466123abb678b9c9f7fd2e5e4
1 /*
2 * Message queues related functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 /*
8 * This code assumes that there is only one Windows task (hence
9 * one message queue).
12 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
14 #include <stdlib.h>
16 #include "message.h"
17 #include "win.h"
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 /***********************************************************************
32 * MSG_GetMessageType
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 /***********************************************************************
50 * MSG_AddMsg
52 * Add a message to the queue. Return FALSE if queue is full.
54 int MSG_AddMsg( MSG * msg, DWORD extraInfo )
56 int pos, type;
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))
66 return FALSE;
68 /* Store message */
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++;
78 else pos = 0;
79 msgQueue->nextFreeMessage = pos;
80 msgQueue->msgCount++;
82 return TRUE;
86 /***********************************************************************
87 * MSG_FindMsg
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++;
108 else pos = 0;
110 return -1;
114 /***********************************************************************
115 * MSG_RemoveMsg
117 * Remove a message from the queue (pos must be a valid position).
119 void MSG_RemoveMsg( int pos )
121 int i, type;
122 QMSG * qmsg;
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;
137 else
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--;
147 /* Recalc status */
148 type = 0;
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 )
165 int queueSize;
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;
176 msgQueue->next = 0;
177 msgQueue->hTask = 0;
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;
188 msgQueue->msg = 0;
189 msgQueue->hWnd = 0;
190 msgQueue->wPostQMsg = 0;
191 msgQueue->wExitCode = 0;
192 msgQueue->InSendMessageHandle = 0;
193 msgQueue->tempStatus = 0;
194 msgQueue->status = 0;
196 return TRUE;
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)
229 BOOL GetInputState()
231 return msgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
235 /***********************************************************************
236 * MSG_PeekMessage
238 BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
240 int pos;
242 /* First handle a WM_QUIT message */
243 if (msgQueue->wPostQMsg)
245 msg->hwnd = hwnd;
246 msg->message = WM_QUIT;
247 msg->wParam = msgQueue->wExitCode;
248 msg->lParam = 0;
249 return TRUE;
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;
265 return TRUE;
271 /* Now find a normal message */
272 pos = MSG_FindMsg( hwnd, first, last );
273 if (pos != -1)
275 QMSG *qmsg = &msgQueue->messages[pos];
276 *msg = qmsg->msg;
277 msgQueue->GetMessageTimeVal = msg->time;
278 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
279 msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
281 if (flags & PM_REMOVE) MSG_RemoveMsg(pos);
282 return TRUE;
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;
290 msg->wParam = 0;
291 msg->lParam = 0;
292 return (msg->hwnd != 0);
294 return FALSE;
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 )
315 while(1)
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 )
330 MSG msg;
332 msg.hwnd = hwnd;
333 msg.message = message;
334 msg.wParam = wParam;
335 msg.lParam = lParam;
336 msg.time = GetTickCount();
337 msg.pt.x = 0;
338 msg.pt.y = 0;
340 return MSG_AddMsg( &msg, 0 );
344 /***********************************************************************
345 * SendMessage (USER.111)
347 LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
349 LONG retval = 0;
350 WND * wndPtr = WIN_FindWndPtr( hwnd );
351 if (wndPtr)
353 retval = CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg,
354 wParam, lParam );
355 GlobalUnlock( hwnd );
357 return retval;
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))
371 #ifdef DEBUG_MSG
372 printf( "Translating key message\n" );
373 #endif
374 return TRUE;
376 return FALSE;
380 /***********************************************************************
381 * DispatchMessage (USER.114)
383 LONG DispatchMessage( LPMSG msg )
385 LONG retval = 0;
386 WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
388 #ifdef DEBUG_MSG
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 );
392 #endif
393 if (wndPtr)
395 retval = CallWindowProc(wndPtr->lpfnWndProc, msg->hwnd, msg->message,
396 msg->wParam, msg->lParam );
397 GlobalUnlock( msg->hwnd );
399 return retval;
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;