1 /* --------- message.c ---------- */
5 static int handshaking
= 0;
7 BOOL AllocTesting
= FALSE
;
11 /* ---------- event queue ---------- */
17 } EventQueue
[MAXMESSAGES
];
19 /* ---------- message queue --------- */
26 } MsgQueue
[MAXMESSAGES
];
28 static int EventQueueOnCtr
;
29 static int EventQueueOffCtr
;
30 static int EventQueueCtr
;
32 static int MsgQueueOnCtr
;
33 static int MsgQueueOffCtr
;
34 static int MsgQueueCtr
;
37 DFWINDOW CaptureMouse
;
38 DFWINDOW CaptureKeyboard
;
39 static BOOL NoChildCaptureMouse
;
40 static BOOL NoChildCaptureKeyboard
;
42 static int doubletimer
= -1;
43 static int delaytimer
= -1;
44 static int clocktimer
= -1;
48 static char ermsg
[] = "Error accessing drive x";
51 static void StopMsg(void)
59 /* ------------ initialize the message system --------- */
60 BOOL
init_messages (VOID
)
63 if (setjmp(AllocError
) != 0)
69 /* enable mouse events */
70 SetConsoleMode (GetStdHandle (STD_INPUT_HANDLE
),
77 CaptureKeyboard
= NULL
;
78 NoChildCaptureMouse
= FALSE
;
79 NoChildCaptureKeyboard
= FALSE
;
86 DfPostMessage (NULL
, DFM_START
, 0, 0);
91 /* ----- post an event and parameters to event queue ---- */
92 static void PostEvent(DFMESSAGE event
, int p1
, int p2
)
94 if (EventQueueCtr
!= MAXMESSAGES
) {
95 EventQueue
[EventQueueOnCtr
].event
= event
;
96 EventQueue
[EventQueueOnCtr
].mx
= p1
;
97 EventQueue
[EventQueueOnCtr
].my
= p2
;
98 if (++EventQueueOnCtr
== MAXMESSAGES
)
104 /* ------ collect mouse, clock, and keyboard events ----- */
105 static void collect_events(void)
107 static int OldShiftKeys
= 0;
110 #ifdef TIMER_AVAILABLE
111 static BOOL flipflop
= FALSE
;
112 static char timestr
[9];
117 HANDLE hInput
= GetStdHandle (STD_INPUT_HANDLE
);
122 #ifdef TIMER_AVAILABLE
123 /* -------- test for a clock event (one/second) ------- */
124 if (timed_out(clocktimer
))
126 /* ----- get the current time ----- */
127 time_t t
= time(NULL
);
129 hr
= now
->tm_hour
> 12 ?
134 sprintf(timestr
, "%2d:%02d", hr
, now
->tm_min
);
135 strcpy(timestr
+5, now
->tm_hour
> 11 ? "pm " : "am ");
136 /* ------- blink the : at one-second intervals ----- */
140 /* -------- reset the timer -------- */
141 set_timer(clocktimer
, 1);
142 /* -------- post the clock event -------- */
143 PostEvent(CLOCKTICK
, (PARAM
)timestr
, 0);
147 // WaitForSingleObject (hInput, INFINITE);
148 ReadConsoleInput (hInput
, &ir
, 1, &dwRead
);
150 if ((ir
.EventType
== KEY_EVENT
) &&
151 (ir
.Event
.KeyEvent
.bKeyDown
== TRUE
))
153 /* handle key down events */
155 /* handle shift state changes */
156 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
157 (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
161 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
162 (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
168 if (sk
!= OldShiftKeys
)
171 /* the shift status changed */
172 PostEvent(SHIFT_CHANGED
, sk
, 0);
180 if (ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0)
182 switch (ir
.Event
.KeyEvent
.wVirtualKeyCode
)
191 else if (sk
& CTRLKEY
)
237 c
= ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
239 PostEvent (KEYBOARD
, c
, sk
);
241 else if (ir
.EventType
== MOUSE_EVENT
)
243 /* handle mouse events */
244 if (ir
.Event
.MouseEvent
.dwEventFlags
== MOUSE_MOVED
)
246 PostEvent (MOUSE_MOVED
,
247 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
248 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
250 else if (ir
.Event
.MouseEvent
.dwEventFlags
== DOUBLE_CLICK
)
252 if (ir
.Event
.MouseEvent
.dwButtonState
==
253 FROM_LEFT_1ST_BUTTON_PRESSED
)
255 PostEvent (DOUBLE_CLICK
,
256 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
257 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
260 else if (ir
.Event
.MouseEvent
.dwEventFlags
== 0)
263 if (ir
.Event
.MouseEvent
.dwButtonState
==
264 FROM_LEFT_1ST_BUTTON_PRESSED
)
266 PostEvent (LEFT_BUTTON
,
267 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
268 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
270 else if (ir
.Event
.MouseEvent
.dwButtonState
==
271 RIGHTMOST_BUTTON_PRESSED
)
273 PostEvent (RIGHT_BUTTON
,
274 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
275 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
277 else if (ir
.Event
.MouseEvent
.dwButtonState
== 0)
279 PostEvent (DFM_BUTTON_RELEASED
,
280 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
281 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
288 /* --------- keyboard events ---------- */
289 if ((sk
= getshift()) != ShiftKeys
)
292 /* ---- the shift status changed ---- */
293 PostEvent(SHIFT_CHANGED
, sk
, 0);
298 /* ---- build keyboard events for key combinations that
299 BIOS doesn't report --------- */
301 if (keyportvalue
== 14) {
303 PostEvent(KEYBOARD
, ALT_BS
, sk
);
305 if (keyportvalue
== 83) {
307 PostEvent(KEYBOARD
, ALT_DEL
, sk
);
314 if (keyportvalue
== 82) {
315 PostEvent(KEYBOARD
, CTRL_INS
, sk
);
318 /* ----------- test for keystroke ------- */
320 static int cvt
[] = {SHIFT_INS
,END
,DN
,PGDN
,BS
,'5',
326 c
= ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
329 /* -------- convert numeric pad keys ------- */
330 if (sk
& (LEFTSHIFT
| RIGHTSHIFT
))
332 if (c
>= '0' && c
<= '9')
334 else if (c
== '.' || c
== DEL
)
339 /* ------ post the keyboard event ------ */
340 PostEvent(KEYBOARD
, c
, sk
);
345 /* ----- post a message and parameters to msg queue ---- */
346 void DfPostMessage(DFWINDOW wnd
, DFMESSAGE msg
, PARAM p1
, PARAM p2
)
348 if (msg
== ENDDIALOG
)
354 if (MsgQueueCtr
!= MAXMESSAGES
)
356 MsgQueue
[MsgQueueOnCtr
].wnd
= wnd
;
357 MsgQueue
[MsgQueueOnCtr
].msg
= msg
;
358 MsgQueue
[MsgQueueOnCtr
].p1
= p1
;
359 MsgQueue
[MsgQueueOnCtr
].p2
= p2
;
360 if (++MsgQueueOnCtr
== MAXMESSAGES
)
366 /* --------- send a message to a window ----------- */
367 int DfSendMessage(DFWINDOW wnd
, DFMESSAGE msg
, PARAM p1
, PARAM p2
)
369 int rtn
= TRUE
, x
, y
;
371 #ifdef INCLUDE_LOGGING
372 LogMessages(wnd
, msg
, p1
, p2
);
378 /* ------- don't send these messages unless the
379 window is visible -------- */
381 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
386 case DFM_BUTTON_RELEASED
:
387 /* --- don't send these messages unless the
388 window is visible or has captured the mouse -- */
389 if (isVisible(wnd
) || wnd
== CaptureMouse
)
390 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
394 /* ------- don't send these messages unless the
395 window is visible or has captured the keyboard -- */
396 if (!(isVisible(wnd
) || wnd
== CaptureKeyboard
))
399 rtn
= (*wnd
->wndproc
)(wnd
, msg
, p1
, p2
);
402 /* ----- window processor returned true or the message was sent
403 to no window at all (NULL) ----- */
405 /* --------- process messages that a window sends to the
406 system itself ---------- */
411 /* ------- clock messages --------- */
414 set_timer(clocktimer
, 0);
418 disable_timer(clocktimer
);
420 /* -------- keyboard messages ------- */
421 case KEYBOARD_CURSOR
:
423 cursor((int)p1
, (int)p2
);
424 else if (wnd
== inFocus
)
425 cursor(GetClientLeft(wnd
)+(int)p1
,
426 GetClientTop(wnd
)+(int)p2
);
428 case CAPTURE_KEYBOARD
:
430 ((DFWINDOW
)p2
)->PrevKeyboard
=CaptureKeyboard
;
432 wnd
->PrevKeyboard
= CaptureKeyboard
;
433 CaptureKeyboard
= wnd
;
434 NoChildCaptureKeyboard
= (int)p1
;
436 case RELEASE_KEYBOARD
:
439 if (CaptureKeyboard
== wnd
|| (int)p1
)
440 CaptureKeyboard
= wnd
->PrevKeyboard
;
443 DFWINDOW twnd
= CaptureKeyboard
;
446 if (twnd
->PrevKeyboard
== wnd
)
448 twnd
->PrevKeyboard
= wnd
->PrevKeyboard
;
451 twnd
= twnd
->PrevKeyboard
;
454 CaptureKeyboard
= NULL
;
456 wnd
->PrevKeyboard
= NULL
;
459 CaptureKeyboard
= NULL
;
460 NoChildCaptureKeyboard
= FALSE
;
462 case CURRENT_KEYBOARD_CURSOR
:
479 set_cursor_type(0x0106);
481 set_cursor_type(0x0607);
487 ((DFWINDOW
)p2
)->PrevMouse
= CaptureMouse
;
489 wnd
->PrevMouse
= CaptureMouse
;
491 NoChildCaptureMouse
= (int)p1
;
497 if (CaptureMouse
== wnd
|| (int)p1
)
498 CaptureMouse
= wnd
->PrevMouse
;
501 DFWINDOW twnd
= CaptureMouse
;
504 if (twnd
->PrevMouse
== wnd
)
506 twnd
->PrevMouse
= wnd
->PrevMouse
;
509 twnd
= twnd
->PrevMouse
;
514 wnd
->PrevMouse
= NULL
;
518 NoChildCaptureMouse
= FALSE
;
528 static DFRECT
VisibleRect(DFWINDOW wnd
)
530 DFRECT rc
= WindowRect(wnd
);
531 if (!TestAttribute(wnd
, NOCLIP
))
533 DFWINDOW pwnd
= GetParent(wnd
);
535 prc
= ClientRect(pwnd
);
538 if (TestAttribute(pwnd
, NOCLIP
))
540 rc
= subRectangle(rc
, prc
);
543 if ((pwnd
= GetParent(pwnd
)) != NULL
)
544 prc
= ClientRect(pwnd
);
550 /* ----- find window that mouse coordinates are in --- */
551 static DFWINDOW
inWindow(DFWINDOW wnd
, int x
, int y
)
554 while (wnd
!= NULL
) {
555 if (isVisible(wnd
)) {
557 DFRECT rc
= VisibleRect(wnd
);
558 if (InsideRect(x
, y
, rc
))
560 if ((wnd1
= inWindow(LastWindow(wnd
), x
, y
)) != NULL
)
565 wnd
= PrevWindow(wnd
);
570 static DFWINDOW
MouseWindow(int x
, int y
)
572 /* get the window in which a mouse event occurred */
573 DFWINDOW Mwnd
= inWindow(ApplicationWindow
, x
, y
);
575 /* ---- process mouse captures ----- */
576 if (CaptureMouse
!= NULL
)
578 if (NoChildCaptureMouse
||
580 !isAncestor(Mwnd
, CaptureMouse
))
590 DfDispatchMessage ();
595 /* ---- dispatch messages to the message proc function ---- */
596 BOOL
DfDispatchMessage (void)
600 /* -------- collect mouse and keyboard events ------- */
603 /* --------- dequeue and process events -------- */
604 while (EventQueueCtr
> 0)
608 ev
= EventQueue
[EventQueueOffCtr
];
609 if (++EventQueueOffCtr
== MAXMESSAGES
)
610 EventQueueOffCtr
= 0;
613 /* get the window in which a keyboard event occurred */
616 /* process keyboard captures */
617 if (CaptureKeyboard
!= NULL
)
620 NoChildCaptureKeyboard
||
621 !isAncestor(Kwnd
, CaptureKeyboard
))
622 Kwnd
= CaptureKeyboard
;
625 /* send mouse and keyboard messages to the
626 window that should get them */
632 DfSendMessage(Kwnd
, ev
.event
, ev
.mx
, ev
.my
);
638 Mwnd
= MouseWindow(ev
.mx
, ev
.my
);
640 (!NoChildCaptureMouse
&&
641 isAncestor(Mwnd
, CaptureMouse
)))
644 DfSendMessage(Mwnd
, SETFOCUS
, TRUE
, 0);
645 DfSendMessage(Mwnd
, LEFT_BUTTON
, ev
.mx
, ev
.my
);
650 case DFM_BUTTON_RELEASED
:
657 Mwnd
= MouseWindow(ev
.mx
, ev
.my
);
658 DfSendMessage(Mwnd
, ev
.event
, ev
.mx
, ev
.my
);
662 DfSendMessage(Cwnd
, ev
.event
, ev
.mx
, ev
.my
);
670 /* ------ dequeue and process messages ----- */
671 while (MsgQueueCtr
> 0)
675 mq
= MsgQueue
[MsgQueueOffCtr
];
677 if (++MsgQueueOffCtr
== MAXMESSAGES
)
681 DfSendMessage (mq
.wnd
, mq
.msg
, mq
.p1
, mq
.p2
);
682 if (mq
.msg
== ENDDIALOG
)
685 if (mq
.msg
== DFM_STOP
)