Subject: v08i024: The JOVE text editor, Part05/13 Newsgroups: mod.sources Approved: mirror!rs Submitted by: seismo!rochester!jpayne (Jonathan Payne) Mod.sources: Volume 8, Issue 24 Archive-name: jove/Part05 #! /bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # If all goes well, you will see the message "End of archive 5 (of 13)." # Contents: jove.c jove.h macros.c malloc.c marks.c setmaps.c PATH=/bin:/usr/bin:/usr/ucb; export PATH echo shar: extracting "'jove.c'" '(19628 characters)' if test -f 'jove.c' ; then echo shar: will not over-write existing file "'jove.c'" else sed 's/^X//' >jove.c <<'@//E*O*F jove.c//' X/************************************************************************ X * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * X * provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ************************************************************************/ X X/* Contains the main loop initializations, and some system dependent X type things, e.g. putting terminal in CBREAK mode, etc. */ X X#include "jove.h" X#include "io.h" X#include "termcap.h" X X#include X#include X#include X#include X#ifndef SYSV X#include X#else X#include X#endif SYSV X#include X X#ifdef TIOCSLTC Xstruct ltchars ls1, X ls2; X#endif TIOCSLTC X X#ifdef TIOCGETC Xstruct tchars tc1, X tc2; X#endif X X#ifdef BRLUNIX Xstruct sg_brl sg1, sg2; X#else X#ifdef SYSV Xstruct termio sg1, sg2; X#else SYSV Xstruct sgttyb sg1, sg2; X#endif SYSV X#endif BRLUNIX X X#ifdef BIFF Xprivate struct stat tt_stat; /* for biff */ X#ifndef BSD4_2 Xprivate char *tt_name = 0; /* name of the control tty */ Xextern char *ttyname(); /* for systems w/o fchmod ... */ X#endif Xprivate int dw_biff = NO; /* whether or not to fotz at all */ X#endif X Xtime_t time0; /* when jove started up */ Xint errormsg; Xextern char *tfname; Xchar NullStr[] = ""; X Xfinish(code) X{ X int CoreDump = (code != 0 && code != SIGHUP), X DelTmps = 1; /* Usually we delete them. */ X X#ifdef LSRHS X if (CoreDump) X setdump(1); X#endif X if (code == SIGINT) { X char c; X X#ifndef MENLO_JCL X (void) signal(code, finish); X#endif X f_mess("Abort (Type 'n' if you're not sure)? "); X (void) read(0, &c, 1); X message(NullStr); X if ((c & 0377) != 'y') { X redisplay(); X return; X } X } X ttyset(OFF); X UnsetTerm(NullStr); X if (code != 0) { X if (!Crashing) { X Crashing++; X lsave(); X SyncRec(); X printf("JOVE CRASH!! (code %d)\n", code); X if (ModBufs(1)) { X printf("Your buffers have been saved.\n"); X printf("Use \"jove_recover\" or \"jove -r\"\n"); X printf("to have a look at them.\n"); X DelTmps = 0; /* Don't delete anymore. */ X } else X printf("You didn't lose any work.\n"); X } else X printf("\r\nYou may have lost your work!\n"); X } X flusho(); X if (DelTmps) { X tmpclose(); X recclose(); X } X if (CoreDump) X abort(); X#ifdef PROFILING X exit(exp_p); X#else X _exit(exp_p); X#endif X} X Xprivate char smbuf[20], X *bp = smbuf; Xprivate int nchars = 0; X Xprivate char peekbuf[10], X *peekp = peekbuf; X X#ifdef SYSV Xvoid Xsetblock(fd, on) /* turn blocking on or off */ Xregister int fd, on; X{ X static int blockf, nonblockf; X static int first = 1; X int flags; X X if (first) { X first = 0; X if ((flags = fcntl(fd, F_GETFL, 0)) == -1) X finish(SIGHUP); X blockf = flags & ~O_NDELAY; /* make sure O_NDELAY is off */ X nonblockf = flags | O_NDELAY; /* make sure O_NDELAY is on */ X } X if (fcntl(fd, F_SETFL, on ? blockf : nonblockf) == -1) X finish(SIGHUP); X return; X} X#endif SYSV X XPeekc() X{ X int c; X X if (peekp == peekbuf) X c = -1; X else X c = *--peekp & 0377; X return c; X} X XUngetc(c) X{ X if (peekp == &peekbuf[(sizeof peekbuf) - 1]) X return; /* Sorry, can't oblige you ... */ X *peekp++ = c; X} X Xchar *Inputp = 0; X X#ifdef IPROCS X#ifdef PIPEPROCS Xgetchar() X{ X extern int errno; X register int c; X X if (nchars <= 0) { X do X nchars = read(0, smbuf, sizeof smbuf); X#ifdef SYSV X while (nchars == 0 || (nchars < 0 && errno == EINTR)); X if (nchars < 0) X#else X while (nchars < 0 && errno == EINTR); X if (nchars <= 0) X#endif SYSV X finish(SIGHUP); X bp = smbuf; X InputPending = nchars > 1; X } X if (((c = *bp) & 0200) && MetaKey != 0) { X *bp = (c & 0177); X return '\033'; X } X nchars--; X return (*bp++ & 0177); X} X#else PIPEPROCS Xgetchar() X{ X extern int global_fd, X NumProcs, X errno; X register int tmp, X nfds; X int reads, X c; X X if (nchars <= 0) { X /* Get a character from the keyboard, first checking for X any input from a process. Handle that first, and then X deal with the terminal input. */ X if (NumProcs > 0) { X do { X do { X reads = global_fd; X nfds = select(32, &reads, (int *) 0, (int *) 0, (struct timeval *) 0); X } while (nfds < 0 && errno == EINTR); X X switch (nfds) { X case -1: X printf("\rerror %d in select %d", errno, global_fd); X global_fd = 1; X break; X default: X if (reads & 01) { X nchars = read(0, smbuf, sizeof(smbuf)); X reads &= ~01; X --nfds; X } X X while (nfds--) { X tmp = ffs(reads) - 1; X read_proc(tmp); X reads &= ~tmp; X } X X break; X } X } while (nchars <= 0); X } else { X do X nchars = read(0, smbuf, sizeof(smbuf)); X while (nchars < 0 && errno == EINTR); X } X X if (nchars <= 0) X finish(SIGHUP); X X bp = smbuf; X InputPending = (nchars > 1); X } X X if (((c = *bp) & 0200) && MetaKey != 0) { X *bp = (c & 0177); X return '\033'; X } X nchars--; X return *bp++ & 0377; X} X#endif PIPEPROCS X#else IPROCS Xgetchar() X{ X extern int errno; X register int c; X X if (nchars <= 0) { X do X nchars = read(0, smbuf, sizeof smbuf); X while (nchars < 0 && errno == EINTR); X X if (nchars <= 0) X finish(SIGHUP); X bp = smbuf; X InputPending = nchars > 1; X } X if (((c = *bp) & 0200) && MetaKey != 0) { X *bp = (c & 0177); X return '\033'; X } X nchars--; X return *bp++ & 0377; X} X#endif IPROCS X Xint InputPending = 0; X X/* Returns non-zero if a character waiting */ X Xcharp() X{ X int some = 0; X X if (InJoverc != 0 || nchars > 0 || Inputp != 0) X return 1; X#ifdef BRLUNIX X { X static struct sg_brl gttyBuf; X X gtty(0, (char *) >tyBuf); X if (gttyBuf.sg_xflags & INWAIT) X some++; X } X#endif X#ifdef FIONREAD X { X long c; X X if (ioctl(0, FIONREAD, (struct sgttyb *) &c) == -1) X c = 0; X some = (c > 0); X } X#endif FIONREAD X#ifdef SYSV X setblock(0, 0); /* turn blocking off */ X nchars = read(0, smbuf, sizeof smbuf); /* Is anything there? */ X setblock(0, 1); /* turn blocking on */ X if (nchars > 0) /* something was there */ X bp = smbuf; /* make sure bp points to it */ X some = (nchars > 0); /* just say we found something */ X#endif SYSV X#ifdef c70 X some = !empty(0); X#endif X return some; X} X XResetTerm() X{ X putpad(TI, 1); X putpad(VS, 1); X putpad(KS, 1); X#ifdef BIFF X if (BiffChk != dw_biff) X biff_init(); X /* just in case we changed our minds about whether to deal with X biff */ X#endif X (void) chkmail(YES); /* force it to check to we can be accurate */ X do_sgtty(); /* this is so if you change baudrate or stuff X like that, JOVE will notice. */ X ttyset(ON); X} X XUnsetTerm(mesg) Xchar *mesg; X{ X ttyset(OFF); X putpad(KE, 1); X putpad(VE, 1); X putpad(TE, 1); X#ifdef ID_CHAR X INSmode(0); X#endif X Placur(ILI, 0); X printf("%s", mesg); X putpad(CE, 1); X flusho(); X} X X#ifdef JOB_CONTROL XPauseJove() X{ X UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr); X (void) kill(0, SIGTSTP); X ResetTerm(); X ClAndRedraw(); X} X#endif X XPush() X{ X int pid, X (*old_int)() = signal(SIGINT, SIG_IGN), X (*old_quit)() = signal(SIGQUIT, SIG_IGN); X X#ifdef IPROCS X sighold(SIGCHLD); X#endif X switch (pid = fork()) { X case -1: X complain("[Fork failed]"); X X case 0: X UnsetTerm(NullStr); X#ifdef IPROCS X sigrelse(SIGCHLD); X#endif X (void) signal(SIGTERM, SIG_DFL); X (void) signal(SIGINT, SIG_DFL); X (void) signal(SIGQUIT, SIG_DFL); X execl(Shell, basename(Shell), (char *)0); X message("[Execl failed]"); X _exit(1); X } X dowait(pid, (int *) 0); X#ifdef IPROCS X sigrelse(SIGCHLD); X#endif X ResetTerm(); X ClAndRedraw(); X (void) signal(SIGQUIT, old_quit); X (void) signal(SIGINT, old_int); X} X Xint OKXonXoff = 0, /* ^S and ^Q initially DON'T work */ X IntChar = CTL(]); X Xttsize() X{ X#ifdef TIOCGWINSZ X struct winsize win; X X if (ioctl (0, TIOCGWINSZ, &win) == 0) { X if (win.ws_col) X CO = win.ws_col; X if (win.ws_row) X LI = win.ws_row; X } X#else TIOCGWINSZ X#ifdef BTL_BLIT X#include X struct jwinsize jwin; X X if (ioctl(0, JWINSIZE, &jwin) == 0) { X if (jwin.bytesx) X CO = jwin.bytesx; X if (jwin.bytesy) X LI = jwin.bytesy; X } X#endif BTL_BLIT X#endif TIOCGWINSZ X ILI = LI - 1; X} X X#ifdef BIFF Xbiff_init() X{ X dw_biff = ((BiffChk) && X#ifndef BSD4_2 X ((tt_name != 0) || (tt_name = ttyname(0))) && X (stat(tt_name, &tt_stat) != -1) && X#else X (fstat(0, &tt_stat) != -1) && X#endif X (tt_stat.st_mode & S_IEXEC)); /* he's using biff */ X X} X Xbiff(on) X{ X if (dw_biff == NO) X return; X#ifndef BSD4_2 X (void) chmod(tt_name, on ? tt_stat.st_mode : X (tt_stat.st_mode & ~S_IEXEC)); X#else X (void) fchmod(0, on ? tt_stat.st_mode : X (tt_stat.st_mode & ~S_IEXEC)); X#endif X} X X#endif X Xttinit() X{ X#ifdef BIFF X biff_init(); X#endif X#ifdef TIOCSLTC X (void) ioctl(0, TIOCGLTC, (struct sgttyb *) &ls1); X ls2 = ls1; X ls2.t_suspc = (char) -1; X ls2.t_dsuspc = (char) -1; X ls2.t_flushc = (char) -1; X ls2.t_lnextc = (char) -1; X#endif X X#ifdef TIOCGETC X /* Change interupt and quit. */ X (void) ioctl(0, TIOCGETC, (struct sgttyb *) &tc1); X tc2 = tc1; X tc2.t_intrc = IntChar; X tc2.t_quitc = (char) -1; X if (OKXonXoff) { X tc2.t_stopc = (char) -1; X tc2.t_startc = (char) -1; X } X#endif TIOCGETC X do_sgtty(); X} X Xprivate int done_ttinit = 0; X Xdo_sgtty() X{ X#ifdef SYSV X (void) ioctl(0, TCGETA, (char *) &sg1); X#else X (void) gtty(0, &sg1); X#endif SYSV X sg2 = sg1; X X#ifdef SYSV X TABS = !((sg1.c_oflag & TAB3) == TAB3); X ospeed = sg1.c_cflag & CBAUD; X X sg2.c_iflag &= ~(INLCR|ICRNL|IGNCR); X sg2.c_lflag &= ~(ISIG|ICANON|ECHO); X sg2.c_oflag &= ~(OCRNL|ONLCR); X sg2.c_cc[VMIN] = sizeof smbuf; X sg2.c_cc[VTIME] = 1; X#else X TABS = !(sg1.sg_flags & XTABS); X ospeed = sg1.sg_ospeed; X#ifdef BRLUNIX X sg2.sg_flags &= ~(ECHO | CRMOD); X sg2.sg_flags |= CBREAK; X X /* VT100 Kludge: leave STALL on for flow control if DC3DC1 (Yuck.) */ X sg2.sg_xflags &= ~((sg2.sg_xflags&DC3DC1 ? 0 : STALL) | PAGE); X#else X sg2.sg_flags &= ~(ECHO | CRMOD); X#endif BRLUNIX X X#ifdef EUNICE X sg2.sg_flags |= RAW; /* Eunice needs RAW mode last I heard. */ X#else X#ifdef PURDUE_EE X# ifdef pdp11 X sg2.sg_flags |= RAW; X# else X sg2.sg_flags |= (MetaKey ? RAW : CBREAK); X# endif X#else X sg2.sg_flags |= (MetaKey ? RAW : CBREAK); X#endif PURDUE_EE X#endif EUNICE X#endif SYSV X} X Xtty_reset() X{ X if (!done_ttinit) X return; X ttyset(OFF); /* go back to original modes */ X ttinit(); X ttyset(ON); X} X X/* If n is OFF reset to original modes */ X Xttyset(n) X{ X if (!done_ttinit && n == 0) /* Try to reset before we've set! */ X return; X#ifdef SYSV X (void) ioctl(0, TCSETAW, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2); X#else X#ifdef BRLUNIX X (void) stty(0, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2); X#else X (void) ioctl(0, TIOCSETN, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2); X#endif BRLUNIX X#endif SYSV X X#ifdef TIOCSETC X (void) ioctl(0, TIOCSETC, n == 0 ? (struct sgttyb *) &tc1 : (struct sgttyb *) &tc2); X#endif TIOCSETC X#ifdef TIOCSLTC X (void) ioctl(0, TIOCSLTC, n == 0 ? (struct sgttyb *) &ls1 : (struct sgttyb *) &ls2); X#endif TIOCSLTC X done_ttinit = 1; X#ifdef BIFF X biff(!n); X#endif X} X Xint this_cmd, X last_cmd; X Xdispatch(c) Xregister int c; X{ X data_obj *cp; X X this_cmd = 0; X cp = mainmap[c & 0177]; X X if (cp == 0) { X rbell(); X exp = 1; X exp_p = errormsg = NO; X message(NullStr); X } else X ExecCmd(cp); X} X Xint LastKeyStruck, X MetaKey = 0; X Xgetch() X{ X register int c, X peekc; X#ifdef IPROCS X extern int NumProcs; X#endif X extern int ModCount, X Interactive; X X if (Inputp) { X if ((c = *Inputp++) != 0) X return LastKeyStruck = c; X Inputp = 0; X } X X if (InJoverc) X return EOF; /* somethings wrong if Inputp runs out while X we're reading a .joverc file. */ X X if (ModCount >= SyncFreq) { X ModCount = 0; X SyncRec(); X } X X /* If we're not interactive and we're not executing a macro, X AND there are no ungetc'd characters, we read from the X terminal (i.e., getch()). And characters only get put X in macros from inside this if. */ X if (((peekc = c = Peekc()) == -1) && (Interactive || ((c = mac_getc()) == -1))) { X /* So messages that aren't error messages don't X hang around forever. */ X if (!UpdMesg && !Asking) { /* Don't erase if we are asking */ X if (mesgbuf[0] && !errormsg) X message(NullStr); X } X redisplay(); X#ifdef IPROCS X# ifdef PIPEPROCS X if (NumProcs > 0) { X sigrelse(INPUT_SIG); X sigrelse(SIGCHLD); X } X# endif X#endif X inIOread = 1; X if ((c = getchar()) == EOF) X finish(SIGHUP); X inIOread = 0; X X#ifdef IPROCS X# ifdef PIPEPROCS X if (NumProcs > 0) { X sighold(INPUT_SIG); X sighold(SIGCHLD); X } X# endif X#endif X if (!Interactive && (KeyMacro.m_flags & DEFINE)) X mac_putc(c); X } X if (peekc == -1) /* Don't add_stroke peekc's */ X add_stroke(c); X return LastKeyStruck = c; X} X Xdorecover() X{ X execl(Recover, "jove_recover", "-d", TmpFilePath, (char *)0); X printf("%s: execl failed!\n", Recover); X flusho(); X _exit(-1); X} X X XShowVersion() X{ X extern char *version; X X s_mess("Jonathan's Own Version of Emacs (%s)", version); X} X XUNIX_cmdline(argc, argv) Xchar *argv[]; X{ X int lineno = 0, X nwinds = 1; X Buffer *b; X X ShowVersion(); X while (argc > 1) { X if (argv[1][0] != '-' && argv[1][0] != '+') { X int force = (nwinds > 0 || lineno != 0); X X minib_add(argv[1], force ? YES : NO); X b = do_find(nwinds > 0 ? curwind : (Window *) 0, X argv[1], force); X if (force) { X SetABuf(curbuf); X SetBuf(b); X SetLine(next_line(curbuf->b_first, lineno)); X if (nwinds > 1) X NextWindow(); X if (nwinds) X nwinds--; X } X lineno = 0; X } else switch (argv[1][1]) { X case 'd': X ++argv; X --argc; X break; X X case 'j': /* Ignore .joverc in HOME */ X break; X X case 'p': X ++argv; X --argc; X SetBuf(do_find(curwind, argv[1], 0)); X ParseAll(); X nwinds = 0; X break; X X case 't': X ++argv; X --argc; X exp_p = YES; X find_tag(argv[1], YES); X break; X X case 'w': X if (argv[1][2] == '\0') X nwinds++; X else X nwinds += -1 + chr_to_int(&argv[1][2], 10, NIL); X (void) div_wind(curwind, nwinds - 1); X break; X X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X lineno = chr_to_int(&argv[1][1], 10, 0) - 1; X break; X } X ++argv; X --argc; X } X} X X/* VARARGS1 */ X Xerror(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X va_list ap; X X if (fmt) { X va_start(ap); X format(mesgbuf, sizeof mesgbuf, fmt, ap); X va_end(ap); X UpdMesg++; X } X rbell(); X (void) longjmp(mainjmp, ERROR); X} X X/* VARARGS1 */ X Xcomplain(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X va_list ap; X X if (fmt) { X va_start(ap); X format(mesgbuf, sizeof mesgbuf, fmt, ap); X va_end(ap); X UpdMesg++; X } X rbell(); X (void) longjmp(mainjmp, COMPLAIN); X} X X/* VARARGS1 */ X Xconfirm(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X char *yorn; X va_list ap; X X va_start(ap); X format(mesgbuf, sizeof mesgbuf, fmt, ap); X va_end(ap); X yorn = ask((char *) 0, mesgbuf); X if (*yorn != 'Y' && *yorn != 'y') X (void) longjmp(mainjmp, COMPLAIN); X} X Xint RecDepth = 0; X XRecur() X{ X char bname[128]; X Mark *m; X X sprintf(bname, "%s", curbuf->b_name); X m = MakeMark(curline, curchar, FLOATER); X X RecDepth++; X UpdModLine++; X DoKeys(1); /* 1 means not first time */ X UpdModLine++; X RecDepth--; X SetBuf(do_select(curwind, bname)); X if (exp_p == NO) X ToMark(m); X DelMark(m); X} X Xjmp_buf mainjmp; Xint iniargc; /* main sets these for DoKeys() */ Xchar **iniargv; X XDoKeys(nocmdline) X{ X int c; X jmp_buf savejmp; X X push_env(savejmp); X X switch (setjmp(mainjmp)) { X case 0: X if (!nocmdline) X UNIX_cmdline(iniargc, iniargv); X break; X X case QUIT: X if (RecDepth == 0) { X if (ModMacs()) { X rbell(); X if (Upper(*ask("No", X"Some MACROS haven't been saved; leave anyway? ")) != 'Y') X break; X } X if (ModBufs(0)) { X rbell(); X if (Upper(*ask("No", X"Some buffers haven't been saved; leave anyway? ")) != 'Y') X break; X } X#ifdef IPROCS X KillProcs(); X#endif X } X pop_env(savejmp); X return; X X case ERROR: X getDOT(); /* God knows what state linebuf was in */ X X case COMPLAIN: X gc_openfiles(); /* close any files we left open */ X errormsg++; X fix_macros(); X Asking = 0; X curwind->w_bufp = curbuf; X redisplay(); X break; X } X X this_cmd = last_cmd = 0; X X for (;;) { X if (this_cmd != ARG_CMD) { X exp = 1; X exp_p = NO; X last_cmd = this_cmd; X init_strokes(); X } X c = getch(); X if (c == -1) X continue; X dispatch(c); X } X} X Xint Crashing = 0; X Xchar ** Xscanvec(args, str) Xregister char **args, X *str; X{ X while (*args) { X if (strcmp(*args, str) == 0) X return args; X args++; X } X return 0; X} X Xint UpdFreq = 30, X inIOread = 0; X Xupdmode() X{ X UpdModLine++; X if (inIOread) X redisplay(); X#ifndef JOB_CONTROL X (void) signal(SIGALRM, updmode); X#endif X (void) alarm((unsigned) UpdFreq); X} X X#ifdef TIOCGWINSZ X#ifdef SIGWINCH Xextern win_reshape(); X#endif X#endif X X#ifdef TIOCGWINSZ X#ifdef SIGWINCH Xwin_reshape() X{ X register int diff; X X (void) signal(SIGWINCH, SIG_IGN); X X /* X * Save old number of lines. X */ X diff = LI; X X /* X * Get new line/col info. X */ X ttsize(); X X /* X * LI has changed, and now holds the X * new value. See how much the size X * changed. X */ X diff = LI - diff; X X /* X * Change the size of the current window X * only. If they shrank by more than X * the window size, tough. X */ X if ((curwind->w_height + diff) < 2) X curwind->w_height = 2; X else X curwind->w_height += diff; X X make_scr(); X redisplay(); X X (void) signal(SIGWINCH, win_reshape); X} X#endif X#endif X Xmain(argc, argv) Xchar *argv[]; X{ X char ttbuf[512], X#ifndef VMUNIX X s_iobuff[LBSIZE], X s_genbuf[LBSIZE], X s_linebuf[LBSIZE], X#endif X *cp; X X X#ifndef VMUNIX X /* The way I look at it, there ain't no way I is gonna run X out of stack space UNLESS I have some kind of infinite X recursive bug. So why use up some valuable memory, when X there is plenty of space on the stack? (This only matters X on wimpy pdp11's, of course.) */ X X iobuff = s_iobuff; X genbuf = s_genbuf; X linebuf = s_linebuf; X#endif X X errormsg = 0; X X iniargc = argc; X iniargv = argv; X X if (setjmp(mainjmp)) { X printf("\rAck! I can't deal with error \"%s\" now.\n\r", mesgbuf); X finish(0); X } X X getTERM(); /* Get terminal. */ X if (getenv("METAKEY")) X MetaKey = 1; X ttsize(); X InitCM(); X X d_cache_init(); /* initialize the disk buffer cache */ X X if (cp = getenv("SHELL")) X strcpy(Shell, cp); X X make_scr(); X mac_init(); /* Initialize Macros */ X winit(); /* Initialize Window */ X#ifdef IPROCS X pinit(); /* Pipes/process initialization */ X#endif X SetBuf(do_select(curwind, Mainbuf)); X X#ifdef CHDIR X { X char **argp; X X if ((argp = scanvec(argv, "-d")) && (argp[1][0] == '/')) X setCWD(argp[1]); X else X getCWD(); /* After we setup curbuf in case we have to getwd() */ X } X#endif X HomeDir = getenv("HOME"); X if (HomeDir == 0) X HomeDir = "/"; X HomeLen = strlen(HomeDir); X#ifdef SYSV X sprintf(Mailbox, "/usr/mail/%s", getenv("LOGNAME")); X#else X sprintf(Mailbox, "/usr/spool/mail/%s", getenv("USER")); X#endif SYSV X (void) joverc(Joverc); X if (!scanvec(argv, "-j")) { X char tmpbuf[100]; X X sprintf(tmpbuf, "%s/.joverc", HomeDir); X (void) joverc(tmpbuf); X } X if (scanvec(argv, "-r")) X dorecover(); X X (void) time(&time0); X ttinit(); /* initialize terminal (after ~/.joverc) */ X settout(ttbuf); /* not until we know baudrate */ X ResetTerm(); X X (void) signal(SIGHUP, finish); X (void) signal(SIGINT, finish); X (void) signal(SIGBUS, finish); X (void) signal(SIGSEGV, finish); X (void) signal(SIGPIPE, finish); X (void) signal(SIGTERM, SIG_IGN); X#ifdef TIOCGWINSZ X#ifdef SIGWINCH X (void) signal(SIGWINCH, win_reshape); X#endif X#endif X X /* set things up to update the modeline every UpdFreq seconds */ X (void) signal(SIGALRM, updmode); X (void) alarm((unsigned) UpdFreq); X X cl_scr(1); X flusho(); X RedrawDisplay(); /* start the redisplay process. */ X DoKeys(0); X finish(0); X} @//E*O*F jove.c// if test 19628 -ne "`wc -c <'jove.c'`"; then echo shar: error transmitting "'jove.c'" '(should have been 19628 characters)' fi fi # end of overwriting check echo shar: extracting "'jove.h'" '(14747 characters)' if test -f 'jove.h' ; then echo shar: will not over-write existing file "'jove.h'" else sed 's/^X//' >jove.h <<'@//E*O*F jove.h//' X/************************************************************************ X * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * X * provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ************************************************************************/ X X/* jove.h header file to be included by EVERYONE */ X X#include X#include X X#ifndef TUNED X# include "tune.h" X#endif X X#define private static X X#ifndef BSD4_2 X# ifdef MENLO_JCL X# ifndef EUNICE X# define signal sigset X# endif X# endif MENLO_JCL X#endif X X#define EOF -1 X#define NULL 0 X#define NIL 0 X X/* kinds of regular expression compiles */ X#define NORM 0 /* nothing special */ X#define OKAY_RE 1 /* allow regular expressions */ X#define IN_CB 2 /* in curly brace; implies OKAY_RE */ X X/* return codes for command completion (all < 0 because >= 0 are X legitimate offsets into array of strings */ X X#define AMBIGUOUS -2 /* matches more than one at this point */ X#define UNIQUE -3 /* matches only one string */ X#define ORIGINAL -4 /* matches no strings at all! */ X#define NULLSTRING -5 /* just hit return without typing anything */ X X/* values for the `flags' argument to complete */ X#define NOTHING 0 /* opposite of RET_STATE */ X#define RET_STATE 1 /* return state when we hit return */ X#define RCOMMAND 2 /* we are reading a joverc file */ X#define CASEIND 4 /* map all to lower case */ X X#define DEFINE 01 /* defining this macro */ X#define EXECUTE 02 /* executing this macro */ X#define SAVE 04 /* this macro needs saving to a file */ X X#define LBSIZE BUFSIZ /* same as a logical disk block */ X#define FILESIZE 256 X X#define FORWARD 1 X#define BACKWARD -1 X X#define CTL(c) ('c' & 037) X#define META(c) ('c' | 0200) X#define RUBOUT '\177' X#define LF CTL(J) X#define CR CTL(M) X#define BS CTL(H) X#define ESC '\033' X X#define DoTimes(f, n) exp_p = YES, exp = n, f X#define HALF(wp) ((wp->w_height - 1) / 2) X#define IsModified(b) (b->b_modified) X#define SIZE(wp) (wp->w_height - 1) X#define SavLine(a, b) (a->l_dline = putline(b)) X#define SetLine(line) DotTo(line, 0) X#define bobp() (firstp(curline) && bolp()) X#define bolp() (curchar == 0) X#define eobp() (lastp(curline) && eolp()) X#define eolp() (linebuf[curchar] == '\0') X#define firstp(line) (line == curbuf->b_first) X#define getDOT() getline(curline->l_dline, linebuf) X#define isdirty(line) (line->l_dline & DIRTY) X#define lastp(line) (line == curbuf->b_last) X#define makedirty(line) line->l_dline |= DIRTY X#define one_windp() (fwind->w_next == fwind) X Xextern int OkayAbort, /* okay to abort redisplay */ X BufSize; X X#define ARG_CMD 1 X#define LINECMD 2 X#define KILLCMD 3 /* so we can merge kills */ X#define YANKCMD 4 /* so we can do ESC Y (yank-pop) */ X X/* Buffer type */ X X#define B_SCRATCH 1 /* for internal things, e.g. minibuffer ... */ X#define B_FILE 2 /* normal file (We Auto-save these.) */ X#define B_PROCESS 3 /* process output in this buffer */ X X/* Major modes */ X#define FUNDAMENTAL 0 /* Fundamental mode */ X#define TEXT 1 /* Text mode */ X#define CMODE 2 /* C mode */ X#ifdef LISP X# define LISPMODE 3 /* Lisp mode */ X# define NMAJORS 4 X#else X# define NMAJORS 3 X#endif X X/* Minor Modes */ X#define Indent (1 << 0) /* indent same as previous line after return */ X#define ShowMatch (1 << 1) /* paren flash mode */ X#define Fill (1 << 2) /* text fill mode */ X#define OverWrite (1 << 3) /* over write mode */ X#define Abbrev (1 << 4) /* abbrev mode */ X X#define BufMinorMode(b, x) (b->b_minor & x) X X#define MinorMode(x) BufMinorMode(curbuf, x) X#define MajorMode(x) (curbuf->b_major == x) X#define SetMajor(x) ((curbuf->b_major = x), UpdModLine++) X Xextern char CharTable[NMAJORS][128]; X X/* setjmp/longjmp args for DoKeys() mainjmp */ X#define FIRSTCALL 0 X#define ERROR 1 X#define COMPLAIN 2 /* do the error without a getDOT */ X#define QUIT 3 /* leave this level of recursion */ X X#define QUIET 1 /* sure, why not? */ X X#define YES 1 X#define NO 0 X#define TRUE 1 X#define FALSE 0 X#define ON 1 X#define OFF 0 X#define YES_NODIGIT 2 X Xextern char *Mainbuf, X *HomeDir, /* home directory */ X key_strokes[], /* strokes that make up current command */ X *Inputp; X Xextern int HomeLen; /* length of home directory */ X Xextern char NullStr[]; X X#ifdef VMUNIX Xextern char genbuf[LBSIZE], X linebuf[LBSIZE], X iobuff[LBSIZE]; X#else Xextern char *genbuf, /* scratch pad points at s_genbuf (see main()) */ X *linebuf, /* points at s_linebuf */ X *iobuff; /* for file reading ... points at s_iobuff */ X#endif X Xextern int InJoverc, X Interactive; X X#define READ 0 X#define WRITE 1 Xextern int errno; X Xextern jmp_buf mainjmp; X X#ifdef IPROCS Xtypedef struct process Process; X#endif Xtypedef struct window Window; Xtypedef struct position Bufpos; Xtypedef struct mark Mark; Xtypedef struct buffer Buffer; Xtypedef struct line Line; Xtypedef struct iobuf IOBUF; Xtypedef struct data_obj { X int Type; X char *Name; X} data_obj; /* points to cmd, macro, or variable */ Xtypedef data_obj *keymap[0200]; X Xstruct line { X Line *l_prev, /* pointer to prev */ X *l_next; /* pointer to next */ X disk_line l_dline; /* pointer to disk location */ X}; X X#ifdef IPROCS Xstruct process { X Process *p_next; X#ifdef PIPEPROCS X int p_toproc, /* read p_fromproc and write p_toproc */ X p_portpid, /* Pid of child (the portsrv) */ X p_pid; /* Pid of real child i.e. not portsrv */ X#else X int p_fd, /* File descriptor of ptyp? opened r/w */ X p_pid; /* pid of child (the shell) */ X#endif X Buffer *p_buffer; /* Add output to end of this buffer */ X char *p_name; /* ... */ X char p_state, /* State */ X p_howdied, /* Killed? or Exited? */ X p_reason, /* If signaled, p_reason is the signal; else X it is the the exit code */ X p_eof; /* Received EOF, so can be free'd up */ X Mark *p_mark; /* Where output left us. */ X data_obj X *p_cmd; /* Command to call when process dies */ X}; X#endif IPROCS X Xstruct window { X Window *w_prev, /* circular list */ X *w_next; X Buffer *w_bufp; /* buffer associated with this window */ X Line *w_top, /* top line */ X *w_line; /* current line */ X int w_char, X w_height, /* window height */ X w_topnum, /* line number of the topline */ X w_dotcol, /* UpdWindow sets this ... */ X w_dotline, /* ... and this */ X w_flags; X#define W_TOPGONE 01 X#define W_CURGONE 02 /* topline (curline) of window has been deleted X since the last time a redisplay was called */ X#define W_VISSPACE 04 X#define W_NUMLINES 010 X}; X Xextern Window *fwind, /* first window in list */ X *curwind; /* current window */ X Xstruct position { X Line *p_line; X int p_char; X}; X Xstruct mark { X Line *m_line; X int m_char; X Mark *m_next; /* list of marks */ X#define FLOATER 1 X char m_floater; /* FLOATERing mark? */ X}; X Xstruct buffer { X Buffer *b_next; /* next buffer in chain */ X char *b_name, /* buffer name */ X *b_fname; /* file name associated with buffer */ X ino_t b_ino; /* inode of file name */ X time_t b_mtime; /* last modify time ... X to detect two people writing X to the same file */ X Line *b_first, /* pointer to first line in list */ X *b_dot, /* current line */ X *b_last; /* last line in list */ X int b_char; /* current character in line */ X X#define NMARKS 8 /* number of marks in the ring */ X X Mark *b_markring[NMARKS], /* new marks are pushed saved here */ X *b_marks; /* all the marks for this buffer */ X char b_themark, /* current mark (in b_markring) */ X b_type, /* file, scratch, process, iprocess */ X b_ntbf, /* needs to be found when we X first select? */ X b_modified; /* is the buffer modified? */ X int b_major, /* major mode */ X b_minor; /* and minor mode */ X keymap *b_keybinds; /* local bindings (if any) */ X#ifdef IPROCS X Process *b_process; /* process we're attached to */ X#endif X}; X Xstruct macro { X int Type; /* in this case a macro */ X char *Name; /* name is always second ... */ X int m_len, /* length of macro so we can use ^@ */ X m_buflen, /* memory allocated for it */ X m_offset, /* index into body for defining and running */ X m_flags, /* defining/running this macro? */ X m_ntimes; /* number of times to run this macro */ X char *m_body; /* actual body of the macro */ X struct macro X *m_nextm; X}; X Xstruct variable { X int Type; /* in this case a variable */ X char *Name; /* name is always second */ X int *v_value, X v_flags; X}; X Xstruct cmd { X int Type; X char *Name; X int (*c_proc)(); X}; X Xextern keymap mainmap, /* various key maps */ X pref1map, X pref2map, X miscmap; X Xextern data_obj *LastCmd; /* last command invoked */ X Xextern char *ProcFmt; X Xextern struct cmd commands[]; Xextern struct macro *macros; Xextern struct variable variables[]; X Xextern struct macro X *macstack[], X KeyMacro; X X#define FUNCTION 1 X#define VARIABLE 2 X#define MACRO 3 X#define TYPEMASK 07 X#define MAJOR_MODE 010 X#define MINOR_MODE 020 X#define DefMajor(x) (FUNCTION|MAJOR_MODE|(x << 8)) X#define DefMinor(x) (FUNCTION|MINOR_MODE|(x << 8)) X Xextern Buffer *world, /* first buffer */ X *curbuf; /* pointer into world for current buffer */ X X#define curline curbuf->b_dot X#define curchar curbuf->b_char X X#define NUMKILLS 10 /* number of kills saved in the kill ring */ X X#define DIRTY 01 /* just needs updating for some reason */ X#define MODELINE 02 /* this is a modeline */ X#define L_MOD 04 /* this line has been modified internally */ X Xstruct scrimage { X int s_offset, /* offset to start printing at */ X s_flags, /* various flags */ X s_id, /* which buffer line */ X s_vln; /* Visible Line Number */ X Line *s_lp; /* so we can turn off red bit */ X Window *s_window; /* window that contains this line */ X}; X Xextern struct scrimage X *DesiredScreen, /* what we want */ X *PhysScreen; /* what we got */ X X/* Variable flags (that can be set). */ X#define V_BASE10 01 /* is integer in base 10 */ X#define V_BASE8 02 /* is integer in base 8 */ X#define V_BOOL 04 /* is a boolean */ X#define V_STRING 010 /* is a string */ X#define V_CHAR 020 /* is a character */ X#define V_FILENAME 040 /* a file name (implies V_STRING) */ X#define V_TYPEMASK 077 /* mask off the extra bits */ X#define V_MODELINE 0100 /* update modeline */ X#define V_CLRSCREEN 0200 /* clear and redraw screen */ X#define V_TTY_RESET 0400 /* redo the tty modes */ X Xextern int X OKXonXoff, /* disable start/stop characters */ X MetaKey, /* this terminal has a meta key */ X VisBell, /* use visible bell (if possible) */ X WrapScan, /* make searches wrap */ X phystab, /* terminal's tabstop settings */ X tabstop, /* expand tabs to this number of spaces */ X#ifdef BACKUPFILES X BkupOnWrite, /* make backup files when writing */ X#endif X RMargin, /* right margin */ X LMargin, /* left margin */ X ScrollStep, /* how should we scroll */ X WtOnMk, /* write files on compile-it command */ X EndWNewline, /* end files with a blank line */ X MarkThresh, /* moves greater than MarkThresh X will SetMark */ X PDelay, /* paren flash delay in tenths of a second */ X CIndIncrmt, /* how much each indentation level pushes X over in C mode */ X CreatMode, /* default mode for creat'ing files */ X CaseIgnore, /* case ignore search */ X#ifdef ABBREV X AutoCaseAbbrev, /* automatically do case on abbreviations */ X#endif X MarksShouldFloat, /* adjust marks on insertion/deletion */ X UseRE, /* use regular expressions in search */ X SyncFreq, /* how often to sync the file pointers */ X BriteMode, /* make the mode line inverse? */ X OkayBadChars, /* allow bad characters in files created X by JOVE */ X UpdFreq, /* how often to update modeline */ X UseBuffers, /* use buffers with Typeout() */ X#ifdef BIFF X BiffChk, /* turn off/on biff with entering/exiting jove */ X#endif X MailInt, /* mail check interval */ X#ifdef ID_CHAR X UseIC, /* whether or not to use i/d char X processesing */ X SExitChar, /* type this to stop i-search */ X#endif X IntChar, /* ttysets this to generate QUIT */ X EWSize; /* size to make the error window */ X Xextern char X#ifdef IPROCS X proc_prompt[80], /* process prompt */ X#endif X#ifdef F_COMPLETION X BadExtensions[128], /* extensions (e.g., ".o" to ignore) */ X#endif X#ifdef CMT_FMT X CmtFmt[80], X#endif X ModeFmt[120], /* mode line format string */ X Mailbox[128], /* mailbox name */ X TmpFilePath[128], /* directory/device to store tmp files */ X TagFile[128], /* default tag file */ X Shell[128]; /* shell to use */ X Xextern int X exp, /* argument count */ X exp_p, /* argument count is supplied */ X X TOabort, /* flag set by Typeout() */ X io, /* file descriptor for reading and writing files */ X errormsg, /* last message was an error message X so don't erase the error before it X has been read */ X this_cmd, /* ... */ X last_cmd, /* last command ... to implement appending X to kill buffer */ X RecDepth, /* recursion depth */ X InputPending, /* nonzero if there is input waiting to X be processed */ X killptr, /* index into killbuf */ X CanScroll, /* can this terminal scroll? */ X Crashing, /* we are in the middle of crashing */ X Asking, /* are we on read a string from the terminal? */ X inIOread; /* so we know whether we can do a redisplay. */ X Xextern char Minibuf[LBSIZE]; X X#define curmark (curbuf->b_markring[curbuf->b_themark]) X#define b_curmark(b) (b->b_markring[b->b_themark]) X Xextern Line *killbuf[NUMKILLS]; /* array of pointers to killed stuff */ X X#define MESG_SIZE 128 Xextern char mesgbuf[MESG_SIZE]; X Xstruct screenline { X char *s_line, X *s_length; X}; X Xextern int X LastKeyStruck; X Xextern int X stackp, X X CapLine, /* cursor line and cursor column */ X CapCol, X X UpdModLine, /* whether we want to update the mode line */ X UpdMesg; /* update the message line */ X X#define CATCH \ X{\ X jmp_buf sav_jmp; \ X\ X push_env(sav_jmp); \ X if (setjmp(mainjmp) == 0) { X X#define ONERROR \ X } else { \ X X#define ENDCATCH \ X } \ X pop_env(sav_jmp); \ X} X Xextern int X read(), X write(); X getch(); X Xextern time_t time(); Xextern long lseek(); X Xextern disk_line X putline(); X Xextern data_obj X *findcom(), X *findvar(), X *findmac(); X Xextern Line X *next_line(), X *prev_line(), X *nbufline(), X *reg_delete(), X *lastline(), X *listput(); X Xextern char X *getsearch(), X *pwd(), X *itoa(), X *get_time(), X *copystr(), X *basename(), X *filename(), X *IOerr(), X *index(), X *ask(), X *do_ask(), X *ask_buf(), X *ask_file(), X *lcontents(), X *malloc(), X *emalloc(), X *mktemp(), X *realloc(), X *ltobuf(), X *lbptr(), X *rindex(), X *getenv(), X *tgoto(), X *pr_name(), X *sprint(), X *StrIndex(); X Xextern Bufpos X *docompiled(), X *dosearch(), X *DoYank(), X *c_indent(), X#ifdef LISP X *lisp_indent(), X#endif X *m_paren(); X Xextern Mark X *CurMark(), X *MakeMark(); X Xextern Window X *windbp(), X *div_wind(); X Xextern data_obj X **IsPrefix(); X Xextern Buffer X *do_find(), X *do_select(), X *mak_buf(), X *buf_exists(), X *file_exists(); X Xstruct cmd * X FindCmd(); @//E*O*F jove.h// if test 14747 -ne "`wc -c <'jove.h'`"; then echo shar: error transmitting "'jove.h'" '(should have been 14747 characters)' fi fi # end of overwriting check echo shar: extracting "'macros.c'" '(9026 characters)' if test -f 'macros.c' ; then echo shar: will not over-write existing file "'macros.c'" else sed 's/^X//' >macros.c <<'@//E*O*F macros.c//' X/************************************************************************ X * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * X * provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ************************************************************************/ X X#include "jove.h" X Xstruct macro *macros = 0; /* Macros */ Xdata_obj *LastCmd; X Xprivate Xadd_mac(new) Xstruct macro *new; X{ X register struct macro *mp, X *prev = 0; X X for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm) X if (mp == new) X return; X X if (prev) X prev->m_nextm = new; X else X macros = new; X new->m_nextm = 0; X new->Type = MACRO; X} X Xprivate Xdel_mac(mac) Xstruct macro *mac; X{ X register struct macro *m; X X for (m = macros; m != 0; m = m->m_nextm) X if (m->m_nextm == mac) { X m->m_nextm = mac->m_nextm; X break; X } X free(mac->Name); X free(mac->m_body); X free((char *) mac); X} X Xstruct macro KeyMacro; /* Macro used for defining */ X X#define NMACROS 40 /* This is bad, bad, BAD! */ X Xstruct macro *macstack[NMACROS]; Xprivate int stackp = 0; X Xfix_macros() X{ X register int i; X register struct macro *mp; X X for (i = 0; macstack[i]; i++) { X mp = macstack[i]; X macstack[i] = 0; X mp->m_flags = mp->m_offset = 0; X } X stackp = -1; X KeyMacro.m_flags = KeyMacro.m_offset = 0; X} X Xprivate Xmac_err(err) Xchar *err; X{ X KeyMacro.m_flags = 0; X MacNolen(&KeyMacro); X complain(err); X} X Xdo_macro(mac) Xstruct macro *mac; X{ X if (mac->m_flags & EXECUTE) X mac_err("[Attempt to execute macro recursively!]"); X if (++stackp >= NMACROS) X complain("[Too many macros at once!]"); X macstack[stackp] = mac; X mac->m_offset = 0; X mac->m_ntimes = exp; X mac->m_flags |= EXECUTE; X} X Xprivate XMacNolen(m) Xstruct macro *m; X{ X m->m_len = m->m_offset = 0; X} X Xprivate struct macro * Xmac_exists(name) Xchar *name; X{ X register struct macro *mp; X X for (mp = macros; mp; mp = mp->m_nextm) X if (strcmp(mp->Name, name) == 0) X return mp; X return 0; X} X Xmac_init() X{ X add_mac(&KeyMacro); X MacNolen(&KeyMacro); X KeyMacro.Name = "keyboard-macro"; X KeyMacro.m_buflen = 16; X KeyMacro.m_body = emalloc(KeyMacro.m_buflen); X KeyMacro.m_ntimes = KeyMacro.m_flags = 0; X fix_macros(); X} X Xmac_putc(c) Xint c; X{ X if (KeyMacro.m_len >= KeyMacro.m_buflen) { X KeyMacro.m_buflen += 16; X KeyMacro.m_body = realloc(KeyMacro.m_body, (unsigned) KeyMacro.m_buflen); X if (KeyMacro.m_body == 0) X mac_err("[Can't allocate storage for keyboard macro]"); X } X KeyMacro.m_body[KeyMacro.m_offset++] = c; X KeyMacro.m_len++; X} X Xin_macro() X{ X return ((stackp >= 0) && ((macstack[stackp])->m_flags & EXECUTE)); X} X Xmac_getc() X{ X struct macro *m; X X if (stackp < 0 || ((m = macstack[stackp])->m_flags & EXECUTE) == 0) X return -1; X if (m->m_offset == m->m_len) { X m->m_offset = 0; X if (--m->m_ntimes == 0) { X m->m_flags &= ~EXECUTE; X stackp--; X } X return mac_getc(); X } X return m->m_body[m->m_offset++]; X} X XNameMac() X{ X char *name; X struct macro *m; X X if (KeyMacro.m_len == 0) X complain("[No keyboard macro to name!]"); X if (KeyMacro.m_flags & (DEFINE | EXECUTE)) X complain("[Can't name while defining/executing]"); X if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0) X m = (struct macro *) emalloc(sizeof *m); X else { X if (strcmp(name, KeyMacro.Name) == 0) X complain("[Can't name it that!]"); X free(m->Name); X free(m->m_body); X } X name = copystr(name); X m->Type = KeyMacro.Type; X m->m_len = KeyMacro.m_len; X m->m_buflen = KeyMacro.m_buflen; X m->m_body = emalloc(m->m_buflen); X byte_copy(KeyMacro.m_body, m->m_body, m->m_len); X m->m_ntimes = m->m_offset = 0; /* At the beginning */ X m->m_flags = SAVE; X m->Name = name; X add_mac(m); X} X XRunMacro() X{ X struct macro *m; X X if (m = (struct macro *) findmac(ProcFmt)) X do_macro(m); X} X Xprivate int mac_fd; X Xprivate Xmac_io(fcn, ptr, nbytes) Xint (*fcn)(); Xchar *ptr; X{ X int nio; X X if ((nio = (*fcn)(mac_fd, ptr, nbytes)) != nbytes) X complain("[Macro %s error: %d got %d]", X (fcn == read) ? "read" : "write", X nbytes, X nio); X} X XWriteMacs() X{ X struct macro *m; X int namelen, X netl, X nmacs = 0; X char *file, X filebuf[FILESIZE]; X long htonl() ; X X file = ask_file((char *) 0, (char *) 0, filebuf); X if ((mac_fd = creat(file, 0666)) == -1) X complain(IOerr("create", file)); X f_mess("\"%s\"", file); X X /* Don't write the keyboard macro which is always the first */ X for (m = macros->m_nextm; m != 0; m = m->m_nextm) { X if (m->m_len == 0) X continue; X nmacs++; X netl = htonl(m->m_len); X mac_io(write, (char *) &netl, sizeof m->m_len); X namelen = strlen(m->Name) + 1; /* Including the null */ X netl = htonl(namelen); X mac_io(write, (char *) &netl, sizeof namelen); X mac_io(write, m->Name, namelen); X mac_io(write, m->m_body, m->m_len); X m->m_flags &= ~SAVE; X } X (void) close(mac_fd); X add_mess(" %d macro%n saved.", nmacs, nmacs); X} X X#define NEWWAY 1 X#define OLDWAY 0 X Xprivate int int_how = NEWWAY; X X/* Formatting int's the old way or the new "improved" way? */ X X#if vax || pdp11 Xlong htonl(x) Xregister long x; X{ X return( (((x >> 0) & 0377) << 24) | X (((x >> 8) & 0377) << 16) | X (((x >> 16) & 0377) << 8) | X (((x >> 24) & 0377) << 0) ); X} X Xshort htons(x) Xregister short x; X{ X return( (((x >> 0) & 0377) << 8) | X (((x >> 8) & 0377) << 0) ); X} X Xlong ntohl(x) Xregister long x; X{ X return( (((x >> 0) & 0377) << 24) | X (((x >> 8) & 0377) << 16) | X (((x >> 16) & 0377) << 8) | X (((x >> 24) & 0377) << 0) ); X} X Xshort ntohs(x) Xregister short x; X{ X return( (((x >> 0) & 0377) << 8) | X (((x >> 8) & 0377) << 0) ); X} X#else Xlong htonl(x) Xregister long x; X{ X return(x); X} X Xshort htons(x) Xregister short x; X{ X return(x); X} X Xlong ntohl(x) Xregister long x; X{ X return(x); X} X Xshort ntohs(x) Xregister short x; X{ X return(x); X} X#endif X Xint_fmt(i) X{ X if (int_how == NEWWAY) X return ntohl(i); X return i; X} X XReadMacs() X{ X char *file, X filebuf[FILESIZE]; X struct macro *m; X int nmacs = 0, X namelen, X bodylen, X tmp, X he_is_sure = 0, X save_em = FALSE; X X file = ask_file((char *) 0, (char *) 0, filebuf); X if ((mac_fd = open(file, 0)) == -1) X complain(IOerr("open", file)); X X f_mess("\"%s\"", file); X while (read(mac_fd, (char *) &tmp, sizeof tmp) == (sizeof tmp)) { Xretry: bodylen = int_fmt(tmp); X if (!he_is_sure && (bodylen <= 0 || bodylen > 10000)) { X if (int_how == NEWWAY) { X int_how = OLDWAY; X save_em = TRUE; X goto retry; X } else { X confirm("Are you sure \"%s\" is a JOVE macro file? ", filebuf); X he_is_sure = 1; X } X } X nmacs++; X m = (struct macro *) emalloc (sizeof *m); X m->m_flags = 0; X m->m_len = bodylen; X m->m_buflen = m->m_len; X mac_io(read, (char *) &namelen, sizeof namelen); X namelen = int_fmt(namelen); X m->Name = emalloc(namelen); X mac_io(read, m->Name, namelen); X m->m_body = emalloc(m->m_buflen); X mac_io(read, m->m_body, m->m_len); X add_mac(m); X } X (void) close(mac_fd); X add_mess(" %d macro%n defined.", nmacs, nmacs); X if (save_em) { X char *msg = "OK to convert to the new format? ", X ibuf[FILESIZE + 1]; X X if (!InJoverc) { X TOstart("Warning", TRUE); X Typeout("Warning: your macros file is in the old format."); X Typeout("Do you want me to convert \"%s\" to the new", pr_name(file)); X Typeout("format?"); X f_mess(msg); X TOstop(); X confirm(msg); X } X /* WriteMacs requests a file name. This is what it'll get. */ X sprintf(ibuf, "%s\n", file); X Inputp = ibuf; X WriteMacs(); X } X} X XRemember() X{ X if (KeyMacro.m_flags & EXECUTE) X /* We're already executing the macro; ignore any attempts X to define the keyboard macro while we are executing. */ X return; X if (KeyMacro.m_flags & DEFINE) X message("[Already remembering ... continue with definition]"); X else { X UpdModLine++; X KeyMacro.m_flags |= DEFINE; X MacNolen(&KeyMacro); X message("Remembering..."); X } X} X X/* Is `c' a prefix character */ X Xprivate XPrefChar(c) X{ X return (int) IsPrefix(mainmap[c]); X} X XForget() X{ X char *cp; X struct macro *m = &KeyMacro; X X UpdModLine++; X if (m->m_flags & DEFINE) { X message("Keyboard macro defined."); X m->m_flags &= ~DEFINE; X cp = &m->m_body[m->m_len - 2]; X if (PrefChar(*cp)) X m->m_len -= 2; X else if (commands[*++cp].c_proc == Forget) X m->m_len--; X } X} X XExecMacro() X{ X do_macro(&KeyMacro); X} X XMacInter() X{ X extern int Interactive; X X if (!Asking) X return; X Interactive = 1; X} X XModMacs() X{ X register struct macro *m; X X for (m = macros->m_nextm; m != 0; m = m->m_nextm) X if (m->m_flags & SAVE) X return 1; X return 0; X} X Xdata_obj * Xfindmac(prompt) Xchar *prompt; X{ X char *strings[100]; X register char **strs = strings; X register int com; X register struct macro *m = macros; X X for (; m != 0; m = m->m_nextm) X *strs++ = m->Name; X *strs = 0; X X if ((com = complete(strings, prompt, NOTHING)) < 0) X return 0; X m = macros; X while (--com >= 0) X m = m->m_nextm; X return (data_obj *) m; X} X XDelMacro() X{ X struct macro *m; X X if ((m = (struct macro *) findmac(ProcFmt)) == 0) X return; X if (m == &KeyMacro) X complain("[It's illegal to delete the keyboard-macro!]"); X del_mac(m); X} @//E*O*F macros.c// if test 9026 -ne "`wc -c <'macros.c'`"; then echo shar: error transmitting "'macros.c'" '(should have been 9026 characters)' fi fi # end of overwriting check echo shar: extracting "'malloc.c'" '(4003 characters)' if test -f 'malloc.c' ; then echo shar: will not over-write existing file "'malloc.c'" else sed 's/^X//' >malloc.c <<'@//E*O*F malloc.c//' X/************************************************************************ X * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * X * provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ************************************************************************/ X X#include "tune.h" X X#ifdef MY_MALLOC X X/* avoid break bug */ X#ifdef pdp11 X# define GRANULE 64 X#else X# define GRANULE 0 X#endif X X/* C storage allocator X * circular first-fit strategy X * works with noncontiguous, but monotonically linked, arena X * each block is preceded by a ptr to the (pointer of) X * the next following block X * blocks are exact number of words long X * aligned to the data type requirements of ALIGN X * pointers to blocks must have BUSY bit 0 X * bit in ptr is 1 for busy, 0 for idle X * gaps in arena are merely noted as busy blocks X * last block of arena (pointed to by alloct) is empty and X * has a pointer to first X * idle blocks are coalesced during space search X * X * a different implementation may need to redefine X * ALIGN, NALIGN, BLOCK, BUSY, INT X * where INT is integer type to which a pointer can be cast X */ X X#define INT int X#define ALIGN int X#define NALIGN 1 X#define WORD sizeof(union store) X#define BLOCK 1024 /* a multiple of WORD*/ X#define BUSY 1 X#define NULL 0 X#define testbusy(p) ((INT)(p)&BUSY) X#define setbusy(p) (union store *) ((INT) (p) | BUSY) X#define clearbusy(p) (union store *) ((INT) (p) &~ BUSY) X Xunion store { X union store *ptr; X ALIGN dummy[NALIGN]; X int calloc; /*calloc clears an array of integers*/ X}; X Xstatic union store allocs[2], /*initial arena*/ X *allocp, /*search ptr*/ X *alloct, /*arena top*/ X *allocx; /*for benefit of realloc*/ X Xchar *sbrk(); X Xchar * Xmalloc(nbytes) Xunsigned int nbytes; X{ X register union store *p, X *q; X register int nw; X static int temp; /* coroutines assume no auto */ X X if (allocs[0].ptr == 0) { /* first time */ X allocs[0].ptr = setbusy(&allocs[1]); X allocs[1].ptr = setbusy(&allocs[0]); X alloct = &allocs[1]; X allocp = &allocs[0]; X } X nw = (nbytes + WORD + WORD - 1) / WORD; X for (p = allocp; ; ) { X for (temp = 0; ; ) { X if (!testbusy(p->ptr)) { X while (!testbusy((q = p->ptr)->ptr)) X p->ptr = q->ptr; X if(q >= p + nw && p + nw >= p) X goto found; X } X q = p; X p = clearbusy(p->ptr); X if (p > q) X ; X else if (q != alloct || p != allocs) X return NULL; X else if (++temp > 1) X break; X } X temp = ((nw + BLOCK/WORD) / (BLOCK/WORD)) * (BLOCK/WORD); X q = (union store *) sbrk(0); X if (q + temp + GRANULE < q) X return NULL; X q = (union store *) sbrk(temp * WORD); X if ((INT) q == -1) X return NULL; X alloct->ptr = q; X if (q != alloct+1) X alloct->ptr = setbusy(alloct->ptr); X alloct = q->ptr = q + temp - 1; X alloct->ptr = setbusy(allocs); X } Xfound: X allocp = p + nw; X if (q > allocp) { X allocx = allocp->ptr; X allocp->ptr = p->ptr; X } X p->ptr = setbusy(allocp); X return (char *) (p + 1); X} X X/* freeing strategy tuned for LIFO allocation */ X Xfree(ap) Xregister char *ap; X{ X register union store *p = (union store *) ap; X X allocp = --p; X p->ptr = clearbusy(p->ptr); X} X X/* realloc(p, nbytes) reallocates a block obtained from malloc() X * and freed since last call of malloc() X * to have new size nbytes, and old content X * returns new location, or 0 on failure X*/ X Xchar * Xrealloc(obj, nbytes) Xchar *obj; Xunsigned int nbytes; X{ X register union store *q, X *p = (union store *) obj; X union store *s, X *t; X register unsigned int nw; X unsigned int onw; X X if (testbusy(p[-1].ptr)) X free((char *) p); X onw = p[-1].ptr - p; X q = (union store *) malloc(nbytes); X if(q == NULL || q == p) X return((char *) q); X s = p; X t = q; X nw = (nbytes + WORD - 1)/WORD; X if (nw < onw) X onw = nw; X while (onw-- != 0) X *t++ = *s++; X if(q < p && q + nw >= p) X (q + (q+nw-p))->ptr = allocx; X return (char *) q; X} X X#endif MY_MALLOC @//E*O*F malloc.c// if test 4003 -ne "`wc -c <'malloc.c'`"; then echo shar: error transmitting "'malloc.c'" '(should have been 4003 characters)' fi fi # end of overwriting check echo shar: extracting "'marks.c'" '(4197 characters)' if test -f 'marks.c' ; then echo shar: will not over-write existing file "'marks.c'" else sed 's/^X//' >marks.c <<'@//E*O*F marks.c//' X/************************************************************************ X * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * X * provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ************************************************************************/ X Xint MarksShouldFloat = 1; X X#include "jove.h" X XMark * XMakeMark(line, column, type) Xregister Line *line; X{ X register Mark *newmark = (Mark *) emalloc(sizeof *newmark); X X MarkSet(newmark, line, column); X newmark->m_next = curbuf->b_marks; X newmark->m_floater = type; X curbuf->b_marks = newmark; X return newmark; X} X XDelMark(m) Xregister Mark *m; X{ X register Mark *mp = curbuf->b_marks; X X if (m == mp) X curbuf->b_marks = m->m_next; X else { X while (mp != 0 && mp->m_next != m) X mp = mp->m_next; X if (mp == 0) X complain("Unknown mark!"); X mp->m_next = m->m_next; X } X free((char *) m); X} X XAllMarkSet(b, line, col) XBuffer *b; Xregister Line *line; X{ X register Mark *mp; X X for (mp = b->b_marks; mp != 0; mp = mp->m_next) X MarkSet(mp, line, col); X} X XMarkSet(m, line, column) XMark *m; XLine *line; X{ X m->m_line = line; X m->m_char = column; X} X XPopMark() X{ X int pmark; X X if (curmark == 0) X return; X if (curbuf->b_markring[(curbuf->b_themark + 1) % NMARKS] == 0) { X pmark = curbuf->b_themark; X do { X if (--pmark < 0) X pmark = NMARKS - 1; X } while (curbuf->b_markring[pmark] != 0); X X curbuf->b_markring[pmark] = MakeMark(curline, curchar, MarksShouldFloat); X ToMark(curmark); X DelMark(curmark); X curmark = 0; X } else X PtToMark(); X X pmark = curbuf->b_themark - 1; X if (pmark < 0) X pmark = NMARKS - 1; X curbuf->b_themark = pmark; X} X XSetMark() X{ X if (exp_p) X PopMark(); X else X DoSetMark(curline, curchar); X} X XDoSetMark(l, c) XLine *l; X{ X curbuf->b_themark = (curbuf->b_themark + 1) % NMARKS; X if (curmark == 0) X curmark = MakeMark(l, c, MarksShouldFloat); X else X MarkSet(curmark, l, c); X s_mess("[Point pushed]"); X} X X/* Move point to Mark */ X XToMark(m) XMark *m; X{ X int len; X X if (m == 0) X return; X DotTo(m->m_line, m->m_char); X if (curchar > (len = length(curline))) X curchar = len; X} X XMark * XCurMark() X{ X if (curmark == 0) X complain("No mark."); X return curmark; X} X XPtToMark() X{ X Line *mline; X int mchar; X Mark *m = CurMark(); X X mline = curline; X mchar = curchar; X X ToMark(m); X MarkSet(m, mline, mchar); X} X X/* Fix marks for after a deletion. For now, even marks that don't X float will actually float, because we can't allow marks to point X to non-existant lines. */ X XDFixMarks(line1, char1, line2, char2) Xregister Line *line1, X *line2; X{ X register Mark *m; X Line *lp = line1; X X if (curbuf->b_marks == 0) X return; X while (lp != line2->l_next) { X for (m = curbuf->b_marks; m != 0; m = m->m_next) { X/* if (!m->m_floater) X continue; */ X if (m->m_line == lp) X m->m_char |= (1 << 15); X } X lp = lp->l_next; X } X for (m = curbuf->b_marks; m; m = m->m_next) { X/* if (!m->m_floater) X continue; */ X if ((m->m_char & (1 << 15)) == 0) X continue; /* Not effected */ X m->m_char &= ~(1 << 15); X if (m->m_line == line1 && m->m_char < char1) X continue; /* This mark is not affected */ X if (line1 == line2) { X if (m->m_char >= char1 && m->m_char <= char2) X m->m_char = char1; X else if (m->m_char > char2) X m->m_char -= (char2 - char1); X /* Same line move the mark backward */ X } else if (m->m_line == line2) { X if (m->m_char > char2) X m->m_char = char1 + (m->m_char - char2); X else X m->m_char = char1; X m->m_line = line1; X } else { X m->m_char = char1; X m->m_line = line1; X } X } X} X X/* Fix marks after an insertion. Marks that don't float are ignored X on insertion, which means PtToMark has to be careful ... */ X XIFixMarks(line1, char1, line2, char2) Xregister Line *line1, X *line2; X{ X register Mark *m; X X for (m = curbuf->b_marks; m != 0; m = m->m_next) { X if (!m->m_floater) X continue; X if (m->m_line == line1) { X if (m->m_char > char1) { X m->m_line = line2; X if (line1 == line2) X m->m_char += (char2 - char1); X else X m->m_char = char2 + (m->m_char - char1); X } X } X } X} @//E*O*F marks.c// if test 4197 -ne "`wc -c <'marks.c'`"; then echo shar: error transmitting "'marks.c'" '(should have been 4197 characters)' fi fi # end of overwriting check echo shar: extracting "'setmaps.c'" '(2200 characters)' if test -f 'setmaps.c' ; then echo shar: will not over-write existing file "'setmaps.c'" else sed 's/^X//' >setmaps.c <<'@//E*O*F setmaps.c//' X/************************************************************************ X * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * X * provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ************************************************************************/ X X#define TXT_TO_C X X#include "funcdefs.c" X#undef putchar /* From jove.h via funcdefs.c, conflicts with STDIO */ X#undef putc X#undef getc X#undef EOF X#undef FILE X#undef BUFSIZ X#include X Xmatch(choices, what) Xregister struct cmd choices[]; Xregister char *what; X{ X register int len; X int i, X found = 0, X save, X exactmatch = -1; X X len = strlen(what); X for (i = 0; choices[i].Name != 0; i++) { X if (*what != *choices[i].Name) X continue; X if (strncmp(what, choices[i].Name, len) == 0) X return i; X } X return -1; X} X Xchar * XPPchar(c) Xint c; X{ X static char str[10]; X char *cp = str; X X if (c == '\033') X strcpy(cp, "ESC"); X else if (c < ' ') X (void) sprintf(cp, "C-%c", c + '@'); X else if (c == '\177') X strcpy(cp, "^?"); X else X (void) sprintf(cp, "%c", c); X return cp; X} X Xextract(into, from) Xchar *into, X *from; X{ X from += 2; /* Past tab and first double quote. */ X while ((*into = *from++) != '"') X into++; X *into = 0; X} X Xmain() X{ X FILE *ifile, X *of; X char line[100], X comname[70]; X int comnum, X ch; X X ifile = stdin; X of = stdout; X if (ifile == NULL || of == NULL) { X printf("Cannot read input or write output.\n"); X exit(1); X } X while (fgets(line, sizeof line, ifile) != NULL) { X if (strncmp(line, "\t\"", 2) != 0) { X fprintf(of, line); X ch = 0; X continue; X } X extract(comname, line); X if (strcmp(comname, "unbound") == 0) X comnum = 12345; X else { X comnum = match(commands, comname); X if (comnum < 0) { X fprintf(stderr, "Cannot find command \"%s\".\n", comname); X exit(1); X } X } X if (comnum == 12345) X fprintf(of, " (data_obj *) 0, /* %s */\n", PPchar(ch++)); X else X fprintf(of, " (data_obj *) &commands[%d], /* %s */\n", comnum, PPchar(ch++)); X } X fclose(of); X fclose(ifile); X exit(0); X} @//E*O*F setmaps.c// if test 2200 -ne "`wc -c <'setmaps.c'`"; then echo shar: error transmitting "'setmaps.c'" '(should have been 2200 characters)' fi fi # end of overwriting check echo shar: "End of archive 5 (of 13)." cp /dev/null ark5isdone DONE=true for I in 1 2 3 4 5 6 7 8 9 10 11 12 13; do if test -f ark${I}isdone; then echo "You have run archive ${I}." else echo "You still need to run archive ${I}." DONE=false fi done case $DONE in true) echo "You have run all 13 archives." echo 'Now read the README and Makefile.' ;; esac ## End of shell archive. exit 0