[comp.sources.amiga] v89i041: stevie - vi-like text editor v35a, Part02/06

page@swan.ulowell.edu (Bob Page) (03/15/89)

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

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	alloc.c
#	amiga.c
#	fileio.c
#	os2.c
#	stevie.h
#	tags
#	term.h
#	tos.h
#	version.c
# This archive created: Tue Mar 14 14:41:09 1989
cat << \SHAR_EOF > alloc.c
/*
 * STEVIE - Simply Try this Editor for VI Enthusiasts
 *
 * Code Contributions By : Tim Thompson           twitch!tjt
 *                         Tony Andrews           onecom!wldrdg!tony 
 *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
 */

#include "stevie.h"

/*
 * This file contains various routines dealing with allocation and
 * deallocation of data structures. 
 */

char           *
alloc(size)
    unsigned        size;
{
    char           *p;		/* pointer to new storage space */
#ifdef AMIGA
    char           *pp;

    /*
     * Before allocating any memory make sure there is enough for a system
     * requester left. 
     */
    pp = malloc((unsigned) 40000);
    if (pp == (char *) NULL) {	/* if there is no more room... */
	emsg("alloc() is unable to find memory!");
	return (NULL);
    }
#endif

    p = malloc(size);
    if (p == (char *) NULL)	/* if there is no more room... */
	emsg("alloc() is unable to find memory!");

#ifdef AMIGA
    free(pp);
#endif
    return (p);
}

char           *
strsave(string)
    char           *string;
{
    return (strcpy(alloc((unsigned) (strlen(string) + 1)), string));
}

void
screenalloc()
{
    int             i;

    /*
     * If we're changing the size of the screen, free the old arrays 
     */
    if (Realscreen != NULL)
	free(Realscreen);
    if (Nextscreen != NULL)
	free(Nextscreen);
    if (LinePointers != NULL)
	free((char *) LinePointers);
    if (LineSizes != NULL)
	free(LineSizes);

    Realscreen = malloc((unsigned) (Rows * Columns));
    Nextscreen = malloc((unsigned) (Rows * Columns));
    LinePointers = (LINE **) malloc((unsigned) (Rows * sizeof(LINE *)));
    LineSizes = malloc((unsigned) Rows);

    for (i = 0; i < Rows; i++) {
	LinePointers[i] = NULL;
	LineSizes[i] = 0;
    }
}

/*
 * Allocate and initialize a new line structure with room for 'nchars'
 * characters. 
 */
LINE           *
newline(nchars)
    int             nchars;
{
    register LINE  *l;

    l = (LINE *) alloc((unsigned) sizeof(LINE));
    if (l == NULL)
	return (LINE *) NULL;

    l->s = alloc((unsigned) nchars);	/* the line is empty */
    l->s[0] = NUL;
    l->size = nchars;

    l->prev = (LINE *) NULL;	/* should be initialized by caller */
    l->next = (LINE *) NULL;

    return l;
}

/*
 * filealloc() - construct an initial empty file buffer 
 */
void
filealloc()
{
    if ((Filemem->linep = newline(1)) == NULL) {
	fprintf(stderr, "Unable to allocate file memory!\n");
	getout(1);
    }
    if ((Filetop->linep = newline(1)) == NULL) {
	fprintf(stderr, "Unable to allocate file memory!\n");
	getout(1);
    }
    if ((Fileend->linep = newline(1)) == NULL) {
	fprintf(stderr, "Unable to allocate file memory!\n");
	getout(1);
    }
    Filemem->index = 0;
    Filetop->index = 0;
    Fileend->index = 0;

    Filetop->linep->prev = NULL;
    Filetop->linep->next = Filemem->linep;	/* connect Filetop to Filemem */
    Filemem->linep->prev = Filetop->linep;

    Filemem->linep->next = Fileend->linep;	/* connect Filemem to Fileend */
    Fileend->linep->prev = Filemem->linep;
    Fileend->linep->next = NULL;

    *Curschar = *Filemem;
    *Topchar = *Filemem;

    Filemem->linep->num = 0;
    Fileend->linep->num = 0xffffffffL;

    clrall();			/* clear all marks */
}

/*
 * freeall() - free the current buffer 
 *
 * Free all lines in the current buffer. 
 */
void
freeall()
{
    LINE           *lp;
    LINE           *xlp;
    int             i;

    for (lp = Filetop->linep; lp != NULL; lp = xlp) {
	if (lp->s != NULL)
	    free(lp->s);
	xlp = lp->next;
	free((char *) lp);
    }

    Curschar->linep = NULL;	/* clear pointers */
    Filemem->linep = NULL;
    Filetop->linep = NULL;
    Fileend->linep = NULL;

    for (i = 0; i < Rows; i++) {/* clear screen information */
	LinePointers[i] = NULL;
	LineSizes[i] = 0;
    }
}

/*
 * canincrease(n) - returns TRUE if the current line can be increased 'n'
 * bytes 
 *
 * This routine returns immediately if the requested space is available. If not,
 * it attempts to allocate the space and adjust the data structures
 * accordingly. If everything fails it returns FALSE. 
 */
bool_t
canincrease(n)
    register int    n;
{
    register int    nsize;
    register char  *s;		/* pointer to new space */

    nsize = strlen(Curschar->linep->s) + 1 + n;	/* size required */

    if (nsize <= Curschar->linep->size)
	return TRUE;

    /*
     * Need to allocate more space for the string. Allow some extra space on
     * the assumption that we may need it soon. This avoids excessive numbers
     * of calls to malloc while entering new text. 
     */
    s = alloc((unsigned) (nsize + SLOP));
    if (s == NULL) {
	emsg("Can't add anything, file is too big!");
	State = NORMAL;
	return FALSE;
    }
    Curschar->linep->size = nsize + SLOP;
    strcpy(s, Curschar->linep->s);
    free(Curschar->linep->s);
    Curschar->linep->s = s;

    return TRUE;
}
SHAR_EOF
cat << \SHAR_EOF > amiga.c
/*
 * Amiga system-dependent routines. 
 */

#include <proto/dos.h>
#include "stevie.h"

long            raw_in = 0;
long            raw_out = 0;

#define	BSIZE	2048
static char     outbuf[BSIZE];
static int      bpos = 0;

void
flushbuf()
{
    if (bpos != 0)
	Write(raw_out, outbuf, bpos);
    bpos = 0;
}

/*
 * Macro to output a character. Used within this file for speed. 
 */
#define	outone(c)	outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()

int
GetCharacter()
{
    char            c;

    Read(raw_in, &c, sizeof(c));
    return ((int) c);
}

/*
 * getCSIsequence - get a CSI sequence
 *                - either cursor keys, help, functionkeys, or some
 *                  other sequence (if other, check window size)
 */
