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