1 /* @(#)main.c	1.7	10/10/84
2  *
3  * Copyright -C- 1982 Barry S. Roitblat
4  *
5  *
6  *      This is the main routine for the gremlin picture editor.
7  */
8 
9 
10 #include "gremlin.h"
11 #include "grem2.h"
12 #include <signal.h>
13 #include <sgtty.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/time.h>
17 
18 /* imports from config.c */
19 
20 extern char GMapFile[];
21 
22 /* database imports */
23 
24 extern ELT *DBInit(), *DBRead();
25 extern POINT *PTInit(), *PTMakePoint();
26 
27 /* imports from menu.c */
28 
29 extern MNInterpretCursor();
30 extern MNIcon(), MNInitMenu(), MNDisplayMenu();
31 
32 /* graphics imports */
33 extern GRInit(), GRClose();
34 extern GRSetGrid(), GRDisplayGrid(), GRBlankGrid();
35 extern GRDisableTablet(), GREnableTablet();
36 extern GRSetMap(), GRsetwmask();
37 extern artmode;
38 
39 /* imports from undodb.c */
40 
41 extern UNForget();
42 extern UNELT *unlist, *unback;
43 
44 /* imports from long.c */
45 
46 extern char *Editfile;
47 extern CP(), LGCommand();
48 extern LGQuit();
49 
50 /* imports from short.c */
51 
52 extern SHCommand();
53 extern SHRedis();
54 extern SHUpdate();
55 
56 /* other */
57 
58 extern char *FindAED();
59 
60 /* Forward references within this file: */
61 
62 extern OnStop(), OnCommand();
63 
64 /* Imports from textio.c: */
65 
66 extern TxInit(), TxRedisplay(), TxClose(), TxPutMsg(), TxMsgOK();
67 extern TxLine(), TxPutString();
68 extern char TxGetChar();
69 extern short inline;
70 extern TxPutString();
71 extern TXFIELD TAlign, TAdjust, TBrush, TFont, TGravity, TCSize;
72 extern TXFIELD TEdit, TJustmode;
73 
74 
75 /* Library routines: */
76 
77 extern char *malloc(), *sprintf(), *strcat(), *strcpy();
78 
79 /* Version number */
80 
81 char SccsId [] = "@(#)main.c	1.7	(Berkeley)	10/10/84";
82 
83 #ifdef SIGTINT
84 static int lintrup = LINTRUP;    /* Constant for local mode bit */
85 #endif SIGTINT
86 
87 /* Declaration of Globals */
88 
89 ELT *PICTURE, *cset, arhead;
90 int CBRUSH, CFONT, CSIZE, CJUST, Gridsize, Gridon, Orientation;
91 int Alignment, SEQ, Adjustment, GravityOn, Consume, CHANGED;
92 float PX, PY, Lastx, Lasty;
93 POINT *POINTLIST, *BACKPOINT, MENPOINT[NUSER];
94 ELT *MEN[NUSER];
95 char cmdbuf[400];
96 int SEARCH = TRUE;
97 int jmodes = 16;
98 char *textpos[] = {"bl", "bc", "br", "cl", "cc", "cr", "tl", "tc", "tr",
99                    "lb", "cb", "rb", "lc",       "rc", "lt", "ct", "rt" };
100 char *dispmode[] = {"BL", "BR", "CC", "XX", "XX", "XX", "XX", "XX",
101                     "XX", "XX", "TL", "TC", "TR", "CL", "CR", "BC" };
102 int textmode[] = { 0, 15, 1, 13, 2, 14, 10, 11, 12,
103                    0, 15, 1, 13,    14, 10, 11, 12 };
104 
105 /* symbolic types, brushes, etc. */
106 
107 char *lines[] = { "broken", "dashed", "dotted",
108                   "medium", "narrow", "thick", NULL };
109 int lnum[] = { 2, 4, 1, 6, 5, 3 };
110 char types[] = { 'l', 'r', 'c', 'v', 'a', 'u', '\0' };
111 char *fonts[] = { "Bold", "Italics", "Roman", "Special",
112                   "bold", "italics", "roman", "special", NULL };
113 int fnum[] = { 3, 2, 1, 4, 3, 2, 1, 4 };
114 
115 error(s)
116 char *s;
117 /*
118  *      This routine prints an error message and sets the Consume flag
119  * so that points are not cleared.
120  */
121 {
122     putchar('\7');
123     TxPutMsg(s);
124     Consume = FALSE;
125 }
126 
127 
128 main(argc, argv)
129 int argc;
130 char *argv[];
131 {
132     FILE *fp, *POpen(), *fopen(),*grtty, *tablet, *map, *startup;
133     POINT *p1, pos;
134     int x1, y1, x2, y2, i, j;
135     int button, cux, cuy;
136     char colours[768], msg[50], sw, *arg, *file;
137     char *ptr, *display, *type, *getenv(), home[100];
138     char *path = ".";
139     struct stat buf;
140     ino_t inode;
141 
142     display = FindAED();
143     if (display == NULL) display = "/dev/null";
144     Orientation = 1;
145     file = NULL;
146 
147     /* Parse the command line. */
148 
149     argc -= 1;  argv++;                /* Skip program name. */
150     while (argc > 0)
151     {
152         argc -= 1;
153         arg = *argv++;
154         if (arg[0] != '-') file = arg;
155         else
156         {
157             sw = *++arg;
158             switch (sw)
159             {
160             case 'g':
161                 if (*++arg == '\0')
162                 if (argc-- > 0) arg = *argv++;
163                 if (argc < 0) error("usage: gremlin -g <display name>");
164                 display = arg;
165                 if (*display != '/') display = strcat("/dev/", arg);
166                 break;
167             case 'p':
168                 if (*++arg == '\0')
169                 if (argc-- > 0) arg = *argv++;
170                 if (argc < 0) error("usage: gremlin -p <path>");
171                 path = arg;
172                 SEARCH = TRUE;
173                 break;
174             case 'h':
175                 Orientation = 0;
176                 break;
177             case 'v':
178                 Orientation = 1;
179                 break;
180             default:
181                 (void) sprintf(msg, "unknown switch: %c", sw);
182                 error(msg);
183             }
184         }
185     }
186 
187     PSetPath(path);
188     if ((map = fopen(GMapFile, "r")) == NULL) {
189 	error ("can't open color map");
190     } else
191 	for (i=0; i<768; ++i)    /* read in color map */
192 	{
193 	    (void) fscanf(map,"%o",&j);
194 	    colours[i] = j&0377;
195 	}
196 
197     /* Open the display, and call all of the initialization routines.
198      * Initialize all of the globals defined in this file.
199      */
200     type = getenv("TERM");
201     TxInit(type);
202 
203     /* Ignore quit signals, catch interrupts and stops. */
204 
205     signal(SIGINT, SIG_IGN);
206     signal(SIGTSTP, OnStop);
207     signal(SIGTTIN, OnStop);
208     signal(SIGTTOU, OnStop);
209 
210 #ifdef SIGTINT
211     signal(SIGTINT, OnCommand);
212     sighold(SIGTINT);
213 #endif SIGTINT
214 
215     grtty = fopen(display,"w");
216     if (grtty == NULL)
217     {
218         error("couldn't open display");
219         LGQuit(display);
220     };
221     tablet = fopen(display,"r");
222     if (tablet == NULL) tablet = fopen("/dev/null", "r");
223     GRInit(grtty,0);
224     GRSetMap(colours);
225 
226 #ifdef SIGTINT
227     (void) ioctl(fileno(stdin), TIOCLBIS, (char *) &lintrup);
228 #endif SIGTINT
229 
230     TxRedisplay();    /* display text screen */
231 
232     CBRUSH = 6;
233     CFONT = 1;
234     CSIZE = 1;
235     CJUST = 0;
236     Gridon = FALSE;
237     Adjustment = NOADJ;
238     Alignment = 4;
239     artmode = FALSE;
240     SEQ = 0;
241     GravityOn = FALSE;
242     CHANGED = FALSE;
243     POINTLIST = PTInit();
244     BACKPOINT = PTInit();
245     unlist = unback = nullun;
246     p1 = PTInit();       /* initialize arrowhead template */
247     (void) PTMakePoint(0.0, 0.0, &p1);
248     (void) PTMakePoint(-5.0, 3.0, &p1);
249     (void) PTMakePoint(-3.0, 0.0, &p1);
250     (void) PTMakePoint(-5.0, -3.0, &p1);
251     (void) PTMakePoint(0.0, 0.0, &p1);
252     arhead.type = VECTOR;
253     arhead.ptlist = p1;
254     arhead.brushf = 0;   /* brush filled in when used */
255     arhead.size = 0;
256     arhead.textpt = malloc(1);
257     *(arhead.textpt) = '\0';
258 
259     PICTURE = DBInit();    /* initialize picture databse */
260     cset = DBInit();       /* and current set   */
261     for (i=0; i<4; ++i)    /* and user symbols  */
262         MEN[i] = DBInit();
263     Editfile = malloc(100);
264     if (file == NULL)
265         *Editfile = '\0';
266     else
267     {
268         (void) strcpy(Editfile, file);
269         fp = POpen(Editfile, (char **) NULL, SEARCH);
270         if (fp == NULL)  error("(creating new file)");
271         else PICTURE = DBRead(Editfile,&Orientation, &pos);
272     }
273     unlist = unback = nullun;
274     TxPutString(&TEdit, Editfile);
275     TxPutMsg("        Gremlin - Version 2.3 (1982)");
276     MNIcon();
277     MNInitMenu(Orientation);      /* Initialize Menu */
278     SHUpdate();         /* Display menu and picture, if any */
279 
280     if (Orientation == 0)    /* initialize grid */
281     {
282         x1 = y1 = 0;
283         x2 = 511;
284         y2 = 395;
285     }
286     else
287     {
288         x1 = 116;
289         y1 = 0;
290         x2 = 511;
291         y2 = 483;
292     };
293     Gridsize = 16;
294     GRSetGrid(x1, y1, x2, y2, Gridsize);
295 
296         /* read start-up file */
297         /* look in home directory */
298     sprintf(home,"%s/.gremlinrc",getenv("HOME"));
299     startup = fopen(home, "r");
300     if (startup != NULL)
301     {
302         fstat(startup, &buf);
303         inode = buf.st_ino;
304         ptr = fgets(cmdbuf, 400, startup);
305         while (ptr != NULL)
306         {
307             for (i=0; (cmdbuf[i] != '\n'); ++i)
308                 if (i > 399) break;
309             cmdbuf[i] = '\0';    /* remove trailing carriage return */
310             if (cmdbuf[0] == ':') LGCommand(&(cmdbuf[1]));
311             else SHCommand(&(cmdbuf[0]));
312             ptr = fgets(cmdbuf, 400, startup);
313         }  /* end while */
314     }  /* end if startup */
315     else inode = 0;
316 
317             /* look in current directory */
318     startup = fopen(".gremlinrc", "r");
319     if (startup != NULL)
320     {
321         fstat(startup, &buf);
322         if (buf.st_ino != inode)  /* This isn't the same file as above */
323         {
324             ptr = fgets(cmdbuf, 400, startup);
325             while (ptr != NULL)
326             {
327                 for (i=0; (cmdbuf[i] != '\n'); ++i)
328                     if (i > 399) break;
329                 cmdbuf[i] = '\0';    /* remove trailing carriage return */
330                 if (cmdbuf[0] == ':') LGCommand(&(cmdbuf[1]));
331                 else SHCommand(&(cmdbuf[0]));
332                 ptr = fgets(cmdbuf, 400, startup);
333             }  /* end while */
334         }  /* end if buf */
335     }  /* end if startup */
336 
337     while ( TRUE )    /* Exits through the 'quit' command */
338     {
339         Consume = TRUE;
340         UNForget();
341 
342 #ifdef SIGTINT
343         GREnableTablet();
344               /*  Allow keyboard interrupts while waiting
345                * for cursor input.
346                */
347         sigrelse(SIGTINT);
348         button = GRGetButton(tablet, &cux, &cuy);
349               /*  Ignore keyboard interrupts while processing commands.
350                */
351         sighold(SIGTINT);
352         GRDisableTablet();
353         TxMsgOK();
354         MNInterpretCursor(button, cux, cuy);
355         if (Consume) CP();
356 #else SIGTINT
357         i = 1 << fileno(stdin);
358         GREnableTablet();
359         i |= (1 << fileno(tablet));
360         (void) select(20, &i, 0, 0, 0);
361         if (i & (1 << fileno(stdin)))
362         {
363             TxMsgOK();
364             OnCommand();
365         }
366         else
367         {
368             if ((button = GRGetButton(tablet, &cux, &cuy)) != -4)
369             {
370                 GRDisableTablet();
371                 TxMsgOK();
372                 MNInterpretCursor(button, cux, cuy);
373                 if (Consume) CP();
374             }
375         }
376 #endif SIGTINT
377 
378     }  /* end while */
379 
380 }  /* end main */
381 
382 
383 OnStop(signo)
384 int signo;
385 
386 /*-----------------------------------------------------------------------------
387  *    This procedure handles stop signals.
388  *
389  *    Results:    None.
390  *
391  *    Side Effects:
392  *    The text display is reset, we wait to get restarted, then
393  *    redisplay text.
394  *-----------------------------------------------------------------------------
395  */
396 
397 {
398     TxClose();
399     signal(signo, SIG_DFL);
400     sigsetmask(0);
401     (void) kill(0, signo);
402     signal(signo, OnStop);
403     SHRedis();
404 }
405 
406 
407 OnCommand()
408 
409 /*-----------------------------------------------------------------------------
410  *    This routine responds to interrupts from the command terminal and
411  *    then processes commands as long as there is input.
412  *
413  *    Results:    None.
414  *
415  *    Side Effects:
416  *    Whatever is done by the commands.
417  *-----------------------------------------------------------------------------
418  */
419 
420 {
421 
422 #ifdef SIGTINT
423     long charcount;
424 #else SIGTINT
425     int i;
426     struct timeval selectpoll;
427 #endif SIGTINT
428 
429     static char cmd, lastcmd;
430     int repeat;
431 
432     GRDisableTablet();
433 
434 #ifdef SIGTINT
435     (void) ioctl(fileno(stdin), TIOCLBIC, (char *) &lintrup);
436 #endif SIGTINT
437 
438 
439     while (TRUE)
440     {
441 
442     /* If there is no more input, then reenable the signal and return */
443 
444 
445 #ifdef SIGTINT
446     (void) ioctl(fileno(stdin), FIONREAD, (char *) &charcount);
447     if (charcount == 0)
448     {
449         GREnableTablet();
450         (void) ioctl(fileno(stdin), TIOCLBIS, (char *) &lintrup);
451         return;
452     }
453 #else SIGTINT
454     i = 1 << fileno(stdin);
455     selectpoll.tv_sec = 0l;
456     selectpoll.tv_usec = 0l;
457     if (select(20, &i, 0, 0, &selectpoll) <= 0)
458     {
459         GREnableTablet();
460         return;
461     }
462 #endif SIGTINT
463 
464 
465     /* Read the command and call the long or short command routine */
466 
467     cmd = TxGetChar();
468     if (cmd == '.')
469     {
470         repeat = TRUE;
471         cmd = lastcmd;
472     }
473     else
474     {
475         repeat = FALSE;
476         lastcmd = cmd;
477     }
478     if (cmd == ':')
479     {
480         if (!repeat) TxGetLine(":",cmdbuf,400);
481         LGCommand(cmdbuf);
482     }
483     else
484     {
485         TxLine(inline);
486         if (cmd != '\') putchar(cmd);
487         (void) fflush(stdout);
488         SHCommand(&cmd);
489     }
490     TxLine(inline);
491     printf("                                                                              ");
492     TxLine(inline);
493     if (Consume) CP();
494     Consume = TRUE;
495     UNForget();
496     }
497 }
498 
499