[mod.sources] v07i005: Vi front-end for remote editing, Part02/04

sources-request@mirror.UUCP (08/27/86)

Submitted by: Alan Klietz <ihnp4!dicome!mn-at1!alan>
Mod.sources: Volume 7, Issue 5
Archive-name: rvi/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".
# Wrapped by mirror!rs on Wed Aug 27 00:09:58 EDT 1986

# Exit status; set to 1 on "wc" errors or if would overwrite.
STATUS=0
# Contents:  rv_insert.c rv_linecmd.c rv_misc.c rv_move.c
#	rv_openline.c rv_put.c rv_redraw.c rv_redraw_ln.c rv_scroll.c
#	rv_scroll_bk.c rv_search.c rv_shell.c rv_sync.c rv_undo.c
 
echo x - rv_insert.c
if test -f rv_insert.c ; then
    echo rv_insert.c exists, putting output in $$rv_insert.c
    OUT=$$rv_insert.c
    STATUS=1
else
    OUT=rv_insert.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_insert.c//'
XX#include "rv.h"
XX#include <ctype.h>

XX#define ALLOC_LEN  64  /* Size of reallocation chunk */

XXboolean replace_flag;		/* TRUE if R command */
XXboolean superquote;		/* Set by rv_getchar if char is quoted by ^V */
XXextern INT autoindent;		/* Physical autoindent, if opened_line */

XX       char *fake_input;	/* Set this to fake text into rv_getchar */
XXstatic char fake_buf[512];	/* Buffer for faked characters */
XXextern char *realloc();


