1 /* @(#)short.c 1.3 12/30/83
2 *
3 * Copyright -C- 1982 Barry S. Roitblat
4 *
5 *
6 * This file contains routines to implement the short commands
7 * of the gremlin picture editor.
8 *
9 */
10
11 #include "gremlin.h"
12 #include "grem2.h"
13 #include <signal.h>
14 #include <sgtty.h>
15
16 /* imports from graphics files */
17
18 extern GRVector(), GRPutText();
19 extern GRCurve();
20 extern GRClear();
21 extern int GRArc();
22 extern charxsize, charysize;
23
24 /* imports from display.c */
25
26 extern DISScreenAdd(), DISScreenErase();
27 extern DISDisplaySet(), DISEraseSet(), DISClearSetDisplay();
28
29 /* imports from database files */
30
31 extern ELT *DBInit(), *DBCreateElt();
32 extern DBDelete(), DBGravitate(), DBClearElt();
33 extern ELT *DBCopy();
34 extern DBXform(), DBBounded();
35 extern DBAddSet(), DBClearSet();
36 extern POINT *PTInit(), *PTMakePoint();
37 extern PTDeletePoint();
38
39 /* imports from long.c */
40
41 extern LGIncludeSet();
42
43 /* imports from menu.c */
44
45 extern MNHighLt(), MNUnHighLt();
46 extern HiMen[], HiFont[], HiBrush[], HiMode[];
47
48 int adj[4] = { 0, 0, 1, 2 };
49
50 /* imports from textio.c */
51
52 extern TxMsgOK(), TxPutString(), TxGetLine(), TxRedisplay(), TxPutMsg();
53 extern char TxGetChar();
54 extern TXFIELD TAlign, TAdjust, TBrush, TFont, TGravity, TCSize;
55 extern TXFIELD TEdit, TJustmode;
56
57 /* imports from c */
58
59 extern char *malloc();
60 extern char *sprintf();
61
62 /* imports from main.c */
63
64 extern globinit(); /* global initialization routine */
65 extern ELT *PICTURE; /* current PICTURE database */
66 extern ELT *cset; /* current set database */
67 extern CBRUSH, CSIZE, CFONT; /* current brush, size, font */
68 extern CJUST; /* text justification mode */
69 extern Gridon; /* grid mode flag */
70 extern Orientation; /* orientation of workspace */
71 extern Alignment; /* point alignment indicator */
72 extern float PX, PY; /* cursor coordinates */
73 extern float Lastx, Lasty; /* previous cursor coordinates */
74 extern SEQ; /* point sequence number */
75 extern char *Editfile; /* current edit file */
76 extern POINT *POINTLIST; /* accumulated point list */
77 extern Adjustment; /* point adjustment mode */
78 extern GravityOn; /* gravity mode flag */
79 extern Consume; /* point clear flag */
80 extern CHANGED; /* PICTURE changed flag */
81 extern ELT *MEN[]; /* pointers for user symbols */
82 extern POINT MENPOINT[]; /* pointers used fo user symbols */
83 extern cmdbuf[]; /* line buffer for commands */
84 extern ELT arhead; /* arrow head template */
85 extern char *textpos[], *dispmode[];/* text positioning modes */
86 extern int textmode[]; /* text positioning */
87
88
89 extern SHUpdate(), SHDrawArc(), SHDrawCurve(), SHCopy(), SHRedis(),
90 SHDefineSet(), SHErase(), SHSetArea(), SHGravity(),
91 SHGrid(), SHRotate(), SHScale(), SHTranslate(), SHShellEsc(),
92 SHDrawVector(), SHMAdjust(), SHBox(), SHArrow(),
93 SHSave1(), SHSave2(), SHSave3(), SHSave4();
94
95 /* The following two arrays define the short commands and the routines
96 * that process them.
97 */
98 static char shcmds[] = { '\14', '!', '1', '2', '3', '4', 'a', 'b',
99 'c', 'd', 'e', 'f', 'g', 'l', 'q', 'r',
100 's', 't', 'v', 'w', 'x', 'z', '\0'};
101 static (*(shrtns[]))() = {
102 SHUpdate, /* redraw screen */
103 SHShellEsc, /* shell escape */
104 SHSave1, /* save user symbol */
105 SHSave2, /* save user symbol */
106 SHSave3, /* save user symbol */
107 SHSave4, /* save user symbol */
108 SHDrawArc, /* draw arc */
109 SHDrawCurve, /* draw curve */
110 SHCopy, /* copy current set */
111 SHDefineSet, /* define current set */
112 SHErase, /* erase elements */
113 SHSetArea, /* select area for current set */
114 SHGravity, /* gravity */
115 SHRedis, /* text screen redisplay */
116 SHGrid, /* toggle grid display */
117 SHRotate, /* rotate current set */
118 SHScale, /* scale current set */
119 SHTranslate, /* translate current set */
120 SHDrawVector, /* draw vectors */
121 SHArrow, /* arrowhead */
122 SHBox, /* rectangle from two points */
123 SHMAdjust}; /* manhattan adjust */
124
125
126 int
SHLookup(c,table)127 SHLookup(c, table)
128 char c; /* Pointer to a char to be looked up */
129 char table[]; /* Pointer to an array of characters
130 * which are the valid commands. The array
131 * must be sorted by ascii value.
132 */
133
134 /*---------------------------------------------------------
135 * SHLookup searches a table of characters to find one that matches a
136 * the given character.
137 *
138 * Results: If c is a valid command character, its index is
139 * returned, otherwise, if c is the null command, -2 is returned
140 * else -1 is returned.
141 *
142 * Side Effects: None.
143 *
144 * (Modified from software written by John Ousterhout for the caesar
145 * program)
146 *---------------------------------------------------------
147 */
148
149 {
150 int index;
151
152 if ((c == ' ') || (c == '\0')) return(-2);
153 for (index=0; table[index] != '\0'; index++)
154 {
155 if (table[index] == c) return(index);
156 if (table[index] > c) return(-1);
157 }
158 return(-1);
159 } /* end SHLookup */
160
161
SHCommand(command)162 SHCommand(command)
163 char *command;
164
165 /*---------------------------------------------------------
166 * This routine reads in, looks up, and executes a long command.
167 *
168 * Results: None.
169 *
170 * Side Effects:
171 * Depends on the command that is invoked.
172 *---------------------------------------------------------
173 */
174
175 {
176 int index;
177 index = SHLookup(*command, shcmds);
178 if (index == -2) return;
179 if (index >= 0)
180 {
181
182 (*(shrtns[index]))();
183 }
184 else
185 {
186 error("no such command");
187 }
188 } /* end SHCommand */
189
190 static char nopnt[18] = "not enough points";
191 static char noset[15] = "no current set";
192
SHDrawVector()193 SHDrawVector()
194 /*
195 * This routine creates and displays a VECTOR element from the
196 * points previously specified.
197 */
198
199 {
200 ELT *e1;
201 POINT *plist, *p1, *p2;
202 char *txt;
203
204 if (SEQ < 2) /* not enough points */
205 {
206 error(nopnt);
207 return;
208 }
209 DBClearSet(); /* Clear current set in preparation */
210 DISClearSetDisplay(); /* for making this the new one */
211 GRsetwmask(linemask | setmask);
212 plist = PTInit();
213 p1 = POINTLIST;
214 (void) PTMakePoint(p1->x, p1->y, &plist);
215 p2 = PTNextPoint(p1);
216 while ( !Nullpoint(p2) )
217 {
218 (void) PTMakePoint(p2->x, p2->y, &plist);
219 GRVector(p1, p2, CBRUSH);
220 p1 = p2;
221 p2 = PTNextPoint(p1);
222 } /* end while */;
223 txt = malloc(1);
224 *txt = '\0';
225 e1 = DBCreateElt(VECTOR, plist, CBRUSH, 0, txt, &PICTURE);
226 DBAddSet(e1);
227 CHANGED = TRUE;
228 } /* end SHDrawVector */
229
230 #define twoPi 6.2832
231
SHDrawArc()232 SHDrawArc()
233 /*
234 * This routine creates and displays an ARC element based on the
235 * points previously defined. If 3 or more points are defined, the
236 * extent of the arc is calculated as the angle formed by the
237 * respective lines through the second and third points and the first
238 * point. If only 2 points are specified, a full circle is drawn.
239 */
240
241 {
242 ELT *e1;
243 POINT *plist, *p1, *p2;
244 char *txt;
245 double a1, a2, angle, radius;
246 int stat;
247
248 if (SEQ < 2) /* not enough points */
249 {
250 error(nopnt);
251 return;
252 }
253 plist = PTInit();
254 p1 = POINTLIST;
255 p2 = PTNextPoint(p1);
256 radius = sqrt( pow((p2->x - p1->x), 2.0)
257 + pow((p2->y - p1->y), 2.0));
258 if (SEQ == 2) /* draw full circle */
259 {
260 angle = 0;
261 /* Add extra positioning points */
262 (void) PTMakePoint(p1->x, p1->y, &plist);
263 (void) PTMakePoint(p2->x, p2->y, &plist);
264 (void) PTMakePoint(p1->x, p1->y + radius, &plist);
265 (void) PTMakePoint(p1->x, p1->y - radius, &plist);
266 (void) PTMakePoint(p1->x + radius, p1->y, &plist);
267 (void) PTMakePoint(p1->x - radius, p1->y, &plist);
268 } /* end if */
269 else
270 {
271 (void) PTMakePoint(POINTLIST->x, POINTLIST->y, &plist);
272 p1 = PTNextPoint(POINTLIST);
273 (void) PTMakePoint(p1->x, p1->y, &plist);
274 p2 = PTNextPoint(p1);
275 a1 = atan2((p1->x - POINTLIST->x), (p1->y - POINTLIST->y));
276 a2 = atan2((p2->x - POINTLIST->x), (p2->y - POINTLIST->y));
277 angle = a1 - a2;
278 if (angle < 0.0) angle += twoPi;
279
280 /* Set second point to lie on arc */
281 (void) PTMakePoint((radius * sin(a2) + POINTLIST->x),
282 (radius * cos(a2) + POINTLIST->y),
283 &plist);
284
285 angle *= 360.0/twoPi; /* convert to degrees */
286 };
287 p1 = PTNextPoint(POINTLIST);
288 DBClearSet(); /* Clear current set, this element becomes */
289 DISClearSetDisplay(); /* the new current set */
290 GRsetwmask(linemask | setmask);
291 stat = GRArc(POINTLIST, p1, angle, CBRUSH);
292 if (stat > -1)
293 {
294 txt = malloc(1);
295 *txt = '\0';
296 e1 = DBCreateElt(ARC, plist, CBRUSH, (int) (angle + 0.5),
297 txt, &PICTURE);
298 DBAddSet(e1);
299 CHANGED = TRUE;
300 }
301 } /* end SHDrawARc */
302
303
SHDrawCurve()304 SHDrawCurve()
305 /*
306 * This routine creates and displays a curve using points previously
307 * defined. This is dependent on DISCurve which is not yet implemented.
308 */
309
310 {
311 ELT *e1;
312 char *txt;
313 POINT *p1, *p2, *plist;
314 int stat;
315
316 stat = 0;
317 if (SEQ < 2) /* not enough points */
318 {
319 error("need at least 2 points");
320 return;
321 }
322 plist = PTInit();
323 p1 = POINTLIST;
324 (void) PTMakePoint(p1->x, p1->y, &plist);
325 p2 = PTNextPoint(p1);
326 while ( !Nullpoint(p2) )
327 {
328 (void) PTMakePoint(p2->x, p2->y, &plist);
329 p1 = p2;
330 p2 = PTNextPoint(p1);
331 } /* end while */;
332 DBClearSet(); /* Clear current set, this element */
333 DISClearSetDisplay(); /* the new current set */
334 GRsetwmask(linemask | setmask);
335 stat = GRCurve(plist, CBRUSH);
336 if (stat != 0) /* bad knots */
337 {
338 error("too many consecutive knots at same place");
339 return;
340 }
341 txt = malloc(1);
342 *txt = '\0';
343 e1 = DBCreateElt(CURVE, plist, CBRUSH, 0, txt, &PICTURE);
344 DBAddSet(e1);
345 CHANGED = TRUE;
346 } /* end SHDrawCurve */
347
SHErase()348 SHErase()
349 /*
350 * This routine erases selected elements from the screen and deletes
351 * them from the picture database.
352 */
353
354 {
355 ELT *e1;
356
357 while ( !DBNullelt(cset) ) /* delete elements in current set */
358 {
359 DISScreenErase(cset, (linemask | setmask));
360 e1 = DBNextofSet(cset);
361 DBDelete(cset, &PICTURE);
362 cset = e1;
363 };
364 CHANGED = TRUE;
365 } /* end SHErase */
366
367
SHGravity()368 SHGravity()
369 /*
370 * This routine toggles the gravity mode.
371 */
372
373 {
374 if (GravityOn)
375 {
376 MNUnHighLt(HiMode[3]);
377 GravityOn = FALSE;
378 TxPutString(&TGravity, "OFF");
379 }
380 else
381 {
382 MNHighLt(HiMode[3], hicolor);
383 GravityOn = TRUE;
384 TxPutString(&TGravity, " ON");
385 }
386 Consume = FALSE;
387 } /* End GravityOn */
388
SHGrid()389 SHGrid()
390 /*
391 * This routine toggles the display of the grid
392 */
393
394 {
395 if (Gridon)
396 {
397 Gridon = FALSE;
398 GRBlankGrid();
399 }
400 else
401 {
402 Gridon = TRUE;
403 GRDisplayGrid();
404 }
405 Consume = FALSE;
406 } /* end SHGrid */
407
408
SHMAdjust()409 SHMAdjust()
410 /*
411 * Manhattan Adjust -
412 * This routine toggles the adjustment mode.
413 */
414
415 {
416 if (Adjustment == MAN)
417 {
418 MNUnHighLt(HiMode[adj[MAN]]);
419 Adjustment = NOADJ;
420 TxPutString(&TAdjust, "NO ADJUSTMENT");
421 }
422 else
423 {
424 MNUnHighLt(HiMode[adj[Adjustment]]);
425 MNHighLt(HiMode[adj[MAN]], hicolor);
426 Adjustment = MAN;
427 TxPutString(&TAdjust, " MANHATTAN ");
428 }
429 Consume = FALSE;
430 }
431
432
SHDefineSet()433 SHDefineSet()
434 /*
435 * This routine defines the current set based upon previously
436 * defined points to select elements. The action is performed by
437 * clearing the current set and calling LGIncludeSet.
438 */
439
440 {
441 DBClearSet();
442 DISClearSetDisplay();
443 LGIncludeSet("");
444 } /* end SHDefineSet */
445
SHSetArea()446 SHSetArea()
447 /*
448 * This routine defines the current set by selecting all elements
449 * bounded by a rectangle whose diagonal is defined by specifed points.
450 */
451
452 {
453 ELT *e1;
454 POINT *p1;
455 float x1, y1, x2, y2;
456
457 if (SEQ < 2)
458 {
459 error(nopnt);
460 return;
461 }
462 DBClearSet();
463 DISClearSetDisplay();
464 x1 = POINTLIST->x;
465 y1 = POINTLIST->y;
466 p1 = PTNextPoint(POINTLIST);
467 x2 = p1->x;
468 y2 = p1->y;
469 e1 = PICTURE;
470 while ( !DBNullelt(e1) )
471 {
472 if ( DBBounded(e1, x1, y1, x2, y2) )
473 {
474 DBAddSet(e1);
475 DISDisplaySet(e1);
476 } /* end if */
477 e1 = DBNextElt(e1);
478 } /* end while */
479 } /* end SHSetArea */
480
481
SHTranslate()482 SHTranslate()
483 /*
484 * This routine translates the elements in the current set as defined
485 * by points. The translation is accomplished by defining a transformation
486 * matrix and calling DBXform.
487 */
488
489 {
490 ELT *e1;
491 POINT *p1;
492 float xmat[3][2];
493
494 if (SEQ < 2) /* not enough points */
495 {
496 error(nopnt);
497 return;
498 }
499 if (DBNullelt(cset))
500 {
501 error(noset);
502 return;
503 }
504 p1 = PTNextPoint(POINTLIST);
505 xmat[0][0] = xmat[1][1] = 1; /* set up translation matrix */
506 xmat[1][0] = xmat[0][1] = 0;
507 xmat[2][0] = p1->x - POINTLIST->x;
508 xmat[2][1] = p1->y - POINTLIST->y;
509 e1 = cset;
510 while ( !DBNullelt(e1) )
511 {
512 DISScreenErase(e1, (linemask | setmask));
513 TxMsgOK();
514 DBXform(e1, xmat, &PICTURE);
515 DISScreenAdd(e1, (linemask | setmask));
516 e1 = DBNextofSet(e1);
517 } /* end while */
518 CHANGED = TRUE;
519 } /* end SHTranslate */
520
521
SHCopy()522 SHCopy()
523 /*
524 * This routine copies the elements in the current set as defined
525 * by points. To copy, the current set pointer is cleared so that new
526 * elements as added by DBCopy can be used to comprise the new current
527 * set. A pointer is maintained to the old current set which is traversed
528 * to determine the elements to be copied. This process continues for all
529 * points specified.
530 *
531 * NOTE: This assumes that the DBClearSet routine does not alter the
532 * pointers between elements in the set (which is currently true),
533 * and must be changed it this does not hold.
534 */
535
536 {
537 ELT *e1, *e2;
538 POINT *p1, *p2;
539 float xmat[3][2];
540
541 if (SEQ < 2) /* not enough points */
542 {
543 error(nopnt);
544 return;
545 }
546 if (DBNullelt(cset))
547 {
548 error(noset);
549 return;
550 }
551 p1 = POINTLIST;
552 p2 = PTNextPoint(POINTLIST);
553 while ( !Nullpoint(p2) )
554 {
555 xmat[0][0] = xmat[1][1] = 1; /* set up translation matrix */
556 xmat[1][0] = xmat[0][1] = 0;
557 xmat[2][0] = p2->x - p1->x;
558 xmat[2][1] = p2->y - p1->y;
559 DISClearSetDisplay();
560 e1 = cset;
561 DBClearSet(); /* Dependent on Clearset preserving pointers */
562 while ( !DBNullelt(e1) )
563 {
564 e2 = DBCopy(e1, xmat, &PICTURE);
565 DBAddSet(e2);
566 DISScreenAdd(e2, (linemask | setmask));
567 e1 = DBNextofSet(e1);
568 } /* end while ! null elt */
569 p1 = p2;
570 p2 = PTNextPoint(p2);
571 } /* end while ! null point */
572 CHANGED = TRUE;
573 } /* end SHCopy */
574
575
SHRotate()576 SHRotate()
577 /*
578 * This routine rotates the elements in the current set as defined
579 * by points. The rotation is accomplished by defining a transformation
580 * matrix and calling DBXform.
581 */
582
583 {
584 ELT *e1;
585 POINT pos, *p1, *p2;
586 float xmat[3][2], angle, s, c;
587 int i, j;
588
589 if (SEQ < 3) /* not enough points */
590 {
591 error(nopnt);
592 return;
593 }
594 if (DBNullelt(cset))
595 {
596 error(noset);
597 return;
598 }
599 p1 = PTNextPoint(POINTLIST); /* calculate rotation angle */
600 p2 = PTNextPoint(p1);
601 angle = (float) atan2((p2->x - POINTLIST->x),(p2->y - POINTLIST->y))
602 -(float) atan2((p1->x - POINTLIST->x),(p1->y - POINTLIST->y));
603 s = (float) sin(angle);
604 c = (float) cos(angle);
605
606 /* Define transformation matrix to translate set to origin, rotate,
607 and translate back. */
608
609 xmat[0][0] = c;
610 xmat[0][1] = -s;
611 xmat[1][0] = s;
612 xmat[1][1] = c;
613 xmat[2][0] = (-c) * POINTLIST->x - s * POINTLIST->y + POINTLIST->x;
614 xmat[2][1] = (-c) * POINTLIST->y + s * POINTLIST->x + POINTLIST->y;
615 e1 = cset;
616 while ( !DBNullelt(e1) )
617 {
618 DISScreenErase(e1, (linemask | setmask));
619 TxMsgOK();
620 DBXform(e1, xmat, &PICTURE);
621 if (TEXT(e1->type))
622 {
623 GRsetwmask(textmask | setmask);
624 p1 = e1->ptlist;
625 GRPutText(e1->type, p1, e1->brushf,
626 e1->size,e1->textpt, &pos);
627 i= strlen(e1->textpt);
628 p2 = PTInit();
629 (void) PTMakePoint(p1->x, p1->y, &p2);
630 /* add extra positioning points */
631 (void) PTMakePoint(pos.x, pos.y, &p2);
632 (void) PTMakePoint(pos.x + i * charxsize / 2,
633 pos.y, &p2);
634 (void) PTMakePoint(pos.x + i * charxsize,
635 pos.y, &p2);
636 e1->ptlist = p2;
637 } /* end if TEXT */
638 else
639 DISScreenAdd(e1, (linemask | setmask));
640 e1 = DBNextofSet(e1);
641 } /* end while */
642 CHANGED = TRUE;
643 } /* end SHRotate */
644
645
SHScale()646 SHScale()
647 /*
648 * This routine scales the elements in the current set as defined
649 * by points. The scaling is accomplished by defining a transformation
650 * matrix and calling DBXform.
651 */
652
653 {
654 ELT *e1;
655 POINT pos, *p1, *p2;
656 float xmat[3][2], d1, d2, scalex, scaley;
657 int i, j;
658
659 if (SEQ < 3) /* not enough points */
660 {
661 error(nopnt);
662 return;
663 }
664 if (DBNullelt(cset))
665 {
666 error(noset);
667 return;
668 }
669 p1 = PTNextPoint(POINTLIST);
670 p2 = PTNextPoint(p1);
671 d1 = sqrt( pow((p1->x - POINTLIST->x), 2.0)
672 + pow((p1->y - POINTLIST->y), 2.0));
673 d2 = sqrt( pow((p2->x - POINTLIST->x), 2.0)
674 + pow((p2->y - POINTLIST->y), 2.0));
675 if (d1 == 0)
676 {
677 error("infinite scale");
678 return;
679 }
680 scalex = scaley = d2 / d1;
681
682 /* create transformation matrix to translate set to origin,
683 performaing the scaling and translating back */
684
685 xmat[0][0] = scalex;
686 xmat[1][1] = scaley;
687 xmat[1][0] = xmat[0][1] = 0;
688 xmat[2][0] = - POINTLIST->x * (scalex - 1.0);
689 xmat[2][1] = - POINTLIST->y * (scaley - 1.0);
690 e1 = cset;
691 while ( !DBNullelt(e1) )
692 {
693 DISScreenErase(e1, (linemask | setmask));
694 TxMsgOK();
695 DBXform(e1, xmat, &PICTURE);
696 if (TEXT(e1->type))
697 {
698 GRsetwmask(textmask | setmask);
699 p1 = e1->ptlist;
700 GRPutText(e1->type, p1, e1->brushf,
701 e1->size,e1->textpt, &pos);
702 i= strlen(e1->textpt);
703 p2 = PTInit();
704 (void) PTMakePoint(p1->x, p1->y, &p2);
705 /* add extra positioning points */
706 (void) PTMakePoint(pos.x, pos.y, &p2);
707 (void) PTMakePoint(pos.x + i * charxsize / 2,
708 pos.y, &p2);
709 (void) PTMakePoint(pos.x + i * charxsize,
710 pos.y, &p2);
711 e1->ptlist = p2;
712 } /* end if TEXT */
713 else
714 DISScreenAdd(e1, (linemask | setmask));
715 e1 = DBNextofSet(e1);
716 } /* end while */
717 CHANGED = TRUE;
718 } /* end SHScale */
719
720
SHUpdate()721 SHUpdate()
722 /*
723 * This routine redraws the graphics screen by clearing the screen ,
724 * redisplaying the menu and adding each element back to the display.
725 */
726
727 {
728 ELT *e1;
729 int i;
730
731 GRClear(linemask | setmask | textmask);
732 MNDisplayMenu();
733 e1 = PICTURE;
734 while ( !DBNullelt(e1) )
735 {
736 DISScreenAdd(e1, linemask);
737 e1 = DBNextElt(e1);
738 };
739 e1 = cset;
740 while ( !DBNullelt(e1) )
741 {
742 DISScreenAdd(e1, setmask);
743 e1 = DBNextofSet(e1);
744 };
745 if ( Adjustment != NOADJ) MNHighLt(HiMode[adj[Adjustment]], hicolor);
746 if (GravityOn) MNHighLt(HiMode[3], hicolor); /* re highlight */
747 MNHighLt(HiFont[CFONT-1], hicolor); /* selected menu */
748 MNHighLt(HiBrush[CBRUSH-1], hicolor); /* menu attributes */
749 for (i = 0; i < NUSER; ++i)
750 if ( !DBNullelt(MEN[i]) ) MNHighLt(HiMen[i], hicolor);
751 Consume = FALSE;
752 } /* end SHUpdate */
753
754
SHRedis()755 SHRedis()
756 /*
757 * This routine is used to redisplay the text screen.
758 * It clears the screen, then redisplays the text and each of the
759 * defined fields.
760 */
761
762 {
763 char string[4];
764
765 TxRedisplay();
766 TxPutString(&TEdit, Editfile);
767 (void) sprintf(string,"%1d",CBRUSH);
768 TxPutString(&TBrush,string);
769 (void) sprintf(string, "%1d",CFONT);
770 TxPutString(&TFont,string);
771 (void) sprintf(string, "%1d",CSIZE);
772 TxPutString(&TCSize,string);
773 TxPutString(&TJustmode,dispmode[CJUST]);
774 (void) sprintf(string, "%3d",Alignment);
775 TxPutString(&TAlign,string);
776 (void) sprintf(string,"%1d",CBRUSH);
777 TxPutString(&TBrush,string);
778 if (GravityOn) TxPutString(&TGravity, " ON");
779 else TxPutString(&TGravity, "OFF");
780 switch(Adjustment)
781 {
782 case NOADJ: TxPutString(&TAdjust, "NO ADJUSTMENT");
783 break;
784 case HORZ: TxPutString(&TAdjust, " HORIZONTAL ");
785 break;
786 case VERT: TxPutString(&TAdjust, " VERTICAL ");
787 break;
788 case MAN: TxPutString(&TAdjust, " MANHATTAN ");
789 break;
790 } /* end switch */;
791 Consume = FALSE;
792 } /* end SHRedis */
793
794
SHShellEsc()795 SHShellEsc()
796 /*
797 * This routine performs a shell escape through the c 'system'
798 * function. It first retrieves the command line through TxGetLine.
799 */
800
801 {
802 char line[80];
803
804 TxGetLine("!",line,80);
805 TxClose(); /* Restore text terminal to 'normal' state */
806 (void) system(line); /* do command */
807 /* allow time for user to digest command */
808 printf("Type <cr> to continue");
809 (void) fflush(stdout);
810 line[1] = TxGetChar();
811 SHRedis(); /* reclaim terminal */
812 } /* end ShellEsc */
813
814
savemen(sym)815 static savemen(sym)
816 int sym;
817 /*
818 * This local routine stores the current set in the specified
819 * user symbol.
820 */
821
822 {
823 ELT *elist;
824 float xmat[3][2];
825
826 xmat[0][0] = xmat[1][1] = 1; /* set up copy transformation */
827 xmat[0][1] = xmat[1][0] = 0; /* matrix for no */
828 xmat[2][0] = xmat[2][1] = 0; /* transformation */
829 while ( !DBNullelt(MEN[sym]) )
830 { /* clear out existing symbol */
831 elist = DBNextElt(MEN[sym]);
832 DBClearElt(MEN[sym]);
833 MEN[sym] = elist;
834 };
835 elist = cset; /* copy current set to symbol */
836 while ( !DBNullelt(elist) )
837 {
838 (void) DBCopy(elist, xmat, &(MEN[sym]));
839 elist = DBNextofSet(elist);
840 } /* end while */;
841 if (SEQ == 0) /* no positioning points */
842 {
843 MENPOINT[sym].x = 0;
844 MENPOINT[sym].y = 0;
845 }
846 else
847 {
848 MENPOINT[sym].x = POINTLIST->x;
849 MENPOINT[sym].y = POINTLIST->y;
850 }
851 if ( !DBNullelt(MEN[sym]) ) MNHighLt(HiMen[sym], hicolor);
852 else MNUnHighLt(HiMen[sym]);
853 CHANGED = TRUE;
854 } /* end savemen */
855
SHSave1()856 SHSave1()
857 /*
858 * This routine saves the current set in user symbol 1 by
859 * calling savemen.
860 */
861
862 {
863 savemen(0);
864 }
865
SHSave2()866 SHSave2()
867 /*
868 * This routine saves the current set in user symbol 2 by
869 * calling savemen.
870 */
871
872 {
873 savemen(1);
874 }
875
SHSave3()876 SHSave3()
877 /*
878 * This routine saves the current set in user symbol 3 by
879 * calling savemen.
880 */
881
882 {
883 savemen(2);
884 }
885
SHSave4()886 SHSave4()
887 /*
888 * This routine saves the current set in user symbol 4 by
889 * calling savemen.
890 */
891
892 {
893 savemen(3);
894 }
895
896
897
SHBox()898 SHBox()
899 /*
900 * This routine creates and displays a rectangle whose diagonal is
901 * defined by two points. The routine uses the coordinates of these
902 * points to define a VECTOR element with the appropriate vertices.
903 */
904
905 {
906 POINT *plist, *p1, *p2;
907 char *txt;
908 ELT *e1;
909
910 if (SEQ < 2)
911 {
912 error("not enough points");
913 return;
914 }
915 p1 = POINTLIST;
916 p2 = PTNextPoint(p1);
917 plist = PTInit(); /* create points for vector element which defines
918 the rectangle */
919 (void) PTMakePoint(p1->x, p1->y, &plist);
920 (void) PTMakePoint(p1->x, p2->y, &plist);
921 (void) PTMakePoint(p2->x, p2->y, &plist);
922 (void) PTMakePoint(p2->x, p1->y, &plist);
923 (void) PTMakePoint(p1->x, p1->y, &plist); /* close rectangle */
924 txt = malloc(1);
925 *txt = '\0';
926 DBClearSet(); /* clear old set in preparation to make */
927 DISClearSetDisplay(); /* the new current set */
928 e1 = DBCreateElt(VECTOR, plist, CBRUSH, 0, txt, &PICTURE);
929 DBAddSet(e1);
930 DISScreenAdd(e1, (linemask | setmask));
931 CHANGED = TRUE;
932 } /* end LGBox */
933
SHArrow()934 SHArrow()
935 /*
936 * This routine draws arrow heads by 'copying' the arrow head template
937 * into the picture appropriately transformed.
938 */
939
940 {
941 ELT *e1;
942 POINT p1, *p2;
943 float xmat[3][2], angle, s, c;
944
945 if (SEQ < 2) /* not enough points */
946 {
947 error(nopnt);
948 return;
949 }
950 p1.x = POINTLIST->x - 1;
951 p1.y = POINTLIST->y;
952 p2 = PTNextPoint(POINTLIST);
953 angle = (float) atan2((p2->x - POINTLIST->x),(p2->y - POINTLIST->y))
954 -(float) atan2((p1.x - POINTLIST->x),(p1.y - POINTLIST->y));
955 s = (float) sin(angle);
956 c = (float) cos(angle);
957
958 /* Define transformation matrix to translate element from origin
959 and rotate. */
960
961 xmat[0][0] = c;
962 xmat[0][1] = -s;
963 xmat[1][0] = s;
964 xmat[1][1] = c;
965 xmat[2][0] = POINTLIST->x;
966 xmat[2][1] = POINTLIST->y;
967
968 DBClearSet(); /* clear old set in preparation to make */
969 DISClearSetDisplay(); /* the new current set */
970 arhead.brushf = CBRUSH;
971 e1 = DBCopy(&arhead, xmat, &PICTURE);
972 DBAddSet(e1);
973 DISScreenAdd(e1, (linemask | setmask));
974 CHANGED = TRUE;
975 } /* end SHArrow */
976