1 /* --------- message.c ---------- */
6 static int handshaking
= 0;
8 BOOL AllocTesting
= FALSE
;
12 /* ---------- event queue ---------- */
18 } EventQueue
[DF_MAXMESSAGES
];
20 /* ---------- message queue --------- */
27 } MsgQueue
[DF_MAXMESSAGES
];
29 static int EventQueueOnCtr
;
30 static int EventQueueOffCtr
;
31 static int EventQueueCtr
;
33 static int MsgQueueOnCtr
;
34 static int MsgQueueOffCtr
;
35 static int MsgQueueCtr
;
38 DFWINDOW DfCaptureMouse
;
39 DFWINDOW DfCaptureKeyboard
;
40 static BOOL NoChildCaptureMouse
;
41 static BOOL NoChildCaptureKeyboard
;
43 //static int doubletimer = -1;
44 //static int delaytimer = -1;
45 static int clocktimer
= -1;
49 //static char ermsg[] = "Error accessing drive x";
52 static void StopMsg(void)
60 SHORT
DfGetScreenHeight (void)
62 return DfScreenHeight
;
65 SHORT
DfGetScreenWidth (void)
70 /* ------------ initialize the message system --------- */
71 BOOL
DfInitialize (VOID
)
73 CONSOLE_SCREEN_BUFFER_INFO csbi
;
76 if (setjmp(AllocError
) != 0)
82 /* get input and output handles */
83 DfInput
= GetStdHandle (STD_INPUT_HANDLE
);
84 DfOutput
= GetStdHandle (STD_OUTPUT_HANDLE
);
87 GetConsoleScreenBufferInfo (DfOutput
, &csbi
);
88 DfScreenHeight
= (csbi
.srWindow
.Bottom
- csbi
.srWindow
.Top
) + 1;
89 DfScreenWidth
= (csbi
.srWindow
.Right
- csbi
.srWindow
.Left
) + 1;
91 /* enable mouse events */
92 SetConsoleMode (DfInput
, ENABLE_MOUSE_INPUT
);
97 DfCaptureMouse
= NULL
;
98 DfCaptureKeyboard
= NULL
;
99 NoChildCaptureMouse
= FALSE
;
100 NoChildCaptureKeyboard
= FALSE
;
105 EventQueueOffCtr
= 0;
107 DfPostMessage (NULL
, DFM_START
, 0, 0);
113 void DfTerminate (void)
118 /* ----- post an event and parameters to event queue ---- */
119 static void PostEvent(DFMESSAGE event
, int p1
, int p2
)
121 if (EventQueueCtr
!= DF_MAXMESSAGES
) {
122 EventQueue
[EventQueueOnCtr
].event
= event
;
123 EventQueue
[EventQueueOnCtr
].mx
= p1
;
124 EventQueue
[EventQueueOnCtr
].my
= p2
;
125 if (++EventQueueOnCtr
== DF_MAXMESSAGES
)
131 /* ------ collect mouse, clock, and keyboard events ----- */
132 static void collect_events(void)
134 static int OldShiftKeys
= 0;
137 #ifdef TIMER_AVAILABLE
138 static BOOL flipflop
= FALSE
;
139 static char timestr
[9];
144 HANDLE DfInput
= GetStdHandle (STD_INPUT_HANDLE
);
149 #ifdef TIMER_AVAILABLE
150 /* -------- test for a clock event (one/second) ------- */
151 if (DfTimedOut(clocktimer
))
153 /* ----- get the current time ----- */
154 time_t t
= time(NULL
);
156 hr
= now
->tm_hour
> 12 ?
161 sprintf(timestr
, "%2d:%02d", hr
, now
->tm_min
);
162 strcpy(timestr
+5, now
->tm_hour
> 11 ? "pm " : "am ");
163 /* ------- blink the : at one-second intervals ----- */
167 /* -------- reset the timer -------- */
168 DfSetTimer(clocktimer
, 1);
169 /* -------- post the clock event -------- */
170 PostEvent(DFM_CLOCKTICK
, (DF_PARAM
)timestr
, 0);
174 // WaitForSingleObject (DfInput, INFINITE);
175 ReadConsoleInput (DfInput
, &ir
, 1, &dwRead
);
177 if ((ir
.EventType
== KEY_EVENT
) &&
178 (ir
.Event
.KeyEvent
.bKeyDown
== TRUE
))
180 /* handle key down events */
182 /* handle shift state changes */
183 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
184 (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
188 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
189 (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
193 if (ir
.Event
.KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
)
195 sk
|= DF_LEFTSHIFT
+ DF_RIGHTSHIFT
;
198 if (sk
!= OldShiftKeys
)
201 /* the shift status changed */
202 PostEvent(DFM_SHIFT_CHANGED
, sk
, 0);
211 if (ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0)
213 switch (ir
.Event
.KeyEvent
.wVirtualKeyCode
)
222 else if (sk
& DF_CTRLKEY
)
277 /* special handling of SHIFT+TAB */
278 if (ir
.Event
.KeyEvent
.uChar
.AsciiChar
== VK_TAB
&&
279 (ir
.Event
.KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
))
282 c
= ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
285 PostEvent (DFM_KEYBOARD
, c
, sk
);
287 else if (ir
.EventType
== MOUSE_EVENT
)
289 /* handle mouse events */
290 if (ir
.Event
.MouseEvent
.dwEventFlags
== MOUSE_MOVED
)
292 PostEvent (MOUSE_MOVED
,
293 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
294 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
296 else if (ir
.Event
.MouseEvent
.dwEventFlags
== DOUBLE_CLICK
)
298 if (ir
.Event
.MouseEvent
.dwButtonState
==
299 FROM_LEFT_1ST_BUTTON_PRESSED
)
301 PostEvent (DOUBLE_CLICK
,
302 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
303 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
306 else if (ir
.Event
.MouseEvent
.dwEventFlags
== 0)
309 if (ir
.Event
.MouseEvent
.dwButtonState
==
310 FROM_LEFT_1ST_BUTTON_PRESSED
)
312 PostEvent (DFM_LEFT_BUTTON
,
313 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
314 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
316 else if (ir
.Event
.MouseEvent
.dwButtonState
==
317 RIGHTMOST_BUTTON_PRESSED
)
319 PostEvent (DFM_RIGHT_BUTTON
,
320 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
321 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
323 else if (ir
.Event
.MouseEvent
.dwButtonState
== 0)
325 PostEvent (DFM_BUTTON_RELEASED
,
326 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
327 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
334 /* ----- post a message and parameters to msg queue ---- */
335 void DfPostMessage(DFWINDOW wnd
, DFMESSAGE msg
, DF_PARAM p1
, DF_PARAM p2
)
337 if (msg
== DFM_ENDDIALOG
)
343 if (MsgQueueCtr
!= DF_MAXMESSAGES
)
345 MsgQueue
[MsgQueueOnCtr
].wnd
= wnd
;
346 MsgQueue
[MsgQueueOnCtr
].msg
= msg
;
347 MsgQueue
[MsgQueueOnCtr
].p1
= p1
;
348 MsgQueue
[MsgQueueOnCtr
].p2
= p2
;
349 if (++MsgQueueOnCtr
== DF_MAXMESSAGES
)
355 /* --------- send a message to a window ----------- */
356 int DfSendMessage(DFWINDOW wnd
, DFMESSAGE msg
, DF_PARAM p1
, DF_PARAM p2
)
358 int rtn
= TRUE
, x
, y
;
360 #ifdef INCLUDE_LOGGING
361 DfLogMessages(wnd
, msg
, p1
, p2
);
367 /* ------- don't send these messages unless the
368 window is visible -------- */
369 if (DfIsVisible(wnd
))
370 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
372 case DFM_RIGHT_BUTTON
:
373 case DFM_LEFT_BUTTON
:
375 case DFM_BUTTON_RELEASED
:
376 /* --- don't send these messages unless the
377 window is visible or has captured the mouse -- */
378 if (DfIsVisible(wnd
) || wnd
== DfCaptureMouse
)
379 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
382 case DFM_SHIFT_CHANGED
:
383 /* ------- don't send these messages unless the
384 window is visible or has captured the keyboard -- */
385 if (!(DfIsVisible(wnd
) || wnd
== DfCaptureKeyboard
))
388 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
391 /* ----- window processor returned true or the message was sent
392 to no window at all (NULL) ----- */
394 /* --------- process messages that a window sends to the
395 system itself ---------- */
400 /* ------- clock messages --------- */
401 case DFM_CAPTURE_CLOCK
:
403 DfSetTimer(clocktimer
, 0);
405 case DFM_RELEASE_CLOCK
:
407 DfDisableTimer(clocktimer
);
409 /* -------- keyboard messages ------- */
410 case DFM_KEYBOARD_CURSOR
:
412 DfCursor((int)p1
, (int)p2
);
413 else if (wnd
== DfInFocus
)
414 DfCursor(DfGetClientLeft(wnd
)+(int)p1
,
415 DfGetClientTop(wnd
)+(int)p2
);
417 case DFM_CAPTURE_KEYBOARD
:
419 ((DFWINDOW
)p2
)->PrevKeyboard
=DfCaptureKeyboard
;
421 wnd
->PrevKeyboard
= DfCaptureKeyboard
;
422 DfCaptureKeyboard
= wnd
;
423 NoChildCaptureKeyboard
= (int)p1
;
425 case DFM_RELEASE_KEYBOARD
:
428 if (DfCaptureKeyboard
== wnd
|| (int)p1
)
429 DfCaptureKeyboard
= wnd
->PrevKeyboard
;
432 DFWINDOW twnd
= DfCaptureKeyboard
;
435 if (twnd
->PrevKeyboard
== wnd
)
437 twnd
->PrevKeyboard
= wnd
->PrevKeyboard
;
440 twnd
= twnd
->PrevKeyboard
;
443 DfCaptureKeyboard
= NULL
;
445 wnd
->PrevKeyboard
= NULL
;
448 DfCaptureKeyboard
= NULL
;
449 NoChildCaptureKeyboard
= FALSE
;
451 case DFM_CURRENT_KEYBOARD_CURSOR
:
452 DfCurrCursor(&x
, &y
);
456 case DFM_SAVE_CURSOR
:
459 case DFM_RESTORE_CURSOR
:
462 case DFM_HIDE_CURSOR
:
466 case DFM_SHOW_CURSOR
:
468 DfSetCursorSize(100);
474 case DFM_CAPTURE_MOUSE
:
476 ((DFWINDOW
)p2
)->PrevMouse
= DfCaptureMouse
;
478 wnd
->PrevMouse
= DfCaptureMouse
;
479 DfCaptureMouse
= wnd
;
480 NoChildCaptureMouse
= (int)p1
;
483 case DFM_RELEASE_MOUSE
:
486 if (DfCaptureMouse
== wnd
|| (int)p1
)
487 DfCaptureMouse
= wnd
->PrevMouse
;
490 DFWINDOW twnd
= DfCaptureMouse
;
493 if (twnd
->PrevMouse
== wnd
)
495 twnd
->PrevMouse
= wnd
->PrevMouse
;
498 twnd
= twnd
->PrevMouse
;
501 DfCaptureMouse
= NULL
;
503 wnd
->PrevMouse
= NULL
;
506 DfCaptureMouse
= NULL
;
507 NoChildCaptureMouse
= FALSE
;
517 static DFRECT
VisibleRect(DFWINDOW wnd
)
519 DFRECT rc
= DfWindowRect(wnd
);
520 if (!DfTestAttribute(wnd
, DF_NOCLIP
))
522 DFWINDOW pwnd
= DfGetParent(wnd
);
524 prc
= DfClientRect(pwnd
);
527 if (DfTestAttribute(pwnd
, DF_NOCLIP
))
529 rc
= DfSubRectangle(rc
, prc
);
530 if (!DfValidRect(rc
))
532 if ((pwnd
= DfGetParent(pwnd
)) != NULL
)
533 prc
= DfClientRect(pwnd
);
539 /* ----- find window that mouse coordinates are in --- */
540 static DFWINDOW
inWindow(DFWINDOW wnd
, int x
, int y
)
543 while (wnd
!= NULL
) {
544 if (DfIsVisible(wnd
)) {
546 DFRECT rc
= VisibleRect(wnd
);
547 if (DfInsideRect(x
, y
, rc
))
549 if ((wnd1
= inWindow(DfLastWindow(wnd
), x
, y
)) != NULL
)
554 wnd
= DfPrevWindow(wnd
);
559 static DFWINDOW
MouseWindow(int x
, int y
)
561 /* get the window in which a mouse event occurred */
562 DFWINDOW Mwnd
= inWindow(DfApplicationWindow
, x
, y
);
564 /* ---- process mouse captures ----- */
565 if (DfCaptureMouse
!= NULL
)
567 if (NoChildCaptureMouse
||
569 !DfIsAncestor(Mwnd
, DfCaptureMouse
))
570 Mwnd
= DfCaptureMouse
;
576 void DfHandshake(void)
579 DfDispatchMessage ();
584 /* ---- dispatch messages to the message proc function ---- */
585 BOOL
DfDispatchMessage (void)
589 /* -------- collect mouse and keyboard events ------- */
592 /* --------- dequeue and process events -------- */
593 while (EventQueueCtr
> 0)
597 ev
= EventQueue
[EventQueueOffCtr
];
598 if (++EventQueueOffCtr
== DF_MAXMESSAGES
)
599 EventQueueOffCtr
= 0;
602 /* get the window in which a keyboard event occurred */
605 /* process keyboard captures */
606 if (DfCaptureKeyboard
!= NULL
)
609 NoChildCaptureKeyboard
||
610 !DfIsAncestor(Kwnd
, DfCaptureKeyboard
))
611 Kwnd
= DfCaptureKeyboard
;
614 /* send mouse and keyboard messages to the
615 window that should get them */
618 case DFM_SHIFT_CHANGED
:
621 DfSendMessage(Kwnd
, ev
.event
, ev
.mx
, ev
.my
);
624 case DFM_LEFT_BUTTON
:
627 Mwnd
= MouseWindow(ev
.mx
, ev
.my
);
628 if (!DfCaptureMouse
||
629 (!NoChildCaptureMouse
&&
630 DfIsAncestor(Mwnd
, DfCaptureMouse
)))
632 if (Mwnd
!= DfInFocus
)
633 DfSendMessage(Mwnd
, DFM_SETFOCUS
, TRUE
, 0);
634 DfSendMessage(Mwnd
, DFM_LEFT_BUTTON
, ev
.mx
, ev
.my
);
639 case DFM_BUTTON_RELEASED
:
641 case DFM_RIGHT_BUTTON
:
646 Mwnd
= MouseWindow(ev
.mx
, ev
.my
);
647 DfSendMessage(Mwnd
, ev
.event
, ev
.mx
, ev
.my
);
651 DfSendMessage(Cwnd
, ev
.event
, ev
.mx
, ev
.my
);
659 /* ------ dequeue and process messages ----- */
660 while (MsgQueueCtr
> 0)
664 mq
= MsgQueue
[MsgQueueOffCtr
];
666 if (++MsgQueueOffCtr
== DF_MAXMESSAGES
)
670 DfSendMessage (mq
.wnd
, mq
.msg
, mq
.p1
, mq
.p2
);
671 if (mq
.msg
== DFM_ENDDIALOG
)
674 if (mq
.msg
== DFM_STOP
)