reactos/rosapps/dflat32/message.c
Steven Edwards 456be5d16b remove trailing whitespace at end of lines
svn path=/trunk/; revision=15091
2005-05-07 21:24:31 +00:00

682 lines
15 KiB
C

/* --------- message.c ---------- */
#include "dflat.h"
#include "system.h"
static int handshaking = 0;
BOOL AllocTesting = FALSE;
jmp_buf AllocError;
BOOL AltDown = FALSE;
/* ---------- event queue ---------- */
static struct events
{
DFMESSAGE event;
int mx;
int my;
} EventQueue[DF_MAXMESSAGES];
/* ---------- message queue --------- */
static struct msgs
{
DFWINDOW wnd;
DFMESSAGE msg;
DF_PARAM p1;
DF_PARAM p2;
} MsgQueue[DF_MAXMESSAGES];
static int EventQueueOnCtr;
static int EventQueueOffCtr;
static int EventQueueCtr;
static int MsgQueueOnCtr;
static int MsgQueueOffCtr;
static int MsgQueueCtr;
DFWINDOW DfCaptureMouse;
DFWINDOW DfCaptureKeyboard;
static BOOL NoChildCaptureMouse;
static BOOL NoChildCaptureKeyboard;
//static int doubletimer = -1;
//static int delaytimer = -1;
static int clocktimer = -1;
static DFWINDOW Cwnd;
//static char ermsg[] = "Error accessing drive x";
static void StopMsg(void)
{
DfClearClipboard();
DfClearDialogBoxes();
DfRestoreCursor();
DfUnhideCursor();
}
SHORT DfGetScreenHeight (void)
{
return DfScreenHeight;
}
SHORT DfGetScreenWidth (void)
{
return DfScreenWidth;
}
/* ------------ initialize the message system --------- */
BOOL DfInitialize (VOID)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
AllocTesting = TRUE;
if (setjmp(AllocError) != 0)
{
StopMsg();
return FALSE;
}
/* get input and output handles */
DfInput = GetStdHandle (STD_INPUT_HANDLE);
DfOutput = GetStdHandle (STD_OUTPUT_HANDLE);
/* get screen size */
GetConsoleScreenBufferInfo (DfOutput, &csbi);
DfScreenHeight = (csbi.srWindow.Bottom - csbi.srWindow.Top) + 1;
DfScreenWidth = (csbi.srWindow.Right - csbi.srWindow.Left) + 1;
/* enable mouse events */
SetConsoleMode (DfInput, ENABLE_MOUSE_INPUT);
DfSaveCursor();
DfHideCursor();
DfCaptureMouse = NULL;
DfCaptureKeyboard = NULL;
NoChildCaptureMouse = FALSE;
NoChildCaptureKeyboard = FALSE;
MsgQueueOnCtr = 0;
MsgQueueOffCtr = 0;
MsgQueueCtr = 0;
EventQueueOnCtr = 0;
EventQueueOffCtr = 0;
EventQueueCtr = 0;
DfPostMessage (NULL, DFM_START, 0, 0);
return TRUE;
}
void DfTerminate (void)
{
}
/* ----- post an event and parameters to event queue ---- */
static void PostEvent(DFMESSAGE event, int p1, int p2)
{
if (EventQueueCtr != DF_MAXMESSAGES) {
EventQueue[EventQueueOnCtr].event = event;
EventQueue[EventQueueOnCtr].mx = p1;
EventQueue[EventQueueOnCtr].my = p2;
if (++EventQueueOnCtr == DF_MAXMESSAGES)
EventQueueOnCtr = 0;
EventQueueCtr++;
}
}
/* ------ collect mouse, clock, and keyboard events ----- */
static void collect_events(void)
{
static int OldShiftKeys = 0;
int sk = 0;
#ifdef TIMER_AVAILABLE
static BOOL flipflop = FALSE;
static char timestr[9];
struct tm *now;
int hr;
#endif
HANDLE DfInput = GetStdHandle (STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD dwRead;
int c;
#ifdef TIMER_AVAILABLE
/* -------- test for a clock event (one/second) ------- */
if (DfTimedOut(clocktimer))
{
/* ----- get the current time ----- */
time_t t = time(NULL);
now = localtime(&t);
hr = now->tm_hour > 12 ?
now->tm_hour - 12 :
now->tm_hour;
if (hr == 0)
hr = 12;
sprintf(timestr, "%2d:%02d", hr, now->tm_min);
strcpy(timestr+5, now->tm_hour > 11 ? "pm " : "am ");
/* ------- blink the : at one-second intervals ----- */
if (flipflop)
*(timestr+2) = ' ';
flipflop ^= TRUE;
/* -------- reset the timer -------- */
DfSetTimer(clocktimer, 1);
/* -------- post the clock event -------- */
PostEvent(DFM_CLOCKTICK, (DF_PARAM)timestr, 0);
}
#endif
// WaitForSingleObject (DfInput, INFINITE);
ReadConsoleInput (DfInput, &ir, 1, &dwRead);
if ((ir.EventType == KEY_EVENT) &&
(ir.Event.KeyEvent.bKeyDown == TRUE))
{
/* handle key down events */
/* handle shift state changes */
if (ir.Event.KeyEvent.dwControlKeyState &
(LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
{
sk |= DF_ALTKEY;
}
if (ir.Event.KeyEvent.dwControlKeyState &
(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
{
sk |= DF_CTRLKEY;
}
if (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
{
sk |= DF_LEFTSHIFT + DF_RIGHTSHIFT;
}
if (sk != OldShiftKeys)
{
OldShiftKeys = sk;
/* the shift status changed */
PostEvent(DFM_SHIFT_CHANGED, sk, 0);
#if 0
if (sk & DF_ALTKEY)
AltDown = TRUE;
else
AltDown = FALSE;
#endif
}
if (ir.Event.KeyEvent.uChar.AsciiChar == 0)
{
switch (ir.Event.KeyEvent.wVirtualKeyCode)
{
case VK_F1:
c = DF_F1;
break;
case VK_F4:
if (sk & DF_ALTKEY)
c = DF_ALT_F4;
else if (sk & DF_CTRLKEY)
c = DF_CTRL_F4;
else
c = DF_F4;
case VK_F10:
c = DF_F10;
break;
case VK_UP:
c = DF_UP;
break;
case VK_DOWN:
c = DF_DN;
break;
case VK_LEFT:
c = DF_BS;
break;
case VK_RIGHT:
c = DF_FWD;
break;
case VK_INSERT:
c = DF_INS;
break;
case VK_DELETE:
c = DF_DEL;
break;
case VK_HOME:
c = DF_HOME;
break;
case VK_END:
c = DF_END;
break;
case VK_PRIOR:
c = DF_PGUP;
break;
case VK_NEXT:
c = DF_PGDN;
break;
default:
return;
}
}
else
{
/* special handling of SHIFT+TAB */
if (ir.Event.KeyEvent.uChar.AsciiChar == VK_TAB &&
(ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED))
c = DF_SHIFT_HT;
else
c = ir.Event.KeyEvent.uChar.AsciiChar;
}
PostEvent (DFM_KEYBOARD, c, sk);
}
else if (ir.EventType == MOUSE_EVENT)
{
/* handle mouse events */
if (ir.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
{
PostEvent (MOUSE_MOVED,
ir.Event.MouseEvent.dwMousePosition.X,
ir.Event.MouseEvent.dwMousePosition.Y);
}
else if (ir.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
{
if (ir.Event.MouseEvent.dwButtonState ==
FROM_LEFT_1ST_BUTTON_PRESSED)
{
PostEvent (DOUBLE_CLICK,
ir.Event.MouseEvent.dwMousePosition.X,
ir.Event.MouseEvent.dwMousePosition.Y);
}
}
else if (ir.Event.MouseEvent.dwEventFlags == 0)
{
/* single click */
if (ir.Event.MouseEvent.dwButtonState ==
FROM_LEFT_1ST_BUTTON_PRESSED)
{
PostEvent (DFM_LEFT_BUTTON,
ir.Event.MouseEvent.dwMousePosition.X,
ir.Event.MouseEvent.dwMousePosition.Y);
}
else if (ir.Event.MouseEvent.dwButtonState ==
RIGHTMOST_BUTTON_PRESSED)
{
PostEvent (DFM_RIGHT_BUTTON,
ir.Event.MouseEvent.dwMousePosition.X,
ir.Event.MouseEvent.dwMousePosition.Y);
}
else if (ir.Event.MouseEvent.dwButtonState == 0)
{
PostEvent (DFM_BUTTON_RELEASED,
ir.Event.MouseEvent.dwMousePosition.X,
ir.Event.MouseEvent.dwMousePosition.Y);
}
}
}
}
/* ----- post a message and parameters to msg queue ---- */
void DfPostMessage(DFWINDOW wnd, DFMESSAGE msg, DF_PARAM p1, DF_PARAM p2)
{
if (msg == DFM_ENDDIALOG)
{
msg++;
--msg;
}
if (MsgQueueCtr != DF_MAXMESSAGES)
{
MsgQueue[MsgQueueOnCtr].wnd = wnd;
MsgQueue[MsgQueueOnCtr].msg = msg;
MsgQueue[MsgQueueOnCtr].p1 = p1;
MsgQueue[MsgQueueOnCtr].p2 = p2;
if (++MsgQueueOnCtr == DF_MAXMESSAGES)
MsgQueueOnCtr = 0;
MsgQueueCtr++;
}
}
/* --------- send a message to a window ----------- */
int DfSendMessage(DFWINDOW wnd, DFMESSAGE msg, DF_PARAM p1, DF_PARAM p2)
{
int rtn = TRUE, x, y;
#ifdef INCLUDE_LOGGING
DfLogMessages(wnd, msg, p1, p2);
#endif
if (wnd != NULL)
switch (msg) {
case DFM_PAINT:
case DFM_BORDER:
/* ------- don't send these messages unless the
window is visible -------- */
if (DfIsVisible(wnd))
rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
break;
case DFM_RIGHT_BUTTON:
case DFM_LEFT_BUTTON:
case DOUBLE_CLICK:
case DFM_BUTTON_RELEASED:
/* --- don't send these messages unless the
window is visible or has captured the mouse -- */
if (DfIsVisible(wnd) || wnd == DfCaptureMouse)
rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
break;
case DFM_KEYBOARD:
case DFM_SHIFT_CHANGED:
/* ------- don't send these messages unless the
window is visible or has captured the keyboard -- */
if (!(DfIsVisible(wnd) || wnd == DfCaptureKeyboard))
break;
default:
rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
break;
}
/* ----- window processor returned true or the message was sent
to no window at all (NULL) ----- */
if (rtn != FALSE) {
/* --------- process messages that a window sends to the
system itself ---------- */
switch (msg) {
case DFM_STOP:
StopMsg();
break;
/* ------- clock messages --------- */
case DFM_CAPTURE_CLOCK:
Cwnd = wnd;
DfSetTimer(clocktimer, 0);
break;
case DFM_RELEASE_CLOCK:
Cwnd = NULL;
DfDisableTimer(clocktimer);
break;
/* -------- keyboard messages ------- */
case DFM_KEYBOARD_CURSOR:
if (wnd == NULL)
DfCursor((int)p1, (int)p2);
else if (wnd == DfInFocus)
DfCursor(DfGetClientLeft(wnd)+(int)p1,
DfGetClientTop(wnd)+(int)p2);
break;
case DFM_CAPTURE_KEYBOARD:
if (p2)
((DFWINDOW)p2)->PrevKeyboard=DfCaptureKeyboard;
else
wnd->PrevKeyboard = DfCaptureKeyboard;
DfCaptureKeyboard = wnd;
NoChildCaptureKeyboard = (int)p1;
break;
case DFM_RELEASE_KEYBOARD:
if (wnd != NULL)
{
if (DfCaptureKeyboard == wnd || (int)p1)
DfCaptureKeyboard = wnd->PrevKeyboard;
else
{
DFWINDOW twnd = DfCaptureKeyboard;
while (twnd != NULL)
{
if (twnd->PrevKeyboard == wnd)
{
twnd->PrevKeyboard = wnd->PrevKeyboard;
break;
}
twnd = twnd->PrevKeyboard;
}
if (twnd == NULL)
DfCaptureKeyboard = NULL;
}
wnd->PrevKeyboard = NULL;
}
else
DfCaptureKeyboard = NULL;
NoChildCaptureKeyboard = FALSE;
break;
case DFM_CURRENT_KEYBOARD_CURSOR:
DfCurrCursor(&x, &y);
*(int*)p1 = x;
*(int*)p2 = y;
break;
case DFM_SAVE_CURSOR:
DfSaveCursor();
break;
case DFM_RESTORE_CURSOR:
DfRestoreCursor();
break;
case DFM_HIDE_CURSOR:
DfNormalCursor();
DfHideCursor();
break;
case DFM_SHOW_CURSOR:
if (p1)
DfSetCursorSize(100);
else
DfSetCursorSize(5);
DfUnhideCursor();
break;
case DFM_CAPTURE_MOUSE:
if (p2)
((DFWINDOW)p2)->PrevMouse = DfCaptureMouse;
else
wnd->PrevMouse = DfCaptureMouse;
DfCaptureMouse = wnd;
NoChildCaptureMouse = (int)p1;
break;
case DFM_RELEASE_MOUSE:
if (wnd != NULL)
{
if (DfCaptureMouse == wnd || (int)p1)
DfCaptureMouse = wnd->PrevMouse;
else
{
DFWINDOW twnd = DfCaptureMouse;
while (twnd != NULL)
{
if (twnd->PrevMouse == wnd)
{
twnd->PrevMouse = wnd->PrevMouse;
break;
}
twnd = twnd->PrevMouse;
}
if (twnd == NULL)
DfCaptureMouse = NULL;
}
wnd->PrevMouse = NULL;
}
else
DfCaptureMouse = NULL;
NoChildCaptureMouse = FALSE;
break;
default:
break;
}
}
return rtn;
}
static DFRECT VisibleRect(DFWINDOW wnd)
{
DFRECT rc = DfWindowRect(wnd);
if (!DfTestAttribute(wnd, DF_NOCLIP))
{
DFWINDOW pwnd = DfGetParent(wnd);
DFRECT prc;
prc = DfClientRect(pwnd);
while (pwnd != NULL)
{
if (DfTestAttribute(pwnd, DF_NOCLIP))
break;
rc = DfSubRectangle(rc, prc);
if (!DfValidRect(rc))
break;
if ((pwnd = DfGetParent(pwnd)) != NULL)
prc = DfClientRect(pwnd);
}
}
return rc;
}
/* ----- find window that mouse coordinates are in --- */
static DFWINDOW inWindow(DFWINDOW wnd, int x, int y)
{
DFWINDOW Hit = NULL;
while (wnd != NULL) {
if (DfIsVisible(wnd)) {
DFWINDOW wnd1;
DFRECT rc = VisibleRect(wnd);
if (DfInsideRect(x, y, rc))
Hit = wnd;
if ((wnd1 = inWindow(DfLastWindow(wnd), x, y)) != NULL)
Hit = wnd1;
if (Hit != NULL)
break;
}
wnd = DfPrevWindow(wnd);
}
return Hit;
}
static DFWINDOW MouseWindow(int x, int y)
{
/* get the window in which a mouse event occurred */
DFWINDOW Mwnd = inWindow(DfApplicationWindow, x, y);
/* ---- process mouse captures ----- */
if (DfCaptureMouse != NULL)
{
if (NoChildCaptureMouse ||
Mwnd == NULL ||
!DfIsAncestor(Mwnd, DfCaptureMouse))
Mwnd = DfCaptureMouse;
}
return Mwnd;
}
void DfHandshake(void)
{
handshaking++;
DfDispatchMessage ();
--handshaking;
}
/* ---- dispatch messages to the message proc function ---- */
BOOL DfDispatchMessage (void)
{
DFWINDOW Mwnd, Kwnd;
/* -------- collect mouse and keyboard events ------- */
collect_events();
/* --------- dequeue and process events -------- */
while (EventQueueCtr > 0)
{
struct events ev;
ev = EventQueue[EventQueueOffCtr];
if (++EventQueueOffCtr == DF_MAXMESSAGES)
EventQueueOffCtr = 0;
--EventQueueCtr;
/* get the window in which a keyboard event occurred */
Kwnd = DfInFocus;
/* process keyboard captures */
if (DfCaptureKeyboard != NULL)
{
if (Kwnd == NULL ||
NoChildCaptureKeyboard ||
!DfIsAncestor(Kwnd, DfCaptureKeyboard))
Kwnd = DfCaptureKeyboard;
}
/* send mouse and keyboard messages to the
window that should get them */
switch (ev.event)
{
case DFM_SHIFT_CHANGED:
case DFM_KEYBOARD:
if (!handshaking)
DfSendMessage(Kwnd, ev.event, ev.mx, ev.my);
break;
case DFM_LEFT_BUTTON:
if (!handshaking)
{
Mwnd = MouseWindow(ev.mx, ev.my);
if (!DfCaptureMouse ||
(!NoChildCaptureMouse &&
DfIsAncestor(Mwnd, DfCaptureMouse)))
{
if (Mwnd != DfInFocus)
DfSendMessage(Mwnd, DFM_SETFOCUS, TRUE, 0);
DfSendMessage(Mwnd, DFM_LEFT_BUTTON, ev.mx, ev.my);
}
}
break;
case DFM_BUTTON_RELEASED:
case DOUBLE_CLICK:
case DFM_RIGHT_BUTTON:
if (handshaking)
break;
case MOUSE_MOVED:
Mwnd = MouseWindow(ev.mx, ev.my);
DfSendMessage(Mwnd, ev.event, ev.mx, ev.my);
break;
case DFM_CLOCKTICK:
DfSendMessage(Cwnd, ev.event, ev.mx, ev.my);
break;
default:
break;
}
}
/* ------ dequeue and process messages ----- */
while (MsgQueueCtr > 0)
{
struct msgs mq;
mq = MsgQueue[MsgQueueOffCtr];
if (++MsgQueueOffCtr == DF_MAXMESSAGES)
MsgQueueOffCtr = 0;
--MsgQueueCtr;
DfSendMessage (mq.wnd, mq.msg, mq.p1, mq.p2);
if (mq.msg == DFM_ENDDIALOG)
return FALSE;
if (mq.msg == DFM_STOP)
return FALSE;
}
return TRUE;
}
/* EOF */