int
getCSIsequence()
{
    int             c;
    int             param1;
    int             param2;

    c = GetCharacter();
    if (isdigit(c)) {
	param1 = 0;
	while (isdigit(c)) {
	    param1 = param1 * 10 + c - '0';
	    c = GetCharacter();
	}
	if (c == '~')		/* function key */
	    return ((char) (K_F1 + param1));

	/* must be an event of some sort or a window bound report */
	if (c == ';') {
	    param2 = 0;
	    c = GetCharacter();
	    while (isdigit(c)) {
		param2 = param2 * 10 + c - '0';
		c = GetCharacter();
	    }
	    if (c == ';') {
		param1 = 0;
		c = GetCharacter();
		while (isdigit(c)) {
		    param1 = param1 * 10 + c - '0';
		    c = GetCharacter();
		}
		if (c == ';') {
		    param2 = 0;
		    c = GetCharacter();
		    while (isdigit(c)) {
			param2 = param2 * 10 + c - '0';
			c = GetCharacter();
		    }
		    if (c == ' ') {
			c = GetCharacter();
			if (c == 'r') {
			    if (param1 < 2)
				param1 = 2;
			    if (param2 < 5)
				param2 = 5;
			    if (Columns != param2 || Rows != param1) {
				Columns = param2;
				Rows = param1;
				P(P_LI) = Rows;
				return (-1);
			    } else
				return 0;
			}
		    }
		}
	    }
	}
	while ((c != '|') && (c != '~'))
	    c = GetCharacter();

	outstr("\033[0 q");
	flushbuf();
    }
    switch (c) {
      case 'A':		/* cursor up */
	return K_UARROW;
      case 'B':		/* cursor down */
	return K_DARROW;
      case 'C':		/* cursor right */
	return K_RARROW;
      case 'D':		/* cursor left */
	return K_LARROW;
      case 'T':		/* shift cursor up */
	return K_SUARROW;
      case 'S':		/* shift cursor down */
	return K_SDARROW;
      case ' ':		/* shift cursor left or right */
	c = GetCharacter();
	if (c == 'A')		/* shift cursor left */
	    return K_SLARROW;
	if (c == '@')		/* shift cursor right */
	    return K_SRARROW;
	break;
      case '?':		/* help */
	c = GetCharacter();
	if (c == '~')
	    return K_HELP;
	break;
    }
    return 0;			/* some other control code */
}

/*
 * inchar() - get a character from the keyboard 
 */
int
inchar()
{
    int             c;

    flushbuf();

    for (;;) {
	c = GetCharacter();
	if (c != 0x9b)
	    break;
	c = getCSIsequence();
	if (c > 0)
	    break;
	if (c == -1) {
	    screenalloc();
	    screenclear();
	    msg("");
	    updateNextscreen(NOT_VALID);
	    cursupdate();
	    updateNextscreen(NOT_VALID);
	    cursupdate();
	    updateRealscreen();
	    windgoto(Cursrow, Curscol);
	    flushbuf();
	}
    }
    return c;
}

void
outchar(c)
    char            c;
{
    outbuf[bpos++] = c;
    if (bpos >= BSIZE)
	flushbuf();
}

void
outstr(s)
    char           *s;
{
    while (*s)
	outone(*s++);
}

void
beep()
{
    if (RedrawingDisabled)
	return;

    outone('\007');
}

void
sleep(n)
    int             n;
{
    void            Delay();

    if (n > 0)
	Delay(50L * n);
}

void
delay()
{
    void            Delay();

    Delay(25L);
}

void
windinit()
{
    Columns = 80;
    P(P_LI) = Rows = 24;

    raw_in = Input();
    if (!IsInteractive(raw_in)) {
	raw_in = Open("RAW:0/0/480/200/STEVIE", MODE_NEWFILE);
	if (raw_in == NULL) {
	    fprintf(stderr, "Can't open window ?!?!?!?\n");
	    exit(2);
	}
	raw_out = raw_in;
    } else {
	raw_out = Output();
	if (raw(stdin) != 0)
	    perror("Can't change to raw mode ?!?!?!?");
    }

    outstr("\033[12{");		/* window resize events activated */
    flushbuf();

    for (;;) {
	outstr("\033[0 q");	/* get window size */
	flushbuf();
	if (GetCharacter() == 0x9b)
	    if (getCSIsequence() == -1)
		break;
    }
}

void
windexit(r)
    int             r;
{
    outstr("\033[12}");		/* window resize events de-activated */
    flushbuf();

    if (raw_in != raw_out) {
	if (cooked(stdin) != 0)
	    perror("Can't change to cooked mode ?!?!?!?");
    } else {
	Close(raw_in);
    }
    exit(r);
}

void
windgoto(r, c)
    int             c;
    int             r;
{
    r++;
    c++;

    outstr("\033[");
    if (r >= 10)
	outchar((char) (r / 10 + '0'));
    outchar((char) (r % 10 + '0'));
    outchar(';');
    if (c >= 10)
	outchar((char) (c / 10 + '0'));
    outchar((char) (c % 10 + '0'));
    outchar('H');
}

FILE           *
fopenb(fname, mode)
    char           *fname;
    char           *mode;
{
    FILE           *fopen();
    char            modestr[16];

    sprintf(modestr, "%sb", mode);
    return fopen(fname, modestr);
}
SHAR_EOF
cat << \SHAR_EOF > fileio.c
/*
 * STEVIE - Simply Try this Editor for VI Enthusiasts
 *
 * Code Contributions By : Tim Thompson           twitch!tjt
 *                         Tony Andrews           onecom!wldrdg!tony 
 *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
 */

#include "stevie.h"

void
filemess(s)
    char           *s;
{
    sprintf(IObuff, "\"%s\" %s", ((Filename == NULL) ? "" : Filename), s);
    msg(IObuff);
}

void
renum()
{
    LPtr           *p;
    unsigned long   l = 0;

    for (p = Filemem; p != NULL; p = nextline(p), l += LINEINC)
	p->linep->num = l;

    Fileend->linep->num = 0xffffffffL;
}

#ifdef	MEGAMAX
overlay "fileio"
#endif

