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
error(s)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
main(argc,argv)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
OnStop(signo)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
OnCommand()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