home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 05 / d_flat / normal.c < prev    next >
Text File  |  1991-02-22  |  21KB  |  800 lines

  1. /* ------------- normal.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <conio.h>
  7. #include "dflat.h"
  8.  
  9. int WindowMoving = FALSE;
  10. int WindowSizing = FALSE;
  11. static int dragcount = -1;
  12. static int diff;
  13. static struct window dwnd = {DUMMY, NULL, NULL, NormalProc,
  14.                                 {-1,-1,-1,-1}};
  15.  
  16. struct LinkedList Focus = {NULLWND, NULLWND};
  17. struct LinkedList Built = {NULLWND, NULLWND};
  18. static WINDOW NextWindow;
  19.  
  20. static void TerminateMoveSize(void);
  21. static void near PaintOverLappers(WINDOW wnd);
  22. static void near dragborder(WINDOW, int, int);
  23. static void near sizeborder(WINDOW, int, int);
  24. static void SaveBorder(RECT);
  25. static void RestoreBorder(RECT);
  26. static void RemoveWindow(WINDOW, int);
  27. static void AddWindow(WINDOW, int);
  28. static int InsideWindow(WINDOW, int, int);
  29.  
  30. static int px = -1, py = -1;
  31. static int CloseDepth = 0;
  32.  
  33. int NormalProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  34. {
  35.     int    mx = (int) p1 - GetLeft(wnd);
  36.     int    my = (int) p2 - GetTop(wnd);
  37.     switch (msg)    {
  38.         case CREATE_WINDOW:
  39.             AddWindow(wnd, TRUE);
  40.             if (!SendMessage(NULLWND, MOUSE_INSTALLED, 0, 0))
  41.                 ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
  42.             if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
  43.                 GetVideoBuffer(wnd);
  44.             break;
  45.         case SHOW_WINDOW:
  46.             if (GetParent(wnd) == NULLWND ||
  47.                         isVisible(GetParent(wnd)))    {
  48.                 WINDOW cwnd = Focus.FirstWindow;
  49.                 if (TestAttribute(wnd, SAVESELF) && wnd->videosave == NULL)
  50.                     GetVideoBuffer(wnd);
  51.                 SetVisible(wnd);
  52.                 SendMessage(wnd, PAINT, 0, 0);
  53.                 SendMessage(wnd, BORDER, 0, 0);
  54.                 while (cwnd != NULLWND)    {
  55.                     if (GetParent(cwnd) == wnd)
  56.                         SendMessage(cwnd, msg, p1, p2);
  57.                     cwnd = NextWindow(cwnd);
  58.                 }
  59.             }
  60.             break;
  61.         case HIDE_WINDOW:
  62.             if (isVisible(wnd))    {
  63.                 WINDOW cwnd = Focus.LastWindow;
  64.                 while (cwnd != NULLWND)    {
  65.                     if (GetParent(cwnd) == wnd)
  66.                         ClearVisible(cwnd);
  67.                     cwnd = PrevWindow(cwnd);
  68.                 }
  69.                 if (wnd->videosave != NULL)
  70.                     RestoreVideoBuffer(wnd);
  71.                 else
  72.                     PaintOverLappers(wnd);
  73.                 ClearVisible(wnd);
  74.             }
  75.             break;
  76.         case INSIDE_WINDOW:
  77.             return InsideWindow(wnd, (int) p1, (int) p2);
  78.         case KEYBOARD:
  79.             if (WindowMoving || WindowSizing)    {
  80.                 int x, y;
  81.                 x = WindowMoving ? GetLeft(&dwnd) : GetRight(&dwnd);
  82.                 y = WindowMoving ? GetTop(&dwnd) : GetBottom(&dwnd);
  83.                 switch ((int)p1)    {
  84.                     case ESC:
  85.                         TerminateMoveSize();
  86.                         return TRUE;
  87.                     case UP:
  88.                         if (y)
  89.                             --y;
  90.                         break;
  91.                     case DN:
  92.                         if (y < SCREENHEIGHT-1)
  93.                             y++;
  94.                         break;
  95.                     case FWD:
  96.                         if (x < SCREENWIDTH-1)
  97.                             x++;
  98.                         break;
  99.                     case BS:
  100.                         if (x)
  101.                             --x;
  102.                         break;
  103.                     case '\r':
  104.                         SendMessage(wnd, BUTTON_RELEASED, x, y);
  105.                     default:
  106.                         return TRUE;
  107.                 }
  108.                 SendMessage(wnd, MOUSE_CURSOR, x, y);
  109.                 SendMessage(wnd, MOUSE_MOVED, x, y);
  110.                 break;
  111.             }
  112.             PostMessage(GetParent(wnd), msg, p1, p2);
  113.             break;
  114.         case PAINT:
  115.             if (isVisible(wnd))    
  116.                 ClearWindow(wnd, (RECT *)p1, ' ');
  117.             break;
  118.         case BORDER:
  119.             if (isVisible(wnd))
  120.                 RepaintBorder(wnd, (RECT *)p1);
  121.             break;
  122.         case COMMAND:
  123.             switch ((int)p1)    {
  124.                 case ID_SYSRESTORE:
  125.                     SendMessage(wnd, RESTORE, 0, 0);
  126.                     break;
  127.                 case ID_SYSMOVE:
  128.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE, (PARAM) &dwnd);
  129.                     SendMessage(wnd, CAPTURE_KEYBOARD, TRUE, (PARAM) &dwnd);
  130.                     SendMessage(wnd, MOUSE_CURSOR, GetLeft(wnd), GetTop(wnd));
  131.                     WindowMoving = TRUE;
  132.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  133.                     break;
  134.                 case ID_SYSSIZE:
  135.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE, (PARAM) &dwnd);
  136.                     SendMessage(wnd, CAPTURE_KEYBOARD, TRUE, (PARAM) &dwnd);
  137.                     SendMessage(wnd, MOUSE_CURSOR, GetRight(wnd), GetBottom(wnd));
  138.                     WindowSizing = TRUE;
  139.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  140.                     break;
  141.                 case ID_SYSMINIMIZE:
  142.                     SendMessage(wnd, MINIMIZE, 0, 0);
  143.                     break;
  144.                 case ID_SYSMAXIMIZE:
  145.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  146.                     break;
  147.                 case ID_SYSCLOSE:
  148.                     SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  149.                     break;
  150.                 default:
  151.                     break;
  152.             }
  153.             break;
  154.         case SETFOCUS:
  155.             if (p1 && inFocus != wnd)    {
  156.                 SendMessage(inFocus, SETFOCUS, FALSE, 0);
  157.                 /* remove from list */
  158.                 RemoveWindow(wnd, FALSE);
  159.                 /* move window to end of list */
  160.                 AddWindow(wnd, FALSE);
  161.                 inFocus = wnd;
  162.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  163.             }
  164.             else if (!p1 && inFocus == wnd)    {
  165.                 inFocus = NULL;
  166.                 SendMessage(wnd, BORDER, 0, 0);
  167.             }
  168.             break;
  169.         case DOUBLE_CLICK:
  170.             if (!SendMessage(wnd, INSIDE_WINDOW, p1, p2) &&
  171.                         CaptureMouse == NULLWND)    {
  172.                 PostMessage(GetParent(wnd), msg, p1, p2);
  173.                 break;
  174.             }
  175.             if (!WindowSizing && !WindowMoving)
  176.                 if (HitControlBox(wnd, mx, my))
  177.                     PostMessage(wnd, CLOSE_WINDOW, 0, 0);
  178.             break;
  179.         case LEFT_BUTTON:
  180.             if (WindowSizing || WindowMoving)
  181.                 return FALSE;
  182.             if ((!SendMessage(wnd, INSIDE_WINDOW, p1, p2) &&
  183.                     CaptureMouse == NULLWND) ||
  184.                         HitControlBox(wnd, mx, my))    {
  185.                 PostMessage(GetParent(wnd), msg, p1, p2);
  186.                 break;
  187.             }
  188.             if (my == 0 && TestAttribute(wnd, TITLEBAR))    {
  189.                 /* ---------- hit the title bar -------- */
  190.                 if (TestAttribute(wnd, MINMAXBOX))        {
  191.                     if (mx == WindowWidth(wnd)-2)    {
  192.                         if (wnd->condition == ISRESTORED)    {
  193.                             SendMessage(wnd, MAXIMIZE, 0, 0);
  194.                             break;
  195.                         }
  196.                         else    {
  197.                             SendMessage(wnd, RESTORE, 0, 0);
  198.                             break;
  199.                         }
  200.                     }
  201.                     else if (mx == WindowWidth(wnd)-3)    {
  202.                         if (wnd->condition != ISMINIMIZED)    {
  203.                             SendMessage(wnd, MINIMIZE, 0, 0);
  204.                             break;
  205.                         }
  206.                     }
  207.                 }
  208.             }
  209.             if ((TestAttribute(wnd, MOVEABLE) && my == 0) ||
  210.                 TestAttribute(wnd, SIZEABLE) &&
  211.                         mx == WindowWidth(wnd)-1 && my == WindowHeight(wnd)-1)    {
  212.                 if (wnd->condition == ISMAXIMIZED)
  213.                     break;
  214.                 if (my != 0 && wnd->condition == ISMINIMIZED)
  215.                     break;
  216.                 if (dragcount == -1)
  217.                     dragcount = 2;
  218.                 if (--dragcount == 0)    {
  219.                     if (px != (int)p1 || py != (int)p2)    {
  220.                         px = py = -1;
  221.                         break;
  222.                     }
  223.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE, (PARAM) &dwnd);
  224.                     if (my == 0)    {
  225.                         WindowMoving = TRUE;
  226.                         px = mx;
  227.                         py = my;
  228.                         diff = (int) mx;
  229.                     }
  230.                     else
  231.                         WindowSizing = TRUE;
  232.                     dragcount = -1;
  233.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  234.                     return FALSE;
  235.                 }
  236.                 else {
  237.                     px = (int)p1;
  238.                     py = (int)p2;
  239.                 }
  240.             }
  241.             break;
  242.         case MOUSE_MOVED:
  243.             if (WindowMoving)    {
  244.                 int leftmost = 0, topmost = 0,
  245.                     bottommost = 23, rightmost = 78;
  246.                 int x = (int) p1 - diff;
  247.                 int y = (int) p2;
  248.                 if (GetParent(wnd) != NULLWND)    {
  249.                     WINDOW wnd1 = GetParent(wnd);
  250.                     topmost    = GetClientTop(wnd1);
  251.                     leftmost   = GetClientLeft(wnd1);
  252.                     bottommost = GetClientBottom(wnd1);
  253.                     rightmost  = GetClientRight(wnd1)-1;
  254.                     if (TestAttribute(wnd1, HASMENUBAR))
  255.                         topmost++;
  256.                 }
  257.                 if (x < leftmost || x > rightmost ||
  258.                         y < topmost || y > bottommost)    {
  259.                     x = max(x, leftmost);
  260.                     x = min(x, rightmost);
  261.                     y = max(y, topmost);
  262.                     y = min(y, bottommost);
  263.                     SendMessage(NULLWND, MOUSE_CURSOR, x+diff, y);
  264.                 }
  265.                 if (x != px || y != py)    {
  266.                     px = x;
  267.                     py = y;
  268.                     dragborder(wnd, x, y);
  269.                 }
  270.                 return TRUE;
  271.             }
  272.             if (WindowSizing)    {
  273.                 sizeborder(wnd, (int) p1, (int) p2);
  274.                 return TRUE;
  275.             }
  276.             break;
  277.         case BUTTON_RELEASED:
  278.             if (WindowMoving || WindowSizing)    {
  279.                 if (WindowMoving)
  280.                     PostMessage(wnd, MOVE, dwnd.rc.lf, dwnd.rc.tp);
  281.                 else
  282.                     PostMessage(wnd, SIZE, dwnd.rc.rt, dwnd.rc.bt);
  283.                 TerminateMoveSize();
  284.             }
  285.             break;
  286.         case MAXIMIZE:
  287.             if (wnd->condition != ISMAXIMIZED)    {
  288.                 RECT rc = {0, 0, SCREENWIDTH-1, SCREENHEIGHT-1};
  289.                 RECT holdrc = wnd->RestoredRC;
  290.                 if (GetParent(wnd))
  291.                     rc = ClientRect(GetParent(wnd));
  292.                 wnd->condition = ISMAXIMIZED;
  293.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  294.                 SendMessage(wnd, MOVE, RectLeft(rc), RectTop(rc));
  295.                 SendMessage(wnd, SIZE, RectRight(rc), RectBottom(rc));
  296.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  297.                 wnd->RestoredRC = holdrc;
  298.             }
  299.             break;
  300.         case MINIMIZE:
  301.             if (wnd->condition != ISMINIMIZED)    {
  302.                 RECT rc = {74, 22, SCREENWIDTH-1, SCREENHEIGHT-1};
  303.                 RECT holdrc = wnd->RestoredRC;
  304.                 if (GetParent(wnd))    {
  305.                     RECT prc = WindowRect(GetParent(wnd));
  306.                     RectLeft(rc) = RectRight(prc) - 10;
  307.                     RectTop(rc) = RectBottom(prc) - 4;
  308.                     RectRight(rc) = RectLeft(rc)+9;
  309.                     RectBottom(rc) = RectTop(rc)+2;
  310.                 }
  311.                 wnd->condition = ISMINIMIZED;
  312.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  313.                 SendMessage(wnd, MOVE, RectLeft(rc), RectTop(rc));
  314.                 SendMessage(wnd, SIZE, RectRight(rc), RectBottom(rc));
  315.                 SetNextFocus(wnd, FALSE);
  316.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  317.                 wnd->RestoredRC = holdrc;
  318.             }
  319.             break;
  320.         case RESTORE:
  321.             if (wnd->condition != ISRESTORED)    {
  322.                 RECT holdrc = wnd->RestoredRC;
  323.                 wnd->condition = ISRESTORED;
  324.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  325.                 SendMessage(wnd, MOVE, wnd->RestoredRC.lf,
  326.                     wnd->RestoredRC.tp);
  327.                 wnd->RestoredRC = holdrc;
  328.                 SendMessage(wnd, SIZE, wnd->RestoredRC.rt,
  329.                     wnd->RestoredRC.bt);
  330.                 SendMessage(wnd, SETFOCUS, TRUE, 0);
  331.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  332.             }
  333.             break;
  334.         case MOVE:    {
  335.             int xdif = (int) p1 - wnd->rc.lf;
  336.             int ydif = (int) p2 - wnd->rc.tp;
  337.             WINDOW wnd1 = Focus.FirstWindow;
  338.  
  339.             SendMessage(wnd, HIDE_WINDOW, 0, 0);
  340.             wnd->rc.lf = (int) p1;
  341.             wnd->rc.tp = (int) p2;
  342.             wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
  343.             wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
  344.             if (wnd->condition == ISRESTORED)
  345.                 wnd->RestoredRC = wnd->rc;
  346.             while (wnd1 != NULLWND)    {
  347.                 if (GetParent(wnd1) == wnd)
  348.                     SendMessage(wnd1, MOVE,
  349.                         wnd1->rc.lf+xdif, wnd1->rc.tp+ydif);
  350.                 wnd1 = NextWindow(wnd1);
  351.             }
  352.             SendMessage(wnd, SHOW_WINDOW, 0, 0);
  353.             break;
  354.         }
  355.         case SIZE:
  356.             SendMessage(wnd, HIDE_WINDOW, 0, 0);
  357.             wnd->rc.rt = (int) p1;
  358.             wnd->rc.bt = (int) p2;
  359.             wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
  360.             wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
  361.             wnd->RestoredRC = WindowRect(wnd);
  362.             SendMessage(wnd, SHOW_WINDOW, 0, 0);
  363.             break;
  364.         case CLOSE_WINDOW:
  365.             if (isWindow(wnd))    {
  366.                  int DoneClosing = FALSE;
  367.  
  368.                 /* ----------- hide this window ------------ */
  369.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  370.  
  371.                 /* ------- close the children of this window ------- */
  372.                 CloseDepth++;
  373.                 while (!DoneClosing)    {
  374.                     WINDOW wnd1 = Focus.LastWindow;
  375.                     DoneClosing = TRUE;
  376.                     while (wnd1 != NULLWND)    {
  377.                         WINDOW prwnd = PrevWindow(wnd1);
  378.                         if (GetParent(wnd1) == wnd)    {
  379.                             SendMessage(wnd1, CLOSE_WINDOW, 0, 0);
  380.                             DoneClosing = FALSE;
  381.                             break;
  382.                         }
  383.                         wnd1 = prwnd;
  384.                     }
  385.                 }
  386.                 --CloseDepth;
  387.  
  388.                 /* ------- remove this window from the
  389.                         list of open windows ------------- */
  390.  
  391.                 RemoveWindow(wnd, TRUE);
  392.  
  393.                 /* --- change focus if this window had it --- */
  394.                 if (CloseDepth == 0)
  395.                     SetNextFocus(wnd, TRUE);
  396.                 else if (wnd == inFocus)
  397.                     inFocus = NULL;
  398.  
  399.                 /* ----- free memory allocated to this window ----- */
  400.                 if (wnd->title != NULL)
  401.                     free(wnd->title);
  402.                 if (wnd->videosave != NULL)
  403.                     free(wnd->videosave);
  404.                 free(wnd);
  405.             }
  406.             break;
  407.         default:
  408.             break;
  409.     }
  410.     return TRUE;
  411. }
  412.  
  413. static void TerminateMoveSize(void)
  414. {
  415.     px = py = -1;
  416.     diff = 0;
  417.     SendMessage(&dwnd, RELEASE_MOUSE, 0, 0);
  418.     SendMessage(&dwnd, RELEASE_KEYBOARD, 0, 0);
  419.     RestoreBorder(dwnd.rc);
  420.     WindowMoving = WindowSizing = FALSE;
  421. }
  422.  
  423. static void near dragborder(WINDOW wnd, int x, int y)
  424. {
  425.     RestoreBorder(dwnd.rc);
  426.     /* ------- build the dummy window -------- */
  427.     dwnd.rc.lf = x;
  428.     dwnd.rc.tp = y;
  429.     dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
  430.     dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
  431.     dwnd.ht = WindowHeight(wnd);
  432.     dwnd.wd = WindowWidth(wnd);
  433.     dwnd.parent = GetParent(wnd);
  434.     dwnd.attrib = VISIBLE | HASBORDER;
  435.     SaveBorder(dwnd.rc);
  436.     DisplayBorder(&dwnd);
  437. }
  438.  
  439. static void near sizeborder(WINDOW wnd, int rt, int bt)
  440. {
  441.     int leftmost = GetLeft(wnd)+10;
  442.     int topmost = GetTop(wnd)+3;
  443.     int bottommost = SCREENHEIGHT-1;
  444.     int rightmost  = SCREENWIDTH-1;
  445.     if (GetParent(wnd))    {
  446.         bottommost = min(bottommost, GetBottom(GetParent(wnd))-1);
  447.         rightmost  = min(rightmost, GetRight(GetParent(wnd))-1);
  448.     }
  449.     rt = min(rt, rightmost);
  450.     bt = min(bt, bottommost);
  451.     rt = max(rt, leftmost);
  452.     bt = max(bt, topmost);
  453.     SendMessage(NULLWND, MOUSE_CURSOR, rt, bt);
  454.  
  455.     if (rt != px || bt != py)
  456.         RestoreBorder(dwnd.rc);
  457.  
  458.     /* ------- change the dummy window -------- */
  459.     dwnd.ht = bt-dwnd.rc.tp+1;
  460.     dwnd.wd = rt-dwnd.rc.lf+1;
  461.     dwnd.rc.rt = rt;
  462.     dwnd.rc.bt = bt;
  463.     if (rt != px || bt != py)    {
  464.         px = rt;
  465.         py = bt;
  466.         SaveBorder(dwnd.rc);
  467.         DisplayBorder(&dwnd);
  468.     }
  469. }
  470.  
  471. void SetNextFocus(WINDOW wnd, int PassParam)
  472. {
  473.     if (NextWindow(Focus.FirstWindow) == NULLWND)
  474.         inFocus = NULLWND;
  475.     else if (wnd == inFocus)    {
  476.         int loopctr = 0;
  477.         WINDOW wnd1 = wnd;
  478.         while (wnd1 != NULLWND)    {
  479.             if (NextWindow(wnd1) == NULLWND)    {
  480.                 wnd1 = Focus.FirstWindow;
  481.                 if (loopctr++)    {
  482.                     if (PassParam)
  483.                         inFocus = NULLWND;
  484.                     break;
  485.                 }
  486.             }
  487.             else
  488.                 wnd1 = NextWindow(wnd1);
  489.             if (wnd1 == wnd)
  490.                 continue;
  491.             if (GetParent(wnd1) != GetParent(wnd))
  492.                 continue;
  493.             if (SendMessage(wnd1, SETFOCUS, TRUE, PassParam))
  494.                 break;
  495.         }
  496.     }
  497. }
  498.  
  499. static void near PaintOverLap(WINDOW wnd, RECT rc)
  500. {
  501.     RECT src = rc;
  502.  
  503.     int isLF = RectLeft(rc) == GetLeft(wnd);
  504.     int isBT = RectBottom(rc) == GetBottom(wnd);
  505.     int isRT = RectRight(rc) == GetRight(wnd);
  506.     int isTP = RectTop(rc) == GetTop(wnd);
  507.     int isRSH = TestAttribute(wnd, SHADOW) && RectRight(rc) == GetRight(wnd)+1;
  508.     int isBSH = TestAttribute(wnd, SHADOW) && RectBottom(rc) == GetBottom(wnd)+1;
  509.     int isSH = isRSH | isBSH;
  510.  
  511.     /* ---- adjust rect to remove border intersections --- */
  512.     if (isLF)
  513.         RectLeft(rc)++;
  514.     if (isRT)
  515.         --RectRight(rc);
  516.     if (isTP)
  517.         RectTop(rc)++;
  518.     if (isBT)
  519.         --RectBottom(rc);
  520.     if (isRSH)
  521.         RectRight(rc) -= 2;
  522.     if (isBSH)
  523.         RectBottom(rc) -= 2;
  524.  
  525.     /* ---- adjust rectangle to be relative to window's client area ---- */
  526.     RectLeft(rc) -= GetClientLeft(wnd);
  527.     RectTop(rc) -= GetClientTop(wnd);
  528.     RectRight(rc) -= GetClientLeft(wnd);
  529.     RectBottom(rc) -= GetClientTop(wnd);
  530.  
  531.     SendMessage(wnd, PAINT, (PARAM) &rc, 0);
  532.  
  533.     /* -- adjust border rectangle to be relative to window's area -- */
  534.     RectLeft(src) -= GetLeft(wnd);
  535.     RectTop(src) -= GetTop(wnd);
  536.     RectRight(src) -= GetLeft(wnd);
  537.     RectBottom(src) -= GetTop(wnd);
  538.  
  539.     if (isRT || isTP || isLF || isBT || isSH)
  540.         SendMessage(wnd, BORDER, (PARAM) &src, 0);
  541. }
  542.  
  543. static RECT adjShadow(WINDOW wnd)
  544. {
  545.     RECT rc = wnd->rc;
  546.     if (TestAttribute(wnd, SHADOW))    {
  547.         if (RectRight(rc) < SCREENWIDTH-1)
  548.             RectRight(rc)++;           
  549.         if (RectBottom(rc) < SCREENHEIGHT-1)
  550.             RectBottom(rc)++;
  551.     }
  552.     return rc;
  553. }
  554.  
  555. static void near PaintOverLappers(WINDOW wnd)
  556. {
  557.     if (isVisible(wnd))    {
  558.         WINDOW lownd = Focus.FirstWindow;
  559.         RECT wrc = adjShadow(wnd);
  560.         while (lownd != NULL)    {
  561.             if (lownd != wnd && isVisible(lownd))    {
  562.                 RECT rc = adjShadow(lownd);
  563.                 rc = subRectangle(rc, wrc);
  564.                 if (ValidRect(rc))
  565.                     if (GetParent(lownd) != wnd)
  566.                         PaintOverLap(lownd, rc);
  567.             }
  568.             lownd = NextWindow(lownd);
  569.         }
  570.     }
  571. }
  572.  
  573. static int *Bsave = NULL;
  574. static int Bht, Bwd;
  575.  
  576. static void SaveBorder(RECT rc)
  577. {
  578.     Bht = RectBottom(rc) - RectTop(rc) + 1;
  579.     Bwd = RectRight(rc) - RectLeft(rc) + 1;
  580.     if ((Bsave = realloc(Bsave, (Bht + Bwd) * 4)) != NULL)    {
  581.         RECT lrc = rc;
  582.         int i;
  583.         int *cp;
  584.         RectBottom(lrc) = RectTop(lrc);
  585.         getvideo(lrc, Bsave);
  586.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  587.         getvideo(lrc, Bsave + Bwd);
  588.         cp = Bsave + Bwd * 2;
  589.         for (i = 1; i < Bht-1; i++)    {
  590.             *cp++ = GetVideoChar(RectLeft(rc),RectTop(rc)+i);
  591.             *cp++ = GetVideoChar(RectRight(rc),RectTop(rc)+i);
  592.         }
  593.     }
  594. }
  595.  
  596. static void RestoreBorder(RECT rc)
  597. {
  598.     if (Bsave != NULL)    {
  599.         RECT lrc = rc;
  600.         int i;
  601.         int *cp;
  602.         RectBottom(lrc) = RectTop(lrc);
  603.         storevideo(lrc, Bsave);
  604.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  605.         storevideo(lrc, Bsave + Bwd);
  606.         cp = Bsave + Bwd * 2;
  607.         for (i = 1; i < Bht-1; i++)    {
  608.             PutVideoChar(RectLeft(rc),RectTop(rc)+i, *cp++);
  609.             PutVideoChar(RectRight(rc),RectTop(rc)+i, *cp++);
  610.         }
  611.         free(Bsave);
  612.         Bsave = NULL;
  613.     }
  614. }
  615.  
  616. static void RemoveWindow(WINDOW wnd, int Both)
  617. {
  618.     if (PrevWindow(wnd) != NULLWND)
  619.         NextWindow(PrevWindow(wnd)) = NextWindow(wnd);
  620.     if (NextWindow(wnd) != NULLWND)
  621.         PrevWindow(NextWindow(wnd)) = PrevWindow(wnd);
  622.     if (wnd == Focus.FirstWindow)
  623.         Focus.FirstWindow = NextWindow(wnd);
  624.     if (wnd == Focus.LastWindow)
  625.         Focus.LastWindow = PrevWindow(wnd);
  626.     if (Both)    {
  627.         if (PrevWindowBuilt(wnd) != NULLWND)
  628.             NextWindowBuilt(PrevWindowBuilt(wnd)) = NextWindowBuilt(wnd);
  629.         if (NextWindowBuilt(wnd) != NULLWND)
  630.             PrevWindowBuilt(NextWindowBuilt(wnd)) = PrevWindowBuilt(wnd);
  631.         if (wnd == Built.FirstWindow)
  632.             Built.FirstWindow = NextWindowBuilt(wnd);
  633.         if (wnd == Built.LastWindow)
  634.             Built.LastWindow = PrevWindowBuilt(wnd);
  635.     }
  636. }
  637.  
  638. static void AddWindow(WINDOW wnd, int Both)
  639. {
  640.     if (Focus.FirstWindow == NULLWND)
  641.         Focus.FirstWindow = wnd;
  642.     if (Focus.LastWindow != NULLWND)
  643.         NextWindow(Focus.LastWindow) = wnd;
  644.     PrevWindow(wnd) = Focus.LastWindow;
  645.     NextWindow(wnd) = NULLWND;
  646.     Focus.LastWindow = wnd;
  647.     if (Both)    {
  648.         if (Built.FirstWindow == NULLWND)
  649.             Built.FirstWindow = wnd;
  650.         if (Built.LastWindow != NULLWND)
  651.             NextWindowBuilt(Built.LastWindow) = wnd;
  652.         PrevWindowBuilt(wnd) = Built.LastWindow;
  653.         NextWindowBuilt(wnd) = NULLWND;
  654.         Built.LastWindow = wnd;
  655.     }
  656. }
  657.  
  658. WINDOW GetFirstChild(WINDOW wnd)
  659. {
  660.     NextWindow = Built.FirstWindow;
  661.     while (NextWindow != NULLWND)    {
  662.         if (GetParent(NextWindow) == wnd)
  663.             break;
  664.         NextWindow = NextWindowBuilt(NextWindow);
  665.     }
  666.     return NextWindow;
  667. }
  668.  
  669. WINDOW GetNextChild(WINDOW wnd)
  670. {
  671.     do    {
  672.         NextWindow = NextWindowBuilt(NextWindow);
  673.         if (GetParent(NextWindow) == wnd)
  674.             break;
  675.     }    while (NextWindow != NULLWND);
  676.     return NextWindow;
  677. }
  678.  
  679. WINDOW GetLastChild(WINDOW wnd)
  680. {
  681.     NextWindow = Built.LastWindow;
  682.     while (NextWindow != NULLWND)    {
  683.         if (GetParent(NextWindow) == wnd)
  684.             break;
  685.         NextWindow = PrevWindowBuilt(NextWindow);
  686.     }
  687.     return NextWindow;
  688. }
  689.  
  690. WINDOW GetPrevChild(WINDOW wnd)
  691. {
  692.     do    {
  693.         NextWindow = PrevWindowBuilt(NextWindow);
  694.         if (GetParent(NextWindow) == wnd)
  695.             break;
  696.     }    while (NextWindow != NULLWND);
  697.     return NextWindow;
  698. }
  699.  
  700. static int InsideWindow(WINDOW wnd, int x, int y)
  701. {
  702.     RECT rc = WindowRect(wnd);
  703.     if (!TestAttribute(wnd, NOCLIP))    {
  704.         WINDOW pwnd = GetParent(wnd);
  705.         while (pwnd != NULL)    {
  706.             rc = subRectangle(rc, ClientRect(pwnd));
  707.             pwnd = GetParent(pwnd);
  708.         }
  709.     }
  710.     return InsideRect(x, y, rc);
  711. }
  712.  
  713. WINDOW inWindow(int x, int y)
  714. {
  715.     WINDOW wnd = Focus.LastWindow;
  716.     while (wnd != NULLWND)    {
  717.         if (SendMessage(wnd, INSIDE_WINDOW, x, y))
  718.             break;
  719.         wnd = PrevWindow(wnd);
  720.     }
  721.     return wnd;
  722. }
  723.  
  724. int isWindow(WINDOW wnd)
  725. {
  726.     WINDOW ws = Focus.FirstWindow;
  727.     while (ws != NULLWND)    {
  728.         if (ws == wnd)
  729.             break;
  730.         ws = NextWindow(ws);
  731.     }
  732.     return ws != NULLWND;
  733. }
  734.  
  735. int WndForeground(WINDOW wnd)
  736. {
  737.     CLASS class = FindClass(GetClass(wnd));
  738.     if (classdefs[class].fg == NULL)
  739.         class = FindClass(GetClass(GetParent(wnd)));
  740.     return *classdefs[class].fg;
  741. }
  742.  
  743. int WndBackground(WINDOW wnd)
  744. {
  745.     CLASS class = FindClass(GetClass(wnd));
  746.     if (classdefs[class].bg == NULL)
  747.         class = FindClass(GetClass(GetParent(wnd)));
  748.     return *classdefs[class].bg;
  749. }
  750.  
  751. int FrameForeground(WINDOW wnd)
  752. {
  753.     CLASS class = FindClass(GetClass(wnd));
  754.     if (classdefs[class].fbg != NULL)
  755.         return *classdefs[class].ffg;
  756.     else
  757.         return WndForeground(wnd);
  758. }
  759.  
  760. int FrameBackground(WINDOW wnd)
  761. {
  762.     CLASS class = FindClass(GetClass(wnd));
  763.     if (classdefs[class].fbg != NULL)
  764.         return *classdefs[class].fbg;
  765.     else
  766.         return WndBackground(wnd);
  767. }
  768.  
  769. int SelectForeground(WINDOW wnd)
  770. {
  771.     CLASS class = FindClass(GetClass(wnd));
  772.     return *classdefs[class].sfg;
  773. }
  774.  
  775. int SelectBackground(WINDOW wnd)
  776. {
  777.     int class = FindClass(GetClass(wnd));
  778.     return *classdefs[class].sbg;
  779. }
  780.  
  781. void SetStandardColor(WINDOW wnd)
  782. {
  783.     foreground = WndForeground(wnd);
  784.     background = WndBackground(wnd);
  785. }
  786.  
  787. void SetReverseColor(WINDOW wnd)
  788. {
  789.     foreground = SelectForeground(wnd);
  790.     background = SelectBackground(wnd);
  791. }
  792.  
  793. void SetClassColors(CLASS class)
  794. {
  795.     foreground = *classdefs[class].fg;
  796.     background = *classdefs[class].bg;
  797. }
  798.  
  799.  
  800.