home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 08 / dflat5 / normal.c < prev    next >
Text File  |  1991-06-28  |  35KB  |  963 lines

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