bool_t
readfile(fname, fromp, nochangename)
    char           *fname;
    LPtr           *fromp;
    bool_t          nochangename;	/* if TRUE, don't change the Filename */
{
    FILE           *f, *fopen();
    LINE           *curr;
    char            buf2[80];
    int             c;
    int             IObuffsize = 0;
    long            nchars = 0;
    int             linecnt = 0;
    bool_t          wasempty = bufempty();
    int             nonascii = 0;	/* count garbage characters */
    int             nulls = 0;	/* count nulls */
    bool_t          incomplete = FALSE;	/* was the last line incomplete? */
    bool_t          toolong = FALSE;	/* a line was too long */

    curr = fromp->linep;

    if (!nochangename)
	Filename = strsave(fname);

    f = fopen(fname, "r");
    if (f == NULL)
	return TRUE;

    filemess("");

    do {
	c = getc(f);

	if (c == EOF) {
	    if (IObuffsize == 0)/* normal loop termination */
		break;

	    /*
	     * If we get EOF in the middle of a line, note the fact and
	     * complete the line ourselves. 
	     */
	    incomplete = TRUE;
	    c = NL;
	}
	if (c >= 0x80) {
	    c -= 0x80;
	    nonascii++;
	}
	/*
	 * If we reached the end of the line, OR we ran out of space for it,
	 * then process the complete line. 
	 */
	if (c == NL || IObuffsize == (IOSIZE - 1)) {
	    LINE           *lp;

	    if (c != NL)
		toolong = TRUE;

	    IObuff[IObuffsize++] = NUL;
	    if ((lp = newline(IObuffsize)) == NULL) {
		fprintf(stderr, "not enough memory - should never happen");
		getout(1);
	    }
	    strcpy(lp->s, IObuff);

	    curr->next->prev = lp;	/* new line to next one */
	    lp->next = curr->next;

	    curr->next = lp;	/* new line to prior one */
	    lp->prev = curr;

	    curr = lp;		/* new line becomes current */
	    IObuffsize = 0;
	    linecnt++;
	} else if (c == NUL) {
	    nulls++;		/* count and ignore nulls */
	} else {
	    IObuff[IObuffsize++] = (char) c;	/* normal character */
	}

	nchars++;
    } while (!incomplete && !toolong);

    fclose(f);

    /*
     * If the buffer was empty when we started, we have to go back and remove
     * the "dummy" line at Filemem and patch up the ptrs. 
     */
    if (wasempty && linecnt != 0) {
	LINE           *dummy = Filemem->linep;	/* dummy line ptr */

	free(dummy->s);		/* free string space */
	Filemem->linep = Filemem->linep->next;
	free((char *) dummy);	/* free LINE struct */
	Filemem->linep->prev = Filetop->linep;
	Filetop->linep->next = Filemem->linep;

	Curschar->linep = Filemem->linep;
	Topchar->linep = Filemem->linep;
    }
    renum();

    if (toolong) {
	sprintf(IObuff, "\"%s\" Line too long", fname);
	msg(IObuff);
	return FALSE;
    }
    sprintf(IObuff, "\"%s\" %s%d line%s, %ld character%s",
	    fname,
	    incomplete ? "[Incomplete last line] " : "",
	    linecnt, (linecnt > 1) ? "s" : "",
	    nchars, (nchars > 1) ? "s" : "");

    buf2[0] = NUL;

    if (nonascii || nulls) {
	if (nonascii) {
	    if (nulls)
		sprintf(buf2, " (%d null, %d non-ASCII)",
			nulls, nonascii);
	    else
		sprintf(buf2, " (%d non-ASCII)", nonascii);
	} else
	    sprintf(buf2, " (%d null)", nulls);
    }
    strcat(IObuff, buf2);
    msg(IObuff);

    return FALSE;
}

/*
 * writeit - write to file 'fname' lines 'start' through 'end' 
 *
 * If either 'start' or 'end' contain null line pointers, the default is to use
 * the start or end of the file respectively. 
 */
bool_t
writeit(fname, start, end)
    char           *fname;
    LPtr           *start, *end;
{
    FILE           *f, *fopen();
    FILE           *fopenb();	/* open in binary mode, where needed */
    char           *backup, *s;
    long            nchars;
    int             lines;
    LPtr           *p;

    sprintf(IObuff, "\"%s\"", fname);
    msg(IObuff);

    /*
     * Form the backup file name - change foo.* to foo.bak 
     */
    backup = alloc((unsigned) (strlen(fname) + 5));
    strcpy(backup, fname);
    for (s = backup; *s && *s != '.'; s++);
    *s = NUL;
    strcat(backup, ".bak");

    /*
     * Delete any existing backup and move the current version to the backup.
     * For safety, we don't remove the backup until the write has finished
     * successfully. And if the 'backup' option is set, leave it around. 
     */
    rename(fname, backup);

    f = P(P_CR) ? fopen(fname, "w") : fopenb(fname, "w");

    if (f == NULL) {
	emsg("Can't open file for writing!");
	free((char *) backup);
	return FALSE;
    }
    /*
     * If we were given a bound, start there. Otherwise just start at the
     * beginning of the file. 
     */
    if (start == NULL || start->linep == NULL)
	p = Filemem;
    else
	p = start;

    lines = 0;
    nchars = 0;
    do {
	fprintf(f, "%s\n", p->linep->s);
	nchars += strlen(p->linep->s) + 1;
	lines++;

	/*
	 * If we were given an upper bound, and we just did that line, then
	 * bag it now. 
	 */
	if (end != NULL && end->linep != NULL) {
	    if (end->linep == p->linep)
		break;
	}
    } while ((p = nextline(p)) != NULL);

    fclose(f);
    sprintf(IObuff, "\"%s\" %d line%s, %ld character%s", fname,
	    lines, (lines > 1) ? "s" : "",
	    nchars, (nchars > 1) ? "s" : "");
    msg(IObuff);
    UNCHANGED;

    /*
     * Remove the backup unless they want it left around 
     */
    if (!P(P_BK))
	remove(backup);

    free((char *) backup);

    return TRUE;
}
SHAR_EOF
cat << \SHAR_EOF > os2.c
/*
 * OS/2 System-dependent routines.
 *
 * $Log:	os2.c,v $
 * Revision 1.2  88/04/25  16:50:19  tony
 * Minor changes for OS/2 version 1.1; also fixed up the RCS header.
 * 
 * Revision 1.1  88/03/21  12:04:23  tony
 * Initial revision
 * 
 *
 */

#define	INCL_BASE
#include <os2.h>
#include "stevie.h"

/*
 * inchar() - get a character from the keyboard
 */
int
inchar()
{
    int             c;

    for (;; beep()) {		/* loop until we get a valid character */

	flushbuf();		/* flush any pending output */

	switch (c = getch()) {
	  case 0x1e:
	    return K_CGRAVE;
	  case 0:		/* special key */
	  case 0xe0:		/* special key */
	    if (State != NORMAL) {
		c = getch();	/* throw away next char */
		continue;	/* and loop for another char */
	    }
	    switch (c = getch()) {
	      case 0x50:
		return K_DARROW;
	      case 0x48:
		return K_UARROW;
	      case 0x4b:
		return K_LARROW;
	      case 0x4d:
		return K_RARROW;
	      case 0x52:
		return K_INSERT;
	      case 0x47:
		stuffReadbuff("1G");
		return -1;
	      case 0x4f:
		stuffReadbuff("G");
		return -1;
	      case 0x51:
		stuffReadbuff(mkstr(CTRL('F')));
		return -1;
	      case 0x49:
		stuffReadbuff(mkstr(CTRL('B')));
		return -1;
		/*
		 * Hard-code some useful function key macros. 
		 */
	      case 0x3b:	/* F1 */
		stuffReadbuff(":p\n");
		return -1;
	      case 0x54:	/* SF1 */
		stuffReadbuff(":p!\n");
		return -1;
	      case 0x3c:	/* F2 */
		stuffReadbuff(":n\n");
		return -1;
	      case 0x55:	/* SF2 */
		stuffReadbuff(":n!\n");
		return -1;
	      case 0x3d:	/* F3 */
		stuffReadbuff(":e #\n");
		return -1;
	      case 0x3e:	/* F4 */
		stuffReadbuff(":rew\n");
		return -1;
	      case 0x57:	/* SF4 */
		stuffReadbuff(":rew!\n");
		return -1;
	      case 0x3f:	/* F5 */
		stuffReadbuff("[[");
		return -1;
	      case 0x40:	/* F6 */
		stuffReadbuff("]]");
		return -1;
	      case 0x41:	/* F7 */
		stuffReadbuff("<<");
		return -1;
	      case 0x42:	/* F8 */
		stuffReadbuff(">>");
		return -1;
	      case 0x43:	/* F9 */
		stuffReadbuff(":x\n");
		return -1;
	      case 0x44:	/* F10 */
		stuffReadbuff(":help\n");
		return -1;
	      default:
		break;
	    }
	    break;

	  default:
	    return c;
	}
    }
}

