Release 960314
[wine/multimedia.git] / windows / queue.c
blob1d0028a4120b3b67f67dfe532809f864dd1fa2c0
1 /*
2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include "module.h"
9 #include "queue.h"
10 #include "win.h"
11 #include "stddebug.h"
12 #include "debug.h"
14 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
16 static HQUEUE hFirstQueue = 0;
17 static HQUEUE hmemSysMsgQueue = 0;
18 static MESSAGEQUEUE *sysMsgQueue = NULL;
21 /***********************************************************************
22 * QUEUE_DumpQueue
24 void QUEUE_DumpQueue( HQUEUE hQueue )
26 MESSAGEQUEUE *pq;
28 if (!(pq = (MESSAGEQUEUE*) GlobalLock( hQueue )) ||
29 GlobalSize(hQueue) < sizeof(MESSAGEQUEUE) + pq->queueSize*sizeof(QMSG))
31 fprintf( stderr, NPFMT " is not a queue handle\n", hQueue );
32 return;
35 fprintf( stderr,
36 "next: %12.4x Intertask SendMessage:\n"
37 "hTask: %11.4x ----------------------\n"
38 "msgSize: %9.4x hWnd: %10.4x\n"
39 "msgCount: %8.4x msg: %11.4x\n"
40 "msgNext: %9.4x wParam: %8.4x\n"
41 "msgFree: %9.4x lParam: %8.8x\n"
42 "qSize: %11.4x lRet: %10.8x\n"
43 "wWinVer: %9.4x ISMH: %10.4x\n"
44 "paints: %10.4x hSendTask: %5.4x\n"
45 "timers: %10.4x hPrevSend: %5.4x\n"
46 "wakeBits: %8.4x\n"
47 "wakeMask: %8.4x\n"
48 "hCurHook: %8.4x\n",
49 pq->next, pq->hTask, pq->msgSize, pq->hWnd,
50 pq->msgCount, pq->msg, pq->nextMessage, pq->wParam,
51 pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize,
52 (unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle,
53 pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
54 pq->hPrevSendingTask, pq->status, pq->wakeMask, pq->hCurHook);
58 /***********************************************************************
59 * QUEUE_WalkQueues
61 void QUEUE_WalkQueues(void)
63 HQUEUE hQueue = hFirstQueue;
65 fprintf( stderr, "Queue Size Msgs Task\n" );
66 while (hQueue)
68 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock( hQueue );
69 if (!queue)
71 fprintf( stderr, "*** Bad queue handle "NPFMT"\n", hQueue );
72 return;
74 fprintf( stderr, "%04x %5d %4d %04x %s\n",
75 hQueue, queue->msgSize, queue->msgCount, queue->hTask,
76 MODULE_GetModuleName( GetExePtr(queue->hTask) ) );
77 hQueue = queue->next;
79 fprintf( stderr, "\n" );
83 /***********************************************************************
84 * QUEUE_CreateMsgQueue
86 * Creates a message queue. Doesn't link it into queue list!
88 static HQUEUE QUEUE_CreateMsgQueue( int size )
90 HQUEUE hQueue;
91 MESSAGEQUEUE * msgQueue;
92 int queueSize;
94 queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
95 if (!(hQueue = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
96 return 0;
97 msgQueue = (MESSAGEQUEUE *) GlobalLock( hQueue );
98 msgQueue->msgSize = sizeof(QMSG);
99 msgQueue->queueSize = size;
100 msgQueue->wWinVersion = 0; /* FIXME? */
101 GlobalUnlock( hQueue );
102 return hQueue;
106 /***********************************************************************
107 * QUEUE_DeleteMsgQueue
109 * Unlinks and deletes a message queue.
111 BOOL QUEUE_DeleteMsgQueue( HQUEUE hQueue )
113 MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)GlobalLock(hQueue);
114 HQUEUE *pPrev;
116 if (!hQueue || !msgQueue)
118 dprintf_msg(stddeb,"DeleteMsgQueue: invalid argument.\n");
119 return 0;
122 pPrev = &hFirstQueue;
123 while (*pPrev && (*pPrev != hQueue))
125 MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock(*pPrev);
126 pPrev = &msgQ->next;
128 if (*pPrev) *pPrev = msgQueue->next;
129 GlobalFree( hQueue );
130 return 1;
134 /***********************************************************************
135 * QUEUE_CreateSysMsgQueue
137 * Create the system message queue, and set the double-click speed.
138 * Must be called only once.
140 BOOL QUEUE_CreateSysMsgQueue( int size )
142 if (size > MAX_QUEUE_SIZE) size = MAX_QUEUE_SIZE;
143 else if (size <= 0) size = 1;
144 if (!(hmemSysMsgQueue = QUEUE_CreateMsgQueue( size ))) return FALSE;
145 sysMsgQueue = (MESSAGEQUEUE *) GlobalLock( hmemSysMsgQueue );
146 return TRUE;
150 /***********************************************************************
151 * QUEUE_GetSysQueue
153 MESSAGEQUEUE *QUEUE_GetSysQueue(void)
155 return sysMsgQueue;
159 /***********************************************************************
160 * QUEUE_AddMsg
162 * Add a message to the queue. Return FALSE if queue is full.
164 BOOL QUEUE_AddMsg( HQUEUE hQueue, MSG * msg, DWORD extraInfo )
166 int pos;
167 MESSAGEQUEUE *msgQueue;
169 if (!(msgQueue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return FALSE;
170 pos = msgQueue->nextFreeMessage;
172 /* Check if queue is full */
173 if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
175 fprintf(stderr,"MSG_AddMsg // queue is full !\n");
176 return FALSE;
179 /* Store message */
180 msgQueue->messages[pos].msg = *msg;
181 msgQueue->messages[pos].extraInfo = extraInfo;
182 if (pos < msgQueue->queueSize-1) pos++;
183 else pos = 0;
184 msgQueue->nextFreeMessage = pos;
185 msgQueue->msgCount++;
186 msgQueue->status |= QS_POSTMESSAGE;
187 msgQueue->tempStatus |= QS_POSTMESSAGE;
188 return TRUE;
192 /***********************************************************************
193 * QUEUE_FindMsg
195 * Find a message matching the given parameters. Return -1 if none available.
197 int QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND hwnd, int first, int last )
199 int i, pos = msgQueue->nextMessage;
201 dprintf_msg(stddeb,"MSG_FindMsg: hwnd=0x"NPFMT"\n\n", hwnd );
203 if (!msgQueue->msgCount) return -1;
204 if (!hwnd && !first && !last) return pos;
206 for (i = 0; i < msgQueue->msgCount; i++)
208 MSG * msg = &msgQueue->messages[pos].msg;
210 if (!hwnd || (msg->hwnd == hwnd))
212 if (!first && !last) return pos;
213 if ((msg->message >= first) && (msg->message <= last)) return pos;
215 if (pos < msgQueue->queueSize-1) pos++;
216 else pos = 0;
218 return -1;
222 /***********************************************************************
223 * QUEUE_RemoveMsg
225 * Remove a message from the queue (pos must be a valid position).
227 void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
229 if (pos >= msgQueue->nextMessage)
231 for ( ; pos > msgQueue->nextMessage; pos--)
232 msgQueue->messages[pos] = msgQueue->messages[pos-1];
233 msgQueue->nextMessage++;
234 if (msgQueue->nextMessage >= msgQueue->queueSize)
235 msgQueue->nextMessage = 0;
237 else
239 for ( ; pos < msgQueue->nextFreeMessage; pos++)
240 msgQueue->messages[pos] = msgQueue->messages[pos+1];
241 if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
242 else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
244 msgQueue->msgCount--;
245 if (!msgQueue->msgCount) msgQueue->status &= ~QS_POSTMESSAGE;
246 msgQueue->tempStatus = 0;
250 /***********************************************************************
251 * hardware_event
253 * Add an event to the system message queue.
254 * Note: the position is relative to the desktop window.
256 void hardware_event( WORD message, WORD wParam, LONG lParam,
257 int xPos, int yPos, DWORD time, DWORD extraInfo )
259 MSG *msg;
260 int pos;
262 if (!sysMsgQueue) return;
263 pos = sysMsgQueue->nextFreeMessage;
265 /* Merge with previous event if possible */
267 if ((message == WM_MOUSEMOVE) && sysMsgQueue->msgCount)
269 if (pos > 0) pos--;
270 else pos = sysMsgQueue->queueSize - 1;
271 msg = &sysMsgQueue->messages[pos].msg;
272 if ((msg->message == message) && (msg->wParam == wParam))
273 sysMsgQueue->msgCount--; /* Merge events */
274 else
275 pos = sysMsgQueue->nextFreeMessage; /* Don't merge */
278 /* Check if queue is full */
280 if ((pos == sysMsgQueue->nextMessage) && sysMsgQueue->msgCount)
282 /* Queue is full, beep (but not on every mouse motion...) */
283 if (message != WM_MOUSEMOVE) MessageBeep(0);
284 return;
287 /* Store message */
289 msg = &sysMsgQueue->messages[pos].msg;
290 msg->hwnd = 0;
291 msg->message = message;
292 msg->wParam = wParam;
293 msg->lParam = lParam;
294 msg->time = time;
295 msg->pt.x = xPos & 0xffff;
296 msg->pt.y = yPos & 0xffff;
297 sysMsgQueue->messages[pos].extraInfo = extraInfo;
298 if (pos < sysMsgQueue->queueSize - 1) pos++;
299 else pos = 0;
300 sysMsgQueue->nextFreeMessage = pos;
301 sysMsgQueue->msgCount++;
305 /***********************************************************************
306 * QUEUE_GetQueueTask
308 HTASK QUEUE_GetQueueTask( HQUEUE hQueue )
310 MESSAGEQUEUE *queue = GlobalLock( hQueue );
311 return (queue) ? queue->hTask : 0 ;
315 /***********************************************************************
316 * QUEUE_IncPaintCount
318 void QUEUE_IncPaintCount( HQUEUE hQueue )
320 MESSAGEQUEUE *queue;
322 if (!(queue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return;
323 queue->wPaintCount++;
324 queue->status |= QS_PAINT;
325 queue->tempStatus |= QS_PAINT;
329 /***********************************************************************
330 * QUEUE_DecPaintCount
332 void QUEUE_DecPaintCount( HQUEUE hQueue )
334 MESSAGEQUEUE *queue;
336 if (!(queue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return;
337 queue->wPaintCount--;
338 if (!queue->wPaintCount) queue->status &= ~QS_PAINT;
342 /***********************************************************************
343 * QUEUE_IncTimerCount
345 void QUEUE_IncTimerCount( HQUEUE hQueue )
347 MESSAGEQUEUE *queue;
349 if (!(queue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return;
350 queue->wTimerCount++;
351 queue->status |= QS_TIMER;
352 queue->tempStatus |= QS_TIMER;
356 /***********************************************************************
357 * QUEUE_DecTimerCount
359 void QUEUE_DecTimerCount( HQUEUE hQueue )
361 MESSAGEQUEUE *queue;
363 if (!(queue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return;
364 queue->wTimerCount--;
365 if (!queue->wTimerCount) queue->status &= ~QS_TIMER;
369 /***********************************************************************
370 * PostQuitMessage (USER.6)
372 void PostQuitMessage( INT exitCode )
374 MESSAGEQUEUE *queue;
376 if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return;
377 queue->wPostQMsg = TRUE;
378 queue->wExitCode = (WORD)exitCode;
382 /***********************************************************************
383 * GetWindowTask (USER.224)
385 HTASK GetWindowTask( HWND hwnd )
387 WND *wndPtr = WIN_FindWndPtr( hwnd );
389 if (!wndPtr) return 0;
390 return QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
394 /***********************************************************************
395 * SetMessageQueue (USER.266)
397 BOOL SetMessageQueue( int size )
399 HQUEUE hQueue, hNewQueue;
400 MESSAGEQUEUE *queuePtr;
402 if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
404 if( !(hNewQueue = QUEUE_CreateMsgQueue( size )))
406 dprintf_msg(stddeb,"SetMessageQueue: failed!\n");
407 return FALSE;
410 /* Free the old message queue */
411 if ((hQueue = GetTaskQueue(0)) != 0) QUEUE_DeleteMsgQueue( hQueue );
413 /* Link new queue into list */
414 queuePtr = (MESSAGEQUEUE *)GlobalLock( hNewQueue );
415 queuePtr->hTask = GetCurrentTask();
416 queuePtr->next = hFirstQueue;
417 hFirstQueue = hNewQueue;
419 SetTaskQueue( 0, hNewQueue );
420 return TRUE;
424 /***********************************************************************
425 * GetQueueStatus (USER.334)
427 DWORD GetQueueStatus( UINT flags )
429 MESSAGEQUEUE *queue;
430 DWORD ret;
432 if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
433 ret = MAKELONG( queue->tempStatus, queue->status );
434 queue->tempStatus = 0;
435 return ret & MAKELONG( flags, flags );
439 /***********************************************************************
440 * GetInputState (USER.335)
442 BOOL GetInputState()
444 MESSAGEQUEUE *queue;
446 if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return FALSE;
447 return queue->status & (QS_KEY | QS_MOUSEBUTTON);
451 /***********************************************************************
452 * GetMessagePos (USER.119)
454 DWORD GetMessagePos(void)
456 MESSAGEQUEUE *queue;
458 if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
459 return queue->GetMessagePosVal;
463 /***********************************************************************
464 * GetMessageTime (USER.120)
466 LONG GetMessageTime(void)
468 MESSAGEQUEUE *queue;
470 if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
471 return queue->GetMessageTimeVal;
475 /***********************************************************************
476 * GetMessageExtraInfo (USER.288)
478 LONG GetMessageExtraInfo(void)
480 MESSAGEQUEUE *queue;
482 if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
483 return queue->GetMessageExtraInfoVal;