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 *) >tyBuf); 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(®s, ®s); 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