home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / dflt10.exe / NORMAL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-10  |  31.5 KB  |  1,046 lines

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