/* * 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 #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; }