sources-request@mirror.TMC.COM (02/05/87)
Submitted by: seismo!rochester!jpayne (Jonathan Payne) Mod.sources: Volume 8, Issue 26 Archive-name: jove/Part07 #! /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 7 (of 13)." # Contents: re.c recover.c scandir.c screen.c teachjove.c # tune.template version.c PATH=/bin:/usr/bin:/usr/ucb; export PATH echo shar: extracting "'re.c'" '(17213 characters)' if test -f 're.c' ; then echo shar: will not over-write existing file "'re.c'" else sed 's/^X//' >re.c <<'@//E*O*F re.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/* search package */ X X#include "jove.h" X#include "ctype.h" X X#define NALTS 16 /* number of alternate search strings */ X Xchar searchstr[128], X compbuf[256], /* global default compbuf */ X rep_search[128], /* replace search string */ X rep_str[128], /* contains replacement string */ X *cur_compb, /* usually points at compbuf */ X REbuf[LBSIZE], /* points at line we're scanning */ X *alternates[NALTS]; X Xint REdirection; X Xint CaseIgnore = 0, X WrapScan = 0, X UseRE = 0; X Xprivate char CaseEquiv[] = { X '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', X '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', X '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', X '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', X '\040', '!', '"', '#', '$', '%', '&', '\'', X '(', ')', '*', '+', ',', '-', '.', '/', X '0', '1', '2', '3', '4', '5', '6', '7', X '8', '9', ':', ';', '<', '=', '>', '?', X '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', X 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', X 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', X 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', X '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', X 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', X 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', X 'X', 'Y', 'Z', '{', '|', '}', '~', '\177' X}; X X#define cind_cmp(a, b) (CaseEquiv[a] == CaseEquiv[b]) X Xprivate int REpeekc; Xprivate char *REptr; X Xprivate XREgetc() X{ X int c; X X if ((c = REpeekc) != -1) X REpeekc = -1; X else if (*REptr) X c = *REptr++; X else X c = 0; X X return c; X} X X#define STAR 01 /* Match any number of last RE. */ X#define AT_BOL 2 /* ^ */ X#define AT_EOL 4 /* $ */ X#define AT_BOW 6 /* \< */ X#define AT_EOW 8 /* \> */ X#define OPENP 10 /* \( */ X#define CLOSEP 12 /* \) */ X#define CURLYB 14 /* \{ */ X X#define NOSTR 14 /* Codes <= NOSTR can't be *'d. */ X X#define ANYC NOSTR+2 /* . */ X#define NORMC ANYC+2 /* normal character */ X#define CINDC NORMC+2 /* case independent character */ X#define ONE_OF CINDC+2 /* [xxx] */ X#define NONE_OF ONE_OF+2 /* [^xxx] */ X#define BACKREF NONE_OF+2 /* \# */ X#define EOP BACKREF+2 /* end of pattern */ X X#define NPAR 9 /* [1-9] */ Xprivate int nparens; Xprivate char *comp_p, X **alt_p, X **alt_endp; X XREcompile(pattern, re, into_buf, alt_bufp) Xchar *pattern, X *into_buf, X **alt_bufp; X{ X REptr = pattern; X REpeekc = -1; X comp_p = cur_compb = into_buf; X alt_p = alt_bufp; X alt_endp = alt_p + NALTS; X *alt_p++ = comp_p; X nparens = 0; X (void) do_comp(re ? OKAY_RE : NORM); X *alt_p = 0; X} X X/* compile the pattern into an internal code */ X Xprivate Xdo_comp(kind) X{ X char *last_p, X *chr_cnt = 0; X int parens[NPAR], X *parenp, X c, X ret_code; X X parenp = parens; X last_p = 0; X ret_code = 1; X X while (c = REgetc()) { X if (comp_p > &cur_compb[(sizeof compbuf) - 4]) Xtoolong: complain("Search string too long/complex."); X if (c != '*') X last_p = comp_p; X X if (kind == NORM && index(".[*", c) != 0) X goto defchar; X switch (c) { X case '\\': X switch (c = REgetc()) { X case 0: X complain("Premature end of pattern."); X X case '{': X { X char *wcntp; /* word count */ X X *comp_p++ = CURLYB; X wcntp = comp_p; X *comp_p++ = 0; X for (;;) { X int comp_val; X char *comp_len; X X comp_len = comp_p++; X comp_val = do_comp(IN_CB); X *comp_len = comp_p - comp_len; X (*wcntp)++; X if (comp_val == 0) X break; X } X break; X } X X case '}': X if (kind != IN_CB) X complain("Unexpected \}."); X ret_code = 0; X goto outahere; X X case '(': X if (nparens >= NPAR) X complain("Too many ('s; max is %d.", NPAR); X *comp_p++ = OPENP; X *comp_p++ = nparens; X *parenp++ = nparens++; X break; X X case ')': X if (parenp == parens) X complain("Too many )'s."); X *comp_p++ = CLOSEP; X *comp_p++ = *--parenp; X break; X X case '|': X if (alt_p >= alt_endp) X complain("Too many alternates; max %d.", NALTS); X *comp_p++ = EOP; X *alt_p++ = comp_p; X nparens = 0; X break; X 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 *comp_p++ = BACKREF; X *comp_p++ = c - '1'; X break; X X case '<': X *comp_p++ = AT_BOW; X break; X X case '>': X *comp_p++ = AT_EOW; X break; X X default: X goto defchar; X } X break; X X case ',': X if (kind != IN_CB) X goto defchar; X goto outahere; X X case '.': X *comp_p++ = ANYC; X break; X X case '^': X if (comp_p == cur_compb || comp_p[-1] == EOP) { X *comp_p++ = AT_BOL; X break; X } X goto defchar; X X case '$': X if ((REpeekc = REgetc()) != 0 && REpeekc != '\\') X goto defchar; X *comp_p++ = AT_EOL; X break; X X case '[': X { X int chrcnt; X X *comp_p++ = ONE_OF; X if (comp_p + 16 >= &cur_compb[(sizeof compbuf)]) X goto toolong; X bzero(comp_p, 16); X if ((REpeekc = REgetc()) == '^') { X *last_p = NONE_OF; X /* Get it for real this time. */ X (void) REgetc(); X } X chrcnt = 1; X while ((c = REgetc()) != ']' && c != 0) { X if (c == '\\') X c = REgetc(); X else if ((REpeekc = REgetc()) == '-') { X int c2; X X (void) REgetc(); /* reread '-' */ X c2 = REgetc(); X while (c < c2) { X comp_p[c/8] |= (1 << (c%8)); X c++; X } X } X comp_p[c/8] |= (1 << (c%8)); X chrcnt++; X } X if (c == 0) X complain("Missing ]."); X if (chrcnt == 1) X complain("Empty []."); X comp_p += 16; X break; X } X X case '*': X if (last_p == 0 || *last_p <= NOSTR) X goto defchar; X if (chr_cnt) { X char lastc = chr_cnt[*chr_cnt]; X X comp_p = chr_cnt + *chr_cnt; X (*chr_cnt)--; X *comp_p++ = chr_cnt[-1] | STAR; X *comp_p++ = lastc; X } else X *last_p |= STAR; X break; X X default: Xdefchar: if (chr_cnt) X (*chr_cnt)++; /* increment the count */ X else { X *comp_p++ = (CaseIgnore) ? CINDC : NORMC; X chr_cnt = comp_p++; X *chr_cnt = 1; /* last_p[1] = 1; */ X } X *comp_p++ = c; X continue; X } X chr_cnt = FALSE; X } Xoutahere: X /* End of pattern, let's do some error checking. */ X if (parenp != parens) X complain("Unmatched ()'s."); X if (kind == IN_CB && c == 0) /* End of pattern with \}. */ X complain("Missing \}."); X *comp_p++ = EOP; X X return ret_code; X} X Xprivate char *pstrtlst[NPAR], /* index into REbuf */ X *pendlst[NPAR], X *REbolp, X *locs, X *loc1, X *loc2; X Xint REbom, X REeom, /* beginning and end of match */ X REalt_num; /* if alternatives, which one matched? */ X Xprivate Xbackref(n, linep) Xregister char *linep; X{ X register char *backsp, X *backep; X X backsp = pstrtlst[n]; X backep = pendlst[n]; X while (*backsp++ == *linep++) X if (backsp >= backep) X return 1; X return 0; X} X Xprivate Xmember(comp_p, c, af) Xregister char *comp_p; Xregister int c, X af; X{ X if (c == 0) X return 0; /* try to match EOL always fails */ X if (comp_p[c/8] & (1 << (c%8))) X return af; X return !af; X} X Xprivate XREmatch(linep, comp_p) Xregister char *linep, X *comp_p; X{ X char *first_p = linep; X register int n; X X for (;;) switch (*comp_p++) { X case NORMC: X n = *comp_p++; X while (--n >= 0) X if (*linep++ != *comp_p++) X return 0; X continue; X X case CINDC: /* case independent comparison */ X n = *comp_p++; X while (--n >= 0) X if (!cind_cmp(*linep++, *comp_p++)) X return 0; X continue; X X case EOP: X loc2 = linep; X REeom = (loc2 - REbolp); X return 1; /* Success! */ X X case AT_BOL: X if (linep == REbolp) X continue; X return 0; X X case AT_EOL: X if (*linep == 0) X continue; X return 0; X X case ANYC: X if (*linep++ != 0) X continue; X return 0; X X case AT_BOW: X if (ismword(*linep) && (linep == REbolp || !ismword(linep[-1]))) X continue; X return 0; X X case AT_EOW: X if ((*linep == 0 || !ismword(*linep)) && X (linep != REbolp && ismword(linep[-1]))) X continue; X return 0; X X case ONE_OF: X case NONE_OF: X if (member(comp_p, *linep++, comp_p[-1] == ONE_OF)) { X comp_p += 16; X continue; X } X return 0; X X case OPENP: X pstrtlst[*comp_p++] = linep; X continue; X X case CLOSEP: X pendlst[*comp_p++] = linep; X continue; X X case BACKREF: X if (pstrtlst[n = *comp_p++] == 0) { X s_mess("\\%d was not specified.", n + 1); X return 0; X } X if (backref(n, linep)) { X linep += pendlst[n] - pstrtlst[n]; X continue; X } X return 0; X X case CURLYB: X { X int wcnt, X any; X X wcnt = *comp_p++; X any = 0; X X while (--wcnt >= 0) { X if (any == 0) X any = REmatch(linep, comp_p + 1); X comp_p += *comp_p; X } X if (any == 0) X return 0; X linep = loc2; X continue; X } X X case ANYC | STAR: X first_p = linep; X while (*linep++) X ; X goto star; X X case NORMC | STAR: X first_p = linep; X while (*comp_p == *linep++) X ; X comp_p++; X goto star; X X case CINDC | STAR: X first_p = linep; X while (cind_cmp(*comp_p, *linep++)) X ; X comp_p++; X goto star; X X case ONE_OF | STAR: X case NONE_OF | STAR: X first_p = linep; X while (member(comp_p, *linep++, comp_p[-1] == (ONE_OF | STAR))) X ; X comp_p += 16; X goto star; X X case BACKREF | STAR: X first_p = linep; X n = *comp_p++; X while (backref(n, linep)) X linep += pendlst[n] - pstrtlst[n]; X while (linep >= first_p) { X if (REmatch(linep, comp_p)) X return 1; X linep -= pendlst[n] - pstrtlst[n]; X } X continue; X Xstar: do { X linep--; X if (linep < locs) X break; X if (REmatch(linep, comp_p)) X return 1; X } while (linep > first_p); X return 0; X X default: X complain("RE error match (%d).", comp_p[-1]); X } X /* NOTREACHED. */ X} X Xprivate XREreset() X{ X register int i; X X for (i = 0; i < NPAR; i++) X pstrtlst[i] = pendlst[i] = 0; X} X X/* Index LINE at OFFSET, the compiled EXPR, with alternates ALTS. If X lbuf_okay is nonzero it's okay to use linebuf if LINE is the current X line. This should save lots of time in things like paren matching in X LISP mode. Saves all that copying from linebuf to REbuf. substitute() X is the guy who calls re_lindex with lbuf_okay as 0, since the substitution X gets placed in linebuf ... doesn't work too well when the source and X destination strings are the same. I hate all these arguments! X X This code is cumbersome, repetetive for reasons of efficiency. Fast X search is a must as far as I am concerned. */ X Xre_lindex(line, offset, expr, alts, lbuf_okay) XLine *line; Xchar *expr, X **alts; X{ X int isquick; X register int firstc, X c; X register char *resp; X X REreset(); X if (lbuf_okay) { X REbolp = lbptr(line); X if (offset == -1) X offset = strlen(REbolp); /* arg! */ X } else { X REbolp = ltobuf(line, REbuf); X if (offset == -1) { /* Reverse search, find end of line. */ X extern int Jr_Len; X X offset = Jr_Len; /* Just Read Len. */ X } X } X resp = REbolp; X isquick = ((expr[0] == NORMC || expr[0] == CINDC) && X (alternates[1] == 0)); X if (isquick) { X firstc = expr[2]; X if (expr[0] == CINDC) X firstc = CaseEquiv[firstc]; X } X locs = REbolp + offset; X X if (REdirection == FORWARD) { X do { X char **altp = alts; X X if (isquick) { X if (expr[0] == NORMC) X while ((c = *locs++) != 0 && c != firstc) X ; X else X while (((c = *locs++) != 0) && X (CaseEquiv[c] != firstc)) X ; X if (*--locs == 0) X break; X } X REalt_num = 1; X while (*altp) { X if (REmatch(locs, *altp++)) { X loc1 = locs; X REbom = loc1 - REbolp; X return 1; X } X REalt_num++; X } X } while (*locs++); X } else { X do { X char **altp = alts; X X if (isquick) { X if (expr[0] == NORMC) { X while (locs >= REbolp && *locs-- != firstc) X ; X if (*++locs != firstc) X break; X } else { X while (locs >= REbolp && CaseEquiv[*locs--] != firstc) X ; X if (CaseEquiv[*++locs] != firstc) X break; X } X } X REalt_num = 1; X while (*altp) { X if (REmatch(locs, *altp++)) { X loc1 = locs; X REbom = loc1 - REbolp; X return 1; X } X REalt_num++; X } X } while (--locs >= resp); X } X X return 0; X} X Xint okay_wrap = 0; /* Do a wrap search ... not when we're X parsing errors ... */ X XBufpos * Xdosearch(pattern, dir, re) Xchar *pattern; X{ X Bufpos *pos; X X if (bobp() && eobp()) /* Can't match! There's no buffer. */ X return 0; X X REcompile(pattern, re, compbuf, alternates); X X pos = docompiled(dir, compbuf, alternates); X return pos; X} X XBufpos * Xdocompiled(dir, expr, alts) Xchar *expr, X **alts; X{ X static Bufpos ret; X register Line *lp; X register int offset; X int we_wrapped = 0; X X lsave(); X /* Search now lsave()'s so it doesn't make any assumptions on X whether the the contents of curline/curchar are in linebuf. X Nowhere does search write all over linebuf. However, we have to X be careful about what calls we make here, because many of them X assume (and rightly so) that curline is in linebuf. */ X X REdirection = dir; X lp = curline; X offset = curchar; X if (dir == BACKWARD) { X if (bobp()) { X if (okay_wrap && WrapScan) X goto doit; X return 0; X } X /* here we simulate BackChar() */ X if (bolp()) { X lp = lp->l_prev; X offset = strlen(lbptr(lp)); X } else X --offset; X } else if ((dir == FORWARD) && X (lbptr(lp)[offset] == '\0') && X !lastp(lp)) { X lp = lp->l_next; X offset = 0; X } X X do { X if (re_lindex(lp, offset, expr, alts, YES)) X break; Xdoit: lp = (dir == FORWARD) ? lp->l_next : lp->l_prev; X if (lp == 0) { X if (okay_wrap && WrapScan) { X lp = (dir == FORWARD) ? X curbuf->b_first : curbuf->b_last; X we_wrapped++; X } else X break; X } X if (dir == FORWARD) X offset = 0; X else X offset = -1; /* signals re_lindex ... */ X } while (lp != curline); X X if (lp == curline && we_wrapped) X lp = 0; X if (lp == 0) X return 0; X ret.p_line = lp; X ret.p_char = (dir == FORWARD) ? REeom : REbom; X return &ret; X} X Xprivate char * Xinsert(off, endp, which) Xchar *off, X *endp; X{ X register char *pp; X register int n; X X n = pendlst[which] - pstrtlst[which]; X pp = pstrtlst[which]; X while (--n >= 0) { X *off++ = *pp++; X if (off >= endp) X len_error(ERROR); X } X return off; X} X X/* Perform the substitution. If DELP is nonzero the matched string is X deleted, i.e., the substitution string is not inserted. */ X Xre_dosub(tobuf, delp) Xchar *tobuf; X{ X register char *tp, X *rp, X *repp; X int c; X char *endp; X X tp = tobuf; X endp = tp + LBSIZE; X rp = REbuf; X repp = rep_str; X X while (rp < loc1) X *tp++ = *rp++; X X if (!delp) while (c = *repp++) { X if (c == '\\') { X if ((c = *repp++) == '\0') { X *tp++ = '\\'; X goto endchk; X } else if ((c = *repp++) >= '1' && c <= nparens + '1') { X tp = insert(tp, endp, c - '1'); X continue; X } X } X *tp++ = c; Xendchk: if (tp >= endp) X len_error(ERROR); X } X rp = loc2; X loc2 = REbuf + max(1, tp - tobuf); X REeom = loc2 - REbuf; X /* At least one character past the match, to prevent an infinite X number of replacements in the same position, e.g., X replace "^" with "". */ X while (*tp++ = *rp++) X if (tp >= endp) X len_error(ERROR); X} X Xputmatch(which, buf, size) Xchar *buf; X{ X *(insert(buf, buf + size, which - 1)) = 0; X} X Xsetsearch(str) Xchar *str; X{ X strcpy(searchstr, str); X} X Xchar * Xgetsearch() X{ X return searchstr; X} X XRErecur() X{ X char sbuf[sizeof searchstr], X cbuf[sizeof compbuf], X repbuf[sizeof rep_str], X *altbuf[NALTS]; X int npars; X Mark *m = MakeMark(curline, REbom, FLOATER); X X message("Type C-X C-C to continue with query replace."); X X npars = nparens; X byte_copy(compbuf, cbuf, sizeof compbuf); X byte_copy(searchstr, sbuf, sizeof searchstr); X byte_copy(rep_str, repbuf, sizeof rep_str); X byte_copy((char *) alternates, (char *) altbuf, sizeof alternates); X Recur(); X nparens = npars; X byte_copy(cbuf, compbuf, sizeof compbuf); X byte_copy(sbuf, searchstr, sizeof searchstr); X byte_copy(repbuf, rep_str, sizeof rep_str); X byte_copy((char *) altbuf, (char *) alternates, sizeof alternates); X if (!exp_p) X ToMark(m); X DelMark(m); X} X XForSearch() X{ X search(FORWARD, UseRE, YES); X} X XRevSearch() X{ X search(BACKWARD, UseRE, YES); X} X XFSrchND() X{ X search(FORWARD, UseRE, NO); X} X XRSrchND() X{ X search(BACKWARD, UseRE, NO); X} X Xprivate Xsearch(dir, re, setdefault) X{ X Bufpos *newdot; X char *s; X X s = ask(searchstr, ProcFmt); X if (setdefault) X setsearch(s); X okay_wrap = YES; X newdot = dosearch(s, dir, re); X okay_wrap = NO; X if (newdot == 0) { X if (WrapScan) X complain("No \"%s\" in buffer.", s); X else X complain("No \"%s\" found to %s.", s, X (dir == FORWARD) ? "bottom" : "top"); X } X PushPntp(newdot->p_line); X SetDot(newdot); X} X X/* Do we match PATTERN at OFFSET in BUF? */ X XLookingAt(pattern, buf, offset) Xchar *pattern, X *buf; X{ X register char **alt = alternates; X X REcompile(pattern, 1, compbuf, alternates); X REreset(); X locs = buf + offset; X REbolp = buf; X X while (*alt) X if (REmatch(locs, *alt++)) X return 1; X return 0; X} X Xlook_at(expr) Xchar *expr; X{ X REcompile(expr, 0, compbuf, alternates); X REreset(); X locs = linebuf + curchar; X REbolp = linebuf; X if (REmatch(locs, alternates[0])) X return 1; X return 0; X} X @//E*O*F re.c// if test 17213 -ne "`wc -c <'re.c'`"; then echo shar: error transmitting "'re.c'" '(should have been 17213 characters)' fi fi # end of overwriting check echo shar: extracting "'recover.c'" '(14068 characters)' if test -f 'recover.c' ; then echo shar: will not over-write existing file "'recover.c'" else sed 's/^X//' >recover.c <<'@//E*O*F recover.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/* Recovers JOVE files after a system/editor crash. X Usage: recover [-d directory] [-syscrash] X The -syscrash option is specified in /etc/rc and what it does it X move all the jove tmp files from TMP_DIR to REC_DIR. X X The -d option lets you specify the directory to search for tmp files when X the default isn't the right one. X X Look in Makefile to change the default directories. */ X X#include <stdio.h> /* Do stdio first so it doesn't override OUR X definitions. */ X#undef EOF X#undef BUFSIZ X#undef putchar X X#include "jove.h" X#include "temp.h" X#include "rec.h" X#include <signal.h> X#include <sys/file.h> X#include <sys/stat.h> X#include <sys/dir.h> X X#ifndef L_SET X# define L_SET 0 X# define L_INCR 1 X#endif X Xchar blk_buf[BUFSIZ]; Xint nleft; XFILE *ptrs_fp; Xint data_fd; Xstruct rec_head Header; Xchar datafile[40], X pntrfile[40]; Xlong Nchars, X Nlines; Xchar tty[] = "/dev/tty"; Xint UserID, X Verbose = 0; Xchar *Directory = 0; /* the directory we're looking in */ X Xstruct file_pair { X char *file_data, X *file_rec; X#define INSPECTED 01 X int file_flags; X struct file_pair *file_next; X} *First = 0, X *Last = 0; X Xstruct rec_entry *buflist[100] = {0}; X X#ifndef BSD4_2 X Xtypedef struct { X int d_fd; /* File descriptor for this directory */ X} DIR; X XDIR * Xopendir(dir) Xchar *dir; X{ X DIR *dp = (DIR *) malloc(sizeof *dp); X X if ((dp->d_fd = open(dir, 0)) == -1) X return NULL; X return dp; X} X Xclosedir(dp) XDIR *dp; X{ X (void) close(dp->d_fd); X free(dp); X} X Xstruct direct * Xreaddir(dp) XDIR *dp; X{ X static struct direct dir; X X do X if (read(dp->d_fd, &dir, sizeof dir) != sizeof dir) X return NULL; X while (dir.d_ino == 0); X X return &dir; X} X X#endif BSD4_2 X X/* Get a line at `tl' in the tmp file into `buf' which should be LBSIZE X long. */ X Xgetline(tl, buf) Xdisk_line tl; Xchar *buf; X{ X register char *bp, X *lp; X register int nl; X char *getblock(); X X lp = buf; X bp = getblock(tl >> 1); X nl = nleft; X tl = blk_round(tl); X X while (*lp++ = *bp++) { X if (--nl == 0) { X tl = forward_block(tl); X bp = getblock(tl >> 1); X nl = nleft; X } X } X} X Xchar * Xgetblock(atl) Xdisk_line atl; X{ X int bno, X off; X static int curblock = -1; X X bno = daddr_to_bno(atl); X off = daddr_to_off(atl); X nleft = BUFSIZ - off; X X if (bno != curblock) { X lseek(data_fd, (long) bno * BUFSIZ, L_SET); X read(data_fd, blk_buf, BUFSIZ); X curblock = bno; X } X return blk_buf + off; X} X Xchar * Xcopystr(s) Xchar *s; X{ X char *str; X X str = malloc(strlen(s) + 1); X strcpy(str, s); X X return str; X} X X/* Scandir returns the number of entries or -1 if the directory cannoot X be opened or malloc fails. */ X Xscandir(dir, nmptr, qualify, sorter) Xchar *dir; Xstruct direct ***nmptr; Xint (*qualify)(); Xstruct direct *(*sorter)(); X{ X DIR *dirp; X struct direct *entry, X **ourarray; X int nalloc = 10, X nentries = 0; X X if ((dirp = opendir(dir)) == NULL) X return -1; X ourarray = (struct direct **) malloc(nalloc * sizeof (struct direct *)); X while ((entry = readdir(dirp)) != NULL) { X if (qualify != 0 && (*qualify)(entry) == 0) X continue; X if (nentries == nalloc) { X ourarray = (struct direct **) realloc(ourarray, (nalloc += 10) * sizeof (struct direct)); X if (ourarray == NULL) X return -1; X } X ourarray[nentries] = (struct direct *) malloc(sizeof *entry); X *ourarray[nentries] = *entry; X nentries++; X } X closedir(dirp); X if (nentries != nalloc) X ourarray = (struct direct **) realloc(ourarray, X (nentries * sizeof (struct direct))); X if (sorter != 0) X qsort(ourarray, nentries, sizeof (struct direct **), sorter); X *nmptr = ourarray; X X return nentries; X} X Xalphacomp(a, b) Xstruct direct **a, X **b; X{ X return strcmp((*a)->d_name, (*b)->d_name); X} X Xchar *CurDir; X X/* Scan the DIRNAME directory for jove tmp files, and make a linked list X out of them. */ X Xget_files(dirname) Xchar *dirname; X{ X int add_name(); X struct direct **nmptr; X X CurDir = dirname; X scandir(dirname, &nmptr, add_name, (int (*)())0); X} X Xadd_name(dp) Xstruct direct *dp; X{ X char dfile[128], X rfile[128]; X struct file_pair *fp; X struct rec_head header; X int fd; X X if (strncmp(dp->d_name, "jrec", 4) != 0) X return 0; X /* If we get here, we found a "recover" tmp file, so now X we look for the corresponding "data" tmp file. First, X though, we check to see whether there is anything in X the "recover" file. If it's 0 length, there's no point X in saving its name. */ X (void) sprintf(rfile, "%s/%s", CurDir, dp->d_name); X (void) sprintf(dfile, "%s/jove%s", CurDir, dp->d_name + 4); X if ((fd = open(rfile, 0)) != -1) { X if ((read(fd, (char *) &header, sizeof header) != sizeof header)) { X close(fd); X return 0; X } else X close(fd); X } X if (access(dfile, 0) != 0) { X fprintf(stderr, "recover: can't find the data file for %s/%s\n", Directory, dp->d_name); X fprintf(stderr, "so deleting...\n"); X (void) unlink(rfile); X (void) unlink(dfile); X return 0; X } X /* If we get here, we've found both files, so we put them X in the list. */ X fp = (struct file_pair *) malloc (sizeof *fp); X if ((char *) fp == 0) { X fprintf(stderr, "recover: cannot malloc for file_pair.\n"); X exit(-1); X } X fp->file_data = copystr(dfile); X fp->file_rec = copystr(rfile); X fp->file_flags = 0; X fp->file_next = First; X First = fp; X X return 1; X} X Xoptions() X{ X printf("Options are:\n"); X printf(" ? list options.\n"); X printf(" get get a buffer to a file.\n"); X printf(" list list known buffers.\n"); X printf(" print print a buffer to terminal.\n"); X printf(" quit quit and delete jove tmp files.\n"); X printf(" restore restore all buffers.\n"); X} X X/* Returns a legitimate buffer # */ X Xstruct rec_entry ** Xgetsrc() X{ X char name[128]; X int number; X X for (;;) { X tellme("Which buffer ('?' for list)? ", name); X if (name[0] == '?') X list(); X else if (name[0] == '\0') X return 0; X else if ((number = atoi(name)) > 0 && number <= Header.Nbuffers) X return &buflist[number]; X else { X int i; X X for (i = 1; i <= Header.Nbuffers; i++) X if (strcmp(buflist[i]->r_bname, name) == 0) X return &buflist[i]; X printf("%s: unknown buffer.\n", name); X } X } X} X X/* Get a destination file name. */ X Xstatic char * Xgetdest() X{ X static char filebuf[256]; X X tellme("Output file: ", filebuf); X if (filebuf[0] == '\0') X return 0; X return filebuf; X} X X#include "ctype.h" X Xchar * Xreadword(buf) Xchar *buf; X{ X int c; X char *bp = buf; X X while (index(" \t\n", c = getchar())) X ; X X do { X if (index(" \t\n", c)) X break; X *bp++ = c; X } while ((c = getchar()) != EOF); X *bp = 0; X X return buf; X} X Xtellme(quest, answer) Xchar *quest, X *answer; X{ X if (stdin->_cnt <= 0) { X printf("%s", quest); X fflush(stdout); X } X readword(answer); X} X X/* Print the specified file to strandard output. */ X Xjmp_buf int_env; X Xcatch() X{ X longjmp(int_env, 1); X} X Xrestore() X{ X register int i; X char tofile[100], X answer[30]; X int nrecovered = 0; X X for (i = 1; i <= Header.Nbuffers; i++) { X (void) sprintf(tofile, "#%s", buflist[i]->r_bname); Xtryagain: X printf("Restoring %s to %s, okay?", buflist[i]->r_bname, X tofile); X tellme(" ", answer); X switch (answer[0]) { X case 'y': X break; X X case 'n': X continue; X X default: X tellme("What file should I use instead? ", tofile); X goto tryagain; X } X get(&buflist[i], tofile); X nrecovered++; X } X printf("Recovered %d buffers.\n", nrecovered); X} X Xget(src, dest) Xstruct rec_entry **src; Xchar *dest; X{ X FILE *outfile; X X if (src == 0 || dest == 0) X return; X (void) signal(SIGINT, catch); X if (setjmp(int_env) == 0) { X if ((outfile = fopen(dest, "w")) == NULL) { X printf("recover: cannot create %s.\n", dest); X return; X } X seekto(src - buflist); X if (dest != tty) X printf("\"%s\"", dest); X dump_file(outfile); X } else X printf("\nAborted!\n"); X fclose(outfile); X if (dest != tty) X printf(" %ld lines, %ld characters.\n", Nlines, Nchars); X (void) signal(SIGINT, SIG_DFL); X} 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 Xread_rec(recptr) Xstruct rec_entry *recptr; X{ X if (fread((char *) recptr, sizeof *recptr, 1, ptrs_fp) != 1) X fprintf(stderr, "recover: cannot read record.\n"); X} X Xseekto(which) X{ X struct rec_entry rec; X X fseek(ptrs_fp, (long) (sizeof Header), L_SET); X X while (which-- > 1) { X read_rec(&rec); X if (fseek(ptrs_fp, (long) rec.r_nlines * sizeof (disk_line), X L_INCR) == -1) X printf("recover: improper fseek!\n"); X } X} X Xmakblist() X{ X int i; X X for (i = 1; i <= Header.Nbuffers; i++) { X seekto(i); X if (buflist[i] == 0) X buflist[i] = (struct rec_entry *) malloc (sizeof (struct rec_entry)); X read_rec(buflist[i]); X } X if (buflist[i]) { X free((char *) buflist[i]); X buflist[i] = 0; X } X} X Xdisk_line Xgetaddr(fp) Xregister FILE *fp; X{ X register int nchars = sizeof (disk_line); X disk_line addr; X register char *cp = (char *) &addr; X X while (--nchars >= 0) X *cp++ = getc(fp); X X return addr; X} X Xdump_file(out) XFILE *out; X{ X struct rec_entry record; X register int nlines; X register disk_line daddr; X char buf[BUFSIZ]; X X read_rec(&record); X nlines = record.r_nlines; X Nchars = Nlines = 0L; X while (--nlines >= 0) { X daddr = getaddr(ptrs_fp); X getline(daddr, buf); X Nlines++; X Nchars += 1 + strlen(buf); X fputs(buf, out); X if (nlines > 0) X fputc('\n', out); X } X if (out != stdout) X fclose(out); X} X X/* List all the buffers. */ X Xlist() X{ X int i; X X for (i = 1; i <= Header.Nbuffers; i++) X printf("%d) buffer %s \"%s\" (%d lines)\n", i, X buflist[i]->r_bname, X buflist[i]->r_fname, X buflist[i]->r_nlines); X} X Xdoit(fp) Xstruct file_pair *fp; X{ X char answer[30]; X char *datafile = fp->file_data, X *pntrfile = fp->file_rec; X X ptrs_fp = fopen(pntrfile, "r"); X if (ptrs_fp == NULL) { X if (Verbose) X fprintf(stderr, "recover: cannot read rec file (%s).\n", pntrfile); X return 0; X } X fread((char *) &Header, sizeof Header, 1, ptrs_fp); X if (Header.Uid != UserID) X return 0; X X /* Don't ask about JOVE's that are still running ... */ X#ifdef KILL0 X if (kill(Header.Pid, 0) == 0) X return 0; X#else X#ifdef LSRHS X if (pexist(Header.Pid)) X return 0; X#endif LSRHS X#endif KILL0 X X if (Header.Nbuffers == 0) { X printf("There are no modified buffers in %s; should I delete the tmp file?", pntrfile); X ask_del(" ", fp); X return 1; X } X X if (Header.Nbuffers < 0) { X fprintf(stderr, "recover: %s doesn't look like a jove file.\n", pntrfile); X ask_del("Should I delete it? ", fp); X return 1; /* We'll, we sort of found something. */ X } X printf("Found %d buffer%s last updated: %s", X Header.Nbuffers, X Header.Nbuffers != 1 ? "s" : "", X ctime(&Header.UpdTime)); X data_fd = open(datafile, 0); X if (data_fd == -1) { X fprintf(stderr, "recover: but I can't read the data file (%s).\n", datafile); X ask_del("Should I delete the tmp files? ", fp); X return 1; X } X makblist(); X X for (;;) { X tellme("(Type '?' for options): ", answer); X switch (answer[0]) { X case '\0': X continue; X X case '?': X options(); X break; X X case 'l': X list(); X break; X X case 'p': X get(getsrc(), tty); X break; X X case 'q': X ask_del("Shall I delete the tmp files? ", fp); X return 1; X X case 'g': X { /* So it asks for src first. */ X char *dest; X struct rec_entry **src; X X if ((src = getsrc()) == 0) X break; X dest = getdest(); X get(src, dest); X break; X } X X case 'r': X restore(); X break; X X default: X printf("I don't know how to \"%s\"!\n", answer); X break; X } X } X} X Xask_del(prompt, fp) Xchar *prompt; Xstruct file_pair *fp; X{ X char yorn[20]; X X tellme(prompt, yorn); X if (yorn[0] == 'y') X del_files(fp); X} X Xdel_files(fp) Xstruct file_pair *fp; X{ X (void) unlink(fp->file_data); X (void) unlink(fp->file_rec); X} X X#ifdef notdef Xsavetmps() X{ X struct file_pair *fp; X int status, X pid; X X if (strcmp(TMP_DIR, REC_DIR) == 0) X return; /* Files are moved to the same place. */ X get_files(TMP_DIR); X for (fp = First; fp != 0; fp = fp->file_next) { X switch (pid = fork()) { X case -1: X fprintf(stderr, "recover: can't fork\n!"); X exit(-1); X X case 0: X execl("/bin/cp", "cp", fp->file_data, fp->file_rec, X REC_DIR, (char *)0); X fprintf(stderr, "recover: cannot execl /bin/cp.\n"); X exit(-1); X X default: X while (wait(&status) != pid) X ; X if (status != 0) X fprintf(stderr, "recover: non-zero status (%d) returned from copy.\n", status); X } X } X} X#endif X Xlookup(dir) Xchar *dir; X{ X struct file_pair *fp; X struct rec_head header; X char yorn[20]; X int nfound = 0, X this_one; X X printf("Checking %s ...\n", dir); X Directory = dir; X get_files(dir); X for (fp = First; fp != 0; fp = fp->file_next) { X nfound += doit(fp); X if (ptrs_fp) X (void) fclose(ptrs_fp); X if (data_fd > 0) X (void) close(data_fd); X } X return nfound; X} X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int nfound; X char **argvp; X X UserID = getuid(); X X if (scanvec(argv, "-help")) { X printf("recover: usage: recover [-d directory]\n"); X printf("Use \"recover\" after JOVE has died for some\n"); X printf("unknown reason.\n\n"); X printf("Use \"recover -syscrash\" when the system is in the process\n"); X printf("of rebooting. This is done automatically at reboot time\n"); X printf("and so most of you don't have to worry about that.\n\n"); X printf("Use \"recover -d directory\" when the tmp files are store\n"); X printf("in DIRECTORY instead of the default one (/tmp).\n"); X exit(0); X } X if (scanvec(argv, "-v")) X Verbose++; X/* if (scanvec(argv, "-syscrash")) { X printf("Recovering jove files ... "); X savetmps(); X printf("Done.\n"); X exit(0); X } */ X if (argvp = scanvec(argv, "-uid")) X UserID = atoi(argvp[1]); X if (argvp = scanvec(argv, "-d")) X nfound = lookup(argvp[1]); X else X nfound = lookup(TmpFilePath); X if (nfound == 0) X printf("There's nothing to recover.\n"); X} @//E*O*F recover.c// if test 14068 -ne "`wc -c <'recover.c'`"; then echo shar: error transmitting "'recover.c'" '(should have been 14068 characters)' fi fi # end of overwriting check echo shar: extracting "'scandir.c'" '(2708 characters)' if test -f 'scandir.c' ; then echo shar: will not over-write existing file "'scandir.c'" else sed 's/^X//' >scandir.c <<'@//E*O*F scandir.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#include <sys/stat.h> X#include <sys/dir.h> X X#ifdef F_COMPLETION X X#ifdef BSD4_2 X X#define DIRSIZE(entry) DIRSIZ(entry) X X#else X X#define DIRSIZE(entry) (min(strlen(entry->d_name), DIRSIZ)) X Xtypedef struct { X int d_fd; /* File descriptor for this directory */ X} DIR; X XDIR * Xopendir(dir) Xchar *dir; X{ X DIR *dp = (DIR *) malloc(sizeof *dp); X struct stat stbuf; X X if ((dp->d_fd = open(dir, 0)) == -1) X return 0; X if ((fstat(dp->d_fd, &stbuf) == -1) || !(stbuf.st_mode & S_IFDIR)) { X closedir(dp); X return 0; /* this isn't a directory! */ X } X return dp; X} X Xclosedir(dp) XDIR *dp; X{ X (void) close(dp->d_fd); X free((char *) dp); X} X Xstruct direct * Xreaddir(dp) XDIR *dp; X{ X static struct direct dir; X X do X if (read(dp->d_fd, &dir, sizeof dir) != sizeof dir) X return 0; X while (dir.d_ino == 0); X X return &dir; X} X X#endif BSD4_2 X X/* Scandir returns the number of entries or -1 if the directory cannoot X be opened or malloc fails. */ X Xscandir(dir, nmptr, qualify, sorter) Xchar *dir; Xchar ***nmptr; Xint (*qualify)(); Xint (*sorter)(); X{ X DIR *dirp; X struct direct *entry; X char **ourarray; X unsigned int nalloc = 10, X nentries = 0; X X if ((dirp = opendir(dir)) == 0) X return -1; X if ((ourarray = (char **) malloc(nalloc * sizeof (char *))) == 0) Xmemfail: complain("[Malloc failed: cannot scandir]"); X while ((entry = readdir(dirp)) != 0) { X if (qualify != 0 && (*qualify)(entry->d_name) == 0) X continue; X if (nentries == nalloc) { X ourarray = (char **) realloc((char *) ourarray, (nalloc += 10) * sizeof (char *)); X if (ourarray == 0) X goto memfail; X } X ourarray[nentries] = (char *) malloc(DIRSIZE(entry) + 1); X null_ncpy(ourarray[nentries], entry->d_name, (int) DIRSIZE(entry)); X nentries++; X } X closedir(dirp); X if ((nentries + 1) != nalloc) X ourarray = (char **) realloc((char *) ourarray, X ((nentries + 1) * sizeof (char *))); X if (sorter != 0) X qsort((char *) ourarray, nentries, sizeof (char **), sorter); X *nmptr = ourarray; X ourarray[nentries] = 0; /* guaranteed 0 pointer */ X X return nentries; X} X Xfreedir(nmptr, nentries) Xchar ***nmptr; X{ X char **ourarray = *nmptr; X X while (--nentries >= 0) X free(*ourarray++); X free((char *) *nmptr); X *nmptr = 0; X} X Xalphacomp(a, b) Xchar **a, X **b; X{ X return strcmp(*a, *b); X} X X#endif @//E*O*F scandir.c// if test 2708 -ne "`wc -c <'scandir.c'`"; then echo shar: error transmitting "'scandir.c'" '(should have been 2708 characters)' fi fi # end of overwriting check echo shar: extracting "'screen.c'" '(17553 characters)' if test -f 'screen.c' ; then echo shar: will not over-write existing file "'screen.c'" else sed 's/^X//' >screen.c <<'@//E*O*F screen.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#include "io.h" X#include "ctype.h" X#include "termcap.h" X Xextern int BufSize; X Xint OkayAbort, X tabstop = 8; X Xint (*TTins_line)(), X (*TTdel_line)(); X Xstruct scrimage X *DesiredScreen = 0, X *PhysScreen = 0; X Xstruct screenline *Screen = 0, /* the screen (a bunch of screenline) */ X *Savelines = 0, /* another bunch (LI of them) */ X *Curline = 0; /* current line */ Xchar *cursor, /* offset into current Line */ X *cursend; X Xint CapCol, X CapLine, X X i_line, X i_col; X Xmake_scr() X{ X register int i; X register struct screenline *ns; X register char *nsp; X X#ifdef RESHAPING X /* In case we are RESHAPING the window! */ X if (DesiredScreen) X free((char *) DesiredScreen); X if (PhysScreen) X free((char *) PhysScreen); X if (Savelines) X free((char *) Savelines); X if (Screen) { X free(Screen->s_line); /* free all the screen data */ X free((char *) Screen); X } X#endif RESHAPING X X DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage)); X PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage)); X X Savelines = (struct screenline *) X malloc((unsigned) LI * sizeof(struct screenline)); X ns = Screen = (struct screenline *) X malloc((unsigned) LI * sizeof(struct screenline)); X X nsp = (char *) malloc((unsigned)CO * LI); X if (nsp == 0) { X printf("\n\rCannot malloc screen!\n"); X finish(1); X } X X for (i = 0; i < LI; i++) { X ns->s_line = nsp; X nsp += CO; X ns->s_length = nsp - 1; /* End of Line */ X ns++; X } X cl_scr(0); X} X Xclrline(cp1, cp2) Xregister char *cp1, X *cp2; X{ X while (cp1 <= cp2) X *cp1++ = ' '; X} X X#define sputc(c) ((*cursor != (char) (c)) ? dosputc(c) : (cursor++, i_col++)) X#define soutputc(c) if (--n <= 0) break; else sputc(c) X Xcl_eol() X{ X if (cursor > cursend) X return; X X if (cursor < Curline->s_length) { X if (CE) { X Placur(i_line, i_col); X putpad(CE, 1); X clrline(cursor, Curline->s_length); X } else { X /* Ugh. The slow way for dumb terminals. */ X register char *savecp = cursor; X X while (cursor <= Curline->s_length) X sputc(' '); X cursor = savecp; X } X Curline->s_length = cursor; X } X} X Xcl_scr(doit) X{ X register int i; X register struct screenline *sp = Screen; X X for (i = 0; i < LI; i++, sp++) { X clrline(sp->s_line, sp->s_length); X sp->s_length = sp->s_line; X PhysScreen[i].s_id = 0; X } X if (doit) { X putpad(CL, LI); X CapCol = CapLine = 0; X UpdMesg++; X } X} X X#ifdef ID_CHAR Xextern int IN_INSmode; X#endif X X/* Output one character (if necessary) at the current position */ X Xdosputc(c) Xregister char c; X{ X if (*cursor != c) { X#ifdef ID_CHAR X if (IN_INSmode) X INSmode(0); X#endif X if (i_line != CapLine || i_col != CapCol) X Placur(i_line, i_col); X if (UL && (c & 0177) == '_' && (*cursor & 0177) != ' ') X putstr(" \b"); /* Erase so '_' looks right. */ X *cursor++ = c; X putchar(c & 0177); X CapCol++; X i_col++; X } else { X cursor++; X i_col++; X } X} X X/* Write `line' at the current position of `cursor'. Stop when we X reach the end of the screen. Aborts if there is a character X waiting. */ X Xswrite(line, inversep, abortable) Xregister char *line; Xregister int abortable; X{ X register int c; X int col = i_col, X aborted = 0; X register int n = cursend - cursor; X int or_byte = inversep ? 0200 : 0, X thebyte; X X if (n <= 0) X return 1; X X OkayAbort = 0; X while (c = *line++) { X if (abortable && OkayAbort) { X OkayAbort = NO; X if (InputPending = charp()) { X aborted = 1; X break; X } X } X if (c == '\t') { X int nchars; X X nchars = (tabstop - (col % tabstop)); X col += nchars; X X thebyte = (' ' | or_byte); X while (nchars--) X soutputc(thebyte); X if (n <= 0) X break; X } else if (isctrl(c)) { X thebyte = ('^' | or_byte); X soutputc(thebyte); X thebyte = (((c == '\177') ? '?' : c + '@') | or_byte); X soutputc(thebyte); X col += 2; X } else { X thebyte = (c | or_byte); X soutputc(thebyte); X col++; X } X } X if (n <= 0) { X if ((*line == '\0') && (c != '\t') && !isctrl(c)) X sputc(c|or_byte); X else X sputc('!'|or_byte); X } X if (cursor > Curline->s_length) X Curline->s_length = cursor; X return !aborted; X} X X/* This is for writing a buffer line to the screen. This is to X minimize the amount of copying from one buffer to another buffer. X This gets the info directly from the disk buffers. */ X XBufSwrite(linenum) X{ X char *bp; X register int n = cursend - cursor, X col = 0, X c; X int StartCol = DesiredScreen[linenum].s_offset, X visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE, X aborted = 0; X X bp = lcontents(DesiredScreen[linenum].s_lp); X if (*bp) for (;;) { X if (col >= StartCol) { X DesiredScreen[linenum].s_offset = col; X break; X } X X c = *bp++ & 0177; X if (c == '\t') X col += (tabstop - (col % tabstop)); X else if (isctrl(c)) X col += 2; X else X col++; X } X X OkayAbort = 0; X while (c = (*bp++ & 0177)) { X if (OkayAbort) { X OkayAbort = NO; X if (InputPending = charp()) { X aborted = 1; X break; X } X } X if (c == '\t') { X int nchars = (tabstop - (col % tabstop)); X X col += nchars; X if (visspace) { X soutputc('>'); X nchars--; X } X while (--nchars >= 0) X soutputc(' '); X if (n <= 0) X break; X } else if (isctrl(c)) { X soutputc('^'); X soutputc((c == '\177') ? '?' : c + '@'); X col += 2; X } else { X if (c == ' ' && visspace) X c = '_'; X soutputc(c); X col++; X } X } X if (n <= 0) { X if ((*bp == '\0') && (c != '\t') && !isctrl(c)) X sputc(c); X else X sputc('!'); X } X if (cursor > Curline->s_length) X Curline->s_length = cursor; X return !aborted; /* Didn't abort */ X} X Xi_set(nline, ncol) Xregister int nline, X ncol; X{ X Curline = &Screen[nline]; X cursor = Curline->s_line + ncol; X cursend = &Curline->s_line[CO - 1]; X i_line = nline; X i_col = ncol; X} X X/* Insert `num' lines a top, but leave all the lines BELOW `bottom' X alone (at least they won't look any different when we are done). X This changes the screen array AND does the physical changes. */ X Xv_ins_line(num, top, bottom) X{ X register int i; X X /* Save the screen pointers. */ X X for(i = 0; i < num && top + i <= bottom; i++) X Savelines[i] = Screen[bottom - i]; X X /* Num number of bottom lines will be lost. X Copy everything down num number of times. */ X X for (i = bottom; i > top && i-num >= 0; i--) X Screen[i] = Screen[i - num]; X X /* Restore the saved ones, making them blank. */ X X for (i = 0; i < num; i++) { X Screen[top + i] = Savelines[i]; X clrline(Screen[top + i].s_line, Screen[top + i].s_length); X Screen[top + i].s_length = Screen[top + i].s_line; X } X X (*TTins_line)(top, bottom, num); X} X X/* Delete `num' lines starting at `top' leaving the lines below `bottom' X alone. This updates the internal image as well as the physical image. */ X Xv_del_line(num, top, bottom) X{ X register int i, X bot; X X bot = bottom; X X /* Save the lost lines. */ X X for (i = 0; i < num && top + i <= bottom; i++) X Savelines[i] = Screen[top + i]; X X /* Copy everything up num number of lines. */ X X for (i = top; num + i <= bottom; i++) X Screen[i] = Screen[i + num]; X X /* Restore the lost ones, clearing them. */ X X for (i = 0; i < num; i++) { X Screen[bottom - i] = Savelines[i]; X clrline(Screen[bot].s_line, Screen[bot].s_length); X Screen[bot].s_length = Screen[bot].s_line; X bot--; X } X X (*TTdel_line)(top, bottom, num); X} X X X/* The cursor optimization happens here. You may decide that this X is going too far with cursor optimization, or perhaps it should X limit the amount of checking to when the output speed is slow. X What ever turns you on ... */ X Xprivate struct cursaddr { X int c_numchars, X (*c_proc)(); X}; X Xprivate char *Cmstr; Xprivate struct cursaddr *HorMin, X *VertMin, X *DirectMin; X Xprivate ForMotion(), X ForTab(), X BackMotion(), X RetTab(), X DownMotion(), X UpMotion(), X GoDirect(), X HomeGo(), X BottomUp(); X X Xprivate struct cursaddr WarpHor[] = { X 0, ForMotion, X 0, ForTab, X 0, BackMotion, X 0, RetTab X}; X Xprivate struct cursaddr WarpVert[] = { X 0, DownMotion, X 0, UpMotion X}; X Xprivate struct cursaddr WarpDirect[] = { X 0, GoDirect, X 0, HomeGo, X 0, BottomUp X}; X X#undef FORWARD X#define FORWARD 0 /* Move forward */ X#define FORTAB 1 /* Forward using tabs */ X#undef BACKWARD X#define BACKWARD 2 /* Move backward */ X#define RETFORWARD 3 /* Beginning of line and then tabs */ X#define NUMHOR 4 X X#define DOWN 0 /* Move down */ X#define UPMOVE 1 /* Move up */ X#define NUMVERT 2 X X#define DIRECT 0 /* Using CM */ X#define HOME 1 /* HOME */ X#define LOWER 2 /* Lower Line */ X#define NUMDIRECT 3 X X#define home() Placur(0, 0) X#define LowLine() putpad(LL, 1), CapLine = ILI, CapCol = 0 X#define PrintHo() putpad(HO, 1), CapLine = CapCol = 0 X Xint phystab = 8; X Xprivate XGoDirect(line, col) Xregister int line, X col; X{ X putpad(Cmstr, 1); X CapLine = line; X CapCol = col; X} X Xprivate XRetTab(col) Xregister int col; X{ X putchar('\r'); X CapCol = 0; X ForTab(col); X} X Xprivate XHomeGo(line, col) X{ X PrintHo(); X DownMotion(line); X ForTab(col); X} X Xprivate XBottomUp(line, col) Xregister int line, X col; X{ X LowLine(); X UpMotion(line); X ForTab(col); X} X X/* Tries to move forward using tabs (if possible). It tabs to the X closest tabstop which means it may go past 'destcol' and backspace X to it. */ X Xprivate XForTab(destcol) Xint destcol; X{ X register int tabgoal, X ntabs, X tabstp = phystab; X X if (TABS && (tabstp > 0)) { X tabgoal = destcol + (tabstp / 2); X tabgoal -= (tabgoal % tabstp); X X /* Don't tab to last place or else it is likely to screw up. */ X if (tabgoal >= CO) X tabgoal -= tabstp; X X ntabs = (tabgoal / tabstp) - (CapCol / tabstp); X while (--ntabs >= 0) X putchar('\t'); X CapCol = tabgoal; X } X if (CapCol > destcol) X BackMotion(destcol); X else if (CapCol < destcol) X ForMotion(destcol); X} X Xprivate XForMotion(destcol) Xregister int destcol; X{ X register int nchars = destcol - CapCol; X register char *cp = &Screen[CapLine].s_line[CapCol]; X X while (--nchars >= 0) X putchar(*cp++ & 0177); X CapCol = destcol; X} X Xprivate XBackMotion(destcol) Xregister int destcol; X{ X register int nchars = CapCol - destcol; X X if (BC) X while (--nchars >= 0) X putpad(BC, 1); X else X while (--nchars >= 0) X putchar('\b'); X CapCol = destcol; X} X Xprivate XDownMotion(destline) Xregister int destline; X{ X register int nlines = destline - CapLine; X X while (--nlines >= 0) X putchar('\n'); X CapLine = destline; X} X Xprivate XUpMotion(destline) Xregister int destline; X{ X register int nchars = CapLine - destline; X X while (--nchars >= 0) X putpad(UP, 1); X CapLine = destline; X} X X#ifdef ID_CHAR Xstatic int EIlen; X#endif Xextern int IMlen; X XInitCM() X{ X HOlen = HO ? strlen(HO) : 1000; X LLlen = LL ? strlen(LL) : 1000; X UPlen = UP ? strlen(UP) : 1000; X#ifdef ID_CHAR X if (EI) X EIlen = strlen(EI); X#endif X} X XPlacur(line, col) X{ X int dline, /* Number of lines to move */ X dcol; /* Number of columns to move */ X register int best, X i; X register struct cursaddr *cp; X int xtracost = 0; /* Misc addition to cost. */ X X#define CursMin(which,addrs,max) \ X for (best = 0, cp = &addrs[1], i = 1; i < max; i++, cp++) \ X if (cp->c_numchars < addrs[best].c_numchars) \ X best = i; \ X which = &addrs[best]; X X if (line == CapLine && col == CapCol) X return; /* We are already there. */ X X dline = line - CapLine; X dcol = col - CapCol; X#ifdef ID_CHAR X if (IN_INSmode && MI) X xtracost = EIlen + IMlen; X /* If we're already in insert mode, it is likely that we will X want to be in insert mode again, after the insert. */ X#endif X X /* Number of characters to move horizontally for each case. X 1: Just move forward by typing the right character on the screen. X 2: Print the correct number of back spaces. X 3: Try tabbing to the correct place. X 4: Try going to the beginning of the line, and then tab. */ X X if (dcol == 1 || dcol == 0) { /* Most common case. */ X HorMin = &WarpHor[FORWARD]; X HorMin->c_numchars = dcol + xtracost; X } else { X WarpHor[FORWARD].c_numchars = dcol >= 0 ? dcol + xtracost : 1000; X WarpHor[BACKWARD].c_numchars = dcol < 0 ? -(dcol + xtracost) : 1000; X WarpHor[FORTAB].c_numchars = dcol >= 0 && TABS ? X ForNum(CapCol, col) + xtracost : 1000; X WarpHor[RETFORWARD].c_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col)); X X /* Which is the shortest of the bunch */ X X CursMin(HorMin, WarpHor, NUMHOR); X } X X /* Moving vertically is more simple. */ X X WarpVert[DOWN].c_numchars = dline >= 0 ? dline : 1000; X WarpVert[UPMOVE].c_numchars = dline < 0 ? ((-dline) * UPlen) : 1000; X X /* Which of these is simpler */ X CursMin(VertMin, WarpVert, NUMVERT); X X /* Homing first and lowering first are considered X direct motions. X Homing first's total is the sum of the cost of homing X and the sum of tabbing (if possible) to the right. */ X X if (VertMin->c_numchars + HorMin->c_numchars <= 3) { X DirectMin = &WarpDirect[DIRECT]; /* A dummy ... */ X DirectMin->c_numchars = 100; X } else { X WarpDirect[DIRECT].c_numchars = CM ? X strlen(Cmstr = tgoto(CM, col, line)) : 1000; X WarpDirect[HOME].c_numchars = HOlen + line + X WarpHor[RETFORWARD].c_numchars; X WarpDirect[LOWER].c_numchars = LLlen + ((ILI - line) * UPlen) + X WarpHor[RETFORWARD].c_numchars; X CursMin(DirectMin, WarpDirect, NUMDIRECT); X } X X if (HorMin->c_numchars + VertMin->c_numchars < DirectMin->c_numchars) { X if (line != CapLine) X (*VertMin->c_proc)(line); X if (col != CapCol) { X#ifdef ID_CHAR X if (IN_INSmode) /* We may use real characters ... */ X INSmode(0); X#endif X (*HorMin->c_proc)(col); X } X } else { X#ifdef ID_CHAR X if (IN_INSmode && !MI) X INSmode(0); X#endif X (*DirectMin->c_proc)(line, col); X } X} X X#define abs(x) ((x) >= 0 ? (x) : -(x)) X XForNum(from, to) Xregister int from; X{ X register int tabgoal, X tabstp = phystab; X int numchars = 0; X X if (from >= to) X return from - to; X if (TABS && (tabstp > 0)) { X tabgoal = to + (tabstp / 2); X tabgoal -= (tabgoal % tabstp); X if (tabgoal >= CO) X tabgoal -= tabstp; X numchars = (tabgoal / tabstop) - (from / tabstp); X from = tabgoal; X } X return numchars + abs(from - to); X} X X#ifdef WIRED_TERMS X XBGi_lines(top, bottom, num) X{ X printf("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num); X CapCol = CapLine = 0; X} X XSUNi_lines(top, bottom, num) X{ X Placur(bottom - num + 1, 0); X printf("\033[%dM", num); X Placur(top, 0); X printf("\033[%dL", num); X} X XC100i_lines(top, bottom, num) X{ X if (num <= 1) { X GENi_lines(top, bottom, num); X return; X } X printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO); X CapLine = CapCol = 0; X Placur(top, 0); X while (num--) X putpad(AL, ILI - CapLine); X printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO); X CapLine = CapCol = 0; X} X X#endif WIRED_TERMS X XGENi_lines(top, bottom, num) X{ X register int i; X X if (CS) { X putpad(tgoto(CS, bottom, top)); X CapCol = CapLine = 0; X Placur(top, 0); X for (i = 0; i < num; i++) X putpad(SR, bottom - top); X putpad(tgoto(CS, ILI, 0)); X CapCol = CapLine = 0; X } else { X Placur(bottom - num + 1, 0); X if (M_DL && (num > 1)) { X char minibuf[16]; X X sprintf(minibuf, M_DL, num); X putpad(minibuf, ILI - CapLine); X } else { X for (i = 0; i < num; i++) X putpad(DL, ILI - CapLine); X } X Placur(top, 0); X if (M_AL && (num > 1)) { X char minibuf[16]; X X sprintf(minibuf, M_AL, num); X putpad(minibuf, ILI - CapLine); X } else { X for (i = 0; i < num; i++) X putpad(AL, ILI - CapLine); X } X } X} X X#ifdef WIRED_TERMS X XBGd_lines(top, bottom, num) X{ X printf("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num); X CapCol = CapLine = 0; X} X XSUNd_lines(top, bottom, num) X{ X Placur(top, 0); X printf("\033[%dM", num); X Placur(bottom + 1 - num, 0); X printf("\033[%dL", num); X} X XC100d_lines(top, bottom, num) X{ X if (num <= 1) { X GENd_lines(top, bottom, num); X return; X } X printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO); X CapLine = CapCol = 0; X Placur(top, 0); X while (num--) X putpad(DL, ILI - CapLine); X printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO); X CapLine = CapCol = 0; X} X X#endif WIRED_TERMS X XGENd_lines(top, bottom, num) X{ X register int i; X X if (CS) { X putpad(tgoto(CS, bottom, top)); X CapCol = CapLine = 0; X Placur(bottom, 0); X for (i = 0; i < num; i++) X putpad(SF, bottom - top); X putpad(tgoto(CS, ILI, 0)); X CapCol = CapLine = 0; X } else { X Placur(top, 0); X if (M_DL && (num > 1)) { X char minibuf[16]; X X sprintf(minibuf, M_DL, num); X putpad(minibuf, ILI - top); X } else { X for (i = 0; i < num; i++) X putpad(DL, ILI - top); X } X Placur(bottom + 1 - num, 0); X if (M_AL && (num > 1)) { X char minibuf[16]; X X sprintf(minibuf, M_AL, num); X putpad(minibuf, ILI - CapLine); X } else { X for (i = 0; i < num; i++) X putpad(AL, ILI - CapLine); X } X } X} X Xstruct ID_lookup { X char *ID_name; X int (*I_proc)(); /* proc to insert lines */ X int (*D_proc)(); /* proc to delete lines */ X} ID_trms[] = { X "generic", GENi_lines, GENd_lines, /* This should stay here */ X#ifdef WIRED_TERMS X "sun", SUNi_lines, SUNd_lines, X "bg", BGi_lines, BGd_lines, X "c1", C100i_lines, C100d_lines, X#endif WIRED_TERMS X 0, 0, 0 X}; X XIDline_setup(tname) Xchar *tname; X{ X register struct ID_lookup *idp; X X for (idp = &ID_trms[1]; idp->ID_name; idp++) X if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0) X break; X if (idp->ID_name == 0) X idp = &ID_trms[0]; X TTins_line = idp->I_proc; X TTdel_line = idp->D_proc; X} @//E*O*F screen.c// if test 17553 -ne "`wc -c <'screen.c'`"; then echo shar: error transmitting "'screen.c'" '(should have been 17553 characters)' fi fi # end of overwriting check echo shar: extracting "'teachjove.c'" '(1052 characters)' if test -f 'teachjove.c' ; then echo shar: will not over-write existing file "'teachjove.c'" else sed 's/^X//' >teachjove.c <<'@//E*O*F teachjove.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 <sys/types.h> X#include <sys/file.h> X X#ifndef TEACHJOVE X# define TEACHJOVE "/usr/lib/jove/teach-jove" X#endif X X#ifndef W_OK X# define W_OK 2 X# define F_OK 0 X#endif X Xextern char *getenv(); X Xmain() X{ X char cmd[256], X fname[256], X *home; X X if ((home = getenv("HOME")) == 0) { X printf("teachjove: cannot find your home!\n"); X exit(-1); X } X (void) sprintf(fname, "%s/teach-jove", home); X if (access(fname, F_OK) != 0) { X (void) sprintf(cmd, "cp %s %s", TEACHJOVE, fname); X system(cmd); X } X (void) execlp("jove", "teachjove", fname, (char *) 0); X printf("teachjove: cannot execl jove!\n"); X} X @//E*O*F teachjove.c// if test 1052 -ne "`wc -c <'teachjove.c'`"; then echo shar: error transmitting "'teachjove.c'" '(should have been 1052 characters)' fi fi # end of overwriting check echo shar: extracting "'tune.template'" '(882 characters)' if test -f 'tune.template' ; then echo shar: will not over-write existing file "'tune.template'" else sed 's/^X//' >tune.template <<'@//E*O*F tune.template//' 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 NOEXTERNS X X#include "tune.h" X Xchar TmpFilePath[128] = "TMPDIR"; X Xchar *d_tempfile = "joveXXXXXX", /* buffer lines go here */ X *p_tempfile = "jrecXXXXXX", /* line pointers go here */ X *Recover = "LIBDIR/recover", X *CmdDb = "LIBDIR/cmds.doc", X /* copy of "cmds.doc" lives in the doc subdirectory */ X X *Joverc = "LIBDIR/.joverc", X X#ifdef PIPEPROCS X *Portsrv = "LIBDIR/portsrv", X#endif X X Shell[128] = "SHELL", X ShFlags[16] = "-c"; @//E*O*F tune.template// if test 882 -ne "`wc -c <'tune.template'`"; then echo shar: error transmitting "'tune.template'" '(should have been 882 characters)' fi fi # end of overwriting check echo shar: extracting "'version.c'" '(473 characters)' if test -f 'version.c' ; then echo shar: will not over-write existing file "'version.c'" else sed 's/^X//' >version.c <<'@//E*O*F version.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 Xchar *version = "4.6.1.4"; @//E*O*F version.c// if test 473 -ne "`wc -c <'version.c'`"; then echo shar: error transmitting "'version.c'" '(should have been 473 characters)' fi fi # end of overwriting check echo shar: "End of archive 7 (of 13)." cp /dev/null ark7isdone 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