Making dflat32 a dll. Its a little broken ATM.
[reactos.git] / rosapps / lib / dflat32 / message.c
1 /* --------- message.c ----------
2 * Message Que code for all events that dflat32
3 * should know how to handle.
4 *
5 * You understand this? Good I'm glad one of us
6 * does. - sedwards 3-24-02
7 */
8
9 #include <dflat32/dflat.h>
10 #include <dflat32/system.h>
11
12 static int handshaking = 0;
13
14 BOOL AllocTesting = FALSE;
15 jmp_buf AllocError;
16 BOOL AltDown = FALSE;
17
18 /* ---------- event queue ---------- */
19 static struct events
20 {
21 DFMESSAGE event;
22 int mx;
23 int my;
24 } EventQueue[MAXMESSAGES];
25
26 /* ---------- message queue --------- */
27 static struct msgs
28 {
29 DFWINDOW wnd;
30 DFMESSAGE msg;
31 PARAM p1;
32 PARAM p2;
33 } MsgQueue[MAXMESSAGES];
34
35 static int EventQueueOnCtr;
36 static int EventQueueOffCtr;
37 static int EventQueueCtr;
38
39 static int MsgQueueOnCtr;
40 static int MsgQueueOffCtr;
41 static int MsgQueueCtr;
42
43
44 DFWINDOW CaptureMouse;
45 DFWINDOW CaptureKeyboard;
46 static BOOL NoChildCaptureMouse;
47 static BOOL NoChildCaptureKeyboard;
48
49 static int doubletimer = -1;
50 static int delaytimer = -1;
51 static int clocktimer = -1;
52
53 static DFWINDOW Cwnd;
54
55 static char ermsg[] = "Error accessing drive x";
56
57
58 static void StopMsg(void)
59 {
60 ClearClipboard();
61 ClearDialogBoxes();
62 restorecursor();
63 unhidecursor();
64 }
65
66 SHORT DfGetScreenHeight (void)
67 {
68 return sScreenHeight;
69 }
70
71 SHORT DfGetScreenWidth (void)
72 {
73 return sScreenWidth;
74 }
75
76 /* ------------ initialize the message system --------- */
77 BOOL DfInitialize (VOID)
78 {
79 CONSOLE_SCREEN_BUFFER_INFO csbi;
80
81 AllocTesting = TRUE;
82 if (setjmp(AllocError) != 0)
83 {
84 StopMsg();
85 return FALSE;
86 }
87
88 /* get input and output handles */
89 hInput = GetStdHandle (STD_INPUT_HANDLE);
90 hOutput = GetStdHandle (STD_OUTPUT_HANDLE);
91
92 /* get screen size */
93 GetConsoleScreenBufferInfo (hOutput, &csbi);
94 sScreenHeight = (csbi.srWindow.Bottom - csbi.srWindow.Top) + 1;
95 sScreenWidth = (csbi.srWindow.Right - csbi.srWindow.Left) + 1;
96
97 /* enable mouse events */
98 SetConsoleMode (hInput, ENABLE_MOUSE_INPUT);
99
100 savecursor();
101 hidecursor();
102
103 CaptureMouse = NULL;
104 CaptureKeyboard = NULL;
105 NoChildCaptureMouse = FALSE;
106 NoChildCaptureKeyboard = FALSE;
107 MsgQueueOnCtr = 0;
108 MsgQueueOffCtr = 0;
109 MsgQueueCtr = 0;
110 EventQueueOnCtr = 0;
111 EventQueueOffCtr = 0;
112 EventQueueCtr = 0;
113 DfPostMessage (NULL, DFM_START, 0, 0);
114
115 return TRUE;
116 }
117
118
119 void DfTerminate (void)
120 {
121
122 }
123
124 /* ----- post an event and parameters to event queue ---- */
125 static void PostEvent(DFMESSAGE event, int p1, int p2)
126 {
127 if (EventQueueCtr != MAXMESSAGES) {
128 EventQueue[EventQueueOnCtr].event = event;
129 EventQueue[EventQueueOnCtr].mx = p1;
130 EventQueue[EventQueueOnCtr].my = p2;
131 if (++EventQueueOnCtr == MAXMESSAGES)
132 EventQueueOnCtr = 0;
133 EventQueueCtr++;
134 }
135 }
136
137 /* ------ collect mouse, clock, and keyboard events ----- */
138 static void collect_events(void)
139 {
140 static int OldShiftKeys = 0;
141 int sk = 0;
142
143 #ifdef TIMER_AVAILABLE
144 static BOOL flipflop = FALSE;
145 static char timestr[9];
146 struct tm *now;
147 int hr;
148 #endif
149
150 HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
151 INPUT_RECORD ir;
152 DWORD dwRead;
153 int c;
154
155 #ifdef TIMER_AVAILABLE
156 /* -------- test for a clock event (one/second) ------- */
157 if (timed_out(clocktimer))
158 {
159 /* ----- get the current time ----- */
160 time_t t = time(NULL);
161 now = localtime(&t);
162 hr = now->tm_hour > 12 ?
163 now->tm_hour - 12 :
164 now->tm_hour;
165 if (hr == 0)
166 hr = 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 ----- */
170 if (flipflop)
171 *(timestr+2) = ' ';
172 flipflop ^= TRUE;
173 /* -------- reset the timer -------- */
174 set_timer(clocktimer, 1);
175 /* -------- post the clock event -------- */
176 PostEvent(CLOCKTICK, (PARAM)timestr, 0);
177 }
178 #endif
179
180 // WaitForSingleObject (hInput, INFINITE);
181 ReadConsoleInput (hInput, &ir, 1, &dwRead);
182
183 if ((ir.EventType == KEY_EVENT) &&
184 (ir.Event.KeyEvent.bKeyDown == TRUE))
185 {
186 /* handle key down events */
187
188 /* handle shift state changes */
189 if (ir.Event.KeyEvent.dwControlKeyState &
190 (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
191 {
192 sk |= ALTKEY;
193 }
194 if (ir.Event.KeyEvent.dwControlKeyState &
195 (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
196 {
197 sk |= CTRLKEY;
198 }
199 if (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
200 {
201 sk |= LEFTSHIFT + RIGHTSHIFT;
202 }
203
204 if (sk != OldShiftKeys)
205 {
206 OldShiftKeys = sk;
207 /* the shift status changed */
208 PostEvent(SHIFT_CHANGED, sk, 0);
209 #if 0
210 if (sk & ALTKEY)
211 AltDown = TRUE;
212 else
213 AltDown = FALSE;
214 #endif
215 }
216
217 if (ir.Event.KeyEvent.uChar.AsciiChar == 0)
218 {
219 switch (ir.Event.KeyEvent.wVirtualKeyCode)
220 {
221 case VK_F1:
222 c = F1;
223 break;
224
225 case VK_F4:
226 if (sk & ALTKEY)
227 c = ALT_F4;
228 else if (sk & CTRLKEY)
229 c = CTRL_F4;
230 else
231 c = F4;
232
233 case VK_F10:
234 c = F10;
235 break;
236
237 case VK_UP:
238 c = UP;
239 break;
240
241 case VK_DOWN:
242 c = DN;
243 break;
244
245 case VK_LEFT:
246 c = BS;
247 break;
248
249 case VK_RIGHT:
250 c = FWD;
251 break;
252
253 case VK_INSERT:
254 c = INS;
255 break;
256
257 case VK_DELETE:
258 c = DEL;
259 break;
260
261 case VK_HOME:
262 c = HOME;
263 break;
264
265 case VK_END:
266 c = END;
267 break;
268
269 case VK_PRIOR:
270 c = PGUP;
271 break;
272
273 case VK_NEXT:
274 c = PGDN;
275 break;
276
277 default:
278 return;
279 }
280 }
281 else
282 {
283 /* special handling of SHIFT+TAB */
284 if (ir.Event.KeyEvent.uChar.AsciiChar == VK_TAB &&
285 (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED))
286 c = SHIFT_HT;
287 else
288 c = ir.Event.KeyEvent.uChar.AsciiChar;
289 }
290
291 PostEvent (KEYBOARD, c, sk);
292 }
293 else if (ir.EventType == MOUSE_EVENT)
294 {
295 /* handle mouse events */
296 if (ir.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
297 {
298 PostEvent (MOUSE_MOVED,
299 ir.Event.MouseEvent.dwMousePosition.X,
300 ir.Event.MouseEvent.dwMousePosition.Y);
301 }
302 else if (ir.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
303 {
304 if (ir.Event.MouseEvent.dwButtonState ==
305 FROM_LEFT_1ST_BUTTON_PRESSED)
306 {
307 PostEvent (DOUBLE_CLICK,
308 ir.Event.MouseEvent.dwMousePosition.X,
309 ir.Event.MouseEvent.dwMousePosition.Y);
310 }
311 }
312 else if (ir.Event.MouseEvent.dwEventFlags == 0)
313 {
314 /* single click */
315 if (ir.Event.MouseEvent.dwButtonState ==
316 FROM_LEFT_1ST_BUTTON_PRESSED)
317 {
318 PostEvent (LEFT_BUTTON,
319 ir.Event.MouseEvent.dwMousePosition.X,
320 ir.Event.MouseEvent.dwMousePosition.Y);
321 }
322 else if (ir.Event.MouseEvent.dwButtonState ==
323 RIGHTMOST_BUTTON_PRESSED)
324 {
325 PostEvent (RIGHT_BUTTON,
326 ir.Event.MouseEvent.dwMousePosition.X,
327 ir.Event.MouseEvent.dwMousePosition.Y);
328 }
329 else if (ir.Event.MouseEvent.dwButtonState == 0)
330 {
331 PostEvent (DFM_BUTTON_RELEASED,
332 ir.Event.MouseEvent.dwMousePosition.X,
333 ir.Event.MouseEvent.dwMousePosition.Y);
334 }
335 }
336 }
337 }
338
339
340 /* ----- post a message and parameters to msg queue ---- */
341 void DfPostMessage(DFWINDOW wnd, DFMESSAGE msg, PARAM p1, PARAM p2)
342 {
343 if (msg == ENDDIALOG)
344 {
345 msg++;
346 --msg;
347 }
348
349 if (MsgQueueCtr != MAXMESSAGES)
350 {
351 MsgQueue[MsgQueueOnCtr].wnd = wnd;
352 MsgQueue[MsgQueueOnCtr].msg = msg;
353 MsgQueue[MsgQueueOnCtr].p1 = p1;
354 MsgQueue[MsgQueueOnCtr].p2 = p2;
355 if (++MsgQueueOnCtr == MAXMESSAGES)
356 MsgQueueOnCtr = 0;
357 MsgQueueCtr++;
358 }
359 }
360
361 /* --------- send a message to a window ----------- */
362 int DfSendMessage(DFWINDOW wnd, DFMESSAGE msg, PARAM p1, PARAM p2)
363 {
364 int rtn = TRUE, x, y;
365
366 #ifdef INCLUDE_LOGGING
367 LogMessages(wnd, msg, p1, p2);
368 #endif
369 if (wnd != NULL)
370 switch (msg) {
371 case PAINT:
372 case BORDER:
373 /* ------- don't send these messages unless the
374 window is visible -------- */
375 if (isVisible(wnd))
376 rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
377 break;
378 case RIGHT_BUTTON:
379 case LEFT_BUTTON:
380 case DOUBLE_CLICK:
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);
386 break;
387 case KEYBOARD:
388 case SHIFT_CHANGED:
389 /* ------- don't send these messages unless the
390 window is visible or has captured the keyboard -- */
391 if (!(isVisible(wnd) || wnd == CaptureKeyboard))
392 break;
393 default:
394 rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
395 break;
396 }
397 /* ----- window processor returned true or the message was sent
398 to no window at all (NULL) ----- */
399 if (rtn != FALSE) {
400 /* --------- process messages that a window sends to the
401 system itself ---------- */
402 switch (msg) {
403 case DFM_STOP:
404 StopMsg();
405 break;
406 /* ------- clock messages --------- */
407 case CAPTURE_CLOCK:
408 Cwnd = wnd;
409 set_timer(clocktimer, 0);
410 break;
411 case RELEASE_CLOCK:
412 Cwnd = NULL;
413 disable_timer(clocktimer);
414 break;
415 /* -------- keyboard messages ------- */
416 case KEYBOARD_CURSOR:
417 if (wnd == NULL)
418 cursor((int)p1, (int)p2);
419 else if (wnd == inFocus)
420 cursor(GetClientLeft(wnd)+(int)p1,
421 GetClientTop(wnd)+(int)p2);
422 break;
423 case CAPTURE_KEYBOARD:
424 if (p2)
425 ((DFWINDOW)p2)->PrevKeyboard=CaptureKeyboard;
426 else
427 wnd->PrevKeyboard = CaptureKeyboard;
428 CaptureKeyboard = wnd;
429 NoChildCaptureKeyboard = (int)p1;
430 break;
431 case RELEASE_KEYBOARD:
432 if (wnd != NULL)
433 {
434 if (CaptureKeyboard == wnd || (int)p1)
435 CaptureKeyboard = wnd->PrevKeyboard;
436 else
437 {
438 DFWINDOW twnd = CaptureKeyboard;
439 while (twnd != NULL)
440 {
441 if (twnd->PrevKeyboard == wnd)
442 {
443 twnd->PrevKeyboard = wnd->PrevKeyboard;
444 break;
445 }
446 twnd = twnd->PrevKeyboard;
447 }
448 if (twnd == NULL)
449 CaptureKeyboard = NULL;
450 }
451 wnd->PrevKeyboard = NULL;
452 }
453 else
454 CaptureKeyboard = NULL;
455 NoChildCaptureKeyboard = FALSE;
456 break;
457 case CURRENT_KEYBOARD_CURSOR:
458 curr_cursor(&x, &y);
459 *(int*)p1 = x;
460 *(int*)p2 = y;
461 break;
462 case SAVE_CURSOR:
463 savecursor();
464 break;
465 case RESTORE_CURSOR:
466 restorecursor();
467 break;
468 case HIDE_CURSOR:
469 normalcursor();
470 hidecursor();
471 break;
472 case SHOW_CURSOR:
473 if (p1)
474 set_cursor_size(100);
475 else
476 set_cursor_size(5);
477 unhidecursor();
478 break;
479
480 case CAPTURE_MOUSE:
481 if (p2)
482 ((DFWINDOW)p2)->PrevMouse = CaptureMouse;
483 else
484 wnd->PrevMouse = CaptureMouse;
485 CaptureMouse = wnd;
486 NoChildCaptureMouse = (int)p1;
487 break;
488
489 case RELEASE_MOUSE:
490 if (wnd != NULL)
491 {
492 if (CaptureMouse == wnd || (int)p1)
493 CaptureMouse = wnd->PrevMouse;
494 else
495 {
496 DFWINDOW twnd = CaptureMouse;
497 while (twnd != NULL)
498 {
499 if (twnd->PrevMouse == wnd)
500 {
501 twnd->PrevMouse = wnd->PrevMouse;
502 break;
503 }
504 twnd = twnd->PrevMouse;
505 }
506 if (twnd == NULL)
507 CaptureMouse = NULL;
508 }
509 wnd->PrevMouse = NULL;
510 }
511 else
512 CaptureMouse = NULL;
513 NoChildCaptureMouse = FALSE;
514 break;
515
516 default:
517 break;
518 }
519 }
520 return rtn;
521 }
522
523 static DFRECT VisibleRect(DFWINDOW wnd)
524 {
525 DFRECT rc = WindowRect(wnd);
526 if (!TestAttribute(wnd, NOCLIP))
527 {
528 DFWINDOW pwnd = GetParent(wnd);
529 DFRECT prc;
530 prc = ClientRect(pwnd);
531 while (pwnd != NULL)
532 {
533 if (TestAttribute(pwnd, NOCLIP))
534 break;
535 rc = subRectangle(rc, prc);
536 if (!ValidRect(rc))
537 break;
538 if ((pwnd = GetParent(pwnd)) != NULL)
539 prc = ClientRect(pwnd);
540 }
541 }
542 return rc;
543 }
544
545 /* ----- find window that mouse coordinates are in --- */
546 static DFWINDOW inWindow(DFWINDOW wnd, int x, int y)
547 {
548 DFWINDOW Hit = NULL;
549 while (wnd != NULL) {
550 if (isVisible(wnd)) {
551 DFWINDOW wnd1;
552 DFRECT rc = VisibleRect(wnd);
553 if (InsideRect(x, y, rc))
554 Hit = wnd;
555 if ((wnd1 = inWindow(LastWindow(wnd), x, y)) != NULL)
556 Hit = wnd1;
557 if (Hit != NULL)
558 break;
559 }
560 wnd = PrevWindow(wnd);
561 }
562 return Hit;
563 }
564
565 static DFWINDOW MouseWindow(int x, int y)
566 {
567 /* get the window in which a mouse event occurred */
568 DFWINDOW Mwnd = inWindow(ApplicationWindow, x, y);
569
570 /* ---- process mouse captures ----- */
571 if (CaptureMouse != NULL)
572 {
573 if (NoChildCaptureMouse ||
574 Mwnd == NULL ||
575 !isAncestor(Mwnd, CaptureMouse))
576 Mwnd = CaptureMouse;
577 }
578 return Mwnd;
579 }
580
581
582 void handshake(void)
583 {
584 handshaking++;
585 DfDispatchMessage ();
586 --handshaking;
587 }
588
589
590 /* ---- dispatch messages to the message proc function ---- */
591 BOOL DfDispatchMessage (void)
592 {
593 DFWINDOW Mwnd, Kwnd;
594
595 /* -------- collect mouse and keyboard events ------- */
596 collect_events();
597
598 /* --------- dequeue and process events -------- */
599 while (EventQueueCtr > 0)
600 {
601 struct events ev;
602
603 ev = EventQueue[EventQueueOffCtr];
604 if (++EventQueueOffCtr == MAXMESSAGES)
605 EventQueueOffCtr = 0;
606 --EventQueueCtr;
607
608 /* get the window in which a keyboard event occurred */
609 Kwnd = inFocus;
610
611 /* process keyboard captures */
612 if (CaptureKeyboard != NULL)
613 {
614 if (Kwnd == NULL ||
615 NoChildCaptureKeyboard ||
616 !isAncestor(Kwnd, CaptureKeyboard))
617 Kwnd = CaptureKeyboard;
618 }
619
620 /* send mouse and keyboard messages to the
621 window that should get them */
622 switch (ev.event)
623 {
624 case SHIFT_CHANGED:
625 case KEYBOARD:
626 if (!handshaking)
627 DfSendMessage(Kwnd, ev.event, ev.mx, ev.my);
628 break;
629
630 case LEFT_BUTTON:
631 if (!handshaking)
632 {
633 Mwnd = MouseWindow(ev.mx, ev.my);
634 if (!CaptureMouse ||
635 (!NoChildCaptureMouse &&
636 isAncestor(Mwnd, CaptureMouse)))
637 {
638 if (Mwnd != inFocus)
639 DfSendMessage(Mwnd, SETFOCUS, TRUE, 0);
640 DfSendMessage(Mwnd, LEFT_BUTTON, ev.mx, ev.my);
641 }
642 }
643 break;
644
645 case DFM_BUTTON_RELEASED:
646 case DOUBLE_CLICK:
647 case RIGHT_BUTTON:
648 if (handshaking)
649 break;
650
651 case MOUSE_MOVED:
652 Mwnd = MouseWindow(ev.mx, ev.my);
653 DfSendMessage(Mwnd, ev.event, ev.mx, ev.my);
654 break;
655
656 case CLOCKTICK:
657 DfSendMessage(Cwnd, ev.event, ev.mx, ev.my);
658 break;
659
660 default:
661 break;
662 }
663 }
664
665 /* ------ dequeue and process messages ----- */
666 while (MsgQueueCtr > 0)
667 {
668 struct msgs mq;
669
670 mq = MsgQueue[MsgQueueOffCtr];
671
672 if (++MsgQueueOffCtr == MAXMESSAGES)
673 MsgQueueOffCtr = 0;
674 --MsgQueueCtr;
675
676 DfSendMessage (mq.wnd, mq.msg, mq.p1, mq.p2);
677 if (mq.msg == ENDDIALOG)
678 return FALSE;
679
680 if (mq.msg == DFM_STOP)
681 return FALSE;
682 }
683
684 return TRUE;
685 }
686
687 /* EOF */