1 /* --------- message.c ----------
2 * Message Que code for all events that dflat32
3 * should know how to handle.
5 * You understand this? Good I'm glad one of us
6 * does. - sedwards 3-24-02
9 #include <dflat32/dflat.h>
10 #include <dflat32/system.h>
12 static int handshaking
= 0;
14 BOOL AllocTesting
= FALSE
;
18 /* ---------- event queue ---------- */
24 } EventQueue
[MAXMESSAGES
];
26 /* ---------- message queue --------- */
33 } MsgQueue
[MAXMESSAGES
];
35 static int EventQueueOnCtr
;
36 static int EventQueueOffCtr
;
37 static int EventQueueCtr
;
39 static int MsgQueueOnCtr
;
40 static int MsgQueueOffCtr
;
41 static int MsgQueueCtr
;
44 DFWINDOW CaptureMouse
;
45 DFWINDOW CaptureKeyboard
;
46 static BOOL NoChildCaptureMouse
;
47 static BOOL NoChildCaptureKeyboard
;
49 static int doubletimer
= -1;
50 static int delaytimer
= -1;
51 static int clocktimer
= -1;
55 static char ermsg
[] = "Error accessing drive x";
58 static void StopMsg(void)
66 SHORT
DfGetScreenHeight (void)
71 SHORT
DfGetScreenWidth (void)
76 /* ------------ initialize the message system --------- */
77 BOOL
DfInitialize (VOID
)
79 CONSOLE_SCREEN_BUFFER_INFO csbi
;
82 if (setjmp(AllocError
) != 0)
88 /* get input and output handles */
89 hInput
= GetStdHandle (STD_INPUT_HANDLE
);
90 hOutput
= GetStdHandle (STD_OUTPUT_HANDLE
);
93 GetConsoleScreenBufferInfo (hOutput
, &csbi
);
94 sScreenHeight
= (csbi
.srWindow
.Bottom
- csbi
.srWindow
.Top
) + 1;
95 sScreenWidth
= (csbi
.srWindow
.Right
- csbi
.srWindow
.Left
) + 1;
97 /* enable mouse events */
98 SetConsoleMode (hInput
, ENABLE_MOUSE_INPUT
);
104 CaptureKeyboard
= NULL
;
105 NoChildCaptureMouse
= FALSE
;
106 NoChildCaptureKeyboard
= FALSE
;
111 EventQueueOffCtr
= 0;
113 DfPostMessage (NULL
, DFM_START
, 0, 0);
119 void DfTerminate (void)
124 /* ----- post an event and parameters to event queue ---- */
125 static void PostEvent(DFMESSAGE event
, int p1
, int p2
)
127 if (EventQueueCtr
!= MAXMESSAGES
) {
128 EventQueue
[EventQueueOnCtr
].event
= event
;
129 EventQueue
[EventQueueOnCtr
].mx
= p1
;
130 EventQueue
[EventQueueOnCtr
].my
= p2
;
131 if (++EventQueueOnCtr
== MAXMESSAGES
)
137 /* ------ collect mouse, clock, and keyboard events ----- */
138 static void collect_events(void)
140 static int OldShiftKeys
= 0;
143 #ifdef TIMER_AVAILABLE
144 static BOOL flipflop
= FALSE
;
145 static char timestr
[9];
150 HANDLE hInput
= GetStdHandle (STD_INPUT_HANDLE
);
155 #ifdef TIMER_AVAILABLE
156 /* -------- test for a clock event (one/second) ------- */
157 if (timed_out(clocktimer
))
159 /* ----- get the current time ----- */
160 time_t t
= time(NULL
);
162 hr
= now
->tm_hour
> 12 ?
167 sprintf(timestr
, "%2d:%02d", hr
, now
->tm_min
);
168 strcpy(timestr
+5, now
->tm_hour
> 11 ? "pm " : "am ");
169 /* ------- blink the : at one-second intervals ----- */
173 /* -------- reset the timer -------- */
174 set_timer(clocktimer
, 1);
175 /* -------- post the clock event -------- */
176 PostEvent(CLOCKTICK
, (PARAM
)timestr
, 0);
180 // WaitForSingleObject (hInput, INFINITE);
181 ReadConsoleInput (hInput
, &ir
, 1, &dwRead
);
183 if ((ir
.EventType
== KEY_EVENT
) &&
184 (ir
.Event
.KeyEvent
.bKeyDown
== TRUE
))
186 /* handle key down events */
188 /* handle shift state changes */
189 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
190 (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
194 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
195 (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
199 if (ir
.Event
.KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
)
201 sk
|= LEFTSHIFT
+ RIGHTSHIFT
;
204 if (sk
!= OldShiftKeys
)
207 /* the shift status changed */
208 PostEvent(SHIFT_CHANGED
, sk
, 0);
217 if (ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0)
219 switch (ir
.Event
.KeyEvent
.wVirtualKeyCode
)
228 else if (sk
& CTRLKEY
)
283 /* special handling of SHIFT+TAB */
284 if (ir
.Event
.KeyEvent
.uChar
.AsciiChar
== VK_TAB
&&
285 (ir
.Event
.KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
))
288 c
= ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
291 PostEvent (KEYBOARD
, c
, sk
);
293 else if (ir
.EventType
== MOUSE_EVENT
)
295 /* handle mouse events */
296 if (ir
.Event
.MouseEvent
.dwEventFlags
== MOUSE_MOVED
)
298 PostEvent (MOUSE_MOVED
,
299 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
300 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
302 else if (ir
.Event
.MouseEvent
.dwEventFlags
== DOUBLE_CLICK
)
304 if (ir
.Event
.MouseEvent
.dwButtonState
==
305 FROM_LEFT_1ST_BUTTON_PRESSED
)
307 PostEvent (DOUBLE_CLICK
,
308 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
309 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
312 else if (ir
.Event
.MouseEvent
.dwEventFlags
== 0)
315 if (ir
.Event
.MouseEvent
.dwButtonState
==
316 FROM_LEFT_1ST_BUTTON_PRESSED
)
318 PostEvent (LEFT_BUTTON
,
319 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
320 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
322 else if (ir
.Event
.MouseEvent
.dwButtonState
==
323 RIGHTMOST_BUTTON_PRESSED
)
325 PostEvent (RIGHT_BUTTON
,
326 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
327 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
329 else if (ir
.Event
.MouseEvent
.dwButtonState
== 0)
331 PostEvent (DFM_BUTTON_RELEASED
,
332 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
333 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
340 /* ----- post a message and parameters to msg queue ---- */
341 void DfPostMessage(DFWINDOW wnd
, DFMESSAGE msg
, PARAM p1
, PARAM p2
)
343 if (msg
== ENDDIALOG
)
349 if (MsgQueueCtr
!= MAXMESSAGES
)
351 MsgQueue
[MsgQueueOnCtr
].wnd
= wnd
;
352 MsgQueue
[MsgQueueOnCtr
].msg
= msg
;
353 MsgQueue
[MsgQueueOnCtr
].p1
= p1
;
354 MsgQueue
[MsgQueueOnCtr
].p2
= p2
;
355 if (++MsgQueueOnCtr
== MAXMESSAGES
)
361 /* --------- send a message to a window ----------- */
362 int DfSendMessage(DFWINDOW wnd
, DFMESSAGE msg
, PARAM p1
, PARAM p2
)
364 int rtn
= TRUE
, x
, y
;
366 #ifdef INCLUDE_LOGGING
367 LogMessages(wnd
, msg
, p1
, p2
);
373 /* ------- don't send these messages unless the
374 window is visible -------- */
376 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
381 case DFM_BUTTON_RELEASED
:
382 /* --- don't send these messages unless the
383 window is visible or has captured the mouse -- */
384 if (isVisible(wnd
) || wnd
== CaptureMouse
)
385 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
389 /* ------- don't send these messages unless the
390 window is visible or has captured the keyboard -- */
391 if (!(isVisible(wnd
) || wnd
== CaptureKeyboard
))
394 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
397 /* ----- window processor returned true or the message was sent
398 to no window at all (NULL) ----- */
400 /* --------- process messages that a window sends to the
401 system itself ---------- */
406 /* ------- clock messages --------- */
409 set_timer(clocktimer
, 0);
413 disable_timer(clocktimer
);
415 /* -------- keyboard messages ------- */
416 case KEYBOARD_CURSOR
:
418 cursor((int)p1
, (int)p2
);
419 else if (wnd
== inFocus
)
420 cursor(GetClientLeft(wnd
)+(int)p1
,
421 GetClientTop(wnd
)+(int)p2
);
423 case CAPTURE_KEYBOARD
:
425 ((DFWINDOW
)p2
)->PrevKeyboard
=CaptureKeyboard
;
427 wnd
->PrevKeyboard
= CaptureKeyboard
;
428 CaptureKeyboard
= wnd
;
429 NoChildCaptureKeyboard
= (int)p1
;
431 case RELEASE_KEYBOARD
:
434 if (CaptureKeyboard
== wnd
|| (int)p1
)
435 CaptureKeyboard
= wnd
->PrevKeyboard
;
438 DFWINDOW twnd
= CaptureKeyboard
;
441 if (twnd
->PrevKeyboard
== wnd
)
443 twnd
->PrevKeyboard
= wnd
->PrevKeyboard
;
446 twnd
= twnd
->PrevKeyboard
;
449 CaptureKeyboard
= NULL
;
451 wnd
->PrevKeyboard
= NULL
;
454 CaptureKeyboard
= NULL
;
455 NoChildCaptureKeyboard
= FALSE
;
457 case CURRENT_KEYBOARD_CURSOR
:
474 set_cursor_size(100);
482 ((DFWINDOW
)p2
)->PrevMouse
= CaptureMouse
;
484 wnd
->PrevMouse
= CaptureMouse
;
486 NoChildCaptureMouse
= (int)p1
;
492 if (CaptureMouse
== wnd
|| (int)p1
)
493 CaptureMouse
= wnd
->PrevMouse
;
496 DFWINDOW twnd
= CaptureMouse
;
499 if (twnd
->PrevMouse
== wnd
)
501 twnd
->PrevMouse
= wnd
->PrevMouse
;
504 twnd
= twnd
->PrevMouse
;
509 wnd
->PrevMouse
= NULL
;
513 NoChildCaptureMouse
= FALSE
;
523 static DFRECT
VisibleRect(DFWINDOW wnd
)
525 DFRECT rc
= WindowRect(wnd
);
526 if (!TestAttribute(wnd
, NOCLIP
))
528 DFWINDOW pwnd
= GetParent(wnd
);
530 prc
= ClientRect(pwnd
);
533 if (TestAttribute(pwnd
, NOCLIP
))
535 rc
= subRectangle(rc
, prc
);
538 if ((pwnd
= GetParent(pwnd
)) != NULL
)
539 prc
= ClientRect(pwnd
);
545 /* ----- find window that mouse coordinates are in --- */
546 static DFWINDOW
inWindow(DFWINDOW wnd
, int x
, int y
)
549 while (wnd
!= NULL
) {
550 if (isVisible(wnd
)) {
552 DFRECT rc
= VisibleRect(wnd
);
553 if (InsideRect(x
, y
, rc
))
555 if ((wnd1
= inWindow(LastWindow(wnd
), x
, y
)) != NULL
)
560 wnd
= PrevWindow(wnd
);
565 static DFWINDOW
MouseWindow(int x
, int y
)
567 /* get the window in which a mouse event occurred */
568 DFWINDOW Mwnd
= inWindow(ApplicationWindow
, x
, y
);
570 /* ---- process mouse captures ----- */
571 if (CaptureMouse
!= NULL
)
573 if (NoChildCaptureMouse
||
575 !isAncestor(Mwnd
, CaptureMouse
))
585 DfDispatchMessage ();
590 /* ---- dispatch messages to the message proc function ---- */
591 BOOL
DfDispatchMessage (void)
595 /* -------- collect mouse and keyboard events ------- */
598 /* --------- dequeue and process events -------- */
599 while (EventQueueCtr
> 0)
603 ev
= EventQueue
[EventQueueOffCtr
];
604 if (++EventQueueOffCtr
== MAXMESSAGES
)
605 EventQueueOffCtr
= 0;
608 /* get the window in which a keyboard event occurred */
611 /* process keyboard captures */
612 if (CaptureKeyboard
!= NULL
)
615 NoChildCaptureKeyboard
||
616 !isAncestor(Kwnd
, CaptureKeyboard
))
617 Kwnd
= CaptureKeyboard
;
620 /* send mouse and keyboard messages to the
621 window that should get them */
627 DfSendMessage(Kwnd
, ev
.event
, ev
.mx
, ev
.my
);
633 Mwnd
= MouseWindow(ev
.mx
, ev
.my
);
635 (!NoChildCaptureMouse
&&
636 isAncestor(Mwnd
, CaptureMouse
)))
639 DfSendMessage(Mwnd
, SETFOCUS
, TRUE
, 0);
640 DfSendMessage(Mwnd
, LEFT_BUTTON
, ev
.mx
, ev
.my
);
645 case DFM_BUTTON_RELEASED
:
652 Mwnd
= MouseWindow(ev
.mx
, ev
.my
);
653 DfSendMessage(Mwnd
, ev
.event
, ev
.mx
, ev
.my
);
657 DfSendMessage(Cwnd
, ev
.event
, ev
.mx
, ev
.my
);
665 /* ------ dequeue and process messages ----- */
666 while (MsgQueueCtr
> 0)
670 mq
= MsgQueue
[MsgQueueOffCtr
];
672 if (++MsgQueueOffCtr
== MAXMESSAGES
)
676 DfSendMessage (mq
.wnd
, mq
.msg
, mq
.p1
, mq
.p2
);
677 if (mq
.msg
== ENDDIALOG
)
680 if (mq
.msg
== DFM_STOP
)