1 /* @(#)long1.c 1.2 04/18/83
2 *
3 * Copyright -C- 1982 Barry S. Roitblat
4 *
5 *
6 * This file contains routines to implement the long text commands
7 * of the gremlin PICTURE editor.
8 *
9 */
10
11 #include "gremlin.h"
12 #include "grem2.h"
13 #include <ctype.h>
14
15 /* imports from config.c */
16
17 extern char GMailCommand[];
18
19 /* imports from graphics files */
20
21 extern GRVector(), GRArc(), GRPutText();
22 extern GRDisplayPoint(), GRDeletePoint(), GRBlankPoints();
23 extern charxsize, charysize;
24 extern artmode; /* indication of point display size */
25
26 /* imports from display.c */
27
28 extern DISScreenAdd(), DISScreenErase();
29 extern DISDisplaySet(), DISEraseSet(), DISClearSetDisplay();
30
31 /* imports from database files */
32
33 extern ELT *DBInit(), *DBCreateElt(), *DBRead();
34 extern DBDelete(), DBSetGravitate(), DBGravitate(), DBClearElt();
35 extern ELT *DBCopy();
36 extern DBXform(), DBChangeBrush();
37 extern DBAddSet(), DBClearSet();
38 extern POINT *PTInit(), *PTMakePoint();
39 extern PTDeletePoint();
40
41 /* imports from undodb.c */
42
43 extern UNELT *unlist, *unback;
44 extern UNRembMod();
45
46 /* imports from short.c */
47
48 extern SHUpdate();
49
50 /* imports from menu.c */
51
52 extern MNHighLt(), MNUnHighLt();
53 extern MNInitMenu();
54 extern HiMen[], HiFont[], HiBrush[], HiMode[];
55
56 /* imports from textio.c */
57
58 extern TxMsgOK(), TxPutString();
59 extern TXFIELD TAlign, TAdjust, TBrush, TFont, TGravity, TCSize;
60 extern TXFIELD TEdit, TJustmode;
61
62 /* imports from c */
63
64 extern char *malloc();
65 extern char *strcpy(), *sprintf();
66
67 /* imports from main.c */
68
69 extern ELT *PICTURE; /* current PICTURE database */
70 extern ELT *cset; /* current set database */
71 extern CBRUSH, CSIZE, CFONT; /* current brush, size, font */
72 extern CJUST; /* current text justification */
73 extern Gridon; /* grid mode flag */
74 extern Orientation; /* orientation of workspace */
75 extern Alignment; /* point alignment indicator */
76 extern float PX, PY; /* cursor coordinates */
77 extern float Lastx, Lasty; /* previous cursor coordinates */
78 extern SEQ; /* point sequence number */
79 extern char *Editfile; /* current edit file */
80 extern POINT *POINTLIST, *BACKPOINT;/* accumulated point list */
81 extern Adjustment; /* point adjustment mode */
82 extern GravityOn; /* gravity mode flag */
83 extern Consume; /* point clear flag */
84 extern CHANGED; /* PICTURE changed flag */
85 extern ELT *MEN[]; /* pointers for user symbols */
86 extern POINT MENPOINT[]; /* pointers used fo user symbols */
87 extern cmdbuf[]; /* line buffer for commands */
88 extern char *lines[], *fonts[]; /* line and character styles */
89 extern int lnum[], fnum[];
90
91 /* The following is available to the outside world */
92
93 int bang;
94
95
96 /* The following are defined to allow creation of the command
97 * lookup table.
98 */
99
100 extern LGAlign(), LGBrush(), LGClearPoints(), LGGripe(), LGLittlePoint(),
101 LGDeletePoint(), LGEdit(), LGFont(), LGIncludeSet(), LGSize(), LGSave(),
102 LGJust(), LGMenu(), LGPoint(), LGPath(), LGQuit(), LGRead(), LGHAdjust(),
103 LGMBrush(), LGMFont(), LGMSize(), LGMText(), LGMPoint(), LGMirror(),
104 LGOrient(), LGVAdjust(), LGText(), LGUndo(), LGWrite(), LGOpoint(),
105 LGShowPoints();
106
107 /* The following two arrays define the long commands and the routines
108 * that process them.
109 */
110 static char *lcmds[] = {
111 "align",
112 "brush",
113 "buffer",
114 "clearpoints",
115 "deletepoint",
116 "edit",
117 "font",
118 "gripe",
119 "hadjust",
120 "includeset",
121 "justificaion",
122 "littlepoint",
123 "mbrush",
124 "mfont",
125 "mirror",
126 "mpoint",
127 "msize",
128 "mtext",
129 "orient",
130 "path",
131 "point",
132 "quit",
133 "read",
134 "size",
135 "saveset",
136 "showpoints",
137 "text",
138 "undo",
139 "vadjust",
140 "write",
141 "zpoint",
142 NULL};
143 static (*(lrtns[]))() = {
144 LGAlign, /* align */
145 LGBrush, /* set brush */
146 LGMenu, /* select user set buffer */
147 LGClearPoints, /* clear points */
148 LGDeletePoint, /* delete a point */
149 LGEdit, /* edit new file */
150 LGFont, /* set font */
151 LGGripe, /* leave a gripe or bug */
152 LGHAdjust, /* horizontal adjust */
153 LGIncludeSet, /* add to set */
154 LGJust, /* text justification */
155 LGLittlePoint, /* point size */
156 LGMBrush, /* modify brush */
157 LGMFont, /* modify font */
158 LGMirror, /* mirror current set */
159 LGMPoint, /* move point */
160 LGMSize, /* modify size */
161 LGMText, /* modify text string */
162 LGOrient, /* change picture orientation */
163 LGPath, /* set path or toggle search mode */
164 LGOpoint, /* obtain point from terminal */
165 LGQuit, /* quit */
166 LGRead, /* read user sysmbol */
167 LGSize, /* character size */
168 LGSave, /* save current set in file */
169 LGShowPoints, /* display reference points in set */
170 LGText, /* input text */
171 LGUndo, /* undo last command */
172 LGVAdjust, /* vertical adjust */
173 LGWrite, /* write file */
174 LGPoint}; /* create point from cursor */
175
176
177 int
LGLookup(str,table,next)178 LGLookup(str, table, next)
179 char str[]; /* Pointer to a string to be looked up */
180 char *(table[]); /* Pointer to an array of string pointers
181 * which are the valid commands. The strings
182 * must be ordered monotonically (i.e. all
183 * strings whose first characters are identical
184 * must be adjacent in the table).
185 */
186 int *next;
187
188 /*---------------------------------------------------------
189 * LGLookup searches a table of strings to find one that matches a
190 * given string.
191 *
192 * Results:
193 * If str is an unambiguous abbreviation for one of the entries
194 * in table, then the index of the matching entry is returned.
195 * If str is an abbreviation for more than one entry in table,
196 * then -1 is returned. If str doesn't match any entry, then
197 * -2 is returned.
198 *
199 * Side Effects: None.
200 *
201 * (Modified from software written by John Ousterhout for the caesar
202 * program)
203 *---------------------------------------------------------
204 */
205
206 {
207 /* The search is carried out by using two pointers, one which moves
208 * forward through table from its start, and one which moves backward
209 * through table from its end. The two pointers mark the range of
210 * strings that match the portion of str that we have scanned. When
211 * all of the characters of str have been scanned, then the two
212 * pointers better be identical.
213 */
214 char **bot, **top;
215 int match, index;
216
217 bang = FALSE;
218 match = 0;
219 bot = table;
220 for (top = table; *top != NULL; top++);
221 if (top == bot) return(-2);
222 top--;
223
224 for (index=0; ; index++)
225 {
226 *next = index;
227
228 /* Check for the end of string */
229
230 if ( (str[index] == '\0') ||
231 (str[index] == ',') ||
232 (str[index] == ' ') )
233 {
234 if (bot == top) return(match);
235 else return(-1);
236 }
237 if (str[index] == '!') bang = TRUE;
238 else
239 {
240
241 /* Move bot up until the string it points to matches str in the
242 * index'th position. Make match refer to the index of bot in table.
243 */
244 while ((*bot)[index] != str[index])
245 {
246 if (bot == top) return(-2);
247 bot++;
248 match++;
249 }
250
251 /* Move top down until it matches */
252 while ((*top)[index] != str[index])
253 {
254 if (bot == top) return(-2);
255 top--;
256 }
257 }
258 }
259 }
260
261
LGCommand(command)262 LGCommand(command)
263 char *command;
264
265 /*---------------------------------------------------------
266 * This routine reads in, looks up, and executes a long command.
267 *
268 * Results: None.
269 *
270 * Side Effects:
271 * Depends on the command that is invoked.
272 *---------------------------------------------------------
273 */
274
275 {
276 int index, next;
277
278 if (*command == '\0')
279 {
280 Consume = FALSE;
281 return;
282 }
283 index = LGLookup(command, lcmds, &next);
284 if (index >= 0)
285 {
286
287 (*(lrtns[index]))(command + next);
288 }
289 else
290 {
291 if (index == -1) error("command is ambiguous.");
292 if (index == -2) error("not a command.");
293 }
294 }
295
296 static char badarg[10] = "bad args";
297 static char noset[15] = "no current set";
298
299 #define BADNUM -1
300 #define NONUM -2
301 #define Delimiter(c) ((c == '\0') || (c == ' ') || (c == ','))
302
GetNumParm(line,index)303 GetNumParm(line, index)
304 char *line;
305 int *index;
306 /*
307 * This routine trys to interpret the string starting at
308 * line+index as a positive integeral numeric parameter. The function
309 * returns the numeric equivalent or a negative number it there is some
310 * error in interpreting the string.
311 */
312
313 {
314 char num[20];
315 int i, result;
316
317 for (i=0; !Delimiter(*(line + *index)); ++i)
318 {
319 num[i] = *(line + *index);
320 if ( !isdigit(num[i]) ) return (BADNUM);
321 ++(*index);
322 } /* end for */
323 if ( i == 0 ) return(NONUM);
324 num[i] = '\0';
325 (void) sscanf(num,"%d",&result);
326 return(result);
327 } /* end GetNumParm */
328
329
LGOpoint(line)330 LGOpoint(line)
331 char *line;
332 /*
333 * This routine accepts coordinates from the text terminal
334 * and creates and displays a point from them by passing them
335 * along to LGPoint.
336 *
337 * NOTE: coordinates from the terminal must be non-negative
338 * integers.
339 */
340
341 {
342 int index, xcoord, ycoord;
343
344 index = 1;
345 xcoord = GetNumParm(line, &index);
346 if (xcoord < 0)
347 {
348 error(badarg);
349 return;
350 }
351 ++index;
352 ycoord = GetNumParm(line, &index);
353 if (ycoord < 0)
354 {
355 error(badarg);
356 return;
357 }
358 PX = xcoord;
359 PY = ycoord;
360 LGPoint(line);
361 } /* end LGOpoint */
362
363
LGPoint(line)364 LGPoint(line)
365 char *line;
366 /*
367 * This routine accepts cursor coordinates and creates and
368 * displays points according to the current adjustment and alignment
369 * modes. Note that alignment and gravity are mutually exclusive
370 * and adjustment takes precedence over either.
371 */
372
373 {
374 ELT *temp;
375 POINT *p1;
376
377 temp = DBInit();
378 if (GravityOn) DBGravitate (PX, PY, &PX, &PY, &p1, &temp, PICTURE);
379 if (DBNullelt(temp)) /* no gravity in effect */
380 {
381 /* Round to nearest alignment boundary */
382
383 PX = (float) (((int) (PX / Alignment + 0.5)) * Alignment);
384 PY = (float) (((int) (PY / Alignment + 0.5)) * Alignment);
385 }
386
387
388 if (SEQ > 0) /* this isn't the first point */
389 {
390 if (Adjustment == HORZ) PY = Lasty;
391 if (Adjustment == VERT) PX = Lastx;
392 if (Adjustment == MAN)
393 if (fabs(PX - Lastx) > fabs(PY - Lasty)) PY = Lasty;
394 else PX = Lastx;
395 } /* end if SEQ */;
396 GRDisplayPoint((int) PX, (int) PY, SEQ, pointstyle);
397 (void) PTMakePoint(PX, PY, &POINTLIST);
398 Lastx = PX;
399 Lasty = PY;
400 Consume = FALSE;
401 ++SEQ;
402 } /* end Point */
403
CP()404 CP()
405 /*
406 * This routine deletes all points from the POINTLIST and
407 * clears them from the display also.
408 */
409
410 {
411 POINT *temp;
412
413 while ( !Nullpoint(BACKPOINT) )
414 {
415 temp = PTNextPoint(BACKPOINT);
416 free ((char *) BACKPOINT);
417 BACKPOINT = temp;
418 }
419 BACKPOINT = POINTLIST;
420 POINTLIST = PTInit();
421 SEQ = 0;
422 GRBlankPoints();
423 } /* end CP */
424
425
LGClearPoints(line)426 LGClearPoints(line)
427 char *line;
428 /*
429 * This routine is a no-op since all points are cleared by default
430 * each time through the interpreter loop unless Consume is false.
431 */
432 {
433 }
434
LGDeletePoint(line)435 LGDeletePoint(line)
436 char *line;
437 /*
438 * This routine removes the last point from the POINTLIST
439 * and erases it from the screen.
440 */
441
442 {
443 POINT *pt1, *pt2, *pt3;
444 float savex, savey;
445 int i;
446
447 if (SEQ == 0)
448 {
449 error("no point");
450 return;
451 }
452 pt2 = pt3 = POINTLIST;
453 while ( !Nullpoint(pt3) ) /* find last point and pointer to it */
454 {
455 pt1 = pt2;
456 pt2 = pt3;
457 pt3 = PTNextPoint(pt3);
458 };
459 SEQ--;
460 savex = pt2->x;
461 savey = pt2->y;
462 GRErasePoint( (int) pt2->x, (int) pt2->y, SEQ);
463 PTDeletePoint(pt2);
464 if (SEQ > 0) /* any points left after deleting */
465 { /* then pt1 points to last of them */
466 Lastx = pt1->x;
467 Lasty = pt1->y;
468 pt3 = POINTLIST; /* redisplay any nearby points */
469 for (i=0; i<SEQ; ++i) /* which may have been clobbered by */
470 { /* the erase */
471 if (fabs(pt3->x - savex) < (2*halfpoint))
472 if (fabs(pt3->y - savey) < (2*halfpoint))
473 GRDisplayPoint((int) pt3->x,
474 (int) pt3->y,
475 i, pointstyle);
476 pt3 = PTNextPoint(pt3);
477 } /* end for */
478 }
479 Consume = FALSE;
480 } /* end DeletePoint */
481
482
LGShowPoints(line)483 LGShowPoints(line)
484 char *line;
485 /*
486 * This routine causes the text elements in the current set
487 * to be redrawn using the new font.
488 */
489
490 {
491 ELT *elist;
492 POINT *p1;
493 int pno;
494
495 if (DBNullelt(cset))
496 {
497 error(noset);
498 return;
499 }
500 elist = cset;
501 while ( !DBNullelt(elist) )
502 {
503 p1 = elist->ptlist;
504 pno = 0;
505 while (!Nullpoint(p1))
506 {
507 GRDisplayPoint((int)p1->x, (int)p1->y, pno, pointstyle);
508 p1 = PTNextPoint(p1);
509 pno++;
510 }
511 elist = DBNextofSet(elist);
512 } /* end while */
513 Consume = FALSE;
514 } /* end ShowPoints */
515
516
LGText(line)517 LGText(line)
518 char *line;
519 /* This routine implements the text commands. It first looks
520 * for a justification specification (if not specified, default is
521 * centering), and then the text string from the input line. Text
522 * justification requires a point upon which the text is positioned.
523 */
524
525 {
526 ELT *e1;
527 POINT pos, ppnt, *p1;
528 int i, j;
529 char *text;
530
531 if (SEQ == 0)
532 {
533 error("not enough points");
534 return;
535 }
536 if (*line == '\0') return; /* no text */
537 for (; *line == ' '; ++line) /* delete leading blanks */
538 i = strlen(line);
539 text = malloc((unsigned) i + 1);
540 (void) strcpy(text, line);
541 DBClearSet(); /* clear old current set so this can form */
542 DISClearSetDisplay(); /* the new one */
543 GRsetwmask(textmask | setmask);
544 ppnt.x = POINTLIST->x;
545 ppnt.y = POINTLIST->y;
546 if (SEQ > 1)
547 {
548 p1 = PTNextPoint(POINTLIST);
549 ppnt.x = (POINTLIST->x + p1->x)/2;
550 ppnt.y = (POINTLIST->y + p1->y)/2;
551 }
552
553 GRPutText(CJUST, &ppnt, CFONT, CSIZE, text, &pos);
554 p1 = PTInit();
555 (void) PTMakePoint(ppnt.x, ppnt.y, &p1);
556 /* end extra positioning points */
557 (void) PTMakePoint(pos.x, pos.y, &p1);
558 (void) PTMakePoint(pos.x + i * charxsize / 2, pos.y, &p1);
559 (void) PTMakePoint(pos.x + i * charxsize, pos.y, &p1);
560 e1 = DBCreateElt(CJUST, p1, CFONT, CSIZE, text, &PICTURE);
561 DBAddSet(e1);
562 CHANGED = TRUE;
563 } /* end LGText */
564
565
566
LGBrush(line)567 LGBrush(line)
568 char *line;
569 /*
570 * This routine sets the current brush to that specified in the
571 * parameter.
572 */
573
574 {
575 int newbrush, index;
576 char string[2];
577
578 index = 0;
579 if (isalpha(*(++line)))
580 {
581 newbrush = LGLookup(line, lines, &index);
582 if (newbrush >= 0) newbrush = lnum[newbrush];
583 else newbrush = BADNUM;
584 }
585 else newbrush = GetNumParm(line, &index);
586 if ( (newbrush == BADNUM) || (newbrush > NBRUSHES) )
587 {
588 error(badarg);
589 return;
590 }
591 MNUnHighLt(HiBrush[CBRUSH-1]);
592 MNHighLt(HiBrush[newbrush-1], hicolor);
593 CBRUSH = newbrush;
594 (void) sprintf(string,"%1d",newbrush);
595 TxPutString(&TBrush,string);
596 Consume = FALSE;
597 } /* end LGBrush */
598
599
600
LGMBrush(line)601 LGMBrush(line)
602 char *line;
603 /*
604 * This routine causes the elements in the current set
605 * to be redrawn using the new brush.
606 */
607
608 {
609 ELT *elist;
610 int new, index;
611
612 index = 0;
613 if (isalpha(*(++line)))
614 {
615 new = LGLookup(line, lines, &index);
616 if (new >= 0) new = lnum[new];
617 else new = BADNUM;
618 }
619 else new = GetNumParm(line, &index);
620 if ( (new < 0) || (new > NBRUSHES) )
621 {
622 error(badarg);
623 return;
624 }
625 if (DBNullelt(cset))
626 {
627 error(noset);
628 return;
629 }
630 elist = cset;
631 while ( !DBNullelt(elist) )
632 {
633 if (!TEXT(elist->type))
634 {
635 DISScreenErase(elist, (linemask | setmask));
636 DBChangeBrush(elist, new, &PICTURE);
637 DISScreenAdd(elist, (linemask | setmask));
638 } /* end if */
639 elist = DBNextofSet(elist);
640 } /* end while */
641 CHANGED = TRUE;
642 } /* end MBrush */
643
644
LGMFont(line)645 LGMFont(line)
646 char *line;
647 /*
648 * This routine causes the text elements in the current set
649 * to be redrawn using the new font.
650 */
651
652 {
653 ELT *elist;
654 int new, index;
655
656 index = 0;
657 if (isalpha(*(++line)))
658 {
659 new = LGLookup(line, fonts, &index);
660 if (new >= 0) new = fnum[new];
661 else new = BADNUM;
662 }
663 else new = GetNumParm(line, &index);
664 if ( (new < 0) || (new > NFONTS) )
665 {
666 error(badarg);
667 return;
668 }
669 if (DBNullelt(cset))
670 {
671 error(noset);
672 return;
673 }
674 elist = cset;
675 while ( !DBNullelt(elist) )
676 {
677 if (TEXT(elist->type))
678 {
679 DISScreenErase(elist, (linemask | setmask));
680 TxMsgOK();
681 DBChangeFont(elist, new, elist->size, &PICTURE);
682 DISScreenAdd(elist, (linemask | setmask));
683 } /* end if */
684 elist = DBNextofSet(elist);
685 } /* end while */
686 CHANGED = TRUE;
687 } /* end MFont */
688
689
LGMSize(line)690 LGMSize(line)
691 char *line;
692 /*
693 * This routine causes the text elements in the current set
694 * to be redrawn using the new size.
695 *
696 */
697
698 {
699 POINT *p1, *p2, pos;
700 ELT *elist;
701 int new, index, i, j;
702
703 index = 1;
704 new = GetNumParm(line, &index);
705 if ( (new < 0) || (new > NSIZES) )
706 {
707 error(badarg);
708 return;
709 }
710 if (DBNullelt(cset))
711 {
712 error(noset);
713 return;
714 }
715 elist = cset;
716 while ( !DBNullelt(elist) )
717 {
718 if (TEXT(elist->type))
719 {
720 DISScreenErase(elist, (linemask | setmask));
721 TxMsgOK();
722 UNRembMod(elist,&PICTURE);
723 elist->size = new;
724 GRsetwmask(textmask | setmask);
725 p1 = elist->ptlist;
726 GRPutText(elist->type, p1, elist->brushf,
727 elist->size,elist->textpt, &pos);
728 i= strlen(elist->textpt);
729 p2 = PTInit();
730 (void) PTMakePoint(p1->x, p1->y, &p2);
731 /* end extra positioning points */
732 (void) PTMakePoint(pos.x, pos.y, &p2);
733 (void) PTMakePoint(pos.x + i * charxsize / 2,
734 pos.y, &p2);
735 (void) PTMakePoint(pos.x + i * charxsize, pos.y, &p2);
736 elist->ptlist = p2;
737 } /* end if */
738 elist = DBNextofSet(elist);
739 } /* end while */
740 CHANGED = TRUE;
741 } /* end MSize */
742
743
LGMText(line)744 LGMText(line)
745 char *line;
746 /* This routine allows modification of text by replacing
747 * an existing string with a new one, appropriately repositioned
748 */
749
750 {
751 ELT *e1;
752 POINT pos, ppnt, *p1;
753 int i, j;
754 char *text;
755
756 i = strlen(++line);
757 text = malloc((unsigned) i + 1);
758 (void) strcpy(text, line);
759 GRsetwmask(textmask | setmask);
760 e1 = cset;
761 while ( !DBNullelt(e1) )
762 {
763 if (TEXT(e1->type))
764 {
765 DISScreenErase(e1, (textmask | setmask));
766 TxMsgOK();
767 UNRembMod(e1, &PICTURE);
768 ppnt.x = e1->ptlist->x;
769 ppnt.y = e1->ptlist->y;
770
771 GRPutText(e1->type, &ppnt, e1->brushf, e1->size, text, &pos);
772 p1 = PTInit();
773 (void) PTMakePoint(ppnt.x, ppnt.y, &p1);
774 /* end extra positioning points */
775 (void) PTMakePoint(pos.x, pos.y, &p1);
776 (void) PTMakePoint(pos.x + i * charxsize / 2, pos.y, &p1);
777 (void) PTMakePoint(pos.x + i * charxsize, pos.y, &p1);
778 e1->textpt = text;
779 } /* end if text */
780 e1 = DBNextofSet(e1);
781 } /* end while */
782 CHANGED = TRUE;
783 } /* end LGMText */
784
LGMPoint(line)785 LGMPoint(line)
786 char *line;
787 /*
788 * This routine modifies the element which contains the point
789 * closest to the first of two specified points so that that point
790 * coincides with the second of the points (if specified).
791 *
792 * Note: it implies knowlege of the database representation by modifying
793 * the element directly.
794 */
795
796 {
797 ELT *e1;
798 POINT *p1, *p2, *p3, *p4;
799 float x1, y1;
800
801 if (SEQ < 1) /* no points */
802 {
803 error("no point specified");
804 return;
805 }
806 /* find point */
807 DBSetGravitate(POINTLIST->x, POINTLIST->y, &x1, &y1, &p1, &e1, cset);
808 if ( !DBNullelt(e1) )
809 {
810 DBClearSet();
811 DISClearSetDisplay();
812 DISScreenErase(e1, (linemask | setmask));
813 UNRembMod(e1,&PICTURE);
814 if (SEQ > 1) /* move a point, not delete */
815 {
816 p2 = PTNextPoint(POINTLIST);
817 p1->x = p2->x;
818 p1->y = p2->y;
819 p2 = PTNextPoint(p2);
820 if (!Nullpoint(p2))
821 {
822 p3 = PTInit();
823 while (!Nullpoint(p2))
824 {
825 p4 = PTMakePoint(p2->x, p2->y, &p3);
826 p2 = PTNextPoint(p2);
827 }
828 p4->nextpt = p1->nextpt;
829 p1->nextpt = p3;
830 }
831 }
832 else
833 {
834 PTDeletePoint(p1);
835 }
836 DISScreenAdd(e1, (linemask | setmask));
837 DBAddSet(e1);
838 } /* end if !DBNullelt */
839 } /* end MPOINT */
840
841
LGGripe(line)842 LGGripe(line)
843 char *line;
844 /*
845 * This routine allows users to leave gripe messages or report
846 * bugs to the maintainer. Mail is invoked via the defined constant GRIPE.
847 */
848
849 {
850 TxClose(); /* Restore text terminal to 'normal' state */
851 (void) system(GMailCommand); /* mail complaint */
852 SHRedis(); /* reclaim terminal */
853 } /* end Gripe */
854
LGLittlePoint(line)855 LGLittlePoint(line)
856 char *line;
857 /*
858 * This routine controls the size of the point that is displayed
859 * The sizes available are artmode in which a small (3 x 3) point is displayed
860 * with no number and regular (non- artmode).
861 */
862
863 {
864
865 if (artmode) artmode = FALSE;
866 else artmode = TRUE;
867 Consume = FALSE;
868 } /* end Little Point */
869
870
SetOrient(orient)871 SetOrient(orient)
872 int orient;
873 /*
874 * This routine sets up the orientation of the drawing area.
875 */
876
877 {
878 int x1, x2, y1, y2; /* used to set grid parameters */
879
880 if (orient == 0) /* initialize grid */
881 {
882 x1 = y1 = 0;
883 x2 = 511;
884 y2 = 395;
885 }
886 else
887 {
888 x1 = 116;
889 y1 = 0;
890 x2 = 511;
891 y2 = 483;
892 };
893 MNInitMenu(orient);
894 GRSetGrid(x1, y1, x2, y2, 16);
895 }
896
LGOrient(line)897 LGOrient(line)
898 char *line;
899 /*
900 * This routine toggles the orientation of the drawing area.
901 */
902
903 {
904
905 if (Orientation == 1)
906 {
907 Orientation = 0;
908 }
909 else
910 {
911 Orientation = 1;
912 };
913 SetOrient(Orientation);
914 SHUpdate();
915 } /* end Orient */
916
917
LGSave(line)918 LGSave(line)
919 char *line;
920 /*
921 * This routine writes the current set into the specified filename
922 * or to the current Editfile
923 */
924
925 {
926 FILE *fp, *fopen();
927 char tname[50], filename[100], string[100], *tn, *fn, *wfile;
928 ELT *elist;
929 POINT *plist, pos;
930 int i, space, stat;
931
932 space = 100;
933 ++line;
934 tn = tname; fn = filename;
935 (void) sscanf(line, "%s", tname);
936 i = strlen(tname);
937 if (i == 0) /* no filename */
938 {
939 error("write to where?");
940 return;
941 }
942 stat = PConvertTilde(&tn, &fn, &space);
943 *fn = '\0';
944 if (stat == FALSE)
945 {
946 sprintf(string, "unknown path %s", tname);
947 error(string);
948 return;
949 }
950 if ( !bang ) /* user doesn't insist */
951 {
952 fp = fopen(filename, "r");
953 if ( fp != NULL )
954 {
955 error("file already exists");
956 return;
957 }
958 }
959 fp = fopen(filename, "w");
960 wfile = filename;
961 if (fp == NULL) /* file error */
962 {
963 (void) sprintf(string,"can't open %s", wfile);
964 error(string);
965 return;
966 };
967 TxPutMsg("writing file...");
968 CHANGED = FALSE;
969 if (SEQ > 0) /* specified a positioning point */
970 {
971 pos.x = POINTLIST->x;
972 pos.y = POINTLIST->y;
973 }
974 else
975 {
976 if ( !DBNullelt(PICTURE) )
977 {
978 pos.x = PICTURE->ptlist->x;
979 pos.y = PICTURE->ptlist->y;
980 }
981 else
982 {
983 pos.x = pos.y = 0;
984 };
985 }
986 fprintf(fp,"gremlinfile\n"); /* write header */
987 fprintf(fp, "%d %1.2f %1.2f\n", Orientation, pos.x, pos.y);
988 elist = cset;
989 while ( !DBNullelt(elist) ) /* write each element */
990 {
991 fprintf(fp, "%d\n", elist->type);
992 plist = elist->ptlist;
993 while ( !Nullpoint(plist) ) /* write each point */
994 {
995 fprintf(fp, "%1.2f %1.2f\n",plist->x, plist->y);
996 plist = PTNextPoint(plist);
997 } /* end while plist */
998 fprintf(fp, "%1.2f %1.2f\n", -1.0, -1.0); /* end pointlist */
999 fprintf(fp, "%d %d\n",elist->brushf, elist->size);
1000 fprintf(fp,"%d %s\n ", strlen(elist->textpt), elist->textpt);
1001 elist = DBNextofSet(elist);
1002 } /* end while */
1003 fprintf(fp,"%d\n",-1); /* end of element list */
1004 TxMsgOK();
1005 (void) fclose(fp);
1006 } /* end LGSave */;
1007