#define	BSIZE	2048
static char     outbuf[BSIZE];
static int      bpos = 0;

flushbuf()
{
    if (bpos != 0)
	write(1, outbuf, bpos);
    bpos = 0;
}

/*
 * Macro to output a character. Used within this file for speed.
 */
#define	outone(c)	outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()

/*
 * Function version for use outside this file.
 */

void
outchar(c)
    register char   c;
{
    outbuf[bpos++] = c;
    if (bpos >= BSIZE)
	flushbuf();
}

static char     cell[2] = {0, 7};

/*
 * outstr(s) - write a string to the console
 *
 * We implement insert/delete line escape sequences here. This is kind
 * of a kludge, but at least it's localized to a single point.
 */
void
outstr(s)
    register char  *s;
{
    if (strcmp(s, T_DL) == 0) {	/* delete line */
	int             r, c;

	flushbuf();
	VioGetCurPos(&r, &c, 0);
	VioScrollUp(r, 0, 100, 100, 1, cell, 0);
	return;
    }
    if (strcmp(s, T_IL) == 0) {	/* insert line */
	int             r, c;

	flushbuf();
	VioGetCurPos(&r, &c, 0);
	VioScrollDn(r, 0, 100, 100, 1, cell, 0);
	return;
    }
    while (*s) {
	outone(*s++);
    }
}

void
beep()
{
    if (RedrawingDisabled)
	return;

    outone('\007');
}

void
sleep(n)
    int             n;
{
    DosSleep(1000L * n);
}

void
delay()
{
    flushbuf();
    DosSleep(300L);
}

void
windinit()
{
    Columns = 80;
    P(P_LI) = Rows = 25;
}

void
windexit(r)
    int             r;
{
    flushbuf();
    exit(r);
}

void
windgoto(r, c)
    register int    r, c;
{
    r += 1;
    c += 1;

/* I would recommend the following: 
	flushbuf();
	VioSetCurPos(r, c, 0);
Alex */

    /*
     * Check for overflow once, to save time. 
     */
    if (bpos + 8 >= BSIZE)
	flushbuf();

    outbuf[bpos++] = '\033';
    outbuf[bpos++] = '[';
    if (r >= 10)
	outbuf[bpos++] = r / 10 + '0';
    outbuf[bpos++] = r % 10 + '0';
    outbuf[bpos++] = ';';
    if (c >= 10)
	outbuf[bpos++] = c / 10 + '0';
    outbuf[bpos++] = c % 10 + '0';
    outbuf[bpos++] = 'H';
}

FILE           *
fopenb(fname, mode)
    char           *fname;
    char           *mode;
{
    FILE           *fopen();
    char            modestr[16];

    sprintf(modestr, "%sb", mode);
    return fopen(fname, modestr);
}
SHAR_EOF
cat << \SHAR_EOF > stevie.h
/*
 * STEVIE - Simply Try this Editor for VI Enthusiasts
 *
 * Code Contributions By : Tim Thompson           twitch!tjt
 *                         Tony Andrews           onecom!wldrdg!tony 
 *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
 */

#include "env.h"

#include <stdio.h>
#ifndef ATARI
# ifndef UNIX
#   include <stdlib.h>
# endif
#endif
#include <ctype.h>
#ifndef MWC
# include <string.h>
#endif
#include "ascii.h"
#include "keymap.h"
#include "param.h"
#include "term.h"
#include "macros.h"

#ifdef AMIGA
/*
 * This won't be needed if you have a version of Lattice 4.01 without broken
 * break signal handling.
 */
#include <signal.h>
#endif

extern char    *strchr();

#define NORMAL			 0
#define CMDLINE			 1
#define INSERT			 2
#define APPEND			 3
#define UNDO			 4
#define REDO			 5
#define PUT			 6
#define FORWARD			 7
#define BACKWARD		 8
#define VALID			 9
#define NOT_VALID		10
#define VALID_TO_CURSCHAR	11

/*
 * Boolean type definition and constants 
 */
typedef int     bool_t;

#ifndef	TRUE
#define	FALSE	(0)
#define	TRUE	(1)
#endif
#define	SORTOF	(2)
#define YES      TRUE
#define NO       FALSE
#define MAYBE    SORTOF

/*
 * Maximum screen dimensions
 */
#define MAX_COLUMNS 140L

/*
 * Buffer sizes
 */
#define CMDBUFFSIZE MAX_COLUMNS	/* size of the command processing buffer */

#define LSIZE        512	/* max. size of a line in the tags file */

#define IOSIZE     (1024+1)	/* file i/o and sprintf buffer size */

#define YANKSIZE    5200	/* yank buffer size */
#define INSERT_SIZE 5300	/* insert, redo and undo buffer size must be
				 * bigger than YANKSIZE */
#define REDO_UNDO_SIZE 5400	/* redo, undo and (undo an undo) buffer size
				 * must be bigger than INSERT_SIZE */
#define READSIZE    5500	/* read buffer size must be bigger than
				 * YANKSIZE and REDO_UNDO_SIZE */

/*
 * SLOP is the amount of extra space we get for text on a line during editing
 * operations that need more space. This keeps us from calling alloc every
 * time we get a character during insert mode. No extra space is allocated
 * when the file is initially read. 
 */
#define	SLOP	10

/*
 * LINEINC is the gap we leave between the artificial line numbers. This
 * helps to avoid renumbering all the lines every time a new line is
 * inserted. 
 *
 * Since line numbers are stored in longs (32 bits), a LINEINC of 10000
 * lets us have > 200,000 lines and we won't have to renumber very often.
 */
#define	LINEINC	10000

#define CHANGED   { Changed = TRUE; }
#define UNCHANGED { Changed = FALSE; }

struct line {
    struct line    *next;	/* next line */
    struct line    *prev;	/* previous line */
    char           *s;		/* text for this line */
    int             size;	/* actual size of space at 's' */
    unsigned long   num;	/* line "number" */
};

#define	LINEOF(x)	((x)->linep->num)