XXvoid
XXinsert()
XX/*
XX * Insert input at the current cursor position, replacing
XX * text up to lastcol.  If lastcol < cursor, no text replaced.
XX */
XX{
XX	register struct sc_screen *sc;
XX	register struct li_line   *line;
XX	boolean	quick_append;
XX	INT	i;
XX	char	*s, *indentbuf;
XX	void	fake_chars();

XX	file.fi_modified = TRUE;
XX	/*
XX	 * sc_firstcol = first column of insertion. Fixed.
XX	 * sc_lastcol  = last column of insertion.  Grows.
XX	 * sc_column   = current cursor position
XX	 */

XXnextinsert:
XX	input_mode = TRUE;
XX	quick_append = FALSE;
XX	indentbuf = NULL;
XX	save_Undo();
XX	sc = &screen;
XX	line = sc->sc_curline;

XX	if (!opened_line) {
XX		/*
XX		 * Remember insertion for later undo
XX		 */
XX		undo.un_firstline = sc->sc_firstline;
XX		undo.un_lastline = sc->sc_lastline;
XX		undo.un_validcol = TRUE;
XX		undo.un_firstcol = sc->sc_firstcol;
XX		undo.un_inserted = TRUE;
XX		/*
XX		 * Save overwritten text for later undo
XX		 */
XX		yank_cmd = ' ';
XX		if (sc->sc_lastcol >= sc->sc_column) {
XX			yank();
XX			undo.un_deleted = TRUE;
XX		}
XX	} else if (autoindent > 0) {
XX		/*
XX		 * Fake autoindented tabs and spaces into line
XX		 */
XX		fake_input = fake_buf;
XX		indentbuf = xalloc(autoindent+1);
XX		i = autoindent / set_tabstops;
XX		if (set_fortran)
XX			fake_chars(' ', i * set_tabstops);
XX		else
XX			fake_chars('\t', i);
XX		i = autoindent % set_tabstops;
XX		fake_chars(' ', i);
XX		fake_input = fake_buf;
XX		strcpy(indentbuf, fake_input);
XX	}

XX	if (sc->sc_lastcol >= sc->sc_column)
XX		/*
XX		 * Append '$' to end of replaced text
XX		 */
XX		line->li_text[sc->sc_lastcol] = '$';

XX	line->li_text = realloc(line->li_text, line->li_width + ALLOC_LEN + 1);

XX	/*
XX	 * Get and process input chars
XX	 */
XX	for (;;) {
XX		INT	ch;

XX		/*
XX		 * Redisplay line
XX		 * Append is a fast special case
XX		 */
XX		if (quick_append)
XX			quick_append = FALSE;
XX		else {
XX			redraw_curline(line->li_text);
XX			move_cursor(sc->sc_lineno, sc->sc_column);
XX		}

XX		ch = rv_getchar();
XX		if (superquote) /* If quoted with ^V, skip all processing */
XX			goto addchar;

XX		if (ch == erasechar() || ch == '\b') {
XX			/*
XX			 * Delete a character if not blackslashed
XX			 */
XX			if (sc->sc_column == sc->sc_firstcol) {
XX				flash();
XX				continue;
XX			}
XX			if (line->li_text[sc->sc_column-1] == '\\')
XX				line->li_text[sc->sc_column-1] = ch;
XX			else
XX				sc->sc_column--;
XX			continue;
XX		}

XX		if (ch == killchar() || ch == CTRL(X)) {
XX			/*
XX			 * Delete line if not backslashed
XX			 */
XX			if (sc->sc_column == sc->sc_firstcol) {
XX				/*
XX				 * Already at first column, error
XX				 */
XX				flash();
XX				continue;
XX			}
XX			if (line->li_text[sc->sc_column-1] == '\\')
XX				line->li_text[sc->sc_column-1] = ch;
XX			else
XX				sc->sc_column = sc->sc_firstcol;
XX			continue;
XX		}

XX		switch (ch) {
XXcase CTRL([):
XXcase '\n':
XXcase '\r':
XX		/*
XX		 * Escape or newline - end insert
XX		 */
XX		if (replace_flag) {
XX			/*
XX			 * Clean up replace mode
XX			 */
XX			if (sc->sc_column <= sc->sc_lastcol) {
XX				register i;
XX				/*
XX				 * Replace backspaced chars from undo buffer
XX				 */
XX				for (i=sc->sc_column; i <= sc->sc_lastcol; ++i)
XX					if (i < sc->sc_origline.li_width)
XX						line->li_text[i] =
XX						    sc->sc_origline.li_text[i];
XX			}
XX			/*
XX			 * Chop off backspaced chars at end of line
XX			 */
XX			if (sc->sc_lastcol == line->li_width-1 &&
XX					sc->sc_lastcol >= 0) {
XX				line->li_width = sc->sc_column;
XX				line->li_text[line->li_width] = '\0';
XX			}
XX		} else { /* insert mode */
XX			if (sc->sc_lastcol >= sc->sc_column) {
XX				register char	*s, *s2;
XX				/*
XX				 * Close up backspaced text
XX				 */
XX				s  = &line->li_text[sc->sc_column];
XX				s2 = &line->li_text[sc->sc_lastcol+1];
XX				while (*s++ = *s2++)
XX					;
XX				line->li_width = strlen(line->li_text);
XX			}
XX		}

XX		/*
XX		 * Collapse autoindent if line not altered by user
XX		 */
XX		if (opened_line && autoindent > 0 && indentbuf &&
XX				strcmp(indentbuf, line->li_text) == 0) {
XX			redraw_curline("");
XX			sc->sc_column = 0;
XX			i = autoindent;
XX		} else {
XX			redraw_curline(line->li_text);
XX			i = 0;
XX		}
XX		if (indentbuf)
XX			free(indentbuf);

XX		if (ch == CTRL([)) {
XX			input_mode = FALSE;
XX			replace_flag = FALSE;
XX			if (sc->sc_column > 0)
XX				sc->sc_column--;
XX			move_cursor(sc->sc_lineno, sc->sc_column);
XX			if (sc->sc_lastcol < sc->sc_firstcol) {
XX				if (!opened_line)
XX					undo.un_inserted = FALSE;
XX			} else
XX				undo.un_lastcol = sc->sc_column;
XX			return;
XX		} else {
XX			register char *s, *s2;
XX			/*
XX			 * Continue input on new line
XX			 */
XX			s = s2 = &line->li_text[sc->sc_column];
XX			toss_undo();
XX			openline(1);
XX			if (i != 0)
XX				autoindent = i;
XX			if (*s != '\0') { /* if not at end of line */
XX				/*
XX				 * Split line
XX				 */
XX				undo.un_validcol = TRUE;
XX				undo.un_firstcol = 0;
XX				if (set_autoindent)
XX					while (isspace(*s))
XX						++s;
XX				redraw_curline(s);
XX				xmit_curline();
XX				*s2 = '\0';
XX				sc->sc_lineno--;
XX				sc->sc_curline--;
XX				redraw_curline(sc->sc_curline->li_text);
XX				save_Undo();
XX				xmit_curline();
XX				move_cursor(sc->sc_lineno+1, 0);
XX				save_Undo();
XX			}
XX			goto nextinsert; /* quick recursion */
XX		}
XX		break;

XXcase CTRL(W):
XX		/*
XX		 * Control-W - backspace 1 word
XX		 */
XX		/* Implementation deferred */
XX		continue;

XXcase '\t':
XX		/*
XX		 * Tab
XX		 */
XX		if (set_fortran) {
XX			/*
XX			 * Fortran source.  Expand tab to spaces
XX			 */
XX			if (sc->sc_column < 6) {
XX				/*
XX				 * First tab in fortran program, expand
XX				 * to six spaces
XX				 */
XX				fake_input = fake_buf;
XX				fake_chars(' ', 6-sc->sc_column);
XX				fake_input = fake_buf;
XX				continue;
XX			}
XX			/*
XX			 * Expand other tabs to shiftwidth spaces
XX			 */
XX			i = set_shiftwidth - (sc->sc_column % set_shiftwidth);
XX			fake_input = fake_buf;
XX			fake_chars(' ', i);
XX			fake_input = fake_buf;
XX			continue;
XX		}
XX		break;


XXcase CTRL(D):
XX		/*
XX		 * Backtab
XX		 */
XX		if (sc->sc_column == sc->sc_firstcol) {
XX			flash();
XX			continue;
XX		}
XX		i = screen_column(line->li_text, sc->sc_column);
XX		i -= i % set_shiftwidth == 0 ?
XX			set_shiftwidth : i % set_shiftwidth;
XX		i = file_column(line->li_text, i);
XX		if (set_fortran && i < 6 && sc->sc_column > 6)
XX			i = 6;
XX		fake_input = fake_buf;
XX		fake_chars('\b', sc->sc_column - i);
XX		fake_input = fake_buf;
XX		continue;

XX		} /* End switch */

XX		

XX		/*
XX		 * Add character to line
XX		 */

XXaddchar:
XX		/*
XX		 * Check if line needs expansion
XX		 */
XX		if (sc->sc_lastcol < sc->sc_column) {
XX			if (!replace_flag || sc->sc_column >= line->li_width) {
XX				register  char *s, *s2;
XX				/*
XX				 * Expand line 1 character
XX				 */
XX				line->li_width++;
XX				/*
XX				 * Expand line in chunks of ALLOC_LEN
XX				 */
XX				if (line->li_width % ALLOC_LEN == 0)
XX					line->li_text = realloc(line->li_text,
XX						line->li_width + ALLOC_LEN+1);

XX				if (sc->sc_column == line->li_width-1 && 
XX				    ch >= '@' && CURCOLUMN > 0) {
XX					/*
XX					 * Fast special case - add char at
XX					 * eol.  No control chars, no char, 
XX					 * shifting, and no line shifting
XX					 * required.
XX					 */
XX					quick_append = TRUE;
XX					addch(ch);
XX					line->li_text[line->li_width] = '\0';
XX#ifndef USG
XX					/*
XX					 * KLUDGE - Handle VT100 brain damage
XX					 * until Berkeley fixes up curses to 
XX					 * handle it.
XX					 */
XX					if (XN && CURCOLUMN==0) {
XX						addch(' ');
XX						refresh();
XX						addch('\b');
XX					}
XX#endif
XX				} else {
XX					/*
XX					 * Slide text beyond insert right
XX					 */
XX					s  = &line->li_text[line->li_width-1];
XX					s2 = &line->li_text[sc->sc_column];
XX					while (s >= s2) {
XX						*(s+1) = *s;
XX						--s;
XX					}
XX				}
XX			}
XX			sc->sc_lastcol++;
XX			if (sc->sc_lastcol < sc->sc_firstcol)
XX				sc->sc_lastcol = sc->sc_firstcol;
XX		}

XX		/*
XX		 * Insert character
XX		 */
XX		line->li_text[sc->sc_column++] = ch;
XX	}
XX}


XXINT
XXrv_getchar()
XX/*
XX * Get a character from the keyboard.  
XX * Parse ^V as a super quote.
XX */
XX{
XX	INT ch;

XX	superquote = FALSE;
XX	/*
XX	 * Check for fake input
XX	 */
XX	if (fake_input && *fake_input != '\0')
XX		return(*fake_input++);

XX	refresh();
XX	while ((ch = getch()) == '\0') /* null is verboten */
XX		;
XX	if (ch == CTRL(V)) {
XX		raw(); /* Allow ^S, ^Q and interrupt keys */
XX		insch('^');
XX		/*
XX		 * Get raw character, null is verboten.
XX		 */
XX		refresh();
XX		while ((ch = getch()) == '\0')
XX			;
XX		noraw();
XX#ifdef USG
XX		cbreak();
XX#else
XX		crmode();
XX#endif !USG
XX		superquote = (ch != '\n');
XX	}
XX	if (ch == ERR || ch == EOF)
XX		quit();
XX	return(ch);
XX}


XXvoid
XXdup_insert(count)
XX/*
XX * Duplicate the text found between firstcol and column
XX */
XXINT count;
XX{
XX	register struct sc_screen *sc;
XX	register struct li_line   *line;
XX	register char	*buf, *s, *s1, *s2;

XX	sc = &screen;
XX	line = sc->sc_curline;

XX	/*
XX	 * Make sure duplicatable section exists
XX	 */
XX	if (count <= 1 || sc->sc_column  < sc->sc_firstcol
XX		       || sc->sc_lastcol < sc->sc_firstcol)
XX		return;

XX	sc->sc_column++;
XX	/*
XX	 * Get buffer space
XX	 */
XX	buf = xalloc(strlen(line->li_text)+1 + (sc->sc_column -
XX					     sc->sc_firstcol) * count);
XX	/*
XX	 * Copy text up to duplicatable section
XX	 */
XX	s = buf;
XX	s1 = line->li_text;
XX	s2 = &line->li_text[sc->sc_column];
XX	while (s1 < s2)
XX		*s++ = *s1++;

XX	/*
XX	 * Duplicate section
XX	 */
XX	while (--count > 0) {
XX		s1 = &line->li_text[sc->sc_firstcol];
XX		while (s1 < s2)
XX			*s++ = *s1++;
XX	}

XX	/*
XX	 * Position cursor at last character of last duplicated section
XX	 */
XX	sc->sc_column = (s - buf) - 1;

XX	/*
XX	 * Set up for undo
XX	 */
XX	if (!opened_line) {
XX		undo.un_inserted = TRUE;
XX		undo.un_validcol = TRUE;
XX		undo.un_firstline = undo.un_lastline = sc->sc_lineno;
XX		undo.un_firstcol = sc->sc_firstcol;
XX		undo.un_lastcol = sc->sc_column;
XX	}

XX	/*
XX	 * Copy remainder of line
XX	 */
XX	while (*s++ = *s2++)
XX		;
XX	redraw_curline(buf);
XX	free(buf);
XX	move_cursor(sc->sc_lineno, sc->sc_column);
XX}


XXvoid
XXfake_chars(ch, count)
XXchar ch;
XXregister INT count;
XX{
XX	register char *s;

XX	s = fake_input;
XX	for (; count > 0; --count)
XX		*s++ = ch;
XX	*s = '\0';
XX	fake_input = s;
XX}
@//E*O*F rv_insert.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_linecmd.c
if test -f rv_linecmd.c ; then
    echo rv_linecmd.c exists, putting output in $$rv_linecmd.c
    OUT=$$rv_linecmd.c
    STATUS=1
else
    OUT=rv_linecmd.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_linecmd.c//'
XX#include "rv.h"
XX#include <ctype.h>

XXboolean	ed_undo;	/* Set TRUE if last mod was direct ed cmd */

XXextern boolean did_botprint;   /* used by botprint() */

XXstatic struct cm_cmdlist {  /* Commands */
XX	char cm_cmd[12];
XX	INT  cm_index;
XX} cmdlist[] = {
XX	"E",	3,
XX	"Q",	2,
XX	"edit", 3,
XX	"file", 5,
XX	"next", 4,
XX	"quit",	2,
XX	"se",	1,
XX	"set",	1,
XX	"sh",	8,
XX	"shell",8,
XX	"w",	6,
XX	"wq",	7,
XX	"write", 6,
XX	"xit",	7,
XX	"z",	7,
XX};

XXstatic struct op_oplist {   /* Options */
XX	char op_option[12];
XX	INT  op_index;
XX} oplist[] = {
XX	"ai",		1,
XX	"all",		2,
XX	"autoindent", 	1,
XX	"debug",	3,
XX	"fortran",	4,
XX	"list",		5,
XX	"scroll",	6,
XX	"shiftwidth",	7,
XX	"sw",		7,
XX	"tabstops",	8,
XX	"timeout",	10,
XX	"to",		10,
XX	"ts",		8,
XX	"wrapscan",	9,
XX	"ws",		9,
XX};


XXvoid
XXrv_linecmd(cmd)
XX/*
XX * Execute command line
XX */
XXchar *cmd;
XX{
XX	register char *s, *s2;
XX	INT	i, j;
XX	boolean	flag;
XX	char	buf[12];
XX	
XX	if ((s2 = cmd) == NULL || *s2 == '\0')
XX		return;
XX	while (isalnum(*s2))
XX		++s2;
XX	j = *s2;
XX	*s2 = '\0';
XX	i = binsearch(cmd, (char *) cmdlist, sizeof(struct cm_cmdlist),
XX		sizeof(cmdlist) / sizeof(struct cm_cmdlist));
XX	if (i >= 0)
XX		i = cmdlist[i].cm_index;
XX	*s2 = j;

XX	xmit_curline();
XX	switch(i) {
XXcase 1:
XX	/*
XX	 * Set
XX	 */
XX	if (*s2 == '\0')
XX		s2 = "all";
XX	for (;;) {
XX		while (isspace(*s2) && *s2 != '\0')
XX			++s2;
XX		if (*s2 == '\0')
XX			break;
XX		s = s2;
XX		while (isalnum(*s2))
XX			++s2;
XX		if (*s2 != '\0')
XX			*s2++ = '\0';
XX		if (*s == 'n' && *(s+1) == 'o') {
XX			s += 2;
XX			flag = FALSE;
XX		} else
XX			flag = TRUE;
XX		i = binsearch(s, (char *) oplist, sizeof(struct op_oplist),
XX			sizeof(oplist) / sizeof(struct op_oplist));
XX		if (i >= 0)
XX			i = oplist[i].op_index;

XX		switch (i) {

XX		case -2:
XX			botprint(TRUE, "\"%s\" is not unique\n", s);
XX			break;

XX		case -1:
XX			botprint(TRUE, "\"%s\": No such option - 'set all' gives all option values\n", s);
XX			return;

XX		case 1: /* autoindent */
XX			set_autoindent = flag;
XX			break;
XX		
XX		case 2: /* all */
XX			botprint(FALSE, "%sautoindent\n", set_autoindent ?
XX				"" : "no");
XX			botprint(FALSE, "debug=%d\n", set_debug);
XX			botprint(FALSE, "%sfortran\n", set_fortran ? "" :
XX				"no");
XX			botprint(FALSE, "%slist", set_list ? "" : "no");
XX			botprint(FALSE, "scroll=%d\n", set_scroll);
XX			botprint(FALSE, "shiftwidth=%d\n", set_shiftwidth);
XX			botprint(FALSE, "tabstops=%d\n", set_tabstops);
XX			botprint(FALSE, "%stimeout", set_timeout ? "" : "no");
XX			botprint(FALSE, "%swrapscan", set_wrapscan ? "" : "no");
XX			break;

XX		case 3: /* debug */
XX			set_debug = atoi(s2);
XX			while (isdigit(*s2))
XX				++s2;
XX			break;

XX		case 4:
XX			set_fortran = flag;
XX			break;

XX		case 5: set_list = flag;
XX			fetch_window(screen.sc_lineno-NUM_WINDOW_LINES/4-
XX				LINES-2+1, TRUE);
XX			break;

XX		case 6: /* scroll */
XX			set_scroll = atoi(s2);
XX			while (isdigit(*s2))
XX				++s2;
XX			if (set_scroll <= 0)
XX				set_scroll = 1;
XX			break;

XX		case 7: /* shiftwidth */
XX			set_shiftwidth = atoi(s2);
XX			while (isdigit(*s2))
XX				++s2;
XX			if (set_shiftwidth <= 0)
XX				set_shiftwidth = 1;
XX			else if (set_shiftwidth > 40)
XX				set_shiftwidth = 40;
XX			break;

XX		case 8: /* tabstops */
XX			set_tabstops = atoi(s2);
XX			while (isdigit(*s2))
XX				++s2;
XX			if (set_tabstops <= 0)
XX				set_tabstops = 1;
XX			else if (set_tabstops > 40)
XX				set_tabstops = 40;
XX			break;

XX		case 9: /* wrapscan */
XX			set_wrapscan = flag;
XX			break;

XX		case 10: /* timeout */
XX			set_timeout = flag;
XX#ifdef USG
XX			keypad(stdscr, flag ? 1 : 2);
XX#endif
XX			break;

XX		default:
XX			botprint(FALSE, "That option is not yet implemented\n");
XX			break;
XX		}
XX	}
XX	break;


XXcase 2: /* quit */
XX	if (file.fi_modified && *s2 != '!') {
XX		botprint(TRUE, "No write since last change (:q! overrides)");
XX		return;
XX	}
XX	Quit();
XX	break;

XXcase 3: /* edit */
XX	if (file.fi_modified && *s2 != '!') {
XX		botprint(TRUE, "No write since last change (:edit! overrides)");
XX		return;
XX	}
XX	if (*s2 == '!')
XX		++s2;
XX	while (isspace(*s2))
XX		++s2;
XX	edit(s2);
XX	break;

XXcase 4: /* next */
XX	if (file.fi_modified && *s2 != '!') {
XX		botprint(TRUE, "No write since last change (:next! overrides)");
XX		return;
XX	}
XX	if (*s2 == '!')
XX		++s2;
XX	while (isspace(*s2))
XX		++s2;
XX	if (*s2 == '\0' && *nextfile == '\0') {
XX		botprint(TRUE, "No more files to edit");
XX		return;
XX	}
XX	edit(s2);
XX	break;

XXcase 5: /* file */
XX	while (isspace(*s2))
XX		++s2;
XX	if (*s2 == '\0') {
XX		sizemsg();
XX		return;
XX	}
XX	xmit_ed("f %s\n", s2);
XX	strncpy(file.fi_name, s2, 126);
XX	xmit_sync();
XX	(void) recv_sync(TRUE);
XX	sizemsg();
XX	break;

XXcase 6: /* write */
XX	i = 0;
XX	if (*s2 == '!') {
XX		++s2;
XX		i = 1;
XX	}
XX	while (isspace(*s2))
XX		++s2;
XX	if (*s2 == '\0' && file.fi_name[0] == '\0') {
XX		botprint(TRUE, "No current filename");
XX		return;
XX	}
XX	if (i)
XX		xmit_ed("!rm -f %s\n", *s2 ? s2 : file.fi_name);
XX	if (*s2)
XX		xmit_ed("w %s\n", s2);
XX	else {
XX		xmit_ed("w\n");
XX		s2 = file.fi_name;
XX	}
XX	xmit_sync();
XX	botprint(FALSE, "\"%s\"", s2);
XX	hitcr_continue();
XX	refresh();
XX	if (recv_sync(TRUE)) {
XX		botprint(FALSE, "\"%s\" %d lines", s2, file.fi_numlines);
XX		if (strcmp(s2, file.fi_name) == 0)
XX			file.fi_modified = FALSE;
XX	}
XX	else
XX		hitcr_continue();
XX	break;

XXcase 7: /* wq */
XX	if (file.fi_modified)
XX		rv_linecmd("w");
XX	if (!file.fi_modified)
XX		rv_linecmd("q");
XX	break;

XXcase 8: /* shell */
XX	rv_shell("sh -i");
XX	break;
XX	
XXdefault:
XX	if (*s2 == '!') {  /* Shell escape */
XX		if (strcmp(++s2, "sh") == 0)
XX			s2 = "sh -i";
XX		else if (strcmp(s2, "csh") == 0)
XX			s2 = "csh -i";
XX		rv_shell(s2);
XX		return;
XX	}
XX	did_botprint = TRUE;
XX	i = cmd[strlen(cmd)-1];
XX	if (i == 'a' || i == 'c' || i == 'i' || i == 'H' || i == 'X'
XX		     || i == 'P') {
XX		botprint(FALSE, "That command is reserved");
XX		return;
XX	}
XX	toss_undo();
XX	if (i == 'w') {
XX		ed_undo = FALSE;
XX		file.fi_modified = FALSE;
XX	} else
XX		ed_undo = TRUE;
XX	xmit_ed("%d\n", screen.sc_lineno);
XX	xmit_sync();
XX	xmit_ed("%s\n", cmd);
XX	xmit_sync();
XX	xmit_ed(".=\n");
XX	(void) recv_sync(FALSE);
XX	(void) recv_sync(2);
XX	(void) fgets(buf, 10, file.fi_fpin);
XX	if ((i = atoi(buf)) <= 0)
XX		i = screen.sc_lineno;
XX	hitcr_continue();
XX	fetch_window(i-NUM_WINDOW_LINES/4-LINES/2+1, TRUE);
XX	move_abs_cursor(i, COL_FIRST_NONWHITE);
XX	break;
XX	}
XX}
@//E*O*F rv_linecmd.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_misc.c
if test -f rv_misc.c ; then
    echo rv_misc.c exists, putting output in $$rv_misc.c
    OUT=$$rv_misc.c
    STATUS=1
else
    OUT=rv_misc.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_misc.c//'
XX#include "rv.h"

XX/*
XX * Miscellaneous subroutines
XX */

XXchar *xalloc(n)
XX/*
XX * Allocate and zero n bytes
XX */
XX{
XX	char *s;
XX	char *malloc();

XX	if ((s = malloc(n)) == NULL) {
XX		write(2, "Out of memory", 13);
XX		endwin();
XX		exit(1);
XX	}
XX	zero(s, n);
XX	return s;
XX}


XXboolean did_botprint;  /* True if botprint() was already called */
XXboolean scrolled;      /* True if screen scrolled from a call */

XX/*VARARGS1*/
XXvoid
XXbotprint(standout_flag, txt, arg1, arg2, arg3, arg4, arg5)
XX/*
XX * Printf line(s) on bottom of screen with the given attribute(s).
XX */
XXINT  standout_flag;
XXchar *txt, *arg1, *arg2, *arg3, *arg4, *arg5;
XX{
XX	char buf[512];
XX	INT  oldrow, oldcol, l;

XX	oldrow = CURLINE;
XX	oldcol = CURCOLUMN;

XX	sprintf(buf, txt, arg1, arg2, arg3, arg4, arg5);
XX	l = strlen(buf);
XX	if (l > 0 && buf[l-1] == '\n') /* Remove trailing \n */
XX		buf[--l] = '\0';
XX	move(LINES-1, 0);
XX	if (did_botprint) {
XX		rv_fscroll(1);
XX		move(LINES-1, 0);
XX		scrolled = TRUE;
XX	}
XX	else
XX		clrtoeol();

XX	if (standout_flag)
XX		standout();
XX	addstr(buf);
XX	if (standout_flag)
XX		standend();
XX	while (l > 0 && buf[l-1] == '\n') {
XX		buf[--l] = '\0';
XX		/* scroll(stdscr); */
XX		scrolled = TRUE;
XX	}

XX	did_botprint = TRUE;

XX	if (l >= COLS || l > CURCOLUMN)
XX		scrolled = TRUE;

XX	move(oldrow, oldcol);
XX}


XXhitcr_continue()
XX{
XX	INT oldrow, oldcol;
XX	INT c;

XX	if (scrolled) {
XX		/*
XX		 * Screen scrolled.  Redraw
XX		 */
XX		oldrow = CURLINE;
XX		oldcol = CURCOLUMN;
XX		move(LINES-1,0);
XX		rv_fscroll(1);
XX		move(LINES-1, 0);
XX		standout();
XX		addstr("[Hit return to continue]");
XX		standend();
XX		refresh();
XX		while ((c = getch()) != '\r' && c != '\n' && c != ' ')
XX			;
XX		redraw_screen((struct li_line *) 0);
XX		move(oldrow, oldcol);
XX		scrolled = FALSE;
XX	}
XX	did_botprint = FALSE;
XX}


XXvoid
XXpanic(msg)
XX/*
XX * Print msg and abort
XX */
XXchar *msg;
XX{
XX	botprint(TRUE, "Fatal error: %s\n", msg);
XX	move(LINES-1, 0);
XX	rv_fscroll(1);
XX	move(LINES-1, 0);
XX	refresh();
XX	endwin();
XX	exit(1);
XX}

XXvoid
XXsizemsg()
XX{
XX	if (file.fi_name[0] == '\0' || strcmp(file.fi_name, "/dev/null") == 0)
XX		botprint(0, "No file  line %d of %d --%d%%--", 
XX			screen.sc_lineno, file.fi_numlines, 
XX			(screen.sc_lineno*100) / file.fi_numlines);
XX	else
XX		botprint(0, "\"%s\" %sline %d of %d --%d%%--", file.fi_name,
XX			file.fi_modified ? "[modified] " : "",
XX			screen.sc_lineno, file.fi_numlines, 
XX			(screen.sc_lineno*100) / file.fi_numlines);
XX}


XXvoid
XXrv_debug()
XX{
XX	botprint(FALSE, "Absolute:\n");
XX	botprint(FALSE, "wi_topline=%d, wi_botline=%d\n",
XX		window.wi_topline - &line_array[0],
XX		window.wi_botline - &line_array[0]);
XX	botprint(FALSE, "sc_topline=%d, sc_botline=%d, sc_curline=%d\n",
XX		screen.sc_topline - &line_array[0],
XX		screen.sc_botline - &line_array[0],
XX		screen.sc_curline - &line_array[0]);
XX	botprint(FALSE, "sc_lineno=%d, fi_numlines=%d\n",
XX		screen.sc_lineno, file.fi_numlines);
XX	botprint(FALSE, "Relative to window:\n");
XX	botprint(FALSE, "sc_topline=%d, sc_botline=%d, sc_curline=%d\n",
XX		screen.sc_topline - window.wi_topline,
XX		screen.sc_botline - window.wi_topline,
XX		screen.sc_curline - window.wi_topline);
XX}
@//E*O*F rv_misc.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_move.c
if test -f rv_move.c ; then
    echo rv_move.c exists, putting output in $$rv_move.c
    OUT=$$rv_move.c
    STATUS=1
else
    OUT=rv_move.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_move.c//'
XX#include "rv.h"
XX#include <ctype.h>

XX/*
XX * rv_move.c  - Cursor motion routines
XX */

XXvoid
XXmove_abs_cursor(lineno, column)
XX/*
XX * Move cursor to absolute position in file.  Try to stay within the window
XX * if possible.
XX */
XXINT lineno, column;
XX{
XX	register INT	seg;
XX	register struct li_line	*line, *newline;
XX	register struct sc_screen      *sc;
XX	register struct wi_window      *wi;
XX	INT	 oldlineno, offset;
XX	struct   fi_file	       *fi;
XX	void     rv_scroll(), rv_scroll_backward();

XX	sc = &screen;
XX	wi = &window;
XX	fi = &file;
XX	errflag = 0;
XX	/*
XX	 * Boundary checks
XX	 */
XX	if (lineno < 1) { /* If past top of file */
XX		errflag = 1;
XX		flash();
XX		return;
XX	} else if (lineno > fi->fi_numlines) { /* If past bottom of file */
XX		errflag = 1;
XX		flash();
XX		return;
XX	}

XX	if (lineno < sc->sc_lineno - (sc->sc_curline-sc->sc_topline)) {
XX		/*
XX		 * Past top of screen
XX		 */
XX		oldlineno = sc->sc_lineno;
XX		if (lineno < sc->sc_lineno - (sc->sc_curline-wi->wi_topline)) {
XX			/*
XX			 * Past top of window, fetch more data
XX			 */
XX			fetch_window(lineno-NUM_WINDOW_LINES/4-LINES/2+1,
XX									FALSE);
XX			if (errflag)
XX				return;
XX		}
XX		newline = sc->sc_curline - (sc->sc_lineno - lineno);
XX		seg = 0;
XX		if (oldlineno == sc->sc_lineno) { /* If relatively close */
XX			/*
XX			 * Find distance, in segments, above top of screen
XX			 */
XX			for (line = newline; line < sc->sc_topline; ++line)
XX				seg += line->li_segments;
XX			if (seg <= LINES/3+1) { /* If very close */
XX				/*
XX				 * Scroll backwards
XX				 */
XX				rv_scroll_backward(sc->sc_topline - newline);
XX				move_cursor(lineno, column);
XX				return;
XX			}
XX		}

XX		/*
XX		 * Newline is too far away for scrolling,
XX		 * so we redraw the screen and deposit newline
XX		 * in the center.
XX		 */

XX		/*
XX		 * Set the top of the screen at LINES/2 segments above newline
XX		 */
XX		xmit_curline();
XX		seg = LINES/2;
XX		for (line = newline; line >= wi->wi_topline && seg > 0; --line)
XX			seg -= line->li_segments;
XX		sc->sc_topline = line+1;
XX		sc->sc_curline = newline;
XX		sc->sc_lineno = lineno;
XX		sc->sc_abovetop = 0;
XX		/*
XX		 * Compute bottom line
XX		 */
XX		line = sc->sc_topline;
XX		for (seg = line->li_segments; seg < LINES;
XX				seg += line->li_segments) {
XX			++line;
XX			if (line > wi->wi_botline)
XX				break;
XX		}
XX		sc->sc_botline = line-1;

XX		/*
XX		 * Update the screen to curses
XX		 */
XX		move_cursor(lineno, column);
XX		redraw_screen((struct li_line *)0);
XX		return;
XX	} /* End of past top of screen */
XX		

XX	if (lineno > sc->sc_lineno + (sc->sc_botline - sc->sc_curline)) {
XX		/*
XX		 * Past bottom of screen
XX		 */
XX		oldlineno = sc->sc_lineno;
XX		offset = sc->sc_botline - sc->sc_curline;
XX		if (lineno > sc->sc_lineno + (wi->wi_botline-sc->sc_curline)) {
XX			/*
XX			 * Past bottom of window
XX			 */
XX			fetch_window(lineno-NUM_WINDOW_LINES/4-LINES/2+1,
XX									TRUE);
XX			if (errflag)
XX				return;
XX		}
XX		newline = sc->sc_curline + (lineno - sc->sc_lineno);
XX		seg = 0;
XX		if (oldlineno == sc->sc_lineno) { /* If relatively close */
XX			/*
XX			 * Find distance in segments past bottom of screen
XX			 */
XX			for (line = sc->sc_curline+offset+1; line <= newline;
XX									++line)
XX				seg += line->li_segments;
XX			if (seg <= LINES/3+1 && newline >= sc->sc_botline) {
XX				/*
XX				 * Scroll screen forwards
XX				 */
XX				rv_scroll(newline - sc->sc_botline);
XX				move_cursor(lineno, column);
XX				return;
XX			}
XX		}

XX		/*
XX		 * Newline is too far away for scrolling,
XX		 * so we redraw the screen and deposit newline
XX		 * in the center.
XX		 */

XX		/*
XX		 * Set the top of the screen at LINES/2 segments above newline
XX		 */
XX		xmit_curline();
XX		seg = LINES/2;
XX		for (line = newline; line >= wi->wi_topline && seg > 0; --line)
XX			seg -= line->li_segments;
XX		sc->sc_abovetop = 0;
XX		sc->sc_topline = line+1;
XX		sc->sc_curline = newline;
XX		sc->sc_lineno = lineno;
XX		/*
XX		 * Compute bottom line
XX		 */
XX		line = sc->sc_topline;
XX		for (seg = line->li_segments; seg < LINES;
XX				seg += line->li_segments) {
XX			++line;
XX			if (line > wi->wi_botline)
XX				break;
XX		}
XX		sc->sc_botline = line-1;

XX		/*
XX		 * Update the screen to curses
XX		 */
XX		move_cursor(lineno, column);
XX		redraw_screen((struct li_line *)0);
XX		return;
XX	} /* End of past bottom of screen */
XX		
XX	/*
XX	 * Otherwise, newline must already be on the screen
XX	 */

XX	move_cursor(lineno, column);
XX	return;
XX}



XXvoid
XXmove_cursor(lineno, column)
XX/*
XX * Move cursor to position in file.  Must already be on screen.
XX */
XXINT lineno, column;
XX{
XX	register INT	seg;
XX	register struct sc_screen	*sc;
XX	register struct	li_line		*line, *newline;
XX	INT      linewidth;
XX	static	 INT	prev_column;

XX	errflag = 0;
XX	sc = &screen;
XX	newline = sc->sc_curline + (lineno - sc->sc_lineno);
XX	/*
XX	 * Boundary checks
XX	 */
XX	if (newline < sc->sc_topline || newline > sc->sc_botline) {
XX		errflag = 1;
XX		botprint(TRUE,"move_cursor, lineno %d beyond screen\n", lineno);
XX		return;
XX	}

XX	if (column == COL_SAME)
XX		column = file_column(newline->li_text, prev_column);
XX	else {
XX		prev_column = -1;
XX		if (column == COL_FIRST_NONWHITE) {
XX			register char *s;

XX			s = newline->li_text;
XX			while (*s != '\0' && isspace(*s))
XX				++s;
XX			column = s - newline->li_text;
XX		}
XX	}

XX				
XX	if (column < 0) { /* If past left side of screen */
XX		if (sc->sc_column == 0) { /* Already at left side? */
XX			errflag = 1;
XX			flash();
XX			return;
XX		}
XX		column = 0;
XX	}

XX	if (lineno != sc->sc_lineno && sc->sc_origline.li_text != NULL)
XX		xmit_curline();

XX	/*
XX	 * Compute screen column and segment #
XX	 */
XX	sc->sc_curline = newline;
XX	sc->sc_lineno = lineno;
XX	/*
XX	 * Limit column to end of line (or line+1 if input mode)
XX	 */
XX	linewidth = newline->li_width + (input_mode ? 1 : 0);
XX	if (column >= linewidth && column > 0) {
XX		column = (linewidth == 0 ? 0 : linewidth-1);
XX		if (sc->sc_column >= column) /* If already at edge */
XX			flash();
XX	}

XX	sc->sc_column = column;
XX	column = screen_column(newline->li_text, column);
XX	if (prev_column < 0)
XX		prev_column = column;
XX	if (input_mode && sc->sc_column == linewidth-1 && sc->sc_column != 0)
XX		++column;

XX	seg = 0;
XX	for (line=sc->sc_topline; line < newline; ++line)
XX		seg += line->li_segments;
XX	seg += column / COLS + sc->sc_abovetop;
XX	column %= COLS;
XX	if (seg >= LINES) {
XX		errflag = 1;
XX		botprint(TRUE, "move_cursor, seg %d beyond screen\n", seg);
XX		return;
XX	}
XX	/*
XX	 * Update cursor to curses
XX	 */
XX	move(seg, column);
XX}
@//E*O*F rv_move.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_openline.c
if test -f rv_openline.c ; then
    echo rv_openline.c exists, putting output in $$rv_openline.c
    OUT=$$rv_openline.c
    STATUS=1
else
    OUT=rv_openline.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_openline.c//'
XX#include "rv.h"
XX#include <ctype.h>

XXboolean opened_line;	 /* Set TRUE if openline() called */
XXINT  autoindent;	 /* Physical autoindent, used by insert() */

XXvoid
XXopenline(direction)
XX/*
XX *  Openline - Open new line.
XX *
XX *  If direction < 0, open above current line, else
XX *                    open below current line.
XX */
XXINT direction;
XX{
XX	register struct li_line	  *line;
XX	register struct sc_screen *sc;
XX	register struct wi_window *wi;
XX	char *s;

XX	sc = &screen;
XX	wi = &window;

XX	file.fi_modified = TRUE;
XX	xmit_curline();
XX	opened_line = TRUE;

XX	/*
XX	 * Calculate autoindent
XX	 */
XX	autoindent = 0;
XX	if (set_autoindent) {
XX		s = sc->sc_curline->li_text;
XX		while (isspace(*s) && *s != '\0')
XX			if (*s++ == '\t')
XX				autoindent += set_tabstops;
XX			else
XX				autoindent++;
XX	}

XX	/*
XX	 * Send blank line to ed
XX	 */
XX	if (direction >= 0) {
XX		xmit_ed("%da\n\n.\n", sc->sc_lineno);
XX		sc->sc_lineno++;
XX		sc->sc_curline++;
XX	} else
XX		xmit_ed("%di\n\n.\n", sc->sc_lineno);

XX	if (sc->sc_curline <= wi->wi_botline ||
XX			wi->wi_botline < &line_array[NUM_WINDOW_LINES-1]) {
XX		/*
XX		 * Case 1,2,3:  Opening line at top of window, within window,
XX		 *              or bottom of expandable window
XX		 */

XX		/*
XX		 * Scroll off bottom line of window if necessary
XX		 */
XX		if (wi->wi_botline >= &line_array[NUM_WINDOW_LINES-1]) {
XX			if (wi->wi_botline->li_text)
XX				free(wi->wi_botline->li_text);
XX			wi->wi_botline->li_text = NULL;
XX			wi->wi_botline--;
XX		}

XX		/*
XX		 * Slide down window beyond line
XX		 */
XX		for (line = wi->wi_botline; line >= sc->sc_curline; --line) {
XX			(line+1)->li_width = line->li_width;
XX			(line+1)->li_segments = line->li_segments;
XX			(line+1)->li_text = line->li_text;
XX		}
XX		wi->wi_botline++;
XX	} else {
XX		/*
XX		 * Case 4: Opening line beyond edge of unexpandable window
XX		 */

XX		sc->sc_curline--;
XX		/*
XX		 * Scroll off topline of window if necessary
XX		 */
XX		if (wi->wi_topline <= &line_array[0]) {
XX			if (wi->wi_topline->li_text)
XX				free(wi->wi_topline->li_text);
XX			wi->wi_topline->li_text = NULL;
XX			wi->wi_topline++;
XX		}

XX		/*
XX		 * Slide up window
XX		 */
XX		for (line = wi->wi_topline; line < sc->sc_curline; ++line) {
XX			(line-1)->li_width = line->li_width;
XX			(line-1)->li_segments = line->li_segments;
XX			(line-1)->li_text = line->li_text;
XX		}
XX		wi->wi_topline--;
XX		sc->sc_topline--;
XX		sc->sc_botline--;
XX	}

XX	/*
XX	 * Create the empty line
XX	 */
XX	line = sc->sc_curline;
XX	line->li_width = 0;
XX	line->li_segments = 1;
XX	line->li_text = xalloc(1);
XX	line->li_text[0] = '\0';

XX	if (line > wi->wi_botline)
XX		wi->wi_botline = line;

XX	file.fi_numlines++;

XX	/*
XX	 * Set up for insert()
XX	 */
XX	sc->sc_firstcol = 0;
XX	sc->sc_lastcol = -1;

XX	/*
XX	 * Remember opened line for later undo
XX	 */
XX	undo.un_validcol = FALSE;
XX	undo.un_firstline = sc->sc_lineno;
XX	undo.un_lastline = sc->sc_lineno;
XX	undo.un_inserted = TRUE;

XX	/*
XX	 * Update line to curses
XX	 */
XX	if (line > sc->sc_botline) {
XX		redraw_screen(sc->sc_botline+1);
XX		move_cursor(sc->sc_lineno, 0);
XX	} else {
XX		move_cursor(sc->sc_lineno, 0);
XX		rv_finsertln(1);
XX		redraw_screen(sc->sc_botline);
XX	}
XX}
@//E*O*F rv_openline.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_put.c
if test -f rv_put.c ; then
    echo rv_put.c exists, putting output in $$rv_put.c
    OUT=$$rv_put.c
    STATUS=1
else
    OUT=rv_put.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_put.c//'
XX#include "rv.h"

XXextern char *realloc();

XXvoid
XXput(direction)
XX/*
XX * Put buffer at cursor.
XX */
XXINT direction; /* Negative if above cursor */
XX{
XX	register struct li_line	  *line;
XX	register struct ya_yank   *yank;
XX	register struct sc_screen *sc;
XX	INT	indx;

XX	sc = &screen;
XX	line = sc->sc_curline;

XX	indx = char_to_yank(yank_cmd);
XX	if (errflag) {
XX		flash();
XX		return;
XX	}
XX	yank = &yank_array[indx];

XX	file.fi_modified = TRUE;
XX	if (yank->ya_type == YANK_EMPTY) {
XX		errflag = 1;
XX		if (yank_cmd == ' ')
XX			flash();
XX		else 
XX			botprint(TRUE, "Register %c is empty", yank_cmd);
XX		return;
XX	}
XX	undo.un_inserted = TRUE;
XX	undo.un_firstline = undo.un_lastline = sc->sc_lineno;
XX	undo.un_validcol = FALSE;
XX	if (yank->ya_type == YANK_COLS) {
XX		/*
XX		 * Put text within line
XX		 */
XX		register char *s, *s2, *s3;

XX		save_Undo();
XX		undo.un_validcol = sc->sc_validcol = TRUE;
XX		undo.un_firstcol = sc->sc_firstcol = sc->sc_column+1;
XX		undo.un_lastcol = sc->sc_lastcol = sc->sc_column+yank->ya_width;
XX		line->li_text = realloc(line->li_text, line->li_width +
XX			yank->ya_width + 1);
XX		s = &line->li_text[sc->sc_firstcol];
XX		s2 = &line->li_text[line->li_width];
XX		s3 = &line->li_text[line->li_width + yank->ya_width];
XX		while (s2 >= s)
XX			*s3-- = *s2--;
XX		s2 = yank->ya_text;
XX		while (*s2)
XX			*s++ = *s2++;
XX		redraw_curline(line->li_text);
XX		move_cursor(sc->sc_lineno, sc->sc_firstcol + yank->ya_width-1);
XX		if (set_fortran && line->li_width > 72) {
XX			botprint(FALSE, "Line is longer than 72 columns");
XX			hitcr_continue();
XX		}
XX	}
XX	else { /* Put text between lines */
XX		sc->sc_validcol = FALSE;
XX		if (yank->ya_type == YANK_SINGLE) {
XX			/*
XX			 * Simple case - put 1 line
XX			 */
XX			openline(direction);
XX			save_Undo();
XX			redraw_curline(yank->ya_text);
XX			move_cursor(sc->sc_lineno, COL_FIRST_NONWHITE);
XX		}
XX		else {
XX			/*
XX			 * put multiple lines
XX			 */
XX			xmit_curline();
XX			xmit_ed("%dr /tmp/yk%d.%d\n", sc->sc_lineno -
XX				(direction >= 0 ? 0 : 1), getpid(), indx);
XX			undo.un_lastline = sc->sc_lineno + yank->ya_numlines-1;
XX			fetch_window(sc->sc_lineno - NUM_WINDOW_LINES/4 -
XX				LINES/2 + 1, TRUE);
XX			botprint(FALSE, "%d more lines", yank->ya_numlines);
XX			hitcr_continue();
XX		}
XX	}
XX}
@//E*O*F rv_put.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_redraw.c
if test -f rv_redraw.c ; then
    echo rv_redraw.c exists, putting output in $$rv_redraw.c
    OUT=$$rv_redraw.c
    STATUS=1
else
    OUT=rv_redraw.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_redraw.c//'
XX#include "rv.h"

XXvoid
XXredraw_screen(firstline)
XX/*
XX * Regenerate the screen from firstline downwards to curses
XX *
XX * If firstline is NULL, the entire screen is redrawn.
XX */
XXstruct	li_line	*firstline;
XX{
XX	register struct   li_line	*line;
XX	register struct	 sc_screen	*sc;
XX	register struct	 wi_window	*wi;
XX	INT	 saveline, savecol, seg;

XX	sc = &screen;
XX	wi = &window;
XX	if (firstline == (struct li_line *)0)
XX		firstline = sc->sc_topline;
XX	/*
XX	 * Save cursor location
XX	 */
XX	saveline = CURLINE;
XX	savecol = CURCOLUMN;
XX	/*
XX	 * Skip void line segments above topline
XX	 */
XX	if (firstline == sc->sc_topline) {
XX		sc->sc_abovetop = 0; /* Reset topline to real screen top */
XX		seg = 0;
XX	} else
XX		seg = sc->sc_abovetop;
XX	/*
XX	 * Skip lines above firstline
XX	 */
XX	for (line=sc->sc_topline; line < firstline; ++line)
XX		seg += line->li_segments;
XX	/*
XX	 * Clear screen from firstline downward
XX	 */
XX	move(seg,0);
XX	clrtobot();
XX	move(seg,0);  /* Because clrtobot homes the cursor in 4bsd */

XX	/*
XX	 * Redraw remaining lines
XX	 */
XX	if (line <= wi->wi_botline)
XX		seg += line->li_segments;
XX	if (seg >= LINES && sc->sc_curline == line) {
XX		/*
XX		 * Scroll
XX		 */
XX		sc->sc_botline = line-1;
XX		rv_scroll(1);
XX		redraw_screen(line+1);
XX		move(saveline, savecol);
XX		return;
XX	}
XX		
XX	while (seg < LINES) {
XX		if (line <= wi->wi_botline) {
XX			print_line(line->li_text);
XX			if (CURCOLUMN != 0 || line->li_text[0] == '\0')
XX				move(CURLINE+1, 0);
XX			++line;
XX		}
XX		if (line > wi->wi_botline) { /* If past bottom of window */
XX			if ((line - sc->sc_curline) + sc->sc_lineno >
XX					file.fi_numlines) /* If past eof */
XX				break;
XX			/*
XX			 * Fetch window & redraw everything
XX			 */
XX			 if (set_debug > 1)
XX				 fprintf(stderr, "Forced to redraw\n");
XX		         fetch_window(sc->sc_lineno - NUM_WINDOW_LINES/4 -
XX				 LINES/2+1, TRUE);
XX		         return;
XX		}
XX		seg += line->li_segments;
XX	}
XX	sc->sc_botline = line-1;

XX	/*
XX	 * Append '~' or '@' lines to screen
XX	 */
XX	if ((seg = CURLINE) < LINES-1) 
XX		if (file.fi_numlines > sc->sc_lineno +
XX				(sc->sc_botline - sc->sc_curline))
XX			/*
XX			 * Undisplayed lines
XX			 */
XX			while (seg < LINES-1)
XX				mvaddch(seg++, 0, '@');
XX		else
XX			/*
XX			 * End of file
XX			 */
XX			while (seg < LINES-1)
XX				mvaddch(seg++, 0, '~');
XX	/*
XX	 * Restore cursor
XX	 */
XX	move(saveline, savecol);
XX}
@//E*O*F rv_redraw.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_redraw_ln.c
if test -f rv_redraw_ln.c ; then
    echo rv_redraw_ln.c exists, putting output in $$rv_redraw_ln.c
    OUT=$$rv_redraw_ln.c
    STATUS=1
else
    OUT=rv_redraw_ln.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_redraw_ln.c//'
XX#include "rv.h"

XXvoid
XXredraw_curline(txt)
XX/*
XX * Redraw the current line using txt.
XX * Update rest of screen as necessary
XX */
XXchar *txt;
XX{
XX	register struct li_line	  *line;
XX	register struct li_line	*line2;
XX	register struct sc_screen *sc;
XX	register INT	seg, i;
XX	char	*oldtxt;

XX	sc = &screen;
XX	line = sc->sc_curline;
XX	seg = line->li_segments;
XX	oldtxt = line->li_text;

XX	/*
XX	 * Rebuild line internally
XX	 */
XX	line->li_width = strlen(txt);
XX	line->li_segments = 1 + (screen_column(txt, line->li_width-1) +
XX		set_list) / COLS;
XX	if (line->li_text != txt) {
XX		line->li_text = xalloc(line->li_width+1);
XX		strcpy(line->li_text, txt);
XX		if (oldtxt)
XX			free(oldtxt);
XX	}

XX	i = sc->sc_abovetop;
XX	for (line = sc->sc_topline; line < sc->sc_curline; ++line)
XX		i += line->li_segments;
XX	move(i, 0);

XX	if (CURLINE+line->li_segments >= LINES) {
XX		/*
XX		 * Line overflowed screen
XX		 */
XX		redraw_screen(line);
XX		return;
XX	}

XX	/*
XX	 * If grew, push down segs below this line
XX	 */
XX	if (line->li_segments > seg) {
XX		i = line->li_segments - seg;
XX		rv_finsertln(i);
XX		/* Redraw pushed off segs */
XX		i = line->li_segments - seg;
XX		line2 = sc->sc_botline;
XX		while (i >= 0) {
XX			i -= line2->li_segments;
XX			--line2;
XX		}
XX		if (line2 <= line)
XX			line2 = line + 1;
XX		redraw_screen(line2);
XX	}

XX	/*
XX	 * Clear segments and redraw
XX	 */
XX	clrtoeol();
XX	for (i=line->li_segments; i > 1; --i) {
XX		move(CURLINE+1, 0);
XX		clrtoeol();
XX	}
XX	/*
XX	 * Move to first seg of line
XX	 */
XX	if (line->li_segments > 1)
XX		move(CURLINE-line->li_segments+1, 0);

XX	/*
XX	 * Draw line
XX	 */
XX	i = CURLINE;
XX	print_line(line->li_text);
XX	if (seg <= line->li_segments)
XX		return;

XX	/*
XX	 * Shrunk, delete surplus segs
XX	 */
XX	move(i+line->li_segments, 0);
XX	i = seg - line->li_segments;
XX	rv_fdeleteln(i);
XX	redraw_screen(sc->sc_botline+1);
XX}
@//E*O*F rv_redraw_ln.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_scroll.c
if test -f rv_scroll.c ; then
    echo rv_scroll.c exists, putting output in $$rv_scroll.c
    OUT=$$rv_scroll.c
    STATUS=1
else
    OUT=rv_scroll.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_scroll.c//'
XX#include "rv.h"

XXvoid
XXrv_scroll(n)
XX/*
XX * Scroll n lines
XX * Must be within window
XX * Cursor is set to last line
XX */
XXregister INT n;
XX{
XX	register struct li_line   *line, *oldline;
XX	register struct sc_screen *sc;
XX	register INT	seg,newseg,i;
XX	register struct wi_window *wi;

XX	sc = &screen;
XX	wi = &window;
XX	/*
XX	 * Set cursor to bottom line+1
XX	 */
XX	newseg = 0;
XX	for (line = sc->sc_topline; line <= sc->sc_botline; ++line)
XX		newseg += line->li_segments;
XX	newseg += sc->sc_abovetop;
XX	move(newseg,0);
XX	clrtobot();
XX	/*
XX	 * Calculate number of segments to scroll in
XX	 */
XX	seg = 0;
XX	for (i=n; i > 0 && line <= wi->wi_botline; --i, ++line)
XX		seg += line->li_segments;
XX	seg -= LINES-newseg-1;
XX	move(LINES-1,0);
XX	rv_fscroll(seg);
XX	move(newseg-seg,0);
XX	/*
XX	 * Scroll in new line(s)
XX	 */
XX	for (line = sc->sc_botline+1; n > 0; --n, ++line) {
XX		if (line > wi->wi_botline) {
XX			errflag = 1;
XX			botprint(TRUE, "rv_scroll - past bottom of window\n\n");
XX			hitcr_continue();
XX			return;
XX		}
XX		print_line(line->li_text);
XX		if (CURCOLUMN != 0 || line->li_text[0] == '\0') {
XX			if (CURLINE == LINES-1) {
XX				move(LINES-1, 0);
XX			} else
XX				move(CURLINE+1, 0);
XX		}
XX	}
XX	/*
XX	 * Adjust screen params
XX	 */
XX	xmit_curline();
XX	--line;
XX	sc->sc_lineno += (line - sc->sc_curline);
XX	sc->sc_botline = line;
XX	sc->sc_curline = line;
XX	sc->sc_column = 0;

XX	/*
XX	 * Compute new top line
XX	 */
XX	for (seg = line->li_segments; seg < LINES;
XX			seg += line->li_segments) {
XX		--line;
XX		if (line < wi->wi_topline)
XX			break;
XX	}
XX	sc->sc_topline = line+1;
XX	/*
XX	 * Compute # of displayed segs above top line
XX	 */
XX	if (line >= wi->wi_topline)
XX		sc->sc_abovetop = LINES-1 - (seg - line->li_segments);
XX}
@//E*O*F rv_scroll.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_scroll_bk.c
if test -f rv_scroll_bk.c ; then
    echo rv_scroll_bk.c exists, putting output in $$rv_scroll_bk.c
    OUT=$$rv_scroll_bk.c
    STATUS=1
else
    OUT=rv_scroll_bk.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_scroll_bk.c//'
XX#include "rv.h"

XXvoid
XXrv_scroll_backward(n)
XX/*
XX * Scroll n lines backward
XX * Must be within window
XX * Cursor location is undefined
XX */
XXregister n;
XX{
XX	register struct li_line   *line, *newline;
XX	register struct sc_screen *sc;
XX	register INT	seg;
XX	register struct wi_window *wi;
XX	register struct fi_file	  *fi;

XX	sc = &screen;
XX	wi = &window;
XX	fi = &file;
XX	seg = 0;
XX	for (line = sc->sc_topline-1; n > 0; --n, --line) {
XX		if (line < wi->wi_topline) {
XX			errflag = 1;
XX			botprint(TRUE,
XX			    "rv_scroll_backward - past top of window\n\n");
XX			hitcr_continue();
XX			return;
XX		}
XX		seg += line->li_segments;
XX	}
XX	++line;
XX	move(0,0);
XX	seg -= sc->sc_abovetop;
XX	rv_finsertln(seg);
XX	move(0,0);
XX	for (newline = line; newline < sc->sc_topline; ++newline) {
XX		print_line(newline->li_text);
XX		if (CURCOLUMN != 0 || newline->li_text[0] == '\0')
XX			move(CURLINE+1, 0);
XX	}
XX	xmit_curline();
XX	sc->sc_lineno = sc->sc_lineno - (sc->sc_curline - line);
XX	sc->sc_topline = line;
XX	sc->sc_curline = line;
XX	sc->sc_column = 0;
XX	sc->sc_abovetop = 0;

XX	/*
XX	 * Compute bottom line
XX	 */
XX	for (seg = line->li_segments; seg < LINES;
XX			seg += line->li_segments) {
XX		++line;
XX		if (line > wi->wi_botline)
XX			break;
XX	}
XX	sc->sc_botline = line-1;

XX	if (line <= wi->wi_botline)
XX		seg -= line->li_segments;
XX	move(seg, 0);
XX	clrtobot();
XX	move(seg, 0); /* Because clrtobot homes the cursor in 4bsd */
XX	/*
XX	 * Append '~' or '@' lines to screen
XX	 */
XX	if (seg < LINES-1) 
XX		if (fi->fi_numlines > sc->sc_lineno +
XX				(sc->sc_botline - sc->sc_curline))
XX		/*
XX		 * Undisplayed lines
XX		 */
XX		while (seg < LINES-1)
XX			mvaddch(seg++, 0, '@');
XX	else
XX		/*
XX		 * End of file
XX		 */
XX		while (seg < LINES-1)
XX			mvaddch(seg++, 0, '~');
XX	move(0,0);
XX}
@//E*O*F rv_scroll_bk.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_search.c
if test -f rv_search.c ; then
    echo rv_search.c exists, putting output in $$rv_search.c
    OUT=$$rv_search.c
    STATUS=1
else
    OUT=rv_search.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_search.c//'
XX#include "rv.h"
XX#include "regexp.h"

XX#ifdef CRAY
XX#define move_cursor_flag   mc_flag
XX#endif

XXstatic char prev_search[256];   /* Buffer holding previous search string */
XXstatic char buf[256];		/* Buffer holding current search string */
XXstatic regexp *cmp;		/* Compiled regular expression (RE) */

XXboolean
XXsearch(direction, txt, move_cursor_flag)
XX/*
XX * Search file for match
XX *
XX * Scan current line using regexec() for txt
XX * If not found, xmit search request to ed
XX *      Scan line that ed finds using regex()
XX * Put cursor at new location, if move_cursor_flag
XX */
XXINT  direction;   /* Direction of search (-1, 1) */
XXchar *txt;        /* Regular expression to search for */
XXboolean move_cursor_flag; /* TRUE if cursor to be moved to match */
XX{
XX	register struct sc_screen *sc;
XX	register char *s, *s2;
XX	register INT i, ch;
XX	struct li_line   *line;
XX	INT offset = 0;
XX	char *found, numbuf[20];

XX	sc = &screen;
XX	sc->sc_validcol = TRUE;
XX	sc->sc_firstcol = sc->sc_lastcol = sc->sc_column;
XX	sc->sc_firstline = sc->sc_lastline = sc->sc_lineno;

XX	if (txt == NULL)
XX		return FALSE;
XX	strcpy(buf, txt);
XX	if (direction >= 0)
XX		ch = '/';
XX	else
XX		ch = '?';
XX	s = buf;
XX	/*
XX	 * Scan for first / or ? not preceeded by an odd number of backslashes
XX	 */
XX	i = 0;
XX	while (*s != '\0' && (*s != ch || i & 1)) {
XX		i = *s == '\\' ? i+1 : 0;
XX		++s;
XX	}
XX	/*
XX	 * Drop '\0' into matching / or ?
XX	 */
XX	if (*s != '\0')
XX		*s++ = '\0';
XX	ch = *s;

XX	/*
XX	 * Check for +/- offset
XX	 */
XX	if (ch == '+' || ch == '-') {
XX		offset = atoi(s);
XX		if (offset == 0 && *(s+1) != '0')
XX			offset = 1;
XX		if (*s == '-')
XX			offset = -offset;
XX		sc->sc_validcol = FALSE;
XX	}

XX	if (*buf == '\0')
XX		strcpy(buf, prev_search);
XX	if (*buf == '\0') {
XX		botprint(TRUE, "No remembered search string");
XX		return FALSE;
XX	}
XX	/*
XX	 * Compile RE
XX	 */
XX	if (cmp)
XX		free(cmp);
XX	if ((cmp = regcomp(buf)) == 0) {
XX		return FALSE;
XX	}

XX	strcpy(prev_search, buf);

XX	line = sc->sc_curline;
XX	s = &line->li_text[sc->sc_column];
XX	found = NULL;
XX	if (direction >= 0) {
XX		/*
XX		 * Search current line after cursor 
XX		 */
XX		if (*buf != '^' && *++s != '\0')
XX			if (regexec(cmp, s) != 0) {
XX				found = cmp->startp[0];
XX				sc->sc_lastcol = found - line->li_text - 1;
XX			}
XX	} else {
XX		/*
XX		 * Search current line before cursor
XX		 */
XX		s2 = line->li_text;
XX		while (s2 < s) {
XX			if (regexec(cmp, s2) == 0 || cmp->startp[0] >= s)
XX				break;
XX			found = cmp->startp[0];
XX			if (*buf == '^') /* If anchored */
XX				break;
XX			s2 = cmp->startp[0]+1;
XX		}
XX		if (found) {
XX			sc->sc_lastcol--;
XX			sc->sc_firstcol = found - line->li_text;
XX		}
XX	}

XX	if (found) {
XX		/*
XX		 * Found match on current line
XX		 */
XX		 if (offset != 0) {
XX			/*
XX			 * Line offset requested from current line (sigh)
XX			 */
XX			sc->sc_validcol = FALSE;
XX			if ((i = sc->sc_lineno + offset) < 1) {
XX				botprint(TRUE, "Negative address");
XX				return FALSE;
XX			}
XX			if (i > file.fi_numlines) {
XX				botprint(TRUE, "Not that many lines in buffer");
XX				return FALSE;
XX			}
XX			if (i < sc->sc_lineno)
XX				sc->sc_firstline = i;
XX			else if (i > sc->sc_lineno)
XX				sc->sc_lastline = i-1;
XX			if (move_cursor_flag)
XX				move_abs_cursor(i, COL_FIRST_NONWHITE);
XX			return TRUE;
XX		}
XX		if (move_cursor_flag)
XX			if (sc->sc_firstcol != sc->sc_column)
XX				move_cursor(sc->sc_lineno, sc->sc_firstcol);
XX			else
XX				move_cursor(sc->sc_lineno, sc->sc_lastcol+1);
XX		return TRUE;
XX        }

XX	sc->sc_validcol = FALSE;
XX	/*
XX	 * Xmit search to ed
XX	 */
XX	xmit_curline();
XX	i = sc->sc_lineno;
XX	if (direction >= 0)
XX		xmit_ed("%d\n/%s/\n", i, buf);
XX	else
XX		xmit_ed("%d\n?%s?\n", i, buf);
XX	xmit_sync();
XX	xmit_ed(".=\n");
XX	(void) recv_sync(FALSE);
XX	(void) fgets(numbuf, 18, file.fi_fpin);
XX	if ((i = atoi(numbuf)) == sc->sc_lineno) {
XX		botprint(TRUE, "Pattern not found");
XX		return FALSE;
XX	}
XX	if (set_wrapscan == FALSE && 
XX	    ((direction > 0 && i < sc->sc_lineno) ||
XX	     (direction < 0 && i > sc->sc_lineno))) { /* If wrapped */
XX		botprint(TRUE, "Address search hit %s without matching pattern",
XX			direction < 0 ? "TOP" : "BOTTOM");
XX		return FALSE;
XX	}
XX		
XX	i += offset;

XX	if (i < 1) {
XX		botprint(TRUE, "Negative address");
XX		return FALSE;
XX	}
XX	if (i > file.fi_numlines) {
XX		botprint(TRUE, "Not that many lines in buffer");
XX		return FALSE;
XX	}

XX	if (i < sc->sc_lineno)
XX		sc->sc_firstline = i;
XX	else if (i > sc->sc_lineno)
XX		sc->sc_lastline = i-1;
XX	if (!move_cursor_flag)
XX		return TRUE;
XX		
XX	/*
XX	 * Cursor movement requested
XX	 */

XX	/*
XX	 * Move to line,col of match
XX	 */
XX	if (offset != 0) {
XX		move_abs_cursor(i, COL_FIRST_NONWHITE);
XX		return TRUE;
XX	}
XX	move_abs_cursor(i, 0);
XX	line = sc->sc_curline;
XX	if (direction >= 0) {
XX		if (regexec(cmp, line->li_text) != 0)
XX			sc->sc_column = cmp->startp[0] - line->li_text;
XX	} else {
XX		s2 = line->li_text;
XX		found = NULL;
XX		while (*s2 != '\0') {
XX			if (regexec(cmp, s2) == 0)
XX				break;
XX			found = cmp->startp[0];
XX			if (*buf == '^') /* If anchored */
XX				break;
XX			s2 = cmp->startp[0]+1;
XX		}
XX		if (found)
XX			sc->sc_column = found - line->li_text;
XX	}
XX	move_cursor(sc->sc_lineno, sc->sc_column);
XX	return TRUE;
XX}
@//E*O*F rv_search.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_shell.c
if test -f rv_shell.c ; then
    echo rv_shell.c exists, putting output in $$rv_shell.c
    OUT=$$rv_shell.c
    STATUS=1
else
    OUT=rv_shell.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_shell.c//'
XX#include "rv.h"
XX#include <signal.h>

XX#ifndef USG
XX#  define strchr index
XX#endif

XX/*
XX * This entire module is a hack
XX */

XXextern boolean	scrolled;

XXextern char *strchr();

XXrv_shell(cmd)
XXchar *cmd;
XX{
XX	INT cpid, len, infd, outfd;
XX	char buf[513], *s;
XX	int (*prev_func)();
XX#ifdef USG
XX	struct termio tm;
XX#endif
XX	
XX	xmit_sync();
XX	(void) recv_sync(FALSE);
XX	xmit_ed("!sh -c '%s' ; echo '@''$''#'\n", cmd);
XX	fflush(file.fi_fpout);
XX	if (file.fi_modified)
XX		botprint(FALSE, "[No write since last change]");
XX	move(LINES-1, 0);
XX	rv_fscroll(1);
XX	move(LINES-1, 0);
XX	refresh();

XX	/* prev_func = signal(SIGINT, SIG_IGN);  Use at your own risk */
XX	if (use_linemode) {
XX#ifdef USG
XX		nocbreak();
XX#else
XX		nocrmode();
XX#endif
XX		nl();
XX		echo();
XX#ifdef TCGETA             /* Echo doesn't in System V, sigh */
XX		ioctl(0, TCGETA, &tm);
XX		tm.c_lflag |= ECHO;
XX		ioctl(0, TCSETA, &tm);
XX#endif
XX		if (set_debug > 2)
XX			printf("Using line mode.\n");
XX	}
XX	infd = atoi(Argv[1]);
XX	outfd = atoi(Argv[2]);
XX	if ((cpid = fork()) < 0)
XX		panic("Can't fork");
XX	if (cpid == 0) { /* Child */
XX		for (;;) {
XX			if ((len = read(0, buf, 512)) < 0)
XX				_exit(0);
XX			if (len == 0)
XX				write(outfd, "\004\n", 2);
XX			else
XX				write(outfd, buf, len);
XX		}
XX		/*NOTREACHED*/
XX	}
XX	for (;;) { /*  Parent */
XX		if ((len = read(infd, buf, 512)) <= 0)
XX			panic("EOF on read from pipe");
XX		if ((s = strchr(buf, '@')) != NULL) {
XX			if (s-buf+1 >= len) {
XX				write(1, buf, len);
XX				len = read(infd, buf, 512);
XX				s = buf;
XX			}
XX			if (*++s == '$') {
XX				if (s-buf+1 >= len) { 
XX					write(1, buf, len);
XX					len = read(infd, buf, 512);
XX					s = buf;
XX				}
XX				if (*++s == '#') {
XX					if (s-buf >= 3)
XX						write(1, buf, s-buf-2);
XX					kill(cpid, 9);
XX					while (wait((int *)0) != cpid)
XX						;
XX					break;
XX				}
XX			}
XX		}
XX		write(1, buf, len);
XX	}
XX	if (use_linemode) {
XX#ifdef USG
XX		cbreak();
XX#else
XX		crmode();
XX#endif
XX		nonl();
XX		noecho();
XX	}
XX	/* (void) signal(SIGINT, prev_func);  Use at your own risk */
XX	refresh();
XX	scrolled = TRUE;
XX	hitcr_continue();
XX	clearok(curscr, TRUE);
XX	redraw_screen((struct li_line *)0);
XX	move_cursor(screen.sc_lineno, screen.sc_column);
XX}
@//E*O*F rv_shell.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_sync.c
if test -f rv_sync.c ; then
    echo rv_sync.c exists, putting output in $$rv_sync.c
    OUT=$$rv_sync.c
    STATUS=1
else
    OUT=rv_sync.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_sync.c//'
XX#include "rv.h"

XX/*
XX * Synchronize communication by sending a command
XX * with a recognizable response.
XX */

XXvoid
XXxmit_sync()
XX/*
XX * Transmit sync
XX *
XX * A sync consists of transmitting two f commands followed
XX * by an illegal command, and waiting to receive the file name echoed
XX * twice followed by a question mark.
XX */
XX{
XX	if (fputs("f\nf\nzzz\n", file.fi_fpout) == NULL)
XX		panic("Error while writing to ed\n\n");
XX}

XXboolean
XXrecv_sync(disp_flag)
XX/*
XX * Wait for sync to come back
XX *
XX * Returns TRUE if no errors received prior to sync, else
XX *	 displays errors if disp_flag is TRUE.
XX */
XXboolean disp_flag;
XX{
XX	register char buf[512];
XX	register INT i, namematch = 0, errcount = 0;
XX	INT old_alarm;
XX	extern alarmring();

XX	old_alarm = alarm(RV_TIMEOUT);

XX	fflush(file.fi_fpout);
XX	for (;;) {
XX		if (fgets(buf, 511, file.fi_fpin) == NULL)
XX			panic("Error while reading from ed\n\n");
XX		/*
XX		 * Strip trailing \n
XX		 */
XX		if ((i = strlen(buf)) > 0 && buf[i-1] == '\n')
XX			buf[--i] = '\0';
XX		if (buf[0] == '?') {
XX			if (namematch > 1)
XX				goto found;
XX			/*
XX			 * Display error
XX			 */
XX			++errcount;
XX			if (file.fi_sysv) {
XX				if (buf[1] != ' ' ||
XX						file.fi_cray == FALSE)
XX					fgets(buf, 511, file.fi_fpin);
XX				if (disp_flag)
XX					botprint(TRUE, "%s", buf);
XX			}
XX			else
XX				if (disp_flag)
XX					botprint(TRUE, "Failed ");
XX			namematch = 0;
XX			continue;
XX		}
XX		/*
XX		 * Look for file name echoed twice
XX		 */
XX		if (strcmp(buf, file.fi_name) == 0) 
XX			++namematch;
XX		else
XX			namematch = 0;
XX		if (namematch >= 2) {
XX			(void) fgets(buf, 511, file.fi_fpin);
XX			if ((i = strlen(buf)) > 0 && buf[i-1] == '\n')
XX				buf[--i] = '\0';
XX			/*
XX			 * Look for question mark
XX			 */
XX			if (buf[0] == '?') {
XX		found:
XX				if (file.fi_sysv &&
XX				    (buf[1] != ' ' || file.fi_cray == FALSE))
XX					/*
XX					 * Skip error msg
XX					 */
XX					fgets(buf, 511, file.fi_fpin);
XX				break;
XX			}
XX			else {
XX				if (disp_flag > 1)
XX					botprint(FALSE, "%s", file.fi_name);
XX				if (strcmp(buf, file.fi_name)) {
XX					if (disp_flag > 1)
XX					    botprint(FALSE, "%s", file.fi_name);
XX					namematch = 0;
XX				}
XX			}
XX		}
XX		if (disp_flag > 1 && namematch == 0)
XX			botprint(FALSE, "%s", buf);
XX	}
XX	alarm(old_alarm);

XX	return (errcount == 0);
XX}
@//E*O*F rv_sync.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rv_undo.c
if test -f rv_undo.c ; then
    echo rv_undo.c exists, putting output in $$rv_undo.c
    OUT=$$rv_undo.c
    STATUS=1
else
    OUT=rv_undo.c
fi
sed 's/^XX//' > $OUT <<'@//E*O*F rv_undo.c//'
XX#include "rv.h"

XXvoid
XXrv_undo()
XX/*
XX * undo last change
XX *
XX * undo is accomplished by deleting the last inserted text, and
XX * restoring the last deleted text, both of which are assumed
XX * to start at the same row,col position.
XX */
XX{
XX	struct ya_yank	 *yank, *save_yank;
XX	boolean deleted;
XX	void rv_linecmd();
XX	INT direction = -1;

XX	if (ed_undo) {
XX		rv_linecmd("u");
XX		ed_undo = TRUE;
XX		return;
XX	}
XX		
XX	yank = &yank_array[0];
XX	save_yank = &yank_array[NUM_YANK_BUFS-1];

XX	/*
XX	 * See if there is something to undo
XX	 */
XX	if (undo.un_deleted == FALSE && undo.un_inserted == FALSE) {
XX		flash();
XX		errflag = 1;
XX		return;
XX	}

XX	/*
XX	 * Save previous yanked (deleted) text
XX	 */
XX	copy((char *)save_yank, (char *)yank, sizeof(struct ya_yank));
XX	if (yank->ya_text) {
XX		save_yank->ya_text = xalloc(strlen(yank->ya_text)+1);
XX		strcpy(save_yank->ya_text, yank->ya_text);
XX	}
XX	deleted = undo.un_deleted;
XX	undo.un_deleted = FALSE;

XX	if (undo.un_firstline > file.fi_numlines) {
XX		direction = 1;
XX		undo.un_firstline = file.fi_numlines;
XX	}

XX	move_abs_cursor(undo.un_firstline, 0);
XX	/*
XX	 * Delete last inserted text
XX	 */
XX	if (undo.un_inserted) {
XX		register struct sc_screen *sc;

XX		sc = &screen;
XX		sc->sc_firstline = undo.un_firstline;
XX		sc->sc_lastline = undo.un_lastline;
XX		if (undo.un_validcol == FALSE)
XX			sc->sc_validcol = FALSE;
XX		else {
XX			sc->sc_validcol = TRUE;
XX			sc->sc_firstcol = undo.un_firstcol;
XX			sc->sc_lastcol = undo.un_lastcol;
XX		}
XX		undo.un_inserted = FALSE;
XX		delete();
XX	}
XX	/*
XX	 * Restore last deleted text
XX	 */
XX	if (deleted && save_yank->ya_type != YANK_EMPTY) {
XX		move_abs_cursor(undo.un_firstline, 0);
XX		if (save_yank->ya_type == YANK_COLS)
XX			screen.sc_column = undo.un_firstcol-1;
XX		yank_cmd = '$';
XX		put(direction);
XX	}

XX	/*
XX	 * Free saved yank text
XX	 */
XX	if (save_yank->ya_text) {
XX		free(save_yank->ya_text);
XX		save_yank->ya_text = NULL;
XX	}
XX	save_yank->ya_type = YANK_EMPTY;
XX}



XXvoid
XXsave_Undo()
XX/*
XX * Save current line into Undo buffer
XX */
XX{
XX	register struct li_line   *line;
XX	register struct sc_screen *sc;

XX	sc = &screen;
XX	line = sc->sc_curline;
XX	file.fi_modified = TRUE;
XX	if (sc->sc_origline.li_text == NULL) {
XX		/*
XX		 * Copy line into Undo buffer
XX		 */
XX		sc->sc_origline.li_text = xalloc(line->li_width+1);
XX		sc->sc_origline.li_segments = line->li_segments;
XX		sc->sc_origline.li_width = line->li_width;
XX		strcpy(sc->sc_origline.li_text, line->li_text);
XX	}
XX}


XXvoid
XXtoss_undo()
XX/*
XX * Forget last undo operation
XX */
XX{
XX	struct ya_yank *yank;

XX	yank = &yank_array[0];
XX	undo.un_inserted = FALSE;
XX	undo.un_deleted = FALSE; 
XX	undo.un_validcol = FALSE;
XX	if (yank->ya_text) {
XX		free(yank->ya_text);
XX		yank->ya_text = NULL;
XX	}
XX	yank->ya_type = YANK_EMPTY;
XX	ed_undo = FALSE;
XX}
@//E*O*F rv_undo.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo Inspecting for damage in transit...
temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
     500    1357   10031 rv_insert.c
     324     848    5971 rv_linecmd.c
     153     375    3006 rv_misc.c
     280     887    6189 rv_move.c
     146     365    3019 rv_openline.c
      91     256    2163 rv_put.c
     107     315    2256 rv_redraw.c
      95     238    1757 rv_redraw_ln.c
      81     239    1642 rv_scroll.c
      83     234    1684 rv_scroll_bk.c
     230     748    4959 rv_search.c
     112     298    2092 rv_shell.c
     108     321    2191 rv_sync.c
     137     326    2671 rv_undo.c
    2447    6807   49631 total
!!!
wc $FILES | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if test -s $dtemp ; then
    echo "Ouch [diff of wc output]:"
    cat $dtemp
    STATUS=1
elif test $STATUS = 0 ; then
    echo "No problems found."
else
    echo "WARNING -- PROBLEMS WERE FOUND..."
fi
exit $STATUS