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