blob: a1288c5c54cdf34315a80b2f4742294ebd10c4cf [file] [log] [blame]
/*
* Message queues related functions
*
* Copyright 1993 Alexandre Julliard
*/
/*
* This code assumes that there is only one Windows task (hence
* one message queue).
*/
static char Copyright[] = "Copyright Alexandre Julliard, 1993";
#include <stdlib.h>
#ifdef __NetBSD__
#define HZ 100
#endif
#include "message.h"
#include "win.h"
#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
extern HWND WIN_FindWinToRepaint( HWND hwnd );
extern Display * XT_display;
extern Screen * XT_screen;
extern XtAppContext XT_app_context;
static MESSAGEQUEUE * msgQueue = NULL;
/***********************************************************************
* MSG_GetMessageType
*
*/
int MSG_GetMessageType( int msg )
{
if ((msg >= WM_KEYFIRST) && (msg <= WM_KEYLAST)) return QS_KEY;
else if ((msg >= WM_MOUSEFIRST) && (msg <= WM_MOUSELAST))
{
if (msg == WM_MOUSEMOVE) return QS_MOUSEMOVE;
else return QS_MOUSEBUTTON;
}
else if (msg == WM_PAINT) return QS_PAINT;
else if (msg == WM_TIMER) return QS_TIMER;
return QS_POSTMESSAGE;
}
/***********************************************************************
* MSG_AddMsg
*
* Add a message to the queue. Return FALSE if queue is full.
*/
int MSG_AddMsg( MSG * msg, DWORD extraInfo )
{
int pos, type;
if (!msgQueue) return FALSE;
pos = msgQueue->nextFreeMessage;
/* No need to store WM_PAINT messages */
if (msg->message == WM_PAINT) return TRUE;
/* Check if queue is full */
if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
return FALSE;
/* Store message */
msgQueue->messages[pos].msg = *msg;
msgQueue->messages[pos].extraInfo = extraInfo;
/* Store message type */
type = MSG_GetMessageType( msg->message );
msgQueue->status |= type;
msgQueue->tempStatus |= type;
if (pos < msgQueue->queueSize-1) pos++;
else pos = 0;
msgQueue->nextFreeMessage = pos;
msgQueue->msgCount++;
return TRUE;
}
/***********************************************************************
* MSG_FindMsg
*
* Find a message matching the given parameters. Return -1 if none available.
*/
int MSG_FindMsg( HWND hwnd, int first, int last )
{
int i, pos = msgQueue->nextMessage;
if (!msgQueue->msgCount) return -1;
if (!hwnd && !first && !last) return pos;
for (i = 0; i < msgQueue->msgCount; i++)
{
MSG * msg = &msgQueue->messages[pos].msg;
if (!hwnd || (msg->hwnd == hwnd))
{
if (!first && !last) return pos;
if ((msg->message >= first) && (msg->message <= last)) return pos;
}
if (pos < msgQueue->queueSize-1) pos++;
else pos = 0;
}
return -1;
}
/***********************************************************************
* MSG_RemoveMsg
*
* Remove a message from the queue (pos must be a valid position).
*/
void MSG_RemoveMsg( int pos )
{
int i, type;
QMSG * qmsg;
if (!msgQueue) return;
qmsg = &msgQueue->messages[pos];
if (pos >= msgQueue->nextMessage)
{
int count = pos - msgQueue->nextMessage;
if (count) memmove( &msgQueue->messages[msgQueue->nextMessage+1],
&msgQueue->messages[msgQueue->nextMessage],
count * sizeof(QMSG) );
msgQueue->nextMessage++;
if (msgQueue->nextMessage >= msgQueue->queueSize)
msgQueue->nextMessage = 0;
}
else
{
int count = msgQueue->nextFreeMessage - pos;
if (count) memmove( &msgQueue->messages[pos],
&msgQueue->messages[pos+1], count * sizeof(QMSG) );
if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
}
msgQueue->msgCount--;
/* Recalc status */
type = 0;
pos = msgQueue->nextMessage;
for (i = 0; i < msgQueue->msgCount; i++)
{
type |= MSG_GetMessageType( msgQueue->messages[pos].msg.message );
if (++pos >= msgQueue->queueSize-1) pos = 0;
}
msgQueue->status = (msgQueue->status & QS_SENDMESSAGE) | type;
msgQueue->tempStatus = 0;
}
/***********************************************************************
* SetMessageQueue (USER.266)
*/
BOOL SetMessageQueue( int size )
{
int queueSize;
/* Free the old message queue */
if (msgQueue) free(msgQueue);
if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return FALSE;
queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
msgQueue = (MESSAGEQUEUE *) malloc(queueSize);
if (!msgQueue) return FALSE;
msgQueue->next = 0;
msgQueue->hTask = 0;
msgQueue->msgSize = sizeof(QMSG);
msgQueue->msgCount = 0;
msgQueue->nextMessage = 0;
msgQueue->nextFreeMessage = 0;
msgQueue->queueSize = size;
msgQueue->GetMessageTimeVal = 0;
msgQueue->GetMessagePosVal = 0;
msgQueue->GetMessageExtraInfoVal = 0;
msgQueue->lParam = 0;
msgQueue->wParam = 0;
msgQueue->msg = 0;
msgQueue->hWnd = 0;
msgQueue->wPostQMsg = 0;
msgQueue->wExitCode = 0;
msgQueue->InSendMessageHandle = 0;
msgQueue->tempStatus = 0;
msgQueue->status = 0;
return TRUE;
}
/***********************************************************************
* PostQuitMessage (USER.6)
*/
void PostQuitMessage( int exitCode )
{
if (!msgQueue) return;
msgQueue->wPostQMsg = TRUE;
msgQueue->wExitCode = exitCode;
}
/***********************************************************************
* GetQueueStatus (USER.334)
*/
DWORD GetQueueStatus( int flags )
{
unsigned long ret = (msgQueue->status << 16) | msgQueue->tempStatus;
if (flags & QS_PAINT)
{
if (WIN_FindWinToRepaint(0)) ret |= QS_PAINT | (QS_PAINT << 16);
}
msgQueue->tempStatus = 0;
return ret & ((flags << 16) | flags);
}
/***********************************************************************
* GetInputState (USER.335)
*/
BOOL GetInputState()
{
return msgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
}
/***********************************************************************
* MSG_PeekMessage
*/
BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
{
int pos;
/* First handle a WM_QUIT message */
if (msgQueue->wPostQMsg)
{
msg->hwnd = hwnd;
msg->message = WM_QUIT;
msg->wParam = msgQueue->wExitCode;
msg->lParam = 0;
return TRUE;
}
/* Then handle a message put by SendMessage() */
if (msgQueue->status & QS_SENDMESSAGE)
{
if (!hwnd || (msgQueue->hWnd == hwnd))
{
if ((!first && !last) ||
((msgQueue->msg >= first) && (msgQueue->msg <= last)))
{
msg->hwnd = msgQueue->hWnd;
msg->message = msgQueue->msg;
msg->wParam = msgQueue->wParam;
msg->lParam = msgQueue->lParam;
if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
return TRUE;
}
}
}
/* Now find a normal message */
pos = MSG_FindMsg( hwnd, first, last );
if (pos != -1)
{
QMSG *qmsg = &msgQueue->messages[pos];
*msg = qmsg->msg;
msgQueue->GetMessageTimeVal = msg->time;
msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
if (flags & PM_REMOVE) MSG_RemoveMsg(pos);
return TRUE;
}
/* If nothing else, return a WM_PAINT message */
if ((!first && !last) || ((first <= WM_PAINT) && (last >= WM_PAINT)))
{
msg->hwnd = WIN_FindWinToRepaint( hwnd );
msg->message = WM_PAINT;
msg->wParam = 0;
msg->lParam = 0;
return (msg->hwnd != 0);
}
return FALSE;
}
/***********************************************************************
* PeekMessage (USER.109)
*/
BOOL PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
{
while (XtAppPending( XT_app_context ))
XtAppProcessEvent( XT_app_context, XtIMAll );
return MSG_PeekMessage( msg, hwnd, first, last, flags );
}
/***********************************************************************
* GetMessage (USER.108)
*/
BOOL GetMessage( LPMSG msg, HWND hwnd, WORD first, WORD last )
{
while(1)
{
if (MSG_PeekMessage( msg, hwnd, first, last, PM_REMOVE )) break;
XtAppProcessEvent( XT_app_context, XtIMAll );
}
return (msg->message != WM_QUIT);
}
/***********************************************************************
* PostMessage (USER.110)
*/
BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{
MSG msg;
msg.hwnd = hwnd;
msg.message = message;
msg.wParam = wParam;
msg.lParam = lParam;
msg.time = GetTickCount();
msg.pt.x = 0;
msg.pt.y = 0;
return MSG_AddMsg( &msg, 0 );
}
/***********************************************************************
* SendMessage (USER.111)
*/
LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
{
LONG retval = 0;
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (wndPtr)
{
retval = CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg,
wParam, lParam );
GlobalUnlock( hwnd );
}
return retval;
}
/***********************************************************************
* TranslateMessage (USER.113)
*/
BOOL TranslateMessage( LPMSG msg )
{
int message = msg->message;
if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
(message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
{
#ifdef DEBUG_MSG
printf( "Translating key message\n" );
#endif
return TRUE;
}
return FALSE;
}
/***********************************************************************
* DispatchMessage (USER.114)
*/
LONG DispatchMessage( LPMSG msg )
{
LONG retval = 0;
WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
#ifdef DEBUG_MSG
printf( "Dispatch message hwnd=%08x msg=%d w=%d l=%d time=%u pt=%d,%d\n",
msg->hwnd, msg->message, msg->wParam, msg->lParam,
msg->time, msg->pt.x, msg->pt.y );
#endif
if (wndPtr)
{
retval = CallWindowProc(wndPtr->lpfnWndProc, msg->hwnd, msg->message,
msg->wParam, msg->lParam );
GlobalUnlock( msg->hwnd );
}
return retval;
}
/***********************************************************************
* GetMessagePos (USER.119)
*/
DWORD GetMessagePos(void)
{
return msgQueue->GetMessagePosVal;
}
/***********************************************************************
* GetMessageTime (USER.120)
*/
LONG GetMessageTime(void)
{
return msgQueue->GetMessageTimeVal;
}
/***********************************************************************
* GetMessageExtraInfo (USER.288)
*/
LONG GetMessageExtraInfo(void)
{
return msgQueue->GetMessageExtraInfoVal;
}