|
|
1.1 root 1: /************************************************************************
2: *
3: * lfcmd.c -- Subroutines for menu command processing for LineFractal.
4: *
5: * Created by Microsoft Corporation, 1989
6: *
7: ************************************************************************/
8:
9: #define INCL_WIN
10: #define INCL_GPI
11: #define INCL_BITMAPFILEFORMAT
12: #define INCL_DOSSEMAPHORES
13: #define INCL_DOSMEMMGR
14: #define INCL_DOSPROCESS
15: #include <os2.h>
16:
17: #include <mt\stdio.h>
18: #include <mt\stdlib.h>
19: #include <mt\math.h>
20:
21: #include "opendlg.h"
22:
23: #define INCL_GLOBALS
24: #define INCL_THREADS
25: #include "linefrac.h"
26:
27: #define INCL_LFCMD
28: #define INCL_LFDLG
29: #define INCL_LFMAIN
30: #define INCL_LFTHREAD
31: #define INCL_LFPS
32: #define INCL_LFDRAW
33: #define INCL_LFUTIL
34: #define INCL_LFFILE
35: #include "lffuncs.h"
36:
37:
38:
39:
40: /************************************************************************
41: *
42: * Macros
43: *
44: * Helper macros for repetitious code.
45: *
46: ************************************************************************/
47:
48: #define UPDATE_MENU_BOOL(var, val) \
49: { \
50: TOGGLE_BOOL((var)); \
51: TOGGLE_MENU_ITEM(global.hwndFrame, (val), (var)); \
52: }
53:
54: #define UPDATE_MENU_LIST(var, val) \
55: { \
56: UNCHECK_MENU_ITEM(global.hwndFrame, (var)); \
57: (var) = (val); \
58: CHECK_MENU_ITEM(global.hwndFrame, (var)); \
59: }
60:
61:
62:
63:
64: /************************************************************************
65: *
66: * Global Variables
67: *
68: * global Global data block.
69: * aulRops Array of BitBlt rops available for pasting.
70: * aXform Array of built-in transforms and default positioning
71: * and sizing information.
72: *
73: ************************************************************************/
74:
75: extern GLOBALDATA global;
76: extern XFORMDATA aXform[];
77:
78: ULONG aulRops[] =
79: {
80: ROP_SRCCOPY,
81: ROP_SRCAND,
82: ROP_SRCPAINT,
83: ROP_SRCINVERT,
84: (~ROP_SRCCOPY) & 0xFF,
85: (~ROP_SRCAND) & 0xFF,
86: (~ROP_SRCPAINT) & 0xFF,
87: (~ROP_SRCINVERT) & 0xFF
88: };
89:
90: char *pszAttrs = "Previous attributes not read yet.";
91:
92:
93:
94:
95: /************************************************************************
96: *
97: * LfCommand
98: *
99: * Dispatches menu commands to the proper handlers.
100: *
101: ************************************************************************/
102:
103: VOID
104: LfCommand(hwnd, id)
105: HWND hwnd;
106: USHORT id;
107: {
108: switch (id)
109: {
110:
111: /********************************************************************
112: *
113: * File menu
114: *
115: ********************************************************************/
116:
117: case IDM_LOAD:
118: case IDM_SAVE:
119: case IDM_ABOUT:
120: LfFileMenu(hwnd, id);
121: break;
122:
123: /********************************************************************
124: *
125: * Edit menu
126: *
127: ********************************************************************/
128:
129: case IDM_SELECT:
130: case IDM_SELECTALL:
131: case IDM_CUT:
132: case IDM_COPY:
133: case IDM_PASTE:
134: case IDM_USECLIPBRD:
135: case IDM_PASTES:
136: case IDM_PASTEDSA:
137: case IDM_PASTEDSO:
138: case IDM_PASTEDSX:
139: case IDM_PASTESN:
140: case IDM_PASTEDSAN:
141: case IDM_PASTEDSON:
142: case IDM_PASTEDSXN:
143: LfEditMenu(hwnd, id);
144: break;
145:
146: /********************************************************************
147: *
148: * Thread menu
149: *
150: ********************************************************************/
151:
152: case IDM_DCPOSTSCRIPT:
153: case IDM_DCPROPRINTER:
154: case IDM_DCDIRECT:
155: case IDM_DCMEMORY:
156: case IDM_EDITTHREADPARAMS:
157: case IDM_THR0TOTOP:
158: case IDM_THR1TOTOP:
159: case IDM_THR2TOTOP:
160: case IDM_THR3TOTOP:
161: case IDM_THR4TOTOP:
162: case IDM_THR5TOTOP:
163: case IDM_THR6TOTOP:
164: case IDM_THR7TOTOP:
165: case IDM_THR8TOTOP:
166: case IDM_THR9TOTOP:
167: case IDM_KILLTOPTHREAD:
168: case IDM_KILLALLTHREADS:
169: case IDM_AUTOSWITCH:
170: case IDM_SWITCHDELAY:
171: case IDM_UPDATEMENUS:
172: case IDM_THREADINHERITANCE:
173: LfThreadMenu(hwnd, id);
174: break;
175:
176: /********************************************************************
177: *
178: * Control menu
179: *
180: ********************************************************************/
181:
182: case IDM_CLEARBITMAP:
183: case IDM_COPYBITMAPTOSCREEN:
184: case IDM_SQUAREBITMAP:
185: case IDM_RESIZEBITMAPTOWINDOW:
186: case IDM_MOUSECHANGESRECURSION:
187: case IDM_ANIMATEPTR:
188: case IDM_PTRPREFERENCES:
189: case IDM_TIMERDELAY:
190: if (LfControlMenu(hwnd, id))
191: goto lfcmd_redraw;
192: break;
193:
194: /********************************************************************
195: *
196: * Fractal menu
197: *
198: ********************************************************************/
199:
200: case IDM_SHARKTOOTH:
201: case IDM_SAWTOOTH:
202: case IDM_KOCH:
203: case IDM_SPACEFILLER:
204: case IDM_STOVE:
205: case IDM_SQUAREWAVE:
206: case IDM_HOURGLASS:
207: case IDM_FRACREDRAW:
208: if (LfFractalMenu(hwnd, id))
209: goto lfcmd_redraw;
210: break;
211:
212: /********************************************************************
213: *
214: * Primitive menu
215: *
216: ********************************************************************/
217:
218: case IDM_POLYLINE:
219: case IDM_POLYFILLET:
220: case IDM_POLYSPLINE:
221: case IDM_POLYMARKER:
222: case IDM_PEANO:
223: case IDM_PRIMREDRAW:
224: if (LfPrimitiveMenu(hwnd, id))
225: goto lfcmd_redraw;
226: break;
227:
228: /********************************************************************
229: *
230: * Attributes menu
231: *
232: ********************************************************************/
233:
234: case IDM_LINEATTRS:
235: case IDM_MARKERATTRS:
236: case IDM_AREAATTRS:
237: case IDM_IMAGEATTRS:
238: case IDM_MISCATTRS:
239: case IDM_DIMENSIONS:
240: case IDM_DRAGDIMS:
241: case IDM_ATTRREDRAW:
242: if (LfAttributesMenu(hwnd, id))
243: goto lfcmd_redraw;
244: break;
245:
246: /********************************************************************
247: *
248: * Environment menu
249: *
250: ********************************************************************/
251:
252: case IDM_AUTORESIZE:
253: case IDM_AUTOSELECTDIMS:
254: case IDM_CLEARONREDRAW:
255: case IDM_AUTOSTARTREDRAW:
256: case IDM_COLLECTBOUNDS:
257: LfEnvironmentMenu(hwnd, id);
258: break;
259:
260: /********************************************************************
261: *
262: * Control menu, continued. These two commands dovetail
263: * conveniently, so they are placed out of sequence here.
264: *
265: ********************************************************************/
266:
267: lfcmd_redraw:
268: case IDM_REDRAW:
269: DosSemClear(&(global.pThrTop)->lSemRedraw);
270:
271: /* Fall through to restart the drawing. */
272:
273: case IDM_ABORT:
274: global.pThrTop->fInterrupted = TRUE;
275: break;
276: }
277: }
278:
279:
280:
281:
282: /************************************************************************
283: *
284: * LfFileMenu
285: *
286: * These commands allow the loading and saving of bitmaps from threads
287: * with memory DC's. The about box shows the version number, title,
288: * and author.
289: *
290: ************************************************************************/
291:
292: VOID
293: LfFileMenu(hwnd, id)
294: HWND hwnd;
295: USHORT id;
296: {
297: switch (id)
298: {
299: case IDM_LOAD:
300: if (global.pThrTop->dcType == IDM_DCMEMORY)
301: LfReadFile(hwnd, global.pThrTop);
302: else
303: MyMessageBox(hwnd, "Cannot load bitmap into a\nnon-memory DC.");
304: break;
305:
306: case IDM_SAVE:
307: if (global.pThrTop->dcType == IDM_DCMEMORY)
308: LfWriteFile(hwnd, global.pThrTop);
309: else
310: MyMessageBox(hwnd, "Cannot save bitmap from a\nnon-memory DC.");
311: break;
312:
313: case IDM_ABOUT:
314: WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)AboutDlg, NULL,
315: IDR_ABOUTDLG, NULL );
316: break;
317: }
318: }
319:
320:
321:
322:
323: /************************************************************************
324: *
325: * LfEditMenu
326: *
327: * These commands allow for cutting, copying, and pasting of rectangles
328: * of bits. The user can drag a rectangle or select the entire surface.
329: * The GpiBitBlt rop to use when pasting can be any of those listed.
330: * The user can specify that the system clipboard be used for storing
331: * the cut or copied bits, or that a private bitmap be used.
332: *
333: ************************************************************************/
334:
335: VOID
336: LfEditMenu(hwnd, id)
337: HWND hwnd;
338: USHORT id;
339: {
340: switch (id)
341: {
342: case IDM_SELECT:
343: global.fSelecting = TRUE;
344: break;
345:
346: case IDM_SELECTALL:
347: LfSelectAll(hwnd);
348: break;
349:
350: case IDM_CUT:
351: if (global.fShowSelectRc)
352: LfCut(hwnd);
353: break;
354:
355: case IDM_COPY:
356: if (global.fShowSelectRc)
357: LfCopy(hwnd);
358: break;
359:
360: case IDM_PASTE:
361: if (global.fHaveSelectRc)
362: {
363: HPS hps;
364:
365: global.fPasting = TRUE;
366: if (global.fShowSelectRc && global.fTempSelect)
367: {
368: hps = WinGetPS(hwnd);
369: LfShowSelectRc(hps, &global.rclSelect);
370: WinReleasePS(hps);
371: global.fShowSelectRc = FALSE;
372: global.fTempSelect = FALSE;
373: }
374: if (!global.fShowSelectRc)
375: {
376: global.fShowSelectRc = TRUE;
377: hps = WinGetPS(hwnd);
378: LfShowSelectRc(hps, &global.rclCutCopy);
379: WinReleasePS(hps);
380: }
381: }
382: break;
383:
384: case IDM_USECLIPBRD:
385: UPDATE_MENU_BOOL(global.fUseClipbrd, IDM_USECLIPBRD);
386: break;
387:
388: /********************************************************************/
389:
390: case IDM_PASTES:
391: case IDM_PASTEDSA:
392: case IDM_PASTEDSO:
393: case IDM_PASTEDSX:
394: case IDM_PASTESN:
395: case IDM_PASTEDSAN:
396: case IDM_PASTEDSON:
397: case IDM_PASTEDSXN:
398: UNCHECK_MENU_ITEM(global.hwndFrame, global.usRopIndex+IDM_PASTES);
399: global.usRopIndex = id - IDM_PASTES;
400: CHECK_MENU_ITEM(global.hwndFrame, global.usRopIndex+IDM_PASTES);
401: global.ulPasteROP = aulRops[global.usRopIndex];
402: break;
403: }
404: }
405:
406:
407:
408:
409: /************************************************************************
410: *
411: * LfThreadMenu
412: *
413: * These commands allow the creation, viewing, editing, and deletion
414: * of up to 10 independently drawing threads. The middle group
415: * allow for simple animation by cycling through the threads at
416: * a user-selectable rate. The updating of menus can be disabled to
417: * allow a faster thread-switch rate. The last group determine how
418: * new threads will look and act. If inheritance is enabled, a new
419: * thread will be drawn with the attributes of the top thread, otherwise
420: * it will use the program's default values.
421: *
422: ************************************************************************/
423:
424: VOID
425: LfThreadMenu(hwnd, id)
426: HWND hwnd;
427: USHORT id;
428: {
429: static char *szError1 = "Could not start thread.";
430:
431: switch (id)
432: {
433: case IDM_DCPOSTSCRIPT:
434: case IDM_DCPROPRINTER:
435: break; /* not implemented yet */
436:
437: case IDM_DCDIRECT:
438: {
439: PTHR pthr;
440:
441: if (global.cThr < MAX_THREADS)
442: if (pthr = LfStartThread(IDM_DCDIRECT))
443: {
444: (global.aThr)[global.cThr] = pthr;
445: ++global.cThr;
446: pthr->dcType = id;
447:
448: LfBringThreadToTop(pthr);
449: break;
450: }
451: MyMessageBox(hwnd, szError1);
452: }
453: break;
454:
455: case IDM_DCMEMORY:
456:
457: if (global.cThr < MAX_THREADS)
458: {
459: if (global.fFirstThread)
460: {
461: global.bm.cx = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
462: global.bm.cy = (USHORT) (global.rcl.yTop - global.rcl.yBottom);
463: global.bm.cPlanes = 0;
464: global.bm.cBitCount = 0;
465: global.fFirstThread = FALSE;
466: }
467: else if (global.fThreadInheritance)
468: {
469: global.bm.cx = (USHORT) global.pThrTop->rcl.xRight;
470: global.bm.cy = (USHORT) global.pThrTop->rcl.yTop;
471: global.bm.cPlanes = global.pThrTop->cPlanes;
472: global.bm.cBitCount = global.pThrTop->cBitCount;
473: }
474: else
475: {
476: global.bm.cx = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
477: global.bm.cy = (USHORT) (global.rcl.yTop - global.rcl.yBottom);
478: global.bm.cPlanes = 0;
479: global.bm.cBitCount = 0;
480: if (!WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)BitmapParamsDlg, NULL,
481: IDR_BITMAPPARAMSDLG, NULL ))
482: break; /* if user hit "cancel", don't start thread */
483: }
484:
485: {
486: PTHR pthr;
487:
488: if (pthr = LfStartThread(IDM_DCMEMORY))
489: {
490: (global.aThr)[global.cThr] = pthr;
491: ++global.cThr;
492: pthr->dcType = id;
493:
494: LfBringThreadToTop(pthr);
495: break;
496: }
497: }
498: }
499: MyMessageBox(hwnd, szError1);
500: break;
501:
502: case IDM_EDITTHREADPARAMS:
503: if (global.pThrTop->dcType == IDM_DCMEMORY)
504: {
505: USHORT cxT, cyT, cpT, cbT;
506:
507: cxT = global.bm.cx = (USHORT) global.pThrTop->rcl.xRight;
508: cyT = global.bm.cy = (USHORT) global.pThrTop->rcl.yTop;
509: cpT = global.bm.cPlanes = global.pThrTop->cPlanes;
510: cbT = global.bm.cBitCount = global.pThrTop->cBitCount;
511:
512: if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)BitmapParamsDlg, NULL,
513: IDR_BITMAPPARAMSDLG, NULL ))
514: if ((cxT != global.bm.cx) ||
515: (cyT != global.bm.cy) ||
516: (cpT != global.bm.cPlanes) ||
517: (cbT != global.bm.cBitCount))
518: LfResizePS(global.pThrTop);
519: }
520: else
521: MyMessageBox(hwnd, "No editable DC parameters.");
522: break;
523:
524: case IDM_THR0TOTOP:
525: case IDM_THR1TOTOP:
526: case IDM_THR2TOTOP:
527: case IDM_THR3TOTOP:
528: case IDM_THR4TOTOP:
529: case IDM_THR5TOTOP:
530: case IDM_THR6TOTOP:
531: case IDM_THR7TOTOP:
532: case IDM_THR8TOTOP:
533: case IDM_THR9TOTOP:
534: {
535: USHORT i;
536:
537: if ((i = id-IDM_THR0TOTOP) < global.cThr)
538: LfBringThreadToTop(global.aThr[i]);
539: }
540: break;
541:
542: case IDM_KILLTOPTHREAD:
543: {
544: PTHR pthr;
545:
546: pthr = global.pThrTop;
547: if (global.cThr > 1)
548: {
549: SHORT i;
550:
551: if ((i = global.iThrTop+1) == global.cThr)
552: i -= 2;
553: LfBringThreadToTop(global.aThr[i]);
554: }
555: else
556: LfBringThreadToTop(NULL);
557:
558: LfKillThread(pthr);
559: LfBringThreadToTop(global.pThrTop); /* update global.iThrTop and menu */
560:
561: /* If no threads left, then start over. */
562: if (global.cThr == 0)
563: {
564: global.fFirstThread = TRUE;
565: WinSendMsg(hwnd, WM_COMMAND, (MPARAM)IDM_DCMEMORY, 0);
566: }
567: }
568: break;
569:
570: case IDM_KILLALLTHREADS:
571: {
572: SHORT i;
573:
574: /* Delete them all and start over. */
575: LfBringThreadToTop(NULL);
576: for (i = global.cThr-1; i >= 0; --i)
577: LfKillThread(global.aThr[i]);
578: global.fFirstThread = TRUE;
579: WinSendMsg(hwnd, WM_COMMAND, (MPARAM)IDM_DCMEMORY, 0);
580: }
581: break;
582:
583: /********************************************************************/
584:
585: case IDM_AUTOSWITCH:
586: UPDATE_MENU_BOOL(global.fAutoSwitch, IDM_AUTOSWITCH);
587: if (global.fAutoSwitch)
588: WinStartTimer(global.hab, global.hwnd, IDT_AUTOSWITCH, global.usSwitchDelay);
589: else
590: WinStopTimer(global.hab, global.hwnd, IDT_AUTOSWITCH);
591: break;
592:
593: case IDM_SWITCHDELAY:
594: WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)SwitchDelayDlg, NULL,
595: IDR_SWITCHDELAYDLG, NULL );
596: break;
597:
598: case IDM_UPDATEMENUS:
599: UPDATE_MENU_BOOL(global.fUpdateMenusOnThreadSwitch, IDM_UPDATEMENUS);
600: break;
601:
602: /********************************************************************/
603:
604: case IDM_THREADINHERITANCE:
605: UPDATE_MENU_BOOL(global.fThreadInheritance, IDM_THREADINHERITANCE);
606: break;
607:
608: }
609: }
610:
611:
612:
613:
614: /************************************************************************
615: *
616: * LfControlMenu
617: *
618: * These commands cause global effects. The top set cause immediate
619: * results. The bottom set determine how the program reacts to
620: * certain events (mouse movement and button messages, timer messages).
621: *
622: ************************************************************************/
623:
624: BOOL
625: LfControlMenu(hwnd, id)
626: HWND hwnd;
627: USHORT id;
628: {
629: BOOL fRedraw = FALSE;
630:
631: switch (id)
632: {
633: case IDM_CLEARBITMAP:
634: LfClearRect(global.pThrTop, NULL);
635: break;
636:
637: case IDM_COPYBITMAPTOSCREEN:
638: if (global.pThrTop->hps)
639: WinInvalidateRect(global.hwnd, &(global.pThrTop)->rcl, FALSE);
640: break;
641:
642: case IDM_SQUAREBITMAP:
643: LfSquareBitmap(hwnd);
644: break;
645:
646: case IDM_RESIZEBITMAPTOWINDOW:
647: LfResizeBitmapToWindow();
648: fRedraw = TRUE;
649: break;
650:
651: /********************************************************************/
652:
653: case IDM_MOUSECHANGESRECURSION:
654: UPDATE_MENU_BOOL(global.fMouseChangesRecursion, IDM_MOUSECHANGESRECURSION);
655: break;
656:
657: case IDM_ANIMATEPTR:
658: UPDATE_MENU_BOOL(global.fAnimatePtr, IDM_ANIMATEPTR);
659: if (global.fAnimatePtr)
660: global.usPtrIncr = 1;
661: else
662: {
663: global.usPtrIncr = 0;
664: global.usCurPtr = global.usUserPtr;
665: }
666: break;
667:
668: case IDM_PTRPREFERENCES:
669: WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)PtrPreferencesDlg, NULL,
670: IDR_PTRPREFERENCESDLG, NULL );
671: break;
672:
673: case IDM_TIMERDELAY:
674: WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)TimerDelayDlg, NULL,
675: IDR_TIMERDELAYDLG, NULL );
676: break;
677: }
678:
679: return fRedraw;
680: }
681:
682:
683:
684:
685: /************************************************************************
686: *
687: * LfFractalMenu
688: *
689: * These commands select the fractal similarity transform, i.e. the
690: * basic fractal shape, for a thread.
691: *
692: ************************************************************************/
693:
694: BOOL
695: LfFractalMenu(hwnd, id)
696: HWND hwnd;
697: USHORT id;
698: {
699: BOOL fRedraw = FALSE;
700:
701: switch (id)
702: {
703: case IDM_SHARKTOOTH:
704: case IDM_SAWTOOTH:
705: case IDM_KOCH:
706: case IDM_SPACEFILLER:
707: case IDM_STOVE:
708: case IDM_SQUAREWAVE:
709: case IDM_HOURGLASS:
710: LfSelectXform(hwnd, global.pThrTop, id);
711: if (global.pThrTop->fFracRedraw)
712: fRedraw = TRUE;
713: break;
714:
715: /********************************************************************/
716:
717: case IDM_FRACREDRAW:
718: UPDATE_MENU_BOOL(global.pThrTop->fFracRedraw, IDM_FRACREDRAW);
719: break;
720: }
721:
722: return fRedraw;
723: }
724:
725:
726:
727:
728: /************************************************************************
729: *
730: * LfPrimitiveMenu
731: *
732: * These commands select the drawing primitive used to output the
733: * fractal for a thread.
734: *
735: ************************************************************************/
736:
737: BOOL
738: LfPrimitiveMenu(hwnd, id)
739: HWND hwnd;
740: USHORT id;
741: {
742: BOOL fRedraw = FALSE;
743:
744: switch (id)
745: {
746: case IDM_POLYLINE:
747: case IDM_POLYFILLET:
748: case IDM_POLYSPLINE:
749: case IDM_POLYMARKER:
750: case IDM_PEANO:
751: LfSelectPrim(hwnd, global.pThrTop, id);
752: if (global.pThrTop->fPrimRedraw)
753: fRedraw = TRUE;
754: break;
755:
756: /********************************************************************/
757:
758: case IDM_PRIMREDRAW:
759: UPDATE_MENU_BOOL(global.pThrTop->fPrimRedraw, IDM_PRIMREDRAW);
760: break;
761: }
762:
763: return fRedraw;
764: }
765:
766:
767:
768:
769: /************************************************************************
770: *
771: * LfAttributesMenu
772: *
773: * These commands allow the user to alter all the drawing attributes
774: * of a fractal (color, mix mode, marker symbol, etc.), as well as
775: * some fractal-related attributes such as width, height, offset,
776: * number of sides to polygonal frame, and rotation. Each thread
777: * has an independent set of all these attributes.
778: *
779: ************************************************************************/
780:
781: BOOL
782: LfAttributesMenu(hwnd, id)
783: HWND hwnd;
784: USHORT id;
785: {
786: BOOL fRedraw = FALSE;
787:
788: switch (id)
789: {
790: case IDM_LINEATTRS:
791: if (global.fUpdateAttrs && (global.flLineAttrs & LFA_LINEALL))
792: MyMessageBox(hwnd, pszAttrs);
793: if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)LineAttrsDlg, NULL,
794: IDR_LINEATTRSDLG, NULL ))
795: fRedraw = TRUE;
796: break;
797:
798: case IDM_MARKERATTRS:
799: if (global.fUpdateAttrs && (global.flMarkerAttrs & LFA_MARKALL))
800: MyMessageBox(hwnd, pszAttrs);
801: if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)MarkerAttrsDlg, NULL,
802: IDR_MARKERATTRSDLG, NULL ))
803: fRedraw = TRUE;
804: break;
805:
806: case IDM_AREAATTRS:
807: if (global.fUpdateAttrs && (global.flAreaAttrs & LFA_AREAALL))
808: MyMessageBox(hwnd, pszAttrs);
809: if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)AreaAttrsDlg, NULL,
810: IDR_AREAATTRSDLG, NULL ))
811: fRedraw = TRUE;
812: break;
813:
814: case IDM_IMAGEATTRS:
815: if (global.fUpdateAttrs && (global.flImageAttrs & LFA_IMAGEALL))
816: MyMessageBox(hwnd, pszAttrs);
817: if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)ImageAttrsDlg, NULL,
818: IDR_IMAGEATTRSDLG, NULL ))
819: fRedraw = TRUE;
820: break;
821:
822: case IDM_MISCATTRS:
823: if (global.fUpdateAttrs && (global.flMiscAttrs & (LFA_RECURSION |
824: LFA_CPTMAX | LFA_POLYGONSIDES | LFA_ROTATION)))
825: MyMessageBox(hwnd, pszAttrs);
826: if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)MiscAttrsDlg, NULL,
827: IDR_MISCATTRSDLG, NULL ))
828: fRedraw = TRUE;
829: break;
830:
831: case IDM_DIMENSIONS:
832: if (global.fUpdateAttrs && (global.flMiscAttrs & (LFA_XOFF |
833: LFA_YOFF | LFA_XSCALE | LFA_YSCALE)))
834: MyMessageBox(hwnd, pszAttrs);
835: if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)DimensionsDlg, NULL,
836: IDR_DIMENSIONSDLG, NULL ))
837: fRedraw = TRUE;
838: break;
839:
840: case IDM_DRAGDIMS:
841: global.fTracking = TRUE;
842: break;
843:
844: /********************************************************************/
845:
846: case IDM_ATTRREDRAW:
847: UPDATE_MENU_BOOL(global.pThrTop->fAttrRedraw, IDM_ATTRREDRAW);
848: break;
849: }
850:
851: if (fRedraw)
852: if (global.pThrTop->fAttrRedraw)
853: return TRUE;
854: return FALSE;
855: }
856:
857:
858:
859:
860: /************************************************************************
861: *
862: * LfEnvironmentMenu
863: *
864: * These commands alter the way a thread reacts to system and program
865: * events by toggling certain flags. Each thread has its own
866: * environment flags.
867: *
868: ************************************************************************/
869:
870: VOID
871: LfEnvironmentMenu(hwnd, id)
872: HWND hwnd;
873: USHORT id;
874: {
875: switch (id)
876: {
877: case IDM_AUTORESIZE:
878: UPDATE_MENU_BOOL(global.pThrTop->fAutoSizePS, IDM_AUTORESIZE);
879: break;
880:
881: case IDM_AUTOSELECTDIMS:
882: UPDATE_MENU_BOOL(global.pThrTop->fAutoSelectDims, IDM_AUTOSELECTDIMS);
883: break;
884:
885: case IDM_CLEARONREDRAW:
886: UPDATE_MENU_BOOL(global.pThrTop->fClearOnRedraw, IDM_CLEARONREDRAW);
887: break;
888:
889: case IDM_AUTOSTARTREDRAW:
890: UPDATE_MENU_BOOL(global.pThrTop->fAutoStartRedraw, IDM_AUTOSTARTREDRAW);
891: if (global.pThrTop->fAutoStartRedraw)
892: LfStartRedrawTimer();
893: break;
894:
895: case IDM_COLLECTBOUNDS:
896: UPDATE_MENU_BOOL(global.pThrTop->fCollectBounds, IDM_COLLECTBOUNDS);
897: break;
898:
899: }
900:
901: hwnd; /* this prevents an "unused variable" warning message */
902: }
903:
904:
905:
906:
907: /************************************************************************
908: *
909: * LfSelectDimension
910: *
911: * Set the dimensions of the next fractal by dragging a rectangle
912: * on the screen.
913: *
914: ************************************************************************/
915:
916: VOID
917: LfSelectDimension(hwnd, pt)
918: HWND hwnd;
919: POINTS pt;
920: {
921: TRACKINFO ti;
922: LONG lXExt, lYExt;
923:
924:
925: WinSendMsg(global.hwndFrame, WM_QUERYTRACKINFO, (MPARAM)TF_MOVE, (MPARAM)&ti);
926:
927: ti.cxBorder = 1;
928: ti.cyBorder = 1;
929: ti.rclTrack.xLeft = (LONG)pt.x;
930: ti.rclTrack.yBottom = (LONG)pt.y;
931: ti.rclTrack.xRight = (LONG)pt.x;
932: ti.rclTrack.yTop = (LONG)pt.y;
933: ti.fs = TF_RIGHT | TF_TOP;
934: ti.ptlMinTrackSize.x = 1L;
935: ti.ptlMinTrackSize.y = 1L;
936:
937: if (WinTrackRect(hwnd, NULL, &ti))
938: {
939: lXExt = (global.pThrTop->rcl).xRight - (global.pThrTop->rcl).xLeft;
940: lYExt = (global.pThrTop->rcl).yTop - (global.pThrTop->rcl).yBottom;
941:
942: global.dblXScale = (double)(ti.rclTrack.xRight - ti.rclTrack.xLeft) / (double)lXExt;
943: global.dblYScale = (double)(ti.rclTrack.yTop - ti.rclTrack.yBottom) / (double)lYExt;
944: global.dblXOff = (double) ti.rclTrack.xLeft / (double)lXExt;
945: global.dblYOff = (double) ti.rclTrack.yBottom / (double)lYExt;
946:
947: global.flMiscAttrs |= LFA_XSCALE | LFA_YSCALE | LFA_XOFF | LFA_YOFF;
948:
949: global.pThrTop->fUpdateAttrs = TRUE;
950: global.fUpdateAttrs = TRUE;
951: }
952: }
953:
954:
955:
956:
957: /************************************************************************
958: *
959: * LfSquareBitmap
960: *
961: * Resize the window horizontally to so that the client area is a
962: * square.
963: *
964: ************************************************************************/
965:
966: VOID
967: LfSquareBitmap(hwnd)
968: HWND hwnd;
969: {
970: SWP swp;
971: HWND hwndDesk;
972: RECTL rcl;
973:
974: if (hwnd == global.hwnd)
975: if (hwndDesk = WinQueryDesktopWindow(global.hab, NULL))
976: if (WinQueryWindowPos(global.hwndFrame, (PSWP)&swp))
977: {
978: rcl.xLeft = 0L;
979: rcl.yBottom = 0L;
980: rcl.xRight = swp.cx;
981: rcl.yTop = swp.cy;
982: if (WinCalcFrameRect(global.hwndFrame, &rcl, TRUE))
983: {
984: rcl.xRight = (SHORT)((LONG)rcl.yTop *
985: global.pThrTop->AspectRatio.lHorz /
986: global.pThrTop->AspectRatio.lVert);
987:
988: if (WinCalcFrameRect(global.hwndFrame, &rcl, FALSE))
989: WinSetWindowPos(global.hwndFrame, 0, swp.x, swp.y,
990: (SHORT)rcl.xRight, (SHORT)rcl.yTop,
991: SWP_SIZE);
992: }
993: }
994: }
995:
996:
997:
998:
999: /************************************************************************
1000: *
1001: * LfResizeBitmapToWindow
1002: *
1003: * Resize the bitmap to match the windows dimensions exactly.
1004: *
1005: ************************************************************************/
1006:
1007: VOID
1008: LfResizeBitmapToWindow()
1009: {
1010: global.bm.cx = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
1011: global.bm.cy = (USHORT) (global.rcl.yTop - global.rcl.yBottom);
1012: global.bm.cPlanes = global.pThrTop->cPlanes;
1013: global.bm.cBitCount = global.pThrTop->cBitCount;
1014:
1015: LfResizePS(global.pThrTop);
1016: }
1017:
1018:
1019:
1020:
1021: /************************************************************************
1022: *
1023: * LfSelect
1024: *
1025: * Select a rectangle to cut or copy to the clipboard.
1026: *
1027: ************************************************************************/
1028:
1029: VOID
1030: LfSelect(hwnd, pt)
1031: HWND hwnd;
1032: POINTS pt;
1033: {
1034: HPS hps;
1035: TRACKINFO ti;
1036: PRECTL prcl;
1037:
1038:
1039: if (global.fShowSelectRc)
1040: {
1041: global.fShowSelectRc = FALSE;
1042: hps = WinGetPS(hwnd);
1043: if (global.fTempSelect)
1044: {
1045: prcl = &global.rclSelect;
1046: global.fTempSelect = FALSE;
1047: }
1048: else
1049: prcl = &global.rclCutCopy;
1050: LfShowSelectRc(hps, prcl);
1051: WinReleasePS(hps);
1052: }
1053:
1054: WinSendMsg(global.hwndFrame, WM_QUERYTRACKINFO, (MPARAM)TF_MOVE, (MPARAM)&ti);
1055:
1056: ti.cxBorder = 1;
1057: ti.cyBorder = 1;
1058: ti.rclTrack.xLeft = (LONG)pt.x;
1059: ti.rclTrack.yBottom = (LONG)pt.y;
1060: ti.rclTrack.xRight = (LONG)pt.x;
1061: ti.rclTrack.yTop = (LONG)pt.y;
1062: ti.fs = TF_RIGHT | TF_TOP;
1063: ti.ptlMinTrackSize.x = 1L;
1064: ti.ptlMinTrackSize.y = 1L;
1065:
1066: if (WinTrackRect(hwnd, NULL, &ti))
1067: {
1068: global.rclSelect.xLeft = ti.rclTrack.xLeft;
1069: global.rclSelect.yBottom = ti.rclTrack.yBottom;
1070: global.rclSelect.xRight = ti.rclTrack.xRight;
1071: global.rclSelect.yTop = ti.rclTrack.yTop;
1072:
1073: global.fShowSelectRc = TRUE;
1074: global.fTempSelect = TRUE;
1075: hps = WinGetPS(hwnd);
1076: LfShowSelectRc(hps, &global.rclSelect);
1077: WinReleasePS(hps);
1078: }
1079: }
1080:
1081:
1082:
1083:
1084: /************************************************************************
1085: *
1086: * LfSelectAll
1087: *
1088: * Select the entire surface to cut or copy to the clipboard.
1089: *
1090: ************************************************************************/
1091:
1092: VOID
1093: LfSelectAll(hwnd)
1094: HWND hwnd;
1095: {
1096: HPS hps;
1097:
1098: global.rclSelect = global.pThrTop->rcl;
1099:
1100: global.fShowSelectRc = TRUE;
1101: global.fTempSelect = TRUE;
1102: hps = WinGetPS(hwnd);
1103: LfShowSelectRc(hps, &global.rclSelect);
1104: WinReleasePS(hps);
1105: }
1106:
1107:
1108:
1109:
1110: /************************************************************************
1111: *
1112: * LfCut
1113: *
1114: * Cuts the selected rectangle from the bitmap and puts it in the
1115: * clipboard.
1116: *
1117: ************************************************************************/
1118:
1119: VOID
1120: LfCut(hwnd)
1121: HWND hwnd;
1122: {
1123: if (LfCopy(hwnd))
1124: LfClearRect(global.pThrTop, &global.rclCutCopy);
1125: }
1126:
1127:
1128:
1129:
1130: /************************************************************************
1131: *
1132: * LfCopy
1133: *
1134: * Copies the selected rectangle from the bitmap the clipboard.
1135: *
1136: ************************************************************************/
1137:
1138: BOOL
1139: LfCopy(hwnd)
1140: HWND hwnd;
1141: {
1142: HPS hps;
1143: PRECTL prcl;
1144: SIZEL size;
1145: BITMAPINFOHEADER bminfo;
1146: POINTL aptl[4];
1147:
1148:
1149:
1150: global.fShowSelectRc = FALSE;
1151: hps = WinGetPS(hwnd);
1152: if (global.fTempSelect)
1153: {
1154: prcl = &global.rclSelect;
1155: global.fTempSelect = FALSE;
1156: }
1157: else
1158: prcl = &global.rclCutCopy;
1159: LfShowSelectRc(hps, prcl);
1160: WinReleasePS(hps);
1161:
1162: if (global.fUseClipbrd)
1163: {
1164: if (WinOpenClipbrd(global.hab))
1165: {
1166: global.fHaveSelectRc = TRUE;
1167: global.rclCutCopy.xLeft = global.rclSelect.xLeft;
1168: global.rclCutCopy.yBottom = global.rclSelect.yBottom;
1169: global.rclCutCopy.xRight = global.rclSelect.xRight;
1170: global.rclCutCopy.yTop = global.rclSelect.yTop;
1171:
1172: /* copy bits here */
1173:
1174: WinCloseClipbrd(global.hab);
1175:
1176: return TRUE;
1177: }
1178: }
1179: else
1180: {
1181: global.fHaveSelectRc = TRUE;
1182: global.rclCutCopy.xLeft = global.rclSelect.xLeft;
1183: global.rclCutCopy.yBottom = global.rclSelect.yBottom;
1184: global.rclCutCopy.xRight = global.rclSelect.xRight;
1185: global.rclCutCopy.yTop = global.rclSelect.yTop;
1186:
1187: if (global.fHaveCutCopyDC)
1188: {
1189: GpiSetBitmap(global.CutCopyPS, NULL);
1190: GpiDeleteBitmap(global.CutCopyBM);
1191: GpiDestroyPS(global.CutCopyPS);
1192: DevCloseDC(global.CutCopyDC);
1193: global.fHaveCutCopyDC = FALSE;
1194: }
1195:
1196: global.CutCopyDC = DevOpenDC(global.hab, OD_MEMORY, "*", 0L, NULL, NULL);
1197: if (!global.CutCopyDC)
1198: return FALSE;
1199:
1200: size.cx = 0L;
1201: size.cy = 0L;
1202: global.CutCopyPS = GpiCreatePS(global.hab, global.CutCopyDC, &size,
1203: PU_PELS|GPIT_MICRO|GPIA_ASSOC);
1204: if (!global.CutCopyPS)
1205: goto lfc_error_close_dc;
1206:
1207:
1208: bminfo.cbFix = sizeof(BITMAPINFOHEADER);
1209: bminfo.cx = (USHORT) (global.rclCutCopy.xRight - global.rclCutCopy.xLeft);
1210: bminfo.cy = (USHORT) (global.rclCutCopy.yTop - global.rclCutCopy.yBottom);
1211: bminfo.cPlanes = global.pThrTop->cPlanes;
1212: bminfo.cBitCount = global.pThrTop->cBitCount;
1213: global.CutCopyBM = GpiCreateBitmap(global.CutCopyPS, &bminfo, 0L, 0L, 0L);
1214: if (!global.CutCopyBM)
1215: goto lfc_error_destroy_ps;
1216: GpiSetBitmap(global.CutCopyPS, global.CutCopyBM);
1217:
1218: aptl[0].x = 0L;
1219: aptl[0].y = 0L;
1220: aptl[1].x = global.rclCutCopy.xRight - global.rclCutCopy.xLeft;
1221: aptl[1].y = global.rclCutCopy.yTop - global.rclCutCopy.yBottom;
1222: aptl[2].x = global.rclCutCopy.xLeft;
1223: aptl[2].y = global.rclCutCopy.yBottom;
1224:
1225: GpiBitBlt(global.CutCopyPS, global.pThrTop->hps, 3L, aptl, ROP_SRCCOPY, NULL);
1226:
1227: global.fHaveCutCopyDC = TRUE;
1228: return TRUE;
1229:
1230:
1231: lfc_error_destroy_ps:
1232: GpiDestroyPS(global.CutCopyPS);
1233: lfc_error_close_dc:
1234: DevCloseDC(global.CutCopyDC);
1235: return FALSE;
1236: }
1237:
1238: return FALSE;
1239: }
1240:
1241:
1242:
1243:
1244: /************************************************************************
1245: *
1246: * LfPaste
1247: *
1248: * Pastes the selected rectangle from the clipboard to the bitmap.
1249: * Hides the selection rectangle before calling WinTrackRect.
1250: *
1251: ************************************************************************/
1252:
1253: VOID
1254: LfPaste(hwnd)
1255: HWND hwnd;
1256: {
1257: HPS hps;
1258: PRECTL prcl;
1259: TRACKINFO ti;
1260: POINTL aptl[4];
1261:
1262:
1263: if (global.fShowSelectRc)
1264: {
1265: global.fShowSelectRc = FALSE;
1266: hps = WinGetPS(hwnd);
1267: if (global.fTempSelect)
1268: {
1269: prcl = &global.rclSelect;
1270: global.fTempSelect = FALSE;
1271: }
1272: else
1273: prcl = &global.rclCutCopy;
1274: LfShowSelectRc(hps, prcl);
1275: WinReleasePS(hps);
1276: }
1277:
1278: WinSendMsg(global.hwndFrame, WM_QUERYTRACKINFO, (MPARAM)TF_MOVE, (MPARAM)&ti);
1279:
1280: ti.cxBorder = 1;
1281: ti.cyBorder = 1;
1282: ti.rclTrack.xLeft = global.rclCutCopy.xLeft;
1283: ti.rclTrack.yBottom = global.rclCutCopy.yBottom;
1284: ti.rclTrack.xRight = global.rclCutCopy.xRight;
1285: ti.rclTrack.yTop = global.rclCutCopy.yTop;
1286: ti.fs = TF_MOVE;
1287: ti.ptlMinTrackSize.x = 1L;
1288: ti.ptlMinTrackSize.y = 1L;
1289:
1290: if (WinTrackRect(hwnd, NULL, &ti))
1291: {
1292: if (global.fUseClipbrd)
1293: {
1294: if (WinOpenClipbrd(global.hab))
1295: {
1296: /* copy bits here */
1297: WinCloseClipbrd(global.hab);
1298: }
1299: }
1300: else
1301: {
1302: aptl[0].x = ti.rclTrack.xLeft;
1303: aptl[0].y = ti.rclTrack.yBottom;
1304: aptl[1].x = ti.rclTrack.xLeft + (global.rclCutCopy.xRight - global.rclCutCopy.xLeft);
1305: aptl[1].y = ti.rclTrack.yBottom + (global.rclCutCopy.yTop - global.rclCutCopy.yBottom);
1306: aptl[2].x = 0L;
1307: aptl[2].y = 0L;
1308:
1309: GpiBitBlt(global.pThrTop->hps, global.CutCopyPS, 3L, aptl, global.ulPasteROP, NULL);
1310: WinInvalidateRect(global.hwnd, &(ti.rclTrack), FALSE);
1311: }
1312: }
1313: }
1314:
1315:
1316:
1317:
1318: /************************************************************************
1319: *
1320: * LfSelectXform
1321: *
1322: * Select a similarity transform.
1323: *
1324: ************************************************************************/
1325:
1326: VOID
1327: LfSelectXform(hwnd, pthr, id)
1328: HWND hwnd;
1329: PTHR pthr;
1330: USHORT id;
1331: {
1332: BOOL fAlreadySaidIt = FALSE;
1333:
1334:
1335: if ((id != pthr->usCurXform) ||
1336: ((id != global.usCurXform) && global.fUpdateAttrs))
1337: {
1338: if (global.fUpdateAttrs && (global.flMiscAttrs & LFA_CURXFORM))
1339: {
1340: MyMessageBox(hwnd, pszAttrs);
1341: fAlreadySaidIt = TRUE;
1342: }
1343:
1344: global.flMiscAttrs |= LFA_CURXFORM;
1345:
1346: if (LfIsThreadTop(pthr))
1347: {
1348: if (fAlreadySaidIt)
1349: UNCHECK_MENU_ITEM(global.hwndFrame, global.usCurXform);
1350: else
1351: UNCHECK_MENU_ITEM(global.hwndFrame, pthr->usCurXform);
1352: global.usCurXform = id;
1353: CHECK_MENU_ITEM(global.hwndFrame, id);
1354: }
1355: else
1356: global.usCurXform = id;
1357:
1358: pthr->fUpdateAttrs = TRUE;
1359: global.fUpdateAttrs = TRUE;
1360: }
1361:
1362: if (pthr->fAutoSelectDims)
1363: {
1364: if (global.fUpdateAttrs && (global.flMiscAttrs & (LFA_XSCALE |
1365: LFA_YSCALE | LFA_XOFF | LFA_YOFF | LFA_POLYGONSIDES)))
1366: if (!fAlreadySaidIt)
1367: MyMessageBox(hwnd, pszAttrs);
1368:
1369: global.dblXScale = aXform[id - IDM_SHARKTOOTH].xScale;
1370: global.dblYScale = aXform[id - IDM_SHARKTOOTH].yScale;
1371: global.dblXOff = aXform[id - IDM_SHARKTOOTH].xOff;
1372: global.dblYOff = aXform[id - IDM_SHARKTOOTH].yOff;
1373: global.usPolygonSides = aXform[id - IDM_SHARKTOOTH].usSides;
1374:
1375: global.flMiscAttrs |= LFA_XSCALE | LFA_YSCALE | LFA_XOFF | LFA_YOFF |
1376: LFA_POLYGONSIDES;
1377: pthr->fUpdateAttrs = TRUE;
1378: global.fUpdateAttrs = TRUE;
1379: }
1380: }
1381:
1382:
1383:
1384:
1385: /************************************************************************
1386: *
1387: * LfSelectPrim
1388: *
1389: * Select a drawing primitive.
1390: *
1391: ************************************************************************/
1392:
1393: VOID
1394: LfSelectPrim(hwnd, pthr, id)
1395: HWND hwnd;
1396: PTHR pthr;
1397: USHORT id;
1398: {
1399: BOOL fAlreadySaidIt = FALSE;
1400:
1401:
1402: if ((id != pthr->usCurPrim) ||
1403: ((id != global.usCurPrim) && global.fUpdateAttrs))
1404: {
1405: if (global.fUpdateAttrs && (global.flMiscAttrs & LFA_CURPRIM))
1406: {
1407: MyMessageBox(hwnd, "Previous attributes not read yet.");
1408: fAlreadySaidIt = TRUE;
1409: }
1410:
1411: if (LfIsThreadTop(pthr))
1412: {
1413: if (fAlreadySaidIt)
1414: UNCHECK_MENU_ITEM(global.hwndFrame, global.usCurPrim);
1415: else
1416: UNCHECK_MENU_ITEM(global.hwndFrame, pthr->usCurPrim);
1417: global.usCurPrim = id;
1418: CHECK_MENU_ITEM(global.hwndFrame, id);
1419: }
1420: else
1421: global.usCurPrim = id;
1422:
1423: global.flMiscAttrs |= LFA_CURPRIM;
1424: pthr->fUpdateAttrs = TRUE;
1425: global.fUpdateAttrs = TRUE;
1426: }
1427: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.