home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / edpline / edpline.c next >
Encoding:
C/C++ Source or Header  |  1990-07-05  |  20.4 KB  |  983 lines

  1. /*
  2.     edpline.c -- polyline editor, for practice in mouse handling
  3.     Created by Microsoft Corporation, 1989
  4. */
  5. #define INCL_DOSMEMMGR
  6. #define INCL_WINWINDOWMGR
  7. #define INCL_WINMESSAGEMGR
  8. #define INCL_WINSWITCHLIST
  9. #define INCL_WINDIALOGS
  10. #define INCL_GPIBITMAPS
  11. #define INCL_GPIPRIMITIVES
  12. #define INCL_WINMENUS
  13. #define    INCL_WININPUT
  14. #define    INCL_WINFRAMEMGR
  15. #include <os2.h>
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19.  
  20. #include "edpline.h"
  21.  
  22.  
  23.  
  24. #define    abs(x)            (((x) > 0) ? (x) : -(x))
  25. #define PRIM_POLYLINE        0x0001
  26. #define PRIM_POLYFILLET     0x0002
  27. #define PRIM_POLYSPLINE     0x0004
  28. #define PRIM_POINTARC        0x0008
  29.  
  30.  
  31. /************************************************************************
  32. *
  33. *   Function declarations
  34. *
  35. ************************************************************************/
  36.  
  37. /* Private functions */
  38.  
  39. VOID   cdecl main(VOID);
  40. BOOL   InitGlobals(VOID);
  41. BOOL   InitApp(VOID);
  42. VOID   Close(HWND);
  43. VOID   Command(HWND, USHORT);
  44. VOID   Paint(HPS, BOOL);
  45. VOID   MouseMove(HWND, MPARAM);
  46. VOID   ButtonUp(HWND, USHORT);
  47. VOID   ButtonDown(HWND, USHORT, MPARAM);
  48. USHORT IsPtInList(PPOINTL);
  49. USHORT AddPtToList(PPOINTL);
  50. BOOL   IsPtCloseToLine(PPOINTL, PPOINTL, PPOINTL);
  51. VOID   DrawPrimitive(HPS, USHORT);
  52. VOID   DrawPolyLine(HPS);
  53. VOID   DrawPolyFillet(HPS);
  54. VOID   DrawPolySpline(HPS);
  55. VOID   DrawPointArc(HPS);
  56. VOID   DrawControlPoints(HPS, LONG, PPOINTL);
  57. VOID   MyMessageBox(HWND, PSZ);
  58. VOID   SwapLong(PLONG, PLONG);
  59.  
  60. /* Exported functions */
  61.  
  62. ULONG    EXPENTRY WndProc(HWND, USHORT, MPARAM, MPARAM);
  63. MRESULT EXPENTRY AboutDlgProc(HWND, USHORT, MPARAM, MPARAM);
  64.  
  65.  
  66.  
  67. /************************************************************************
  68. *
  69. *   Global Variables
  70. *
  71. ************************************************************************/
  72.  
  73. typedef struct
  74. {
  75.     HAB  hab;
  76.     HMQ  hMsgQ;
  77.     HWND hwndFrame;
  78.     HWND hwnd;
  79.  
  80.     ULONG   flPrim;
  81.     BOOL    fDisplayControlPoints;
  82.     LONG    cptl;
  83.     PPOINTL pptl;
  84.  
  85.     USHORT  usPtGrabbed;
  86.     BOOL    fDragging;
  87.  
  88.     ULONG   ulHitPrecision;
  89.  
  90. } GLOBALDATA;
  91. GLOBALDATA global;
  92.  
  93.  
  94.  
  95.  
  96. /************************************************************************
  97. *
  98. *   main
  99. *
  100. *   WinInitialize resizes our ring 2 stack, among other things, so
  101. *   we won't GP fault trying to do graphics.  WinCreateMsgQueue defines
  102. *   us as a REAL PM app. (as well as the WINDOWAPI statement in the .DEF
  103. *   file...)   Call a sub to register our window class and create a window.
  104. *   Loop over messages.  Exit cleanly.
  105. *
  106. ************************************************************************/
  107.  
  108. VOID cdecl
  109. main()
  110. {
  111.     QMSG qMsg;
  112.     int iRet = 0;
  113.  
  114.  
  115.     global.hab     = WinInitialize(0);
  116.     global.hMsgQ = WinCreateMsgQueue(global.hab, 0);
  117.  
  118.     if (InitApp())
  119.     while (WinGetMsg( global.hab, (PQMSG)&qMsg, (HWND)NULL, 0, 0 ))
  120.         WinDispatchMsg( global.hab, (PQMSG)&qMsg );
  121.     else
  122.     iRet = -1;
  123.  
  124.     WinDestroyWindow( global.hwndFrame );
  125.     WinDestroyMsgQueue( global.hMsgQ );
  126.     WinTerminate( global.hab );
  127.     DosExit(EXIT_PROCESS, iRet);
  128. }
  129.  
  130.  
  131.  
  132.  
  133. /****************************************************************************
  134. *
  135. *   InitGlobals
  136. *
  137. *   Initialize global variables.
  138. *
  139. ****************************************************************************/
  140.  
  141. BOOL
  142. InitGlobals()
  143. {
  144.     global.flPrim = PRIM_POLYLINE;
  145.     global.fDisplayControlPoints = TRUE;
  146.  
  147.     global.cptl = 0L;
  148.     global.pptl = NULL;
  149.     if (DosAllocSeg(CPTLMAX * sizeof(POINTL),
  150.            ((PUSHORT)&global.pptl)+1, 0))
  151.     return FALSE;
  152.  
  153.     global.usPtGrabbed = -1;
  154.     global.fDragging = FALSE;
  155.     global.ulHitPrecision = 0L;
  156.  
  157.     return TRUE;
  158. }
  159.  
  160.  
  161.  
  162.  
  163. /****************************************************************************
  164. *
  165. *   InitApp
  166. *
  167. *   Register application window class and creates standard window.
  168. *
  169. ****************************************************************************/
  170.  
  171. #define INIT_MENU_ITEM(val, var)     \
  172.     TOGGLE_MENU_ITEM(global.hwndFrame, (val), (var))
  173.  
  174. BOOL
  175. InitApp()
  176. {
  177.     char szTitle[24];
  178.     ULONG ctldata;
  179.     PID pid;
  180.     TID tid;
  181.     HSWITCH hsw;
  182.     static SWCNTRL swctl = { 0, 0, 0, 0, 0, SWL_VISIBLE,
  183.                  SWL_JUMPABLE, "Edit Polyline", 0 };
  184.  
  185.     if (!InitGlobals())
  186.     return FALSE;
  187.  
  188.  
  189.     /*  Register Application Window Class  */
  190.  
  191.     WinLoadString( global.hab, (HMODULE) NULL, IDS_TITLE, sizeof(szTitle), (PCH)szTitle );
  192.     if ( !WinRegisterClass( global.hab, (PCH)szTitle, (PFNWP)WndProc,
  193.         CS_SIZEREDRAW, 0 ))
  194.     return FALSE;
  195.  
  196.  
  197.  
  198.     /* Create a window instance of class "PolyLine Editor" */
  199.  
  200.     ctldata = FCF_STANDARD &
  201.      ~(ULONG)(FCF_ICON | FCF_ACCELTABLE | FCF_TASKLIST);
  202.  
  203.     if (global.hwndFrame = WinCreateStdWindow(
  204.     HWND_DESKTOP,           /* specify desktop as parent window        */
  205.     WS_VISIBLE,           /* window styles                */
  206.     &ctldata,           /* frame creation flags            */
  207.     (PCH)szTitle,           /* window class name             */
  208.     (PCH)szTitle,           /* name appearing in window caption        */
  209.     0L,               /*                        */
  210.     (HMODULE)NULL,           /* use current executable module id        */
  211.     IDR_EDPLINE,           /* menu id                    */
  212.     (HWND FAR *)&global.hwnd   /* window handle                */
  213.     ))
  214.     {
  215.     INIT_MENU_ITEM(IDM_CTLPOINTS, global.fDisplayControlPoints);
  216.  
  217.     if (global.flPrim & PRIM_POLYLINE)
  218.         CHECK_MENU_ITEM(global.hwndFrame, IDM_POLYLINE);
  219.     if (global.flPrim & PRIM_POLYFILLET)
  220.         CHECK_MENU_ITEM(global.hwndFrame, IDM_POLYFILLET);
  221.     if (global.flPrim & PRIM_POLYSPLINE)
  222.         CHECK_MENU_ITEM(global.hwndFrame, IDM_POLYSPLINE);
  223.     if (global.flPrim & PRIM_POINTARC)
  224.         CHECK_MENU_ITEM(global.hwndFrame, IDM_POINTARC);
  225.  
  226.  
  227.     /* Add ourselves to the switch list. */
  228.  
  229.     WinQueryWindowProcess(global.hwndFrame, &pid, &tid);
  230.     swctl.hwnd    = global.hwndFrame;
  231.     swctl.idProcess = pid;
  232.     hsw = WinAddSwitchEntry(&swctl);
  233.  
  234.     return TRUE;
  235.     }
  236.     return FALSE;
  237. }
  238.  
  239.  
  240.  
  241.  
  242. /************************************************************************
  243. *
  244. *   WndProc
  245. *
  246. *   Process messages for the window class.
  247. *
  248. ************************************************************************/
  249.  
  250. ULONG EXPENTRY
  251. WndProc( hwnd, usMsg, mp1, mp2 )
  252. HWND   hwnd;
  253. USHORT usMsg;
  254. MPARAM  mp1;
  255. MPARAM  mp2;
  256. {
  257.     HPS   hps;
  258.  
  259.  
  260.     switch (usMsg)
  261.     {
  262.     case WM_CLOSE:
  263.     Close(hwnd);
  264.     break;
  265.  
  266.     case WM_COMMAND:
  267.     Command(hwnd, LOUSHORT(mp1));
  268.     break;
  269.  
  270.     case WM_PAINT:
  271.     hps = WinBeginPaint(global.hwnd, NULL, NULL);
  272.     if (global.ulHitPrecision == 0L)
  273.     {
  274.         HDC hdc;
  275.         LONG cx;
  276.  
  277.         if (hdc = WinQueryWindowDC(global.hwnd)) {
  278.         DevQueryCaps(hdc, CAPS_MARKER_WIDTH,  1L,  &cx);
  279.         global.ulHitPrecision = (cx >> 17) + 1L;
  280.         } else {
  281.         global.ulHitPrecision = 6L;
  282.         }
  283.     }
  284.     Paint(hps, TRUE);
  285.     WinEndPaint(hps);
  286.     break;
  287.  
  288.     case WM_BUTTON1DOWN:
  289.     case WM_BUTTON2DOWN:
  290.     ButtonDown(hwnd, usMsg, mp1);
  291.     break;
  292.  
  293.     case WM_BUTTON1UP:
  294.     case WM_BUTTON2UP:
  295.     ButtonUp(hwnd, usMsg);
  296.     break;
  297.  
  298.     case WM_MOUSEMOVE:
  299.     MouseMove(hwnd, mp1);
  300.     return( (ULONG)WinDefWindowProc(hwnd, usMsg, mp1, mp2));
  301.     break;
  302.  
  303.     default:
  304.     return( (ULONG)WinDefWindowProc(hwnd, usMsg, mp1, mp2));
  305.     break;
  306.     }
  307.  
  308.     return FALSE;
  309. }
  310.  
  311.  
  312.  
  313.  
  314. /************************************************************************
  315. *
  316. *   MouseMove
  317. *
  318. ************************************************************************/
  319.  
  320. VOID
  321. MouseMove(hwnd, mp1)
  322. HWND hwnd;
  323. MPARAM mp1;
  324. {
  325.     POINTL ptl;
  326.     HPS hps;
  327.  
  328.     if (hwnd == global.hwnd)
  329.     if (global.fDragging)
  330.     {
  331.         ptl.x = (LONG) LOUSHORT(mp1);
  332.         ptl.y = (LONG) HIUSHORT(mp1);
  333.  
  334.         if (global.usPtGrabbed != -1)
  335.         {
  336.         hps = WinGetPS(hwnd);
  337.         Paint(hps, FALSE);
  338.  
  339.         *(global.pptl+global.usPtGrabbed) = ptl;
  340.  
  341.         Paint(hps, FALSE);
  342.         WinReleasePS(hps);
  343.         }
  344.     }
  345. }
  346.  
  347.  
  348.  
  349.  
  350. /************************************************************************
  351. *
  352. *   ButtonUp
  353. *
  354. ************************************************************************/
  355.  
  356. VOID
  357. ButtonUp(hwnd, usMsg)
  358. HWND hwnd;
  359. USHORT usMsg;
  360. {
  361.     int i;
  362.     HPS hps;
  363.  
  364.  
  365.     if (hwnd == global.hwnd)
  366.     if (global.fDragging)
  367.     {
  368.         global.fDragging = FALSE;
  369.         if (global.usPtGrabbed != -1)
  370.         {
  371.         if (usMsg == WM_BUTTON2UP)
  372.         {
  373.             hps = WinGetPS(hwnd);
  374.             Paint(hps, FALSE);
  375.  
  376.             if ((i = global.usPtGrabbed) < (int) global.cptl-1)
  377.             while (i < (int) global.cptl-1)
  378.             {
  379.                 global.pptl[i] = global.pptl[i+1];
  380.                 ++i;
  381.             }
  382.  
  383.             --global.cptl;
  384.             global.usPtGrabbed = -1;
  385.  
  386.             Paint(hps, FALSE);
  387.             WinReleasePS(hps);
  388.         }
  389.         else    /* WM_BUTTON1UP */
  390.             global.usPtGrabbed = -1;
  391.         }
  392.     }
  393. }
  394.  
  395.  
  396.  
  397.  
  398. /************************************************************************
  399. *
  400. *   ButtonDown
  401. *
  402. ************************************************************************/
  403.  
  404. VOID
  405. ButtonDown(hwnd, usMsg, mp1)
  406. HWND hwnd;
  407. USHORT usMsg;
  408. MPARAM mp1;
  409. {
  410.     POINTL ptl;
  411.     HPS hps;
  412.     USHORT usNewPtGrabbed;
  413.  
  414.  
  415.     if (hwnd == global.hwnd)
  416.     if (!global.fDragging)
  417.     {
  418.         global.fDragging = TRUE;
  419.  
  420.         ptl.x = (LONG) LOUSHORT(mp1);
  421.         ptl.y = (LONG) HIUSHORT(mp1);
  422.  
  423.         if ((usNewPtGrabbed = IsPtInList(&ptl)) != -1)
  424.         global.usPtGrabbed = usNewPtGrabbed;
  425.  
  426.         if (usMsg == WM_BUTTON1DOWN)
  427.         {
  428.         hps = WinGetPS(hwnd);
  429.         Paint(hps, FALSE);
  430.  
  431.         if (usNewPtGrabbed == -1)
  432.             global.usPtGrabbed = AddPtToList(&ptl);
  433.         else
  434.             global.usPtGrabbed = usNewPtGrabbed;
  435.  
  436.         Paint(hps, FALSE);
  437.         WinReleasePS(hps);
  438.  
  439.         if (global.usPtGrabbed == -1)
  440.             MyMessageBox(global.hwnd, "Cannot add any more points.");
  441.         }
  442.     }
  443. }
  444.  
  445.  
  446.  
  447.  
  448. /************************************************************************
  449. *
  450. *   IsPtInList
  451. *
  452. ************************************************************************/
  453.  
  454. USHORT
  455. IsPtInList(pptl)
  456. PPOINTL pptl;
  457. {
  458.     int i;
  459.  
  460.  
  461.     /* try to find pptl in the points we already have */
  462.     for (i = 0; i < (int) global.cptl; ++i)
  463.     if (((abs(pptl->x - global.pptl[i].x))
  464.         <= (LONG) global.ulHitPrecision)
  465.      && ((abs(pptl->y - global.pptl[i].y))
  466.         <= (LONG) global.ulHitPrecision))
  467.         return i;
  468.  
  469.     /* couldn't find it */
  470.     return -1;
  471. }
  472.  
  473.  
  474.  
  475.  
  476. /************************************************************************
  477. *
  478. *   AddPtToList
  479. *
  480. ************************************************************************/
  481.  
  482. USHORT
  483. AddPtToList(pptl)
  484. PPOINTL pptl;
  485. {
  486.     int i, j;
  487.  
  488.     if (global.cptl < CPTLMAX)
  489.     {
  490.     /* check for new points lying on a line segment */
  491.     for (i = 0; i < (int) (global.cptl - 1L); ++i)
  492.         if (IsPtCloseToLine(&global.pptl[i], &global.pptl[i+1], pptl))
  493.         {
  494.         for (j = (int) global.cptl; j > i+1; --j)
  495.             global.pptl[j] = global.pptl[j - 1];
  496.         global.pptl[i+1] = *pptl;
  497.         ++global.cptl;
  498.         return i+1;
  499.         }
  500.  
  501.     /* append the point */
  502.  
  503.     i = (int) global.cptl;
  504.     global.pptl[i] = *pptl;
  505.     ++global.cptl;
  506.     return i;
  507.     }
  508.  
  509.     return -1;
  510. }
  511.  
  512.  
  513.  
  514.  
  515. /************************************************************************
  516. *
  517. *   IsPtCloseToLine
  518. *
  519. ************************************************************************/
  520.  
  521. BOOL
  522. IsPtCloseToLine(pptl1, pptl2, pptlTest)
  523. PPOINTL pptl1;
  524. PPOINTL pptl2;
  525. PPOINTL pptlTest;
  526. {
  527.     POINTL ptlLL, ptlUR;
  528.     LONG dx, dy, yIntercept, result;
  529.  
  530.  
  531.     /* find the bounding box of the line segment */
  532.  
  533.     ptlLL = *pptl1;    /* assume line goes lower left to upper right */
  534.     ptlUR = *pptl2;
  535.     if (pptl1->x > pptl2->x)
  536.     SwapLong(&ptlLL.x, &ptlUR.x);
  537.     if (pptl1->y > pptl2->y)
  538.     SwapLong(&ptlLL.y, &ptlUR.y);
  539.  
  540.  
  541.     /* adjust the bounding box if it's too narrow */
  542.  
  543.     dx = pptl2->x - pptl1->x;
  544.     if (abs(dx) <= (LONG) (global.ulHitPrecision >> 1))
  545.     {
  546.     ptlLL.x -= (LONG) (global.ulHitPrecision >> 1);
  547.     ptlUR.x += (LONG) (global.ulHitPrecision >> 1);
  548.     }
  549.     dy = pptl2->y - pptl1->y;
  550.     if (abs(dy) <= (LONG) (global.ulHitPrecision >> 1))
  551.     {
  552.     ptlLL.y -= (LONG) (global.ulHitPrecision >> 1);
  553.     ptlUR.y += (LONG) (global.ulHitPrecision >> 1);
  554.     }
  555.  
  556.  
  557.     /* see if the test point is in the bounding box of the line segment */
  558.  
  559.     if ((pptlTest->x >= ptlLL.x) &&
  560.     (pptlTest->x <= ptlUR.x) &&
  561.     (pptlTest->y >= ptlLL.y) &&
  562.     (pptlTest->y <= ptlUR.y))
  563.     {
  564.     /* test for special cases */
  565.  
  566.     if (dx == 0)
  567.     {
  568.         if (abs(pptlTest->x - pptl1->x) <= (LONG) global.ulHitPrecision)
  569.         return TRUE;
  570.         else
  571.         return FALSE;
  572.     }
  573.  
  574.     if (dy == 0)
  575.     {
  576.         if (abs(pptlTest->y - pptl1->y) <= (LONG) global.ulHitPrecision)
  577.         return TRUE;
  578.         else
  579.         return FALSE;
  580.     }
  581.  
  582.  
  583.     /* test for general case */
  584.  
  585.     yIntercept = pptl1->y - (pptl1->x * dy) / dx;
  586.  
  587.     result = pptlTest->y - (pptlTest->x * dy / dx) - yIntercept;
  588.     if (abs(result) <= (LONG) global.ulHitPrecision)
  589.         return TRUE;
  590.     }
  591.  
  592.     return FALSE;
  593. }
  594.  
  595.  
  596.  
  597.  
  598. /************************************************************************
  599. *
  600. *   SwapLong
  601. *
  602. ************************************************************************/
  603.  
  604. VOID
  605. SwapLong(pl1, pl2)
  606. PLONG pl1, pl2;
  607. {
  608.     LONG lTmp;
  609.  
  610.     lTmp = *pl1;
  611.     *pl1 = *pl2;
  612.     *pl2 = lTmp;
  613. }
  614.  
  615.  
  616.  
  617.  
  618. /************************************************************************
  619. *
  620. *   Close
  621. *
  622. ************************************************************************/
  623.  
  624. VOID
  625. Close(hwnd)
  626. HWND hwnd;
  627. {
  628.     WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
  629. }
  630.  
  631.  
  632.  
  633.  
  634. /************************************************************************
  635. *
  636. *   Command
  637. *
  638. *   Dispatches menu commands to the proper handlers.
  639. *
  640. ************************************************************************/
  641.  
  642. #define UPDATE_MENU_BOOL(var, val)                \
  643.     {                            \
  644.         TOGGLE_BOOL((var));                 \
  645.         TOGGLE_MENU_ITEM(global.hwndFrame, (val), (var));    \
  646.     }
  647.  
  648. #define UPDATE_MENU_LIST(var, val)                \
  649.     {                            \
  650.         UNCHECK_MENU_ITEM(global.hwndFrame, (var));     \
  651.         (var) = (val);                    \
  652.         CHECK_MENU_ITEM(global.hwndFrame, (var));        \
  653.     }
  654.  
  655. VOID
  656. Command(hwnd, id)
  657. HWND hwnd;
  658. USHORT id;
  659. {
  660.     HPS hps;
  661.     BOOL fRedraw = FALSE;
  662.     int rc;
  663.  
  664.     switch (id)
  665.     {
  666.     case IDM_ABOUT:
  667.     rc = WinDlgBox(HWND_DESKTOP, hwnd, AboutDlgProc, (HMODULE) NULL, IDD_ABOUT, NULL);
  668.     fRedraw = FALSE;
  669.     break;
  670.  
  671.     case IDM_NOPRIM:
  672.     global.flPrim = 0L;
  673.     TOGGLE_MENU_ITEM(global.hwndFrame, IDM_POLYLINE, 0);
  674.     TOGGLE_MENU_ITEM(global.hwndFrame, IDM_POLYFILLET, 0);
  675.     TOGGLE_MENU_ITEM(global.hwndFrame, IDM_POLYSPLINE, 0);
  676.     fRedraw = TRUE;
  677.     break;
  678.  
  679.     case IDM_POLYLINE:
  680.     global.flPrim ^= PRIM_POLYLINE;
  681.     TOGGLE_MENU_ITEM(global.hwndFrame, id, (global.flPrim & PRIM_POLYLINE));
  682.     fRedraw = TRUE;
  683.     break;
  684.  
  685.     case IDM_POLYFILLET:
  686.     global.flPrim ^= PRIM_POLYFILLET;
  687.     TOGGLE_MENU_ITEM(global.hwndFrame, id, (global.flPrim & PRIM_POLYFILLET));
  688.     fRedraw = TRUE;
  689.     break;
  690.  
  691.     case IDM_POLYSPLINE:
  692.     global.flPrim ^= PRIM_POLYSPLINE;
  693.     TOGGLE_MENU_ITEM(global.hwndFrame, id, (global.flPrim & PRIM_POLYSPLINE));
  694.     fRedraw = TRUE;
  695.     break;
  696.  
  697.     case IDM_POINTARC:
  698.     global.flPrim ^= PRIM_POINTARC;
  699.     TOGGLE_MENU_ITEM(global.hwndFrame, id, (global.flPrim & PRIM_POINTARC));
  700.     fRedraw = TRUE;
  701.     break;
  702.  
  703.     case IDM_CTLPOINTS:
  704.     UPDATE_MENU_BOOL(global.fDisplayControlPoints, IDM_CTLPOINTS);
  705.     fRedraw = TRUE;
  706.     break;
  707.  
  708.     case IDM_CLEARALL:
  709.     global.cptl = 0L;
  710.     fRedraw = TRUE;
  711.     break;
  712.     }
  713.  
  714.     if (fRedraw)
  715.     {
  716.     hps = WinGetPS(hwnd);
  717.     Paint(hps, TRUE);
  718.     WinReleasePS(hps);
  719.     }
  720. }
  721.  
  722.  
  723.  
  724.  
  725. /************************************************************************
  726. *
  727. *   Paint
  728. *
  729. ************************************************************************/
  730.  
  731. VOID
  732. Paint(hps, fClearScreen)
  733. HPS  hps;
  734. BOOL fClearScreen;
  735. {
  736.     LINEBUNDLE lb;
  737.     RECTL rcl;
  738.  
  739.  
  740.  
  741.     if (fClearScreen)
  742.     {
  743.     /* clear the screen */
  744.     WinQueryWindowRect(global.hwnd, &rcl);
  745.     GpiBitBlt(hps, NULL, 2L, (PPOINTL) &rcl, ROP_ONE, 0L);
  746.     }
  747.  
  748.  
  749.     if (global.cptl > 0L)
  750.     {
  751.     if (global.fDisplayControlPoints)
  752.     {
  753.         if (fClearScreen)
  754.         /* draw all the control points */
  755.         DrawControlPoints(hps, global.cptl, global.pptl);
  756.         else if (global.usPtGrabbed != -1)
  757.         /* draw just the control point that moved */
  758.         DrawControlPoints(hps, 1L, global.pptl+global.usPtGrabbed);
  759.     }
  760.  
  761.     /* set mix mode to xor */
  762.     lb.usMixMode = FM_XOR;
  763.     GpiSetAttrs(hps, PRIM_LINE, LBB_MIX_MODE, 0L, &lb);
  764.  
  765.     /* draw the current primitives */
  766.  
  767.     if (global.flPrim & PRIM_POLYLINE)
  768.     {
  769.         lb.lColor = CLR_BROWN;
  770.         GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb);
  771.         DrawPrimitive(hps, IDM_POLYLINE);
  772.     }
  773.  
  774.     if (global.flPrim & PRIM_POLYFILLET)
  775.     {
  776.         lb.lColor = CLR_DARKCYAN;
  777.         GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb);
  778.         DrawPrimitive(hps, IDM_POLYFILLET);
  779.     }
  780.  
  781.     if (global.flPrim & PRIM_POLYSPLINE)
  782.     {
  783.         lb.lColor = CLR_DARKPINK;
  784.         GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb);
  785.         DrawPrimitive(hps, IDM_POLYSPLINE);
  786.     }
  787.  
  788.     if (global.flPrim & PRIM_POINTARC)
  789.     {
  790.         lb.lColor = CLR_BACKGROUND;
  791.         GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb);
  792.         DrawPrimitive(hps, IDM_POINTARC);
  793.     }
  794.     }
  795. }
  796.  
  797.  
  798.  
  799.  
  800. /************************************************************************
  801. *
  802. *   DrawPrimitive
  803. *
  804. ************************************************************************/
  805.  
  806. VOID
  807. DrawPrimitive(hps, usPrim)
  808. HPS hps;
  809. USHORT usPrim;
  810. {
  811.     switch ( usPrim )
  812.     {
  813.     case IDM_POLYLINE:
  814.     DrawPolyLine(hps);
  815.     break;
  816.  
  817.     case IDM_POLYFILLET:
  818.     DrawPolyFillet(hps);
  819.     break;
  820.  
  821.     case IDM_POLYSPLINE:
  822.     DrawPolySpline(hps);
  823.     break;
  824.  
  825.     case IDM_POINTARC:
  826.     DrawPointArc(hps);
  827.     break;
  828.     }
  829. }
  830.  
  831.  
  832.  
  833.  
  834. /************************************************************************
  835. *
  836. *   DrawPolyLine
  837. *
  838. ************************************************************************/
  839.  
  840. VOID
  841. DrawPolyLine(hps)
  842. HPS hps;
  843. {
  844.     GpiSetCurrentPosition( hps, global.pptl );
  845.     GpiPolyLine( hps, global.cptl-1L, global.pptl+1 );
  846. }
  847.  
  848.  
  849.  
  850.  
  851. /************************************************************************
  852. *
  853. *   DrawPolyFillet
  854. *
  855. ************************************************************************/
  856.  
  857. VOID
  858. DrawPolyFillet(hps)
  859. HPS hps;
  860. {
  861.     if (global.cptl > 2)
  862.     {
  863.     GpiSetCurrentPosition( hps, global.pptl );
  864.     GpiPolyFillet( hps, global.cptl-1L, global.pptl+1 );
  865.     }
  866. }
  867.  
  868.  
  869.  
  870.  
  871. /************************************************************************
  872. *
  873. *   DrawPolySpline
  874. *
  875. ************************************************************************/
  876.  
  877. VOID
  878. DrawPolySpline(hps)
  879. HPS hps;
  880. {
  881.     USHORT cptSlack;    /* # points in pptl not usable by PolySpline */
  882.  
  883.     /* GpiPolySpline expects the number of points to be a
  884.        multiple of 3.  If we have a non-multiple of three,
  885.        (excluding the first point, which we've used to set
  886.        the current position), only pass the largest multiple
  887.        of three, saving the rest for the next go-round. */
  888.  
  889.     cptSlack = (int)((global.cptl-1L) % 3) + 1;
  890.     GpiSetCurrentPosition( hps, global.pptl );
  891.     GpiPolySpline( hps, global.cptl-cptSlack,
  892.            global.pptl+1 );
  893. }
  894.  
  895.  
  896.  
  897.  
  898. /************************************************************************
  899. *
  900. *   DrawPointArc
  901. *
  902. ************************************************************************/
  903.  
  904. VOID
  905. DrawPointArc(hps)
  906. HPS hps;
  907. {
  908.     if (global.cptl >= 3L)
  909.     {
  910.     GpiSetCurrentPosition( hps, global.pptl );
  911.     GpiPointArc( hps, global.pptl+1 );
  912.     }
  913. }
  914.  
  915.  
  916.  
  917.  
  918. /************************************************************************
  919. *
  920. *   DrawControlPoints
  921. *
  922. ************************************************************************/
  923.  
  924. VOID
  925. DrawControlPoints(hps, cptl, pptl)
  926. HPS hps;
  927. LONG cptl;
  928. PPOINTL pptl;
  929. {
  930.     MARKERBUNDLE mb;
  931.  
  932.     mb.lColor = CLR_TRUE;
  933.     mb.usMixMode = FM_XOR;
  934.     GpiSetAttrs(hps, PRIM_MARKER, MBB_COLOR | MBB_MIX_MODE, 0L, &mb);
  935.  
  936.     GpiPolyMarker(hps, cptl, pptl);
  937. }
  938.  
  939.  
  940.  
  941.  
  942. /************************************************************************
  943. *
  944. *   MyMessageBox
  945. *
  946. *   Displays a message box with the given string.  To simplify matters,
  947. *   the box will always have the same title ("PolyLine Editor"), will always
  948. *   have a single button ("Ok"), will always have an exclamation point
  949. *   icon, and will always be application modal.
  950. *
  951. ************************************************************************/
  952.  
  953. VOID
  954. MyMessageBox(hWnd, sz)
  955. HWND hWnd;
  956. PSZ sz;
  957. {
  958.     static char *szTitle = "PolyLine Editor";
  959.  
  960.     WinMessageBox(HWND_DESKTOP, hWnd, sz, szTitle, (HMODULE) NULL,
  961.           MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
  962. }
  963.  
  964. MRESULT EXPENTRY AboutDlgProc(hDlg, msg, mp1, mp2)
  965. /*
  966.     About... dialog procedure
  967. */
  968. HWND    hDlg;
  969. USHORT    msg;
  970. MPARAM    mp1;
  971. MPARAM    mp2;
  972. {
  973.     switch(msg) {
  974.     case WM_COMMAND:
  975.         switch(COMMANDMSG(&msg)->cmd) {
  976.         case DID_OK: WinDismissDlg(hDlg, TRUE); break;
  977.         default: break;
  978.         }
  979.     default: return WinDefDlgProc(hDlg, msg, mp1, mp2);
  980.     }
  981.     return FALSE;
  982. }
  983.