sources-request@mirror.UUCP (02/04/87)
Submitted by: seismo!rochester!jpayne (Jonathan Payne) Mod.sources: Volume 8, Issue 21 Archive-name: jove/Part02 #! /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 2 (of 13)." # Contents: c.c ctype.c delete.c disp.c fmt.c re.h rec.h # doc/cmds.doc.nr PATH=/bin:/usr/bin:/usr/ucb; export PATH echo shar: extracting "'c.c'" '(13187 characters)' if test -f 'c.c' ; then echo shar: will not over-write existing file "'c.c'" else sed 's/^X//' >c.c <<'@//E*O*F c.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 commands for C mode. Paren matching routines are in here. */ X X#include "jove.h" X#include "re.h" X#include "ctype.h" X Xprivate Xbackslashed(lp, cpos) Xregister char *lp; Xregister int cpos; X{ X register int cnt = 0; X X while (cpos > 0 && lp[--cpos] == '\\') X cnt++; X return (cnt % 2); X} X Xprivate char *p_types = "(){}[]"; Xprivate int mp_kind; X#define MP_OKAY 0 X#define MP_MISMATCH 1 X#define MP_UNBALANCED 2 X Xmp_error() X{ X switch (mp_kind) { X case MP_MISMATCH: X message("[Mismatched parentheses]"); X break; X X case MP_UNBALANCED: X message("[Unbalanced parenthesis]"); X break; X X case MP_OKAY: X default: X return; X } X rbell(); X} X X/* Search from the current position for the paren that matches p_type. X Search in the direction dir. If can_mismatch is YES then it is okay X to have mismatched parens. If stop_early is YES then when an open X paren is found at the beginning of a line, it is assumed that there X is no point in backing up further. This is so when you hit tab or X LineFeed outside, in-between procedure/function definitions, it won't X sit there searching all the way to the beginning of the file for a X match that doesn't exist. {forward,backward}-s-expression are the X only ones that insist on getting the "true" story. */ X XBufpos * Xm_paren(p_type, dir, can_mismatch, can_stop) Xchar p_type; Xregister int dir; X{ X static Bufpos ret; X Bufpos savedot, X *sp; X char re_buf[100], X *re_alts[NALTS]; X int count = 0; X register char *lp, X c; X char p_match, X re_str[128], X *cp, X quote_c = 0; X register int c_char; X int in_comment = NO, X stopped = NO; X X sprintf(re_str, "[(){}[\\]%s]", (MajorMode(CMODE)) ? "/\"'" : "\""); X REcompile(re_str, 1, re_buf, re_alts); X if (cp = index(p_types, p_type)) X p_match = cp[dir]; X else X complain("[Cannot match %c's]", p_type); X DOTsave(&savedot); X X /* To make things a little faster I avoid copying lines into X linebuf by setting curline and curchar by hand. Warning: X this is slightly to very risky. When I did this there were X lots of problems with procedures that expect the contents of X curline to be in linebuf. */ X while (count >= 0) { X sp = docompiled(dir, re_buf, re_alts); X if (sp == 0) X break; X lp = lbptr(sp->p_line); X X curline = sp->p_line; X curchar = sp->p_char; /* here's where I cheat */ X c_char = curchar; X if (dir == FORWARD) X c_char--; X X if (backslashed(lp, c_char)) X continue; X c = lp[c_char]; X /* check if this is a comment (if we're not inside quotes) */ X if (quote_c == 0 && c == '/') { X if ((c_char != 0) && lp[c_char - 1] == '*') X in_comment = (dir == FORWARD) ? NO : YES; X else if (lp[c_char + 1] == '*') X in_comment = (dir == FORWARD) ? YES : NO; X } X if (in_comment) X continue; X if (c == '"' || c == '\'') { X if (quote_c == c) X quote_c = 0; X else if (quote_c == 0) X quote_c = c; X } X if (quote_c != 0) X continue; X if (isopenp(c)) { X count += dir; X if (c_char == 0 && can_stop == YES && count >= 0) { X stopped = YES; X break; X } X } else if (isclosep(c)) X count -= dir; X } X X ret.p_line = curline; X ret.p_char = curchar; X X curline = savedot.p_line; X curchar = savedot.p_char; /* here's where I undo it */ X X if (count >= 0) X mp_kind = MP_UNBALANCED; X else if (c != p_match) X mp_kind = MP_MISMATCH; X else X mp_kind = MP_OKAY; X X /* If we stopped (which means we were allowed to stop) and there X was an error, we clear the error so no error message is printed. X An error should be printed ONLY when we are sure about the fact, X namely we didn't stop prematurely HOPING that it was the right X answer. */ X if (stopped && mp_kind != MP_OKAY) { X mp_kind = MP_OKAY; X return 0; X } X if (mp_kind == MP_OKAY || (mp_kind == MP_MISMATCH && can_mismatch == YES)) X return &ret; X return 0; X} X Xprivate Xdo_expr(dir, skip_words) Xregister int dir; X{ X register char c, X syntax = (dir == FORWARD) ? _Op : _Cl; X X exp = 1; X if (dir == BACKWARD) X BackChar(); X c = linebuf[curchar]; X for (;;) { X if (!skip_words && ismword(c)) { X WITH_TABLE(curbuf->b_major) X (dir == FORWARD) ? ForWord() : BackWord(); X END_TABLE(); X break; X } else if (has_syntax(c, syntax)) { X FindMatch(dir); X break; X } X DoTimes(ForChar(), dir); X if (eobp() || bobp()) X return; X c = linebuf[curchar]; X } X} X XFSexpr() X{ X register int num = exp; X X if (exp < 0) { X exp = -exp; X BSexpr(); X } X while (--num >= 0) X do_expr(FORWARD, NO); X} X XFList() X{ X register int num = exp; X X if (exp < 0) { X exp = -exp; X BList(); X } X while (--num >= 0) X do_expr(FORWARD, YES); X} X XBSexpr() X{ X register int num = exp; X X if (exp < 0) { X exp = -exp; X FSexpr(); X } X while (--num >= 0) X do_expr(BACKWARD, NO); X} X XBList() X{ X register int num = exp; X X if (exp < 0) { X exp = -exp; X FList(); X } X while (--num >= 0) X do_expr(BACKWARD, YES); X} X XBUpList() X{ X Bufpos *mp; X char c = (MajorMode(CMODE) ? '}' : ')'); X X mp = m_paren(c, BACKWARD, NO, YES); X if (mp == 0) X mp_error(); X else X SetDot(mp); X} X XFDownList() X{ X Bufpos *sp; X char *sstr = (MajorMode(CMODE) ? "[{([\\])}]" : "[()]"), X *lp; X X sp = dosearch(sstr, FORWARD, YES); X if (sp != 0) X lp = lcontents(sp->p_line); X if (sp == 0 || has_syntax(lp[sp->p_char - 1], _Cl)) X complain("[No contained expression]"); X SetDot(sp); X} X X/* Move to the matching brace or paren depending on the current position X in the buffer. */ X Xprivate XFindMatch(dir) X{ X register Bufpos *bp; X register char c = linebuf[curchar]; X X if ((index(p_types, c) == 0) || X (backslashed(linebuf, curchar))) X complain((char *) 0); X if (dir == FORWARD) X ForChar(); X bp = m_paren(c, dir, YES, NO); X if (dir == FORWARD) X BackChar(); X if (bp != 0) X SetDot(bp); X mp_error(); /* if there is an error the user wants to X know about it */ X} X XBufpos * Xc_indent(incrmt) X{ X Bufpos *bp; X int indent = 0; X X if (bp = m_paren('}', BACKWARD, NO, YES)) { X Bufpos save; X X DOTsave(&save); X SetDot(bp); X ToIndent(); X indent = calc_pos(linebuf, curchar); X SetDot(&save); X } X if (incrmt) { X if (indent == 0) X incrmt = tabstop; X else X incrmt = (tabstop - (indent%tabstop)); X } X n_indent(indent + incrmt); X return bp; X} X X#ifdef CMT_FMT X Xchar CmtFmt[80] = "/*%n%! * %c%!%n */"; X XComment() X{ X FillComment(CmtFmt); X} X X/* Strip leading and trailing white space. Skip over any imbedded '\r's. */ X Xprivate Xstrip_c(from, to) Xchar *from, X *to; X{ X register char *fr_p = from, X *to_p = to, X c; X X while (c = *fr_p) { X if (c == ' ' || c == '\t' || c == '\r') X fr_p++; X else X break; X } X while (c = *fr_p) { X if (c != '\r') X *to_p++ = c; X fr_p++; X } X while (--to_p >= to) X if (*to_p != ' ' && *to_p != '\t') X break; X *++to_p = '\0'; X} X Xprivate char open_c[20], /* the open comment format string */ X open_pat[20], /* the search pattern for open comment */ X l_header[20], /* the prefix for each comment line */ X l_trailer[20], /* the suffix ... */ X close_c[20], X close_pat[20]; X Xprivate char *comment_body[] = { X open_c, X l_header, X l_trailer, X close_c X}; X Xprivate int nlflags; X X/* Fill in the data structures above from the format string. Don't return X if there's trouble. */ X Xprivate Xparse_cmt_fmt(str) Xchar *str; X{ X register char *fmtp = str; X register char **c_body = comment_body, X *body_p = *c_body; X int c, X newlines = 1; X X /* pick apart the comment string */ X while (c = *fmtp++) { X if (c != '%') { X *body_p++ = c; X continue; X } X switch(c = *fmtp++) { X case 'n': X if (newlines == 2 || newlines == 3) X complain("%n not allowed in line header or trailer: %s", X fmtp - 2); X nlflags += newlines; X *body_p++ = '\r'; X break; X case 't': X *body_p++ = '\t'; X break; X case '%': X *body_p++ = '%'; X break; X case '!': X case 'c': X newlines++; X *body_p++ = '\0'; X body_p = *++c_body; X break; X default: X complain("[Unknown comment escape: %%%c]", c); X /* VARARGS */ X break; X } X } X *body_p = '\0'; X /* make search patterns */ X strip_c(open_c, open_pat); X strip_c(close_c, close_pat); X} X X#define NL_IN_OPEN_C ((nlflags % 4) == 1) X#define NL_IN_CLOSE_C (nlflags >= 4) X XFillComment(format) Xchar *format; X{ X int saveRMargin, X indent_pos, X close_at_dot = 0, X slen, X header_len, X trailer_len; X register char *cp; X static char inside_err[] = "[Must be between %s and %s to re-format]"; X Bufpos open_c_pt, X close_c_pt, X tmp_bp, X *match_o, X *match_c; X Mark *entry_mark, X *open_c_mark, X *savedot; X X parse_cmt_fmt(format); X /* figure out if we're "inside" a comment */ X if ((match_o = dosearch(open_pat, BACKWARD, 0)) == 0) X /* VARARGS */ X complain("No opening %s to match to.", open_pat); X open_c_pt = *match_o; X if ((match_c = dosearch(close_pat, BACKWARD, NO)) != 0 && X inorder(open_c_pt.p_line, open_c_pt.p_char, X match_c->p_line, match_c->p_char)) X complain(inside_err, open_pat, close_pat); X if ((match_o = dosearch(open_pat, FORWARD, NO)) != 0) { X tmp_bp = *match_o; X match_o = &tmp_bp; X } X if ((match_c = dosearch(close_pat, FORWARD, 0)) != (Bufpos *) 0) X close_c_pt = *match_c; X X /* Here's where we figure out whether to format from dot or from X the close comment. Note that we've already searched backwards to X find the open comment symbol for the comment we are formatting. X The open symbol mentioned below refers to the possible existence X of the next comment. There are 5 cases: X 1) no open or close symbol ==> dot X 2) open, but no close symbol ==> dot X 3) close, but no open ==> close X 4) open, close are inorder ==> dot X 5) open, close are not inorder ==> close */ X X X if (match_o == (Bufpos *) 0) { X if (match_c == (Bufpos *) 0) X close_at_dot++; X } else if (match_c == (Bufpos *) 0) X close_at_dot++; X else if (inorder(match_o->p_line, match_o->p_char, X match_c->p_line, match_c->p_char)) X close_at_dot++; X X if (close_at_dot) { X close_c_pt.p_line = curline; X close_c_pt.p_char = curchar; X } else { X SetDot(match_c); X } X SetDot(&open_c_pt); X open_c_mark = MakeMark(curline, curchar, FLOATER); X indent_pos = calc_pos(linebuf, curchar); X /* search for a close comment; delete it if it exits */ X SetDot(&close_c_pt); X if (close_at_dot == 0) { X slen = strlen(close_pat); X while (slen--) X DelPChar(); X } X entry_mark = MakeMark(curline, curchar, FLOATER); X ToMark(open_c_mark); X /* always separate the comment body from anything preceeding it */ X LineInsert(1); X DelWtSpace(); X Bol(); X for (cp = open_c; *cp; cp++) { X if (*cp == '\r') { X if (!eolp()) X LineInsert(1); X else X line_move(FORWARD, NO); X } else if (*cp == ' ' || *cp == '\t') { X if (linebuf[curchar] != *cp) X Insert(*cp); X } else X /* Since we matched the open comment string on this X line, we don't need to worry about crossing line X boundaries. */ X curchar++; X } X savedot = MakeMark(curline, curchar, FLOATER); X X /* We need to strip the line header pattern of leading white space X since we need to match the line after all of its leading X whitespace is gone. */ X for (cp = l_header; *cp && (isspace(*cp)); cp++) X ; X header_len = strlen(cp); X trailer_len = strlen(l_trailer); X X /* Strip each comment line of the open and close comment strings X before reformatting it. */ X X do { X Bol(); X DelWtSpace(); X if (header_len && !strncmp(linebuf, cp, header_len)) X DoTimes(DelNChar(), header_len); X if (trailer_len) { X Eol(); X if ((curchar > trailer_len) && X (!strncmp(&linebuf[curchar - trailer_len], X l_trailer, trailer_len))) X DoTimes(DelPChar(), trailer_len); X } X if (curline->l_next != 0) X line_move(FORWARD, NO); X else X break; X } while (curline != entry_mark->m_line->l_next); X X DoSetMark(savedot->m_line, savedot->m_char); X ToMark(entry_mark); X saveRMargin = RMargin; X RMargin = saveRMargin - strlen(l_header) - X strlen(l_trailer) - indent_pos + 2; X /* do not use the left margin */ X exp_p = NO; X do_rfill(); X RMargin = saveRMargin; X /* get back to the start of the comment */ X PopMark(); X do { X if (curline == open_c_mark->m_line->l_next) { X ; X } else { X n_indent(indent_pos); X ins_str(l_header, NO); X } X Eol(); X if (!NL_IN_CLOSE_C && (curline == entry_mark->m_line)) X ; X else X ins_str(l_trailer, NO); X if (curline->l_next != 0) X line_move(FORWARD, NO); X else X break; X } while (curline != entry_mark->m_line->l_next); X /* handle the close comment symbol */ X if (curline == entry_mark->m_line->l_next) { X line_move(BACKWARD, NO); X Eol(); X } X DelWtSpace(); X /* if the addition of the close symbol would cause the line to be X too long, put the close symbol on the next line. */ X if (strlen(close_c) + calc_pos(linebuf, curchar) > RMargin) { X LineInsert(1); X n_indent(indent_pos); X } X for (cp = close_c; *cp; cp++) { X if (*cp == '\r') { X LineInsert(1); X n_indent(indent_pos); X } else X Insert(*cp); X } X ToMark(open_c_mark); X Eol(); X exp_p = NO; X DelNChar(); X} X X#endif CMT_FMT X @//E*O*F c.c// if test 13187 -ne "`wc -c <'c.c'`"; then echo shar: error transmitting "'c.c'" '(should have been 13187 characters)' fi fi # end of overwriting check echo shar: extracting "'ctype.c'" '(3709 characters)' if test -f 'ctype.c' ; then echo shar: will not over-write existing file "'ctype.c'" else sed 's/^X//' >ctype.c <<'@//E*O*F ctype.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 "ctype.h" X Xint SyntaxTable = FUNDAMENTAL; /* Current table to use. */ X Xchar CharTable[NMAJORS][128] = { X{ _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _P, _P, _P, _P, _P, _P, _P, _P, X _Op|_P, _Cl|_P, _P, _P, _P, _P, _P, _P, X _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, X _W|_N, _W|_N, _P, _P, _P, _P, _P, _P, X _P, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _Op|_P, _P, _Cl|_P, _P, _P, X _P, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _Op|_P, _P, _Cl|_P, _P, _C }, X X{ _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _P, _P, _P, _P, _P, _P, _P, _P|_W, X _Op|_P, _Cl|_P, _P, _P, _P, _P, _P, _P, X _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, X _W|_N, _W|_N, _P, _P, _P, _P, _P, _P, X _P, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _Op|_P, _P, _Cl|_P, _P, _P, X _P, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _Op|_P, _P, _Cl|_P, _P, _C }, X X{ _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _P, _P, _P, _P, _P|_W, _P, _P, _P, X _Op|_P, _Cl|_P, _P, _P, _P, _P, _P, _P, X _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, X _W|_N, _W|_N, _P, _P, _P, _P, _P, _P, X _P, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _Op|_P, _P, _Cl|_P, _P, _P|_W, X _P, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _Op|_P, _P, _Cl|_P, _P, _C X#ifndef LISP X} X#else X}, X X{ _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _C, _C, _C, _C, _C, _C, _C, _C, X _P, _W|_P, _P, _P, _W|_P, _W|_P, _W|_P, _P, X _Op|_P, _Cl|_P, _W|_P, _W|_P, _P, _W|_P, _P, _P, X _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, _W|_N, X _W|_N, _W|_N, _W|_P, _P, _W|_P, _W|_P, _W|_P, _W|_P, X _W|_P, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, _W|_U, X _W|_U, _W|_U, _W|_U, _Op|_P, _P, _Cl|_P, _W|_P, _W|_P, X _P, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, _W|_L, X _W|_L, _W|_L, _W|_L, _Op|_W|_P, _W|_P, _Cl|_W|_P, _W|_P, _W|_C }, X#endif X}; X Xismword(c) X{ X return ((CharTable[curbuf->b_major])[c]&(_W)); X} @//E*O*F ctype.c// if test 3709 -ne "`wc -c <'ctype.c'`"; then echo shar: error transmitting "'ctype.c'" '(should have been 3709 characters)' fi fi # end of overwriting check echo shar: extracting "'delete.c'" '(6395 characters)' if test -f 'delete.c' ; then echo shar: will not over-write existing file "'delete.c'" else sed 's/^X//' >delete.c <<'@//E*O*F delete.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/* Routines to perform all kinds of deletion. */ X X#include "jove.h" X X/* Assumes that either line1 or line2 is actual the current line, so it can X put its result into linebuf. */ X Xpatchup(line1, char1, line2, char2) XLine *line1, X *line2; Xregister int char1, X char2; X{ X if (line1 != line2) X ChkWindows(line1, line2); X DotTo(line1, char1); X modify(); X linecopy(linebuf, curchar, lcontents(line2) + char2); X X /* The following is a redisplay optimization. */ X if (line1 != line2 && (char1 == 0 && char2 == 0)) X line1->l_dline = line2->l_dline; X X DFixMarks(line1, char1, line2, char2); X makedirty(curline); X} X X/* Deletes the region by unlinking the lines in the middle, X and patching things up. The unlinked lines are still in X order. */ X XLine * Xreg_delete(line1, char1, line2, char2) XLine *line1, X *line2; X{ X register Line *retline; X X if ((line1 == line2 && char1 == char2) || line2 == 0) X complain((char *) 0); X (void) fixorder(&line1, &char1, &line2, &char2); X X retline = nbufline(); /* New buffer line */ X X (void) ltobuf(line1, genbuf); X if (line1 == line2) X genbuf[char2] = '\0'; X X retline->l_prev = 0; X retline->l_dline = putline(&genbuf[char1]); X patchup(line1, char1, line2, char2); X X if (line1 == line2) X retline->l_next = 0; X else { X retline->l_next = line1->l_next; X (void) ltobuf(line2, genbuf); X genbuf[char2] = '\0'; X line2->l_dline = putline(genbuf); X /* Shorten this line */ X } X X if (line1 != line2) { X line1->l_next = line2->l_next; X if (line1->l_next) X line1->l_next->l_prev = line1; X else X curbuf->b_last = line1; X line2->l_next = 0; X } X X return retline; X} X Xlremove(line1, line2) Xregister Line *line1, X *line2; X{ X Line *next = line1->l_next; X X if (line1 == line2) X return; X line1->l_next = line2->l_next; X if (line1->l_next) X line1->l_next->l_prev = line1; X else X curbuf->b_last = line1; X lfreereg(next, line2); /* Put region at end of free line list. */ X} X X/* Delete character forward */ X XDelNChar() X{ X del_char(1); X} X X/* Delete character backward */ X XDelPChar() X{ X if (MinorMode(OverWrite)) { X int count = min(exp, curchar); X X DoTimes(BackChar(), count); X LastKeyStruck = ' '; /* can you say gross? */ X DoTimes(SelfInsert(), count); X DoTimes(BackChar(), count); X } else X del_char(0); X} X X/* Delete some characters. If deleting `forward' then call for_char X to the final position otherwise call back_char. Then delete the X region between the two with patchup(). */ X Xdel_char(forward) X{ X Bufpos before, X after; X int killp = (exp_p && abs(exp) > 1); X X DOTsave(&before); X (forward) ? ForChar() : BackChar(); X if (before.p_line == curline && before.p_char == curchar) X complain((char *) 0); X if (killp) X reg_kill(before.p_line, before.p_char, 1); X else { X DOTsave(&after); X (void) fixorder(&before.p_line, &before.p_char, &after.p_line, &after.p_char); X patchup(before.p_line, before.p_char, after.p_line, after.p_char); X lremove(before.p_line, after.p_line); X } X} X X/* This kills a region between point, and line1/char1 and puts it on X the kill-ring. If the last command was one of the kill commands, X the region is appended (prepended if backwards) to the last entry. */ X Xint killptr = 0; XLine *killbuf[NUMKILLS]; X Xreg_kill(line2, char2, dot_moved) XLine *line2; X{ X Line *nl, X *line1 = curline; X int char1 = curchar; X int backwards; X X backwards = !fixorder(&line1, &char1, &line2, &char2); X /* This is a kludge! But it possible for commands that don't X know which direction they are deleting in (e.g., delete X previous word could have been called with a negative argument X in which case, it wouldn't know that it really deleted X forward. */ X X if (!dot_moved) X backwards = !backwards; X X DotTo(line1, char1); X X nl = reg_delete(line1, char1, line2, char2); X X if (last_cmd != KILLCMD) { X killptr = ((killptr + 1) % NUMKILLS); X lfreelist(killbuf[killptr]); X killbuf[killptr] = nl; X } else { X Line *lastln = lastline(nl); X X if (backwards) X (void) DoYank(nl, 0, lastln, length(lastln), killbuf[killptr], 0, (Buffer *) 0); X else { X Line *olastln = lastline(killbuf[killptr]); X X (void) DoYank(nl, 0, lastln, length(lastln), olastln, length(olastln), (Buffer *) 0); X } X } X this_cmd = KILLCMD; X} X XDelReg() X{ X register Mark *mp = CurMark(); X X reg_kill(mp->m_line, mp->m_char, 0); X} X X/* Save a region. A pretend kill. */ X XCopyRegion() X{ X register Line *nl; X register Mark *mp; X register int status; X X mp = CurMark(); X if (mp->m_line == curline && mp->m_char == curchar) X complain((char *) 0); X X killptr = ((killptr + 1) % NUMKILLS); X if (killbuf[killptr]) X lfreelist(killbuf[killptr]); X nl = killbuf[killptr] = nbufline(); X SavLine(nl, NullStr); X nl->l_next = nl->l_prev = 0; X X status = inorder(mp->m_line, mp->m_char, curline, curchar); X if (status == -1) X return; X X if (status) X (void) DoYank(mp->m_line, mp->m_char, curline, curchar, X nl, 0, (Buffer *) 0); X else X (void) DoYank(curline, curchar, mp->m_line, mp->m_char, X nl, 0, (Buffer *) 0); X} X XDelWtSpace() X{ X register char *ep = &linebuf[curchar], X *sp = &linebuf[curchar]; X X while (*ep == ' ' || *ep == '\t') X ep++; X while (sp > linebuf && *(sp - 1) == ' ' || *(sp - 1) == '\t') X sp--; X if (sp != ep) { X curchar = sp - linebuf; X DFixMarks(curline, curchar, curline, curchar + (ep - sp)); X strcpy(sp, ep); X makedirty(curline); X modify(); X } X} X XDelBlnkLines() X{ X register Mark *dot; X int all; X X exp = 1; X if (!blnkp(&linebuf[curchar])) X return; X dot = MakeMark(curline, curchar, FLOATER); X all = !blnkp(linebuf); X while (blnkp(linebuf) && curline->l_prev) X SetLine(curline->l_prev); X all |= (firstp(curline)); X Eol(); X DelWtSpace(); X line_move(FORWARD, NO); X while (blnkp(linebuf) && !eobp()) { X DelWtSpace(); X DelNChar(); X } X if (!all && !eobp()) X OpenLine(); X ToMark(dot); X DelMark(dot); X} X XDelNWord() X{ X dword(1); X} X XDelPWord() X{ X dword(0); X} X Xdword(forward) X{ X Bufpos savedot; X X DOTsave(&savedot); X forward ? ForWord() : BackWord(); X reg_kill(savedot.p_line, savedot.p_char, 1); X} @//E*O*F delete.c// if test 6395 -ne "`wc -c <'delete.c'`"; then echo shar: error transmitting "'delete.c'" '(should have been 6395 characters)' fi fi # end of overwriting check echo shar: extracting "'disp.c'" '(24166 characters)' if test -f 'disp.c' ; then echo shar: will not over-write existing file "'disp.c'" else sed 's/^X//' >disp.c <<'@//E*O*F disp.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 "ctype.h" X#include "termcap.h" X X#include <varargs.h> X#include <signal.h> X#include <sys/stat.h> X X/* Kludge windows gets called by the routines that delete lines from the X buffer. If the w->w_line or w->w_top are deleted and this procedure X is not called, the redisplay routine will barf. */ X XChkWindows(line1, line2) XLine *line1; Xregister Line *line2; X{ X register Window *w = fwind; X register Line *lp; X X do { X for (lp = line1->l_next; lp != line2->l_next; lp = lp->l_next) { X if (lp == w->w_top) X w->w_flags |= W_TOPGONE; X if (lp == w->w_line) X w->w_flags |= W_CURGONE; X } X w = w->w_next; X } while (w != fwind); X} X Xextern int RingBell; X Xredisplay() X{ X register Window *w = fwind; X int lineno, X done_ID = 0, X i; X register struct scrimage *des_p, X *phys_p; X X curwind->w_line = curwind->w_bufp->b_dot; X curwind->w_char = curwind->w_bufp->b_char; X X if (InputPending = charp()) X return; X X#ifdef JOB_CONTROL X if (UpdFreq) X sighold(SIGALRM); X#endif X if (RingBell) { X dobell(1); X RingBell = 0; X } X if (UpdMesg) X DrawMesg(YES); X X for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) { X UpdWindow(w, lineno); X lineno += w->w_height; X } X X des_p = DesiredScreen; X phys_p = PhysScreen; X for (i = 0; i < ILI; i++, des_p++, phys_p++) { X if (!done_ID && (des_p->s_id != phys_p->s_id)) { X DoIDline(i); X done_ID++; X } X if ((des_p->s_flags & (DIRTY | L_MOD)) || X (des_p->s_id != phys_p->s_id) || X (des_p->s_vln != phys_p->s_vln) || X (des_p->s_offset != phys_p->s_offset)) X UpdLine(i); X if (InputPending) X goto ret; X } X X UpdModLine = 0; X X if (Asking) { X Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, Asking))); X /* Nice kludge */ X flusho(); X } else X GotoDot(); Xret: X#ifdef JOB_CONTROL X if (UpdFreq) X sigrelse(SIGALRM); X#else X ; /* yuck */ X#endif X X} X Xdobell(n) X{ X while (--n >= 0) { X if (VisBell && VB) X putstr(VB); X else X#ifdef SYSV /* release 2, at least */ X putpad("$<20>\007", 1) ; X#else X putpad("20\007", 1); X#endif SYSV X } X flusho(); X} X X/* find_pos() returns the position on the line, that c_char represents X in line. */ X Xfind_pos(line, c_char) XLine *line; X{ X return calc_pos(lcontents(line), c_char); X} X Xcalc_pos(lp, c_char) Xregister char *lp; Xregister int c_char; X{ X register int pos = 0; X register int c; X X while ((--c_char >= 0) && ((c = *lp++) & 0177) != 0) { X if (c == '\t') X pos += (tabstop - (pos % tabstop)); X else if (isctrl(c)) X pos += 2; X else X pos++; X } X return pos; X} X Xint UpdModLine = 0, X UpdMesg = 0, X CanScroll = 0; X XDoIDline(start) X{ X register struct scrimage *des_p = &DesiredScreen[start]; X struct scrimage *phys_p = &PhysScreen[start]; X register int i, X j; X X /* Some changes have been made. Try for insert or delete lines. X If either case has happened, Addlines and/or DelLines will do X necessary scrolling, also CONVERTING PhysScreen to account for the X physical changes. The comparison continues from where the X insertion/deletion takes place; this doesn't happen very often, X usually it happens with more than one window with the same X buffer. */ X X if (!CanScroll) X return; /* We should never have been called! */ X X for (i = start; i < ILI; i++, des_p++, phys_p++) X if (des_p->s_id != phys_p->s_id) X break; X X for (; i < ILI; i++) { X for (j = i + 1; j < ILI; j++) { X des_p = &DesiredScreen[j]; X phys_p = &PhysScreen[j]; X if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id) X break; X if (des_p->s_id == PhysScreen[i].s_id) { X if (des_p->s_id == 0) X continue; X if (AddLines(i, j - i)) { X DoIDline(j); X return; X } X break; X } X if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) { X if (des_p->s_id == 0) X continue; X if (DelLines(i, j - i)) { X DoIDline(i); X return; X } X break; X } X } X } X} X X/* Make DesiredScreen reflect what the screen should look like when we are done X with the redisplay. This deals with horizontal scrolling. Also makes X sure the current line of the Window is in the window. */ X XUpdWindow(w, start) Xregister Window *w; X{ X Line *lp; X int i, X DotIsHere = 0, X upper, /* Top of window */ X lower, /* Bottom of window */ X ntries = 0; /* # of tries at updating window. */ X register struct scrimage *des_p, X *phys_p; X Buffer *bp = w->w_bufp; X Xretry: X if (w->w_flags & W_CURGONE) { X w->w_line = bp->b_dot; X w->w_char = bp->b_char; X } X if (w->w_flags & W_TOPGONE) X CentWind(w); /* Reset topline of screen */ X w->w_flags &= ~(W_CURGONE|W_TOPGONE); X for (i = w->w_height, lp = w->w_top; --i > 0 && lp != 0; lp = lp->l_next) X if (lp == w->w_line) X break; X if (i == 0 || lp == 0) { /* current line not in window */ X ntries++; X if (ntries == 1) { X CalcWind(w); X goto retry; X } else if (ntries == 2) { X w->w_top = w->w_line = w->w_bufp->b_first; X printf("\rERROR in redisplay: I got hopelessly lost!"); X dobell(2); X goto retry; X } else if (ntries == 3) { X printf("\n\rOops, still lost, quitting ...\r\n"); X finish(1); X } X } X X upper = start; X lower = upper + w->w_height - 1; /* Don't include modeline */ X des_p = &DesiredScreen[upper]; X phys_p = &PhysScreen[upper]; X for (i = upper, lp = w->w_top; lp != 0 && i < lower; i++, des_p++, phys_p++, lp = lp->l_next) { X des_p->s_window = w; X des_p->s_lp = lp; X des_p->s_id = lp->l_dline & ~DIRTY; X des_p->s_flags = isdirty(lp) ? L_MOD : 0; X if (w->w_flags & W_NUMLINES) X des_p->s_vln = w->w_topnum + (i - upper); X else X des_p->s_vln = 0; X X if (lp == w->w_line) { X int diff = (w->w_flags & W_NUMLINES) ? 8 : 0, X strt_col = phys_p->s_offset, X end_col = strt_col + (CO - 2) - diff; X X /* Right now we are displaying from strt_col to X end_col of the buffer line. These are PRINT X colums, not actual characters. */ X w->w_dotline = i; X w->w_dotcol = find_pos(lp, w->w_char); X /* if the new dotcol is out of range, reselect X a horizontal window */ X if (w->w_dotcol < strt_col || w->w_dotcol >= end_col) { X if (w->w_dotcol < ((CO - 2) - diff)) X strt_col = 0; X else X strt_col = w->w_dotcol - (CO / 2); X } X w->w_dotcol += diff; X des_p->s_offset = strt_col; X DotIsHere++; X } else X des_p->s_offset = 0; X } X if (!DotIsHere) { X f_mess("DotNotHere is impossible!"); X finish(1); X } X X /* Is structure assignment faster than copy each field seperately */ X if (i < lower) { X static struct scrimage dirty_plate = { 0, DIRTY, 0, 0, 0, 0 }, X clean_plate = { 0, 0, 0, 0, 0, 0 }; X X for (; i < lower; i++, des_p++, phys_p++) X if (phys_p->s_id != 0) X *des_p = dirty_plate; X else X *des_p = clean_plate; X } X X des_p->s_window = w; X des_p->s_flags = 0; X if (((des_p->s_id = (int) w->w_bufp) != phys_p->s_id) || UpdModLine) X des_p->s_flags = MODELINE | DIRTY; X} X X/* Write whatever is in mesgbuf (maybe we are Asking, or just printed X a message). Turns off the UpdateMesg line flag. */ X XDrawMesg(abortable) X{ X if (charp()) X return; X i_set(ILI, 0); X if (swrite(mesgbuf, NIL, abortable)) { X cl_eol(); X UpdMesg = 0; X } X flusho(); X} X X/* Goto the current position in the current window. Presumably redisplay() X has already been called, and curwind->{w_dotline,w_dotcol} have been set X correctly. */ X XGotoDot() X{ X if (InputPending) X return; X Placur(curwind->w_dotline, curwind->w_dotcol - X PhysScreen[curwind->w_dotline].s_offset); X flusho(); X} X Xprivate XUntilEqual(start) Xregister int start; X{ X register struct scrimage *des_p = &DesiredScreen[start], X *phys_p = &PhysScreen[start]; X X while ((start < ILI) && (des_p->s_id != phys_p->s_id)) { X des_p++; X phys_p++; X start++; X } X X return start; X} X X/* Calls the routine to do the physical changes, and changes PhysScreen to X reflect those changes. */ X XAddLines(at, num) Xregister int at, X num; X{ X register int i; X int bottom = UntilEqual(at + num); X X if (num == 0 || num >= ((bottom - 1) - at)) X return 0; /* We did nothing */ X v_ins_line(num, at, bottom - 1); X X /* Now change PhysScreen to account for the physical change. */ X X for (i = bottom - 1; i - num >= at; i--) X PhysScreen[i] = PhysScreen[i - num]; X for (i = 0; i < num; i++) X PhysScreen[at + i].s_id = 0; X return 1; /* We did something. */ X} X XDelLines(at, num) Xregister int at, X num; X{ X register int i; X int bottom = UntilEqual(at + num); X X if (num == 0 || num >= ((bottom - 1) - at)) X return 0; X v_del_line(num, at, bottom - 1); X X for (i = at; num + i < bottom; i++) X PhysScreen[i] = PhysScreen[num + i]; X for (i = bottom - num; i < bottom; i++) X PhysScreen[i].s_id = 0; X return 1; X} X X/* Update line linenum in window w. Only set PhysScreen to DesiredScreen X if the swrite or cl_eol works, that is nothing is interupted by X characters typed. */ X XUpdLine(linenum) Xregister int linenum; X{ X register struct scrimage *des_p = &DesiredScreen[linenum]; X register Window *w = des_p->s_window; X X i_set(linenum, 0); X if (des_p->s_flags & MODELINE) X ModeLine(w); X else if (des_p->s_id) { X des_p->s_lp->l_dline &= ~DIRTY; X des_p->s_flags &= ~(DIRTY | L_MOD); X#ifdef ID_CHAR X if (!UseIC && (w->w_flags & W_NUMLINES)) X#else X if (w->w_flags & W_NUMLINES) X#endif X (void) swrite(sprint("%6d ", des_p->s_vln), NIL, YES); X X#ifdef ID_CHAR X if (UseIC) { X char outbuf[256], X *lptr; X int fromcol = (w->w_flags & W_NUMLINES) ? 8 : 0; X X if (w->w_flags & W_NUMLINES) X sprintf(outbuf, "%6d ", des_p->s_vln); X lptr = lcontents(des_p->s_lp); X DeTab(des_p->s_offset, lptr, outbuf + fromcol, X (sizeof outbuf) - 1 - fromcol, X des_p->s_window->w_flags & W_VISSPACE); X if (IDchar(outbuf, linenum, 0)) X PhysScreen[linenum] = *des_p; X else if (i_set(linenum, 0), swrite(outbuf, NIL, YES)) X do_cl_eol(linenum); X else X PhysScreen[linenum].s_id = -1; X } else X#endif ID_CHAR X if (BufSwrite(linenum)) X do_cl_eol(linenum); X else X PhysScreen[linenum].s_id = -1; X } else if (PhysScreen[linenum].s_id) /* Not the same ... make sure */ X do_cl_eol(linenum); X} X Xdo_cl_eol(linenum) Xregister int linenum; X{ X cl_eol(); X PhysScreen[linenum] = DesiredScreen[linenum]; X} X X#ifdef ID_CHAR X X/* From here to the end of the file is code that tries to utilize the X insert/delete character feature on some terminals. It is very confusing X and not so well written code, AND there is a lot of it. You may want X to use the space for something else. */ X Xextern struct screenline *Screen; Xint IN_INSmode = 0; X Xint UseIC; X Xint DClen, X MDClen, X IClen, X MIClen, X IMlen, X CElen; X Xdisp_opt_init() X{ X DClen = DC ? strlen(DC) : 0; X MDClen = M_DC ? strlen(M_DC) : 9999; X IClen = IC ? strlen(IC) : 0; X MIClen = M_IC ? strlen(M_IC) : 9999; X IMlen = IM ? strlen(IM) : 0; X CElen = CE ? strlen(CE) : 0; X X UseIC = (IC || IM || M_IC); X} X XINSmode(on) X{ X if (on && !IN_INSmode) { X putpad(IM, 1); X IN_INSmode++; X } else if (!on && IN_INSmode) { X putpad(EI, 1); X IN_INSmode = 0; X } X} X Xprivate XDeTab(s_offset, buf, outbuf, limit, visspace) Xregister char *buf; Xchar *outbuf; X{ X register char *phys_p = outbuf, X c; X register int pos = 0; X char *limitp = &outbuf[limit]; X X#define OkayOut(ch) if ((pos++ >= s_offset) && (phys_p < limitp))\ X *phys_p++ = ch;\ X else X X while (c = *buf++) { X if (c == '\t') { X int nchars = (tabstop - (pos % tabstop)); X X if (visspace) { X OkayOut('>'); X --nchars; X } X while (--nchars >= 0) X OkayOut(' '); X X } else if (isctrl(c)) { X OkayOut('^'); X OkayOut(c == 0177 ? '?' : c + '@'); X } else { X if (visspace && c == ' ') X c = '_'; X OkayOut(c); X } X if (pos - s_offset >= CO) { X phys_p = &outbuf[CO - 1]; X *phys_p++ = '!'; X break; X } X } X *phys_p = 0; X} X X/* ID character routines full of special cases and other fun stuff like that. X It actually works though ... X X Returns Non-Zero if you are finished (no differences left). */ X Xprivate XIDchar(new, lineno, col) Xregister char *new; X{ X register int i; X int j, X oldlen, X NumSaved; X register struct screenline *sline = &Screen[lineno]; X X oldlen = sline->s_length - sline->s_line; X X for (i = col; i < oldlen && new[i] != 0; i++) X if (sline->s_line[i] != new[i]) X break; X if (new[i] == 0 || i == oldlen) X return (new[i] == 0 && i == oldlen); X X for (j = i + 1; j < oldlen && new[j]; j++) { X if (new[j] == sline->s_line[i]) { X NumSaved = IDcomp(new + j, sline->s_line + i, X strlen(new)) + NumSimilar(new + i, X sline->s_line + i, j - i); X if (OkayInsert(NumSaved, j - i)) { X InsChar(lineno, i, j - i, new); X return(IDchar(new, lineno, j)); X } X } X } X X for (j = i + 1; j < oldlen && new[i]; j++) { X if (new[i] == sline->s_line[j]) { X NumSaved = IDcomp(new + i, sline->s_line + j, X oldlen - j); X if (OkayDelete(NumSaved, j - i, new[oldlen] == 0)) { X DelChar(lineno, i, j - i); X return(IDchar(new, lineno, j)); X } X } X } X return 0; X} X Xprivate XNumSimilar(s, t, n) Xregister char *s, X *t; X{ X register int num = 0; X X while (n--) X if (*s++ == *t++) X num++; X return num; X} X Xprivate XIDcomp(s, t, len) Xregister char *s, X *t; X{ X register int i; X int num = 0, X nonspace = 0; X char c; X X for (i = 0; i < len; i++) { X if ((c = *s++) != *t++) X break; X if (c != ' ') X nonspace++; X if (nonspace) X num++; X } X X return num; X} X Xprivate XOkayDelete(Saved, num, samelength) X{ X /* If the old and the new are the same length, then we don't X * have to clear to end of line. We take that into consideration. X */ X return ((Saved + (!samelength ? CElen : 0)) X > min(MDClen, DClen * num)); X} X Xprivate XOkayInsert(Saved, num) X{ X register int n = 0; X X if (IC) /* Per character prefixes */ X n = min(num * IClen, MIClen); X X if (IM && !IN_INSmode) { X /* Good terminal. Fewer characters in this case */ X n += IMlen; X } X X n += num; /* The characters themselves */ X X return Saved > n; X} X Xextern int CapCol; Xextern char *cursend; Xextern struct screenline *Curline; X Xprivate XDelChar(lineno, col, num) X{ X register char *from, X *to; X register int i; X struct screenline *sp = (&Screen[lineno]); X X Placur(lineno, col); X if (M_DC && num > 1) { X char minibuf[16]; X X sprintf(minibuf, M_DC, num); X putpad(minibuf, num); X } else { X for (i = num; --i >= 0; ) X putpad(DC, 1); X } X X to = sp->s_line + col; X from = to + num; X X byte_copy(from, to, sp->s_length - from + 1); X clrline(sp->s_length - num, sp->s_length); X sp->s_length -= num; X} X Xprivate XInsChar(lineno, col, num, new) Xchar *new; X{ X register char *sp1, X *sp2, /* To push over the array. */ X *sp3; /* Last character to push over. */ X int i; X X i_set(lineno, 0); X sp2 = Curline->s_length + num; X X if (sp2 >= cursend) { X i_set(lineno, CO - num - 1); X cl_eol(); X sp2 = cursend - 1; X } X Curline->s_length = sp2; X sp1 = sp2 - num; X sp3 = Curline->s_line + col; X X while (sp1 >= sp3) X *sp2-- = *sp1--; X X new += col; X byte_copy(new, sp3, num); X /* The internal screen is correct, and now we have to do X the physical stuff. */ X X Placur(lineno, col); X if (IM) { X if (!IN_INSmode) X INSmode(1); X } else if (M_IC && num > 1) { X char minibuf[16]; X X sprintf(minibuf, M_IC, num); X putpad(minibuf, num); X } else if (IC) { X for (i = 0; i < num; i++) X putpad(IC, 1); X } X for (i = 0; i < num; i++) { X putchar(new[i]); X if (IN_INSmode) X putpad(IP, 1); X } X CapCol += num; X} X X#endif ID_CHAR X X/* chkmail() returns nonzero if there is new mail since the X last time we checked. */ X Xchar Mailbox[128]; /* initialized in main */ Xint MailInt = 60; /* check no more often than 60 seconds */ X#ifdef BIFF Xint BiffChk = NO; /* whether or not to turn off biff while in JOVE */ X#endif X Xchkmail(force) X{ X time_t now; X static time_t last_chk = 0; X static int value = FALSE; X static off_t last_size = 0; X struct stat stbuf; X int last_val; X extern time_t time0; X X time(&now); X if (!force && (now < last_chk + MailInt)) X return value; X if (stat(Mailbox, &stbuf) < 0) X return FALSE; X last_val = value; X value = ((stbuf.st_mtime > time0) && X (stbuf.st_size > 0) && X (stbuf.st_size > last_size) && X (stbuf.st_mtime + 5 > stbuf.st_atime)); X last_chk = now; X last_size = stbuf.st_size; X if (value == TRUE && value != last_val) X dobell(3); X return value; X} X X/* Print the mode line. */ X Xprivate char *mode_p, X *mend_p; Xint BriteMode = 1; /* modeline should standout */ X Xprivate Xmode_app(str) Xregister char *str; X{ X if (mode_p >= mend_p) X return; X while ((mode_p < mend_p) && (*mode_p++ = *str++)) X ; X mode_p--; /* back over the null */ X} X Xchar ModeFmt[120] = "%3c %[%sJOVE (%M) Buffer: %b \"%f\" %]%s%m*- %((%t)%s%)%e"; X XModeLine(w) Xregister Window *w; X{ X extern int i_line; X int n, X ign_some = 0; X char line[132], X *fmt = ModeFmt, X tmp[16], X fillc, X c; X register Buffer *thisbuf = w->w_bufp; X register Buffer *bp; X X mode_p = line; X mend_p = &line[(sizeof line) - 1]; X X if (BriteMode != 0 && SO == 0) X BriteMode = 0; X fillc = BriteMode ? ' ' : '-'; X X while (c = *fmt++) { X if (c != '%') { X if (c == '\\') X if ((c = *fmt++) == '\0') X break; X if (!ign_some) X *mode_p++ = c; X continue; X } X if ((c = *fmt++) == '\0') /* char after the '%' */ X break; X if (ign_some && c != ')') X continue; X n = 1; X if (c >= '0' && c <= '9') { X n = 0; X while (c >= '0' && c <= '9') { X n = n * 10 + (c - '0'); X c = *fmt++; X } X } X switch (c) { X case '(': X if (w->w_next != fwind) /* Not bottom window. */ X ign_some++; X break; X X case ')': X ign_some = 0; X break; X X case 'c': X while (--n >= 0) X *mode_p++ = fillc; X break; X X case '[': X case ']': X { X char *strs = (c == '[') ? "[[[[[[[[[[" : "]]]]]]]]]]"; X X mode_app(strs + 10 - RecDepth); X break; X } X X case 's': X if (mode_p[-1] == ' ') X continue; X *mode_p++ = ' '; X break; X X case 'M': X { X static char *mmodes[] = { X "Fundamental ", X "Text ", X "C ", X#ifdef LISP X "Lisp ", X#endif X 0 X }; X X mode_app(mmodes[thisbuf->b_major]); X X if (BufMinorMode(thisbuf, Fill)) X mode_app("Fill "); X if (BufMinorMode(thisbuf, Abbrev)) X mode_app("Abbrev "); X if (BufMinorMode(thisbuf, OverWrite)) X mode_app("OvrWt "); X if (BufMinorMode(thisbuf, Indent)) X mode_app("AI "); X if (KeyMacro.m_flags & DEFINE) X mode_app("Def "); X mode_p--; /* Back over the extra space. */ X break; X } X X case 'b': X mode_app(thisbuf->b_name); X break; X X case 'f': X case 'F': X if (thisbuf->b_fname == 0) X mode_app("[No file]"); X else { X if (c == 'f') X mode_app(pr_name(thisbuf->b_fname)); X else X mode_app(basename(thisbuf->b_fname)); X } X break; X X X case 'n': X for (bp = world, n = 1; bp != 0; bp = bp->b_next, n++) X if (bp == thisbuf) X break; X X sprintf(tmp, "%d", n); X mode_app(tmp); X break; X X case 'm': X if (IsModified(w->w_bufp)) X *mode_p++ = fmt[0]; X else X *mode_p++ = fmt[1]; X fmt += 2; /* skip two characters */ X break; X X case 't': X { X char timestr[12]; X X mode_app(get_time((time_t *) 0, timestr, 11, 16)); X break; X } X X#ifdef LOAD_AV X case 'l': X { X double theavg; X char minibuf[10]; X X get_la(&theavg); X theavg += .005; /* round to nearest .01 */ X sprintf(minibuf, "%d.%02d", X (int) theavg, X (int)((theavg - (int) theavg) * 100)); X mode_app(minibuf); X } X break; X#endif X X case 'C': /* check mail here */ X if (chkmail(NO)) X mode_app("[New mail]"); X break; X X#ifdef CHDIR X case 'd': /* print working directory */ X mode_app(pr_name(pwd())); X break; X#endif X X case 'e': X { X /* 2 space pad pluss padding for magic cookies */ X char *last_p = &line[CO - 2 - (2 * SG)]; X X while (mode_p < last_p) X *mode_p++ = fillc; X X goto outahere; /* %e means we're done! */ X } X } X } X Xoutahere: X *mode_p = 0; X X /* Highlight mode line. */ X if (BriteMode) { X#ifdef ID_CHAR X if (IN_INSmode) X INSmode(0); X#endif X putpad(SO, 1); X } X if (swrite(line, BriteMode, YES)) X do_cl_eol(i_line); X if (BriteMode) X putpad(SE, 1); X} X XRedrawDisplay() X{ X Line *newtop = prev_line((curwind->w_line = curline), exp_p ? X exp : HALF(curwind)); X X if (newtop == curwind->w_top) X v_clear(FLine(curwind), FLine(curwind) + SIZE(curwind)); X else X SetTop(curwind, newtop); X} X Xv_clear(line1, line2) Xregister int line1; X{ X register struct scrimage *phys_p, *des_p; X X phys_p = &PhysScreen[line1]; X des_p = &DesiredScreen[line1]; X X while (line1 <= line2) { X i_set(line1++, 0); X cl_eol(); X phys_p->s_id = des_p->s_id = 0; X phys_p++, des_p++; X } X} X XClAndRedraw() X{ X cl_scr(1); X} X XNextPage() X{ X Line *newline; X X if (Asking) X return; X if (exp < 0) { X exp = -exp; X PrevPage(); X return; X } X if (exp_p == YES) X UpScroll(); X else { X if (in_window(curwind, curwind->w_bufp->b_last) != -1) { X rbell(); X return; X } X newline = next_line(curwind->w_top, max(1, SIZE(curwind) - 1)); X SetTop(curwind, curwind->w_line = newline); X if (curwind->w_bufp == curbuf) X SetLine(newline); X } X} X XPrevPage() X{ X Line *newline; X X if (Asking) X return; X if (exp < 0) { X exp = -exp; X NextPage(); X return; X } X if (exp_p == YES) X DownScroll(); X else { X newline = prev_line(curwind->w_top, max(1, SIZE(curwind) - 1)); X SetTop(curwind, curwind->w_line = newline); X if (curwind->w_bufp == curbuf) X SetLine(newline); X } X} X XUpScroll() X{ X SetTop(curwind, next_line(curwind->w_top, exp)); X if ((curwind->w_bufp == curbuf) && X (in_window(curwind, curline) == -1)) X SetLine(curwind->w_top); X} X XDownScroll() X{ X SetTop(curwind, prev_line(curwind->w_top, exp)); X if ((curwind->w_bufp == curbuf) && X (in_window(curwind, curline) == -1)) X SetLine(curwind->w_top); X} X Xint VisBell = 0, X RingBell = 0; /* So if we have a lot of errors ... X ring the bell only ONCE */ Xrbell() X{ X RingBell++; X} X X/* Message prints the null terminated string onto the bottom line of the X terminal. */ X Xmessage(str) Xchar *str; X{ X if (InJoverc) X return; X UpdMesg++; X errormsg = 0; X if (str != mesgbuf) X null_ncpy(mesgbuf, str, (sizeof mesgbuf) - 1); X} X X/* End of Window */ X XEow() X{ X if (Asking) X return; X SetLine(next_line(curwind->w_top, SIZE(curwind) - 1 - X min(SIZE(curwind) - 1, exp - 1))); X if (exp_p == NO) X Eol(); X} X X/* Beginning of Window */ X XBow() X{ X if (Asking) X return; X SetLine(next_line(curwind->w_top, min(SIZE(curwind) - 1, exp - 1))); X} X Xprivate int LineNo, X last_col, X DoAutoNL; Xprivate Window *old_wind; /* save the window we were in BEFORE X before we were called, if UseBuffers X is nonzero */ X Xint UseBuffers = FALSE; Xint TOabort = 0; X X/* This initializes the typeout. If send-typeout-to-buffers is set X the buffer NAME is created (emptied if it already exists) and output X goes to the buffer. Otherwise output is drawn on the screen and X erased by TOstop() */ X XTOstart(name, auto_newline) Xchar *name; X{ X if (UseBuffers) { X old_wind = curwind; X pop_wind(name, YES, B_SCRATCH); X } X TOabort = LineNo = last_col = 0; X DoAutoNL = auto_newline; X} X X/* VARARGS1 */ X XTypeout(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X if (TOabort) X return; X X if (!UseBuffers && (LineNo == ILI - 1)) { X register int c; X X LineNo = 0; X last_col = 0; X f_mess("--more--"); X if ((c = getchar()) != ' ') { X TOabort++; X if (c != CTL(G) && c != RUBOUT) X Ungetc(c); X return; X } X f_mess(NullStr); X } X X if (fmt) { X extern int i_col; X char string[132]; X va_list ap; X X va_start(ap); X format(string, sizeof string, fmt, ap); X va_end(ap); X if (UseBuffers) X ins_str(string, NO); X else { X i_set(LineNo, last_col); X (void) swrite(string, NIL, YES); X last_col = i_col; X } X } X if (!UseBuffers) { X PhysScreen[LineNo].s_id = -1; X if (fmt == 0 || DoAutoNL != 0) { X cl_eol(); X flusho(); X LineNo++; X last_col = 0; X } X } else if (fmt == 0 || DoAutoNL != 0) X ins_str("\n", NO); X} X XTOstop() X{ X int c; X X if (UseBuffers) { X ToFirst(); X SetWind(old_wind); X } else { X if (TOabort) X return; X if (last_col != 0) X Typeout((char *) 0); X Typeout("----------"); X cl_eol(); X flusho(); X c = getchar(); X if (c != ' ') X Ungetc(c); X } X} @//E*O*F disp.c// if test 24166 -ne "`wc -c <'disp.c'`"; then echo shar: error transmitting "'disp.c'" '(should have been 24166 characters)' fi fi # end of overwriting check echo shar: extracting "'fmt.c'" '(4845 characters)' if test -f 'fmt.c' ; then echo shar: will not over-write existing file "'fmt.c'" else sed 's/^X//' >fmt.c <<'@//E*O*F fmt.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 "termcap.h" X X#include <varargs.h> X Xchar mesgbuf[MESG_SIZE]; X X/* VARARGS2 */ X Xformat(buf, len, fmt, ap) Xchar *buf, X *fmt; Xva_list ap; X{ X File strbuf, X *sp = &strbuf; X X sp->f_ptr = sp->f_base = buf; X sp->f_fd = -1; /* Not legit for files */ X sp->f_cnt = len; X sp->f_flags = F_STRING; X sp->f_bufsize = len; X X doformat(sp, fmt, ap); X putc('\0', sp); X} X Xstatic char padc = ' '; Xstatic File *curiop = 0; X Xstatic XPPchar(c, str) Xint c; Xchar *str; X{ X char *cp = str; X X if (c == '\033') X strcpy(cp, "ESC"); X else if (c < ' ') X sprintf(cp, "C-%c", c + '@'); X else if (c == '\177') X strcpy(cp, "^?"); X else X sprintf(cp, "%c", c); X} X Xstatic Xputld(leftadj, width, d, base) Xlong d; X{ X int length = 1; X long tmpd = d; X X while (tmpd = (tmpd / base)) X length++; X if (d < 0) X length++; X if (!leftadj) X pad(padc, width - length); X if (d < 0) { X putc('-', curiop); X d = -d; X } X outld(d, base); X if (leftadj) X pad(padc, width - length); X} X Xstatic Xoutld(d, base) Xlong d; X{ X long n; X X if (n = (d / base)) X outld(n, base); X putc((int) ('0' + (int) (d % base)), curiop); X} X Xstatic Xputs(leftadj, width, str) Xchar *str; X{ X int length; X register char *cp, X c; X X if (str == 0) X#if pyr X str = ""; X#else X str = "(null)"; X#endif X length = strlen(str); X cp = str; X if (!leftadj) X pad(' ', width - length); X while (c = *cp++) X putc(c, curiop); X if (leftadj) X pad(' ', width - length); X} X Xstatic Xpad(c, amount) Xregister int c, X amount; X{ X while (--amount >= 0) X putc(c, curiop); X} X Xstatic Xdoformat(sp, fmt, ap) Xregister File *sp; Xregister char *fmt; Xva_list ap; X{ X register char c; X int leftadj, X width; X File *pushiop = curiop; X X curiop = sp; X X while (c = *fmt++) { X if (c != '%') { X putc(c, sp); X continue; X } X X padc = ' '; X leftadj = width = 0; X c = *fmt++; X if (c == '-') { X leftadj++; X c = *fmt++; X } X if (c == '0') { X padc = '0'; X c = *fmt++; X } X while (c >= '0' && c <= '9') { X width = width * 10 + (c - '0'); X c = *fmt++; X } X if (c == '*') { X width = va_arg(ap, int); X c = *fmt++; X } X reswitch: X /* At this point, fmt points at one past the format letter. */ X switch (c) { X case '%': X putc('%', curiop); X break; X X case 'D': X putld(leftadj, width, va_arg(ap, long), 10); X break; X X case 'b': X { X Buffer *b = va_arg(ap, Buffer *); X X puts(leftadj, width, b->b_name); X break; X } X X case 'c': X putc(va_arg(ap, int), curiop); X break; X X case 'd': X putld(leftadj, width, (long) va_arg(ap, int), 10); X break; X X case 'f': /* current command name gets inserted here! */ X puts(leftadj, width, LastCmd->Name); X break; X X case 'l': X c = Upper(*++fmt); X goto reswitch; X X case 'n': X if (va_arg(ap, int) != 1) X puts(leftadj, width, "s"); X break; X X case 'o': X putld(leftadj, width, (long) va_arg(ap, int), 8); X break; X X case 'p': X { X char cbuf[20]; X X PPchar(va_arg(ap, int), cbuf); X puts(leftadj, width, cbuf); X break; X } X X case 's': X puts(leftadj, width, va_arg(ap, char *)); X break; X X default: X complain("Unknown format directive: \"%%%c\"", c); X } X } X curiop = pushiop; X} X X/* VARARGS1 */ X Xchar * Xsprint(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X va_list ap; X static char line[100]; X X va_start(ap); X format(line, sizeof line, fmt, ap); X va_end(ap); X return line; X} X X/* VARARGS1 */ X Xprintf(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X va_list ap; X X va_start(ap); X doformat(stdout, fmt, ap); X va_end(ap); X} X X/* VARARGS1 */ X Xfprintf(fp, fmt, va_alist) XFile *fp; Xchar *fmt; Xva_dcl X{ X va_list ap; X X va_start(ap); X doformat(fp, fmt, ap); X va_end(ap); X} X X/* VARARGS2 */ X Xsprintf(str, fmt, va_alist) Xchar *str, X *fmt; Xva_dcl X{ X va_list ap; X X va_start(ap); X format(str, 130, fmt, ap); X va_end(ap); X} X X/* VARARGS1 */ X Xs_mess(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X va_list ap; X X if (InJoverc) X return; X va_start(ap); X format(mesgbuf, sizeof mesgbuf, fmt, ap); X va_end(ap); X message(mesgbuf); X} X X/* VARARGS1 */ X Xf_mess(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X va_list ap; X X va_start(ap); X format(mesgbuf, sizeof mesgbuf, fmt, ap); X va_end(ap); X DrawMesg(NO); X UpdMesg++; /* Still needs updating (for convenience) */ X} X X/* VARARGS1 */ X Xadd_mess(fmt, va_alist) Xchar *fmt; Xva_dcl X{ X int mesg_len = strlen(mesgbuf); X va_list ap; X X if (InJoverc) X return; X va_start(ap); X format(&mesgbuf[mesg_len], (sizeof mesgbuf) - mesg_len, fmt, ap); X va_end(ap); X message(mesgbuf); X} @//E*O*F fmt.c// if test 4845 -ne "`wc -c <'fmt.c'`"; then echo shar: error transmitting "'fmt.c'" '(should have been 4845 characters)' fi fi # end of overwriting check echo shar: extracting "'re.h'" '(856 characters)' if test -f 're.h' ; then echo shar: will not over-write existing file "'re.h'" else sed 's/^X//' >re.h <<'@//E*O*F re.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#define NALTS 10 /* number of alternate search strings */ X Xextern char searchstr[128], X compbuf[128], /* 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 Xextern int REdirection, X REeom, X REbom, X REalt_num; @//E*O*F re.h// if test 856 -ne "`wc -c <'re.h'`"; then echo shar: error transmitting "'re.h'" '(should have been 856 characters)' fi fi # end of overwriting check echo shar: extracting "'rec.h'" '(699 characters)' if test -f 'rec.h' ; then echo shar: will not over-write existing file "'rec.h'" else sed 's/^X//' >rec.h <<'@//E*O*F rec.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 Xstruct rec_head { X int Uid, /* Uid of owner. */ X Pid; /* Pid of jove process. */ X time_t UpdTime; /* Last time this was updated. */ X int Nbuffers; /* Number of buffers. */ X}; X Xstruct rec_entry { X char r_bname[128], X r_fname[128]; X int r_nlines; X}; X @//E*O*F rec.h// if test 699 -ne "`wc -c <'rec.h'`"; then echo shar: error transmitting "'rec.h'" '(should have been 699 characters)' fi fi # end of overwriting check echo shar: extracting "'doc/cmds.doc.nr'" '(238 characters)' if test -f 'doc/cmds.doc.nr' ; then echo shar: will not over-write existing file "'doc/cmds.doc.nr'" else sed 's/^X//' >doc/cmds.doc.nr <<'@//E*O*F doc/cmds.doc.nr//' X.de bp X.. X.de NH X.. X.de IQ X"\\$1" X.. X.de dc X.sp 1 X:entry "\\$1" X.if '\\$2'(variable)' "Variable" X.if !'\\$2'(variable)' "Command" X.br X.. X.de ID X.sp 1 X.in +5 X.. X.de DE X.fi X.sp 1 X.in -5 X.. X.de DS X.nf X.sp 1 X.in +5 X.. X.de UX XUNIX\c X.. X.ll 7i @//E*O*F doc/cmds.doc.nr// if test 238 -ne "`wc -c <'doc/cmds.doc.nr'`"; then echo shar: error transmitting "'doc/cmds.doc.nr'" '(should have been 238 characters)' fi fi # end of overwriting check echo shar: "End of archive 2 (of 13)." cp /dev/null ark2isdone 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