struct lptr {
    struct line    *linep;	/* line we're referencing */
    int             index;	/* position within that line */
};

typedef struct line LINE;
typedef struct lptr LPtr;

struct charinfo {
    char            ch_size;
    char           *ch_str;
};

extern struct charinfo chars[];

extern int      State;
extern int      Rows;
extern int      Columns;
extern char    *Realscreen;
extern char    *Nextscreen;
extern int      NumLineSizes;
extern LINE   **LinePointers;
extern char    *LineSizes;
extern char    *Filename;
extern LPtr    *Filemem;
extern LPtr    *Filetop;
extern LPtr    *Fileend;
extern LPtr    *Topchar;
extern LPtr    *Botchar;
extern LPtr    *Curschar;
extern LPtr    *Insstart;
extern int      Cursrow, Curscol, Cursvcol, Curswant;
extern bool_t   set_want_col;
extern int      Prenum;
extern bool_t   Changed;
extern bool_t   RedrawingDisabled;
extern bool_t   MustRedrawLine;
extern bool_t   MustRedrawScreen;
extern bool_t   UndoInProgress;
extern bool_t   Binary;
extern char    *IObuff;
extern char    *Insbuffptr;
extern char    *Insbuff;
extern char    *Readbuffptr;
extern char    *Readbuff;
extern char    *Redobuffptr;
extern char    *Redobuff;
extern char    *Undobuffptr;
extern char    *Undobuff;
extern char    *UndoUndobuffptr;
extern char    *UndoUndobuff;
extern char    *Yankbuffptr;
extern char    *Yankbuff;
extern char     last_command;
extern char     last_command_char;

extern char    *strcpy();

/* alloc.c */
char  *alloc();
char  *strsave();
void   screenalloc(), filealloc(), freeall();
LINE  *newline();
bool_t canincrease();

/* cmdline.c */
void   readcmdline();
void   dotag();
void   msg(), emsg(), smsg();
void   gotocmdline();
void   wait_return();

/* dec.c */
int    dec();

/* edit.c */
void   edit(), insertchar(), getout(), scrollup(), scrolldown(), beginline();
bool_t oneright(), oneleft(), oneup(), onedown();

/* fileio.c */
void   filemess(), renum();
bool_t readfile(), writeit();

/* updateNs.c */
void   updateNextscreen();

/* updateRs.c */
void   updateRealscreen();

/* help.c */
bool_t help();

/* inc.c */
int    inc();

/* linefunc.c */
LPtr   *nextline(), *prevline(), *coladvance();

/* main.c */
void   stuffReadbuff();
void   stuffnumReadbuff();
char   vgetc();
char   vpeekc();

/* mark.c */
void   setpcmark(), clrall(), clrmark();
bool_t setmark();
LPtr  *getmark();

/* misccmds.c */
bool_t OpenForward();
bool_t OpenBackward();
void   fileinfo(), inschar(), insstr(), delline();
bool_t delchar();
int    cntllines(), plines();
LPtr  *gotoline();

/* normal.c */
void   normal();
void   ResetBuffers();
void   AppendToInsbuff();
void   AppendToRedobuff();
void   AppendNumberToRedobuff();
void   AppendToUndobuff();
void   AppendNumberToUndobuff();
void   AppendPositionToUndobuff();
void   AppendToUndoUndobuff();
void   AppendNumberToUndoUndobuff();
void   AppendPositionToUndoUndobuff();
bool_t linewhite();

/* mk.c */
char  *mkstr();
char  *mkline();

/* param.c */
void   doset();

/* screen.c */
void   nexttoscreen();
void   updateline();
void   redrawline();
void   screenclear();
void   cursupdate();
void   prt_line();
void   s_del();
void   s_ins();

/* search.c */
void   doglob();
void   dosub();
void   searchagain();
bool_t dosearch();
bool_t repsearch();
bool_t searchc(), crepsearch(), findfunc();
LPtr  *showmatch();
LPtr  *fwd_word(), *bck_word(), *end_word();

/*
 * Machine-dependent routines. 
 */
