1 /* @(#)main.c	1.5	07/06/83
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 <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.5	(Berkeley)	07/06/83";
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     map = fopen(GMapFile, "r");
189     for (i=0; i<768; ++i)    /* read in color map */
190     {
191         (void) fscanf(map,"%o",&j);
192         colours[i] = j&0377;
193     };
194 
195     /* Open the display, and call all of the initialization routines.
196      * Initialize all of the globals defined in this file.
197      */
198     type = getenv("TERM");
199     TxInit(type);
200 
201     /* Ignore quit signals, catch interrupts and stops. */
202 
203     signal(SIGINT, SIG_IGN);
204     signal(SIGTSTP, OnStop);
205     signal(SIGTTIN, OnStop);
206     signal(SIGTTOU, OnStop);
207 
208 #ifdef SIGTINT
209     signal(SIGTINT, OnCommand);
210     sighold(SIGTINT);
211 #endif SIGTINT
212 
213     grtty = fopen(display,"w");
214     if (grtty == NULL)
215     {
216         error("couldn't open display");
217         LGQuit(display);
218     };
219     tablet = fopen(display,"r");
220     if (tablet == NULL) tablet = fopen("/dev/null", "r");
221     GRInit(grtty,0);
222     GRSetMap(colours);
223 
224 #ifdef SIGTINT
225     (void) ioctl(fileno(stdin), TIOCLBIS, (char *) &lintrup);
226 #endif SIGTINT
227 
228     TxRedisplay();    /* display text screen */
229 
230     CBRUSH = 6;
231     CFONT = 1;
232     CSIZE = 1;
233     CJUST = 0;
234     Gridon = FALSE;
235     Adjustment = NOADJ;
236     Alignment = 4;
237     artmode = FALSE;
238     SEQ = 0;
239     GravityOn = FALSE;
240     CHANGED = FALSE;
241     POINTLIST = PTInit();
242     BACKPOINT = PTInit();
243     unlist = unback = nullun;
244     p1 = PTInit();       /* initialize arrowhead template */
245     (void) PTMakePoint(0.0, 0.0, &p1);
246     (void) PTMakePoint(-5.0, 3.0, &p1);
247     (void) PTMakePoint(-3.0, 0.0, &p1);
248     (void) PTMakePoint(-5.0, -3.0, &p1);
249     (void) PTMakePoint(0.0, 0.0, &p1);
250     arhead.type = VECTOR;
251     arhead.ptlist = p1;
252     arhead.brushf = 0;   /* brush filled in when used */
253     arhead.size = 0;
254     arhead.textpt = malloc(1);
255     *(arhead.textpt) = '\0';
256 
257     PICTURE = DBInit();    /* initialize picture databse */
258     cset = DBInit();       /* and current set   */
259     for (i=0; i<4; ++i)    /* and user symbols  */
260         MEN[i] = DBInit();
261     Editfile = malloc(100);
262     if (file == NULL)
263         *Editfile = '\0';
264     else
265     {
266         (void) strcpy(Editfile, file);
267         fp = POpen(Editfile, (char **) NULL, SEARCH);
268         if (fp == NULL)  error("(creating new file)");
269         else PICTURE = DBRead(Editfile,&Orientation, &pos);
270     }
271     unlist = unback = nullun;
272     TxPutString(&TEdit, Editfile);
273     TxPutMsg("        Gremlin - Version 2.3 (1982)");
274     MNIcon();
275     MNInitMenu(Orientation);      /* Initialize Menu */
276     SHUpdate();         /* Display menu and picture, if any */
277 
278     if (Orientation == 0)    /* initialize grid */
279     {
280         x1 = y1 = 0;
281         x2 = 511;
282         y2 = 395;
283     }
284     else
285     {
286         x1 = 116;
287         y1 = 0;
288         x2 = 511;
289         y2 = 483;
290     };
291     Gridsize = 16;
292     GRSetGrid(x1, y1, x2, y2, Gridsize);
293 
294         /* read start-up file */
295         /* look in home directory */
296     sprintf(home,"%s/.gremlinrc",getenv("HOME"));
297     startup = fopen(home, "r");
298     if (startup != NULL)
299     {
300         fstat(startup, &buf);
301         inode = buf.st_ino;
302         ptr = fgets(cmdbuf, 400, startup);
303         while (ptr != NULL)
304         {
305             for (i=0; (cmdbuf[i] != '\n'); ++i)
306                 if (i > 399) break;
307             cmdbuf[i] = '\0';    /* remove trailing carriage return */
308             if (cmdbuf[0] == ':') LGCommand(&(cmdbuf[1]));
309             else SHCommand(&(cmdbuf[0]));
310             ptr = fgets(cmdbuf, 400, startup);
311         }  /* end while */
312     }  /* end if startup */
313     else inode = 0;
314 
315             /* look in current directory */
316     startup = fopen(".gremlinrc", "r");
317     if (startup != NULL)
318     {
319         fstat(startup, &buf);
320         if (buf.st_ino != inode)  /* This isn't the same file as above */
321         {
322             ptr = fgets(cmdbuf, 400, startup);
323             while (ptr != NULL)
324             {
325                 for (i=0; (cmdbuf[i] != '\n'); ++i)
326                     if (i > 399) break;
327                 cmdbuf[i] = '\0';    /* remove trailing carriage return */
328                 if (cmdbuf[0] == ':') LGCommand(&(cmdbuf[1]));
329                 else SHCommand(&(cmdbuf[0]));
330                 ptr = fgets(cmdbuf, 400, startup);
331             }  /* end while */
332         }  /* end if buf */
333     }  /* end if startup */
334 
335     while ( TRUE )    /* Exits through the 'quit' command */
336     {
337         Consume = TRUE;
338         UNForget();
339 
340 #ifdef SIGTINT
341         GREnableTablet();
342               /*  Allow keyboard interrupts while waiting
343                * for cursor input.
344                */
345         sigrelse(SIGTINT);
346         button = GRGetButton(tablet, &cux, &cuy);
347               /*  Ignore keyboard interrupts while processing commands.
348                */
349         sighold(SIGTINT);
350         GRDisableTablet();
351         TxMsgOK();
352         MNInterpretCursor(button, cux, cuy);
353         if (Consume) CP();
354 #else SIGTINT
355         i = 1 << fileno(stdin);
356         GREnableTablet();
357         i |= (1 << fileno(tablet));
358         (void) select(20, &i, 0, 0, 0);
359         if (i & (1 << fileno(stdin)))
360         {
361             TxMsgOK();
362             OnCommand();
363         }
364         else
365         {
366             if ((button = GRGetButton(tablet, &cux, &cuy)) != -4)
367             {
368                 GRDisableTablet();
369                 TxMsgOK();
370                 MNInterpretCursor(button, cux, cuy);
371                 if (Consume) CP();
372             }
373         }
374 #endif SIGTINT
375 
376     }  /* end while */
377 
378 }  /* end main */
379 
380 
381 OnStop(signo)
382 int signo;
383 
384 /*-----------------------------------------------------------------------------
385  *    This procedure handles stop signals.
386  *
387  *    Results:    None.
388  *
389  *    Side Effects:
390  *    The text display is reset, we wait to get restarted, then
391  *    redisplay text.
392  *-----------------------------------------------------------------------------
393  */
394 
395 {
396     TxClose();
397     signal(signo, SIG_DFL);
398     sigsetmask(0);
399     (void) kill(0, signo);
400     signal(signo, OnStop);
401     SHRedis();
402 }
403 
404 
405 OnCommand()
406 
407 /*-----------------------------------------------------------------------------
408  *    This routine responds to interrupts from the command terminal and
409  *    then processes commands as long as there is input.
410  *
411  *    Results:    None.
412  *
413  *    Side Effects:
414  *    Whatever is done by the commands.
415  *-----------------------------------------------------------------------------
416  */
417 
418 {
419 
420 #ifdef SIGTINT
421     long charcount;
422 #else SIGTINT
423     int i;
424     struct timeval selectpoll;
425 #endif SIGTINT
426 
427     static char cmd, lastcmd;
428     int repeat;
429 
430     GRDisableTablet();
431 
432 #ifdef SIGTINT
433     (void) ioctl(fileno(stdin), TIOCLBIC, (char *) &lintrup);
434 #endif SIGTINT
435 
436 
437     while (TRUE)
438     {
439 
440     /* If there is no more input, then reenable the signal and return */
441 
442 
443 #ifdef SIGTINT
444     (void) ioctl(fileno(stdin), FIONREAD, (char *) &charcount);
445     if (charcount == 0)
446     {
447         GREnableTablet();
448         (void) ioctl(fileno(stdin), TIOCLBIS, (char *) &lintrup);
449         return;
450     }
451 #else SIGTINT
452     i = 1 << fileno(stdin);
453     selectpoll.tv_sec = 0l;
454     selectpoll.tv_usec = 0l;
455     if (select(20, &i, 0, 0, &selectpoll) <= 0)
456     {
457         GREnableTablet();
458         return;
459     }
460 #endif SIGTINT
461 
462 
463     /* Read the command and call the long or short command routine */
464 
465     cmd = TxGetChar();
466     if (cmd == '.')
467     {
468         repeat = TRUE;
469         cmd = lastcmd;
470     }
471     else
472     {
473         repeat = FALSE;
474         lastcmd = cmd;
475     }
476     if (cmd == ':')
477     {
478         if (!repeat) TxGetLine(":",cmdbuf,400);
479         LGCommand(cmdbuf);
480     }
481     else
482     {
483         TxLine(inline);
484         if (cmd != '\') putchar(cmd);
485         (void) fflush(stdout);
486         SHCommand(&cmd);
487     }
488     TxLine(inline);
489     printf("                                                                              ");
490     TxLine(inline);
491     if (Consume) CP();
492     Consume = TRUE;
493     UNForget();
494     }
495 }
496 
497