reactos/rosapps/lib/dflat32/message.c
Steven Edwards 81345fd691 Still working on making dflat32 a dll. Alot of this will be cleaned up in the
next few weeks. I'm going through the DFLAT api doc and fixing the export
names and then going to try to build a simple hello dflat application.

svn path=/trunk/; revision=2844
2002-04-14 10:15:06 +00:00

682 lines
15 KiB
C

/* --------- message.c ---------- */
#include "dflat32/dflat.h"
#include "dflat32/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[MAXMESSAGES];
/* ---------- message queue --------- */
static struct msgs
{
DFWINDOW wnd;
DFMESSAGE msg;
PARAM p1;
PARAM p2;
} MsgQueue[MAXMESSAGES];
static int EventQueueOnCtr;
static int EventQueueOffCtr;
static int EventQueueCtr;
static int MsgQueueOnCtr;
static int MsgQueueOffCtr;
static int MsgQueueCtr;
DFWINDOW CaptureMouse;
DFWINDOW CaptureKeyboard;
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)
{
ClearClipboard();
ClearDialogBoxes();
restorecursor();
unhidecursor();
}
SHORT DfGetScreenHeight (void)
{
return sScreenHeight;
}
SHORT DfGetScreenWidth (void)
{
return sScreenWidth;
}
/* ------------ 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 */
hInput = GetStdHandle (STD_INPUT_HANDLE);
hOutput = GetStdHandle (STD_OUTPUT_HANDLE);
/* get screen size */
GetConsoleScreenBufferInfo (hOutput, &csbi);
sScreenHeight = (csbi.srWindow.Bottom - csbi.srWindow.Top) + 1;
sScreenWidth = (csbi.srWindow.Right - csbi.srWindow.Left) + 1;
/* enable mouse events */
SetConsoleMode (hInput, ENABLE_MOUSE_INPUT);
savecursor();
hidecursor();
CaptureMouse = NULL;
CaptureKeyboard = 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 != MAXMESSAGES) {
EventQueue[EventQueueOnCtr].event = event;
EventQueue[EventQueueOnCtr].mx = p1;
EventQueue[EventQueueOnCtr].my = p2;
if (++EventQueueOnCtr == 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 hInput = GetStdHandle (STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD dwRead;
int c;
#ifdef TIMER_AVAILABLE
/* -------- test for a clock event (one/second) ------- */
if (timed_out(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 -------- */
set_timer(clocktimer, 1);
/* -------- post the clock event -------- */
PostEvent(CLOCKTICK, (PARAM)timestr, 0);
}
#endif
// WaitForSingleObject (hInput, INFINITE);
ReadConsoleInput (hInput, &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 |= ALTKEY;
}
if (ir.Event.KeyEvent.dwControlKeyState &
(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
{
sk |= CTRLKEY;
}
if (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
{
sk |= LEFTSHIFT + RIGHTSHIFT;
}
if (sk != OldShiftKeys)
{
OldShiftKeys = sk;
/* the shift status changed */
PostEvent(SHIFT_CHANGED, sk, 0);
#if 0
if (sk & ALTKEY)
AltDown = TRUE;
else
AltDown = FALSE;
#endif
}
if (ir.Event.KeyEvent.uChar.AsciiChar == 0)
{
switch (ir.Event.KeyEvent.wVirtualKeyCode)
{
case VK_F1:
c = F1;
break;
case VK_F4:
if (sk & ALTKEY)
c = ALT_F4;
else if (sk & CTRLKEY)
c = CTRL_F4;
else
c = F4;
case VK_F10:
c = F10;
break;
case VK_UP:
c = UP;
break;
case VK_DOWN:
c = DN;
break;
case VK_LEFT:
c = BS;
break;
case VK_RIGHT:
c = FWD;
break;
case VK_INSERT:
c = INS;
break;
case VK_DELETE:
c = DEL;
break;
case VK_HOME:
c = HOME;
break;
case VK_END:
c = END;
break;
case VK_PRIOR:
c = PGUP;
break;
case VK_NEXT:
c = 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 = SHIFT_HT;
else
c = ir.Event.KeyEvent.uChar.AsciiChar;
}
PostEvent (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 (LEFT_BUTTON,
ir.Event.MouseEvent.dwMousePosition.X,
ir.Event.MouseEvent.dwMousePosition.Y);
}
else if (ir.Event.MouseEvent.dwButtonState ==
RIGHTMOST_BUTTON_PRESSED)
{
PostEvent (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, PARAM p1, PARAM p2)
{
if (msg == ENDDIALOG)
{
msg++;
--msg;
}
if (MsgQueueCtr != MAXMESSAGES)
{
MsgQueue[MsgQueueOnCtr].wnd = wnd;
MsgQueue[MsgQueueOnCtr].msg = msg;
MsgQueue[MsgQueueOnCtr].p1 = p1;
MsgQueue[MsgQueueOnCtr].p2 = p2;
if (++MsgQueueOnCtr == MAXMESSAGES)
MsgQueueOnCtr = 0;
MsgQueueCtr++;
}
}
/* --------- send a message to a window ----------- */
int DfSendMessage(DFWINDOW wnd, DFMESSAGE msg, PARAM p1, PARAM p2)
{
int rtn = TRUE, x, y;
#ifdef INCLUDE_LOGGING
LogMessages(wnd, msg, p1, p2);
#endif
if (wnd != NULL)
switch (msg) {
case PAINT:
case BORDER:
/* ------- don't send these messages unless the
window is visible -------- */
if (isVisible(wnd))
rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
break;
case RIGHT_BUTTON:
case 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 (isVisible(wnd) || wnd == CaptureMouse)
rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
break;
case KEYBOARD:
case SHIFT_CHANGED:
/* ------- don't send these messages unless the
window is visible or has captured the keyboard -- */
if (!(isVisible(wnd) || wnd == CaptureKeyboard))
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 CAPTURE_CLOCK:
Cwnd = wnd;
set_timer(clocktimer, 0);
break;
case RELEASE_CLOCK:
Cwnd = NULL;
disable_timer(clocktimer);
break;
/* -------- keyboard messages ------- */
case KEYBOARD_CURSOR:
if (wnd == NULL)
cursor((int)p1, (int)p2);
else if (wnd == inFocus)
cursor(GetClientLeft(wnd)+(int)p1,
GetClientTop(wnd)+(int)p2);
break;
case CAPTURE_KEYBOARD:
if (p2)
((DFWINDOW)p2)->PrevKeyboard=CaptureKeyboard;
else
wnd->PrevKeyboard = CaptureKeyboard;
CaptureKeyboard = wnd;
NoChildCaptureKeyboard = (int)p1;
break;
case RELEASE_KEYBOARD:
if (wnd != NULL)
{
if (CaptureKeyboard == wnd || (int)p1)
CaptureKeyboard = wnd->PrevKeyboard;
else
{
DFWINDOW twnd = CaptureKeyboard;
while (twnd != NULL)
{
if (twnd->PrevKeyboard == wnd)
{
twnd->PrevKeyboard = wnd->PrevKeyboard;
break;
}
twnd = twnd->PrevKeyboard;
}
if (twnd == NULL)
CaptureKeyboard = NULL;
}
wnd->PrevKeyboard = NULL;
}
else
CaptureKeyboard = NULL;
NoChildCaptureKeyboard = FALSE;
break;
case CURRENT_KEYBOARD_CURSOR:
curr_cursor(&x, &y);
*(int*)p1 = x;
*(int*)p2 = y;
break;
case SAVE_CURSOR:
savecursor();
break;
case RESTORE_CURSOR:
restorecursor();
break;
case HIDE_CURSOR:
normalcursor();
hidecursor();
break;
case SHOW_CURSOR:
if (p1)
set_cursor_size(100);
else
set_cursor_size(5);
unhidecursor();
break;
case CAPTURE_MOUSE:
if (p2)
((DFWINDOW)p2)->PrevMouse = CaptureMouse;
else
wnd->PrevMouse = CaptureMouse;
CaptureMouse = wnd;
NoChildCaptureMouse = (int)p1;
break;
case RELEASE_MOUSE:
if (wnd != NULL)
{
if (CaptureMouse == wnd || (int)p1)
CaptureMouse = wnd->PrevMouse;
else
{
DFWINDOW twnd = CaptureMouse;
while (twnd != NULL)
{
if (twnd->PrevMouse == wnd)
{
twnd->PrevMouse = wnd->PrevMouse;
break;
}
twnd = twnd->PrevMouse;
}
if (twnd == NULL)
CaptureMouse = NULL;
}
wnd->PrevMouse = NULL;
}
else
CaptureMouse = NULL;
NoChildCaptureMouse = FALSE;
break;
default:
break;
}
}
return rtn;
}
static DFRECT VisibleRect(DFWINDOW wnd)
{
DFRECT rc = WindowRect(wnd);
if (!TestAttribute(wnd, NOCLIP))
{
DFWINDOW pwnd = GetParent(wnd);
DFRECT prc;
prc = ClientRect(pwnd);
while (pwnd != NULL)
{
if (TestAttribute(pwnd, NOCLIP))
break;
rc = subRectangle(rc, prc);
if (!ValidRect(rc))
break;
if ((pwnd = GetParent(pwnd)) != NULL)
prc = ClientRect(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 (isVisible(wnd)) {
DFWINDOW wnd1;
DFRECT rc = VisibleRect(wnd);
if (InsideRect(x, y, rc))
Hit = wnd;
if ((wnd1 = inWindow(LastWindow(wnd), x, y)) != NULL)
Hit = wnd1;
if (Hit != NULL)
break;
}
wnd = PrevWindow(wnd);
}
return Hit;
}
static DFWINDOW MouseWindow(int x, int y)
{
/* get the window in which a mouse event occurred */
DFWINDOW Mwnd = inWindow(ApplicationWindow, x, y);
/* ---- process mouse captures ----- */
if (CaptureMouse != NULL)
{
if (NoChildCaptureMouse ||
Mwnd == NULL ||
!isAncestor(Mwnd, CaptureMouse))
Mwnd = CaptureMouse;
}
return Mwnd;
}
void handshake(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 == MAXMESSAGES)
EventQueueOffCtr = 0;
--EventQueueCtr;
/* get the window in which a keyboard event occurred */
Kwnd = inFocus;
/* process keyboard captures */
if (CaptureKeyboard != NULL)
{
if (Kwnd == NULL ||
NoChildCaptureKeyboard ||
!isAncestor(Kwnd, CaptureKeyboard))
Kwnd = CaptureKeyboard;
}
/* send mouse and keyboard messages to the
window that should get them */
switch (ev.event)
{
case SHIFT_CHANGED:
case KEYBOARD:
if (!handshaking)
DfSendMessage(Kwnd, ev.event, ev.mx, ev.my);
break;
case LEFT_BUTTON:
if (!handshaking)
{
Mwnd = MouseWindow(ev.mx, ev.my);
if (!CaptureMouse ||
(!NoChildCaptureMouse &&
isAncestor(Mwnd, CaptureMouse)))
{
if (Mwnd != inFocus)
DfSendMessage(Mwnd, SETFOCUS, TRUE, 0);
DfSendMessage(Mwnd, LEFT_BUTTON, ev.mx, ev.my);
}
}
break;
case DFM_BUTTON_RELEASED:
case DOUBLE_CLICK:
case RIGHT_BUTTON:
if (handshaking)
break;
case MOUSE_MOVED:
Mwnd = MouseWindow(ev.mx, ev.my);
DfSendMessage(Mwnd, ev.event, ev.mx, ev.my);
break;
case 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 == MAXMESSAGES)
MsgQueueOffCtr = 0;
--MsgQueueCtr;
DfSendMessage (mq.wnd, mq.msg, mq.p1, mq.p2);
if (mq.msg == ENDDIALOG)
return FALSE;
if (mq.msg == DFM_STOP)
return FALSE;
}
return TRUE;
}
/* EOF */