#ifdef AMIGA
# include "amiga.h"
#endif
#ifdef BSD
# include "bsd.h"
#endif
#ifdef UNIX
# include "unix.h"
#endif
#ifdef TOS
# include "tos.h"
#endif
#ifdef OS2
# include "os2.h"
#endif
#ifdef DOS
# include "dos.h"
#endif
SHAR_EOF
cat << \SHAR_EOF > tags
ISSPECIAL	edit.c	/^#define	ISSPECIAL(c)	((c) == BS || (c) == NL || (c/
alloc	alloc.c	/^alloc(size)$/
badcmd	cmdline.c	/^badcmd()$/
beginline	edit.c	/^beginline(flag)$/
canincrease	alloc.c	/^canincrease(n)$/
dec	dec.c	/^dec(lp)$/
doecmd	cmdline.c	/^doecmd(arg, force)$/
doshell	cmdline.c	/^doshell()$/
dotag	cmdline.c	/^dotag(tag, force)$/
edit	edit.c	/^edit()$/
emsg	cmdline.c	/^emsg(s)$/
filealloc	alloc.c	/^filealloc()$/
freeall	alloc.c	/^freeall()$/
get_line	cmdline.c	/^get_line(cp)$/
get_range	cmdline.c	/^get_range(cp)$/
getout	edit.c	/^getout(r)$/
gotocmdline	cmdline.c	/^gotocmdline(clr, firstc)$/
insertchar	edit.c	/^insertchar(c)$/
msg	cmdline.c	/^msg(s)$/
newline	alloc.c	/^newline(nchars)$/
onedown	edit.c	/^onedown(n)$/
oneleft	edit.c	/^oneleft()$/
oneright	edit.c	/^oneright()$/
oneup	edit.c	/^oneup(n)$/
readcmdline	cmdline.c	/^readcmdline(firstc, cmdline)$/
screenalloc	alloc.c	/^screenalloc()$/
scrolldown	edit.c	/^scrolldown(nlines)$/
scrollup	edit.c	/^scrollup(nlines)$/
smsg	cmdline.c	/^smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)$/
strsave	alloc.c	/^strsave(string)$/
wait_return	cmdline.c	/^wait_return()$/
Mmain	main.c	/^main(argc, argv)$/
clrall	mark.c	/^clrall()$/
clrmark	mark.c	/^clrmark(line)$/
coladvance	linefunc.c	/^coladvance(p, col)$/
filemess	fileio.c	/^filemess(s)$/
getmark	mark.c	/^getmark(c)$/
help	help.c	/^help()$/
inc	inc.c	/^inc(lp)$/
longline	help.c	/^longline(p)$/
nextline	linefunc.c	/^nextline(curr)$/
prevline	linefunc.c	/^prevline(curr)$/
readfile	fileio.c	/^readfile(fname, fromp, nochangename)$/
renum	fileio.c	/^renum()$/
setmark	mark.c	/^setmark(c)$/
setpcmark	mark.c	/^setpcmark()$/
stuffReadbuff	main.c	/^stuffReadbuff(s)$/
stuffnumReadbuff	main.c	/^stuffnumReadbuff(n)$/
usage	main.c	/^usage()$/
vgetc	main.c	/^vgetc()$/
vpeekc	main.c	/^vpeekc()$/
writeit	fileio.c	/^writeit(fname, start, end)$/
AppendNumberToRedobuff	normal.c	/^AppendNumberToRedobuff(n)$/
AppendNumberToUndoUndobuff	normal.c	/^AppendNumberToUndoUndobuff(n)$/
AppendNumberToUndobuff	normal.c	/^AppendNumberToUndobuff(n)$/
AppendPositionToUndoUndobuff	normal.c	/^AppendPositionToUndoUndobuff(column, row)$/
AppendPositionToUndobuff	normal.c	/^AppendPositionToUndobuff(column, row)$/
AppendToInsbuff	normal.c	/^AppendToInsbuff(s)$/
AppendToRedobuff	normal.c	/^AppendToRedobuff(s)$/
AppendToUndoUndobuff	normal.c	/^AppendToUndoUndobuff(s)$/
AppendToUndobuff	normal.c	/^AppendToUndobuff(s)$/
DEFAULT1	normal.c	/^#define	DEFAULT1(x)	(((x) == 0) ? 1 : (x))$/
IDCHAR	normal.c	/^#define	IDCHAR(c)	(isalpha(c) || isdigit(c) || (c)/
OpenBackward	misccmds.c	/^OpenBackward(can_ai)$/
OpenForward	misccmds.c	/^OpenForward(can_ai)$/
ResetBuffers	normal.c	/^ResetBuffers()$/
cntllines	misccmds.c	/^cntllines(pbegin, pend)$/
cooked	raw.c	/^cooked(fp)$/
cursupdate	screen.c	/^cursupdate()$/
delchar	misccmds.c	/^delchar(fixpos, undo)$/
delline	misccmds.c	/^delline(nlines, can_update)$/
dochange	normal.c	/^dochange()$/
dodelete	normal.c	/^dodelete(redraw, setup_for_undo, try_to_yank)$/
dojoin	normal.c	/^dojoin(leading_space, strip_leading_spaces)$/
doput	normal.c	/^doput(dir)$/
doset	param.c	/^doset(arg, inter)$/
doshift	normal.c	/^doshift(op)$/
doyank	normal.c	/^doyank()$/
fileinfo	misccmds.c	/^fileinfo()$/
gotoline	misccmds.c	/^gotoline(n)$/
inschar	misccmds.c	/^inschar(c)$/
insstr	misccmds.c	/^insstr(s)$/
linewhite	normal.c	/^linewhite(p)$/
normal	normal.c	/^normal(c)$/
plines	misccmds.c	/^plines(p)$/
prt_line	screen.c	/^prt_line(s)$/
raw	raw.c	/^raw(fp)$/
redrawline	screen.c	/^redrawline()$/
s_del	screen.c	/^s_del(row, nlines)$/
s_ins	screen.c	/^s_ins(row, nlines)$/
screenclear	screen.c	/^screenclear()$/
showparms	param.c	/^showparms(all)$/
startinsert	normal.c	/^startinsert(startln)$/
tabinout	normal.c	/^tabinout(shift_type, num)$/
updateline	screen.c	/^updateline()$/
C0	search.c	/^#define	C0(c)	(((c) == ' ') || ((c) == '\\t') || ((/
C1	search.c	/^#define	C1(c)	(isalpha(c) || isdigit(c) || ((c) ==/
OTHERDIR	search.c	/^#define	OTHERDIR(x)	(((x) == FORWARD) ? BACKWARD :/
SendPacket	sendpacket.c	/^SendPacket(pid, action, args, nargs)$/
bck_word	search.c	/^bck_word(p, type)$/
bcksearch	search.c	/^bcksearch(str)$/
cls	search.c	/^cls(c)$/
crepsearch	search.c	/^crepsearch(flag)$/
doglob	search.c	/^doglob(lp, up, cmd)$/
dosearch	search.c	/^dosearch(dir, str)$/
dosub	search.c	/^dosub(lp, up, cmd)$/
end_word	search.c	/^end_word(p, type)$/
findfunc	search.c	/^findfunc(dir)$/
fwd_word	search.c	/^fwd_word(p, type)$/
fwdsearch	search.c	/^fwdsearch(str)$/
mapstring	search.c	/^mapstring(s)$/
regerror	search.c	/^regerror(s)$/
repsearch	search.c	/^repsearch(flag)$/
searchagain	search.c	/^searchagain(dir)$/
searchc	search.c	/^searchc(c, dir, type)$/
showmatch	search.c	/^showmatch()$/
ssearch	search.c	/^ssearch(dir, str)$/
updateNextscreen	updateNs.c	/^updateNextscreen(type)$/
CTRL	ascii.h	/^#define	CTRL(x)	((x) & 0x1f)$/
updateRealscreen	updateRs.c	/^updateRealscreen()$/
LINE	stevie.h	122
LINEOF	stevie.h	/^#define	LINEOF(x)	((x)->linep->num)$/
LPTR	stevie.h	123
P	param.h	/^#define	P(n)	(params[n].value)$/
RowNumber	macros.h	/^#define RowNumber(p) (UndoInProgress ? 0 : cntllin/
anyinput	macros.h	/^#define anyinput() (Readbuffptr != NULL)$/
bool_t	stevie.h	53
buf1line	macros.h	/^#define buf1line() (Filemem->linep->next == Fileen/
bufempty	macros.h	/^#define bufempty() (buf1line() && Filemem->linep->/
endofline	macros.h	/^#define endofline(p) \\$/
equal	macros.h	/^#define equal(a, b) (((a)->linep == (b)->linep) &&/
gchar	macros.h	/^#define gchar(lp) ((lp)->linep->s[(lp)->index])$/
gt	macros.h	/^#define gt(a, b) ((LINEOF(a) != LINEOF(b)) \\$/
gtoreq	macros.h	/^#define gtoreq(a, b) ((LINEOF(a) != LINEOF(b)) \\$/
lineempty	macros.h	/^#define lineempty(p) ((p)->linep->s[0] == NUL)$/
lt	macros.h	/^#define lt(a, b) ((LINEOF(a) != LINEOF(b)) \\$/
ltoreq	macros.h	/^#define ltoreq(a, b) ((LINEOF(a) != LINEOF(b)) \\$/
mkline	mk.c	/^mkline(n)$/
mkstr	mk.c	/^mkstr(c)$/
pchar	macros.h	/^#define pchar(lp, c) ((lp)->linep->s[(lp)->index] /
pswap	macros.h	/^#define pswap(a, b) { LPTR pswaptmp; pswaptmp = a;/
startofline	macros.h	/^#define startofline(p) ((p)->index == 0)$/
GetCharacter	amiga.c	/^GetCharacter()$/
beep	amiga.c	/^beep()$/
delay	amiga.c	/^delay()$/
flushbuf	amiga.c	/^flushbuf()$/
fopenb	amiga.c	/^fopenb(fname, mode)$/
getCSIsequence	amiga.c	/^getCSIsequence()$/
inchar	amiga.c	/^inchar()$/
outchar	amiga.c	/^outchar(c)$/
outone	amiga.c	/^#define	outone(c)	outbuf[bpos++] = c; if (bpos >= /
outstr	amiga.c	/^outstr(s)$/
sleep	amiga.c	/^sleep(n)$/
windexit	amiga.c	/^windexit(r)$/
windgoto	amiga.c	/^windgoto(r, c)$/
windinit	amiga.c	/^windinit()$/
SHAR_EOF
cat << \SHAR_EOF > term.h
/*
 * STEVIE - Simply Try this Editor for VI Enthusiasts
 *
 * Code Contributions By : Tim Thompson           twitch!tjt
 *                         Tony Andrews           onecom!wldrdg!tony 
 *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
 */

