1: /***************************************************************************
   2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
   3:  * is provided to you without charge, and with no warranty.  You may give  *
   4:  * away copies of JOVE, including sources, provided that this notice is    *
   5:  * included in all the files.                                              *
   6:  ***************************************************************************/
   7: 
   8: /* Contains the main loop initializations, and some system dependent
   9:    type things, e.g. putting terminal in CBREAK mode, etc. */
  10: 
  11: #include "jove.h"
  12: #include "io.h"
  13: #include "termcap.h"
  14: 
  15: #ifdef MAC
  16: #	include "mac.h"
  17: #else
  18: #	include <varargs.h>
  19: #	include <sys/stat.h>
  20: #endif
  21: 
  22: #include <signal.h>
  23: #include <errno.h>
  24: 
  25: #ifdef UNIX
  26: #	ifndef SYSV
  27: #		include <sgtty.h>
  28: #	else
  29: #		include <termio.h>
  30: #	endif /* SYSV */
  31: #endif /* UNIX */
  32: 
  33: #ifdef MSDOS
  34: #	include <process.h>
  35: #endif /* MSDOS */
  36: 
  37: #ifndef MAC
  38: #	include <fcntl.h>
  39: #endif
  40: 
  41: #ifdef MAC
  42: #	undef private
  43: #	define private
  44: #endif
  45: 
  46: #ifdef  LINT_ARGS
  47: extern  long    time(long *);
  48: private void    break_off(void);
  49: private void    break_rst(void);
  50: #else
  51: extern  long    time();
  52: private void    break_off();
  53: private void    break_rst();
  54: #endif
  55: 
  56: #ifdef MAC
  57: #	undef private
  58: #	define private static
  59: #endif
  60: 
  61: #ifdef UNIX
  62: #   ifdef TIOCSLTC
  63: struct ltchars  ls1, ls2;
  64: #   endif /* TIOCSLTC */
  65: 
  66: #   ifdef TIOCGETC
  67: struct tchars   tc1, tc2;
  68: #   endif
  69: 
  70: #   ifdef PASS8         /* use pass8 instead of raw for meta-key */
  71: int lmword1, lmword2;   /* local mode word */
  72: #   endif
  73: 
  74: #   ifdef BRLUNIX
  75: struct sg_brl   sg1, sg2;
  76: #   else
  77: #	ifdef SYSV
  78: struct termio   sg1, sg2;
  79: #	else /* SYSV */
  80: struct sgttyb   sg1, sg2;
  81: #	endif /* SYSV */
  82: #   endif /* BRLUNIX */
  83: 
  84: #   ifdef BIFF
  85: private struct stat tt_stat;    /* for biff */
  86: #	ifndef BSD4_2
  87: private char    *tt_name = 0;       /* name of the control tty */
  88: extern char *ttyname();     /* for systems w/o fchmod ... */
  89: #	endif
  90: private int dw_biff = NO;       /* whether or not to fotz at all */
  91: #   endif /* BIFF */
  92: #endif /* UNIX */
  93: 
  94: int errormsg;
  95: extern char *tfname;
  96: char    NullStr[] = "";
  97: 
  98: #ifdef MSDOS
  99: #    define SIGHUP  99
 100: #endif /* MSDOS */
 101: 
 102: void
 103: finish(code)
 104: {
 105:     int CoreDump = (code != 0 && code != SIGHUP),
 106:         DelTmps = 1;        /* Usually we delete them. */
 107: 
 108:     if (code == SIGINT) {
 109:         char    c;
 110: 
 111: #ifndef MENLO_JCL
 112:         (void) signal(code, finish);
 113: #endif
 114:         f_mess("Abort (Type 'n' if you're not sure)? ");
 115: #ifndef MSDOS
 116:         (void) read(0, &c, 1);
 117: #else /* MSDOS */
 118:         c = getrawinchar();
 119: #endif /* MSDOS */
 120:         message(NullStr);
 121:         if ((c & 0377) != 'y') {
 122:             redisplay();
 123:             return;
 124:         }
 125:     }
 126:     ttyset(OFF);
 127:     UnsetTerm(NullStr);
 128: #ifndef MSDOS
 129:     if (code != 0) {
 130:         if (!Crashing) {
 131:             Crashing = YES;
 132:             lsave();
 133:             SyncRec();
 134:             printf("JOVE CRASH!! (code %d)\n", code);
 135:             if (ModBufs(1)) {
 136:                 printf("Your buffers have been saved.\n");
 137:                 printf("Use \"jove -r\" to have a look at them.\n");
 138:                 DelTmps = 0;    /* Don't delete anymore. */
 139:             } else
 140:                 printf("You didn't lose any work.\n");
 141:         } else
 142:             printf("\r\nYou may have lost your work!\n");
 143:     }
 144: #endif /* MSDOS */
 145:     flusho();
 146:     if (DelTmps) {
 147:         tmpclose();
 148: #ifndef MSDOS
 149:         recclose();
 150: #endif /* MSDOS */
 151:     }
 152: #ifdef UNIX
 153:     if (CoreDump)
 154:         abort();
 155: #ifdef PROFILING
 156:     monitor(0);
 157: #endif
 158:     _exit(0);
 159: #else /* MSDOS or MAC*/
 160: #ifdef MSDOS
 161:     break_rst();    /* restore previous ctrl-c handling */
 162: #endif
 163:     exit(0);
 164: #endif /* UNIX */
 165: }
 166: 
 167: private char    smbuf[20],
 168:         *bp = smbuf;
 169: private int nchars = 0;
 170: 
 171: private char    peekbuf[10],
 172:         *peekp = peekbuf;
 173: 
 174: #if defined(SYSV) || defined(M_XENIX)
 175: void
 176: setblock(fd, on)    /* turn blocking on or off */
 177: register int    fd, on;
 178: {
 179:     static int blockf, nonblockf;
 180:     static int first = 1;
 181:     int flags;
 182: 
 183:     if (first) {
 184:     first = 0;
 185:     if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
 186:         finish(SIGHUP);
 187:     blockf = flags & ~O_NDELAY; /* make sure O_NDELAY is off */
 188:     nonblockf = flags | O_NDELAY;   /* make sure O_NDELAY is on */
 189:     }
 190:     if (fcntl(fd, F_SETFL, on ? blockf : nonblockf) == -1)
 191:     finish(SIGHUP);
 192: }
 193: #endif /* SYSV */
 194: 
 195: int
 196: Peekc()
 197: {
 198:     int c;
 199: 
 200:     if (peekp == peekbuf)
 201:         c = -1;
 202:     else
 203:         c = *--peekp & 0377;
 204:     return c;
 205: }
 206: 
 207: void
 208: Ungetc(c)
 209: {
 210:     if (peekp == &peekbuf[(sizeof peekbuf) - 1])
 211:         return;     /* Sorry, can't oblige you ... */
 212:     *peekp++ = c;
 213: }
 214: 
 215: int InputPending = 0;
 216: 
 217: char    *Inputp = 0;
 218: 
 219: #if (defined(IPROCS) && !defined(PIPEPROCS))    /* that is, if ptys */
 220: getchar()
 221: {
 222:     extern long global_fd;
 223:     long        reads;
 224:     extern int  NumProcs,
 225:             errno;
 226:     register int    tmp,
 227:             nfds;
 228:     int     c;
 229: 
 230:     if (nchars <= 0) {
 231:         /* Get a character from the keyboard, first checking for
 232: 		   any input from a process.  Handle that first, and then
 233: 		   deal with the terminal input. */
 234:         do {
 235:             do {
 236:                 reads = global_fd;
 237:                 nfds = select(32, &reads, (long *) 0, (long *) 0, (struct timeval *) 0);
 238:             } while (nfds < 0 && errno == EINTR);
 239: 
 240:             if (nfds == -1)
 241:                 complain("\rerror %d in select %ld", errno, global_fd);
 242:             else {
 243:                 if (reads & 01) {
 244:                     nchars = read(0, smbuf, sizeof(smbuf));
 245:                     reads &= ~01;
 246:                     nfds -= 1;
 247:                 }
 248:                 while (nfds--) {
 249:                     tmp = ffs(reads) - 1;
 250:                     read_proc(tmp);
 251:                     reads &= ~(1L << tmp);
 252:                 }
 253:             }
 254:         } while (nchars <= 0);
 255: 
 256:         if (nchars <= 0)
 257:             finish(SIGHUP);
 258: 
 259:         bp = smbuf;
 260:         InputPending = (nchars > 1);
 261:     }
 262: 
 263:     if (((c = *bp) & 0200) && MetaKey != 0) {
 264:         *bp = (c & CHARMASK);
 265:         return '\033';
 266:     }
 267:     nchars -= 1;
 268:     return *bp++ & 0377;
 269: }
 270: 
 271: #else
 272: 
 273: getchar()
 274: {
 275:     extern int  errno;
 276:     register int    c;
 277: 
 278:     if (nchars <= 0) {
 279:         bp = smbuf;
 280: #ifdef MSDOS
 281:         *bp = getrawinchar();
 282:         nchars = 1;
 283: #else
 284:         do
 285:             nchars = read(0, smbuf, sizeof smbuf);
 286: #   ifdef SYSV
 287:         while (nchars == 0 || (nchars < 0 && errno == EINTR));
 288:         if (nchars < 0)
 289: #   else
 290:         while (nchars < 0 && errno == EINTR);
 291:         if (nchars <= 0)
 292: #   endif /* SYSV */
 293:             finish(SIGHUP);
 294: #endif MSDOS
 295:         InputPending = nchars > 1;
 296:     }
 297:     if (((c = *bp) & 0200) && MetaKey != 0) {
 298:         *bp = (c & CHARMASK);
 299:         return '\033';
 300:     }
 301:     nchars -= 1;
 302:     return (*bp++ & CHARMASK);
 303: }
 304: 
 305: #endif /* IPROCS */
 306: 
 307: /* Returns non-zero if a character waiting */
 308: 
 309: int
 310: charp()
 311: {
 312: #ifndef MSDOS
 313:     int some = 0;
 314: #endif /* MSDOS */
 315: 
 316:     if (InJoverc != 0 || nchars > 0 || Inputp != 0)
 317:         return 1;
 318: #ifdef BRLUNIX
 319:     {
 320:         static struct sg_brl gttyBuf;
 321: 
 322:         gtty(0, (char *) &gttyBuf);
 323:         if (gttyBuf.sg_xflags & INWAIT)
 324:             some += 1;
 325:     }
 326: #endif
 327: #ifdef FIONREAD
 328:     {
 329:         long c;
 330: 
 331:         if (ioctl(0, FIONREAD, (struct sgttyb *) &c) == -1)
 332:             c = 0;
 333:         some = (c > 0);
 334:     }
 335: #endif /* FIONREAD */
 336: #if defined(SYSV) || defined(M_XENIX)
 337:     setblock(0, 0);     /* turn blocking off */
 338:     nchars = read(0, smbuf, sizeof smbuf);  /* Is anything there? */
 339:     setblock(0, 1);     /* turn blocking on */
 340:     if (nchars > 0)     /* something was there */
 341:         bp = smbuf;     /* make sure bp points to it */
 342:     some = (nchars > 0);    /* just say we found something */
 343: #endif /* SYSV */
 344: #ifdef c70
 345:     some = !empty(0);
 346: #endif
 347: #ifdef MSDOS
 348:     return rawkey_ready();
 349: #else
 350: #ifdef MAC
 351:     some = rawchkc();
 352: #endif
 353:     return some;
 354: #endif /* MSDOS */
 355: }
 356: 
 357: #ifdef TERMCAP
 358: void
 359: ResetTerm()
 360: {
 361:     putpad(TI, 1);
 362:     putpad(VS, 1);
 363:     putpad(KS, 1);
 364: #ifndef MSDOS
 365:     (void) chkmail(YES);    /* force it to check to we can be accurate */
 366: #endif
 367: #ifdef BIFF
 368:     if (BiffChk != dw_biff)
 369:         biff_init();
 370:     /* just in case we changed our minds about whether to deal with
 371: 	   biff */
 372: #endif
 373:     do_sgtty();     /* this is so if you change baudrate or stuff
 374: 				   like that, JOVE will notice. */
 375:     ttyset(ON);
 376: }
 377: 
 378: void
 379: UnsetTerm(mesg)
 380: char    *mesg;
 381: {
 382:     ttyset(OFF);
 383:     putpad(KE, 1);
 384:     putpad(VE, 1);
 385:     putpad(TE, 1);
 386: #ifdef ID_CHAR
 387:     INSmode(0);
 388: #endif
 389:     Placur(ILI, 0);
 390:     printf("%s", mesg);
 391:     putpad(CE, 1);
 392:     flusho();
 393: }
 394: #endif /* TERMCAP */
 395: 
 396: #ifdef JOB_CONTROL
 397: PauseJove()
 398: {
 399:     UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr);
 400:     (void) kill(0, SIGTSTP);
 401:     ResetTerm();
 402:     ClAndRedraw();
 403: }
 404: #endif
 405: 
 406: 
 407: #ifndef MAC
 408: void
 409: Push()
 410: {
 411:     int
 412: #ifndef MSDOS
 413:         pid,
 414:         (*old_quit)() = signal(SIGQUIT, SIG_IGN),
 415: #endif /* MSDOS */
 416:         (*old_int)() = signal(SIGINT, SIG_IGN);
 417: 
 418: #ifndef MSDOS
 419: #ifdef IPROCS
 420:     sighold(SIGCHLD);
 421: #endif
 422:     switch (pid = fork()) {
 423:     case -1:
 424:         complain("[Fork failed]");
 425: 
 426:     case 0:
 427:         UnsetTerm(NullStr);
 428: #ifdef IPROCS
 429:         sigrelse(SIGCHLD);
 430: #endif
 431:         (void) signal(SIGTERM, SIG_DFL);
 432: #else /* MSDOS */
 433:     UnsetTerm(NullStr);
 434: #endif /* MSDOS */
 435:         (void) signal(SIGINT, SIG_DFL);
 436: #ifdef UNIX
 437:         (void) signal(SIGQUIT, SIG_DFL);
 438:         execl(Shell, basename(Shell), (char *)0);
 439:         message("[Execl failed]");
 440:         _exit(1);
 441:     }
 442:         dowait(pid, (int *) 0);
 443: #ifdef IPROCS
 444:     sigrelse(SIGCHLD);
 445: #endif
 446: #endif /* UNIX */
 447: #ifdef MSDOS
 448:     break_rst();
 449:     if (spawnl(0, Shell, basename(Shell), (char *)0) == -1)
 450:         message("[Spawn failed]");
 451: #endif /* MSDOS */
 452:         ResetTerm();
 453:         ClAndRedraw();
 454: #ifndef MSDOS
 455:     (void) signal(SIGQUIT, old_quit);
 456: #else /* MSDOS */
 457:     break_off();
 458: #ifdef CHDIR
 459:     getCWD();
 460: #endif
 461: #endif /* MSDOS */
 462:         (void) signal(SIGINT, old_int);
 463: }
 464: #endif /* MAC */
 465: 
 466: int OKXonXoff = 0,      /* ^S and ^Q initially DON'T work */
 467:     IntChar = CTL(']');
 468: 
 469: void
 470: ttsize()
 471: {
 472: #ifdef UNIX
 473: #   ifdef TIOCGWINSZ
 474:     struct winsize win;
 475: 
 476:     if (ioctl (0, TIOCGWINSZ, &win) == 0) {
 477:         if (win.ws_col)
 478:             CO = win.ws_col;
 479:         if (win.ws_row)
 480:             LI = win.ws_row;
 481:     }
 482: #   else /* TIOCGWINSZ */
 483: #	ifdef BTL_BLIT
 484: #include <sys/jioctl.h>
 485:     struct jwinsize jwin;
 486: 
 487:     if (ioctl(0, JWINSIZE, &jwin) == 0) {
 488:         if (jwin.bytesx)
 489:             CO = jwin.bytesx;
 490:         if (jwin.bytesy)
 491:             LI = jwin.bytesy;
 492:     }
 493: #	endif /* BTL_BLIT */
 494: #   endif /* TIOCGWINSZ */
 495: #endif /* UNIX */
 496:     ILI = LI - 1;
 497: }
 498: 
 499: #ifdef BIFF
 500: biff_init()
 501: {
 502:     dw_biff = ((BiffChk) &&
 503: #   ifndef BSD4_2
 504:            ((tt_name != 0) || (tt_name = ttyname(0))) &&
 505:            (stat(tt_name, &tt_stat) != -1) &&
 506: #   else
 507:            (fstat(0, &tt_stat) != -1) &&
 508: #   endif
 509:            (tt_stat.st_mode & S_IEXEC));    /* he's using biff */
 510: 
 511: }
 512: 
 513: biff(on)
 514: {
 515:     if (dw_biff == NO)
 516:         return;
 517: #   ifndef BSD4_2
 518:     (void) chmod(tt_name, on ? tt_stat.st_mode :
 519:                    (tt_stat.st_mode & ~S_IEXEC));
 520: #   else
 521:     (void) fchmod(0, on ? tt_stat.st_mode :
 522:                   (tt_stat.st_mode & ~S_IEXEC));
 523: #   endif
 524: }
 525: 
 526: #endif /* BIFF */
 527: 
 528: void
 529: ttinit()
 530: {
 531: #ifdef BIFF
 532:     biff_init();
 533: #endif
 534: #ifdef TIOCSLTC
 535:     (void) ioctl(0, TIOCGLTC, (struct sgttyb *) &ls1);
 536:     ls2 = ls1;
 537:     ls2.t_suspc = (char) -1;
 538:     ls2.t_dsuspc = (char) -1;
 539:     ls2.t_flushc = (char) -1;
 540:     ls2.t_lnextc = (char) -1;
 541: #endif
 542: 
 543: #ifdef TIOCGETC
 544:     /* Change interupt and quit. */
 545:     (void) ioctl(0, TIOCGETC, (struct sgttyb *) &tc1);
 546:     tc2 = tc1;
 547:     tc2.t_intrc = IntChar;
 548:     tc2.t_quitc = (char) -1;
 549:     if (OKXonXoff) {
 550:         tc2.t_stopc = (char) -1;
 551:         tc2.t_startc = (char) -1;
 552:     }
 553: #endif /* TIOCGETC */
 554:     do_sgtty();
 555: }
 556: 
 557: private int done_ttinit = 0;
 558: 
 559: void
 560: do_sgtty()
 561: {
 562: #ifdef UNIX
 563: # ifdef SYSV
 564:     (void) ioctl(0, TCGETA, (char *) &sg1);
 565: # else
 566:     (void) gtty(0, &sg1);
 567: # endif /* SYSV */
 568:     sg2 = sg1;
 569: 
 570: # ifdef LPASS8
 571:     (void) ioctl(0, TIOCLGET, &lmword1);
 572:     lmword2 = lmword1;
 573:     if (MetaKey == YES)
 574:         lmword2 |= LPASS8;
 575: # endif
 576: 
 577: # ifdef SYSV
 578:     TABS = !((sg1.c_oflag & TAB3) == TAB3);
 579:     ospeed = sg1.c_cflag & CBAUD;
 580: 
 581:     if (OKXonXoff)
 582:         sg2.c_iflag &= ~(IXON | IXOFF);
 583:     sg2.c_iflag &= ~(INLCR|ICRNL|IGNCR);
 584:     sg2.c_lflag &= ~(ISIG|ICANON|ECHO);
 585:     sg2.c_oflag &= ~(OCRNL|ONLCR);
 586:     sg2.c_cc[VMIN] = sizeof smbuf;
 587:     sg2.c_cc[VTIME] = 1;
 588: # else
 589:     TABS = !(sg1.sg_flags & XTABS);
 590:     ospeed = sg1.sg_ospeed;
 591: #  ifdef BRLUNIX
 592:     sg2.sg_flags &= ~(ECHO | CRMOD);
 593:     sg2.sg_flags |= CBREAK;
 594: 
 595:     /* VT100 Kludge: leave STALL on for flow control if DC3DC1 (Yuck.) */
 596:     sg2.sg_xflags &= ~((sg2.sg_xflags&DC3DC1 ? 0 : STALL) | PAGE);
 597: #  else
 598:     sg2.sg_flags &= ~(ECHO | CRMOD);
 599: #  endif /* BRLUNIX */
 600: 
 601: #  ifdef PURDUE_EE
 602: #   ifdef pdp11
 603:     sg2.sg_flags |= RAW;
 604: #   else
 605:     sg2.sg_flags |= (MetaKey ? RAW : CBREAK);
 606: #   endif
 607: #  else
 608: #   ifdef LPASS8
 609:     sg2.sg_flags |= CBREAK;
 610: #   else
 611:     sg2.sg_flags |= (MetaKey ? RAW : CBREAK);
 612: #   endif
 613: #  endif /* PURDUE_EE */
 614: # endif /* SYSV */
 615: #endif /* UNIX */
 616: 
 617: #ifdef MSDOS
 618: # ifndef IBMPC
 619:     setmode(1, 0x8000);
 620: # endif /* IBMPC */
 621:     TABS = 0;
 622: #endif /* MSDOS */
 623: }
 624: 
 625: void
 626: tty_reset()
 627: {
 628:     if (!done_ttinit)
 629:         return;
 630:     ttyset(OFF);    /* go back to original modes */
 631:     ttinit();
 632:     ttyset(ON);
 633: }
 634: 
 635: /* If n is OFF reset to original modes */
 636: 
 637: void
 638: ttyset(n)
 639: {
 640:     if (!done_ttinit && n == 0) /* Try to reset before we've set! */
 641:         return;
 642: #ifdef UNIX
 643: # ifdef SYSV
 644:     (void) ioctl(0, TCSETAW, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2);
 645: # else
 646: #  ifdef BRLUNIX
 647:     (void) stty(0, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2);
 648: #  else
 649:     (void) ioctl(0, TIOCSETN, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2);
 650: #  endif /* BRLUNIX */
 651: # endif /* SYSV */
 652: 
 653: # ifdef TIOCSETC
 654:     (void) ioctl(0, TIOCSETC, n == 0 ? (struct sgttyb *) &tc1 : (struct sgttyb *) &tc2);
 655: # endif /* TIOCSETC */
 656: # ifdef TIOCSLTC
 657:     (void) ioctl(0, TIOCSLTC, n == 0 ? (struct sgttyb *) &ls1 : (struct sgttyb *) &ls2);
 658: # endif /* TIOCSLTC */
 659: # ifdef LPASS8
 660:     (void) ioctl(0, TIOCLSET, n == 0 ? &lmword1 : &lmword2);
 661: # endif
 662: #endif /* UNIX */
 663: 
 664: #ifdef MSDOS
 665: # ifndef IBMPC
 666:     setmode(1, n == 0 ? 0x4000 : 0x8000);
 667: # endif
 668: #endif /* MSDOS */
 669:     done_ttinit = 1;
 670: #ifdef BIFF
 671:     biff(!n);
 672: #endif
 673: }
 674: 
 675: int this_cmd,
 676:     last_cmd;
 677: 
 678: int LastKeyStruck,
 679:     MetaKey = 0;
 680: 
 681: int
 682: getch()
 683: {
 684:     register int    c,
 685:             peekc;
 686: #ifdef IPROCS
 687:     extern int  NumProcs;
 688: #endif
 689:     extern int  ModCount,
 690:             Interactive;
 691: 
 692:     if (Inputp) {
 693:         if ((c = *Inputp++) != 0)
 694:             return LastKeyStruck = c;
 695:         Inputp = 0;
 696:     }
 697: 
 698:     if (InJoverc)
 699:         return EOF; /* somethings wrong if Inputp runs out while
 700: 				   we're reading a .joverc file. */
 701: 
 702: #ifndef MSDOS
 703:     if (ModCount >= SyncFreq) {
 704:         ModCount = 0;
 705:         SyncRec();
 706:     }
 707: #endif /* MSDOS */
 708: 
 709:     /* If we're not interactive and we're not executing a macro,
 710: 	   AND there are no ungetc'd characters, we read from the
 711: 	   terminal (i.e., getch()).  And characters only get put
 712: 	   in macros from inside this if. */
 713:     if (((peekc = c = Peekc()) == -1) && (Interactive || ((c = mac_getc()) == -1))) {
 714:         /* So messages that aren't error messages don't
 715: 		   hang around forever. */
 716:         if (!UpdMesg && !Asking) {  /* Don't erase if we are asking */
 717:             if (mesgbuf[0] && !errormsg)
 718:                 message(NullStr);
 719:         }
 720:         redisplay();
 721: #if defined(IPROCS) && defined(PIPEPROCS)
 722:         if (NumProcs > 0) {
 723:             sigrelse(INPUT_SIG);
 724:             sigrelse(SIGCHLD);
 725:         }
 726: #endif
 727: #ifdef UNIX
 728:         inIOread = 1;
 729: #endif
 730:         if ((c = getchar()) == EOF)
 731:             finish(SIGHUP);
 732: #ifdef UNIX
 733:         inIOread = 0;
 734: #endif
 735: 
 736: #if defined(IPROCS) && defined(PIPEPROCS)
 737:         if (NumProcs > 0) {
 738:             sighold(INPUT_SIG);
 739:             sighold(SIGCHLD);
 740:         }
 741: #endif
 742:         if (!Interactive && InMacDefine)
 743:             mac_putc(c);
 744:     }
 745:     if (peekc == -1)    /* don't add_stroke peekc's */
 746:         add_stroke(c);
 747:     return LastKeyStruck = c;
 748: }
 749: 
 750: #ifdef UNIX
 751: dorecover()
 752: {
 753:     execl(Recover, "recover", "-d", TmpFilePath, (char *) 0);
 754:     printf("%s: execl failed!\n", Recover);
 755:     flusho();
 756:     _exit(-1);
 757: }
 758: #endif /* UNIX */
 759: 
 760: void
 761: ShowVersion()
 762: {
 763:     extern char *version;
 764: 
 765:     s_mess("Jonathan's Own Version of Emacs (%s)", version);
 766: }
 767: 
 768: void
 769: UNIX_cmdline(argc, argv)
 770: char    *argv[];
 771: {
 772:     int lineno = 0,
 773:         nwinds = 1;
 774:     Buffer  *b;
 775: 
 776:     ShowVersion();
 777:     while (argc > 1) {
 778:         if (argv[1][0] != '-' && argv[1][0] != '+') {
 779:             int force = (nwinds > 0 || lineno != 0);
 780: 
 781: #ifdef MSDOS
 782:             strlwr(argv[1]);
 783: #endif
 784:             minib_add(argv[1], force ? YES : NO);
 785:             b = do_find(nwinds > 0 ? curwind : (Window *) 0,
 786:                     argv[1], force);
 787:             if (force) {
 788:                 SetABuf(curbuf);
 789:                 SetBuf(b);
 790:                 if (lineno >= 0)
 791:                     SetLine(next_line(curbuf->b_first, lineno));
 792:                 else
 793:                     SetLine(curbuf->b_last);
 794:                 if (nwinds > 1)
 795:                     NextWindow();
 796:                 if (nwinds)
 797:                     nwinds -= 1;
 798:             }
 799:             lineno = 0;
 800:         } else  switch (argv[1][1]) {
 801:             case 'd':
 802:                 argv += 1;
 803:                 argc -= 1;
 804:                 break;
 805: 
 806:             case 'j':   /* Ignore .joverc in HOME */
 807:                 break;
 808: #ifndef MAC
 809:             case 'p':
 810:                 argv += 1;
 811:                 argc -= 1;
 812:                 if (argv[1] != 0) {
 813:                     SetBuf(do_find(curwind, argv[1], 0));
 814:                     ErrParse();
 815:                     nwinds = 0;
 816:                 }
 817:                 break;
 818: #endif
 819:             case 't':
 820:                 /* check if syntax is -tTag or -t Tag */
 821:                 if (argv[1][2] != 0) {
 822:                     find_tag(&(argv[1][2]), YES);
 823:                 } else {
 824:                     argv += 1;
 825:                     argc -= 1;
 826:                     if (argv[1] != 0)
 827:                         find_tag(argv[1], YES);
 828:                 }
 829:                 break;
 830: 
 831:             case 'w':
 832:                 if (argv[1][2] == '\0')
 833:                     nwinds += 1;
 834:                 else {
 835:                     int n;
 836: 
 837:                     (void) chr_to_int(&argv[1][2], 10, NO, &n);
 838:                     nwinds += -1 + n;
 839:                 }
 840:                 (void) div_wind(curwind, nwinds - 1);
 841:                 break;
 842: 
 843:             case '0':
 844:             case '1':
 845:             case '2':
 846:             case '3':
 847:             case '4':
 848:             case '5':
 849:             case '6':
 850:             case '7':
 851:             case '8':
 852:             case '9':
 853:                 (void) chr_to_int(&argv[1][1], 10, NO, &lineno);
 854:                 lineno -= 1;
 855:                 break;
 856:             case  0:
 857:                 lineno = -1;    /* goto end of file ... */
 858:                 break;      /* just like some people's */
 859:         }               /* favourite editor */
 860:         argv += 1;
 861:         argc -= 1;
 862:     }
 863: }
 864: 
 865: /* VARARGS1 */
 866: 
 867: void
 868: error(fmt, va_alist)
 869: char    *fmt;
 870: va_dcl
 871: {
 872:     va_list ap;
 873: 
 874:     if (fmt) {
 875:         va_start(ap);
 876:         format(mesgbuf, sizeof mesgbuf, fmt, ap);
 877:         va_end(ap);
 878:         UpdMesg = YES;
 879:     }
 880:     rbell();
 881:     longjmp(mainjmp, ERROR);
 882: }
 883: 
 884: /* VARARGS1 */
 885: 
 886: void
 887: complain(fmt, va_alist)
 888: char    *fmt;
 889: va_dcl
 890: {
 891:     va_list ap;
 892: 
 893:     if (fmt) {
 894:         va_start(ap);
 895:         format(mesgbuf, sizeof mesgbuf, fmt, ap);
 896:         va_end(ap);
 897:         UpdMesg = YES;
 898:     }
 899:     rbell();
 900:     longjmp(mainjmp, COMPLAIN);
 901: }
 902: 
 903: /* VARARGS1 */
 904: 
 905: void
 906: confirm(fmt, va_alist)
 907: char    *fmt;
 908: va_dcl
 909: {
 910:     char    *yorn;
 911:     va_list ap;
 912: 
 913:     va_start(ap);
 914:     format(mesgbuf, sizeof mesgbuf, fmt, ap);
 915:     va_end(ap);
 916:     yorn = ask((char *) 0, mesgbuf);
 917:     if (*yorn != 'Y' && *yorn != 'y')
 918:         longjmp(mainjmp, COMPLAIN);
 919: }
 920: 
 921: int RecDepth = 0;
 922: 
 923: void
 924: Recur()
 925: {
 926:     char    bname[128];
 927:     Mark    *m;
 928: 
 929:     sprintf(bname, "%s", curbuf->b_name);
 930:     m = MakeMark(curline, curchar, M_FLOATER);
 931: 
 932:     RecDepth += 1;
 933:     UpdModLine = YES;
 934:     DoKeys(1);  /* 1 means not first time */
 935:     UpdModLine = YES;
 936:     RecDepth -= 1;
 937:     SetBuf(do_select(curwind, bname));
 938:     if (!is_an_arg())
 939:         ToMark(m);
 940:     DelMark(m);
 941: }
 942: 
 943: jmp_buf mainjmp;
 944: 
 945: #ifdef MAC
 946: jmp_buf auxjmp;
 947: #endif
 948: 
 949: int iniargc;    /* main sets these for DoKeys() */
 950: char    **iniargv;
 951: 
 952: void
 953: DoKeys(nocmdline)
 954: {
 955:     int c;
 956:     jmp_buf savejmp;
 957: 
 958:     push_env(savejmp);
 959: 
 960:     switch (setjmp(mainjmp)) {
 961:     case 0:
 962:         if (!nocmdline)
 963:             UNIX_cmdline(iniargc, iniargv);
 964:         break;
 965: 
 966:     case QUIT:
 967:         if (RecDepth == 0) {
 968:             if (ModMacs()) {
 969:                 rbell();
 970:                 if (CharUpcase(*ask("No",
 971: "Some MACROS haven't been saved; leave anyway? ")) != 'Y')
 972:                     break;
 973:             }
 974:             if (ModBufs(0)) {
 975:                 rbell();
 976:                 if (CharUpcase(*ask("No",
 977: "Some buffers haven't been saved; leave anyway? ")) != 'Y')
 978:                     break;
 979:             }
 980: #ifdef IPROCS
 981:             KillProcs();
 982: #endif
 983:         }
 984:         pop_env(savejmp);
 985:         return;
 986: 
 987:     case ERROR:
 988:         getDOT();   /* God knows what state linebuf was in */
 989: 
 990:     case COMPLAIN:
 991:         {
 992:         extern int  DisabledRedisplay;
 993: 
 994:         gc_openfiles(); /* close any files we left open */
 995:         errormsg = YES;
 996:         unwind_macro_stack();
 997:         Asking = 0;
 998:         curwind->w_bufp = curbuf;
 999:         DisabledRedisplay = NO;
1000:         redisplay();
1001:         break;
1002:         }
1003:     }
1004: 
1005:     this_cmd = last_cmd = 0;
1006: 
1007:     for (;;) {
1008: #ifdef MAC
1009:         setjmp(auxjmp);
1010: #endif
1011:         if (this_cmd != ARG_CMD) {
1012:             clr_arg_value();
1013:             last_cmd = this_cmd;
1014:             init_strokes();
1015:         }
1016: #ifdef MAC
1017:         HiliteMenu(0);
1018:         EventCmd = 0;
1019:         menus_on();
1020: #endif
1021:         c = getch();
1022:         if (c == -1)
1023:             continue;
1024:         dispatch(c);
1025:     }
1026: }
1027: 
1028: int Crashing = 0;
1029: 
1030: char **
1031: scanvec(args, str)
1032: register char   **args,
1033:         *str;
1034: {
1035:     while (*args) {
1036:         if (strcmp(*args, str) == 0)
1037:             return args;
1038:         args += 1;
1039:     }
1040:     return 0;
1041: }
1042: 
1043: #ifdef UNIX
1044: int UpdFreq = 30,
1045:     inIOread = 0;
1046: 
1047: updmode()
1048: {
1049:     UpdModLine = YES;
1050:     if (inIOread)
1051:         redisplay();
1052: #ifndef JOB_CONTROL
1053:     (void) signal(SIGALRM, updmode);
1054: #endif
1055:     (void) alarm((unsigned) UpdFreq);
1056: }
1057: #endif /* UNIX */
1058: 
1059: #ifndef MSDOS
1060: # if defined(TIOCGWINSZ) && defined(SIGWINCH)
1061: extern win_reshape();
1062: # endif
1063: #else /* MSDOS */
1064: # ifndef IBMPC
1065: char    ttbuf[BUFSIZ];
1066: # endif	/* IBMPC */
1067: #endif /* MSDOS */
1068: 
1069: #if defined(TIOCGWINSZ) && defined(SIGWINCH)
1070: win_reshape()
1071: {
1072:     register int oldsize;
1073:     register int newsize, total;
1074:     register Window *wp;
1075: 
1076:     (void) signal(SIGWINCH, SIG_IGN);
1077: 
1078:     /*
1079: 	 * Save old number of lines.
1080: 	 */
1081:     oldsize = LI;
1082: 
1083:     /*
1084: 	 * Get new line/col info.
1085: 	 */
1086:     ttsize();
1087: 
1088:     /*
1089: 	 * LI has changed, and now holds the
1090: 	 * new value.
1091: 	 */
1092:     /*
1093: 	 *  Go through the window list, changing each window size in
1094: 	 *  proportion to the resize. If a window becomes too small,
1095: 	 *  delete it. We keep track of all the excess lines (caused by
1096: 	 *  roundoff!), and give them to the current window, as a sop -
1097: 	 *  can't be more than one or two lines anyway. This seems fairer
1098: 	 *  than just resizing the current window.
1099: 	 */
1100:     wp = fwind;
1101:     total = 0;
1102:     do {
1103:         newsize = LI * wp->w_height / oldsize;
1104: 
1105:         if (newsize < 2) {
1106:             total += wp->w_height;
1107:             wp = wp->w_next;
1108:             del_wind(wp->w_prev);
1109:         } else {
1110:             wp->w_height = newsize;
1111:             total += newsize;
1112:             wp = wp->w_next;
1113:         }
1114:     } while (wp != fwind);
1115: 
1116:     curwind->w_height += LI - total - 1;
1117: 
1118:     /* Make a new screen structure */
1119:     make_scr();
1120:     /* Do a 'hard' update on the screen - clear and redraw */
1121:     cl_scr(1);
1122:     flusho();
1123:     redisplay();
1124: 
1125:     (void) signal(SIGWINCH, win_reshape);
1126: }
1127: #endif
1128: 
1129: void
1130: 
1131: #ifdef MAC  /* will get args from user, if option key held during launch */
1132: main()
1133: {
1134:     int argc;
1135:     char **argv;
1136: #else
1137: main(argc, argv)
1138: char    *argv[];
1139: {
1140: #endif /* MAC */
1141:     char    *cp;
1142: #ifndef MSDOS
1143:     char    ttbuf[MAXTTYBUF],
1144: # ifndef VMUNIX
1145:         s_iobuff[LBSIZE],
1146:         s_genbuf[LBSIZE],
1147:         s_linebuf[LBSIZE];
1148:     /* The way I look at it, there ain't no way I is gonna run
1149: 	   out of stack space UNLESS I have some kind of infinite
1150: 	   recursive bug.  So why use up some valuable memory, when
1151: 	   there is plenty of space on the stack?  (This only matters
1152: 	   on wimpy pdp11's, of course.) */
1153: 
1154:     iobuff = s_iobuff;
1155:     genbuf = s_genbuf;
1156:     linebuf = s_linebuf;
1157: # endif
1158: 
1159: #else /* MSDOS */
1160:     char    *getenv();
1161: #endif /* MSDOS */
1162: 
1163:     errormsg = 0;
1164: 
1165: #ifdef MAC
1166:     MacInit();      /* initializes all */
1167:     if(make_cache() == 0) exit(-1);
1168:     argc = getArgs(&argv);
1169: #endif /* MAC */
1170: 
1171:     iniargc = argc;
1172:     iniargv = argv;
1173: 
1174:     if (setjmp(mainjmp)) {
1175:         printf("\rAck! I can't deal with error \"%s\" now.\n\r", mesgbuf);
1176:         finish(0);
1177:     }
1178: 
1179: #ifdef MSDOS
1180:     /* import the temporary file path from the environment and
1181: 	   fix the string, so that we can append a slash safely	*/
1182: 
1183:     if (((cp = getenv("TMP")) || (cp = getenv("TMPDIR"))) &&
1184:         (*cp != '\0')) {
1185:         strcpy(TmpFilePath, cp);
1186:         cp = &TmpFilePath[strlen(TmpFilePath)-1];
1187:         if ((*cp == '/') || (*cp == '\\'))
1188:             *cp = 0;
1189:     }
1190:     ShFlags[0] = switchar();
1191: #endif /* MSDOS */
1192: 
1193:     getTERM();  /* Get terminal. */
1194:     if (getenv("METAKEY"))
1195:         MetaKey = 1;
1196:     ttsize();
1197:     InitCM();
1198: #ifdef MAC
1199:     InitEvents();
1200: #endif
1201: 
1202:     d_cache_init();     /* initialize the disk buffer cache */
1203: #ifndef MAC
1204:     if ((cp = getenv("COMSPEC")) && (*cp != '\0')) {
1205:         strcpy(Shell, cp);
1206:     }
1207: #endif
1208: #ifdef MSDOS
1209:     if ((cp = getenv("DESCRIBE")) && (*cp != '\0'))
1210:        strcpy(CmdDb, cp);
1211: #endif /* MSDOS */
1212: 
1213:     make_scr();
1214:     mac_init(); /* Initialize Macros */
1215:     winit();    /* Initialize Window */
1216: #ifdef IPROCS
1217:     pinit();    /* Pipes/process initialization */
1218: #endif
1219:     SetBuf(do_select(curwind, Mainbuf));
1220: 
1221: #ifdef CHDIR
1222:     {
1223:         char    **argp;
1224: 
1225:         if ((argp = scanvec(argv, "-d")) && (argp[1][0] == '/'))
1226:             setCWD(argp[1]);
1227:         else
1228:             getCWD();   /* After we setup curbuf in case we have to getwd() */
1229:     }
1230: #endif
1231:     HomeDir = getenv("HOME");
1232:     if (HomeDir == 0)
1233:         HomeDir = "/";
1234:     HomeLen = strlen(HomeDir);
1235: 
1236: #ifdef UNIX
1237: # ifdef SYSV
1238:     sprintf(Mailbox, "/usr/mail/%s", getenv("LOGNAME"));
1239: # else
1240:     sprintf(Mailbox, "/usr/spool/mail/%s", getenv("USER"));
1241: # endif
1242: #endif
1243: 
1244: #ifdef MSDOS
1245:     if ((cp = getenv("JOVERC")) && (*cp != '\0'))
1246:        (void) joverc(cp);
1247: #endif /* MSDOS */
1248:     (void) joverc(Joverc);
1249:     if (!scanvec(argv, "-j")) {
1250:         char    tmpbuf[100];
1251:         sprintf(tmpbuf, "%s/.joverc", HomeDir);
1252:         (void) joverc(tmpbuf);
1253:     }
1254: #ifndef MSDOS
1255:     if (scanvec(argv, "-r"))
1256:         dorecover();
1257:     if (scanvec(argv, "-rc"))
1258:         FullRecover();
1259: #endif 	/* MSDOS */
1260:     ttinit();   /* initialize terminal (after ~/.joverc) */
1261: #ifndef IBMPC
1262:     settout(ttbuf); /* not until we know baudrate */
1263: #endif
1264: 
1265: #ifdef MSDOS
1266:     (void) signal(SIGINT, SIG_IGN);
1267:     break_off();    /* disable ctrl-c checking */
1268: #endif /* MSDOS */
1269: #ifdef UNIX
1270:     (void) signal(SIGHUP, finish);
1271:     (void) signal(SIGINT, finish);
1272:     (void) signal(SIGBUS, finish);
1273:     (void) signal(SIGSEGV, finish);
1274:     (void) signal(SIGPIPE, finish);
1275:     (void) signal(SIGTERM, SIG_IGN);
1276: # if defined(TIOCGWINSZ) && defined(SIGWINCH)
1277:     (void) signal(SIGWINCH, win_reshape);
1278: # endif
1279:     /* set things up to update the modeline every UpdFreq seconds */
1280:     (void) signal(SIGALRM, updmode);
1281:     (void) alarm((unsigned) (60 - (time((time_t *) 0) % 60)));
1282: #endif /* UNIX */
1283: 
1284:     ResetTerm();
1285:     cl_scr(1);
1286:     flusho();
1287:     RedrawDisplay();    /* start the redisplay process. */
1288:     DoKeys(0);
1289:     finish(0);
1290: }
1291: 
1292: #ifdef MSDOS
1293: 
1294: #include <dos.h>
1295: 
1296: static  char break_state;
1297: 
1298: /* set the break state to off */
1299: private void
1300: break_off()
1301: {
1302:     union REGS regs;
1303: 
1304:     regs.h.ah = 0x33;       /* break status */
1305:     regs.h.al = 0x00;       /* request current state */
1306:     intdos(&regs, &regs);
1307:     break_state = regs.h.dl;
1308:     bdos(0x33, 0, 1);   /* turn off break */
1309: }
1310: 
1311: /* reset the break state */
1312: private void
1313: break_rst()
1314: {
1315:     bdos(0x33, break_state, 1);
1316: }
1317: #endif

Defined functions

DoKeys defined in line 952; used 4 times
PauseJove defined in line 397; used 3 times
Peekc defined in line 195; used 3 times
Push defined in line 408; used 5 times
ResetTerm defined in line 358; used 3 times
ShowVersion defined in line 760; used 5 times
UNIX_cmdline defined in line 768; used 3 times
UnsetTerm defined in line 378; used 4 times
biff defined in line 513; used 1 times
biff_init defined in line 500; used 2 times
break_off defined in line 1299; used 4 times
break_rst defined in line 1312; used 4 times
complain defined in line 886; used 141 times
do_sgtty defined in line 559; used 5 times
dorecover defined in line 751; used 1 times
error defined in line 867; never used
main defined in line 1137; never used
scanvec defined in line 1030; used 6 times
setblock defined in line 175; used 2 times
ttinit defined in line 528; used 4 times
ttsize defined in line 469; used 4 times
ttyset defined in line 637; used 8 times
updmode defined in line 1047; used 4 times
win_reshape defined in line 1070; used 3 times

Defined variables

Crashing defined in line 1028; used 2 times
InputPending defined in line 215; used 8 times
Inputp defined in line 217; used 5 times
LastKeyStruck defined in line 678; used 2 times
MetaKey defined in line 679; used 7 times
OKXonXoff defined in line 466; used 3 times
RecDepth defined in line 921; used 3 times
UpdFreq defined in line 1044; used 3 times
auxjmp defined in line 946; used 1 times
bp defined in line 168; used 10 times
break_state defined in line 1296; used 2 times
done_ttinit defined in line 557; used 3 times
dw_biff defined in line 90; used 3 times
errormsg defined in line 94; used 5 times
iniargc defined in line 949; used 2 times
iniargv defined in line 950; used 2 times
last_cmd defined in line 676; used 4 times
lmword1 defined in line 71; used 3 times
lmword2 defined in line 71; used 3 times
ls1 defined in line 63; used 6 times
ls2 defined in line 63; used 6 times
mainjmp defined in line 943; used 9 times
nchars defined in line 169; used 20 times
peekbuf defined in line 171; used 4 times
peekp defined in line 172; used 4 times
private defined in line 1312; never used
sg1 defined in line 80; used 11 times
sg2 defined in line 80; used 19 times
smbuf defined in line 167; used 11 times
tc1 defined in line 67; used 7 times
tc2 defined in line 67; used 6 times
tt_name defined in line 87; used 4 times
tt_stat defined in line 85; used 7 times
ttbuf defined in line 1065; used 2 times

Defined macros

SIGHUP defined in line 99; used 7 times
private defined in line 58; used 12 times
Last modified: 1988-08-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 421
Valid CSS Valid XHTML 1.0 Strict