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