/*
 * This file contains the machine dependent escape sequences that the editor
 * needs to perform various operations. Some of the sequences here are
 * optional. Anything not available should be indicated by a null string. In
 * the case of insert/delete line sequences, the editor checks the capability
 * and works around the deficiency, if necessary. 
 *
 * Currently, insert/delete line sequences are used for screen scrolling. There
 * are lots of terminals that have 'index' and 'reverse index' capabilities,
 * but no line insert/delete. For this reason, the editor routines s_ins()
 * and s_del() should be modified to use 'index' sequences when the line to
 * be inserted or deleted at line zero. 
 */

/*
 * The macro names here correspond (more or less) to the actual ANSI names 
 */

#ifdef	ATARI
#define	T_EL	"\033l"		/* erase the entire current line */
#define	T_IL	"\033L"		/* insert one line */
#define	T_IL_B	""
#define	T_DL	"\033M"		/* delete one line */
#define	T_DL_B	""
#define	T_SC	"\033j"		/* save the cursor position */
#define	T_ED	"\033E"		/* erase display (may optionally home cursor) */
#define	T_RC	"\033k"		/* restore the cursor position */
#define	T_CI	"\033f"		/* invisible cursor (very optional) */
#define	T_CV	"\033e"		/* visible cursor (very optional) */
#define T_TP    ""		/* plain text */
#define T_TI    ""		/* inverse-video text */
#endif

#ifdef	UNIX
/*
 * The UNIX sequences are hard-wired for ansi-like terminals. I should really
 * use termcap/terminfo, but the UNIX port was done for profiling, not for
 * actual use, so it wasn't worth the effort. 
 */
#define	T_EL	"\033[2K"	/* erase the entire current line */
#define	T_IL	"\033[L"	/* insert one line */
#define	T_IL_B	""
#define	T_DL	"\033[M"	/* delete one line */
#define	T_DL_B	""
#define	T_ED	"\033[2J"	/* erase display (may optionally home cursor) */
#define	T_SC	"\0337"		/* save the cursor position */
#define	T_RC	"\0338"		/* restore the cursor position */
#define	T_CI	""		/* invisible cursor (very optional) */
#define	T_CV	""		/* visible cursor (very optional) */
#define T_TP    ""		/* plain text */
#define T_TI    ""		/* inverse-video text */
#endif

#ifdef	BSD
/* The BSD 4.3 sequences are hard-wired for ansi-like terminals. */
#define	T_EL	"\033[2K"	/* erase the entire current line */
#define	T_IL	"\033[L"	/* insert line */
#define	T_IL_B	""
#define	T_DL	"\033[M"	/* delete line */
#define	T_DL_B	""
#define	T_ED	"\033[2J"	/* erase display (may optionally home cursor) */
#define	T_SC	""		/* save the cursor position */
#define	T_RC	""		/* restore the cursor position */
#define	T_CI	""		/* invisible cursor (very optional) */
#define	T_CV	""		/* visible cursor (very optional) */
#define T_TP    ""		/* plain text */
#define T_TI    ""		/* inverse-video text */
#endif

#ifdef	OS2
/*
 * The OS/2 ansi console driver is pretty deficient. No insert or delete line
 * sequences. The erase line sequence only erases from the cursor to the end
 * of the line. For our purposes that works out okay, since the only time
 * T_EL is used is when the cursor is in column 0.
 *
 * The insert/delete line sequences marked here are actually implemented in
 * the file os2.c using direct OS/2 system calls. This makes the capability
 * available for the rest of the editor via appropriate escape sequences
 * passed to outstr().
 */
#define	T_EL	"\033[K"	/* erase the entire current line */
#define	T_IL	"\033[L"	/* insert one line - fake (see os2.c) */
#define	T_IL_B	""
#define	T_DL	"\033[M"	/* delete one line - fake (see os2.c) */
#define	T_DL_B	""
#define	T_ED	"\033[2J"	/* erase display (may optionally home cursor) */
#define	T_SC	"\033[s"	/* save the cursor position */
#define	T_RC	"\033[u"	/* restore the cursor position */
#define	T_CI	""		/* invisible cursor (very optional) */
#define	T_CV	""		/* visible cursor (very optional) */
#define T_TP    ""		/* plain text */
#define T_TI    ""		/* inverse-video text */
#endif

#ifdef AMIGA
/*
 * The erase line sequence only erases from the cursor to the end of the
 * line. For our purposes that works out okay, since the only time T_EL is
 * used is when the cursor is in column 0. 
 */
#define	T_EL	"\033[K"	/* erase the entire current line */
#define	T_IL	"\033["		/* insert line */
#define	T_IL_B	"L"
#define	T_DL	"\033["		/* delete line */
#define	T_DL_B	"M"
#define	T_ED	"\014"		/* erase display (may optionally home cursor) */
#define	T_RC	""		/* restore the cursor position */
#define	T_SC	""		/* save the cursor position */
#define	T_CI	"\033[0 p"	/* invisible cursor (very optional) */
#define	T_CV	"\033[1 p"	/* visible cursor (very optional) */
#define T_TP    "\033[0m"	/* plain text */
#define T_TI    "\033[7m"	/* inverse-video text */
#endif

#ifdef	DOS
/*
 * DOS sequences
 *
 * Some of the following sequences require the use of the "nansi.sys"
 * console driver. The standard "ansi.sys" driver doesn't support
 * sequences for insert/delete line.
 */
#define	T_EL	"\033[K"	/* erase the entire current line */
#define	T_IL	"\033[L"	/* insert line (requires nansi.sys driver) */
#define	T_IL_B	""
#define	T_DL	"\033[M"	/* delete line (requires nansi.sys driver) */
#define	T_DL_B	""
#define	T_ED	"\033[2J"	/* erase display (may optionally home cursor) */
#define	T_SC	"\033[s"	/* save the cursor position */
#define	T_RC	"\033[u"	/* restore the cursor position */
#define	T_CI	""		/* invisible cursor (very optional) */
#define	T_CV	""		/* visible cursor (very optional) */
#define T_TP    ""		/* plain text */
#define T_TI    ""		/* inverse-video text */
#endif
SHAR_EOF
cat << \SHAR_EOF > tos.h
/*
 * Atari Machine-dependent routines. 
 */

