home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1992 / 06 / dflt12 / normal.c < prev    next >
Text File  |  1992-04-17  |  34KB  |  1,087 lines

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