Release 960521
[wine.git] / windows / queue.c
blob5935bac6efab69325941e43870941b921da3d291
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 HQUEUE hDoomedQueue = 0;
19 static MESSAGEQUEUE *sysMsgQueue = NULL;
21 /***********************************************************************
22 * QUEUE_GetDoomedQueue/QUEUE_SetDoomedQueue
24 HQUEUE QUEUE_GetDoomedQueue()
26 return hDoomedQueue;
28 void QUEUE_SetDoomedQueue(HQUEUE hQueue)
30 hDoomedQueue = hQueue;
33 /***********************************************************************
34 * QUEUE_DumpQueue
36 void QUEUE_DumpQueue( HQUEUE hQueue )
38 MESSAGEQUEUE *pq;
40 if (!(pq = (MESSAGEQUEUE*) GlobalLock16( hQueue )) ||
41 GlobalSize16(hQueue) < sizeof(MESSAGEQUEUE)+pq->queueSize*sizeof(QMSG))
43 fprintf( stderr, "%04x is not a queue handle\n", hQueue );
44 return;
47 fprintf( stderr,
48 "next: %12.4x Intertask SendMessage:\n"
49 "hTask: %11.4x ----------------------\n"
50 "msgSize: %9.4x hWnd: %10.4x\n"
51 "msgCount: %8.4x msg: %11.4x\n"
52 "msgNext: %9.4x wParam: %8.4x\n"
53 "msgFree: %9.4x lParam: %8.8x\n"
54 "qSize: %11.4x lRet: %10.8x\n"
55 "wWinVer: %9.4x ISMH: %10.4x\n"
56 "paints: %10.4x hSendTask: %5.4x\n"
57 "timers: %10.4x hPrevSend: %5.4x\n"
58 "wakeBits: %8.4x\n"
59 "wakeMask: %8.4x\n"
60 "hCurHook: %8.4x\n",
61 pq->next, pq->hTask, pq->msgSize, pq->hWnd,
62 pq->msgCount, pq->msg, pq->nextMessage, pq->wParam,
63 pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize,
64 (unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle,
65 pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
66 pq->hPrevSendingTask, pq->status, pq->wakeMask, pq->hCurHook);
70 /***********************************************************************
71 * QUEUE_WalkQueues
73 void QUEUE_WalkQueues(void)
75 HQUEUE hQueue = hFirstQueue;
77 fprintf( stderr, "Queue Size Msgs Task\n" );
78 while (hQueue)
80 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
81 if (!queue)
83 fprintf( stderr, "*** Bad queue handle %04x\n", hQueue );
84 return;
86 fprintf( stderr, "%04x %5d %4d %04x %s\n",
87 hQueue, queue->msgSize, queue->msgCount, queue->hTask,
88 MODULE_GetModuleName( GetExePtr(queue->hTask) ) );
89 hQueue = queue->next;
91 fprintf( stderr, "\n" );
95 /***********************************************************************
96 * QUEUE_CreateMsgQueue
98 * Creates a message queue. Doesn't link it into queue list!
100 static HQUEUE QUEUE_CreateMsgQueue( int size )
102 HQUEUE hQueue;
103 MESSAGEQUEUE * msgQueue;
104 int queueSize;
106 dprintf_msg(stddeb,"Creating message queue...\n");
108 queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
109 if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
110 return 0;
111 msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
112 msgQueue->msgSize = sizeof(QMSG);
113 msgQueue->queueSize = size;
114 msgQueue->wWinVersion = 0; /* FIXME? */
115 GlobalUnlock16( hQueue );
116 return hQueue;
120 /***********************************************************************
121 * QUEUE_DeleteMsgQueue
123 * Unlinks and deletes a message queue.
125 BOOL QUEUE_DeleteMsgQueue( HQUEUE hQueue )
127 MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)GlobalLock16(hQueue);
128 HQUEUE *pPrev;
130 dprintf_msg(stddeb,"Deleting message queue %04x\n", hQueue);
132 if (!hQueue || !msgQueue)
134 dprintf_msg(stddeb,"DeleteMsgQueue: invalid argument.\n");
135 return 0;
138 pPrev = &hFirstQueue;
139 while (*pPrev && (*pPrev != hQueue))
141 MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock16(*pPrev);
142 pPrev = &msgQ->next;
144 if (*pPrev) *pPrev = msgQueue->next;
145 GlobalFree16( hQueue );
146 return 1;
150 /***********************************************************************
151 * QUEUE_CreateSysMsgQueue
153 * Create the system message queue, and set the double-click speed.
154 * Must be called only once.
156 BOOL QUEUE_CreateSysMsgQueue( int size )
158 if (size > MAX_QUEUE_SIZE) size = MAX_QUEUE_SIZE;
159 else if (size <= 0) size = 1;
160 if (!(hmemSysMsgQueue = QUEUE_CreateMsgQueue( size ))) return FALSE;
161 sysMsgQueue = (MESSAGEQUEUE *) GlobalLock16( hmemSysMsgQueue );
162 return TRUE;
166 /***********************************************************************
167 * QUEUE_GetSysQueue
169 MESSAGEQUEUE *QUEUE_GetSysQueue(void)
171 return sysMsgQueue;
175 /***********************************************************************
176 * QUEUE_AddMsg
178 * Add a message to the queue. Return FALSE if queue is full.
180 BOOL QUEUE_AddMsg( HQUEUE hQueue, MSG * msg, DWORD extraInfo )
182 int pos;
183 MESSAGEQUEUE *msgQueue;
185 if (!(msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return FALSE;
186 pos = msgQueue->nextFreeMessage;
188 /* Check if queue is full */
189 if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
191 fprintf(stderr,"MSG_AddMsg // queue is full !\n");
192 return FALSE;
195 /* Store message */
196 msgQueue->messages[pos].msg = *msg;
197 msgQueue->messages[pos].extraInfo = extraInfo;
198 if (pos < msgQueue->queueSize-1) pos++;
199 else pos = 0;
200 msgQueue->nextFreeMessage = pos;
201 msgQueue->msgCount++;
202 msgQueue->status |= QS_POSTMESSAGE;
203 msgQueue->tempStatus |= QS_POSTMESSAGE;
204 return TRUE;
208 /***********************************************************************
209 * QUEUE_FindMsg
211 * Find a message matching the given parameters. Return -1 if none available.
213 int QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND hwnd, int first, int last )
215 int i, pos = msgQueue->nextMessage;
217 dprintf_msg(stddeb,"QUEUE_FindMsg: hwnd=%04x pos=%d\n", hwnd, pos );
219 if (!msgQueue->msgCount) return -1;
220 if (!hwnd && !first && !last) return pos;
222 for (i = 0; i < msgQueue->msgCount; i++)
224 MSG * msg = &msgQueue->messages[pos].msg;
226 if (!hwnd || (msg->hwnd == hwnd))
228 if (!first && !last) return pos;
229 if ((msg->message >= first) && (msg->message <= last)) return pos;
231 if (pos < msgQueue->queueSize-1) pos++;
232 else pos = 0;
234 return -1;
238 /***********************************************************************
239 * QUEUE_RemoveMsg
241 * Remove a message from the queue (pos must be a valid position).
243 void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
245 if (pos >= msgQueue->nextMessage)
247 for ( ; pos > msgQueue->nextMessage; pos--)
248 msgQueue->messages[pos] = msgQueue->messages[pos-1];
249 msgQueue->nextMessage++;
250 if (msgQueue->nextMessage >= msgQueue->queueSize)
251 msgQueue->nextMessage = 0;
253 else
255 for ( ; pos < msgQueue->nextFreeMessage; pos++)
256 msgQueue->messages[pos] = msgQueue->messages[pos+1];
257 if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
258 else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
260 msgQueue->msgCount--;
261 if (!msgQueue->msgCount) msgQueue->status &= ~QS_POSTMESSAGE;
262 msgQueue->tempStatus = 0;
266 /***********************************************************************
267 * hardware_event
269 * Add an event to the system message queue.
270 * Note: the position is relative to the desktop window.
272 void hardware_event( WORD message, WORD wParam, LONG lParam,
273 int xPos, int yPos, DWORD time, DWORD extraInfo )
275 MSG *msg;
276 int pos;
278 if (!sysMsgQueue) return;
279 pos = sysMsgQueue->nextFreeMessage;
281 /* Merge with previous event if possible */
283 if ((message == WM_MOUSEMOVE) && sysMsgQueue->msgCount)
285 if (pos > 0) pos--;
286 else pos = sysMsgQueue->queueSize - 1;
287 msg = &sysMsgQueue->messages[pos].msg;
288 if ((msg->message == message) && (msg->wParam == wParam))
289 sysMsgQueue->msgCount--; /* Merge events */
290 else
291 pos = sysMsgQueue->nextFreeMessage; /* Don't merge */
294 /* Check if queue is full */
296 if ((pos == sysMsgQueue->nextMessage) && sysMsgQueue->msgCount)
298 /* Queue is full, beep (but not on every mouse motion...) */
299 if (message != WM_MOUSEMOVE) MessageBeep(0);
300 return;
303 /* Store message */
305 msg = &sysMsgQueue->messages[pos].msg;
306 msg->hwnd = 0;
307 msg->message = message;
308 msg->wParam = wParam;
309 msg->lParam = lParam;
310 msg->time = time;
311 msg->pt.x = xPos & 0xffff;
312 msg->pt.y = yPos & 0xffff;
313 sysMsgQueue->messages[pos].extraInfo = extraInfo;
314 if (pos < sysMsgQueue->queueSize - 1) pos++;
315 else pos = 0;
316 sysMsgQueue->nextFreeMessage = pos;
317 sysMsgQueue->msgCount++;
321 /***********************************************************************
322 * QUEUE_GetQueueTask
324 HTASK QUEUE_GetQueueTask( HQUEUE hQueue )
326 MESSAGEQUEUE *queue = GlobalLock16( hQueue );
327 return (queue) ? queue->hTask : 0 ;
331 /***********************************************************************
332 * QUEUE_IncPaintCount
334 void QUEUE_IncPaintCount( HQUEUE hQueue )
336 MESSAGEQUEUE *queue;
338 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
339 queue->wPaintCount++;
340 queue->status |= QS_PAINT;
341 queue->tempStatus |= QS_PAINT;
345 /***********************************************************************
346 * QUEUE_DecPaintCount
348 void QUEUE_DecPaintCount( HQUEUE hQueue )
350 MESSAGEQUEUE *queue;
352 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
353 queue->wPaintCount--;
354 if (!queue->wPaintCount) queue->status &= ~QS_PAINT;
358 /***********************************************************************
359 * QUEUE_IncTimerCount
361 void QUEUE_IncTimerCount( HQUEUE hQueue )
363 MESSAGEQUEUE *queue;
365 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
366 queue->wTimerCount++;
367 queue->status |= QS_TIMER;
368 queue->tempStatus |= QS_TIMER;
372 /***********************************************************************
373 * QUEUE_DecTimerCount
375 void QUEUE_DecTimerCount( HQUEUE hQueue )
377 MESSAGEQUEUE *queue;
379 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
380 queue->wTimerCount--;
381 if (!queue->wTimerCount) queue->status &= ~QS_TIMER;
385 /***********************************************************************
386 * PostQuitMessage (USER.6)
388 void PostQuitMessage( INT exitCode )
390 MESSAGEQUEUE *queue;
392 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
393 queue->wPostQMsg = TRUE;
394 queue->wExitCode = (WORD)exitCode;
398 /***********************************************************************
399 * GetWindowTask (USER.224)
401 HTASK GetWindowTask( HWND hwnd )
403 WND *wndPtr = WIN_FindWndPtr( hwnd );
405 if (!wndPtr) return 0;
406 return QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
410 /***********************************************************************
411 * SetMessageQueue (USER.266)
413 BOOL SetMessageQueue( int size )
415 HQUEUE hQueue, hNewQueue;
416 MESSAGEQUEUE *queuePtr;
418 dprintf_msg(stddeb,"SetMessageQueue: task %04x size %i\n", GetCurrentTask(), size);
420 if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
422 if( !(hNewQueue = QUEUE_CreateMsgQueue( size )))
424 dprintf_msg(stddeb,"SetMessageQueue: failed!\n");
425 return FALSE;
428 /* Free the old message queue */
429 if ((hQueue = GetTaskQueue(0)) != 0) QUEUE_DeleteMsgQueue( hQueue );
431 /* Link new queue into list */
432 queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
433 queuePtr->hTask = GetCurrentTask();
434 queuePtr->next = hFirstQueue;
435 hFirstQueue = hNewQueue;
437 SetTaskQueue( 0, hNewQueue );
438 return TRUE;
442 /***********************************************************************
443 * GetQueueStatus (USER.334)
445 DWORD GetQueueStatus( UINT flags )
447 MESSAGEQUEUE *queue;
448 DWORD ret;
450 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
451 ret = MAKELONG( queue->tempStatus, queue->status );
452 queue->tempStatus = 0;
453 return ret & MAKELONG( flags, flags );
457 /***********************************************************************
458 * GetInputState (USER.335)
460 BOOL GetInputState()
462 MESSAGEQUEUE *queue;
464 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return FALSE;
465 return queue->status & (QS_KEY | QS_MOUSEBUTTON);
469 /***********************************************************************
470 * GetMessagePos (USER.119)
472 DWORD GetMessagePos(void)
474 MESSAGEQUEUE *queue;
476 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
477 return queue->GetMessagePosVal;
481 /***********************************************************************
482 * GetMessageTime (USER.120)
484 LONG GetMessageTime(void)
486 MESSAGEQUEUE *queue;
488 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
489 return queue->GetMessageTimeVal;
493 /***********************************************************************
494 * GetMessageExtraInfo (USER.288)
496 LONG GetMessageExtraInfo(void)
498 MESSAGEQUEUE *queue;
500 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
501 return queue->GetMessageExtraInfoVal;