int  inchar();
void outchar();
void outstr(), beep();
void remove(), rename();
void windinit(), windexit(), windgoto();
void delay();
void sleep();
SHAR_EOF
cat << \SHAR_EOF > version.c
/*
 * STEVIE - Simply Try this Editor for VI Enthusiasts
 *
 * Code Contributions By : Tim Thompson           twitch!tjt
 *                         Tony Andrews           onecom!wldrdg!tony 
 *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
 */

/*
 * Version  Changes (and person who did them)
 * -------  ---------------------------------
 * 3.10     - version that started it all. Found on comp.sources.unix
 *            Jun88 Volume 15 i037, i038, i039, i040, i042, and INF3
 *          - Tim Thompson and Tony Andrews
 * 
 * 3.10A    - took version of STEVIE posted to usenet and added Amiga
 *            and BSD support; added undo and redo commands; sped up
 *            output to screen; sped up on-screen activities (such as
 *            cursoring); fixed miscellaneous small bugs and changed some
 *            commands so that they more closely resembled vi.
 *          - GRWalter (Fred)
 * 
 * 3.11B    - added the ability to be run in the background (STEVIE will
 *            attempt to use the current window, but if it can't then it
 *            will open its own window). Fixed some other miscellaneous
 *            bugs (some to do with re-sizing the screen, one to do with
 *            undo'ing changes on lines that start with whitespace).
 *          - GRWalter (Fred)
 * 
 * 3.11C    - fixed a bug that was causing the entire screen to be refreshed
 *            at the wrong times sometimes. Input mode was sped up as well
 *            as a bug involving lines that wrapped was fixed. Changed :ta
 *            a bit. Fixed bug triggered when files are > 6000 lines.
 *          - GRWalter (Fred)
 *
 * 3.31A    - Tony Andrews put out a divergent version of STEVIE (version 3.31).
 *            I moved the important stuff over into my version.
 *
 *            Here is a list of what was moved over :
 * 
 *************************************************************************
 * Revision 3.29  88/06/26  14:53:19  tony
 * Added support for a simple form of the "global" command. It supports
 * commands of the form "g/pat/d" or "g/pat/p", to delete or print lines
 * that match the given pattern. A range spec may be used to limit the
 * lines to be searched.
 * 
 * Revision 3.28  88/06/25  21:44:22  tony
 * Fixed a problem in the processing of colon commands that caused
 * substitutions of patterns containing white space to fail.
 * 
 * Revision 3.26  88/06/10  13:44:06  tony
 * Fixed a bug involving writing out files with long pathnames. A small
 * fixed size buffer was being used. The space for the backup file name
 * is now allocated dynamically.
 * 
 * Revision 1.12  88/05/03  14:39:52  tony
 * Also merged in support for DOS.
 * 
 * Revision 1.11  88/05/02  21:38:21  tony
 * The code that reads files now handles boundary/error conditions much
 * better, and generates status/error messages that are compatible with
 * the real vi. Also fixed a bug in repeated reverse searches that got
 * inserted in the recent changes to search.c.
 * 
 * Revision 1.10  88/05/02  07:35:41  tony
 * Fixed a bug in the routine plines() that was introduced during changes
 * made for the last version.
 * 
 * Revision 1.9  88/05/01  20:10:19  tony
 * Fixed some problems with auto-indent, and added support for the "number"
 * parameter.
 * 
 * Revision 1.8  88/04/30  20:00:49  tony
 * Added support for the auto-indent feature.
 * 
 * Revision 1.6  88/04/28  08:19:35  tony
 * Modified Henry Spencer's regular expression library to support new
 * features that couldn't be done easily with the existing interface.
 * This code is now a direct part of the editor source code. The editor
 * now supports the "ignorecase" parameter, and multiple substitutions
 * per line, as in "1,$s/foo/bar/g".
 * 
 * Revision 1.5  88/04/24  21:38:00  tony
 * Added preliminary support for the substitute command. Full range specs.
 * are supported, but only a single substitution is allowed on each line.
 * 
 * Revision 1.4  88/04/23  20:41:01  tony
 * Worked around a problem with adding lines to the end of the buffer when
 * the cursor is at the bottom of the screen (in misccmds.c). Also fixed a
 * bug that caused reverse searches from the start of the file to bomb.
 * 
 * Revision 1.3  88/03/24  08:57:00  tony
 * Fixed a bug in cmdline() that had to do with backspacing out of colon
 * commands or searches. Searches were okay, but colon commands backed out
 * one backspace too early.
 * 
 * Revision 1.2  88/03/21  16:47:55  tony
 * Fixed a bug in renum() causing problems with large files (>6400 lines).
 *************************************************************************
 *          - GRWalter (Fred)
 *
 * 3.32A    - added the :[range]d command. Played with 'p' and 'P'.
 *            Added undo capability to :s and :g//d commands.
 *            Added '%' as a line range specifier (entire file).
 *            Fixed search so that tags file from real ctags could be used.
 *            Fixed undo after delete everything operation.
 *            Made prt_line work in nu mode (so :g//p works right).
 *            Fixed ai mode (when there was text after the cursor it didn't ai).
 *            Fixed 'J' (didn't handle next line just having whitespace).
 *            Fixed :[range] so it behaves like the real vi (goes to highest
 *            line number in the given range).
 *            Made it so that the cursor is on the last char inserted instead
 *            the one right after when there is exactly 1 char right after.
 *            Made change operator work properly when it ended on the
 *            end of the line.
 *          - GRWalter (Fred)
 *
 * 3.33A    - no longer updateNextscreen when putting or undoing or
 *            redoing until I am done. 'p', 'u' and '.' thus sped up.
 *          - no longer recalculate line lengths when cursupdate() called,
 *            which speeds up lots'a things (like on-screen cursoring).
 *          - avoid redrawing (in updateNextscreen) as much as possible, which
 *            speeds up (among other things) cursoring (off screen), put, undo,
 *            redo, etc.
 *          - GRWalter (Fred)
 *
 * 3.34A    - rewrote updateNextscreen and updatenextline so they won't do as
 *            much work. Sped up cursoring off-screen. Fixed bug in cursupdate
 *            (could index through NULL pointer).
 *          - GRWalter (Fred)
 *
 * 3.35A    - Compiles with Lattice 5.0 now - needed miscellaneous changes.
 *          - Environment variables (EXINIT) finally used.
 *          - Stevie is now compiled so it's residentable.
 *          - Fixed bug in insstr() (caused problems with redo of inserts).
 *          - Fixed buffer overflow/corrupt messages.
 *          - Tweaked updateNextscreen routine some more.
 *          - Added __DATE__ and __TIME__ of compilation to help screen.
 *          - GRWalter (Fred)
 */

char           *Version = "STEVIE - Version 3.35A";
SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.