1 /*
2 * @(#)long1.c 1.2 01/03/85
3 *
4 * Routines to implement "long" commands in the SUN Gremlin picture editor.
5 *
6 * Mark Opperman (opcode@monet.BERKELEY)
7 *
8 */
9
10 /*
11 * This file contains routines to implement the long text commands
12 * of the gremlin PICTURE editor.
13 */
14
15 #include <sunwindow/rect.h>
16 #include "gremlin.h"
17 #include <ctype.h>
18
19 /* imports from graphics files */
20
21 extern GRBlankPoints();
22 extern GRDisplayPoint();
23 extern GRErasePoint();
24 extern GRfontfound();
25 extern GROpenFont();
26 extern GRSetTextPos();
27 extern curve_set; /* TRUE if spline points pre-computed */
28
29 /* imports from point.c */
30
31 extern POINT *PTMakeTextPoints();
32
33 /* imports from display.c */
34
35 extern DISClearSetDisplay();
36 extern DISScreenAdd();
37 extern DISScreenErase();
38
39 /* imports from database files */
40
41 extern ELT *DBCreateElt();
42 extern DBGravitate();
43 extern DBChangeBrush();
44 extern DBChangeFont();
45 extern DBChangeSize();
46 extern DBChangeStipple();
47 extern DBChangeText();
48 extern DBChangeJustify();
49 extern DBAddSet();
50 extern DBClearSet();
51 extern POINT *PTMakePoint();
52 extern PTDeletePoint();
53
54 /* imports from undodb.c */
55
56 extern UNRembMod();
57
58 /* imports from short.c */
59
60 extern SHUpdate();
61
62 /* imports from menu.c */
63
64 extern HiArtMode;
65 extern HiLineStyle;
66 extern HiBrush[];
67 extern MNHighLt();
68 extern MNUnHighLt();
69 extern HiFont[];
70 extern HiSize[];
71 extern HiStipple[];
72
73 /* imports from text.c */
74
75 extern TxKillLine();
76 extern TxMsgOK();
77 extern text_getvalue();
78
79 /* imports from C */
80
81 extern char *malloc();
82 extern char *strcpy();
83
84 /* imports from main.c */
85
86 extern ELT *PICTURE; /* current PICTURE database */
87 extern ELT *cset; /* current set database */
88 extern Artmode; /* indication of point display size */
89 extern CBRUSH, CSIZE, CFONT; /* current brush, size, font */
90 extern CJUST; /* current text justification */
91 extern CSTIPPLE; /* current stipple pattern */
92 extern Alignment; /* point alignment indicator */
93 extern float PX, PY; /* cursor coordinates */
94 extern float Lastx, Lasty; /* previous cursor coordinates */
95 extern SEQ; /* point sequence number */
96 extern POINT *POINTLIST, *BACKPOINT;/* accumulated point list */
97 extern Adjustment; /* point adjustment mode */
98 extern GravityOn; /* gravity mode flag */
99 extern CHANGED; /* PICTURE changed flag */
100 extern SymbolicLines;
101 extern Gridsize;
102
103 extern SUN_XORIGIN;
104 extern SUN_YORIGIN;
105 extern struct rect pix_size;
106
107 /* locals */
108
109 int SHOWPOINTS; /* TRUE if current set reference points on */
110
111 static char badarg[] = "bad args";
112 static char noset[] = "no current set";
113 static char delmsg[] = "can't delete any more points";
114
115 #define BADNUM 0x7fffffff /* largest positive 32-bit integer */
116
117 /*
118 * This routine trys to interpret the string starting at
119 * line+index as an integral numeric parameter. The function
120 * returns the numeric equivalent or the largest possible
121 * integer if there is some error in interpreting the string.
122 */
GetNumParm(line,index)123 GetNumParm(line, index)
124 register char *line;
125 register int *index;
126 {
127 char num[20];
128 register sign = 1;
129 register i;
130 int result;
131
132 for (i=0; (*(line + *index) == ' '); ++i) /* skip blanks */
133 ++(*index);
134
135 if (*(line + *index) == '-') { /* negative number */
136 sign = -1;
137 ++(*index);
138 }
139
140 for (i=0; !Delimiter(*(line + *index)); ++i) {
141 num[i] = *(line + *index);
142 if (!isdigit(num[i]))
143 return(BADNUM);
144 ++(*index);
145 }
146
147 if (i == 0)
148 return(BADNUM);
149
150 num[i] = '\0';
151 (void) sscanf(num, "%d", &result);
152 return(result * sign);
153 } /* end GetNumParm */
154
155
156 /*
157 * This routine accepts coordinates from the text terminal
158 * and creates and displays a point from them by passing them
159 * along to LGPoint.
160 */
LGOPoint()161 LGOPoint()
162 {
163 int index, xcoord, ycoord;
164 char buf[TEXT_BUFMAX];
165
166 text_getvalue(&buf[0]);
167 TxKillLine();
168 index = 0;
169 xcoord = GetNumParm(buf, &index);
170 if (xcoord == BADNUM) {
171 error(badarg);
172 return;
173 }
174
175 ++index;
176 ycoord = GetNumParm(buf, &index);
177 if (ycoord == BADNUM) {
178 error(badarg);
179 return;
180 }
181
182 PX = xcoord;
183 PY = ycoord;
184 LGPoint();
185 } /* end LGOPoint */
186
187
188 /*
189 * This routine accepts cursor coordinates (global PX & PY) and then
190 * creates and displays points according to the current adjustment and
191 * alignment modes. Note that alignment and gravity are mutually exclusive
192 * and adjustment takes precedence over either.
193 */
LGPoint()194 LGPoint()
195 {
196 ELT *temp;
197 POINT *p1;
198 float signx = 1.0;
199 float signy = 1.0;
200
201 temp = DBInit();
202 if (GravityOn)
203 DBGravitate (PX, PY, &PX, &PY, &p1, &temp, PICTURE, FALSE);
204
205 if (DBNullelt(temp)) { /* no gravity in effect */
206 /* Round to nearest alignment boundary */
207 if (PX < 0) {
208 signx = -1.0;
209 PX = -PX;
210 }
211 if (PY < 0) {
212 signy = -1.0;
213 PY = -PY;
214 }
215
216 PX = (float) (((int) (PX / Alignment + 0.5)) * Alignment) * signx;
217 PY = (float) (((int) (PY / Alignment + 0.5)) * Alignment) * signy;
218 }
219
220 if (SEQ > 0) { /* this isn't the first point */
221 switch (Adjustment) {
222 case HORZ:
223 PY = Lasty;
224 break;
225 case VERT:
226 PX = Lastx;
227 break;
228 case MAN:
229 if (fabs(PX - Lastx) > fabs(PY - Lasty))
230 PY = Lasty;
231 else
232 PX = Lastx;
233 break;
234 }
235 }
236
237 if (SEQ >= MAXPOINTS) {
238 error("too many points");
239 return;
240 }
241
242 GRDisplayPoint(PX, PY, SEQ);
243 (void) PTMakePoint(PX, PY, &POINTLIST);
244 Lastx = PX;
245 Lasty = PY;
246
247 ++SEQ;
248 } /* end LGPoint */
249
250
251 /*
252 * Clear all points on from Showpoints command.
253 */
CSP()254 CSP()
255 {
256 if (SHOWPOINTS)
257 LGShowPoints();
258 }
259
260
261 /*
262 * This routine deletes all points from the POINTLIST and
263 * clears them from the display also.
264 */
CP()265 CP()
266 {
267 POINT *temp;
268
269 while (!Nullpoint(BACKPOINT)) {
270 temp = PTNextPoint(BACKPOINT);
271 free ((char *) BACKPOINT);
272 BACKPOINT = temp;
273 }
274
275 GRBlankPoints(POINTLIST);
276 BACKPOINT = POINTLIST;
277 POINTLIST = PTInit();
278 SEQ = 0;
279 } /* end CP */
280
281
282 /*
283 * Clear all displayed points.
284 */
LGClearPoints()285 LGClearPoints()
286 {
287 CP();
288 CSP();
289 } /* end LGClearPoints */
290
291
292 /*
293 * This routine removes the last point from the POINTLIST
294 * and erases it from the screen.
295 */
LGDeletePoint()296 LGDeletePoint()
297 {
298 POINT *pt1, *pt2, *pt3;
299
300 if (SEQ == 0) {
301 error("no point");
302 return;
303 }
304
305 pt2 = pt3 = POINTLIST;
306 while (!Nullpoint(pt3)) { /* find last point and pointer to it */
307 pt1 = pt2;
308 pt2 = pt3;
309 pt3 = PTNextPoint(pt3);
310 }
311
312 SEQ--;
313 GRErasePoint(pt2->x, pt2->y, SEQ);
314 PTDeletePoint(pt2, &POINTLIST);
315 if (SEQ > 0) { /* pt1 points to last one of them */
316 Lastx = pt1->x;
317 Lasty = pt1->y;
318 }
319 } /* end LGDeletePoint */
320
321
322 /*
323 * This routine causes the positioning points of the current set
324 * to be displayed.
325 */
LGShowPoints()326 LGShowPoints()
327 {
328 register ELT *elt;
329 register POINT *p1;
330 register pno;
331
332 if (DBNullelt(cset)) {
333 error(noset);
334 return;
335 }
336
337 elt = cset;
338 while (!DBNullelt(elt)) {
339 p1 = elt->ptlist;
340 pno = 0;
341
342 while (!Nullpoint(p1)) {
343 GRDisplayPoint(p1->x, p1->y, pno);
344 p1 = PTNextPoint(p1);
345 pno++;
346 }
347
348 elt = DBNextofSet(elt);
349 }
350 SHOWPOINTS = !SHOWPOINTS;
351 } /* end LGShowPoints */
352
353
354 /*
355 * This routine handles the two forms of the TEXT command.
356 * From the text subwindow, when a RETURN is pressed, the text
357 * buffer is copied to the LAST point layed down, the text is
358 * consumed, and that point is eaten. This provides a convenient
359 * method of entering several TEXT elements at many locations
360 * in the picture.
361 * From the menu subwindow, the traditional Gremlin TEXT command
362 * is implemented. One or two points may be specified, and all
363 * points are consumed at the end of the command.
364 */
365 static
LGTextDisplay(oldway)366 LGTextDisplay(oldway)
367 int oldway;
368 {
369 register ELT *elt;
370 char buf[TEXT_BUFMAX];
371 POINT pos, ppnt, *p1;
372 char *text;
373
374 if (SEQ == 0) {
375 error("not enough points");
376 return;
377 }
378
379 text_getvalue(&buf[0]);
380
381 if (*buf == '\0') { /* no text */
382 error("empty string");
383 return;
384 }
385
386 GROpenFont(CFONT, CSIZE);
387 if (!GRfontfound(CFONT, CSIZE)) {
388 error("can't open font file");
389 return;
390 }
391
392 UNForget();
393 text = malloc((unsigned) strlen(buf) + 1);
394 (void) strcpy(text, buf);
395 DISClearSetDisplay();
396 DBClearSet();
397
398 if (oldway == TRUE) { /* one or two points OK */
399 ppnt.x = POINTLIST->x;
400 ppnt.y = POINTLIST->y;
401 if (SEQ > 1) {
402 p1 = PTNextPoint(POINTLIST);
403 ppnt.x = (ppnt.x + p1->x) / 2;
404 ppnt.y = (ppnt.y + p1->y) / 2;
405 }
406 }
407 else { /* find last point */
408 p1 = POINTLIST;
409 while (!Nullpoint(PTNextPoint(p1)))
410 p1 = PTNextPoint(p1);
411 ppnt.x = p1->x;
412 ppnt.y = p1->y;
413 }
414
415 GRSetTextPos(text, CJUST, CFONT, CSIZE, &ppnt, &pos);
416 p1 = PTMakeTextPoints(text, CFONT, CSIZE, &ppnt, &pos);
417 elt = DBCreateElt(CJUST, p1, CFONT, CSIZE, text, &PICTURE);
418
419 DISScreenAdd(elt, pixmask | csetmask);
420 DBAddSet(elt);
421
422 if (oldway == TRUE)
423 CP();
424 else
425 LGDeletePoint();
426
427 TxKillLine();
428 CHANGED = TRUE;
429 } /* end LGTextDisplay */
430
431
432 /*
433 * This routine implements the TEXT command from the menu subwindow.
434 */
LGText()435 LGText()
436 {
437 LGTextDisplay(TRUE); /* the old way of doing text entry */
438 } /* end LGText */
439
440
LGTextSW()441 LGTextSW()
442 {
443 LGTextDisplay(FALSE); /* the new way of doing text entry */
444 } /* end LGTextSW */
445
446
447 /*
448 * This routine sets the current brush to that specified in the parameter.
449 */
LGBrush(brush)450 LGBrush(brush)
451 {
452 MNUnHighLt(HiBrush[CBRUSH-1]);
453 CBRUSH = brush;
454 MNHighLt(HiBrush[CBRUSH-1]);
455 } /* end LGBrush */
456
457
LGBrush1()458 LGBrush1()
459 {
460 LGBrush(1);
461 }
462
463
LGBrush2()464 LGBrush2()
465 {
466 LGBrush(2);
467 }
468
469
LGBrush3()470 LGBrush3()
471 {
472 LGBrush(3);
473 }
474
475
LGBrush4()476 LGBrush4()
477 {
478 LGBrush(4);
479 }
480
481
LGBrush5()482 LGBrush5()
483 {
484 LGBrush(5);
485 }
486
487
LGBrush6()488 LGBrush6()
489 {
490 LGBrush(6);
491 }
492
493
494 /*
495 * This routine causes the elements in the current set
496 * to be redrawn using the new brush.
497 */
LGMBrush(brush)498 LGMBrush(brush)
499 int brush;
500 {
501 register ELT *elt;
502
503 if (DBNullelt(cset)) {
504 error(noset);
505 return;
506 }
507
508 UNForget();
509 CSP();
510
511 elt = cset;
512 while (!DBNullelt(elt)) {
513 if (!TEXT(elt->type)) {
514 DISScreenErase(elt, pixmask | csetmask);
515 DBChangeBrush(elt, brush, &PICTURE);
516 curve_set = TRUE; /* no need to re-compute spline points */
517 DISScreenAdd(elt, pixmask | csetmask);
518 }
519 elt = DBNextofSet(elt);
520 }
521
522 CP();
523 CHANGED = TRUE;
524 } /* end LGMBrush */
525
526
LGMBrush1()527 LGMBrush1()
528 {
529 LGMBrush(1);
530 }
531
532
LGMBrush2()533 LGMBrush2()
534 {
535 LGMBrush(2);
536 }
537
538
LGMBrush3()539 LGMBrush3()
540 {
541 LGMBrush(3);
542 }
543
544
LGMBrush4()545 LGMBrush4()
546 {
547 LGMBrush(4);
548 }
549
550
LGMBrush5()551 LGMBrush5()
552 {
553 LGMBrush(5);
554 }
555
556
LGMBrush6()557 LGMBrush6()
558 {
559 LGMBrush(6);
560 }
561
562
563 /*
564 * This routine causes text elements in the current set
565 * to be redrawn using the new justification mode.
566 * mode is 1 - 9 for tl, tc, tr, cl, cc, cl, bl, bc, br
567 */
LGMJustify(just)568 LGMJustify(just)
569 int just;
570 {
571 register ELT *elt;
572
573 if (DBNullelt(cset)) {
574 error(noset);
575 return;
576 }
577
578 UNForget();
579 CSP();
580
581 elt = cset;
582 while (!DBNullelt(elt)) {
583 if (TEXT(elt->type)) {
584 DISScreenErase(elt, pixmask | csetmask);
585 DBChangeJustify(elt, just, &PICTURE);
586 DISScreenAdd(elt, pixmask | csetmask);
587 }
588 elt = DBNextofSet(elt);
589 }
590
591 CP();
592 CHANGED = TRUE;
593 } /* end LGMJustify */
594
595
596 /*
597 * This routine causes the text elements in the current set
598 * to be redrawn using the new font.
599 */
LGMFont(font)600 LGMFont(font)
601 int font;
602 {
603 register ELT *elt;
604
605 if (DBNullelt(cset)) {
606 error(noset);
607 return;
608 }
609
610 UNForget();
611 CSP();
612
613 elt = cset;
614 while (!DBNullelt(elt)) {
615 if (TEXT(elt->type)) {
616 GROpenFont(font, elt->size);
617 if (!GRfontfound(font, elt->size)) {
618 error("can't open font file");
619 }
620 else {
621 DISScreenErase(elt, pixmask | csetmask);
622 TxMsgOK();
623 DBChangeFont(elt, font, &PICTURE);
624 DISScreenAdd(elt, pixmask | csetmask);
625 }
626 }
627 elt = DBNextofSet(elt);
628 }
629
630 CP();
631 CHANGED = TRUE;
632 } /* end LGMFont */
633
634
LGMFont1()635 LGMFont1()
636 {
637 LGMFont(1);
638 }
639
640
LGMFont2()641 LGMFont2()
642 {
643 LGMFont(2);
644 }
645
646
LGMFont3()647 LGMFont3()
648 {
649 LGMFont(3);
650 }
651
652
LGMFont4()653 LGMFont4()
654 {
655 LGMFont(4);
656 }
657
658
659 /*
660 * This routine causes the text elements in the current set
661 * to be redrawn using the new size.
662 */
LGMSize(size)663 LGMSize(size)
664 int size;
665 {
666 register ELT *elt;
667
668 if (DBNullelt(cset)) {
669 error(noset);
670 return;
671 }
672
673 UNForget();
674 CSP();
675
676 elt = cset;
677 while (!DBNullelt(elt)) {
678 if (TEXT(elt->type)) {
679 GROpenFont(elt->brushf, size);
680 if (!GRfontfound(elt->brushf, size)) {
681 error("can't open font file");
682 }
683 else {
684 DISScreenErase(elt, pixmask | csetmask);
685 TxMsgOK();
686 DBChangeSize(elt, size, &PICTURE);
687 DISScreenAdd(elt, pixmask | csetmask);
688 }
689 }
690 elt = DBNextofSet(elt);
691 }
692
693 CP();
694 CHANGED = TRUE;
695 } /* end LGMFize */
696
697
LGMSize1()698 LGMSize1()
699 {
700 LGMSize(1);
701 }
702
703
LGMSize2()704 LGMSize2()
705 {
706 LGMSize(2);
707 }
708
709
LGMSize3()710 LGMSize3()
711 {
712 LGMSize(3);
713 }
714
715
LGMSize4()716 LGMSize4()
717 {
718 LGMSize(4);
719 }
720
721
722 /*
723 * This routine causes the polygon elements in the current set
724 * to be redrawn using the new stipple.
725 */
LGMStipple(stipple)726 LGMStipple(stipple)
727 int stipple;
728 {
729 register ELT *elt;
730
731 if (DBNullelt(cset)) {
732 error(noset);
733 return;
734 }
735
736 UNForget();
737 CSP();
738
739 elt = cset;
740 while (!DBNullelt(elt)) {
741 if (elt->type == POLYGON) {
742 DISScreenErase(elt, pixmask | csetmask);
743 TxMsgOK();
744 DBChangeStipple(elt, stipple, &PICTURE);
745 DISScreenAdd(elt, pixmask | csetmask);
746 }
747 elt = DBNextofSet(elt);
748 }
749
750 CP();
751 CHANGED = TRUE;
752 } /* end LGMStipple */
753
754
LGMStipple1()755 LGMStipple1()
756 {
757 LGMStipple(1);
758 }
759
760
LGMStipple2()761 LGMStipple2()
762 {
763 LGMStipple(2);
764 }
765
766
LGMStipple3()767 LGMStipple3()
768 {
769 LGMStipple(3);
770 }
771
772
LGMStipple4()773 LGMStipple4()
774 {
775 LGMStipple(4);
776 }
777
778
LGMStipple5()779 LGMStipple5()
780 {
781 LGMStipple(5);
782 }
783
784
LGMStipple6()785 LGMStipple6()
786 {
787 LGMStipple(6);
788 }
789
790
LGMStipple7()791 LGMStipple7()
792 {
793 LGMStipple(7);
794 }
795
796
LGMStipple8()797 LGMStipple8()
798 {
799 LGMStipple(8);
800 }
801
802
803 /*
804 * This routine allows modification of text by replacing
805 * an existing string with a new one, appropriately repositioned
806 */
LGMText()807 LGMText()
808 {
809 register ELT *elt;
810 char buf[TEXT_BUFMAX];
811
812 if (DBNullelt(cset)) {
813 error(noset);
814 return;
815 }
816
817 text_getvalue(&buf[0]);
818 if (*buf == '\0') { /* no text */
819 error("empty string");
820 return;
821 }
822
823 UNForget();
824 CSP();
825
826 elt = cset;
827 while (!DBNullelt(elt)) {
828 if (TEXT(elt->type)) {
829 DISScreenErase(elt, pixmask | csetmask);
830 TxMsgOK();
831 DBChangeText(elt, buf, &PICTURE);
832 DISScreenAdd(elt, pixmask | csetmask);
833 }
834 elt = DBNextofSet(elt);
835 }
836
837 CP();
838 TxKillLine();
839 CHANGED = TRUE;
840 } /* end LGMText */
841
842
843 /*
844 * This routine modifies the element which contains the point
845 * closest to the first of two specified points so that that point
846 * coincides with the second of the points (if specified).
847 *
848 * Note: it implies knowledge of the database representation by modifying
849 * the element directly.
850 */
LGMPoint()851 LGMPoint()
852 {
853 ELT *elt;
854 POINT *p1, *p2, *p3, *p4;
855 float x1, y1;
856 int length;
857
858 if (SEQ < 1) {
859 error("no point specified");
860 return;
861 }
862
863 /* find point */
864 DBGravitate(POINTLIST->x, POINTLIST->y, &x1, &y1, &p1, &elt, cset, TRUE);
865
866 if (DBNullelt(elt) || TEXT(elt->type)) {
867 error("can't find a good element");
868 return;
869 }
870
871 if (SEQ == 1) { /* wants to delete a point */
872 length = PTListLength(elt);
873 if (((elt->type == POLYGON) && (length == 3)) || (length == 2)) {
874 error(delmsg);
875 return;
876 }
877 }
878
879 /* now OK to do whatever */
880 UNForget();
881 CSP();
882
883 DBClearSet();
884 GRClear(csetmask);
885 DISScreenErase(elt, pixmask);
886 UNRembMod(elt, &PICTURE);
887 if (SEQ > 1) { /* move a point, not delete */
888 p2 = PTNextPoint(POINTLIST);
889 p1->x = p2->x;
890 p1->y = p2->y;
891 p2 = PTNextPoint(p2);
892 if (!Nullpoint(p2)) {
893 p3 = PTInit();
894 while (!Nullpoint(p2)) {
895 p4 = PTMakePoint(p2->x, p2->y, &p3);
896 p2 = PTNextPoint(p2);
897 }
898 p4->nextpt = p1->nextpt;
899 p1->nextpt = p3;
900 }
901 }
902 else {
903 PTDeletePoint(p1, &(elt->ptlist));
904 }
905
906 DISScreenAdd(elt, pixmask | csetmask);
907 DBAddSet(elt);
908
909 CP();
910 CHANGED = TRUE;
911 } /* end LGMPoint */
912
913
914 /*
915 * This routine allows users to leave gripe messages or report
916 * bugs to the maintainer. Mail is invoked via the defined constant GRIPE.
917 */
LGGripe()918 LGGripe()
919 {
920 TxPutMsg("mail gripes to opcode@monet");
921 } /* end LGGripe */
922
923
924 /*
925 * This routine controls the size of the point that is displayed.
926 * The sizes available are Artmode in which a small (3 x 3) point is displayed
927 * with no number and regular (non-Artmode).
928 */
LGLittlePoint()929 LGLittlePoint()
930 {
931 register POINT *plist;
932 register sp;
933 register i = 0;
934
935 GRBlankPoints(POINTLIST);
936 if ((sp = SHOWPOINTS) != 0) /* turn off show points */
937 CSP();
938 Artmode = !Artmode;
939
940 plist = POINTLIST;
941 while (!Nullpoint(plist)) {
942 GRDisplayPoint(plist->x, plist->y, i++);
943 plist = PTNextPoint(plist);
944 }
945
946 if (sp != 0) /* turn on show points */
947 LGShowPoints();
948
949 if (Artmode)
950 MNUnHighLt(HiArtMode);
951 else
952 MNHighLt(HiArtMode);
953 } /* end LGLittlePoint */
954
955
956 /*
957 * This routine looks at the command line for parameters to set
958 * the current Font.
959 */
LGFont(font)960 LGFont(font)
961 int font;
962 {
963 MNUnHighLt(HiFont[CFONT-1]);
964 CFONT = font;
965 MNHighLt(HiFont[CFONT-1]);
966 } /* end LGFont */
967
968
LGFont1()969 LGFont1()
970 {
971 LGFont(1);
972 }
973
974
LGFont2()975 LGFont2()
976 {
977 LGFont(2);
978 }
979
980
LGFont3()981 LGFont3()
982 {
983 LGFont(3);
984 }
985
986
LGFont4()987 LGFont4()
988 {
989 LGFont(4);
990 }
991
992
993 /*
994 * This routine changes the current character size.
995 */
LGSize(size)996 LGSize(size)
997 int size;
998 {
999 MNUnHighLt(HiSize[CSIZE-1]);
1000 CSIZE = size;
1001 MNHighLt(HiSize[CSIZE-1]);
1002 } /* end LGSize */
1003
1004
LGSize1()1005 LGSize1()
1006 {
1007 LGSize(1);
1008 }
1009
1010
LGSize2()1011 LGSize2()
1012 {
1013 LGSize(2);
1014 }
1015
1016
LGSize3()1017 LGSize3()
1018 {
1019 LGSize(3);
1020 }
1021
1022
LGSize4()1023 LGSize4()
1024 {
1025 LGSize(4);
1026 }
1027
1028
1029 /*
1030 * This routine changes the current stipple pattern.
1031 */
LGStipple(stipple)1032 LGStipple(stipple)
1033 int stipple;
1034 {
1035 MNUnHighLt(HiStipple[CSTIPPLE-1]);
1036 CSTIPPLE = stipple;
1037 MNHighLt(HiStipple[CSTIPPLE-1]);
1038 } /* end LGStipple */
1039
1040
LGStipple1()1041 LGStipple1()
1042 {
1043 LGStipple(1);
1044 }
1045
1046
LGStipple2()1047 LGStipple2()
1048 {
1049 LGStipple(2);
1050 }
1051
1052
LGStipple3()1053 LGStipple3()
1054 {
1055 LGStipple(3);
1056 }
1057
1058
LGStipple4()1059 LGStipple4()
1060 {
1061 LGStipple(4);
1062 }
1063
1064
LGStipple5()1065 LGStipple5()
1066 {
1067 LGStipple(5);
1068 }
1069
1070
LGStipple6()1071 LGStipple6()
1072 {
1073 LGStipple(6);
1074 }
1075
1076
LGStipple7()1077 LGStipple7()
1078 {
1079 LGStipple(7);
1080 }
1081
1082
LGStipple8()1083 LGStipple8()
1084 {
1085 LGStipple(8);
1086 }
1087
1088
1089 /*
1090 * Toggle line style
1091 */
LGLineStyle()1092 LGLineStyle()
1093 {
1094 if (SymbolicLines = !SymbolicLines)
1095 MNUnHighLt(HiLineStyle);
1096 else
1097 MNHighLt(HiLineStyle);
1098
1099 SHUpdate();
1100 } /* end LGLineStyle */
1101
1102
LGPan()1103 LGPan()
1104 {
1105 if (SEQ < 1) {
1106 error("need one point");
1107 return;
1108 }
1109
1110 LGdopan(POINTLIST->x, POINTLIST->y);
1111 }
1112
1113
1114 /*
1115 * Make (wx, wy) center of Gremlin window.
1116 */
LGdopan(wx,wy)1117 LGdopan(wx, wy)
1118 float wx, wy;
1119 {
1120 float cx, cy;
1121 register tx, ty;
1122
1123 CP(); /* eat points first */
1124
1125 cx = SUN_XORIGIN + (pix_size.r_width >> 1); /* window x center */
1126 cy = SUN_YORIGIN - (pix_size.r_height >> 1); /* window y center */
1127
1128 tx = (int) (wx - cx); /* x translation */
1129 ty = (int) (wy - cy); /* y translation */
1130
1131 tx += (tx < 0) ? -1 : 1; /* fudge factor */
1132 ty += (ty < 0) ? -1 : 1;
1133
1134 SUN_XORIGIN += (tx / Gridsize) * Gridsize;
1135 SUN_YORIGIN += (ty / Gridsize) * Gridsize;
1136
1137 SHUpdate();
1138 } /* end LGPan */
1139
1140
1141 /*
1142 * Pan to absolute center of picture.
1143 * Invoked by the middle button on the PAN icon.
1144 */
LGMPan()1145 LGMPan()
1146 {
1147 register ELT *elt;
1148 register POINT *point;
1149 float minx, miny, maxx, maxy;
1150
1151 if (DBNullelt(PICTURE)) {
1152 error("empty picture");
1153 return;
1154 }
1155
1156 elt = PICTURE;
1157 minx = maxx = elt->ptlist->x;
1158 miny = maxy = elt->ptlist->y;
1159
1160 while (!DBNullelt(elt)) {
1161 point = elt->ptlist;
1162
1163 while (!Nullpoint(point)) {
1164 MINMAX(minx, maxx, point->x);
1165 MINMAX(miny, maxy, point->y);
1166 point = PTNextPoint(point);
1167 }
1168
1169 elt = DBNextElt(elt);
1170 }
1171
1172 LGdopan(maxx - ((maxx - minx) / 2.0), maxy - ((maxy - miny) / 2.0));
1173 }
1174