[comp.sources.amiga] v89i131: stevie - vi editor clone v3.6, Part02/06

page%swap@Sun.COM (Bob Page) (05/12/89)

Submitted-by: grwalter@watmath.waterloo.edu (Fred Walter)
Posting-number: Volume 89, Issue 131
Archive-name: editors/stevie36.2

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	cmdline.c
#	dec.c
#	dos.c
#	dos.h
#	edit.c
#	env.h
#	fileio.c
#	format_l.c
#	help.c
#	inc.c
#	keymap.h
#	linefunc.c
#	macros.h
#	main.c
# This is archive 2 of a 6-part kit.
# This archive created: Thu May 11 19:41:25 1989
echo "extracting cmdline.c"
sed 's/^X//' << \SHAR_EOF > cmdline.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
Xstatic char    *altfile = NULL;	/* alternate file */
Xstatic int      altline;	/* line # in alternate file */
X
Xstatic char    *nowrtmsg = "No write since last change (use ! to override)";
X
Xextern char   **files;		/* used for "n" and "rew" */
Xextern int      curfile;
Xextern int      numfiles;
X
X/*
X * The next two variables contain the bounds of any range given in a command.
X * If no range was given, both contain null line pointers. If only a single
X * line was given, u_pos will contain a null line pointer. 
X */
Xstatic LPtr     l_pos, u_pos;
X
Xstatic bool_t   interactive;	/* TRUE if we're reading a real command line */
X
Xstatic bool_t   doecmd();
Xstatic void
Xbadcmd(), doshell(), get_range();
Xstatic LPtr    *get_line();
X
X#ifdef  MEGAMAX
Xoverlay "cmdline"
X#endif
X
X/*
X * readcmdline() - accept a command line starting with ':', '/', or '?' 
X *
X * readcmdline() accepts and processes colon commands and searches. If
X * 'cmdline' is null, the command line is read here. Otherwise, cmdline
X * points to a complete command line that should be used. This is used in
X * main() to handle initialization commands in the environment variable
X * "EXINIT". 
X */
Xvoid
Xreadcmdline(firstc, cmdline)
X    char            firstc;	/* either ':', '/', or '?' */
X    char           *cmdline;	/* optional command string */
X{
X    char            c;
X    char            buff[CMDBUFFSIZE];
X    char            cmdbuf[CMDBUFFSIZE];
X    char            argbuf[CMDBUFFSIZE];
X    char           *p, *q, *cmd, *arg;
X    bool_t          literal_next_flag = FALSE;
X
X    /*
X     * Clear the range variables. 
X     */
X    l_pos.linep = (LINE *) NULL;
X    u_pos.linep = (LINE *) NULL;
X
X    interactive = (cmdline == NULL);
X
X    if (interactive)
X	gotocmdline(YES, firstc);
X    p = buff;
X    if (firstc != ':')
X	*p++ = firstc;
X
X    if (interactive) {
X	/* collect the command string, handling '\b' and @ */
X	for (;;) {
X	    c = vgetc();
X	    if (c == CTRL('V') && !literal_next_flag) {
X		literal_next_flag = TRUE;
X		outchar('^');
X		continue;
X	    }
X	    if (c == '\n' || ((c == '\r' || c == ESC) && (!literal_next_flag)))
X		break;
X	    if ((c == '\b') && (!literal_next_flag)) {
X		if (p > buff + (firstc != ':')) {
X		    p--;
X		    /*
X		     * this is gross, but it relies only on 'gotocmdline' 
X		     */
X		    gotocmdline(YES, firstc == ':' ? ':' : NUL);
X		    for (q = buff; q < p; q++)
X			outstr(chars[*q].ch_str);
X		} else {
X		    msg("");
X		    return;	/* back to cmd mode */
X		}
X		continue;
X	    }
X	    if ((c == '@') && (!literal_next_flag)) {
X		p = buff;
X		gotocmdline(YES, firstc);
X		continue;
X	    }
X	    if (literal_next_flag) {
X		literal_next_flag = FALSE;
X		outchar('\b');
X	    }
X	    outstr(chars[c].ch_str);
X	    *p++ = c;
X	}
X	*p = '\0';
X    } else {
X	if (strlen(cmdline) > CMDBUFFSIZE - 2)	/* should really do something
X						 * better here... */
X	    return;
X	strcpy(p, cmdline);
X    }
X
X    /* skip any initial white space */
X    for (cmd = buff; *cmd != NUL && isspace(*cmd); cmd++);
X
X    /* search commands */
X    c = *cmd;
X    if (c == '/' || c == '?') {
X	cmd++;
X	/* was the command was '//' or '??' (I.E. repeat last search) */
X	if ((*cmd == c) || (*cmd == NUL)) {
X	    if (c == '/')
X		searchagain(FORWARD);
X	    else
X		searchagain(BACKWARD);
X	    return;
X	}
X	/* If there is a matching '/' or '?' at the end, toss it */
X	p = strchr(cmd, NUL);
X	if (*(p - 1) == c && *(p - 2) != '\\')
X	    *(p - 1) = NUL;
X	dosearch((c == '/') ? FORWARD : BACKWARD, cmd);
X	return;
X    }
X    /*
X     * Parse a range, if present (and update the cmd pointer). 
X     */
X    get_range(&cmd);
X    if (l_pos.linep != NULL) {
X	if (LINEOF(&l_pos) > LINEOF(&u_pos)) {
X	    emsg("Invalid range");
X	    return;
X	}
X    }
X    strcpy(cmdbuf, cmd);	/* save the unmodified command */
X
X    /* isolate the command and find any argument */
X    for (p = cmd; *p != NUL && !isspace(*p); p++);
X    if (*p == NUL)
X	arg = NULL;
X    else {
X	*p = NUL;
X	for (p++; *p != NUL && isspace(*p); p++);
X	if (*p == NUL) {
X	    arg = NULL;
X	} else {
X	    strcpy(argbuf, p);
X	    arg = argbuf;
X	}
X    }
X
X    if (strcmp(cmd, "q!") == 0) {
X	getout(0);
X    }
X    if (strcmp(cmd, "q") == 0) {
X	if (Changed) {
X	    emsg(nowrtmsg);
X	} else {
X	    getout(0);
X	}
X	return;
X    }
X    if (strcmp(cmd, "w") == 0) {
X	if (arg == NULL) {
X	    if (Filename != NULL) {
X		if (!writeit(Filename, &l_pos, &u_pos)) {
X		    emsg("Problems occured while writing output file");
X		}
X	    } else {
X		emsg("No output file");
X	    }
X	} else {
X	    (void) writeit(arg, &l_pos, &u_pos);
X	}
X	return;
X    }
X    if (strcmp(cmd, "wq") == 0) {
X	if (Filename != NULL) {
X	    if (writeit(Filename, (LPtr *) NULL, (LPtr *) NULL)) {
X		getout(0);
X	    }
X	} else {
X	    emsg("No output file");
X	}
X	return;
X    }
X    if (strcmp(cmd, "x") == 0) {
X	if (Changed) {
X	    if (Filename != NULL) {
X		if (!writeit(Filename, (LPtr *) NULL, (LPtr *) NULL)) {
X		    emsg("Problems occured while writing output file");
X		    return;
X		}
X	    } else {
X		emsg("No output file");
X		return;
X	    }
X	}
X	getout(0);
X    }
X    if (strcmp(cmd, "f") == 0 && arg == NULL) {
X	fileinfo();
X	return;
X    }
X    if (*cmd == 'n') {
X	if ((curfile + 1) < numfiles) {
X	    /*
X	     * stuff ":e[!] FILE\n" 
X	     */
X	    stuffReadbuff(":e");
X	    if (cmd[1] == '!')
X		stuffReadbuff("!");
X	    stuffReadbuff(" ");
X	    stuffReadbuff(files[++curfile]);
X	    stuffReadbuff("\n");
X	} else
X	    emsg("No more files!");
X	return;
X    }
X    if (*cmd == 'p') {
X	if (curfile > 0) {
X	    /*
X	     * stuff ":e[!] FILE\n" 
X	     */
X	    stuffReadbuff(":e");
X	    if (cmd[1] == '!')
X		stuffReadbuff("!");
X	    stuffReadbuff(" ");
X	    stuffReadbuff(files[--curfile]);
X	    stuffReadbuff("\n");
X	} else
X	    emsg("No more files!");
X	return;
X    }
X    if (strncmp(cmd, "rew", 3) == 0) {
X	if (numfiles <= 1)	/* nothing to rewind */
X	    return;
X	curfile = 0;
X	/*
X	 * stuff ":e[!] FILE\n" 
X	 */
X	stuffReadbuff(":e");
X	if (cmd[3] == '!')
X	    stuffReadbuff("!");
X	stuffReadbuff(" ");
X	stuffReadbuff(files[0]);
X	stuffReadbuff("\n");
X	return;
X    }
X    if (strcmp(cmd, "e") == 0) {
X	if (Changed)
X	    emsg(nowrtmsg);
X	else
X	    (void) doecmd(arg);
X	return;
X    }
X    if (strcmp(cmd, "e!") == 0) {
X	(void) doecmd(arg);
X	return;
X    }
X    if (strcmp(cmd, "f") == 0) {
X	Filename = strsave(arg);
X	filemess("");
X	return;
X    }
X    if (strcmp(cmd, "r") == 0 || strcmp(cmd, ".r") == 0) {
X	if (arg == NULL) {
X	    badcmd();
X	    return;
X	}
X	if (readfile(arg, Curschar, 1)) {
X	    emsg("Can't open file");
X	    return;
X	}
X	CHANGED;
X	return;
X    }
X    if (strcmp(cmd, ".=") == 0) {
X	smsg("line %d", cntllines(Filemem, Curschar));
X	return;
X    }
X    if (strcmp(cmd, "$=") == 0) {
X	smsg("%d", cntllines(Filemem, Fileend) - 1);
X	return;
X    }
X    if (strncmp(cmd, "ta", 2) == 0) {
X	dotag(arg, cmd[2] == '!');
X	return;
X    }
X    if (strcmp(cmd, "set") == 0) {
X	doset(arg, interactive);
X	return;
X    }
X    if (strcmp(cmd, "help") == 0) {
X	if (help())
X	    s_clear();
X	return;
X    }
X    if (strcmp(cmd, "version") == 0) {
X	extern char    *Version;
X
X	msg(Version);
X	return;
X    }
X    if (strcmp(cmd, "sh") == 0) {
X	doshell();
X	return;
X    }
X    if (strncmp(cmd, "d", 1) == 0) {
X	LINE           *cp;
X	int             n;
X
X	if (l_pos.linep == NULL)
X	    l_pos = *Curschar;
X	if (u_pos.linep == NULL)
X	    u_pos = l_pos;
X
X	ResetBuffers();
X	n = RowNumber(&l_pos);
X	AppendPositionToUndoUndobuff(0, n);
X	AppendPositionToUndobuff(0, n);
X	if ((Filetop->linep->next == l_pos.linep) &&
X	    (u_pos.linep->next == Fileend->linep))
X	    AppendToUndobuff("a");
X	else if (u_pos.linep->next == Fileend->linep)
X	    AppendToUndobuff("o");
X	else
X	    AppendToUndobuff("O");
X
X	n = 0;
X	cp = l_pos.linep;
X	for (; cp != NULL && cp != Fileend->linep; cp = cp->next) {
X	    AppendToUndobuff(cp->s);
X	    n++;
X	    if (cp == u_pos.linep)
X		break;
X	    AppendToUndobuff(NL_STR);
X	}
X	AppendToUndobuff(ESC_STR);
X
X	if (n > 1)
X	    AppendNumberToUndoUndobuff(n);
X	AppendToUndoUndobuff("dd");
X
X	*Curschar = l_pos;
X	delline(n);
X	S_NOT_VALID;
X	return;
X    }
X    if (strncmp(cmd, "s/", 2) == 0) {
X	dosub(&l_pos, &u_pos, cmdbuf + 1);
X	return;
X    }
X    if (strncmp(cmd, "g/", 2) == 0) {
X	doglob(&l_pos, &u_pos, cmdbuf + 1);
X	return;
X    }
X    /*
X     * If we got a line, but no command, then go to the line. 
X     */
X    if (*cmd == NUL && l_pos.linep != NULL) {
X	if (u_pos.linep != NULL)
X	    *Curschar = u_pos;
X	else
X	    *Curschar = l_pos;
X
X	S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X	return;
X    }
X    badcmd();
X}
X
X/*
X * get_range - parse a range specifier 
X *
X * Ranges are of the form: 
X *
X * addr[,addr] 
X *
X * where 'addr' is: 
X *
X * %          (entire file)
X * $  [+-NUM]
X * 'x [+-NUM] (where x denotes a currently defined mark)
X * .  [+-NUM]
X * NUM 
X *
X * The pointer *cp is updated to point to the first character following the
X * range spec. If an initial address is found, but no second, the upper bound
X * is equal to the lower. 
X */
Xstatic void
Xget_range(cp)
X    char          **cp;
X{
X    LPtr           *l;
X    char           *p;
X
X    if (**cp == '%') {
X	l_pos.index = 0;
X	l_pos.linep = Filetop->linep->next;
X	u_pos.index = 0;
X	u_pos.linep = Fileend->linep->prev;
X	(*cp)++;
X	return;
X    }
X    if ((l = get_line(cp)) == NULL)
X	return;
X
X    l_pos = *l;
X
X    for (p = *cp; *p != NUL && isspace(*p); p++);
X
X    *cp = p;
X
X    if (*p != ',') {		/* is there another line spec ? */
X	u_pos = l_pos;
X	return;
X    }
X    *cp = ++p;
X
X    if ((l = get_line(cp)) == NULL) {
X	u_pos = l_pos;
X	return;
X    }
X    u_pos = *l;
X}
X
Xstatic LPtr    *
Xget_line(cp)
X    char          **cp;
X{
X    static LPtr     pos;
X    LPtr           *lp;
X    char           *p, c;
X    int             lnum;
X
X    pos.index = 0;		/* shouldn't matter... check back later */
X
X    p = *cp;
X    /*
X     * Determine the basic form, if present. 
X     */
X    switch (c = *p++) {
X
X      case '$':
X	pos.linep = Fileend->linep->prev;
X	break;
X
X      case '.':
X	pos.linep = Curschar->linep;
X	break;
X
X      case '\'':
X	if ((lp = getmark(*p++)) == NULL) {
X	    emsg("Unknown mark");
X	    return (LPtr *) NULL;
X	}
X	pos = *lp;
X	break;
X
X      case '0':
X      case '1':
X      case '2':
X      case '3':
X      case '4':
X      case '5':
X      case '6':
X      case '7':
X      case '8':
X      case '9':
X	for (lnum = c - '0'; isdigit(*p); p++)
X	    lnum = (lnum * 10) + (*p - '0');
X
X	if (lnum == 0)
X	    lnum = 1;
X
X	pos = *gotoline(lnum);
X	break;
X
X      default:
X	return (LPtr *) NULL;
X    }
X
X    while (*p != NUL && isspace(*p))
X	p++;
X
X    if (*p == '-' || *p == '+') {
X	bool_t          neg = (*p++ == '-');
X
X	for (lnum = 0; isdigit(*p); p++)
X	    lnum = (lnum * 10) + (*p - '0');
X
X	if (neg)
X	    lnum = -lnum;
X
X	pos = *gotoline(cntllines(Filemem, &pos) + lnum);
X    }
X    *cp = p;
X    return &pos;
X}
X
Xstatic void
Xbadcmd()
X{
X    if (interactive)
X	emsg("Unrecognized command");
X}
X
X/*
X * dotag(tag, force) - goto tag 
X */
Xvoid
Xdotag(tag, force)
X    char           *tag;
X    bool_t          force;
X{
X    FILE           *tp, *fopen();
X    char            lbuf[LSIZE];
X    char           *fname, *str;
X
X    if ((tp = fopen("tags", "r")) == NULL) {
X	emsg("Can't open tags file");
X	return;
X    }
X    while (fgets(lbuf, LSIZE, tp) != NULL) {
X	if ((fname = strchr(lbuf, TAB)) == NULL) {
X	    emsg("Format error in tags file");
X	    return;
X	}
X	*fname++ = '\0';
X	if ((str = strchr(fname, TAB)) == NULL) {
X	    emsg("Format error in tags file");
X	    return;
X	}
X	*str++ = '\0';
X
X	if (strcmp(lbuf, tag) == 0) {
X	    if (!force && Changed) {
X		emsg(nowrtmsg);
X		return;
X	    }
X	    if (doecmd(fname)) {
X		stuffReadbuff(str);	/* str has \n at end */
X		stuffReadbuff("\007");	/* CTRL('G') */
X		fclose(tp);
X		return;
X	    }
X	}
X    }
X    emsg("tag not found");
X    fclose(tp);
X}
X
Xstatic          bool_t
Xdoecmd(arg)
X    char           *arg;
X{
X    int             line = 1;	/* line # to go to in new file */
X
X    if (arg != NULL) {
X	/*
X	 * First detect a ":e" on the current file. This is mainly for ":ta"
X	 * commands where the destination is within the current file. 
X	 */
X	if (Filename != NULL) {
X	    if (strcmp(arg, Filename) == 0) {
X		if (!Changed) {
X		    return TRUE;
X		}
X	    }
X	}
X	if (strcmp(arg, "#") == 0) {	/* alternate */
X	    char           *s = Filename;
X
X	    if (altfile == NULL) {
X		emsg("No alternate file");
X		return FALSE;
X	    }
X	    Filename = altfile;
X	    altfile = s;
X	    line = altline;
X	    altline = cntllines(Filemem, Curschar);
X	} else {
X	    altfile = Filename;
X	    altline = cntllines(Filemem, Curschar);
X	    Filename = strsave(arg);
X	}
X    }
X    if (Filename == NULL) {
X	emsg("No filename");
X	return FALSE;
X    }
X    /* clear mem and read file */
X    freeall();
X    filealloc();
X    UNCHANGED;
X
X    if (readfile(Filename, Filemem, 0)) {
X	emsg("Can't open file");
X	return FALSE;
X    }
X    *Topchar = *Curschar;
X    if (line != 1) {
X	stuffnumReadbuff(line);
X	stuffReadbuff("G");
X    }
X    setpcmark();
X
X    return TRUE;
X}
X
Xstatic void
Xdoshell()
X{
X    char           *sh, *getenv();
X
X    sh = getenv("SHELL");
X    if (sh == NULL) {
X	emsg("Shell variable not set");
X	return;
X    }
X    gotocmdline(YES, NUL);
X
X    if (system(sh) < 0) {
X	emsg("Exec failed");
X	return;
X    }
X    wait_return();
X}
X
Xvoid
Xgotocmdline(clr, firstc)
X    bool_t          clr;
X    char            firstc;
X{
X    windgoto(Rows - 1, 0);
X    if (clr)
X	outstr(T_EL);		/* clear the bottom line */
X    if (firstc)
X	outchar(firstc);
X}
X
X/*
X * msg(s) - displays the string 's' on the status line 
X */
Xvoid
Xmsg(s)
X    char           *s;
X{
X    gotocmdline(YES, NUL);
X    outstr(s);
X#ifdef AMIGA
X    flushbuf();
X#endif
X#ifdef BSD
X    flushbuf();
X#endif
X}
X
X/* VARARGS */
Xvoid
Xsmsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
X    char           *s;
X    int             a1, a2, a3, a4, a5, a6, a7, a8, a9;
X{
X    char            sbuf[MAX_COLUMNS + 1];
X
X    sprintf(sbuf, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X    msg(sbuf);
X}
X
X/*
X * emsg() - display an error message 
X *
X * Rings the bell, if appropriate, and calls message() to do the real work 
X */
Xvoid
Xemsg(s)
X    char           *s;
X{
X    UndoInProgress = FALSE;
X    RedrawingDisabled = FALSE;
X
X    if (P(P_EB))
X	beep();
X    outstr(T_TI);
X    msg(s);
X    outstr(T_TP);
X#ifdef AMIGA
X    flushbuf();
X#endif
X#ifdef BSD
X    flushbuf();
X#endif
X}
X
Xvoid
Xwait_return()
X{
X    char            c;
X
X    outstr("Press RETURN to continue");
X    do {
X	c = vgetc();
X    } while (c != '\r' && c != '\n');
X
X    s_clear();
X}
SHAR_EOF
echo "extracting dec.c"
sed 's/^X//' << \SHAR_EOF > dec.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
X/*
X * dec(p) 
X *
X * Decrement the line pointer 'p' crossing line boundaries as necessary. Return
X * 1 when crossing a line, -1 when at start of file, 0 otherwise. 
X */
Xint
Xdec(lp)
X    register LPtr  *lp;
X{
X    if (lp->index > 0) {	/* still within line */
X	lp->index--;
X	return 0;
X    }
X    if (lp->linep->prev != Filetop->linep) {	/* there is a prior line */
X	lp->linep = lp->linep->prev;
X	lp->index = strlen(lp->linep->s);
X	return 1;
X    }
X    lp->index = 0;		/* stick at first char */
X    return -1;			/* at start of file */
X}
SHAR_EOF
echo "extracting dos.c"
sed 's/^X//' << \SHAR_EOF > dos.c
X/*
X * DOS System-dependent routines.
X *
X * System-specific code for MS-DOS. This has been tested with
X * MSDOS 3.3 on an AT. Also, the console driver "nansi.sys" is
X * required.
X *
X */
X
X#include <dos.h>
X#include "stevie.h"
X
X/*
X * inchar() - get a character from the keyboard
X */
Xint
Xinchar()
X{
X    int             c;
X
X    for (;; beep()) {		/* loop until we get a valid character */
X
X	flushbuf();		/* flush any pending output */
X
X	switch (c = getch()) {
X	  case 0x1e:
X	    return K_CGRAVE;
X	  case 0:		/* special key */
X	    if (State != NORMAL) {
X		c = getch();	/* throw away next char */
X		continue;	/* and loop for another char */
X	    }
X	    switch (c = getch()) {
X	      case 0x50:
X		return K_DARROW;
X	      case 0x48:
X		return K_UARROW;
X	      case 0x4b:
X		return K_LARROW;
X	      case 0x4d:
X		return K_RARROW;
X	      case 0x52:
X		return K_INSERT;
X	      case 0x47:
X		stuffReadbuff("1G");
X		return -1;
X	      case 0x4f:
X		stuffReadbuff("G");
X		return -1;
X	      case 0x51:
X		stuffReadbuff(mkstr(CTRL('F')));
X		return -1;
X	      case 0x49:
X		stuffReadbuff(mkstr(CTRL('B')));
X		return -1;
X		/*
X		 * Hard-code some useful function key macros. 
X		 */
X	      case 0x3b:	/* F1 */
X		stuffReadbuff(":p\n");
X		return -1;
X	      case 0x54:	/* SF1 */
X		stuffReadbuff(":p!\n");
X		return -1;
X	      case 0x3c:	/* F2 */
X		stuffReadbuff(":n\n");
X		return -1;
X	      case 0x55:	/* SF2 */
X		stuffReadbuff(":n!\n");
X		return -1;
X	      case 0x3d:	/* F3 */
X		stuffReadbuff(":e #\n");
X		return -1;
X	      case 0x3e:	/* F4 */
X		stuffReadbuff(":rew\n");
X		return -1;
X	      case 0x57:	/* SF4 */
X		stuffReadbuff(":rew!\n");
X		return -1;
X	      case 0x3f:	/* F5 */
X		stuffReadbuff("[[");
X		return -1;
X	      case 0x40:	/* F6 */
X		stuffReadbuff("]]");
X		return -1;
X	      case 0x41:	/* F7 */
X		stuffReadbuff("<<");
X		return -1;
X	      case 0x42:	/* F8 */
X		stuffReadbuff(">>");
X		return -1;
X	      case 0x43:	/* F9 */
X		stuffReadbuff(":x\n");
X		return -1;
X	      case 0x44:	/* F10 */
X		stuffReadbuff(":help\n");
X		return -1;
X	      default:
X		break;
X	    }
X	    break;
X
X	  default:
X	    return c;
X	}
X    }
X}
X
X#define BSIZE   2048
Xstatic char     outbuf[BSIZE];
Xstatic int      bpos = 0;
X
Xflushbuf()
X{
X    if (bpos != 0)
X	write(1, outbuf, bpos);
X    bpos = 0;
X}
X
X/*
X * Macro to output a character. Used within this file for speed.
X */
X#define outone(c)       outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
X
X/*
X * Function version for use outside this file.
X */
Xvoid
Xoutchar(c)
X    register char   c;
X{
X    outbuf[bpos++] = c;
X    if (bpos >= BSIZE)
X	flushbuf();
X}
X
Xstatic char     cell[2] = {0, 7};
X
X/*
X * outstr(s) - write a string to the console
X */
Xvoid
Xoutstr(s)
X    register char  *s;
X{
X    while (*s) {
X	outone(*s++);
X    }
X}
X
Xvoid
Xbeep()
X{
X    if (RedrawingDisabled)
X	return;
X
X    outone('\007');
X}
X
Xvoid
Xsleep(n)
X    int             n;
X{
X    /*
X     * Should do something reasonable here. 
X     */
X}
X
Xvoid
Xdelay()
X{
X    long            l;
X
X    flushbuf();
X    /*
X     * Should do something better here... 
X     */
X    for (l = 0; l < 5000; l++);
X}
X
Xvoid
Xwindinit()
X{
X    Columns = 80;
X    P(P_LI) = Rows = 25;
X}
X
Xvoid
Xwindexit(r)
X    int             r;
X{
X    flushbuf();
X    exit(r);
X}
X
Xvoid
Xwindgoto(r, c)
X    register int    r, c;
X{
X    union REGS      rr;
X
X    flushbuf();
X    rr.h.dh = r;
X    rr.h.dl = c;
X    rr.x.bx = 0;
X    rr.x.ax = 0x0200;
X    int86(0x10, &rr, &rr);
X}
X
XFILE           *
Xfopenb(fname, mode)
X    char           *fname;
X    char           *mode;
X{
X    FILE           *fopen();
X    char            modestr[16];
X
X    sprintf(modestr, "%sb", mode);
X    return fopen(fname, modestr);
X}
SHAR_EOF
echo "extracting dos.h"
sed 's/^X//' << \SHAR_EOF > dos.h
X/*
X * MS DOS Machine-dependent routines. 
X */
X
Xint  inchar();
Xvoid outchar();
Xvoid outstr();
Xvoid beep();
Xvoid windinit();
Xvoid windexit();
Xvoid windgoto();
Xvoid delay();
Xvoid sleep();
SHAR_EOF
echo "extracting edit.c"
sed 's/^X//' << \SHAR_EOF > edit.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
X/*
X * This flag is used to make auto-indent work right on lines where only a
X * <RETURN> or <ESC> is typed. It is set when an auto-indent is done, and
X * reset when any other editting is done on the line. If an <ESC> or <RETURN>
X * is received, and did_ai is TRUE, the line is truncated. 
X */
Xbool_t          did_ai = FALSE;
X
Xvoid
Xedit()
X{
X    char            c;
X    bool_t          literal_next_flag = FALSE;
X
X    Prenum = 0;
X
X    /* position the display and the cursor at the top of the file. */
X    *Topchar = *Filemem;
X    *Curschar = *Filemem;
X    Cursrow = Curscol = 0;
X
X    s_refresh(NOT_VALID);
X
X    for (;;) {
X
X	if (!RedrawingDisabled) {
X	    /* Figure out where the cursor is based on Curschar. */
X	    cursupdate(UPDATE_CURSOR);
X	    windgoto(Cursrow, Curscol);
X	}
X	c = vgetc();
X
X	if (State == NORMAL) {
X	    /* We're in the normal (non-insert) mode. */
X
X	    /* Pick up any leading digits and compute 'Prenum' */
X	    if (isascii(c)) {	/* must disallow special chars from "ascii.h" */
X		if ((Prenum > 0 && isdigit(c)) || (isdigit(c) && c != '0')) {
X		    Prenum = Prenum * 10 + (c - '0');
X		    continue;
X		}
X	    }
X	    /* execute the command */
X	    normal(c);
X	    Prenum = 0;
X
X	} else {
X	    if (c == CTRL('V') && !literal_next_flag) {
X		literal_next_flag = TRUE;
X		outchar('^');
X		continue;
X	    }
X	    if (literal_next_flag) {
X		literal_next_flag = FALSE;
X		outchar('\b');
X		if (c != NL) {
X		    did_ai = FALSE;
X		    insertchar(c);
X		    continue;
X		}
X	    }
X	    switch (c) {	/* We're in insert mode */
X
X	      case ESC:	/* an escape ends input mode */
X	doESCkey:
X		/*
X		 * If we just did an auto-indent, truncate the line, and put
X		 * the cursor back. 
X		 */
X		if (did_ai) {
X		    Curschar->linep->s[0] = NUL;
X		    Curschar->index = 0;
X		    did_ai = FALSE;
X		}
X		set_want_col = TRUE;
X
X		/*
X		 * The cursor should end up on the last inserted character.
X		 * This is an attempt to match the real 'vi', but it may not
X		 * be quite right yet. 
X		 */
X		if (Curschar->index != 0) {
X		    if (gchar(Curschar) == NUL)
X			dec(Curschar);
X		    else if (Insbuffptr != NULL)
X			dec(Curschar);
X		}
X		State = NORMAL;
X		msg("");
X
X		if (!UndoInProgress) {
X		    int             n;
X		    char           *p;
X
X		    if (last_command == 'o')
X			AppendToUndobuff(UNDO_SHIFTJ_STR);
X
X		    if (Insbuffptr != NULL) {
X			if (last_command == 'O')
X			    AppendToUndobuff("0");
X			AppendToRedobuff(Insbuff);
X			AppendToUndoUndobuff(Insbuff);
X			n = 0;
X			for (p = Insbuff; *p != NUL; p++) {
X			    if (*p == NL) {
X				if (n) {
X				    AppendNumberToUndobuff(n);
X				    AppendToUndobuff("dl");
X				    n = 0;
X				}
X				AppendToUndobuff(UNDO_SHIFTJ_STR);
X			    } else
X				n++;
X			}
X			if (n) {
X			    AppendNumberToUndobuff(n);
X			    AppendToUndobuff("dl");
X			}
X		    }
X		    if (last_command == 'c') {
X			AppendToUndobuff(mkstr(last_command_char));
X			AppendToUndobuff(Yankbuff);
X			AppendToUndobuff(ESC_STR);
X		    }
X		    AppendToRedobuff(ESC_STR);
X		    AppendToUndoUndobuff(ESC_STR);
X		    if (last_command == 'O')
X			AppendToUndobuff(UNDO_SHIFTJ_STR);
X		}
X		break;
X
X	      case CTRL('D'):
X		/*
X		 * Control-D is treated as a backspace in insert mode to make
X		 * auto-indent easier. This isn't completely compatible with
X		 * vi, but it's a lot easier than doing it exactly right, and
X		 * the difference isn't very noticeable. 
X		 */
X	      case BS:
X		/* can't backup past starting point */
X		if (Curschar->linep == Insstart->linep &&
X		    Curschar->index <= Insstart->index) {
X		    beep();
X		    break;
X		}
X		/* can't backup to a previous line */
X		if (Curschar->linep != Insstart->linep &&
X		    Curschar->index <= 0) {
X		    beep();
X		    break;
X		}
X		did_ai = FALSE;
X		dec(Curschar);
X		delchar(TRUE, FALSE);
X		/*
X		 * It's a little strange to put backspaces into the redo
X		 * buffer, but it makes auto-indent a lot easier to deal
X		 * with. 
X		 */
X		AppendToInsbuff(BS_STR);
X		if (!RedrawingDisabled)	/* screen will be fixed later */
X		    S_LINE_NOT_VALID;
X		break;
X
X	      case CR:
X	      case NL:
X		AppendToInsbuff(NL_STR);
X		if (!OpenForward(!RedrawingDisabled))
X		    goto doESCkey;	/* out of memory */
X		break;
X
X	      default:
X		did_ai = FALSE;
X		insertchar(c);
X		break;
X	    }
X	}
X    }
X}
X
X/*
X * Special characters in this context are those that need processing other
X * than the simple insertion that can be performed here. This includes ESC
X * which terminates the insert, and CR/NL which need special processing to
X * open up a new line. This routine tries to optimize insertions performed by
X * the "redo", "undo" or "put" commands, so it needs to know when it should
X * stop and defer processing to the "normal" mechanism. 
X */
X#define ISSPECIAL(c)    ((c) == BS || (c) == NL || (c) == CR || (c) == ESC)
X
Xvoid
Xinsertchar(c)
X    char            c;
X{
X    if (anyinput()) {		/* If there's any pending input, grab up to
X				 * MAX_COLUMNS at once. */
X	char            p[MAX_COLUMNS + 1];
X	int             i;
X
X	p[0] = c;
X	i = 1;
X	c = vpeekc();
X	while (!ISSPECIAL(c) && anyinput() && (i < MAX_COLUMNS)) {
X	    p[i++] = vgetc();
X	    c = vpeekc();
X	}
X	p[i] = '\0';
X	insstr(p);
X	AppendToInsbuff(p);
X    } else {
X	inschar(c);
X	AppendToInsbuff(mkstr(c));
X    }
X
X    if (!RedrawingDisabled)	/* screen will be fixed later */
X	S_LINE_NOT_VALID;
X}
X
Xvoid
Xgetout(r)
X    int             r;
X{
X    windgoto(Rows - 1, 0);
X    outchar('\r');
X    outchar('\n');
X    windexit(r);
X}
X
Xvoid
Xscrolldown(nlines)
X    int             nlines;
X{
X    register LPtr  *p;
X
X    S_MUST_UPDATE_BOTCHAR;
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    /* Scroll up 'nlines' lines. */
X    while (nlines--) {
X	p = prevline(Topchar);
X	if (p == NULL)
X	    break;
X	Topchar->linep = p->linep;
X    }
X    /*
X     * The calling routine must make sure that Curschar is in the correct
X     * place with relation to Botchar.
X     */
X}
X
Xvoid
Xscrollup(nlines)
X    int             nlines;
X{
X    register LPtr  *p;
X
X    S_MUST_UPDATE_BOTCHAR;
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    /* Scroll down 'nlines' lines. */
X    while (nlines--) {
X	p = nextline(Topchar);
X	if (p == NULL)
X	    break;
X	Topchar->linep = p->linep;
X    }
X    /*
X     * The calling routine must make sure that Curschar is in the correct
X     * place with relation to Topchar.
X     */
X}
X
X/*
X * oneright oneleft onedown oneup 
X *
X * Move one char {right,left,down,up}.  Return TRUE when sucessful, FALSE when
X * we hit a boundary (of a line, or the file). 
X */
X
Xbool_t
Xoneright()
X{
X    set_want_col = TRUE;
X
X    switch (inc(Curschar)) {
X
X      case 0:
X	return TRUE;
X
X      case 1:
X	dec(Curschar);		/* crossed a line, so back up */
X	/* FALLTHROUGH */
X      case -1:
X	return FALSE;
X    }
X
X    return FALSE;		/* PARANOIA: should never reach here */
X}
X
Xbool_t
Xoneleft()
X{
X    set_want_col = TRUE;
X
X    switch (dec(Curschar)) {
X
X      case 0:
X	return TRUE;
X
X      case 1:
X	inc(Curschar);		/* crossed a line, so back up */
X	/* FALLTHROUGH */
X      case -1:
X	return FALSE;
X    }
X
X    return FALSE;		/* PARANOIA: should never reach here */
X}
X
Xvoid
Xbeginline(flag)
X    bool_t          flag;
X{
X    while (oneleft());
X    if (flag) {
X	while (isspace(gchar(Curschar)) && oneright());
X    }
X    set_want_col = TRUE;
X}
X
Xbool_t
Xoneup(n)
X    register int    n;
X{
X    register int    k;
X
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    for (k = 0; k < n; k++) {
X	if (Curschar->linep->prev == Filetop->linep) {
X	    if (k > 0)
X		break;
X	    else
X		return FALSE;
X	}
X	Curschar->linep = Curschar->linep->prev;
X    }
X
X    /* try to advance to the column we want to be at */
X    Curschar->index = 0;
X    coladvance(Curschar, Curswant);
X    return TRUE;
X}
X
Xbool_t
Xonedown(n)
X    register int    n;
X{
X    register int    k;
X
X    S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X    for (k = 0; k < n; k++) {
X	if (Curschar->linep->next == Fileend->linep) {
X	    if (k > 0)
X		break;
X	    else
X		return FALSE;
X	}
X	Curschar->linep = Curschar->linep->next;
X    }
X
X    /* try to advance to the column we want to be at */
X    Curschar->index = 0;
X    coladvance(Curschar, Curswant);
X    return TRUE;
X}
SHAR_EOF
echo "extracting env.h"
sed 's/^X//' << \SHAR_EOF > env.h
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X/*
X * The defines in this file establish the environment we're compiling
X * in. Set these appropriately before compiling the editor.
X */
X
X/*
X * One (and only 1) of the following defines should be uncommented. Most of
X * the code is pretty machine-independent. Machine dependent code goes in a
X * file like tos.c or unix.c. The only other place where machine dependent
X * code goes is term.h for escape sequences. 
X */
X
X#ifndef AMIGA
X# ifndef BSD
X#  ifndef UNIX
X/* Defined in makefile : AMIGA	Amiga */
X/* Defined in makefile : BSD	BSD 4.3 */
X/* Defined in makefile : UNIX	System V */
X/* #define	ATARI		Atari ST */
X/* #define	OS2		Microsoft OS/2 */
X/* #define	DOS		MS DOS 3.3 */
X#  endif
X# endif
X#endif
X
X/*
X * If ATARI is defined, one of the following compilers must be selected. 
X */
X#ifdef	ATARI
X#define MWC			Mark William's C 3.0.9 */
X/* #define	MEGAMAX		Megamax Compiler */
X/* #define	ALCYON		Alcyon C compiler */
X
X# ifdef MWC
X#  define AppendNumberToUndoUndobuff 	XX1
X#  define AppendPositionToUndoUndobuff	XX2
X#  define FOPENB
X# endif
X
X# ifdef MEGAMAX
X#  define FOPENB
X# endif
X#endif
X
X/*
X * If HELP is defined, the :help command shows a vi command summary. 
X */
X#define	HELP			/* enable help command */
X
X/*
X * STRCSPN should be defined if the target system doesn't have the
X * routine strcspn() available. See regexp.c for details.
X */
X
X#ifdef	ATARI
X#define	STRCSPN
X#endif
SHAR_EOF
echo "extracting fileio.c"
sed 's/^X//' << \SHAR_EOF > fileio.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
Xvoid
Xfilemess(s)
X    char           *s;
X{
X    sprintf(IObuff, "\"%s\" %s", ((Filename == NULL) ? "" : Filename), s);
X    msg(IObuff);
X}
X
Xvoid
Xrenum()
X{
X    LPtr           *p;
X    unsigned long   l = 0;
X
X    for (p = Filemem; p != NULL; p = nextline(p), l += LINEINC)
X	p->linep->num = l;
X
X    Fileend->linep->num = 0xffffffffL;
X}
X
X#ifdef  MEGAMAX
Xoverlay "fileio"
X#endif
X
Xbool_t
Xreadfile(fname, fromp, nochangename)
X    char           *fname;
X    LPtr           *fromp;
X    bool_t          nochangename;	/* if TRUE, don't change the Filename */
X{
X    FILE           *f, *fopen();
X    LINE           *curr;
X    char            buf2[80];
X    int             c;
X    int             IObuffsize = 0;
X    long            nchars = 0;
X    int             linecnt = 0;
X    bool_t          wasempty = bufempty();
X    int             nonascii = 0;	/* count garbage characters */
X    int             nulls = 0;	/* count nulls */
X    bool_t          incomplete = FALSE;	/* was the last line incomplete? */
X    bool_t          toolong = FALSE;	/* a line was too long */
X
X    curr = fromp->linep;
X
X    if (!nochangename)
X	Filename = strsave(fname);
X
X    f = fopen(fname, "r");
X    if (f == NULL)
X	return TRUE;
X
X    S_NOT_VALID;
X
X    filemess("");
X
X    do {
X	c = getc(f);
X
X	if (c == EOF) {
X	    if (IObuffsize == 0)/* normal loop termination */
X		break;
X
X	    /*
X	     * If we get EOF in the middle of a line, note the fact and
X	     * complete the line ourselves. 
X	     */
X	    incomplete = TRUE;
X	    c = NL;
X	}
X	if (c >= 0x80) {
X	    c -= 0x80;
X	    nonascii++;
X	}
X	/*
X	 * If we reached the end of the line, OR we ran out of space for it,
X	 * then process the complete line. 
X	 */
X	if (c == NL || IObuffsize == (IOSIZE - 1)) {
X	    LINE           *lp;
X
X	    if (c != NL)
X		toolong = TRUE;
X
X	    IObuff[IObuffsize++] = NUL;
X	    lp = newline(IObuffsize);
X	    if (lp == NULL) {
X		fprintf(stderr, "not enough memory - should never happen");
X		getout(1);
X	    }
X	    strcpy(lp->s, IObuff);
X
X	    curr->next->prev = lp;	/* new line to next one */
X	    lp->next = curr->next;
X
X	    curr->next = lp;	/* new line to prior one */
X	    lp->prev = curr;
X
X	    curr = lp;		/* new line becomes current */
X	    IObuffsize = 0;
X	    linecnt++;
X	} else if (c == NUL) {
X	    nulls++;		/* count and ignore nulls */
X	} else {
X	    IObuff[IObuffsize++] = (char) c;	/* normal character */
X	}
X
X	nchars++;
X    } while (!incomplete && !toolong);
X
X    fclose(f);
X
X    /*
X     * If the buffer was empty when we started, we have to go back and remove
X     * the "dummy" line at Filemem and patch up the ptrs. 
X     */
X    if (wasempty && linecnt != 0) {
X	LINE           *dummy = Filemem->linep;	/* dummy line ptr */
X
X	Filemem->linep = Filemem->linep->next;
X	Filemem->linep->prev = Filetop->linep;
X	Filetop->linep->next = Filemem->linep;
X
X	Curschar->linep = Filemem->linep;
X	Topchar->linep = Filemem->linep;
X
X	free(dummy->s);		/* free string space */
X	free((char *) dummy);	/* free LINE struct */
X    }
X    renum();
X
X    if (toolong) {
X	sprintf(IObuff, "\"%s\" Line too long", fname);
X	msg(IObuff);
X	return FALSE;
X    }
X    sprintf(IObuff, "\"%s\" %s%d line%s, %ld character%s",
X	    fname,
X	    incomplete ? "[Incomplete last line] " : "",
X	    linecnt, (linecnt > 1) ? "s" : "",
X	    nchars, (nchars > 1) ? "s" : "");
X
X    buf2[0] = NUL;
X
X    if (nonascii || nulls) {
X	if (nonascii) {
X	    if (nulls)
X		sprintf(buf2, " (%d null, %d non-ASCII)",
X			nulls, nonascii);
X	    else
X		sprintf(buf2, " (%d non-ASCII)", nonascii);
X	} else
X	    sprintf(buf2, " (%d null)", nulls);
X    }
X    strcat(IObuff, buf2);
X    msg(IObuff);
X
X    return FALSE;
X}
X
X/*
X * writeit - write to file 'fname' lines 'start' through 'end' 
X *
X * If either 'start' or 'end' contain null line pointers, the default is to use
X * the start or end of the file respectively. 
X */
Xbool_t
Xwriteit(fname, start, end)
X    char           *fname;
X    LPtr           *start, *end;
X{
X    FILE           *f;
X    FILE           *fopen();
X    FILE           *fopenb();	/* open in binary mode, where needed */
X    char           *s;
X    long            nchars;
X    int             lines;
X    LPtr           *p;
X
X    sprintf(IObuff, "\"%s\"", fname);
X    msg(IObuff);
X
X    /*
X     * Form the backup file name - change foo.* to foo.bak - use IObuff to
X     * hold the backup file name 
X     */
X    strcpy(IObuff, fname);
X    for (s = IObuff; *s && *s != '.'; s++);
X    *s = NUL;
X    strcat(IObuff, ".bak");
X
X    /*
X     * Delete any existing backup and move the current version to the backup.
X     * For safety, we don't remove the backup until the write has finished
X     * successfully. And if the 'backup' option is set, leave it around. 
X     */
X    rename(fname, IObuff);
X
X    f = P(P_CR) ? fopen(fname, "w") : fopenb(fname, "w");
X    if (f == NULL) {
X	emsg("Can't open file for writing!");
X	return FALSE;
X    }
X    /*
X     * If we were given a bound, start there. Otherwise just start at the
X     * beginning of the file. 
X     */
X    if (start == NULL || start->linep == NULL)
X	p = Filemem;
X    else
X	p = start;
X
X    lines = 0;
X    nchars = 0;
X    do {
X	fprintf(f, "%s\n", p->linep->s);
X	nchars += strlen(p->linep->s) + 1;
X	lines++;
X
X	/*
X	 * If we were given an upper bound, and we just did that line, then
X	 * bag it now. 
X	 */
X	if (end != NULL && end->linep != NULL) {
X	    if (end->linep == p->linep)
X		break;
X	}
X    } while ((p = nextline(p)) != NULL);
X
X    fclose(f);
X
X    /*
X     * Remove the backup unless they want it left around 
X     */
X    if (!P(P_BK))
X	remove(IObuff);
X
X    sprintf(IObuff, "\"%s\" %d line%s, %ld character%s", fname,
X	    lines, (lines > 1) ? "s" : "",
X	    nchars, (nchars > 1) ? "s" : "");
X    msg(IObuff);
X    UNCHANGED;
X
X    return TRUE;
X}
SHAR_EOF
echo "extracting format_l.c"
sed 's/^X//' << \SHAR_EOF > format_l.c
X/*
X * format_line() 
X *
X * Return a pointer to a string buffer containing a formated screen line.
X *
X * By G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
Xchar           *tab_expand = "                ";
X
Xchar           *
Xformat_line(ptr, len)
X    register char  *ptr;
X    int            *len;
X{
X    register char  *dest;
X    register char   c;
X    register int    col;
X    char           *p_extra;
X    int             n_extra;
X    int             coff;	/* column offset */
X
X    dest = IObuff;
X    col = 0;
X
X    coff = P(P_NU) ? 8 : 0;
X
X    n_extra = 0;
X    p_extra = NULL;
X
X    for (;;) {
X	if (n_extra > 0) {
X	    c = *p_extra++;
X	    n_extra--;
X	} else {
X	    c = *ptr++;
X	    while (c >= 32 && c < 127) {
X		*dest++ = c;
X		col++;
X		if (col >= IOSIZE)
X		    goto DONE_FORMAT_LINE;
X		c = *ptr++;
X	    }
X	    if (c == TAB) {
X		if (!P(P_LS)) {
X		    /* tab amount depends on current column */
X		    p_extra = tab_expand;
X		    n_extra = (P(P_TS) - 1) - (col - coff) % P(P_TS);
X		    c = ' ';
X		}
X	    } else if ((n_extra = chars[c].ch_size - 1) > 0) {
X		p_extra = chars[c].ch_str;
X		c = *p_extra++;
X	    } else if (c == NUL) {
X		if (P(P_NU)) {
X		    *dest++ = '$';
X		    col++;
X		}
X		break;
X	    }
X	}
X	*dest++ = c;
X	col++;
X	if (col >= IOSIZE)
X	    break;
X    }
XDONE_FORMAT_LINE:
X    if (col >= IOSIZE) {
X	dest--;
X	col--;
X    }
X    *dest = NUL;
X
X    if (len != NULL)
X	*len = col;
X
X    return (IObuff);
X}
SHAR_EOF
echo "extracting help.c"
sed 's/^X//' << \SHAR_EOF > help.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
Xextern char    *Version;
X
Xstatic int      helprow;
X
X#ifdef  HELP
X
X#ifdef  MEGAMAX
Xoverlay "help"
X#endif
X
Xstatic void     longline();
X
Xbool_t
Xhelp()
X{
X    outstr(T_ED);
X    windgoto(helprow = 0, 0);
X
X    longline("\
XPositioning within file\n\
X=======================\n\
X^F\t\tForward screenfull             Worked on by:\n\
X^B\t\tBackward screenfull                Tim Thompson\n");
X    longline("\
X^D\t\tscroll down half screen            Tony Andrews\n\
X^U\t\tscroll up half screen              G.R. (Fred) Walter\n");
X    longline("\
XG\t\tGoto line (end default)\n\
X]]\t\tnext function\n\
X[[\t\tprevious function\n\
X/re\t\tnext occurence of regular expression 're'\n");
X    longline("\
X?re\t\tprior occurence of regular expression 're'\n\
Xn\t\trepeat last / or ?\n\
XN\t\treverse last / or ?\n\
X%\t\tfind matching (, ), {, }, [, or ]\n");
X    longline("\
X\n\
XAdjusting the screen\n\
X====================\n\
X^L\t\tRedraw the screen\n\
X^E\t\tscroll window down 1 line\n\
X^Y\t\tscroll window up 1 line\n");
X    longline("\
Xz<RETURN>\tredraw, current line at top\n\
Xz-\t\t... at bottom\n\
Xz.\t\t... at center\n");
X
X    windgoto(0, 32);
X    longline(Version);
X#ifdef AMIGA
X    longline(" ");
X    longline(__DATE__);
X    longline(" ");
X    longline(__TIME__);
X#endif
X
X    windgoto(helprow = Rows - 2, 47);
X    longline("<Press space bar to continue>\n");
X    windgoto(helprow = Rows - 1, 47);
X    longline("<Any other key will quit>");
X
X    if (vgetc() != ' ')
X	return TRUE;
X
X    outstr(T_ED);
X    windgoto(helprow = 0, 0);
X
X    longline("\
XCharacter Positioning\n\
X=====================\n\
X^\t\tfirst non-white\n\
X0\t\tbeginning of line\n\
X$\t\tend of line\n\
Xh\t\tbackward\n");
X    longline("\
Xl\t\tforward\n\
X^H\t\tsame as h\n\
Xspace\t\tsame as l\n\
Xfx\t\tfind 'x' forward\n");
X    longline("\
XFx\t\tfind 'x' backward\n\
Xtx\t\tupto 'x' forward\n\
XTx\t\tupto 'x' backward\n\
X;\t\tRepeat last f, F, t, or T\n");
X    longline("\
X,\t\tinverse of ;\n\
X|\t\tto specified column\n\
X%\t\tfind matching (, ), {, }, [, or ]\n");
X
X    windgoto(helprow = Rows - 2, 47);
X    longline("<Press space bar to continue>\n");
X    windgoto(helprow = Rows - 1, 47);
X    longline("<Any other key will quit>");
X
X    if (vgetc() != ' ')
X	return TRUE;
X
X    outstr(T_ED);
X    windgoto(helprow = 0, 0);
X
X    longline("\
XLine Positioning\n\
X================\n\
XH\t\thome window line\n\
XL\t\tlast window line\n\
XM\t\tmiddle window line\n");
X    longline("\
X+\t\tnext line, at first non-white\n\
X-\t\tprevious line, at first non-white\n\
XCR\t\treturn, same as +\n\
Xj\t\tnext line, same column\n\
Xk\t\tprevious line, same column\n");
X
X    longline("\
X\n\
XMarking and Returning\n\
X=====================\n\
X``\t\tprevious context\n\
X''\t\t... at first non-white in line\n");
X    longline("\
Xmx\t\tmark position with letter 'x'\n\
X`x\t\tto mark 'x'\n\
X'x\t\t... at first non-white in line\n");
X
X    windgoto(helprow = Rows - 2, 47);
X    longline("<Press space bar to continue>\n");
X    windgoto(helprow = Rows - 1, 47);
X    longline("<Any other key will quit>");
X
X    if (vgetc() != ' ')
X	return TRUE;
X
X    outstr(T_ED);
X    windgoto(helprow = 0, 0);
X
X    longline("\
XInsert and Replace\n\
X==================\n\
Xa\t\tappend after cursor\n\
Xi\t\tinsert before cursor\n\
XA\t\tappend at end of line\n\
XI\t\tinsert before first non-blank\n");
X    longline("\
Xo\t\topen line below\n\
XO\t\topen line above\n\
Xrx\t\treplace single char with 'x'\n\
XR\t\treplace characters (not yet)\n\
X~\t\treplace character under cursor with other case\n");
X
X    longline("\
X\n\
XWords, sentences, paragraphs\n\
X============================\n\
Xw\t\tword forward\n\
Xb\t\tback word\n\
Xe\t\tend of word\n\
X)\t\tto next sentence (not yet)\n\
X}\t\tto next paragraph (not yet)\n");
X    longline("\
X(\t\tback sentence (not yet)\n\
X{\t\tback paragraph (not yet)\n\
XW\t\tblank delimited word\n\
XB\t\tback W\n\
XE\t\tto end of W");
X
X    windgoto(helprow = Rows - 2, 47);
X    longline("<Press space bar to continue>\n");
X    windgoto(helprow = Rows - 1, 47);
X    longline("<Any other key will quit>");
X
X    if (vgetc() != ' ')
X	return TRUE;
X
X    outstr(T_ED);
X    windgoto(helprow = 0, 0);
X
X    longline("\
XUndo  &  Redo\n\
X=============\n\
Xu\t\tundo last change\n\
XU\t\trestore current line (not yet)\n\
X.\t\trepeat last change\n");
X
X    longline("\
X\n\
XFile manipulation\n\
X=================\n");
X    longline("\
X:w\t\twrite back changes\n\
X:wq\t\twrite and quit\n\
X:x\t\twrite if modified, and quit\n\
X:q\t\tquit\n\
X:q!\t\tquit, discard changes\n\
X:e name\t\tedit file 'name'\n");
X    longline("\
X:e!\t\tre-edit, discard changes\n\
X:e #\t\tedit alternate file\n\
X:w name\t\twrite file 'name'\n");
X    longline("\
X:n\t\tedit next file in arglist\n\
X:n args\t\tspecify new arglist (not yet)\n\
X:rew\t\trewind arglist\n\
X:f\t\thow current file and lines\n");
X    longline("\
X:f file\t\tchange current file name\n\
X:ta tag\t\tto tag file entry 'tag'\n\
X^]\t\t:ta, current word is tag");
X
X    windgoto(helprow = Rows - 2, 47);
X    longline("<Press space bar to continue>\n");
X    windgoto(helprow = Rows - 1, 47);
X    longline("<Any other key will quit>");
X
X    if (vgetc() != ' ')
X	return TRUE;
X
X    outstr(T_ED);
X    windgoto(helprow = 0, 0);
X
X    longline("\
XOperators (double to affect lines)\n\
X==================================\n\
Xd\t\tdelete\n\
Xc\t\tchange\n");
X    longline("\
X<\t\tleft shift\n\
X>\t\tright shift\n\
Xy\t\tyank to buffer\n");
X
X    longline("\n\
XYank and Put\n\
X============\n\
Xp\t\tput back text\n\
XP\t\tput before\n\
XY\t\tyank lines");
X
X    windgoto(helprow = Rows - 2, 47);
X    longline("<Press space bar to continue>\n");
X    windgoto(helprow = Rows - 1, 47);
X    longline("<Any other key will quit>");
X
X    if (vgetc() != ' ')
X	return TRUE;
X
X    outstr(T_ED);
X    windgoto(helprow = 0, 0);
X
X    longline("\n\
XMiscellaneous operations\n\
X========================\n\
XC\t\tchange rest of line\n\
XD\t\tdelete rest of line\n\
Xs\t\tsubstitute chars\n");
X    longline("\
XS\t\tsubstitute lines (not yet)\n\
XJ\t\tjoin lines\n\
Xx\t\tdelete characters\n\
XX\t\t... before cursor\n\
X:[range]s/search/replace/[g]\n\
X:[range]g/search[/p|/d]\n\
X:[range]d\tdelete range of lines\n");
X
X    windgoto(helprow = Rows - 1, 47);
X    longline("<Press any key>");
X
X    vgetc();
X
X    return TRUE;
X}
X
Xstatic void
Xlongline(p)
X    char           *p;
X{
X# ifdef AMIGA
X    outstr(p);
X# else
X    char           *s;
X
X    for (s = p; *s; s++) {
X	if (*s == '\n')
X	    windgoto(++helprow, 0);
X	else
X	    outchar(*s);
X    }
X# endif
X}
X#else
X
Xbool_t
Xhelp()
X{
X    msg("Sorry, help not configured");
X    return FALSE;
X}
X#endif
SHAR_EOF
echo "extracting inc.c"
sed 's/^X//' << \SHAR_EOF > inc.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
X/*
X * inc(p) 
X *
X * Increment the line pointer 'p' crossing line boundaries as necessary. Return
X * 1 when crossing a line, -1 when at end of file, 0 otherwise. 
X */
Xint
Xinc(lp)
X    register LPtr  *lp;
X{
X    register char  *p = &(lp->linep->s[lp->index]);
X
X    if (*p != NUL) {		/* still within line */
X	lp->index++;
X	return ((p[1] != NUL) ? 0 : 1);
X    }
X    if (lp->linep->next != Fileend->linep) {	/* there is a next line */
X	lp->index = 0;
X	lp->linep = lp->linep->next;
X	return 1;
X    }
X    return -1;
X}
SHAR_EOF
echo "extracting keymap.h"
sed 's/^X//' << \SHAR_EOF > keymap.h
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X/*
X * Keycode definitions for special keys 
X *
X * On systems that have any of these keys, the routine 'inchar' in the
X * machine-dependent code should return one of the codes here. 
X */
X
X#define	K_CGRAVE	0x1e	/* control grave accent */
X
X#define	K_HELP		0x80
X#define	K_UNDO		0x81
X#define	K_INSERT	0x82
X#define	K_HOME		0x83
X#define	K_UARROW	0x84
X#define	K_DARROW	0x85
X#define	K_LARROW	0x86
X#define	K_RARROW	0x87
X#define	K_SUARROW	0x88
X#define	K_SDARROW	0x89
X#define	K_SLARROW	0x8a
X#define	K_SRARROW	0x8b
X
X#define	K_F1		0x8c	/* function keys */
X#define	K_F2		0x8d
X#define	K_F3		0x8e
X#define	K_F4		0x8f
X#define	K_F5		0x90
X#define	K_F6		0x91
X#define	K_F7		0x92
X#define	K_F8		0x93
X#define	K_F9		0x94
X#define	K_F10		0x95
X
X#define	K_SF1		0x96	/* shifted function keys */
X#define	K_SF2		0x97
X#define	K_SF3		0x98
X#define	K_SF4		0x99
X#define	K_SF5		0x9a
X#define	K_SF6		0x9b
X#define	K_SF7		0x9c
X#define	K_SF8		0x9d
X#define	K_SF9		0x9e
X#define	K_SF10		0x9f
SHAR_EOF
echo "extracting linefunc.c"
sed 's/^X//' << \SHAR_EOF > linefunc.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#include "stevie.h"
X
X/*
X * nextline(curr) 
X *
X * Return a pointer to the beginning of the next line after the one referenced
X * by 'curr'. Return NULL if there is no next line (at EOF). 
X */
X
XLPtr           *
Xnextline(curr)
X    LPtr           *curr;
X{
X    static LPtr     next;
X
X    if (curr != NULL) {
X	if (curr->linep->next != Fileend->linep) {
X	    next.index = 0;
X	    next.linep = curr->linep->next;
X	    return &next;
X	}
X    }
X    return (LPtr *) NULL;
X}
X
X/*
X * prevline(curr) 
X *
X * Return a pointer to the beginning of the line before the one referenced by
X * 'curr'. Return NULL if there is no prior line. 
X */
X
XLPtr           *
Xprevline(curr)
X    LPtr           *curr;
X{
X    static LPtr     prev;
X
X    if (curr != NULL) {
X	if (curr->linep->prev != Filetop->linep) {
X	    prev.index = 0;
X	    prev.linep = curr->linep->prev;
X	    return &prev;
X	}
X    }
X    return (LPtr *) NULL;
X}
X
X/*
X * coladvance(p,col) 
X *
X * Try to advance to the specified column, starting at p. 
X */
X
Xvoid
Xcoladvance(p, want_col)
X    register LPtr  *p;
X    register int    want_col;
X{
X    register char   c;
X    register int    col;
X    register int    incr;
X
X    if (gchar(p) != NUL) {	/* already at the end of line */
X	for (col = 0; want_col > 0;) {
X	    c = gchar(p);
X	    if (c == TAB && !P(P_LS))
X		incr = (P(P_TS) - col % P(P_TS));
X	    else
X		incr = chars[c].ch_size;
X	    want_col -= incr;
X	    col += incr;
X
X	    /* Don't go past the end of the file or the line. */
X	    if (inc(p)) {
X		dec(p);
X		break;
X	    }
X	}
X    }
X}
SHAR_EOF
echo "extracting macros.h"
sed 's/^X//' << \SHAR_EOF > macros.h
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X/*
X * gchar(lp) - get the character at position "lp" 
X */
X#define gchar(lp) ((lp)->linep->s[(lp)->index])
X
X/*
X * pchar(lp, c) - put character 'c' at position 'lp' 
X */
X#define pchar(lp, c) ((lp)->linep->s[(lp)->index] = (c))
X
X/*
X * pswap(a, b) - swap two position pointers 
X */
X#define pswap(a, b) { LPtr pswaptmp; pswaptmp = a; a = b; b = pswaptmp; }
X
X/*
X * Position comparisons 
X */
X#define lt(a, b) ((LINEOF(a) != LINEOF(b)) \
X                   ? (LINEOF(a) < LINEOF(b)) : ((a)->index < (b)->index))
X
X#define ltoreq(a, b) ((LINEOF(a) != LINEOF(b)) \
X                   ? (LINEOF(a) < LINEOF(b)) : ((a)->index <= (b)->index))
X
X#define gt(a, b) ((LINEOF(a) != LINEOF(b)) \
X                   ? (LINEOF(a) > LINEOF(b)) : ((a)->index > (b)->index))
X
X#define gtoreq(a, b) ((LINEOF(a) != LINEOF(b)) \
X                   ? (LINEOF(a) > LINEOF(b)) : ((a)->index >= (b)->index))
X
X#define equal(a, b) (((a)->linep == (b)->linep) && ((a)->index == (b)->index))
X
X/*
X * anyinput
X *
X * Return non-zero if input is pending.
X */
X#define anyinput() (Readbuffptr != NULL)
X
X/*
X * buf1line() - return TRUE if there is only one line in file buffer
X */
X#define buf1line() (Filemem->linep->next == Fileend->linep)
X
X/*
X * bufempty() - return TRUE if the file buffer is empty 
X */
X#define bufempty() (buf1line() && Filemem->linep->s[0] == NUL)
X
X/*
X * lineempty() - return TRUE if the line is empty 
X */
X#define lineempty(p) ((p)->linep->s[0] == NUL)
X
X/*
X * startofline() - return TRUE if the given position is at start of line 
X */
X#define startofline(p) ((p)->index == 0)
X
X/*
X * endofline() - return TRUE if the given position is at end of line 
X *
X * This routine will probably never be called with a position resting on the NUL
X * byte, but handle it correctly in case it happens. 
X */
X#define endofline(p) \
X     ((p)->linep->s[(p)->index] == NUL || (p)->linep->s[(p)->index + 1] == NUL)
X
X/*
X * RowNumber() - return the row number (if no UndoInProgress)
X */
X#define RowNumber(p) (UndoInProgress ? 0 : cntllines(Filemem, (p)))
SHAR_EOF
echo "extracting main.c"
sed 's/^X//' << \SHAR_EOF > main.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson           twitch!tjt
X *                         Tony Andrews           onecom!wldrdg!tony 
X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
X */
X
X#ifdef AMIGA
X# include <proto/exec.h>
X#endif
X
X#include "stevie.h"
X
Xint             Rows;		/* Number of Rows and Columns */
Xint             Columns;	/* in the current window. */
X
Xint             CheckTopcharAndBotchar = FALSE;
Xint             MustUpdateBotchar = FALSE;
Xint             ValidToCurschar = FALSE;
Xint             LineNotValid = FALSE;
X
Xint             NumLineSizes = -1;	/* # of active LineSizes */
XLINE          **LinePointers = NULL;	/* Pointer to the line for LineSizes */
Xchar           *LineSizes = NULL;	/* Size of a line (pline output) */
X
Xchar           *Filename = NULL;/* Current file name */
X
XLPtr           *Filemem;	/* The contents of the file, as a single
X				 * array. */
XLPtr           *Filetop;	/* Line 'above' the start of the file */
X
XLPtr           *Fileend;	/* Pointer to the end of the file in Filemem.
X				 * (It points to the byte AFTER the last
X				 * byte.) */
X
XLPtr           *Topchar;	/* Pointer to the byte in Filemem which is in
X				 * the upper left corner of the screen. */
X
XLPtr           *Botchar;	/* Pointer to the byte in Filemem which is
X				 * just off the bottom of the screen. */
X
XLPtr           *Curschar;	/* Pointer to byte in Filemem at which the
X				 * cursor is currently placed. */
X
Xint             Curscol;	/* Current position of cursor (column) */
Xint             Cursrow;	/* Current position of cursor (row) */
X
Xint             Cursvcol;	/* Current virtual column, the column number
X				 * of the file's actual line, as opposed to
X				 * the column number we're at on the screen.
X				 * This makes a difference on lines that span
X				 * more than one screen line. */
X
Xint             Curswant = 0;	/* The column we'd like to be at. This is
X				 * used try to stay in the same column
X				 * through up/down cursor motions. */
X
Xbool_t          set_want_col;	/* If set, then update Curswant the next time
X				 * through cursupdate() to the current
X				 * virtual column. */
X
Xint             State = NORMAL;	/* This is the current state of the command
X				 * interpreter. */
X
Xint             Prenum = 0;	/* The (optional) number before a command. */
X
XLPtr           *Insstart;	/* This is where the latest insert/append
X				 * mode started. */
X
Xbool_t          Changed = FALSE;/* Set to TRUE if something in the file has
X				 * been changed and not written out. */
X
Xchar           *IObuff;		/* file reads are done, one line at a time,
X				 * into this buffer; as well as sprintf's */
X
Xchar           *Insbuffptr = NULL;
Xchar           *Insbuff;	/* Each insertion gets stuffed into this
X				 * buffer. */
X
Xchar           *Readbuffptr = NULL;
Xchar           *Readbuff;	/* Having this buffer allows STEVIE to easily
X				 * make itself do commands */
X
Xchar           *Redobuffptr = NULL;
Xchar           *Redobuff;	/* Each command should stuff characters into
X				 * this buffer that will re-execute itself. */
X
Xbool_t          UndoInProgress = FALSE;	/* Set to TRUE if undo'ing */
Xchar           *Undobuffptr = NULL;
Xchar           *Undobuff;	/* Each command should stuff characters into
X				 * this buffer that will undo its effects. */
X
Xchar           *UndoUndobuffptr = NULL;
Xchar           *UndoUndobuff;	/* Each command should stuff characters into
X				 * this buffer that will undo its undo. */
X
Xchar           *Yankbuffptr = NULL;
Xchar           *Yankbuff;	/* Yank buffer */
X
Xchar            last_command = NUL;	/* last command */
Xchar            last_command_char = NUL;	/* character needed to undo
X						 * last command */
X
Xbool_t          RedrawingDisabled = FALSE;	/* Set to TRUE if undo'ing or
X						 * put'ing */
X
Xchar          **files;		/* list of input files */
Xint             numfiles;	/* number of input files */
Xint             curfile;	/* number of the current file */
X
Xstatic void
Xusage()
X{
X    fprintf(stderr, "usage: stevie [file ...]\n");
X    fprintf(stderr, "       stevie -t tag\n");
X    fprintf(stderr, "       stevie +[num] file\n");
X    fprintf(stderr, "       stevie +/pat  file\n");
X    exit(1);
X}
X
X#ifdef AMIGA
Xvoid
X#else
Xint
X#endif
Xmain(argc, argv)
X    int             argc;
X    char          **argv;
X{
X    char           *initstr;	/* init string from the environment */
X    char           *tag = NULL;	/* tag from command line */
X    char           *pat = NULL;	/* pattern from command line */
X    int             line = -1;	/* line number from command line */
X
X    int             atoi();
X    char           *getenv();
X
X#ifdef AMIGA
X    {
X	struct Library *DosBase;/* Used for checking version */
X
X	DosBase = OpenLibrary("dos.library", 33);
X	if (!DosBase) {
X	    fprintf(stderr,
X		 "\nSTEVIE requires Version 33 or later of dos.library.\n");
X	    exit(2);
X	} else {
X	    CloseLibrary(DosBase);
X	}
X
X/*
X * I don't think STEVIE should be exited with a break.
X */
X	(void) signal(SIGINT, SIG_IGN);
X    }
X#endif
X
X    /*
X     * Process the command line arguments. 
X     */
X    if (argc > 1) {
X	switch (argv[1][0]) {
X
X	  case '-':		/* -t tag */
X	    if (argv[1][1] != 't')
X		usage();
X
X	    if (argv[2] == NULL)
X		usage();
X
X	    Filename = NULL;
X	    tag = argv[2];
X	    numfiles = 1;
X	    break;
X
X	  case '+':		/* +n or +/pat */
X	    if (argv[1][1] == '/') {
X		if (argv[2] == NULL)
X		    usage();
X		Filename = strsave(argv[2]);
X		pat = &(argv[1][1]);
X		numfiles = 1;
X
X	    } else if (isdigit(argv[1][1]) || argv[1][1] == NUL) {
X		if (argv[2] == NULL)
X		    usage();
X		Filename = strsave(argv[2]);
X		numfiles = 1;
X
X		line = (isdigit(argv[1][1])) ?
X		    atoi(&(argv[1][1])) : 0;
X	    } else
X		usage();
X
X	    break;
X
X	  default:		/* must be a file name */
X	    Filename = strsave(argv[1]);
X	    files = &(argv[1]);
X	    numfiles = argc - 1;
X	    break;
X	}
X    } else {
X	Filename = NULL;
X	numfiles = 1;
X    }
X    curfile = 0;
X
X    windinit();
X
X    /*
X     * Allocate LPtr structures for all the various position pointers and for
X     * the many buffers. 
X     */
X    Filetop = (LPtr *) alloc((unsigned) sizeof(LPtr));
X    Filemem = (LPtr *) alloc((unsigned) sizeof(LPtr));
X    Fileend = (LPtr *) alloc((unsigned) sizeof(LPtr));
X    Topchar = (LPtr *) alloc((unsigned) sizeof(LPtr));
X    Curschar = (LPtr *) alloc((unsigned) sizeof(LPtr));
X    Botchar = (LPtr *) alloc((unsigned) sizeof(LPtr));
X    Insstart = (LPtr *) alloc((unsigned) sizeof(LPtr));
X    IObuff = alloc(IOSIZE);
X    Insbuff = alloc(INSERT_SIZE);
X    Readbuff = alloc(READSIZE);
X    Redobuff = alloc(REDO_UNDO_SIZE);
X    Undobuff = alloc(REDO_UNDO_SIZE);
X    UndoUndobuff = alloc(REDO_UNDO_SIZE);
X    Yankbuff = alloc(YANKSIZE);
X    if (Filetop == NULL ||
X	Filemem == NULL ||
X	Fileend == NULL ||
X	Topchar == NULL ||
X	Curschar == NULL ||
X	Botchar == NULL ||
X	Insstart == NULL ||
X	IObuff == NULL ||
X	Insbuff == NULL ||
X	Readbuff == NULL ||
X	Redobuff == NULL ||
X	Undobuff == NULL ||
X	UndoUndobuff == NULL ||
X	Yankbuff == NULL) {
X	fprintf(stderr, "Can't allocate data structures\n");
X	windexit(0);
X    }
X    screenalloc();
X    filealloc();		/* Initialize Filemem, Filetop & Fileend */
X
X    s_clear();
X
X    initstr = getenv("EXINIT");
X    if (initstr != NULL) {
X	char           *lp, buf[128];
X
X	lp = getenv("LINES");
X	if (lp != NULL) {
X	    sprintf(buf, "%s lines=%s", initstr, lp);
X	    readcmdline(':', buf);
X	} else
X	    readcmdline(':', initstr);
X    }
X    if (Filename != NULL) {
X	if (readfile(Filename, Filemem, FALSE))
X	    filemess("[New File]");
X    } else
X	msg("Empty Buffer");
X
X    setpcmark();
X
X    if (tag) {
X	stuffReadbuff(":ta ");
X	stuffReadbuff(tag);
X	stuffReadbuff("\n");
X    } else if (pat) {
X	stuffReadbuff(pat);
X	stuffReadbuff("\n");
X    } else if (line >= 0) {
X	if (line > 0)
X	    stuffnumReadbuff(line);
X	stuffReadbuff("G");
X    }
X    edit();
X    /* NOTREACHED */
X    /* windexit(0); */
X}
X
Xvoid
XstuffReadbuff(s)
X    char           *s;
X{
X    if (Readbuffptr == NULL) {
X	if ((strlen(s) + 1) < READSIZE) {
X	    strcpy(Readbuff, s);
X	    Readbuffptr = Readbuff;
X	    return;
X	}
X    } else if ((strlen(Readbuff) + (strlen(s) + 1)) < READSIZE) {
X	strcat(Readbuff, s);
X	return;
X    }
X    emsg("Couldn't stuffReadbuff() - clearing Readbuff\n");
X    *Readbuff = NUL;
X    Readbuffptr = NULL;
X}
X
Xvoid
XstuffnumReadbuff(n)
X    int             n;
X{
X    char            buf[32];
X
X    sprintf(buf, "%d", n);
X    stuffReadbuff(buf);
X}
X
X/* OPTRESULT */
Xchar
Xvgetc()
X{
X    int             c;
X
X    /*
X     * inchar() may map special keys by using stuffReadbuff(). If it does so,
X     * it returns -1 so we know to loop here to get a real char. 
X     */
X    do {
X	if (Readbuffptr != NULL) {
X	    char            nextc = *Readbuffptr++;
X
X	    if (*Readbuffptr == NUL) {
X		*Readbuff = NUL;
X		Readbuffptr = NULL;
X	    }
X	    return (nextc);
X	}
X	c = inchar();
X    } while (c == -1);
X
X    return (char) c;
X}
X
Xchar
Xvpeekc()
X{
X    if (Readbuffptr != NULL)
X	return (*Readbuffptr);
X    return (NUL);
X}
SHAR_EOF
echo "End of archive 2 (of 6)"
# if you want to concatenate archives, remove anything after this line
exit