home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / mdi / mdisplit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-06  |  23.8 KB  |  737 lines

  1. /***************************************************************************\
  2. * split.c - Code for window splitting
  3. *
  4. * Created by Microsoft Corporation, 1989
  5. \***************************************************************************/
  6.  
  7. #define INCL_WINSYS
  8. #define INCL_WINCOMMON
  9. #define INCL_WINMESSAGEMGR
  10. #define INCL_WINPOINTERS
  11. #define INCL_WINMENUS
  12. #define INCL_WININPUT
  13. #define INCL_WINHEAP
  14. #define INCL_WINSCROLLBARS
  15. #define INCL_WINFRAMEMGR
  16. #define INCL_WINWINDOWMGR
  17. #define INCL_WINRECTANGLES
  18. #define INCL_GPIBITMAPS
  19. #define INCL_GPIPRIMITIVES
  20.  
  21. #include <os2.h>
  22. #include "app.h"
  23. #include "appdata.h"
  24. #include "mdi.h"
  25. #include "mdidata.h"
  26.  
  27. VOID InvertRect(HPS, PRECTL);
  28. VOID TrackSplitbars(HWND, USHORT, SHORT, SHORT);
  29. VOID FillSplitbarInteriors(USHORT, HWND, HWND);
  30. HWND QueryBotLeftClient(HWND hwndFrame, NPDOC npdoc);
  31. VOID DrawTrackRects(HPS, PRECTL, SHORT, SHORT, USHORT);
  32. VOID MoveTrackRects(HPS, PRECTL, USHORT, SHORT, SHORT, SHORT, SHORT);
  33. VOID CalcTrackRect(PRECTL, PRECTL, SHORT, USHORT);
  34. VOID SetSplitbarPos(HWND, PRECTL, SHORT, SHORT, USHORT);
  35. HWND QueryBotLeftClient(HWND hwndFrame, NPDOC npdoc);
  36.  
  37. MRESULT EXPENTRY SplitbarWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  38. {
  39.     HPS hps;
  40.     POINTL ptl;
  41.     RECTL rclPaint;
  42.     HWND hwndClient, hwndFrame, hwndOrigin;
  43.     BOOL fControl;
  44.     register NPDOC npdoc;
  45.  
  46.     switch (msg) {
  47.  
  48.     case WM_PAINT:
  49.         hwndFrame = WinQueryWindow(hwnd, QW_PARENT, FALSE);
  50.         hwndClient = WinWindowFromID(hwndFrame, FID_CLIENT);
  51.  
  52.         npdoc = NPDOCFROMCLIENT(hwndClient);
  53.  
  54.         hps = WinBeginPaint(hwnd, NULL, NULL);
  55.  
  56.         WinQueryWindowRect(hwnd, &rclPaint);
  57.  
  58.         if (WinQueryWindowUShort(hwnd, QWS_ID) == ID_VERTSPLITBAR) {
  59.             if (npdoc->fs & DF_SPLITVERT) {
  60.                 WinDrawBorder(hps, &rclPaint, 1, 0, SYSCLR_WINDOWFRAME,
  61.                             SYSCLR_WINDOW, DB_STANDARD);
  62.                 /*
  63.                  * Make the interiors of the splitbars
  64.                  * visually correct.
  65.                  */
  66.                 FillSplitbarInteriors(npdoc->fs, hwnd,
  67.                         WinWindowFromID(hwndFrame, ID_HORZSPLITBAR));
  68.             } else {
  69.                 WinFillRect(hps, &rclPaint, SYSCLR_WINDOWFRAME);
  70.             }
  71.         } else {
  72.             if (npdoc->fs & DF_SPLITHORZ) {
  73.                 WinDrawBorder(hps, &rclPaint, 0, 1, SYSCLR_WINDOWFRAME,
  74.                         SYSCLR_WINDOW, DB_STANDARD | DB_INTERIOR);
  75.             } else {
  76.                 WinFillRect(hps, &rclPaint, SYSCLR_WINDOWFRAME);
  77.             }
  78.         }
  79.  
  80.         WinEndPaint(hps);
  81.         break;
  82.  
  83.     case WM_MOUSEMOVE:
  84.         hwndFrame = WinQueryWindow(hwnd, QW_PARENT, FALSE);
  85.         hwndClient = WinWindowFromID(hwndFrame, FID_CLIENT);
  86.  
  87.         npdoc = NPDOCFROMCLIENT(hwndClient);
  88.  
  89.         ptl.x = SHORT1FROMMP(mp1);
  90.         ptl.y = SHORT2FROMMP(mp1);
  91.  
  92.         hwndOrigin = QueryBotLeftClient(hwndFrame, npdoc);
  93.         WinMapWindowPoints(hwnd, hwndOrigin, (PPOINTL)&ptl, 1);
  94.  
  95.         if (WinQueryWindowUShort(hwnd, QWS_ID) == ID_VERTSPLITBAR) {
  96.  
  97.             if ((npdoc->fs & DF_SPLITHORZ) &&
  98.                     ((SHORT)ptl.y > (npdoc->cyHorzSplitPos - (cyHorzSplitbar))) &&
  99.                     ((SHORT)ptl.y <= (npdoc->cyHorzSplitPos + (cyHorzSplitbar * 2)))) {
  100.                 WinSetPointer(HWND_DESKTOP, hptrHVSplit);
  101.             } else {
  102.                 WinSetPointer(HWND_DESKTOP, hptrVertSplit);
  103.             }
  104.         } else {
  105.             if ((npdoc->fs & DF_SPLITVERT) &&
  106.                     ((SHORT)ptl.x > (npdoc->cxVertSplitPos - (cxVertSplitbar))) &&
  107.                     ((SHORT)ptl.x <= (npdoc->cxVertSplitPos + (cxVertSplitbar * 2)))) {
  108.                 WinSetPointer(HWND_DESKTOP, hptrHVSplit);
  109.             } else {
  110.                 WinSetPointer(HWND_DESKTOP, hptrHorzSplit);
  111.             }
  112.         }
  113.         break;
  114.  
  115.     case WM_BUTTON1DOWN:
  116.     case WM_BUTTON1DBLCLK:
  117.         /*
  118.          * Get the control key state here so the user doesn't
  119.          * have to hold it down the whole time to get the
  120.          * desired effect.
  121.          */
  122.         fControl = (WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000);
  123.  
  124.         hwndFrame = WinQueryWindow(hwnd, QW_PARENT, FALSE);
  125.         hwndClient = WinWindowFromID(hwndFrame, FID_CLIENT);
  126.  
  127.         /*
  128.          * Update the entire window before we start
  129.          * tracking with the splitter bars.
  130.          */
  131.         WinUpdateWindow(hwndFrame);
  132.  
  133.         npdoc = NPDOCFROMCLIENT(hwndClient);
  134.  
  135.         ptl.x = SHORT1FROMMP(mp1);
  136.         ptl.y = SHORT2FROMMP(mp1);
  137.  
  138.         hwndOrigin = QueryBotLeftClient(hwndFrame, npdoc);
  139.         WinMapWindowPoints(hwnd, hwndOrigin, (PPOINTL)&ptl, 1);
  140.  
  141.         if (WinQueryWindowUShort(hwnd, QWS_ID) == ID_VERTSPLITBAR) {
  142.             if ((npdoc->fs & DF_SPLITHORZ) &&
  143.                     ((SHORT)ptl.y > (npdoc->cyHorzSplitPos - (cyHorzSplitbar))) &&
  144.                     ((SHORT)ptl.y <= (npdoc->cyHorzSplitPos + (cyHorzSplitbar * 2)))) {
  145.                 TrackSplitbars(hwndClient, SPS_VERT | SPS_HORZ, (SHORT)ptl.x,
  146.                         (SHORT)ptl.y);
  147.             } else {
  148.                 TrackSplitbars(hwndClient, SPS_VERT, (SHORT)ptl.x,
  149.                         (SHORT)ptl.y);
  150.             }
  151.         } else {
  152.             if ((npdoc->fs & DF_SPLITVERT) &&
  153.                     ((SHORT)ptl.x > (npdoc->cxVertSplitPos - (cxVertSplitbar))) &&
  154.                     ((SHORT)ptl.x <= (npdoc->cxVertSplitPos + (cxVertSplitbar * 2)))) {
  155.                 TrackSplitbars(hwndClient, SPS_VERT | SPS_HORZ, (SHORT)ptl.x,
  156.                         (SHORT)ptl.y);
  157.             } else {
  158.                 TrackSplitbars(hwndClient, SPS_HORZ, (SHORT)ptl.x,
  159.                         (SHORT)ptl.y);
  160.             }
  161.         }
  162.  
  163.         /*
  164.          * If the control key is down, we leave
  165.          * the focus where it is.
  166.          */
  167.         if (fControl == FALSE)
  168.             WinSetFocus(HWND_DESKTOP, hwndClient);
  169.  
  170.         break;
  171.  
  172.     case WM_MOVE:
  173.     case WM_SIZE:
  174.         WinInvalidateRect(hwnd, NULL, FALSE);
  175.         break;
  176.  
  177.     default:
  178.         return(WinDefWindowProc(hwnd, msg, mp1, mp2));
  179.         break;
  180.     }
  181.  
  182.     return (0L);
  183. }
  184.  
  185.  
  186. VOID FillSplitbarInteriors(USHORT fs, HWND hwndVert, HWND hwndHorz)
  187. {
  188.     HPS hps;
  189.     RECTL rclVertSplitbar, rclHorzSplitbar;
  190.  
  191.     if (fs & DF_SPLITVERT) {
  192.         hps = WinGetPS(hwndVert);
  193.         WinQueryWindowRect(hwndVert, &rclVertSplitbar);
  194.         WinInflateRect(NULL, &rclVertSplitbar, -cxBorder, 0);
  195.         WinFillRect(hps, &rclVertSplitbar, SYSCLR_WINDOW);
  196.         WinReleasePS(hps);
  197.     }
  198.  
  199.     if (fs & DF_SPLITHORZ) {
  200.         hps = WinGetPS(hwndHorz);
  201.         WinQueryWindowRect(hwndHorz, &rclHorzSplitbar);
  202.         WinInflateRect(NULL, &rclHorzSplitbar, 0, -cyBorder);
  203.         WinFillRect(hps, &rclHorzSplitbar, SYSCLR_WINDOW);
  204.         WinReleasePS(hps);
  205.     }
  206. }
  207.  
  208.  
  209. BOOL CreateSplitbarWindows(HWND hwndFrame, NPDOC npdoc)
  210. {
  211.     USHORT fsStyle;
  212.     register NPVIEW npview, npviewNew;
  213.     HWND hwndNewClient;
  214.  
  215.     fsStyle = npdoc->fsStyle;
  216.     npview = npdoc->npviewFirst;
  217.  
  218.     if (fsStyle & DS_VERTSPLITBAR) {
  219.         if (WinCreateWindow(hwndFrame, WC_SCROLLBAR, "",
  220.                 SBS_HORZ, 0, 0, 0, 0, hwndFrame,
  221.                 WinWindowFromID(hwndFrame, FID_HORZSCROLL),
  222.                 ID_HORZSCROLL2, NULL, NULL) == NULL)
  223.             return (FALSE);
  224.  
  225.         if (WinCreateWindow(hwndFrame, szSplitbarClass, "",
  226.                 (ULONG)SPS_VERT, 0, 0, 0, 0, hwndFrame,
  227.                 WinWindowFromID(hwndFrame, FID_MINMAX),
  228.                 ID_VERTSPLITBAR, NULL, NULL) == NULL)
  229.             return (FALSE);
  230.  
  231.         hwndNewClient = WinCreateWindow(hwndFrame, szDocClass, "",
  232.                 0L, 0, 0, 0, 0, hwndFrame,
  233.                 WinWindowFromID(hwndFrame, FID_CLIENT),
  234.                 ID_CLIENT2, NULL, NULL);
  235.         if (hwndNewClient == NULL)
  236.             return (FALSE);
  237.  
  238.         /*
  239.          * Link ID_CLIENT2 into npdoc's view list.
  240.          */
  241.         npviewNew = NPVIEWFROMCLIENT(hwndNewClient);
  242.         npview->npviewNext = npviewNew;
  243.         npview = npviewNew;
  244.     }
  245.  
  246.     if (fsStyle & DS_HORZSPLITBAR) {
  247.         if (WinCreateWindow(hwndFrame, WC_SCROLLBAR, "",
  248.                 SBS_VERT, 0, 0, 0, 0, hwndFrame,
  249.                 WinWindowFromID(hwndFrame, FID_VERTSCROLL),
  250.                 ID_VERTSCROLL2, NULL, NULL) == NULL)
  251.             return (FALSE);
  252.  
  253.         if (WinCreateWindow(hwndFrame, szSplitbarClass, "",
  254.                 (ULONG)SPS_HORZ, 0, 0, 0, 0, hwndFrame,
  255.                 WinWindowFromID(hwndFrame, FID_MINMAX),
  256.                 ID_HORZSPLITBAR, NULL, NULL) == NULL)
  257.             return (FALSE);
  258.  
  259.         /*
  260.          * If we're split vertically as well, then we want to
  261.          * insert ID_CLIENT3 behind ID_CLIENT2 and create
  262.          * ID_CLIENT4 behind CLIENT3, otherwise we just create
  263.          * ID_CLIENT3 behind FID_CLIENT.
  264.          */
  265.         if (fsStyle & DS_VERTSPLITBAR) {
  266.             hwndNewClient = WinCreateWindow(hwndFrame, szDocClass, "",
  267.                     0L, 0, 0, 0, 0, hwndFrame,
  268.                     WinWindowFromID(hwndFrame, ID_CLIENT2),
  269.                     ID_CLIENT3, NULL, NULL);
  270.             if (hwndNewClient == NULL)
  271.                 return (FALSE);
  272.  
  273.             /*
  274.              * Link ID_CLIENT3 into npdoc's view list.
  275.              */
  276.             npviewNew = NPVIEWFROMCLIENT(hwndNewClient);
  277.             npview->npviewNext = npviewNew;
  278.             npview = npviewNew;
  279.  
  280.             hwndNewClient = WinCreateWindow(hwndFrame, szDocClass, "",
  281.                     0L, 0, 0, 0, 0, hwndFrame,
  282.                     WinWindowFromID(hwndFrame, ID_CLIENT3),
  283.                     ID_CLIENT4, NULL, NULL);
  284.             if (hwndNewClient == NULL)
  285.                 return (FALSE);
  286.  
  287.             /*
  288.              * Link ID_CLIENT4 into npdoc's view list.
  289.              */
  290.             npviewNew = NPVIEWFROMCLIENT(hwndNewClient);
  291.             npview->npviewNext = npviewNew;
  292.             npview = npviewNew;
  293.  
  294.         } else {
  295.             hwndNewClient = WinCreateWindow(hwndFrame, szDocClass, "",
  296.                     0L, 0, 0, 0, 0, hwndFrame,
  297.                     WinWindowFromID(hwndFrame, FID_CLIENT),
  298.                     ID_CLIENT3, NULL, NULL);
  299.             if (hwndNewClient == NULL)
  300.                 return (FALSE);
  301.  
  302.             /*
  303.              * Link ID_CLIENT3 into npdoc's view list.
  304.              */
  305.             npviewNew = NPVIEWFROMCLIENT(hwndNewClient);
  306.             npview->npviewNext = npviewNew;
  307.             npview = npviewNew;
  308.         }
  309.     }
  310.  
  311.     return (TRUE);
  312. }
  313.  
  314.  
  315. HWND QueryBotLeftClient(HWND hwndFrame, NPDOC npdoc)
  316. {
  317.     if (npdoc->fs & DF_SPLITHORZ) {
  318.         /*
  319.          * If there isn't enough room to split
  320.          * then only the main client will be
  321.          * visible so we'll use it.
  322.          */
  323.         if (WinIsWindowVisible(WinWindowFromID(hwndFrame, ID_HORZSPLITBAR)))
  324.             return (WinWindowFromID(hwndFrame, ID_CLIENT3));
  325.         else
  326.             return (WinWindowFromID(hwndFrame, FID_CLIENT));
  327.  
  328.     } else {
  329.         return (WinWindowFromID(hwndFrame, FID_CLIENT));
  330.     }
  331. }
  332.  
  333.  
  334.  
  335. VOID TrackSplitbars(HWND hwndClient, register USHORT fsTrack, SHORT xMouse,
  336.         SHORT yMouse)
  337. {
  338.     SHORT x, y;
  339.     SHORT xNew, yNew;
  340.     HPS hps;
  341.     RECTL rclClient, rclClientScreen;
  342.     QMSG qmsg;
  343.     AREABUNDLE abnd;
  344.     HWND hwndFrame, hwndOrigin;
  345.     register NPDOC npdoc;
  346.     POINTL ptlPointer;
  347.  
  348.     hwndFrame = WinQueryWindow(hwndClient, QW_PARENT, FALSE);
  349.  
  350.     WinLockWindowUpdate(HWND_DESKTOP, hwndFrame);
  351.  
  352.     /*
  353.      * If we're split horizontally then we want the
  354.      * origin to be a ID_CLIENT3's origin, otherwise
  355.      * we want FID_CLIENT's origin.
  356.      */
  357.     npdoc = NPDOCFROMCLIENT(hwndClient);
  358.     hwndOrigin = QueryBotLeftClient(hwndFrame, npdoc);
  359.  
  360.     /*
  361.      * We use WinCalcFrameRect() to get the client rectangle
  362.      * rather than WinQueryWindowRect() because the window
  363.      * might already be split, so hwndClient's rectangle wouldn't
  364.      * necessarily include the area we want.
  365.      */
  366.     WinQueryWindowRect(hwndFrame, &rclClient);
  367.  
  368.     /*
  369.      * Map rectangle to screen coordinates because
  370.      * WinCalcFrameRect() will byte-align the client.
  371.      */
  372.     WinMapWindowPoints(hwndFrame, HWND_DESKTOP, (PPOINTL)&rclClient, 2);
  373.     WinCalcFrameRect(hwndFrame, &rclClient, TRUE);
  374.  
  375.     WinCopyRect(NULL, &rclClientScreen, &rclClient);
  376.     WinMapWindowPoints(HWND_DESKTOP, hwndOrigin, (PPOINTL)&rclClient, 2);
  377.  
  378.     WinSetCapture(HWND_DESKTOP, hwndOrigin);
  379.  
  380.     /*
  381.      * We get a PSF_PARENTCLIP PS so we can draw the
  382.      * splitbars through the other client windows,
  383.      * but still get the PS origin we want.
  384.      */
  385.     hps = WinGetClipPS(hwndOrigin, NULL,
  386.             PSF_PARENTCLIP | PSF_LOCKWINDOWUPDATE);
  387.  
  388.     abnd.usSymbol = PATSYM_HALFTONE;
  389.     abnd.lColor = CLR_TRUE;
  390.     abnd.lBackColor = CLR_FALSE;
  391.     GpiSetAttrs(hps, PRIM_AREA, ABB_SYMBOL | ABB_COLOR | ABB_BACK_COLOR, 0L,
  392.             (PBUNDLE)&abnd);
  393.  
  394.     if (fsTrack & SPS_HORZ) {
  395.         if (npdoc->fs & DF_SPLITHORZ) {
  396.             y = npdoc->cyHorzSplitPos + (cyHorzSplitbar / 2);
  397.         } else if (npdoc->fs & DF_HSPLITOVERFLOW) {
  398.             y = 0;
  399.             /*
  400.              * Clear the overflow flag since the
  401.              * user can't track to an overflown
  402.              * position.
  403.              */
  404.             npdoc->fs &= ~DF_HSPLITOVERFLOW;
  405.         } else {
  406.             y = (SHORT)rclClient.yTop - (cyHorzSplitbar / 2);
  407.         }
  408.     }
  409.  
  410.     if (fsTrack & SPS_VERT) {
  411.         if (npdoc->fs & DF_SPLITVERT) {
  412.             x = npdoc->cxVertSplitPos + (cxVertSplitbar / 2);
  413.         } else if (npdoc->fs & DF_VSPLITOVERFLOW) {
  414.             x = (SHORT)rclClient.xRight - cxVertSplitbar;
  415.             /*
  416.              * Clear the overflow flag since the
  417.              * user can't track to an overflown
  418.              * position.
  419.              */
  420.             npdoc->fs &= ~DF_VSPLITOVERFLOW;
  421.         } else {
  422.             x = (cxVertSplitbar / 2);
  423.         }
  424.     }
  425.  
  426.     /*
  427.      * If xMouse is -1, then we want to set the pointer
  428.      * position to the position of the splitbars.
  429.      */
  430.     if (xMouse == -1) {
  431.         xMouse = x;
  432.         yMouse = y;
  433.         ptlPointer.x = x;
  434.         ptlPointer.y = y;
  435.         WinMapWindowPoints(hwndOrigin, HWND_DESKTOP, (PPOINTL)&ptlPointer, 1);
  436.         WinSetPointerPos(HWND_DESKTOP, (SHORT)ptlPointer.x, (SHORT)ptlPointer.y);
  437.     }
  438.  
  439.     DrawTrackRects(hps, &rclClient, x, y, fsTrack);
  440.  
  441.     while (WinGetMsg(NULL, (PQMSG)&qmsg, NULL, NULL, NULL)) {
  442.         switch (qmsg.msg) {
  443.  
  444.         case WM_BUTTON1UP:
  445.             DrawTrackRects(hps, &rclClient, x, y, fsTrack);
  446.             WinLockWindowUpdate(HWND_DESKTOP, NULL);
  447.             SetSplitbarPos(hwndClient, &rclClient, x, y, fsTrack);
  448.             goto exit_no_unlock;
  449.  
  450.         case WM_CHAR:
  451.             if ((((USHORT) (ULONG) qmsg.mp1 &
  452.                     (KC_KEYUP | KC_DEADKEY | KC_COMPOSITE | KC_INVALIDCOMP))
  453.                     == 0) && ((USHORT) (ULONG) qmsg.mp1 & KC_VIRTUALKEY)) {
  454.  
  455.                 WinQueryPointerPos(HWND_DESKTOP, (PPOINTL)&ptlPointer);
  456.                 switch (SHORT2FROMMP(qmsg.mp2)) {
  457.  
  458.                 case VK_UP:
  459.                     ptlPointer.y += (cyHorzSplitbar * 2);
  460.                     break;
  461.  
  462.                 case VK_DOWN:
  463.                     ptlPointer.y -= (cyHorzSplitbar * 2);
  464.                     break;
  465.  
  466.                 case VK_RIGHT:
  467.                     ptlPointer.x += (cxVertSplitbar * 2);
  468.                     break;
  469.  
  470.                 case VK_LEFT:
  471.                     ptlPointer.x -= (cxVertSplitbar * 2);
  472.                     break;
  473.  
  474.                 case VK_ENTER:
  475.                 case VK_NEWLINE:
  476.                     DrawTrackRects(hps, &rclClient, x, y, SPS_HORZ | SPS_VERT);
  477.                     WinLockWindowUpdate(HWND_DESKTOP, NULL);
  478.                     SetSplitbarPos(hwndClient, &rclClient, x, y,
  479.                             SPS_HORZ | SPS_VERT);
  480.                     goto exit_no_unlock;
  481.  
  482.                 case VK_ESC:
  483.                     DrawTrackRects(hps, &rclClient, x, y, SPS_HORZ | SPS_VERT);
  484.                     goto exit;
  485.                 }
  486.                 if ((SHORT)ptlPointer.x < (SHORT)rclClientScreen.xLeft)
  487.                     ptlPointer.x = rclClientScreen.xLeft;
  488.                 else if ((SHORT)ptlPointer.x > (SHORT)rclClientScreen.xRight)
  489.                     ptlPointer.x = rclClientScreen.xRight;
  490.  
  491.                 if ((SHORT)ptlPointer.y < (SHORT)rclClientScreen.yBottom)
  492.                     ptlPointer.y = rclClientScreen.yBottom;
  493.                 else if ((SHORT)ptlPointer.y > (SHORT)rclClientScreen.yTop)
  494.                     ptlPointer.y = rclClientScreen.yTop;
  495.  
  496.                 WinSetPointerPos(HWND_DESKTOP, (SHORT)ptlPointer.x,
  497.                         (SHORT)ptlPointer.y);
  498.             }
  499.             break;
  500.  
  501.         case WM_MOUSEMOVE:
  502.             xNew = x + (SHORT1FROMMP(qmsg.mp1) - xMouse);
  503.             xMouse = SHORT1FROMMP(qmsg.mp1);
  504.             yNew = y + (SHORT2FROMMP(qmsg.mp1) - yMouse);
  505.             yMouse = SHORT2FROMMP(qmsg.mp1);
  506.  
  507.             MoveTrackRects(hps, &rclClient, fsTrack, x, y, xNew, yNew);
  508.             x = xNew;
  509.             y = yNew;
  510.             break;
  511.  
  512.         default:
  513.             WinDispatchMsg(NULL, (PQMSG)&qmsg);
  514.             break;
  515.         }
  516.     }
  517.  
  518. exit:
  519.     WinLockWindowUpdate(HWND_DESKTOP, NULL);
  520. exit_no_unlock:
  521.     WinReleasePS(hps);
  522.     WinSetCapture(HWND_DESKTOP, NULL);
  523. }
  524.  
  525.  
  526. VOID SetSplitbarPos(HWND hwndClient, PRECTL prclClient, SHORT x, SHORT y,
  527.         USHORT fsTrack)
  528. {
  529.     register NPDOC npdoc;
  530.     register NPVIEW npview1, npview2, npview3, npview4;
  531.     HWND hwndFrame;
  532.     RECTL rclTrack;
  533.  
  534.     npview1 = (NPVIEW)WinQueryWindowUShort(hwndClient, QWS_USER);
  535.     npdoc = npview1->npdoc;
  536.     hwndFrame = WinQueryWindow(hwndClient, QW_PARENT, FALSE);
  537.  
  538.     if (npdoc->fsStyle & DS_VERTSPLITBAR) {
  539.         npview2 = (NPVIEW)WinQueryWindowUShort(
  540.                 WinWindowFromID(hwndFrame, ID_CLIENT2), QWS_USER);
  541.     }
  542.  
  543.     if (npdoc->fsStyle & DS_HORZSPLITBAR) {
  544.         npview3 = (NPVIEW)WinQueryWindowUShort(
  545.                 WinWindowFromID(hwndFrame, ID_CLIENT3), QWS_USER);
  546.     }
  547.  
  548.     if (npdoc->fsStyle & (DS_HORZSPLITBAR | DS_VERTSPLITBAR)) {
  549.         npview4 = (NPVIEW)WinQueryWindowUShort(
  550.                 WinWindowFromID(hwndFrame, ID_CLIENT4), QWS_USER);
  551.     }
  552.  
  553.     if (fsTrack & SPS_VERT) {
  554.         CalcTrackRect(prclClient, &rclTrack, x, SPS_VERT);
  555.         npdoc->cxVertSplitPos = (SHORT) rclTrack.xLeft;
  556.         if ((npdoc->cxVertSplitPos < (SHORT) cxVertSplitbar) ||
  557.                 (npdoc->cxVertSplitPos >
  558.                 ((SHORT)prclClient->xRight - (cxVertSplitbar * 2)))) {
  559.             npdoc->fs &= ~DF_SPLITVERT;
  560.         } else {
  561.             npdoc->fs |= DF_SPLITVERT;
  562.  
  563.             /*
  564.              * Setup ID_CLIENT2 with the same yOrigin
  565.              * as FID_CLIENT.
  566.              */
  567.             npview2->yOrigin = npview1->yOrigin;
  568.  
  569.             /*
  570.              * If we were horizontally split already, then
  571.              * set ID_CLIENT4 to the same yOrigin
  572.              * as ID_CLIENT3.
  573.              */
  574.             if (npdoc->fs & DF_SPLITHORZ)
  575.                 npview4->yOrigin = npview3->yOrigin;
  576.         }
  577.     }
  578.  
  579.     if (fsTrack & SPS_HORZ) {
  580.         CalcTrackRect(prclClient, &rclTrack, y, SPS_HORZ);
  581.         npdoc->cyHorzSplitPos = (SHORT)rclTrack.yBottom;
  582.         if ((npdoc->cyHorzSplitPos >
  583.                 ((SHORT)prclClient->yTop - (cyHorzSplitbar * 2))) ||
  584.                 (npdoc->cyHorzSplitPos < (SHORT) cyHorzSplitbar)) {
  585.             npdoc->fs &= ~DF_SPLITHORZ;
  586.         } else {
  587.             npdoc->fs |= DF_SPLITHORZ;
  588.  
  589.             /*
  590.              * Setup ID_CLIENT3 with the same xOrigin
  591.              * as FID_CLIENT.
  592.              */
  593.             npview3->xOrigin = npview1->xOrigin;
  594.  
  595.             /*
  596.              * If we were vertically split already, then
  597.              * set ID_CLIENT4 to the same xOrigin
  598.              * as ID_CLIENT2.
  599.              */
  600.             if (npdoc->fs & DF_SPLITHORZ)
  601.                 npview4->xOrigin = npview2->xOrigin;
  602.         }
  603.     }
  604.  
  605.     WinSendMsg(hwndFrame, WM_UPDATEFRAME, 0L, 0L);
  606. }
  607.  
  608.  
  609. VOID CalcTrackRect(PRECTL prclClient, PRECTL prcl, SHORT coord, USHORT fsTrack)
  610. {
  611.     if (fsTrack & SPS_VERT) {
  612.         WinSetRect(NULL, prcl, coord - (cxVertSplitbar / 2), 0,
  613.                 coord + (cxVertSplitbar - (cxVertSplitbar / 2)),
  614.                 (SHORT)prclClient->yTop);
  615.  
  616.         if ((SHORT)prcl->xLeft < 0)
  617.             WinOffsetRect(NULL, prcl, (SHORT)-(prcl->xLeft), 0);
  618.         else if ((SHORT)prcl->xRight > (SHORT)prclClient->xRight)
  619.             WinOffsetRect(NULL, prcl,
  620.                     -((SHORT)prcl->xRight - (SHORT)prclClient->xRight), 0);
  621.     } else if (fsTrack & SPS_HORZ) {
  622.         WinSetRect(NULL, prcl, 0, coord - (cyHorzSplitbar / 2),
  623.                 (SHORT)prclClient->xRight,
  624.                 coord + (cyHorzSplitbar - (cyHorzSplitbar / 2)));
  625.  
  626.         if ((SHORT)prcl->yBottom < 0)
  627.             WinOffsetRect(NULL, prcl, 0, (SHORT)-(prcl->yBottom));
  628.         else if ((SHORT)prcl->yTop > (SHORT)prclClient->yTop)
  629.             WinOffsetRect(NULL, prcl,
  630.                     0, -((SHORT)prcl->yTop - (SHORT)prclClient->yTop));
  631.     }
  632. }
  633.  
  634.  
  635. VOID DrawTrackRects(HPS hps, PRECTL prclClient, SHORT x, SHORT y,
  636.         USHORT fsTrack)
  637. {
  638.     RECTL rclFill;
  639.  
  640.     VOID CalcTrackRect(PRECTL, PRECTL, SHORT, USHORT);
  641.  
  642.     if (fsTrack & SPS_VERT) {
  643.         CalcTrackRect(prclClient, (PRECTL)&rclFill, x, SPS_VERT);
  644.  
  645.         InvertRect(hps, (PRECTL)&rclFill);
  646.     }
  647.  
  648.     if (fsTrack & SPS_HORZ) {
  649.         CalcTrackRect(prclClient, (PRECTL)&rclFill, y, SPS_HORZ);
  650.  
  651.         InvertRect(hps, (PRECTL)&rclFill);
  652.     }
  653. }
  654.  
  655.  
  656. VOID MoveTrackRects(HPS hps, PRECTL prclClient, USHORT fsTrack, SHORT xOld,
  657.         SHORT yOld, SHORT xNew, SHORT yNew)
  658. {
  659.     RECTL rclOld, rclNew, rclScratch;
  660.     VOID CalcTrackRect(PRECTL, PRECTL, SHORT, USHORT);
  661.  
  662.     if (fsTrack & SPS_VERT) {
  663.         CalcTrackRect(prclClient, (PRECTL)&rclOld, xOld, SPS_VERT);
  664.         CalcTrackRect(prclClient, (PRECTL)&rclNew, xNew, SPS_VERT);
  665.  
  666.         if (WinSubtractRect(NULL, &rclScratch, &rclOld, &rclNew))
  667.             InvertRect(hps, (PRECTL)&rclScratch);
  668.         if (WinSubtractRect(NULL, &rclScratch, &rclNew, &rclOld))
  669.             InvertRect(hps, (PRECTL)&rclScratch);
  670.     }
  671.  
  672.     if (fsTrack & SPS_HORZ) {
  673.         CalcTrackRect(prclClient, (PRECTL)&rclOld, yOld, SPS_HORZ);
  674.         CalcTrackRect(prclClient, (PRECTL)&rclNew, yNew, SPS_HORZ);
  675.  
  676.         if (WinSubtractRect(NULL, &rclScratch, &rclOld, &rclNew))
  677.             InvertRect(hps, (PRECTL)&rclScratch);
  678.         if (WinSubtractRect(NULL, &rclScratch, &rclNew, &rclOld))
  679.             InvertRect(hps, (PRECTL)&rclScratch);
  680.     }
  681. }
  682.  
  683.  
  684. VOID InvertRect(HPS hps, PRECTL prcl)
  685. {
  686.     RECTL rclParm[2];
  687.  
  688.     WinCopyRect(NULL, (PRECTL)&rclParm[0], (PRECTL)prcl);
  689.     rclParm[1].xLeft = 0;
  690.     rclParm[1].yBottom = 0;
  691.     GpiBitBlt(hps, (HPS)NULL, 3L, (PPOINTL)rclParm, ROP_PATINVERT, 0L);
  692. }
  693.  
  694.  
  695. VOID FindSwp(PSWP aswp, register USHORT cswp, USHORT id, PSWP FAR *ppswp)
  696. {
  697.     register i;
  698.  
  699.     for (i = 0; i < (SHORT) cswp; i++) {
  700.         if (WinQueryWindowUShort(aswp[i].hwnd, QWS_ID) == id) {
  701.             *ppswp = &aswp[i];
  702.             return;
  703.         }
  704.     }
  705. }
  706.  
  707.  
  708. /*
  709.  * Set the SWP structure to the passed in parameters.
  710.  *
  711.  * This routine is dependent on the order of elements
  712.  * in the SWP structure.
  713.  */
  714. VOID SetSwpPos(PSWP pswp, HWND hwnd, HWND hwndInsertBehind, SHORT x, SHORT y,
  715.         SHORT cx, SHORT cy, USHORT fs)
  716. {
  717.     /*
  718.     *pswp = *((PSWP)&fs);
  719.     */
  720.     pswp->hwnd            =    hwnd;
  721.     pswp->hwndInsertBehind    =    hwndInsertBehind;
  722.     pswp->x            =    x;
  723.     pswp->y            =    y;
  724.     pswp->cx            =    cx;
  725.     pswp->cy            =    cy;
  726.     pswp->fs            =    fs;
  727. }
  728.  
  729.  
  730. VOID HideSwp(PSWP pswp, HWND hwnd, USHORT *piswp)
  731. {
  732.     if (WinIsWindowVisible(hwnd)) {
  733.         SetSwpPos(pswp, hwnd, NULL, 0, 0, 0, 0, SWP_HIDE);
  734.         (*piswp)++;
  735.     }
  736. }
  737.