sources-request@mirror.UUCP (02/04/87)
Submitted by: seismo!rochester!jpayne (Jonathan Payne) Mod.sources: Volume 8, Issue 25 Archive-name: jove/Part06 #! /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 6 (of 13)." # Contents: misc.c move.c paragraph.c portsrv.c proc.c re1.c table.h PATH=/bin:/usr/bin:/usr/ucb; export PATH echo shar: extracting "'misc.c'" '(7568 characters)' if test -f 'misc.c' ; then echo shar: will not over-write existing file "'misc.c'" else sed 's/^X//' >misc.c <<'@//E*O*F misc.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 <signal.h> X#ifdef ANSICODES X#include "termcap.h" X#endif X XDigit() X{ X GetExp(LastKeyStruck); X} X XDigit0() X{ X GetExp('0'); X} X XDigit1() X{ X GetExp('1'); X} X XDigit2() X{ X GetExp('2'); X} X XDigit3() X{ X GetExp('3'); X} X XDigit4() X{ X GetExp('4'); X} X XDigit5() X{ X GetExp('5'); X} X XDigit6() X{ X GetExp('6'); X} X XDigit7() X{ X GetExp('7'); X} X XDigit8() X{ X GetExp('8'); X} X XDigit9() X{ X GetExp('9'); X} X XprCTIME() X{ X s_mess(": %f %s", get_time((time_t *) 0, (char *) 0, 0, -1)); X} X Xextern int alarmed; X XFourTime() X{ X int oldc = LastKeyStruck, X newc; X int nexp; X X alarmed = 0; X exp_p = YES; X this_cmd = ARG_CMD; X do { X if ((nexp = exp * 4) != 0) X exp = nexp; X if (!alarmed) X newc = waitchar(); X else X newc = getch(); X if (alarmed) X message(key_strokes); X } while (newc == oldc); X Ungetc(newc); X} X Xint exp_p, X exp; X XGetExp(c) X{ X int sign = 0; X static int digited; X X if (!isdigit(c) && c != '-') X complain((char *) 0); X if (exp_p == NO) { /* if we just got here */ X exp = 0; /* start over */ X digited = NO; X } else if (exp_p == YES_NODIGIT) { X sign = (exp < 0) ? -1 : 1; X exp = 0; X } X X if (!sign) X sign = (exp < 0) ? -1 : 1; X if (sign == -1) X exp = -exp; X if (c == '-') { X sign = -sign; X goto goread; X } X for (;;) { X if (alarmed) X message(key_strokes); X if (isdigit(c)) { X exp = (exp * 10) + (c - '0'); X digited++; X } else { X if (digited) X exp_p = YES; X else { X exp = 1; X if (exp_p == NO) X exp_p = YES_NODIGIT; X } X exp *= sign; X this_cmd = ARG_CMD; X Ungetc(c); X return; X } Xgoread: if (!alarmed) X c = waitchar(); X else { X add_mess(NullStr); X c = getch(); X } X } X} X XChrToOct() X{ X int c; X X c = waitchar(); X if (alarmed) X message(key_strokes); X ins_str(sprint("\\%03o", c), NO); X} X XStrLength() X{ X static char inquotes[] = "Where are the quotes?"; X char *first = StrIndex(-1, linebuf, curchar, '"'), X *last = StrIndex(1, linebuf, curchar + 1, '"'), X c; X int numchars = 0; X X if (first == 0 || last == 0) X complain(inquotes); X first++; X while (first < last) { X c = *first++; X if (c == '\\') { X int num; X X if (!isdigit(*first)) X ++first; X else { X num = 3; X while (num-- && isdigit(*first++) && first < last) X ; X } X } X numchars++; X } X s_mess("%d characters", numchars); X} X X/* Transpos cur_char with cur_char - 1 */ X XTransChar() X{ X char before; X X if (curchar == 0 || (eolp() && curchar == 1)) X complain((char *) 0); /* BEEP */ X exp = 1; X if (eolp()) X BackChar(); X before = linebuf[curchar - 1]; X DelPChar(); X ForChar(); X Insert(before); X} X X/* Switch current line with previous one */ X XTransLines() X{ X disk_line old_prev; X X if (firstp(curline)) X return; X exp = 1; X lsave(); X old_prev = curline->l_prev->l_dline; X curline->l_prev->l_dline = curline->l_dline; X curline->l_dline = old_prev; X getDOT(); X if (!lastp(curline)) X line_move(FORWARD, NO); X modify(); X} X XLeave() X{ X longjmp(mainjmp, QUIT); X} X X/* If argument is specified, kill that many lines down. Otherwise, X if we "appear" to be at the end of a line, i.e. everything to the X right of the cursor is white space, we delete the line separator X as if we were at the end of the line. */ X XKillEOL() X{ X Line *line2; X int char2; X X if (exp_p) { X if (exp == 0) { /* Kill to beginning of line */ X line2 = curline; X char2 = 0; X } else { X line2 = next_line(curline, exp); X if ((LineDist(curline, line2) < exp) || (line2 == curline)) X char2 = length(line2); X else X char2 = 0; X } X } else if (blnkp(&linebuf[curchar])) { X line2 = next_line(curline, 1); X if (line2 == curline) X char2 = length(curline); X else X char2 = 0; X } else { X line2 = curline; X char2 = length(curline); X } X reg_kill(line2, char2, 0); X} X X/* Kill to beginning of sentence */ X XKillBos() X{ X exp = -exp; X KillEos(); X} X X/* Kill to end of sentence */ X XKillEos() X{ X Line *line1; X int char1; X X line1 = curline; X char1 = curchar; X Eos(); X reg_kill(line1, char1, 1); X} X XKillExpr() X{ X Line *line1; X int char1; X X line1 = curline; X char1 = curchar; X FSexpr(); X reg_kill(line1, char1, 1); X} X XEscPrefix() X{ X HandlePref(pref1map); X} X XCtlxPrefix() X{ X HandlePref(pref2map); X} X XMiscPrefix() X{ X HandlePref(miscmap); X} X XHandlePref(map) Xdata_obj **map; X{ X register data_obj *cp; X register int c; X X c = waitchar(); X if (c == CTL(G)) { X message("[Aborted]"); X rbell(); X return; X } X X if (alarmed) X message(key_strokes); X X cp = map[c]; X if (cp == 0) { X s_mess("[%sunbound]", key_strokes); X rbell(); X } else X ExecCmd(cp); X} X XYank() X{ X Line *line, X *lp; X Bufpos *dot; X X if (killbuf[killptr] == 0) X complain("[Nothing to yank!]"); X lsave(); X this_cmd = YANKCMD; X line = killbuf[killptr]; X lp = lastline(line); X dot = DoYank(line, 0, lp, length(lp), curline, curchar, curbuf); X SetMark(); X SetDot(dot); X} X XWtModBuf() X{ X if (!ModBufs(NO)) X message("[No buffers need saving]"); X else X put_bufs(exp_p); X} X Xput_bufs(askp) X{ X register Buffer *oldb = curbuf, X *b; X X for (b = world; b != 0; b = b->b_next) { X if (!IsModified(b) || b->b_type != B_FILE) X continue; X SetBuf(b); /* Make this current Buffer */ X if (curbuf->b_fname == 0) { X char *newname; X X newname = ask(NullStr, "Buffer \"%s\" needs a file name; type Return to skip: ", b->b_name); X if (*newname == 0) X continue; X setfname(b, newname); X } X if (askp && (yes_or_no_p("Write %s? ", curbuf->b_fname) == NO)) X continue; X filemunge(curbuf->b_fname); X chk_mtime(curbuf, curbuf->b_fname, "save"); X file_write(curbuf->b_fname, 0); X unmodify(); X } X SetBuf(oldb); X} X XToIndent() X{ X register char *cp, X c; X X for (cp = linebuf; c = *cp; cp++) X if (c != ' ' && c != '\t') X break; X curchar = cp - linebuf; X} X XGoLine() X{ X Line *newline; X X#ifndef ANSICODES X if (exp_p == NO) X return; X#else X if (exp_p == NO || exp <= 0) { X if (SP) X putpad(SP, 1); /* Ask for cursor position */ X return; X } X#endif X newline = next_line(curbuf->b_first, exp - 1); X PushPntp(newline); X SetLine(newline); X} X X#ifdef ANSICODES XMoveToCursor(line, col) X{ X register struct scrimage *sp = &PhysScreen[line]; X X while (sp->s_id == NULL) X sp = &PhysScreen[--line]; X if (sp->s_flags & MODELINE) X complain((char *) 0); X if (curwind != sp->s_window) X SetWind(sp->s_window); X SetLine(sp->s_lp); X curchar = how_far(sp->s_lp, col); X} X XAnsiCodes() X{ X int c; X int num1 = 0; X int num2; X static char *unsupported = "[Unsupported ANSI code received]"; X X while (isdigit(c = getch())) X num1 = (num1*10) + (c - '0'); X X switch (c) { X case ';': X num2 = 0; X while (isdigit(c = getch())) X num2 = (num2*10) + (c - '0'); X switch (c) { X case 'R': X MoveToCursor(--num1, --num2); X break; X case 'H': X Eow(); Bol(); X break; X default: X complain(unsupported); X } X break; X case 'A': X line_move(BACKWARD, YES); X break; X case 'B': X line_move(FORWARD, YES); X break; X case 'C': X ForChar(); X break; X case 'D': X BackChar(); X break; X case 'H': X Bow(); X break; X case 'J': X if (num1 == 2) { X ClAndRedraw(); X break; X } X /* FALL THROUGH */ X default: X complain(unsupported); X } X} X#endif ANSICODES X XNotModified() X{ X unmodify(); X} X XSetLMargin() X{ X LMargin = calc_pos(linebuf, curchar); X} X XSetRMargin() X{ X RMargin = calc_pos(linebuf, curchar); X} @//E*O*F misc.c// if test 7568 -ne "`wc -c <'misc.c'`"; then echo shar: error transmitting "'misc.c'" '(should have been 7568 characters)' fi fi # end of overwriting check echo shar: extracting "'move.c'" '(4397 characters)' if test -f 'move.c' ; then echo shar: will not over-write existing file "'move.c'" else sed 's/^X//' >move.c <<'@//E*O*F move.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 Xstatic int line_pos; X XForChar() X{ X register int num = exp; X X if (exp < 0) { X exp = -exp; X BackChar(); X return; X } X exp = 1; X while (--num >= 0) { X if (eolp()) { /* Go to the next Line */ X if (curline->l_next == 0) X break; X SetLine(curline->l_next); X } else X curchar++; X } X} X XBackChar() X{ X register int num = exp; X X if (exp < 0) { X exp = -exp; X ForChar(); X return; X } X exp = 1; X while (--num >= 0) { X if (bolp()) { X if (curline->l_prev == 0) X break; X SetLine(curline->l_prev); X Eol(); X } else X --curchar; X } X} X XNextLine() X{ X if ((curline == curbuf->b_last) && eolp()) X complain(NullStr); X line_move(FORWARD, YES); X} X XPrevLine() X{ X if ((curline == curbuf->b_first) && bolp()) X complain(NullStr); X line_move(BACKWARD, YES); X} X X/* moves to a different line in DIR; LINE_CMD says whether this is X being called from NextLine() or PrevLine(), in which case it tries X to line up the column with the column of the current line */ X Xline_move(dir, line_cmd) X{ X Line *(*proc)() = (dir == FORWARD) ? next_line : prev_line; X Line *line; X X line = (*proc)(curline, exp); X if (line == curline) { X (dir == FORWARD) ? Eol() : Bol(); X return; X } X X if (line_cmd) { X this_cmd = LINECMD; X if (last_cmd != LINECMD) X line_pos = calc_pos(linebuf, curchar); X } X SetLine(line); /* curline is in linebuf now */ X if (line_cmd) X curchar = how_far(curline, line_pos); X} X X/* returns what cur_char should be for that position col */ X Xhow_far(line, col) XLine *line; X{ X register char *lp; X register int pos, X c; X char *base; X X base = lp = lcontents(line); X pos = 0; X X while (pos < col && (c = (*lp & 0177))) { X if (c == '\t') X pos += (tabstop - (pos % tabstop)); X else if (isctrl(c)) X pos += 2; X else X pos++; X lp++; X } X X return lp - base; X} X XBol() X{ X curchar = 0; X} X XEol() X{ X curchar = strlen(linebuf); X} X XEof() X{ X PushPntp(curbuf->b_last); X ToLast(); X} X XBof() X{ X PushPntp(curbuf->b_first); X ToFirst(); X} X X/* Move forward (if dir > 0) or backward (if dir < 0) a sentence. Deals X with all the kludgery involved with paragraphs, and moving backwards X is particularly yucky. */ X Xto_sent(dir) X{ X Bufpos *new, X old; X extern char *ParaStr; X X DOTsave(&old); X X new = dosearch("^[ \t]*$\\|[?.!]", dir, 1); X if (new == 0) { X (dir < 0) ? ToFirst() : ToLast(); X return; X } X SetDot(new); X if (dir < 0) { X to_word(1); X if ((old.p_line == curline && old.p_char <= curchar) || X (inorder(new->p_line, new->p_char, old.p_line, old.p_char) && X inorder(old.p_line, old.p_char, curline, curchar))) { X SetDot(new); X to_sent(dir); X } X return; /* We're there? */ X } X if (blnkp(linebuf)) { X Bol(); X BackChar(); X if (old.p_line == curline && old.p_char >= curchar) { X to_word(1); /* Oh brother this is painful */ X to_sent(1); X } X } else { X extern int REbom; X X curchar = REbom + 1; /* Just after the [?.!] */ X if (LookingAt("[\")] *\\|[\")]$", linebuf, curchar)) X curchar++; X else if (!eolp() && !LookingAt(" *", linebuf, curchar)) X to_sent(dir); X } X} X XBos() X{ X int num = exp; X X if (exp < 0) { X exp = -exp; X Eos(); X return; X } X X exp = 1; X X while (--num >= 0) { X to_sent(-1); X if (bobp()) X break; X } X} X XEos() X{ X int num = exp; X X if (exp < 0) { X exp = -exp; X Bos(); X return; X } X X exp = 1; X X while (--num >= 0) { X to_sent(1); X if (eobp()) X break; X } X} X XForWord() X{ X register char c; X register int num = exp; X X if (exp < 0) { X exp = -exp; X BackWord(); X return; X } X exp = 1; X while (--num >= 0) { X to_word(1); X while ((c = linebuf[curchar]) != 0 && isword(c)) X curchar++; X if (eobp()) X break; X } X this_cmd = 0; /* Semi kludge to stop some unfavorable behavior */ X} X XBackWord() X{ X register int num = exp; X register char c; X X if (exp < 0) { X exp = -exp; X ForWord(); X return; X } X exp = 1; X while (--num >= 0) { X to_word(-1); X while (!bolp() && (c = linebuf[curchar - 1], isword(c))) X --curchar; X if (bobp()) X break; X } X this_cmd = 0; X} @//E*O*F move.c// if test 4397 -ne "`wc -c <'move.c'`"; then echo shar: error transmitting "'move.c'" '(should have been 4397 characters)' fi fi # end of overwriting check echo shar: extracting "'paragraph.c'" '(13888 characters)' if test -f 'paragraph.c' ; then echo shar: will not over-write existing file "'paragraph.c'" else sed 's/^X//' >paragraph.c <<'@//E*O*F paragraph.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 X/* Thanks to Brian Harvey for this paragraph boundery finding algorithm. X It's really quite hairy figuring it out. This deals with paragraphs that X are seperated by blank lines, lines beginning with a Period (assumed to X be an nroff command), lines beginning with BackSlash (assumed to be Tex X commands). Also handles paragraphs that are separated by lines of X different indent; and it deals with outdented paragraphs, too. It's X really quite nice. Here's Brian's algorithm. X X Definitions: X X THIS means the line containing the cursor. X PREV means the line above THIS. X NEXT means the line below THIS. X X BLANK means empty, empty except for spaces and tabs, starts with a period X or a backslash, or nonexistent (because the edge of the buffer is X reached). ((BH 12/24/85 A line starting with backslash is blank only if X the following line also starts with backslash. This is so that \noindent X is part of a paragraph, but long strings of TeX commands don't get X rearranged. It still isn't perfect but it's better.)) X X BSBLANK means BLANK or starts with a backslash. (BH 12/24/85) X X HEAD means the first (nonblank) line of the paragraph containing THIS. X BODY means all other (nonblank) lines of the paragraph. X TAIL means the last (nb) line of the paragraph. (TAIL is part of BODY.) X X HEAD INDENT means the indentation of HEAD. M-J should preserve this. X BODY INDENT means the indentation of BODY. Ditto. X X Subprocedures: X X TAILRULE(BODYLINE) X If BODYLINE is BLANK, the paragraph has only one line, and there is no X BODY and therefore no TAIL. Return. Otherwise, starting from BODYLINE, X move down until you find a line that either is BSBLANK or has a different X indentation from BODYLINE. The line above that different line is TAIL. X Return. X X Rules: X X 1. If THIS is BLANK, which command are you doing? If M-J or M-[, then go X up to the first non-BLANK line and start over. (If there is no non-BLANK X line before THIS, ring the bell.) If M-], then the first non-BLANK line X below THIS is HEAD, and the second consecutive non-BSBLANK line (if any) is X the beginning of BODY. (If there is no non-BLANK line after THIS, ring X the bell.) Do TAILRULE(beginning-of-BODY). Go to rule A. X X 2. If PREV is BLANK or THIS is BSBLANK, then THIS is HEAD, and NEXT (if X not BSBLANK) is in BODY. Do TAILRULE(NEXT). Go to rule A. X X 3. If NEXT is BSBLANK, then THIS is TAIL, therefore part of BODY. Go to X rule 5 to find HEAD. X X 4. If either NEXT or PREV has the same indentation as THIS, then THIS is X part of BODY. Do TAILRULE(THIS). Go to rule 5 to find HEAD. Otherwise, X go to rule 6. X X 5. Go up until you find a line that is either BSBLANK or has a different X indentation from THIS. If that line is BLANK, the line below it is HEAD. X If that line is non-BLANK, then call that new line THIS for what follows. X If (the new) PREV has the same indent as THIS, then (the new) NEXT is X HEAD. If PREV has a different indent from THIS, then THIS is HEAD. Go to X rule A. X X 6. If you got here, then both NEXT and PREV are nonblank and are X differently indented from THIS. This is a tricky case and there is no X guarantee that you're going to win. The most straightforward thing to do X is assume that we are not using hanging indentation. In that case: X whichever of PREV and THIS is indented further is HEAD. Do X TAILRULE(HEAD+1). Go to rule A. X X 6+. A more complicated variant would be this: if THIS is indented further X than PREV, we are using regular indentation and rule 6 applies. If PREV X is indented further than THIS, look at both NEXT and the line after NEXT. X If those two lines are indented equally, and more than THIS, then we are X using hanging indent, THIS is HEAD, and NEXT is the first line of BODY. X Do TAILRULE(NEXT). Otherwise, rule 6 applies. X X A. You now know where HEAD and TAIL are. The indentation of HEAD is HEAD X INDENT; the indentation of TAIL is BODY INDENT. X X B. If you are trying to M-J, you are now ready to do it. X X C. If you are trying to M-], leave point after the newline that ends X TAIL. In other words, leave the cursor at the beginning of the line X after TAIL. It is not possible for this to leave point where it started X unless it was already at the end of the buffer. X X D. If you are trying to M-[, if the line before HEAD is not BLANK, then X leave point just before HEAD. That is, leave the cursor at the beginning X of HEAD. If the line before HEAD is BLANK, then leave the cursor at the X beginning of that line. If the cursor didn't move, go up to the first X earlier non-BLANK line and start over. X X X End of Algorithm. I implemented rule 6+ because it seemed nicer. */ X Xint RMargin = 78, X LMargin = 0; XLine *para_head, X *para_tail; Xint head_indent, X body_indent; Xstatic int use_lmargin; X X/* some defines for paragraph boundery checking */ X#define I_EMPTY -1 /* line "looks" empty (spaces and tabs) */ X#define I_PERIOD -2 /* line begins with "." or "\" */ X#define I_BUFEDGE -3 /* line is nonexistent (edge of buffer) */ X Xstatic int bslash; /* Nonzero if get_indent finds line starting X with backslash */ X Xi_bsblank(lp) XLine *lp; X{ X if (i_blank(lp)) X return 1; X return bslash; X} X Xi_blank(lp) XLine *lp; X{ X return (get_indent(lp) < 0); X} X Xstatic Xget_indent(lp) Xregister Line *lp; X{ X Bufpos save; X register int indent; X X bslash = 0; X if (lp == 0) X return I_BUFEDGE; X DOTsave(&save); X SetLine(lp); X if (blnkp(linebuf)) X indent = I_EMPTY; X else if (linebuf[0] == '.') X indent = I_PERIOD; X else if (linebuf[0] == '\\') { X /* BH 12/24/85. Backslash is BLANK only if next line X also starts with Backslash. */ X bslash++; X SetLine(lp->l_next); X if (linebuf[0] == '\\') X indent = I_PERIOD; X else X indent = 0; X } else { X ToIndent(); X indent = calc_pos(linebuf, curchar); X } X SetDot(&save); X X return indent; X} X Xstatic Line * Xtailrule(lp) Xregister Line *lp; X{ X int i; X X i = get_indent(lp); X if (i < 0) X return lp; /* one line paragraph */ X do { X if ((get_indent(lp->l_next) != i) || bslash) X /* BH line with backslash is head of next para */ X break; X } while ((lp = lp->l_next) != 0); X if (lp == 0) X complain((char *) 0); X return lp; X} X X/* Finds the beginning, end and indent of the current paragraph, and sets X the above global variables. HOW says how to behave when we're between X paragraphs. That is, it's either FORWARD or BACKWARD depending on which X way we're favoring. */ X Xfind_para(how) X{ X Line *this, X *prev, X *next, X *head = 0, X *body = 0, X *tail = 0; X int this_indent; X Bufpos orig; /* remember where we were when we started */ X X exp = 1; X DOTsave(&orig); Xstrt: X this = curline; X prev = curline->l_prev; X next = curline->l_next; X this_indent = get_indent(this); X X if (i_blank(this)) { /* rule 1 */ X if (how == BACKWARD) { X while (i_blank(curline)) X if (firstp(curline)) X complain((char *) 0); X else X line_move(BACKWARD, NO); X goto strt; X } else { X while (i_blank(curline)) X if (lastp(curline)) X complain((char *) 0); X else X line_move(FORWARD, NO); X head = curline; X next = curline->l_next; X if (!i_bsblank(next)) X body = next; X else X body = head; X } X } else if (i_bsblank(this) || i_blank(prev)) { /* rule 2 */ X head = this; X if (!i_bsblank(next)) X body = next; X } else if (i_bsblank(next)) { /* rule 3 */ X tail = this; X body = this; X } else if ((get_indent(next) == this_indent) || /* rule 4 */ X (get_indent(prev) == this_indent)) X body = this; X else { /* rule 6+ */ X if (get_indent(prev) > this_indent) { X /* hanging indent maybe? */ X if ((next != 0) && X (get_indent(next) == get_indent(next->l_next))) { X head = this; X body = next; X } X } X /* Now we handle hanging indent else and the other X case of this_indent > get_indent(prev). That is, X if we didn't resolve HEAD in the above if, then X we are not a hanging indent. */ X if (head == 0) { /* still don't know */ X if (this_indent > get_indent(prev)) X head = this; X else X head = prev; X body = head->l_next; X } X } X /* rule 5 -- find the missing parts */ X if (head == 0) { /* haven't found head of paragraph so do so now */ X Line *lp; X int i; X X lp = this; X do { X i = get_indent(lp->l_prev); X if (i < 0) /* is blank */ X head = lp; X else if (i != this_indent || bslash) { X Line *this = lp->l_prev; X X if (get_indent(this->l_prev) == i) X head = this->l_next; X else X head = this; X } X } while (head == 0 && (lp = lp->l_prev) != 0); X if (lp == 0) X complain((char *) 0); X } X if (body == 0) /* this must be a one line paragraph */ X body = head; X if (tail == 0) X tail = tailrule(body); X if (tail == 0 || head == 0 || body == 0) X complain("BUG! tail(%d),head(%d),body(%d)!", tail, head, body); X para_head = head; X para_tail = tail; X head_indent = get_indent(head); X body_indent = get_indent(body); X X SetDot(&orig); X} X XJustify() X{ X use_lmargin = (exp_p != NO); X find_para(BACKWARD); X DoJustify(para_head, 0, para_tail, length(para_tail), NO, X use_lmargin ? LMargin : body_indent); X} X XLine * Xmax_line(l1, l2) XLine *l1, X *l2; X{ X if (inorder(l1, 0, l2, 0)) X return l2; X return l1; X} X XLine * Xmin_line(l1, l2) XLine *l1, X *l2; X{ X if (inorder(l1, 0, l2, 0)) X return l1; X return l2; X} X XRegJustify() X{ X Mark *mp = CurMark(), X *tailmark; X Line *l1 = curline, X *l2 = mp->m_line; X int c1 = curchar, X c2 = mp->m_char; X Line *rl1, X *rl2; X X use_lmargin = (exp_p != NO); X (void) fixorder(&l1, &c1, &l2, &c2); X do { X DotTo(l1, c1); X find_para(FORWARD); X rl1 = max_line(l1, para_head); X rl2 = min_line(l2, para_tail); X tailmark = MakeMark(para_tail, 0, FLOATER); X DoJustify(rl1, (rl1 == l1) ? c1 : 0, rl2, X (rl2 == l2) ? c2 : length(rl2), X NO, use_lmargin ? LMargin : body_indent); X l1 = tailmark->m_line->l_next; X DelMark(tailmark); X c1 = 0; X } while (l1 != 0 && l2 != rl2); X} X Xdo_rfill() X{ X Mark *mp = CurMark(); X Line *l1 = curline, X *l2 = mp->m_line; X int c1 = curchar, X c2 = mp->m_char; X X use_lmargin = (exp_p != NO); X (void) fixorder(&l1, &c1, &l2, &c2); X DoJustify(l1, c1, l2, c2, NO, use_lmargin ? LMargin : 0); X} X Xdo_space() X{ X int c1 = curchar, X c2 = c1, X diff, X nspace; X char ch; X X while (c1 > 0 && ((ch = linebuf[c1 - 1]) == ' ' || ch == '\t')) X c1--; X while ((ch = linebuf[c2]) == ' ' || ch == '\t') X c2++; X diff = (c2 - c1); X curchar = c2; X X if (diff == 0) X return; X if (c1 > 0) { X int topunct = c1 - 1; X X nspace = 1; X if (diff >= 2) { X while (index("\")]", linebuf[topunct])) { X if (topunct == 0) X break; X topunct--; X } X if (index("?!.:", linebuf[topunct])) X nspace = 2; X } X } else X nspace = 0; X X if (diff > nspace) X DoTimes(DelPChar(), (diff - nspace)); X else if (diff < nspace) X DoTimes(Insert(' '), (nspace - diff)); X} X XDoJustify(l1, c1, l2, c2, scrunch, indent) XLine *l1, X *l2; X{ X int okay_char = -1; X char *cp; X Mark *savedot = MakeMark(curline, curchar, FLOATER), X *endmark; X X exp = 1; X (void) fixorder(&l1, &c1, &l2, &c2); /* l1/c1 will be before l2/c2 */ X DotTo(l1, c1); X if (get_indent(l1) >= c1) { X if (use_lmargin) { X n_indent(indent + (head_indent - body_indent)); X use_lmargin = 0; /* turn this off now */ X } X ToIndent(); X } X endmark = MakeMark(l2, c2, FLOATER); X X for (;;) { X cp = StrIndex(1, linebuf, curchar, ' '); X if (cp == 0) X Eol(); X else X curchar = (cp - linebuf); X if (curline == endmark->m_line && curchar >= endmark->m_char) X goto outahere; X if (eolp()) { X ins_str(" ", NO); X DelNChar(); /* delete line separator */ X curchar -= 2; /* back over the spaces */ X } X /* at this point we are ALWAYS sitting right after X a word - that is, just before some spaces or the X end of the line */ X if (calc_pos(linebuf, curchar) <= RMargin) { X okay_char = curchar; X do_space(); X continue; X } X X /* if we get here, we have done all we can for X this line - now we split the line, or just move X to the next one */ X if (okay_char > 0) X curchar = okay_char; X if (curline == endmark->m_line && curchar >= endmark->m_char) X goto outahere; X /* can't fit in small margin, so we do the best we can */ X if (eolp()) { X line_move(FORWARD, NO); X n_indent(indent); X } else { X /* insert a line break - line WAS too long */ X DelWtSpace(); X LineInsert(1); X if (scrunch && TwoBlank()) { X Eol(); X DelNChar(); X } X n_indent(indent); X } X } Xoutahere: X ToMark(savedot); /* Back to where we were */ X DelMark(endmark); /* Free up marks */ X DelMark(savedot); X this_cmd = last_cmd = 0; /* So everything is under control */ X f_mess(""); X} X Xextern Line *para_head, X *para_tail; X XDoPara(dir) X{ X register int num = exp, X first_time = TRUE; X X while (--num >= 0) { Xtryagain: find_para(dir); /* find paragraph bounderies */ X if ((dir == BACKWARD) && X ((!first_time) || ((para_head == curline) && bolp()))) { X if (bobp()) X complain((char *) 0); X BackChar(); X first_time = !first_time; X goto tryagain; X } X SetLine((dir == BACKWARD) ? para_head : para_tail); X if (dir == BACKWARD && !firstp(curline) && X i_blank(curline->l_prev)) X line_move(BACKWARD, NO); X else if (dir == FORWARD) { X if (lastp(curline)) { X Eol(); X break; X } X /* otherwise */ X line_move(FORWARD, NO); X } X } X} X XBackPara() X{ X DoPara(BACKWARD); X} X XForPara() X{ X DoPara(FORWARD); X} @//E*O*F paragraph.c// if test 13888 -ne "`wc -c <'paragraph.c'`"; then echo shar: error transmitting "'paragraph.c'" '(should have been 13888 characters)' fi fi # end of overwriting check echo shar: extracting "'portsrv.c'" '(3209 characters)' if test -f 'portsrv.c' ; then echo shar: will not over-write existing file "'portsrv.c'" else sed 's/^X//' >portsrv.c <<'@//E*O*F portsrv.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/* This is a server for jove sub processes. It runs the command and X signals jove when there is some output ready to send to jove. By the X time we get here, out standard output goes to jove's process input. */ X X#include "tune.h" X X#ifdef PIPEPROCS /* the whole file! */ X X#include "jove.h" X X#include <signal.h> X#include <sys/ioctl.h> X#ifdef BSD4_2 X# include <sys/wait.h> X#else X# include <wait.h> X#endif X Xstruct header { X int pid; X int nbytes; X char buf[512]; X} header; X X#define HEADSIZE ((sizeof header.pid) + sizeof (header.nbytes)) X Xerror(str) Xchar *str; X{ X header.pid = getpid(); X header.nbytes = strlen(str); X strcpy(header.buf, str); X proc_write(&header, header.nbytes + 8); X exit(-2); X} X Xint ppid, X InputFD, X JovesInput; X Xp_inform() X{ X long nbytes; X X ioctl(JovesInput, FIONREAD, (char *) &nbytes); X if (nbytes > 0) X kill(ppid, INPUT_SIG); X} X Xproc_write(ptr, n) Xchar *ptr; X{ X long nbytes; X X ioctl(1, FIONREAD, (char *) &nbytes); X X if (nbytes == 0) X kill(ppid, INPUT_SIG); X X (void) write(1, ptr, n); X alarm(1); X} X Xread_pipe() X{ X register int n; X X (void) signal(SIGALRM, p_inform); X X while ((header.nbytes = read(InputFD, header.buf, sizeof header.buf)) > 0) { X n = HEADSIZE + header.nbytes; X proc_write(&header, n); X } X} X X/* ARGSUSED */ Xmain(argc, argv) Xchar *argv[]; X{ X int p[2]; X int pid; X X if (pipe(p) == -1) X error("Cannot pipe jove portsrv.\n"); X X ppid = getppid(); X switch (pid = fork()) { X case -1: X error("portsrv: cannot fork.\n"); X X case 0: X /* We'll intercept childs output in p[0] */ X (void) dup2(p[1], 1); X (void) dup2(p[1], 2); X (void) close(p[0]); X (void) close(p[1]); X X (void) setpgrp(getpid(), getpid()); X execv(argv[2], &argv[3]); X _exit(-4); X X default: X (void) close(0); X /* Don't want this guy to read anything X jove sends to our soon to be created X child */ X X JovesInput = atoi(argv[1]); X (void) signal(SIGINT, SIG_IGN); X (void) signal(SIGQUIT, SIG_IGN); X (void) close(p[1]); X X /* Tell jove the pid of the real child as opposed to us. */ X header.pid = getpid(); X header.nbytes = sizeof (int); X *(int *) header.buf = pid; X (void) write(1, (char *) &header, sizeof pid + HEADSIZE); X p_inform(); /* Inform jove */ X X /* Read proc's output and send it to jove */ X InputFD = p[0]; X read_pipe(); X (void) close(p[0]); X header.pid = getpid(); X header.nbytes = EOF; /* Tell jove we are finished */ X (void) write(1, (char *) &header, HEADSIZE); X p_inform(); X /* Try to exit like our child did ... */ X { X union wait w; X X#ifndef VMUNIX X while (wait2(&w.w_status, 0) != pid) X#else X while (wait3(&w.w_status, 0, 0) != pid) X#endif X ; X if (WIFEXITED(w)) X exit(w.w_retcode); X else if (WIFSIGNALED(w)) X kill(getpid(), w.w_termsig); X } X } X} X X#else PIPEPROCS Xmain() X{ X} X#endif @//E*O*F portsrv.c// if test 3209 -ne "`wc -c <'portsrv.c'`"; then echo shar: error transmitting "'portsrv.c'" '(should have been 3209 characters)' fi fi # end of overwriting check echo shar: extracting "'proc.c'" '(14390 characters)' if test -f 'proc.c' ; then echo shar: will not over-write existing file "'proc.c'" else sed 's/^X//' >proc.c <<'@//E*O*F proc.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 <signal.h> X#include <varargs.h> X X/* This disgusting RE search string parses output from the GREP X family, from the pdp11 compiler, pcc, and lint. Jay (HACK) X Fenlasen changed this to work for the lint errors. */ Xprivate char X *errfmt = "^\\{\",\\}\\([^:\"( \t]*\\)\\{\"\\, line ,:,(\\} *\\([0-9][0-9]*\\)[:)]\ X\\|:: *\\([^(]*\\)(\\([0-9]*\\))$\ X\\|( \\([^(]*\\)(\\([0-9]*\\)) ),"; X Xstruct error { X Buffer *er_buf; /* Buffer error is in */ X Line *er_mess, /* Actual error message */ X *er_text; /* Actual error */ X int er_char; /* char pos of error */ X struct error *er_prev, /* List of errors */ X *er_next; X}; X Xstruct error *cur_error = 0, X *errorlist = 0; XBuffer *perr_buf = 0; /* Buffer with error messages */ X Xint WtOnMk = 1; /* Write the modified files when we make */ X X/* Add an error to the end of the list of errors. This is used for X parse-{C,LINT}-errors and for the spell-buffer command */ X Xprivate struct error * XAddError(laste, errline, buf, line, charpos) Xstruct error *laste; XLine *errline, X *line; XBuffer *buf; X{ X struct error *new = (struct error *) emalloc(sizeof *new); X X new->er_prev = laste; X if (laste) X laste->er_next = new; X else { X if (errorlist) /* Free up old errors */ X ErrFree(); X cur_error = errorlist = new; X } X laste = new; X new->er_next = 0; X new->er_buf = buf; X new->er_text = line; X new->er_char = charpos; X new->er_mess = errline; X X return new; X} X XParseAll() X{ X ErrParse(errfmt); X} X XXParse() X{ X char *sstr; X X sstr = ask(errfmt, ProcFmt); X ErrParse(sstr); X} X X/* Parse for {C,LINT} errors (or anything that matches fmtstr) in the X current buffer. Set up for the next-error command. This is neat X because this will work for any kind of output that prints a file X name and a line number on the same line. */ X XErrParse(fmtstr) Xchar *fmtstr; X{ X Bufpos *bp; X char fname[FILESIZE], X lineno[10], X REbuf[256], X *REalts[10]; X int lnum, X last_lnum = -1; X struct error *ep = 0; X Buffer *buf, X *lastb = 0; X Line *err_line; X X ErrFree(); /* This is important! */ X ToFirst(); X perr_buf = curbuf; X REcompile(fmtstr, 1, REbuf, REalts); X /* Find a line with a number on it. */ X while (bp = docompiled(FORWARD, REbuf, REalts)) { X SetDot(bp); X putmatch(1, fname, sizeof fname); X putmatch(2, lineno, sizeof lineno); X buf = do_find((Window *) 0, fname, 1); X if (buf != lastb) { X lastb = buf; X last_lnum = -1; /* signals new file */ X err_line = buf->b_first; X } X lnum = chr_to_int(lineno, 10, 0); X if (lnum == last_lnum) /* one error per line is nicer */ X continue; X if (last_lnum == -1) X last_lnum = 1; /* that's where we really are */ X err_line = next_line(err_line, lnum - last_lnum); X ep = AddError(ep, curline, buf, err_line, 0); X last_lnum = lnum; X } X if (cur_error != 0) X ShowErr(); X exp = 1; X} X X/* Free up all the errors */ X XErrFree() X{ X register struct error *ep; X X for (ep = errorlist; ep != 0; ep = ep->er_next) X free((char *) ep); X errorlist = cur_error = 0; X} X X/* Internal next error sets cur_error to the next error, taking the X argument count, supplied by the user, into consideration. */ X Xprivate char errbounds[] = "You're at the %s error.", X noerrs[] = "No errors!"; X Xprivate Xtoerror(forward) X{ X register int i; X register struct error *e = cur_error; X X if (e == 0) X complain(noerrs); X if ((forward && (e->er_next == 0)) || X (!forward && (e->er_prev == 0))) X complain(errbounds, forward ? "last" : "first"); X X for (i = 0; i < exp; i++) { X if ((e = forward ? e->er_next : e->er_prev) == 0) X break; X cur_error = e; X } X} X XNextError() X{ X ToError(1); X} X XPrevError() X{ X ToError(0); X} X Xprivate Xokay_error() X{ X return ((inlist(perr_buf->b_first, cur_error->er_mess)) && X (inlist(cur_error->er_buf->b_first, cur_error->er_text))); X} X X/* Go the the next error, if there is one. Put the error buffer in X one window and the buffer with the error in another window. X It checks to make sure that the error actually exists. */ X XToError(forward) X{ X do { X toerror(forward); X exp = 1; X } while (!okay_error()); X ShowErr(); X} X Xint EWSize = 20; /* percentage of screen the error window X should be */ X Xset_wsize(wsize) Xint wsize; X{ X wsize = (LI * wsize) / 100; X if (wsize >= 1 && !one_windp()) X WindSize(curwind, wsize - (curwind->w_height - 1)); X} X X/* Show the current error, i.e. put the line containing the error message X in one window, and the buffer containing the actual error in another X window. */ X XShowErr() X{ X Window *err_wind, X *buf_wind; X X if (cur_error == 0) X complain(noerrs); X if (!okay_error()) { X rbell(); X return; X } X err_wind = windbp(perr_buf); X buf_wind = windbp(cur_error->er_buf); X X if (err_wind && !buf_wind) { X SetWind(err_wind); X pop_wind(cur_error->er_buf->b_name, NO, -1); X buf_wind = curwind; X } else if (!err_wind && buf_wind) { X SetWind(buf_wind); X pop_wind(perr_buf->b_name, NO, -1); X err_wind = curwind; X } else if (!err_wind && !buf_wind) { X pop_wind(perr_buf->b_name, NO, -1); X err_wind = curwind; X pop_wind(cur_error->er_buf->b_name, NO, -1); X buf_wind = curwind; X } X X /* Put the current error message at the top of its Window */ X SetWind(err_wind); X SetLine(cur_error->er_mess); X SetTop(curwind, (curwind->w_line = cur_error->er_mess)); X set_wsize(EWSize); X X /* now go to the the line with the error in the other window */ X SetWind(buf_wind); X DotTo(cur_error->er_text, cur_error->er_char); X} X Xchar ShcomBuf[128] = {0}; X X/* Make a buffer name given the command `command', i.e. "fgrep -n foo *.c" X will return the buffer name "fgrep". */ X Xchar * XMakeName(command) Xchar *command; X{ X static char bufname[50]; X register char *cp = bufname, X c; X X while ((c = *command++) && (c == ' ' || c == '\t')) X ; X do X *cp++ = c; X while ((c = *command++) && (c != ' ' && c != '\t')); X *cp = 0; X strcpy(bufname, basename(bufname)); X X return bufname; X} X X/* Run make, first writing all the modified buffers (if the WtOnMk flag is X non-zero), parse the errors, and go the first error. */ X Xchar make_cmd[128] = "make"; X XMakeErrors() X{ X Window *old = curwind; X int status, X compilation; X X if (WtOnMk) X put_bufs(0); X /* When we're not doing make or cc (i.e., the last command X was probably a grep or something) and the user just types X C-X C-E, he probably (possibly, hopefully, usually (in my X case)) doesn't want to do the grep again but rather wants X to do a make again; so we ring the bell and insert the X default command and let the person decide. */ X X compilation = (sindex("make", make_cmd) || sindex("cc", make_cmd)); X if (exp_p || !compilation) { X if (!compilation) { X rbell(); X Inputp = make_cmd; /* insert the default for the X user */ X } X null_ncpy(make_cmd, ask(make_cmd, "Compilation command: "), X sizeof (make_cmd) - 1); X } X status = UnixToBuf(MakeName(make_cmd), YES, EWSize, YES, Shell, ShFlags, make_cmd, (char *) 0); X com_finish(status, make_cmd); X X ErrParse(errfmt); X X if (!cur_error) X SetWind(old); X} X X#ifdef SPELL X XSpelBuffer() X{ X char *Spell = "Spell", X com[100]; X Window *savewp = curwind; X X put_bufs(0); X sprintf(com, "spell %s", curbuf->b_fname); X (void) UnixToBuf(Spell, YES, EWSize, YES, Shell, ShFlags, com, (char *) 0); X message("[Delete the irrelevant words and then type C-X C-C]"); X Recur(); X SetWind(savewp); X SpelParse(Spell); X} X XSpelWords() X{ X char *buftospel; X Buffer *wordsb = curbuf; X X if ((buftospel = ask_buf((Buffer *) 0)) == 0) X return; X SetBuf(do_select(curwind, buftospel)); X SpelParse(wordsb->b_name); X} X XSpelParse(bname) Xchar *bname; X{ X Buffer *buftospel, X *wordsb; X char wordspel[100]; X Bufpos *bp; X struct error *ep = 0; X X ErrFree(); /* This is important! */ X X buftospel = curbuf; X wordsb = buf_exists(bname); X perr_buf = wordsb; /* This is important (buffer containing X error messages) */ X SetBuf(wordsb); X ToFirst(); X f_mess("Finding misspelled words ... "); X while (!lastp(curline)) { X sprintf(wordspel, "\\<%s\\>", linebuf); X SetBuf(buftospel); X ToFirst(); X while (bp = dosearch(wordspel, 1, 1)) { X SetDot(bp); X ep = AddError(ep, wordsb->b_dot, buftospel, X curline, curchar); X } X SetBuf(wordsb); X line_move(FORWARD, NO); X } X add_mess("Done."); X SetBuf(buftospel); X ShowErr(); X} X X#endif SPELL X XShToBuf() X{ X char bufname[100]; X X strcpy(bufname, ask((char *) 0, "Buffer: ")); X DoShell(bufname, ask(ShcomBuf, "Command: ")); X} X XShellCom() X{ X null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1); X DoShell(MakeName(ShcomBuf), ShcomBuf); X} X X/* Run the shell command into `bufname'. Empty the buffer except when we X give a numeric argument, in which case it inserts the output at the X current position in the buffer. */ X Xprivate XDoShell(bufname, command) Xchar *bufname, X *command; X{ X Window *savewp = curwind; X int status; X X exp = 1; X status = UnixToBuf(bufname, YES, 0, !exp_p, Shell, X ShFlags, command, (char *) 0); X com_finish(status, command); X SetWind(savewp); X} X Xprivate Xcom_finish(status, cmd) Xregister int status; Xchar *cmd; X{ X s_mess("[%s: ", cmd); X if (status == 0) X add_mess("completed successfully"); X else X add_mess("exited (%d)", status); X add_mess("]"); X} X Xdowait(pid, status) Xint pid, X *status; X{ X#ifndef IPROCS X X int rpid; X X while ((rpid = wait(status)) != pid) X ; X#else X X#ifdef BSD4_2 X# include <sys/wait.h> X#else X# include <wait.h> X#endif X X union wait w; X int rpid; X X for (;;) { X#ifndef VMUNIX X rpid = wait2(&w.w_status, 0); X#else X rpid = wait3(&w, 0, (struct rusage *) 0); X#endif X if (rpid == pid) { X if (status) X *status = w.w_status; X break; X } else X kill_off(rpid, w); X } X#endif IPROCS X} X X/* Run the command to bufname, erase the buffer if clobber is non-zero, X and redisplay if disp is non-zero. Leaves current buffer in `bufname' X and leaves any windows it creates lying around. It's up to the caller X to fix everything up after we're done. (Usually there's nothing to X fix up.) */ X X/* VARARGS5 */ X XUnixToBuf(bufname, disp, wsize, clobber, va_alist) Xchar *bufname; Xva_dcl X{ X int p[2], X pid, X eof, X status; X va_list ap; X char *argv[32], X *mess; X File *fp; X int (*old_int)(); X X va_start(ap); X make_argv(argv, ap); X va_end(ap); X if (clobber) X isprocbuf(bufname); X if (disp) { X message("Starting up..."); X pop_wind(bufname, clobber, clobber ? B_PROCESS : B_FILE); X set_wsize(wsize); X redisplay(); X } X /* Now I will attempt to describe how I deal with signals during X the execution of the shell command. My desire was to be able X to interrupt the shell command AS SOON AS the window pops up. X So, if we have JOB_CONTROL (i.e., the new signal mechanism) I X hold SIGINT, meaning if we interrupt now, we will eventually X see the interrupt, but not before we are ready for it. We X fork, the child releases the interrupt, it then sees the X interrupt, and so exits. Meanwhile the parent ignores the X signal, so if there was a pending one, it's now lost. X X With no JOB_CONTROL, the best behavior you can expect is, when X you type ^] too very quickly after the window pops up, it may X be ignored. The behavior BEFORE was that it would interrupt X JOVE and then you would have to continue JOVE and wait a X little while longer before trying again. Now that is fixed, X in that you just have to type it twice. */ X X#ifdef IPROCS X sighold(SIGCHLD); X#endif X#ifdef JOB_CONTROL X sighold(SIGINT); X#else X old_int = signal(SIGINT, SIG_IGN), X#endif X exp = 1; X dopipe(p); X pid = fork(); X if (pid == -1) { X pclose(p); X complain("[Fork failed]"); X } X if (pid == 0) { X#ifdef IPROCS X sigrelse(SIGCHLD); /* don't know if this matters */ X#endif IPROCS X (void) signal(SIGINT, SIG_DFL); X#ifdef JOB_CONTROL X sigrelse(SIGINT); X#endif X (void) close(0); X (void) open("/dev/null", 0); X (void) close(1); X (void) close(2); X (void) dup(p[1]); X (void) dup(p[1]); X pclose(p); X execv(argv[0], &argv[1]); X (void) write(1, "Execl failed.\n", 14); X _exit(1); X } X#ifdef JOB_CONTROL X old_int = signal(SIGINT, SIG_IGN); X#endif X (void) close(p[1]); X fp = fd_open(argv[1], F_READ, p[0], iobuff, LBSIZE); X do { X inIOread = 1; X eof = f_gets(fp, genbuf, LBSIZE); X inIOread = 0; X ins_str(genbuf, YES); X if (!eof) X LineInsert(1); X if (disp != 0 && fp->f_cnt <= 0) { X#ifdef LOAD_AV X { X double theavg; X X get_la(&theavg); X if (theavg < 2.0) X mess = "Screaming along..."; X else if (theavg < 5.0) X mess = "Chugging along..."; X else X mess = "Crawling along..."; X } X#else X mess = "Chugging along..."; X#endif LOAD_AV X message(mess); X redisplay(); X } X } while (!eof); X if (disp) X DrawMesg(NO); X close_file(fp); X dowait(pid, &status); X#ifdef JOB_CONTROL X (void) sigrelse(SIGINT); X#endif X (void) signal(SIGINT, old_int); X#ifdef IPROCS X sigrelse(SIGCHLD); X#endif X return status; X} X X#ifdef BSD4_2 X Xprivate int SigMask = 0; X Xsighold(sig) X{ X (void) sigblock(SigMask |= (1 << (sig - 1))); X} X Xsigrelse(sig) X{ X (void) sigsetmask(SigMask &= ~(1 << (sig - 1))); X} X X#endif X XFilterRegion() X{ X char *cmd = ask((char *) 0, ": %f (through command) ", ProcFmt); X X RegToUnix(curbuf, cmd); X} X X/* Send the current region to CMD and insert the output from the X command into OUT_BUF. */ X XRegToUnix(outbuf, cmd) XBuffer *outbuf; Xchar *cmd; X{ X Mark *m = CurMark(); X char *tname = mktemp("/tmp/jfilterXXXXXX"), X combuf[130]; X Window *save_wind = curwind; X int status; X File *fp; X X CATCH X fp = open_file(tname, iobuff, F_WRITE, COMPLAIN, QUIET); X putreg(fp, m->m_line, m->m_char, curline, curchar, YES); X DelReg(); X sprintf(combuf, "%s < %s", cmd, tname); X status = UnixToBuf(outbuf->b_name, NO, 0, outbuf->b_type == B_SCRATCH, X Shell, ShFlags, combuf, (char *) 0); X ONERROR X ; /* Do nothing ... but fall through and delete the tmp X file. */ X ENDCATCH X f_close(fp); X (void) unlink(tname); X SetWind(save_wind); X com_finish(status, combuf); X} X Xisprocbuf(bufname) Xchar *bufname; X{ X Buffer *bp; X X if ((bp = buf_exists(bufname)) != 0 && bp->b_type != B_PROCESS) X confirm("Over-write buffer %s?", bufname); X} @//E*O*F proc.c// if test 14390 -ne "`wc -c <'proc.c'`"; then echo shar: error transmitting "'proc.c'" '(should have been 14390 characters)' fi fi # end of overwriting check echo shar: extracting "'re1.c'" '(9617 characters)' if test -f 're1.c' ; then echo shar: will not over-write existing file "'re1.c'" else sed 's/^X//' >re1.c <<'@//E*O*F re1.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 "re.h" X Xstatic Xsubstitute(query, l1, char1, l2, char2) XLine *l1, X *l2; X{ X Line *lp; X int numdone = 0, X offset = curchar, X stop = 0; X disk_line UNDO_da = 0; X Line *UNDO_lp = 0; X X lsave(); X REdirection = FORWARD; X X lp = l1; X for (lp = l1; (lp != l2->l_next) && !stop; lp = lp->l_next) { X offset = (lp == l1) ? char1 : 0; X while (!stop && re_lindex(lp, offset, compbuf, alternates, 0)) { X if (lp == l2 && REeom > char2) /* nope, leave this alone */ X break; X DotTo(lp, REeom); X offset = curchar; X if (query) { X message("Replace (Type '?' for help)? "); Xreswitch: redisplay(); X switch (Upper(getchar())) { X case '.': X stop++; X /* Fall into ... */ X X case ' ': X case 'Y': X break; X X case BS: X case RUBOUT: X case 'N': X if (linebuf[offset++] == '\0') X goto nxtline; X continue; X X case CTL(W): X re_dosub(linebuf, YES); X numdone++; X offset = curchar = REbom; X makedirty(curline); X /* Fall into ... */ X X case CTL(R): X case 'R': X RErecur(); X offset = curchar; X lp = curline; X continue; X X case CTL(U): X case 'U': X if (UNDO_lp == 0) X continue; X lp = UNDO_lp; X lp->l_dline = UNDO_da | DIRTY; X offset = 0; X numdone--; X continue; X X case 'P': X case '!': X query = 0; X break; X X case CR: X case LF: X case 'Q': X goto done; X X case CTL(L): X RedrawDisplay(); X goto reswitch; X X default: X rbell(); Xmessage("Space or Y, Period, Rubout or N, C-R or R, C-W, C-U or U, P or !, Return."); X goto reswitch; X } X } X re_dosub(linebuf, NO); X numdone++; X modify(); X offset = curchar = REeom; X makedirty(curline); X if (query) { X message(mesgbuf); /* No blinking. */ X redisplay(); /* Show the change. */ X } X UNDO_da = curline->l_dline; X UNDO_lp = curline; X if (linebuf[offset] == 0) Xnxtline: break; X } X } X SetMark(); Xdone: s_mess("%d substitution%n.", numdone, numdone); X} X X/* Prompt for search and replacement strings and do the substitution. The X point is restored when we're done. */ X Xstatic Xreplace(query, inreg) X{ X Mark *save = MakeMark(curline, curchar, FLOATER), X *m; X char *rep_ptr; X Line *l1 = curline, X *l2 = curbuf->b_last; X int char1 = curchar, X char2 = length(curbuf->b_last); X X if (inreg) { X m = CurMark(); X l2 = m->m_line; X char2 = m->m_char; X (void) fixorder(&l1, &char1, &l2, &char2); X } X X /* Get search string. */ X strcpy(rep_search, ask(rep_search[0] ? rep_search : (char *) 0, ProcFmt)); X REcompile(rep_search, UseRE, compbuf, alternates); X /* Now the replacement string. Do_ask() so the user can play with X the default (previous) replacement string by typing C-R in ask(), X OR, he can just hit Return to replace with nothing. */ X rep_ptr = do_ask("\r\n", (int (*)()) 0, rep_str, ": %f %s with ", rep_search); X if (rep_ptr == 0) X rep_ptr = NullStr; X strcpy(rep_str, rep_ptr); X X substitute(query, l1, char1, l2, char2); X ToMark(save); X DelMark(save); X} X XRegReplace() X{ X replace(0, YES); X} X XQRepSearch() X{ X replace(1, NO); X} X XRepSearch() X{ X replace(0, NO); X} X X/* C tags package. */ X Xstatic Xlookup(searchbuf, filebuf, tag, file) Xchar *searchbuf, X *filebuf, X *tag, X *file; X{ X register int taglen = strlen(tag); X char line[128], X pattern[100]; X File *fp; X X fp = open_file(file, iobuff, F_READ, !COMPLAIN, QUIET); X if (fp == NIL) X return 0; X sprintf(pattern, "^%s[^\t]*\t\\([^\t]*\\)\t[?/]\\(.*\\)[?/]$", tag); X while (f_gets(fp, line, sizeof line) != EOF) { X if (line[0] != *tag || strncmp(tag, line, taglen) != 0) X continue; X if (!LookingAt(pattern, line, 0)) { X complain("I thought I saw it!"); X break; X } else { X putmatch(2, searchbuf, 100); X putmatch(1, filebuf, 100); X close_file(fp); X return 1; X } X } X f_close(fp); X s_mess("Can't find tag \"%s\".", tag); X return 0; X} X Xchar TagFile[128] = "./tags"; X Xfind_tag(tag, localp) Xchar *tag; X{ X char filebuf[FILESIZE], X sstr[100], X tfbuf[FILESIZE]; X register Bufpos *bp; X register Buffer *b; X char *tagfname; X X if (!localp) { X char prompt[128]; X X sprintf(prompt, "With tag file (%s default): ", TagFile); X tagfname = ask_file(prompt, TagFile, tfbuf); X } else X tagfname = TagFile; X if (lookup(sstr, filebuf, tag, tagfname) == 0) X return; X SetMark(); X b = do_find(curwind, filebuf, 0); X if (curbuf != b) X SetABuf(curbuf); X SetBuf(b); X if ((bp = dosearch(sstr, BACKWARD, 0)) == 0 && X (WrapScan || ((bp = dosearch(sstr, FORWARD, 0)) == 0))) X message("Well, I found the file, but the tag is missing."); X else X SetDot(bp); X} X XFindTag() X{ X int localp = !exp_p; X char tag[128]; X X strcpy(tag, ask((char *) 0, ProcFmt)); X find_tag(tag, localp); X} X X/* Find Tag at Dot. */ X XFDotTag() X{ X int c1 = curchar, X c2 = c1; X char tagname[50]; X X if (!ismword(linebuf[curchar])) X complain("Not a tag!"); X while (c1 > 0 && ismword(linebuf[c1 - 1])) X c1--; X while (ismword(linebuf[c2])) X c2++; X X null_ncpy(tagname, linebuf + c1, c2 - c1); X find_tag(tagname, !exp_p); X} X X/* I-search returns a code saying what to do: X STOP: We found the match, so unwind the stack and leave X where it is. X DELETE: Rubout the last command. X BACKUP: Back up to where the isearch was last NOT failing. X X When a character is typed it is appended to the search string, and X then, isearch is called recursively. When C-S or C-R is typed, isearch X is again called recursively. */ X X#define STOP 1 X#define DELETE 2 X#define BACKUP 3 X#define TOSTART 4 X Xstatic char ISbuf[128], X *incp = 0; Xint SExitChar = CR; X X#define cmp_char(a, b) ((a) == (b) || (CaseIgnore && (Upper(a) == Upper(b)))) X Xstatic Bufpos * Xdoisearch(dir, c, failing) Xregister int c, X dir, X failing; X{ X static Bufpos buf; X Bufpos *bp; X extern int okay_wrap; X X if (c == CTL(S) || c == CTL(R)) X goto dosrch; X X if (failing) X return 0; X DOTsave(&buf); X if (dir == FORWARD) { X if (cmp_char(linebuf[curchar], c)) { X buf.p_char = curchar + 1; X return &buf; X } X } else { X if (look_at(ISbuf)) X return &buf; X } Xdosrch: okay_wrap = YES; X if ((bp = dosearch(ISbuf, dir, 0)) == 0) X rbell(); /* ring the first time there's no match */ X okay_wrap = NO; X return bp; X} X XIncFSearch() X{ X IncSearch(FORWARD); X} X XIncRSearch() X{ X IncSearch(BACKWARD); X} X Xstatic XIncSearch(dir) X{ X Bufpos save_env; X X DOTsave(&save_env); X ISbuf[0] = 0; X incp = ISbuf; X if (isearch(dir, &save_env) == TOSTART) X SetDot(&save_env); X else { X if (LineDist(curline, save_env.p_line) >= MarkThresh) X DoSetMark(save_env.p_line, save_env.p_char); X } X setsearch(ISbuf); X} X X/* Nicely recursive. */ X Xstatic Xisearch(dir, bp) XBufpos *bp; X{ X Bufpos pushbp; X int c, X ndir, X failing; X char *orig_incp; X X if (bp != 0) { /* Move to the new position. */ X pushbp.p_line = bp->p_line; X pushbp.p_char = bp->p_char; X SetDot(bp); X failing = 0; X } else { X DOTsave(&pushbp); X failing = 1; X } X orig_incp = incp; X ndir = dir; /* Same direction as when we got here, unless X we change it with C-S or C-R. */ X for (;;) { X SetDot(&pushbp); X message(NullStr); X if (failing) X add_mess("Failing "); X if (dir == BACKWARD) X add_mess("reverse-"); X add_mess("I-search: %s", ISbuf); X DrawMesg(NO); X add_mess(NullStr); /* tell me this is disgusting ... */ X c = getch(); X if (c == SExitChar) X return STOP; X switch (c) { X case RUBOUT: X case BS: X return DELETE; X X case CTL(G): X /* If we're failing, we backup until we're no longer X failing or we've reached the beginning; else, we X just about the search and go back to the start. */ X if (failing) X return BACKUP; X return TOSTART; X X case CTL(\\): X c = CTL(S); X case CTL(S): X case CTL(R): X /* If this is the first time through and we have a X search string left over from last time, use that X one now. */ X if (incp == ISbuf) { X strcpy(ISbuf, getsearch()); X incp = &ISbuf[strlen(ISbuf)]; X } X ndir = (c == CTL(S)) ? FORWARD : BACKWARD; X /* If we're failing and we're not changing our X direction, don't recur since there's no way X the search can work. */ X if (failing && ndir == dir) { X rbell(); X continue; X } X break; X X case '\\': X if (incp > &ISbuf[(sizeof ISbuf) - 1]) { X rbell(); X continue; X } X *incp++ = '\\'; X add_mess("\\"); X /* Fall into ... */ X X case CTL(Q): X case CTL(^): X add_mess(""); X c = getch() | 0400; X /* Fall into ... */ X X default: X if (c & 0400) X c &= 0177; X else { X if (c > RUBOUT || (c < ' ' && c != '\t')) { X Ungetc(c); X return STOP; X } X } X if (incp > &ISbuf[(sizeof ISbuf) - 1]) { X rbell(); X continue; X } X *incp++ = c; X *incp = 0; X break; X } X add_mess("%s", orig_incp); X add_mess(" ..."); /* so we know what's going on */ X DrawMesg(NO); /* do it now */ X switch (isearch(ndir, doisearch(ndir, c, failing))) { X case TOSTART: X return TOSTART; X X case STOP: X return STOP; X X case BACKUP: X /* If we're not failing, we just continue to to the X for loop; otherwise we keep returning to the X previous levels until we find one that isn't X failing OR we reach the beginning. */ X if (failing) X return BACKUP; X /* Fall into ... */ X X case DELETE: X incp = orig_incp; X *incp = 0; X continue; X } X } X} @//E*O*F re1.c// if test 9617 -ne "`wc -c <'re1.c'`"; then echo shar: error transmitting "'re1.c'" '(should have been 9617 characters)' fi fi # end of overwriting check echo shar: extracting "'table.h'" '(870 characters)' if test -f 'table.h' ; then echo shar: will not over-write existing file "'table.h'" else sed 's/^X//' >table.h <<'@//E*O*F table.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 Xtypedef struct word Word; Xtypedef struct table Table; X Xstruct word { X Word *wd_next; X char *wd_text; X}; X Xstruct table { X Table *t_next; X Word *t_wordlist; X}; X Xextern Table *make_table(); Xextern Word *word_in_table(); X X#define table_top(table) (table->t_wordlist) X#define next_word(w) (w->wd_next) X#define last_word_p(w) (w->wd_next == NIL) X#define word_text(w) (w->wd_text) X#define word_length(w) (strlen(word_text(w))) @//E*O*F table.h// if test 870 -ne "`wc -c <'table.h'`"; then echo shar: error transmitting "'table.h'" '(should have been 870 characters)' fi fi # end of overwriting check echo shar: "End of archive 6 (of 13)." cp /dev/null ark6isdone 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