Added D-Flat/32 library
[reactos.git] / rosapps / dflat32 / normal.c
1 /* ------------- normal.c ------------ */
2
3 #include "dflat.h"
4
5 #ifdef INCLUDE_MULTI_WINDOWS
6 static void PaintOverLappers(DFWINDOW wnd);
7 static void PaintUnderLappers(DFWINDOW wnd);
8 #endif
9
10 static BOOL InsideWindow(DFWINDOW, int, int);
11 static void TerminateMoveSize(void);
12 static void SaveBorder(DFRECT);
13 static void RestoreBorder(DFRECT);
14 static void GetVideoBuffer(DFWINDOW);
15 static void PutVideoBuffer(DFWINDOW);
16 #ifdef INCLUDE_MINIMIZE
17 static DFRECT PositionIcon(DFWINDOW);
18 #endif
19 static void dragborder(DFWINDOW, int, int);
20 static void sizeborder(DFWINDOW, int, int);
21 static int px = -1, py = -1;
22 static int diff;
23 static struct window dwnd = {DUMMY, NULL, NormalProc,
24 {-1,-1,-1,-1}};
25 static PCHAR_INFO Bsave;
26 static int Bht, Bwd;
27 BOOL WindowMoving;
28 BOOL WindowSizing;
29 /* -------- array of class definitions -------- */
30 CLASSDEFS classdefs[] = {
31 #undef ClassDef
32 #define ClassDef(c,b,p,a) {b,p,a},
33 #include "classes.h"
34 };
35 DFWINDOW HiddenWindow;
36
37 /* --------- CREATE_WINDOW Message ---------- */
38 static void CreateWindowMsg(DFWINDOW wnd)
39 {
40 AppendWindow(wnd);
41 // ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
42 if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
43 GetVideoBuffer(wnd);
44 }
45
46 /* --------- SHOW_WINDOW Message ---------- */
47 static void ShowWindowMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
48 {
49 if (GetParent(wnd) == NULL || isVisible(GetParent(wnd)))
50 {
51 DFWINDOW cwnd;
52
53 if (TestAttribute(wnd, SAVESELF) && wnd->videosave == NULL)
54 GetVideoBuffer(wnd);
55 SetVisible(wnd);
56 DfSendMessage(wnd, PAINT, 0, TRUE);
57 DfSendMessage(wnd, BORDER, 0, 0);
58 /* --- show the children of this window --- */
59 cwnd = FirstWindow(wnd);
60 while (cwnd != NULL)
61 {
62 if (cwnd->condition != ISCLOSING)
63 DfSendMessage(cwnd, SHOW_WINDOW, p1, p2);
64 cwnd = NextWindow(cwnd);
65 }
66 }
67 }
68
69 /* --------- HIDE_WINDOW Message ---------- */
70 static void HideWindowMsg(DFWINDOW wnd)
71 {
72 if (isVisible(wnd))
73 {
74 ClearVisible(wnd);
75 /* --- paint what this window covered --- */
76 if (TestAttribute(wnd, SAVESELF))
77 PutVideoBuffer(wnd);
78 #ifdef INCLUDE_MULTI_WINDOWS
79 else
80 PaintOverLappers(wnd);
81 #endif
82 }
83 }
84
85 /* --------- KEYBOARD Message ---------- */
86 static BOOL KeyboardMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
87 {
88 if (WindowMoving || WindowSizing) {
89 /* -- move or size a window with keyboard -- */
90 int x, y;
91 x=WindowMoving?GetLeft(&dwnd):GetRight(&dwnd);
92 y=WindowMoving?GetTop(&dwnd):GetBottom(&dwnd);
93 switch ((int)p1) {
94 case ESC:
95 TerminateMoveSize();
96 return TRUE;
97 case UP:
98 if (y)
99 --y;
100 break;
101 case DN:
102 if (y < SCREENHEIGHT-1)
103 y++;
104 break;
105 case FWD:
106 if (x < SCREENWIDTH-1)
107 x++;
108 break;
109 case BS:
110 if (x)
111 --x;
112 break;
113 case '\r':
114 DfSendMessage(wnd, DFM_BUTTON_RELEASED,x,y);
115 default:
116 return TRUE;
117 }
118 /* -- use the mouse functions to move/size - */
119 DfSendMessage(wnd, MOUSE_MOVED, x, y);
120 return TRUE;
121 }
122
123 switch ((int)p1)
124 {
125 case F1:
126 DfSendMessage(wnd, DFM_COMMAND, ID_HELP, 0);
127 return TRUE;
128
129 case ' ':
130 if ((int)p2 & ALTKEY)
131 if (TestAttribute(wnd, HASTITLEBAR))
132 if (TestAttribute(wnd, CONTROLBOX))
133 BuildSystemMenu(wnd);
134 return TRUE;
135
136 case CTRL_F4:
137 if (TestAttribute(wnd, CONTROLBOX))
138 {
139 DfSendMessage(wnd, CLOSE_WINDOW, 0, 0);
140 SkipApplicationControls();
141 return TRUE;
142 }
143 break;
144
145 default:
146 break;
147 }
148
149 return FALSE;
150 }
151
152 /* --------- COMMAND Message ---------- */
153 static void CommandMsg(DFWINDOW wnd, PARAM p1)
154 {
155 switch ((int)p1) {
156 case ID_HELP:
157 DisplayHelp(wnd,ClassNames[GetClass(wnd)]);
158 break;
159 #ifdef INCLUDE_RESTORE
160 case ID_SYSRESTORE:
161 DfSendMessage(wnd, RESTORE, 0, 0);
162 break;
163 #endif
164 case ID_SYSMOVE:
165 DfSendMessage(wnd, CAPTURE_MOUSE, TRUE,
166 (PARAM) &dwnd);
167 DfSendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
168 (PARAM) &dwnd);
169 WindowMoving = TRUE;
170 dragborder(wnd, GetLeft(wnd), GetTop(wnd));
171 break;
172 case ID_SYSSIZE:
173 DfSendMessage(wnd, CAPTURE_MOUSE, TRUE,
174 (PARAM) &dwnd);
175 DfSendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
176 (PARAM) &dwnd);
177 WindowSizing = TRUE;
178 dragborder(wnd, GetLeft(wnd), GetTop(wnd));
179 break;
180 #ifdef INCLUDE_MINIMIZE
181 case ID_SYSMINIMIZE:
182 DfSendMessage(wnd, MINIMIZE, 0, 0);
183 break;
184 #endif
185 #ifdef INCLUDE_MAXIMIZE
186 case ID_SYSMAXIMIZE:
187 DfSendMessage(wnd, MAXIMIZE, 0, 0);
188 break;
189 #endif
190 case ID_SYSCLOSE:
191 DfSendMessage(wnd, CLOSE_WINDOW, 0, 0);
192 SkipApplicationControls();
193 break;
194 default:
195 break;
196 }
197 }
198
199 /* --------- SETFOCUS Message ---------- */
200 static void SetFocusMsg(DFWINDOW wnd, PARAM p1)
201 {
202 DFRECT rc = {0,0,0,0};
203
204 if (p1 && wnd != NULL && inFocus != wnd)
205 {
206 DFWINDOW this, thispar;
207 DFWINDOW that = NULL, thatpar = NULL;
208
209 DFWINDOW cwnd = wnd, fwnd = GetParent(wnd);
210 /* ---- post focus in ancestors ---- */
211 while (fwnd != NULL)
212 {
213 fwnd->childfocus = cwnd;
214 cwnd = fwnd;
215 fwnd = GetParent(fwnd);
216 }
217 /* ---- de-post focus in self and children ---- */
218 fwnd = wnd;
219 while (fwnd != NULL)
220 {
221 cwnd = fwnd->childfocus;
222 fwnd->childfocus = NULL;
223 fwnd = cwnd;
224 }
225
226 this = wnd;
227 that = thatpar = inFocus;
228
229 /* ---- find common ancestor of prev focus and this window --- */
230 while (thatpar != NULL)
231 {
232 thispar = wnd;
233 while (thispar != NULL)
234 {
235 if (this == CaptureMouse || this == CaptureKeyboard)
236 {
237 /* ---- don't repaint if this window has capture ---- */
238 that = thatpar = NULL;
239 break;
240 }
241 if (thispar == thatpar)
242 {
243 /* ---- don't repaint if SAVESELF window had focus ---- */
244 if (this != that && TestAttribute(that, SAVESELF))
245 that = thatpar = NULL;
246 break;
247 }
248 this = thispar;
249 thispar = GetParent(thispar);
250 }
251 if (thispar != NULL)
252 break;
253 that = thatpar;
254 thatpar = GetParent(thatpar);
255 }
256 if (inFocus != NULL)
257 DfSendMessage(inFocus, SETFOCUS, FALSE, 0);
258 inFocus = wnd;
259 if (that != NULL && isVisible(wnd))
260 {
261 rc = subRectangle(WindowRect(that), WindowRect(this));
262 if (!ValidRect(rc))
263 {
264 if (ApplicationWindow != NULL)
265 {
266 DFWINDOW fwnd = FirstWindow(ApplicationWindow);
267 while (fwnd != NULL)
268 {
269 if (!isAncestor(wnd, fwnd))
270 {
271 rc = subRectangle(WindowRect(wnd),WindowRect(fwnd));
272 if (ValidRect(rc))
273 break;
274 }
275 fwnd = NextWindow(fwnd);
276 }
277 }
278 }
279 }
280 if (that != NULL && !ValidRect(rc) && isVisible(wnd))
281 {
282 DfSendMessage(wnd, BORDER, 0, 0);
283 this = NULL;
284 }
285 ReFocus(wnd);
286 if (this != NULL)
287 DfSendMessage(this, SHOW_WINDOW, 0, 0);
288 }
289 else if (!p1 && inFocus == wnd)
290 {
291 /* clearing focus */
292 inFocus = NULL;
293 DfSendMessage(wnd, BORDER, 0, 0);
294 }
295 }
296
297 /* --------- DOUBLE_CLICK Message ---------- */
298 static void DoubleClickMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
299 {
300 int mx = (int) p1 - GetLeft(wnd);
301 int my = (int) p2 - GetTop(wnd);
302 if (!WindowSizing && !WindowMoving) {
303 if (HitControlBox(wnd, mx, my)) {
304 DfPostMessage(wnd, CLOSE_WINDOW, 0, 0);
305 SkipApplicationControls();
306 }
307 }
308 }
309
310 /* --------- LEFT_BUTTON Message ---------- */
311 static void LeftButtonMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
312 {
313 int mx = (int) p1 - GetLeft(wnd);
314 int my = (int) p2 - GetTop(wnd);
315 if (WindowSizing || WindowMoving)
316 return;
317 if (HitControlBox(wnd, mx, my)) {
318 BuildSystemMenu(wnd);
319 return;
320 }
321 if (my == 0 && mx > -1 && mx < WindowWidth(wnd)) {
322 /* ---------- hit the top border -------- */
323 if (TestAttribute(wnd, MINMAXBOX) &&
324 TestAttribute(wnd, HASTITLEBAR)) {
325 if (mx == WindowWidth(wnd)-2) {
326 if (wnd->condition != ISRESTORED)
327 /* --- hit the restore box --- */
328 DfSendMessage(wnd, RESTORE, 0, 0);
329 #ifdef INCLUDE_MAXIMIZE
330 else
331 /* --- hit the maximize box --- */
332 DfSendMessage(wnd, MAXIMIZE, 0, 0);
333 #endif
334 return;
335 }
336 #ifdef INCLUDE_MINIMIZE
337 if (mx == WindowWidth(wnd)-3) {
338 /* --- hit the minimize box --- */
339 if (wnd->condition != ISMINIMIZED)
340 DfSendMessage(wnd, MINIMIZE, 0, 0);
341 return;
342 }
343 #endif
344 }
345 #ifdef INCLUDE_MAXIMIZE
346 if (wnd->condition == ISMAXIMIZED)
347 return;
348 #endif
349 if (TestAttribute(wnd, MOVEABLE)) {
350 WindowMoving = TRUE;
351 px = mx;
352 py = my;
353 diff = (int) mx;
354 DfSendMessage(wnd, CAPTURE_MOUSE, TRUE,
355 (PARAM) &dwnd);
356 dragborder(wnd, GetLeft(wnd), GetTop(wnd));
357 }
358 return;
359 }
360 if (mx == WindowWidth(wnd)-1 &&
361 my == WindowHeight(wnd)-1) {
362 /* ------- hit the resize corner ------- */
363 #ifdef INCLUDE_MINIMIZE
364 if (wnd->condition == ISMINIMIZED)
365 return;
366 #endif
367 if (!TestAttribute(wnd, SIZEABLE))
368 return;
369 #ifdef INCLUDE_MAXIMIZE
370 if (wnd->condition == ISMAXIMIZED) {
371 if (GetParent(wnd) == NULL)
372 return;
373 if (TestAttribute(GetParent(wnd),HASBORDER))
374 return;
375 /* ----- resizing a maximized window over a
376 borderless parent ----- */
377 wnd = GetParent(wnd);
378 }
379 #endif
380 WindowSizing = TRUE;
381 DfSendMessage(wnd, CAPTURE_MOUSE,
382 TRUE, (PARAM) &dwnd);
383 dragborder(wnd, GetLeft(wnd), GetTop(wnd));
384 }
385 }
386
387 /* --------- MOUSE_MOVED Message ---------- */
388 static BOOL MouseMovedMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
389 {
390 if (WindowMoving) {
391 int leftmost = 0, topmost = 0,
392 bottommost = SCREENHEIGHT-2,
393 rightmost = SCREENWIDTH-2;
394 int x = (int) p1 - diff;
395 int y = (int) p2;
396 if (GetParent(wnd) != NULL &&
397 !TestAttribute(wnd, NOCLIP)) {
398 DFWINDOW wnd1 = GetParent(wnd);
399 topmost = GetClientTop(wnd1);
400 leftmost = GetClientLeft(wnd1);
401 bottommost = GetClientBottom(wnd1);
402 rightmost = GetClientRight(wnd1);
403 }
404 if (x < leftmost || x > rightmost ||
405 y < topmost || y > bottommost) {
406 x = max(x, leftmost);
407 x = min(x, rightmost);
408 y = max(y, topmost);
409 y = min(y, bottommost);
410 }
411
412 if (x != px || y != py) {
413 px = x;
414 py = y;
415 dragborder(wnd, x, y);
416 }
417 return TRUE;
418 }
419 if (WindowSizing) {
420 sizeborder(wnd, (int) p1, (int) p2);
421 return TRUE;
422 }
423 return FALSE;
424 }
425
426 #ifdef INCLUDE_MAXIMIZE
427 /* --------- MAXIMIZE Message ---------- */
428 static void MaximizeMsg(DFWINDOW wnd)
429 {
430 DFRECT rc = {0, 0, 0, 0};
431 DFRECT holdrc;
432 holdrc = wnd->RestoredRC;
433 rc.rt = SCREENWIDTH-1;
434 rc.bt = SCREENHEIGHT-1;
435 if (GetParent(wnd))
436 rc = ClientRect(GetParent(wnd));
437 wnd->oldcondition = wnd->condition;
438 wnd->condition = ISMAXIMIZED;
439 DfSendMessage(wnd, DFM_HIDE_WINDOW, 0, 0);
440 DfSendMessage(wnd, MOVE,
441 RectLeft(rc), RectTop(rc));
442 DfSendMessage(wnd, DFM_SIZE,
443 RectRight(rc), RectBottom(rc));
444 if (wnd->restored_attrib == 0)
445 wnd->restored_attrib = wnd->attrib;
446 ClearAttribute(wnd, SHADOW);
447 DfSendMessage(wnd, SHOW_WINDOW, 0, 0);
448 wnd->RestoredRC = holdrc;
449 }
450 #endif
451
452 #ifdef INCLUDE_MINIMIZE
453 /* --------- MINIMIZE Message ---------- */
454 static void MinimizeMsg(DFWINDOW wnd)
455 {
456 DFRECT rc;
457 DFRECT holdrc;
458
459 holdrc = wnd->RestoredRC;
460 rc = PositionIcon(wnd);
461 wnd->oldcondition = wnd->condition;
462 wnd->condition = ISMINIMIZED;
463 DfSendMessage(wnd, DFM_HIDE_WINDOW, 0, 0);
464 DfSendMessage(wnd, MOVE,
465 RectLeft(rc), RectTop(rc));
466 DfSendMessage(wnd, DFM_SIZE,
467 RectRight(rc), RectBottom(rc));
468 if (wnd == inFocus)
469 SetNextFocus();
470 if (wnd->restored_attrib == 0)
471 wnd->restored_attrib = wnd->attrib;
472 ClearAttribute(wnd,
473 SHADOW | SIZEABLE | HASMENUBAR |
474 VSCROLLBAR | HSCROLLBAR);
475 DfSendMessage(wnd, SHOW_WINDOW, 0, 0);
476 wnd->RestoredRC = holdrc;
477 }
478 #endif
479
480 #ifdef INCLUDE_RESTORE
481 /* --------- RESTORE Message ---------- */
482 static void RestoreMsg(DFWINDOW wnd)
483 {
484 DFRECT holdrc;
485 holdrc = wnd->RestoredRC;
486 wnd->oldcondition = wnd->condition;
487 wnd->condition = ISRESTORED;
488 DfSendMessage(wnd, DFM_HIDE_WINDOW, 0, 0);
489 wnd->attrib = wnd->restored_attrib;
490 wnd->restored_attrib = 0;
491 DfSendMessage(wnd, MOVE, wnd->RestoredRC.lf,
492 wnd->RestoredRC.tp);
493 wnd->RestoredRC = holdrc;
494 DfSendMessage(wnd, DFM_SIZE, wnd->RestoredRC.rt,
495 wnd->RestoredRC.bt);
496 if (wnd != inFocus)
497 DfSendMessage(wnd, SETFOCUS, TRUE, 0);
498 else
499 DfSendMessage(wnd, SHOW_WINDOW, 0, 0);
500 }
501 #endif
502
503 /* --------- MOVE Message ---------- */
504 static void MoveMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
505 {
506 DFWINDOW cwnd;
507 BOOL wasVisible = isVisible(wnd);
508 int xdif = (int) p1 - wnd->rc.lf;
509 int ydif = (int) p2 - wnd->rc.tp;
510
511 if (xdif == 0 && ydif == 0)
512 return;
513 if (wasVisible)
514 DfSendMessage(wnd, DFM_HIDE_WINDOW, 0, 0);
515 wnd->rc.lf = (int) p1;
516 wnd->rc.tp = (int) p2;
517 wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
518 wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
519 if (wnd->condition == ISRESTORED)
520 wnd->RestoredRC = wnd->rc;
521
522 cwnd = FirstWindow(wnd);
523 while (cwnd != NULL) {
524 DfSendMessage(cwnd, MOVE, cwnd->rc.lf+xdif, cwnd->rc.tp+ydif);
525 cwnd = NextWindow(cwnd);
526 }
527 if (wasVisible)
528 DfSendMessage(wnd, SHOW_WINDOW, 0, 0);
529 }
530
531 /* --------- SIZE Message ---------- */
532 static void SizeMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
533 {
534 BOOL wasVisible = isVisible(wnd);
535 DFWINDOW cwnd;
536 DFRECT rc;
537 int xdif = (int) p1 - wnd->rc.rt;
538 int ydif = (int) p2 - wnd->rc.bt;
539
540 if (xdif == 0 && ydif == 0)
541 return;
542 if (wasVisible)
543 DfSendMessage(wnd, DFM_HIDE_WINDOW, 0, 0);
544 wnd->rc.rt = (int) p1;
545 wnd->rc.bt = (int) p2;
546 wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
547 wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
548
549 if (wnd->condition == ISRESTORED)
550 wnd->RestoredRC = WindowRect(wnd);
551
552 #ifdef INCLUDE_MAXIMIZE
553 rc = ClientRect(wnd);
554
555 cwnd = FirstWindow(wnd);
556 while (cwnd != NULL) {
557 if (cwnd->condition == ISMAXIMIZED)
558 DfSendMessage(cwnd, DFM_SIZE, RectRight(rc), RectBottom(rc));
559 cwnd = NextWindow(cwnd);
560 }
561
562 #endif
563 if (wasVisible)
564 DfSendMessage(wnd, SHOW_WINDOW, 0, 0);
565 }
566
567 /* --------- CLOSE_WINDOW Message ---------- */
568 static void CloseWindowMsg(DFWINDOW wnd)
569 {
570 DFWINDOW cwnd;
571 wnd->condition = ISCLOSING;
572 if (wnd->PrevMouse != NULL)
573 DfSendMessage(wnd, RELEASE_MOUSE, 0, 0);
574 if (wnd->PrevKeyboard != NULL)
575 DfSendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
576 /* ----------- hide this window ------------ */
577 DfSendMessage(wnd, DFM_HIDE_WINDOW, 0, 0);
578 /* --- close the children of this window --- */
579
580 cwnd = LastWindow(wnd);
581 while (cwnd != NULL) {
582 if (inFocus == cwnd)
583 inFocus = wnd;
584 DfSendMessage(cwnd,CLOSE_WINDOW,0,0);
585 cwnd = LastWindow(wnd);
586 }
587
588 /* --- change focus if this window had it -- */
589 if (wnd == inFocus)
590 SetPrevFocus();
591 /* -- free memory allocated to this window - */
592 if (wnd->title != NULL)
593 free(wnd->title);
594 if (wnd->videosave != NULL)
595 free(wnd->videosave);
596 /* -- remove window from parent's list of children -- */
597 RemoveWindow(wnd);
598 if (wnd == inFocus)
599 inFocus = NULL;
600 free(wnd);
601 }
602
603 /* ---- Window-processing module for NORMAL window class ---- */
604 int NormalProc(DFWINDOW wnd, DFMESSAGE msg, PARAM p1, PARAM p2)
605 {
606 switch (msg) {
607 case CREATE_WINDOW:
608 CreateWindowMsg(wnd);
609 break;
610 case SHOW_WINDOW:
611 ShowWindowMsg(wnd, p1, p2);
612 break;
613 case DFM_HIDE_WINDOW:
614 HideWindowMsg(wnd);
615 break;
616 case DISPLAY_HELP:
617 DisplayHelp(wnd, (char *)p1);
618 break;
619 case INSIDE_WINDOW:
620 return InsideWindow(wnd, (int) p1, (int) p2);
621 case KEYBOARD:
622 if (KeyboardMsg(wnd, p1, p2))
623 return TRUE;
624 /* ------- fall through ------- */
625 case ADDSTATUS:
626 case SHIFT_CHANGED:
627 if (GetParent(wnd) != NULL)
628 DfPostMessage(GetParent(wnd), msg, p1, p2);
629 break;
630 case PAINT:
631 if (isVisible(wnd))
632 ClearWindow(wnd, (DFRECT *)p1, ' ');
633 break;
634 case BORDER:
635 if (isVisible(wnd))
636 {
637 if (TestAttribute(wnd, HASBORDER))
638 RepaintBorder(wnd, (DFRECT *)p1);
639 else if (TestAttribute(wnd, HASTITLEBAR))
640 DisplayTitle(wnd, (DFRECT *)p1);
641 }
642 break;
643 case DFM_COMMAND:
644 CommandMsg(wnd, p1);
645 break;
646 case SETFOCUS:
647 SetFocusMsg(wnd, p1);
648 break;
649 case DFM_DOUBLE_CLICK:
650 DoubleClickMsg(wnd, p1, p2);
651 break;
652 case LEFT_BUTTON:
653 LeftButtonMsg(wnd, p1, p2);
654 break;
655 case MOUSE_MOVED:
656 if (MouseMovedMsg(wnd, p1, p2))
657 return TRUE;
658 break;
659 case DFM_BUTTON_RELEASED:
660 if (WindowMoving || WindowSizing)
661 {
662 if (WindowMoving)
663 DfPostMessage(wnd,MOVE,dwnd.rc.lf,dwnd.rc.tp);
664 else
665 DfPostMessage(wnd, DFM_SIZE,dwnd.rc.rt,dwnd.rc.bt);
666 TerminateMoveSize();
667 }
668 break;
669 #ifdef INCLUDE_MAXIMIZE
670 case MAXIMIZE:
671 if (wnd->condition != ISMAXIMIZED)
672 MaximizeMsg(wnd);
673 break;
674 #endif
675 #ifdef INCLUDE_MINIMIZE
676 case MINIMIZE:
677 if (wnd->condition != ISMINIMIZED)
678 MinimizeMsg(wnd);
679 break;
680 #endif
681 #ifdef INCLUDE_RESTORE
682 case RESTORE:
683 if (wnd->condition != ISRESTORED) {
684 #ifdef INCLUDE_MAXIMIZE
685 if (wnd->oldcondition == ISMAXIMIZED)
686 DfSendMessage(wnd, MAXIMIZE, 0, 0);
687 else
688 #endif
689 RestoreMsg(wnd);
690 }
691 break;
692 #endif
693 case MOVE:
694 MoveMsg(wnd, p1, p2);
695 break;
696 case DFM_SIZE: {
697 SizeMsg(wnd, p1, p2);
698 break;
699 }
700 case CLOSE_WINDOW:
701 CloseWindowMsg(wnd);
702 break;
703 default:
704 break;
705 }
706 return TRUE;
707 }
708 #ifdef INCLUDE_MINIMIZE
709 /* ---- compute lower right icon space in a rectangle ---- */
710 static DFRECT LowerRight(DFRECT prc)
711 {
712 DFRECT rc;
713 RectLeft(rc) = RectRight(prc) - ICONWIDTH;
714 RectTop(rc) = RectBottom(prc) - ICONHEIGHT;
715 RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
716 RectBottom(rc) = RectTop(rc)+ICONHEIGHT-1;
717 return rc;
718 }
719 /* ----- compute a position for a minimized window icon ---- */
720 static DFRECT PositionIcon(DFWINDOW wnd)
721 {
722 DFWINDOW pwnd = GetParent(wnd);
723 DFRECT rc;
724 RectLeft(rc) = SCREENWIDTH-ICONWIDTH;
725 RectTop(rc) = SCREENHEIGHT-ICONHEIGHT;
726 RectRight(rc) = SCREENWIDTH-1;
727 RectBottom(rc) = SCREENHEIGHT-1;
728 if (pwnd != NULL) {
729 DFRECT prc = WindowRect(pwnd);
730 DFWINDOW cwnd = FirstWindow(pwnd);
731 rc = LowerRight(prc);
732 /* - search for icon available location - */
733 while (cwnd != NULL) {
734 if (cwnd->condition == ISMINIMIZED) {
735 DFRECT rc1;
736 rc1 = WindowRect(cwnd);
737 if (RectLeft(rc1) == RectLeft(rc) &&
738 RectTop(rc1) == RectTop(rc)) {
739 RectLeft(rc) -= ICONWIDTH;
740 RectRight(rc) -= ICONWIDTH;
741 if (RectLeft(rc) < RectLeft(prc)+1) {
742 RectLeft(rc) =
743 RectRight(prc)-ICONWIDTH;
744 RectRight(rc) =
745 RectLeft(rc)+ICONWIDTH-1;
746 RectTop(rc) -= ICONHEIGHT;
747 RectBottom(rc) -= ICONHEIGHT;
748 if (RectTop(rc) < RectTop(prc)+1)
749 return LowerRight(prc);
750 }
751 break;
752 }
753 }
754 cwnd = NextWindow(cwnd);
755 }
756 }
757 return rc;
758 }
759 #endif
760 /* ----- terminate the move or size operation ----- */
761 static void TerminateMoveSize(void)
762 {
763 px = py = -1;
764 diff = 0;
765 DfSendMessage(&dwnd, RELEASE_MOUSE, TRUE, 0);
766 DfSendMessage(&dwnd, RELEASE_KEYBOARD, TRUE, 0);
767 RestoreBorder(dwnd.rc);
768 WindowMoving = WindowSizing = FALSE;
769 }
770 /* ---- build a dummy window border for moving or sizing --- */
771 static void dragborder(DFWINDOW wnd, int x, int y)
772 {
773 RestoreBorder(dwnd.rc);
774 /* ------- build the dummy window -------- */
775 dwnd.rc.lf = x;
776 dwnd.rc.tp = y;
777 dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
778 dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
779 dwnd.ht = WindowHeight(wnd);
780 dwnd.wd = WindowWidth(wnd);
781 dwnd.parent = GetParent(wnd);
782 dwnd.attrib = VISIBLE | HASBORDER | NOCLIP;
783 InitWindowColors(&dwnd);
784 SaveBorder(dwnd.rc);
785 RepaintBorder(&dwnd, NULL);
786 }
787 /* ---- write the dummy window border for sizing ---- */
788 static void sizeborder(DFWINDOW wnd, int rt, int bt)
789 {
790 int leftmost = GetLeft(wnd)+10;
791 int topmost = GetTop(wnd)+3;
792 int bottommost = SCREENHEIGHT-1;
793 int rightmost = SCREENWIDTH-1;
794 if (GetParent(wnd)) {
795 bottommost = min(bottommost,
796 GetClientBottom(GetParent(wnd)));
797 rightmost = min(rightmost,
798 GetClientRight(GetParent(wnd)));
799 }
800 rt = min(rt, rightmost);
801 bt = min(bt, bottommost);
802 rt = max(rt, leftmost);
803 bt = max(bt, topmost);
804
805 if (rt != px || bt != py)
806 RestoreBorder(dwnd.rc);
807
808 /* ------- change the dummy window -------- */
809 dwnd.ht = bt-dwnd.rc.tp+1;
810 dwnd.wd = rt-dwnd.rc.lf+1;
811 dwnd.rc.rt = rt;
812 dwnd.rc.bt = bt;
813 if (rt != px || bt != py) {
814 px = rt;
815 py = bt;
816 SaveBorder(dwnd.rc);
817 RepaintBorder(&dwnd, NULL);
818 }
819 }
820 #ifdef INCLUDE_MULTI_WINDOWS
821 /* ----- adjust a rectangle to include the shadow ----- */
822 static DFRECT adjShadow(DFWINDOW wnd)
823 {
824 DFRECT rc;
825 rc = wnd->rc;
826 if (TestAttribute(wnd, SHADOW)) {
827 if (RectRight(rc) < SCREENWIDTH-1)
828 RectRight(rc)++;
829 if (RectBottom(rc) < SCREENHEIGHT-1)
830 RectBottom(rc)++;
831 }
832 return rc;
833 }
834 /* --- repaint a rectangular subsection of a window --- */
835 static void PaintOverLap(DFWINDOW wnd, DFRECT rc)
836 {
837 if (isVisible(wnd)) {
838 int isBorder, isTitle, isData;
839 isBorder = isTitle = FALSE;
840 isData = TRUE;
841 if (TestAttribute(wnd, HASBORDER)) {
842 isBorder = RectLeft(rc) == 0 &&
843 RectTop(rc) < WindowHeight(wnd);
844 isBorder |= RectLeft(rc) < WindowWidth(wnd) &&
845 RectRight(rc) >= WindowWidth(wnd)-1 &&
846 RectTop(rc) < WindowHeight(wnd);
847 isBorder |= RectTop(rc) == 0 &&
848 RectLeft(rc) < WindowWidth(wnd);
849 isBorder |= RectTop(rc) < WindowHeight(wnd) &&
850 RectBottom(rc) >= WindowHeight(wnd)-1 &&
851 RectLeft(rc) < WindowWidth(wnd);
852 }
853 else if (TestAttribute(wnd, HASTITLEBAR))
854 isTitle = RectTop(rc) == 0 &&
855 RectRight(rc) > 0 &&
856 RectLeft(rc)<WindowWidth(wnd)-BorderAdj(wnd);
857
858 if (RectLeft(rc) >= WindowWidth(wnd)-BorderAdj(wnd))
859 isData = FALSE;
860 if (RectTop(rc) >= WindowHeight(wnd)-BottomBorderAdj(wnd))
861 isData = FALSE;
862 if (TestAttribute(wnd, HASBORDER)) {
863 if (RectRight(rc) == 0)
864 isData = FALSE;
865 if (RectBottom(rc) == 0)
866 isData = FALSE;
867 }
868 if (TestAttribute(wnd, SHADOW))
869 isBorder |= RectRight(rc) == WindowWidth(wnd) ||
870 RectBottom(rc) == WindowHeight(wnd);
871 if (isData)
872 DfSendMessage(wnd, PAINT, (PARAM) &rc, TRUE);
873 if (isBorder)
874 DfSendMessage(wnd, BORDER, (PARAM) &rc, 0);
875 else if (isTitle)
876 DisplayTitle(wnd, &rc);
877 }
878 }
879 /* ------ paint the part of a window that is overlapped
880 by another window that is being hidden ------- */
881 static void PaintOver(DFWINDOW wnd)
882 {
883 DFRECT wrc, rc;
884 wrc = adjShadow(HiddenWindow);
885 rc = adjShadow(wnd);
886 rc = subRectangle(rc, wrc);
887 if (ValidRect(rc))
888 PaintOverLap(wnd, RelativeWindowRect(wnd, rc));
889 }
890 /* --- paint the overlapped parts of all children --- */
891 static void PaintOverChildren(DFWINDOW pwnd)
892 {
893 DFWINDOW cwnd = FirstWindow(pwnd);
894 while (cwnd != NULL) {
895 if (cwnd != HiddenWindow) {
896 PaintOver(cwnd);
897 PaintOverChildren(cwnd);
898 }
899 cwnd = NextWindow(cwnd);
900 }
901 }
902 /* -- recursive overlapping paint of parents -- */
903 static void PaintOverParents(DFWINDOW wnd)
904 {
905 DFWINDOW pwnd = GetParent(wnd);
906 if (pwnd != NULL) {
907 PaintOverParents(pwnd);
908 PaintOver(pwnd);
909 PaintOverChildren(pwnd);
910 }
911 }
912 /* - paint the parts of all windows that a window is over - */
913 static void PaintOverLappers(DFWINDOW wnd)
914 {
915 HiddenWindow = wnd;
916 PaintOverParents(wnd);
917 }
918 /* --- paint those parts of a window that are overlapped --- */
919 static void PaintUnderLappers(DFWINDOW wnd)
920 {
921 DFWINDOW hwnd = NextWindow(wnd);
922 while (hwnd != NULL) {
923 /* ------- test only at document window level ------ */
924 DFWINDOW pwnd = GetParent(hwnd);
925 /* if (pwnd == NULL || GetClass(pwnd) == APPLICATION) */ {
926 /* ---- don't bother testing self ----- */
927 if (isVisible(hwnd) && hwnd != wnd) {
928 /* --- see if other window is descendent --- */
929 while (pwnd != NULL) {
930 if (pwnd == wnd)
931 break;
932 pwnd = GetParent(pwnd);
933 }
934 /* ----- don't test descendent overlaps ----- */
935 if (pwnd == NULL) {
936 /* -- see if other window is ancestor --- */
937 pwnd = GetParent(wnd);
938 while (pwnd != NULL) {
939 if (pwnd == hwnd)
940 break;
941 pwnd = GetParent(pwnd);
942 }
943 /* --- don't test ancestor overlaps --- */
944 if (pwnd == NULL) {
945 HiddenWindow = GetAncestor(hwnd);
946 ClearVisible(HiddenWindow);
947 PaintOver(wnd);
948 SetVisible(HiddenWindow);
949 }
950 }
951 }
952 }
953 hwnd = NextWindow(hwnd);
954 }
955 /* --------- repaint all children of this window
956 the same way ----------- */
957 hwnd = FirstWindow(wnd);
958 while (hwnd != NULL) {
959 PaintUnderLappers(hwnd);
960 hwnd = NextWindow(hwnd);
961 }
962 }
963 #endif /* #ifdef INCLUDE_MULTI_WINDOWS */
964
965 /* --- save video area to be used by dummy window border --- */
966 static void SaveBorder(DFRECT rc)
967 {
968 Bht = RectBottom(rc) - RectTop(rc) + 1;
969 Bwd = RectRight(rc) - RectLeft(rc) + 1;
970 Bsave = DFrealloc(Bsave, Bht * Bwd * sizeof(CHAR_INFO));
971
972 GetVideo(rc,Bsave);
973 }
974 /* ---- restore video area used by dummy window border ---- */
975 static void RestoreBorder(DFRECT rc)
976 {
977 if (Bsave != NULL)
978 {
979 StoreVideo(rc, Bsave);
980 free(Bsave);
981 Bsave = NULL;
982 }
983 }
984 /* ----- test if screen coordinates are in a window ---- */
985 static BOOL InsideWindow(DFWINDOW wnd, int x, int y)
986 {
987 DFRECT rc;
988 rc = WindowRect(wnd);
989 if (!TestAttribute(wnd, NOCLIP))
990 {
991 DFWINDOW pwnd = GetParent(wnd);
992 while (pwnd != NULL)
993 {
994 rc = subRectangle(rc, ClientRect(pwnd));
995 pwnd = GetParent(pwnd);
996 }
997 }
998 return InsideRect(x, y, rc);
999 }
1000
1001 BOOL isDerivedFrom(DFWINDOW wnd, DFCLASS class)
1002 {
1003 DFCLASS tclass = GetClass(wnd);
1004 while (tclass != -1) {
1005 if (tclass == class)
1006 return TRUE;
1007 tclass = (classdefs[tclass].base);
1008 }
1009 return FALSE;
1010 }
1011
1012 /* -- find the oldest document window ancestor of a window -- */
1013 DFWINDOW GetAncestor(DFWINDOW wnd)
1014 {
1015 if (wnd != NULL) {
1016 while (GetParent(wnd) != NULL) {
1017 if (GetClass(GetParent(wnd)) == APPLICATION)
1018 break;
1019 wnd = GetParent(wnd);
1020 }
1021 }
1022 return wnd;
1023 }
1024
1025 BOOL isVisible(DFWINDOW wnd)
1026 {
1027 while (wnd != NULL) {
1028 if (isHidden(wnd))
1029 return FALSE;
1030 wnd = GetParent(wnd);
1031 }
1032 return TRUE;
1033 }
1034
1035 /* -- adjust a window's rectangle to clip it to its parent - */
1036 static DFRECT ClipRect(DFWINDOW wnd)
1037 {
1038 DFRECT rc;
1039 rc = WindowRect(wnd);
1040 if (TestAttribute(wnd, SHADOW)) {
1041 RectBottom(rc)++;
1042 RectRight(rc)++;
1043 }
1044 return ClipRectangle(wnd, rc);
1045 }
1046
1047 /* -- get the video memory that is to be used by a window -- */
1048 static void GetVideoBuffer(DFWINDOW wnd)
1049 {
1050 DFRECT rc;
1051 int ht;
1052 int wd;
1053
1054 rc = ClipRect(wnd);
1055 ht = RectBottom(rc) - RectTop(rc) + 1;
1056 wd = RectRight(rc) - RectLeft(rc) + 1;
1057 wnd->videosave = DFrealloc(wnd->videosave, (ht * wd * sizeof(CHAR_INFO)));
1058 GetVideo(rc, wnd->videosave);
1059 }
1060
1061 /* -- put the video memory that is used by a window -- */
1062 static void PutVideoBuffer(DFWINDOW wnd)
1063 {
1064 if (wnd->videosave != NULL)
1065 {
1066 DFRECT rc;
1067 rc = ClipRect(wnd);
1068 StoreVideo(rc, wnd->videosave);
1069 free(wnd->videosave);
1070 wnd->videosave = NULL;
1071 }
1072 }
1073
1074 /* ------- return TRUE if awnd is an ancestor of wnd ------- */
1075 BOOL isAncestor(DFWINDOW wnd, DFWINDOW awnd)
1076 {
1077 while (wnd != NULL) {
1078 if (wnd == awnd)
1079 return TRUE;
1080 wnd = GetParent(wnd);
1081 }
1082 return FALSE;
1083 }
1084
1085 /* EOF */