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