#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 13)."
# Contents:  stevie/edit.c stevie/minix.c stevie/os2.c stevie/tagcmd.c
#   stevie/undo.c
# Wrapped by thor@surt on Fri Oct 16 09:43:46 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'stevie/edit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stevie/edit.c'\"
else
echo shar: Extracting \"'stevie/edit.c'\" \(6635 characters\)
sed "s/^X//" >'stevie/edit.c' <<'END_OF_FILE'
X/* $Header: /nw/tony/src/stevie/src/RCS/edit.c,v 1.11 89/08/02 19:57:12 tony Exp $
X *
X * The main edit loop as well as some other simple cursor movement routines.
X */
X
X#include "stevie.h"
X
X/*
X * This flag is used to make auto-indent work right on lines where only
X * a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
X * and reset when any other editting is done on the line. If an <ESC>
X * or <RETURN> is received, and did_ai is TRUE, the line is truncated.
X */
Xbool_t	did_ai = FALSE;
X
Xvoid
Xedit()
X{
X	extern	bool_t	need_redraw;
X	int	c;
X	register char	*p, *q;
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	do_mlines();		/* check for mode lines before starting */
X
X	updatescreen();
X
X	for ( ;; ) {
X
X	/* Figure out where the cursor is based on Curschar. */
X	cursupdate();
X
X	if (need_redraw && !anyinput()) {
X		updatescreen();
X		need_redraw = FALSE;
X	}
X
X	if (!anyinput())
X		windgoto(Cursrow,Curscol);
X
X
X	c = vgetc();
X
X	if (State == NORMAL) {
X
X		/* We're in the normal (non-insert) mode. */
X
X		/* Pick up any leading digits and compute 'Prenum'. Could be
X                     special code K_UARROW etc. so check ascii first. */
X		if ( isascii(c) && isdigit(c) && (Prenum>0 || c!='0') ){
X			Prenum = Prenum*10 + (c-'0');
X			continue;
X		}
X		/* execute the command */
X		normal(c);
X		Prenum = 0;
X
X	} else {
X
X		/*
X		 * Insert or Replace mode.
X		 */
X		switch (c) {
X
X		case ESC:	/* an escape ends input mode */
X
X			/*
X			 * If we just did an auto-indent, truncate the
X			 * line, and put the cursor back.
X			 */
X			if (did_ai) {
X				Curschar->linep->s[0] = NUL;
X				Curschar->index = 0;
X				did_ai = FALSE;
X			}
X
X			set_want_col = TRUE;
X
X			/* Don't end up on a '\n' if you can help it. */
X			if (gchar(Curschar) == NUL && Curschar->index != 0)
X				dec(Curschar);
X
X			/*
X			 * The cursor should end up on the last inserted
X			 * character. This is an attempt to match the real
X			 * 'vi', but it may not be quite right yet.
X			 */
X			if (Curschar->index != 0 && !endofline(Curschar))
X				dec(Curschar);
X
X			State = NORMAL;
X			msg("");
X
X			/* construct the Redo buffer */
X			p=Redobuff;
X			q=Insbuff;
X			while ( q < Insptr )
X				*p++ = *q++;
X			*p++ = ESC;
X			*p = NUL;
X			updatescreen();
X			break;
X
X		case CTRL('D'):
X			/*
X			 * Control-D is treated as a backspace in insert
X			 * mode to make auto-indent easier. This isn't
X			 * completely compatible with vi, but it's a lot
X			 * easier than doing it exactly right, and the
X			 * 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
X			/* can't backup to a previous line */
X			if (Curschar->linep != Insstart->linep &&
X			    Curschar->index <= 0) {
X				beep();
X				break;
X			}
X
X			did_ai = FALSE;
X			dec(Curschar);
X			if (State == INSERT)
X				delchar(TRUE);
X			/*
X			 * It's a little strange to put backspaces into
X			 * the redo buffer, but it makes auto-indent a
X			 * lot easier to deal with.
X			 */
X			*Insptr++ = BS;
X			Ninsert++;
X			cursupdate();
X			updateline();
X			break;
X
X		case CR:
X		case NL:
X			if (State == REPLACE)		/* DMT added, 12/89 */
X				delchar(FALSE);
X			*Insptr++ = NL;
X			Ninsert++;
X			opencmd(FORWARD, TRUE);		/* open a new line */
X			break;
X
X		default:
X			did_ai = FALSE;
X			insertchar(c);
X			break;
X		}
X	}
X	}
X}
X
Xvoid
Xinsertchar(c)
Xint	c;
X{
X	inschar(c);
X	*Insptr++ = c;
X	Ninsert++;
X	/*
X	 * The following kludge avoids overflowing the statically
X	 * allocated insert buffer. Just dump the user back into
X	 * command mode, and print a message.
X	 */
X	if (Insptr+10 >= &Insbuff[1024]) {
X		stuffin(mkstr(ESC));
X		emsg("No buffer space - returning to command mode");
X		sleep(2);
X	}
X	updateline();
X}
X
Xvoid
Xgetout()
X{
X	windgoto(Rows-1,0);
X	putchar('\r');
X	putchar('\n');
X	windexit(0);
X}
X
Xvoid
Xscrolldown(nlines)
Xint	nlines;
X{
X	register LPTR	*p;
X	register int	done = 0;	/* total # of physical lines done */
X
X	/* Scroll up 'nlines' lines. */
X	while (nlines--) {
X		if ((p = prevline(Topchar)) == NULL)
X			break;
X		done += plines(p);
X		*Topchar = *p;
X		/*
X		 * If the cursor is on the bottom line, we need to
X		 * make sure it gets moved up the appropriate number
X		 * of lines so it stays on the screen.
X		 */
X		if (Curschar->linep == Botchar->linep->prev) {
X			int	i = 0;
X			while (i < done) {
X				i += plines(Curschar);
X				*Curschar = *prevline(Curschar);
X			}
X		}
X	}
X	s_ins(0, done);
X}
X
Xvoid
Xscrollup(nlines)
Xint	nlines;
X{
X	register LPTR	*p;
X	register int	done = 0;	/* total # of physical lines done */
X	register int	pl;		/* # of plines for the current line */
X
X	/* Scroll down 'nlines' lines. */
X	while (nlines--) {
X		pl = plines(Topchar);
X		if ((p = nextline(Topchar)) == NULL)
X			break;
X		done += pl;
X		if (Curschar->linep == Topchar->linep)
X			*Curschar = *p;
X		*Topchar = *p;
X
X	}
X	s_del(0, done);
X}
X
X/*
X * oneright
X * oneleft
X * onedown
X * oneup
X *
X * Move one char {right,left,down,up}.  Return TRUE when
X * sucessful, FALSE when 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		/* fall through */
X	case -1:
X		return FALSE;
X	}
X	/*NOTREACHED*/
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		/* fall through */
X	case -1:
X		return FALSE;
X	}
X	/*NOTREACHED*/
X}
X
Xvoid
Xbeginline(flag)
Xbool_t	flag;
X{
X	while ( oneleft() )
X		;
X	if (flag) {
X		while (isspace(gchar(Curschar)) && oneright())
X			;
X	}
X	set_want_col = TRUE;
X}
X
Xbool_t
Xoneup(n)
Xint	n;
X{
X	LPTR	p, *np;
X	register int	k;
X
X	p = *Curschar;
X	for ( k=0; k<n; k++ ) {
X		/* Look for the previous line */
X		if ( (np=prevline(&p)) == NULL ) {
X			/* If we've at least backed up a little .. */
X			if ( k > 0 )
X				break;	/* to update the cursor, etc. */
X			else
X				return FALSE;
X		}
X		p = *np;
X	}
X	*Curschar = p;
X	/* This makes sure Topchar gets updated so the complete line */
X	/* is one the screen. */
X	cursupdate();
X	/* try to advance to the column we want to be at */
X	*Curschar = *coladvance(&p, Curswant);
X	return TRUE;
X}
X
Xbool_t
Xonedown(n)
Xint	n;
X{
X	LPTR	p, *np;
X	register int	k;
X
X	p = *Curschar;
X	for ( k=0; k<n; k++ ) {
X		/* Look for the next line */
X		if ( (np=nextline(&p)) == NULL ) {
X			if ( k > 0 )
X				break;
X			else
X				return FALSE;
X		}
X		p = *np;
X	}
X	/* try to advance to the column we want to be at */
X	*Curschar = *coladvance(&p, Curswant);
X	return TRUE;
X}
END_OF_FILE
if test 6635 -ne `wc -c <'stevie/edit.c'`; then
    echo shar: \"'stevie/edit.c'\" unpacked with wrong size!
fi
# end of 'stevie/edit.c'
fi
if test -f 'stevie/minix.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stevie/minix.c'\"
else
echo shar: Extracting \"'stevie/minix.c'\" \(4836 characters\)
sed "s/^X//" >'stevie/minix.c' <<'END_OF_FILE'
X/* $Header: /nw/tony/src/stevie/src/RCS/minix.c,v 1.5 89/07/11 21:24:18 tony Exp $
X *
X * System-dependent routines for Minix-ST
X */
X
X#include "stevie.h"
X#include <sgtty.h>
X#include <signal.h>
X
X/*
X * inchar() - get a character from the keyboard
X */
Xint
Xinchar()
X{
X	char	c;
X
X	flushbuf();		/* flush any pending output */
X
X	while (read(0, &c, 1) != 1)
X		;
X
X	got_int = FALSE;
X	return c;
X}
X
X#define	BSIZE	2048
Xstatic	char	outbuf[BSIZE];
Xstatic	int	bpos = 0;
X
Xvoid
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)
Xregister char	c;
X{
X	outbuf[bpos++] = c;
X	if (bpos >= BSIZE)
X		flushbuf();
X}
X
Xvoid
Xoutstr(s)
Xregister char	*s;
X{
X	while (*s) {
X		outone(*s++);
X	}
X}
X
Xvoid
Xbeep()
X{
X	if ( P(P_VB) )
X		vbeep();
X	else
X		outone('\007');
X}
X
X/*
X * remove(file) - remove a file
X */
Xvoid
Xremove(file)
Xchar *file;
X{
X	unlink(file);
X}
X
X/*
X * rename(of, nf) - rename existing file 'of' to 'nf'
X */
Xvoid
Xrename(of, nf)
Xchar	*of, *nf;
X{
X	unlink(nf);
X	link(of, nf);
X	unlink(of);
X}
X
Xvoid
Xpause()
X{
X	sleep (1);
X}
X
Xstatic	struct	sgttyb	ostate;
X
X/*
X * Go into cbreak mode
X */
Xvoid
Xset_tty()
X{
X	struct	sgttyb	nstate;
X
X	 ioctl(0, TIOCGETP, &ostate);
X	 nstate = ostate;
X	 nstate.sg_flags &= ~(XTABS|ECHO);
X	 nstate.sg_flags |= CBREAK;
X	 ioctl(0, TIOCSETP, &nstate);
X}
X
X/*
X * Restore original terminal modes
X */
Xvoid
Xreset_tty()
X{
X	ioctl(0, TIOCSETP, &ostate);
X}
X
Xvoid
Xsig()
X{
X	signal(SIGINT, sig);
X	signal(SIGQUIT, sig);
X
X	got_int = TRUE;
X}
X
Xvoid
Xwindinit()
X{
X#ifdef	TERMCAP
X	if (t_init() != 1) {
X		exit(1);
X	}
X#else
X	Columns = 80;
X	P(P_LI) = Rows = 25;
X#endif
X	/*
X	 * The code here makes sure that there isn't a window during which
X	 * we could get interrupted and exit with the tty in a weird state.
X	 */
X	signal(SIGINT, sig);
X	signal(SIGQUIT, sig);
X
X	set_tty();
X
X	if (got_int)
X		windexit(0);
X}
X
Xvoid
Xwindexit(r)
Xint r;
X{
X	reset_tty();
X	exit(r);
X}
X
Xvoid
Xwindgoto(r, c)
Xregister int	r, c;
X{
X#ifdef	TERMCAP
X	char	*tgoto();
X#else
X	r += 1;
X	c += 1;
X#endif
X
X	/*
X	 * Check for overflow once, to save time.
X	 */
X	if (bpos + 8 >= BSIZE)
X		flushbuf();
X
X#ifdef	TERMCAP
X	outstr(tgoto(T_CM, c, r));
X#else
X	outbuf[bpos++] = '\033';
X	outbuf[bpos++] = '[';
X	if (r >= 10)
X		outbuf[bpos++] = r/10 + '0';
X	outbuf[bpos++] = r%10 + '0';
X	outbuf[bpos++] = ';';
X	if (c >= 10)
X		outbuf[bpos++] = c/10 + '0';
X	outbuf[bpos++] = c%10 + '0';
X	outbuf[bpos++] = 'H';
X#endif
X}
X
XFILE *
Xfopenb(fname, mode)
Xchar	*fname;
Xchar	*mode;
X{
X	return fopen(fname, mode);
X}
X
Xchar *
Xstrchr(s, c)
Xchar	*s;
Xchar	c;
X{
X	char *index();
X
X	return index(s, c);
X}
X
Xchar *
Xfixname(s)
Xchar	*s;
X{
X	return s;
X}
X
X/*
X * doshell() - run a command or an interactive shell
X */
Xvoid
Xdoshell(cmd)
Xchar	*cmd;
X{
X	char	*cp, *getenv();
X	char	cline[128];
X
X	outstr("\r\n");
X	flushbuf();
X
X	if (cmd == NULL) {
X		if ((cmd = getenv("SHELL")) == NULL)
X			cmd = "/bin/sh";
X		sprintf(cline, "%s -i", cmd);
X		cmd = cline;
X	}
X
X	reset_tty();
X	system(cmd);
X	set_tty();
X
X	wait_return();
X}
X
X/*
X *	FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
X *
X *	The next couple of functions do system-specific stuff.
X *	They currently do nothing; I'm not familiar enough with
X *	system-specific programming on this system.
X *	If you fill it in for your system, please post the results
X *	and share with the rest of us.
X */
X
X
Xsetcolor (c)
X/*
X * Set the color to c, using the local system convention for numbering
X * colors or video attributes.
X *
X * If you implement this, remember to note the original color in
X * windinit(), before you do any setcolor() commands, and
X * do a setcolor() back to the original as part of windexit().
X */
X  int c:
X{
X}
X
X
Xsetrows (r)
X/*
X * Set the number of lines to r, if possible.  Otherwise
X * "do the right thing".  Return the number of lines actually set.
X *
X * If you implement this, remember to note the original number of rows
X * in windinit(), before you do any setrows() commands, and
X * do a setrows() back to the original as part of windexit().
X */
X  int r;
X{
X	/* Since we do nothing, just return the current number of lines */
X	return ( P(P_LI) );
X}
X
X
Xvbeep ()
X/*
X * Do a "visual bell".  This generally consists of flashing the screen
X * once in inverse video.
X */
X{
X	int	color, revco;
X
X	color = P( P_CO );		/* get current color */
X	revco = reverse_color (color);	/* system-specific */
X	setcolor (revco);
X	flushbuf ();
X	pause ();
X	setcolor (color);
X	windgoto (Cursrow, Curscol);
X	flushbuf ();
X}
X
Xreverse_color (co)
X/*
X * Returns the inverse video attribute or color of co.
X * The existing code below is VERY simple-minded.
X * Replace it with proper code for your system.
X */
X int co;
X{
X	if (co)		return (0);
X	else		return (1);
X}
X
X
X/********** End of do-it-yourself kit **********************/
X
END_OF_FILE
if test 4836 -ne `wc -c <'stevie/minix.c'`; then
    echo shar: \"'stevie/minix.c'\" unpacked with wrong size!
fi
# end of 'stevie/minix.c'
fi
if test -f 'stevie/os2.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stevie/os2.c'\"
else
echo shar: Extracting \"'stevie/os2.c'\" \(7126 characters\)
sed "s/^X//" >'stevie/os2.c' <<'END_OF_FILE'
X/* $Header: /nw/tony/src/stevie/src/RCS/os2.c,v 1.7 89/08/07 05:49:19 tony Exp $
X *
X * OS/2 System-dependent routines.
X */
X
X#define	INCL_BASE
X#include <os2.h>
X#include <signal.h>
X#include "stevie.h"
X
X/*
X * inchar() - get a character from the keyboard
X */
Xint
Xinchar()
X{
X	register int	c;
X
X	got_int = FALSE;
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_CCIRCM;
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:		/* Home key */
X				stuffin("1G");
X				return -1;
X			case 0x4f:		/* End key */
X				stuffin("G");
X				return -1;
X			case 0x51:		/* PgDn key */
X				stuffin(mkstr(CTRL('F')));
X				return -1;
X			case 0x49:		/* PgUp key */
X				stuffin(mkstr(CTRL('B')));
X				return -1;
X			case 0x52:		/* insert key */
X				return K_INSERT;
X			case 0x53:		/* delete key */
X				stuffin("x");
X				return -1;
X			/*
X			 * Hard-code some useful function key macros.
X			 */
X			case 0x3b: /* F1 */
X				stuffin(":help\n");
X				return -1;
X			case 0x3c: /* F2 */
X				stuffin(":n\n");
X				return -1;
X			case 0x55: /* SF2 */
X				stuffin(":n!\n");
X				return -1;
X			case 0x3d: /* F3 */
X				stuffin(":N\n");
X				return -1;
X			case 0x56: /* SF3 */
X				stuffin(":N!\n");
X				return -1;
X			case 0x3e: /* F4 */
X				stuffin(":e #\n");
X				return -1;
X			case 0x57: /* SF4 */
X				stuffin(":e! #\n");
X				return -1;
X			case 0x3f: /* F5 */
X				stuffin(":rew\n");
X				return -1;
X			case 0x58: /* SF5 */
X				stuffin(":rew!\n");
X				return -1;
X			case 0x40: /* F6 */
X				stuffin("]]");
X				return -1;
X			case 0x59: /* SF6 */
X				stuffin("[[");
X				return -1;
X			case 0x42: /* F8 - Set up global substitute */
X				stuffin(":1,$s/");
X				return -1;
X			case 0x43: /* F9 - declare C variable */
X				stuffin("yyp!!cdecl\n");
X				return -1;
X			case 0x5C: /* SF9 - explain C declaration */
X				stuffin("yyp^iexplain \033!!cdecl\n");
X				return -1;
X			case 0x44: /* F10 - save & quit */
X				stuffin(":x\n");
X				return -1;
X			case 0x5D: /* F10 - quit without saving */
X				stuffin(":q!\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
Xvoid
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)
Xregister 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 *
X * We implement insert/delete line escape sequences here. This is kind
X * of a kludge, but at least it's localized to a single point.
X */
Xvoid
Xoutstr(s)
Xregister char	*s;
X{
X	if (strcmp(s, T_DL) == 0) {		/* delete line */
X		int	r, c;
X
X		flushbuf();
X		VioGetCurPos(&r, &c, 0);
X		VioScrollUp(r, 0, 100, 100, 1, cell, 0);
X		return;
X	}
X	if (strcmp(s, T_IL) == 0) {		/* insert line */
X		int	r, c;
X
X		flushbuf();
X		VioGetCurPos(&r, &c, 0);
X		VioScrollDn(r, 0, 100, 100, 1, cell, 0);
X		return;
X	}
X
X	while (*s) {
X		outone(*s++);
X	}
X}
X
Xvoid
Xbeep()
X{
X	in ( P(P_VB) )
X		vbeep();
X	else
X		outone('\007');
X}
X
Xsleep(n)
Xint	n;
X{
X	DosSleep(1000L * n);
X}
X
Xvoid
Xpause()
X{
X	flushbuf();
X	DosSleep(300L);
X}
X
Xvoid
Xsig()
X{
X	signal(SIGINT, sig);
X
X	got_int = TRUE;
X}
X
Xvoid
Xwindinit()
X{
X	Columns = 80;
X	P(P_LI) = Rows = 25;
X
X	signal(SIGINT, sig);
X}
X
Xvoid
Xwindexit(r)
Xint r;
X{
X	flushbuf();
X	exit(r);
X}
X
Xvoid
Xwindgoto(r, c)
Xregister int	r, c;
X{
X	r += 1;
X	c += 1;
X
X	/*
X	 * Check for overflow once, to save time.
X	 */
X	if (bpos + 8 >= BSIZE)
X		flushbuf();
X
X	outbuf[bpos++] = '\033';
X	outbuf[bpos++] = '[';
X	if (r >= 10)
X		outbuf[bpos++] = r/10 + '0';
X	outbuf[bpos++] = r%10 + '0';
X	outbuf[bpos++] = ';';
X	if (c >= 10)
X		outbuf[bpos++] = c/10 + '0';
X	outbuf[bpos++] = c%10 + '0';
X	outbuf[bpos++] = 'H';
X}
X
XFILE *
Xfopenb(fname, mode)
Xchar	*fname;
Xchar	*mode;
X{
X	FILE	*fopen();
X	char	modestr[16];
X
X	sprintf(modestr, "%sb", mode);
X	return fopen(fname, modestr);
X}
X
X#define	PSIZE	128
X
X/*
X * fixname(s) - fix up a dos name
X *
X * Takes a name like:
X *
X *	\x\y\z\base.ext
X *
X * and trims 'base' to 8 characters, and 'ext' to 3.
X */
Xchar *
Xfixname(s)
Xchar	*s;
X{
X	char	*strchr(), *strrchr();
X	static	char	f[PSIZE];
X	char	base[32];
X	char	ext[32];
X	char	*p;
X	int	i;
X
X	strcpy(f, s);
X
X	for (i=0; i < PSIZE ;i++)
X		if (f[i] == '/')
X			f[i] = '\\';
X
X	/*
X	 * Split the name into directory, base, extension.
X	 */
X	if ((p = strrchr(f, '\\')) != NULL) {
X		strcpy(base, p+1);
X		p[1] = '\0';
X	} else {
X		strcpy(base, f);
X		f[0] = '\0';
X	}
X
X	if ((p = strchr(base, '.')) != NULL) {
X		strcpy(ext, p+1);
X		*p = '\0';
X	} else
X		ext[0] = '\0';
X
X	/*
X	 * Trim the base name if necessary.
X	 */
X	if (strlen(base) > 8)
X		base[8] = '\0';
X	
X	if (strlen(ext) > 3)
X		ext[3] = '\0';
X
X	/*
X	 * Paste it all back together
X	 */
X	strcat(f, base);
X	strcat(f, ".");
X	strcat(f, ext);
X
X	return f;
X}
X
Xvoid
Xdoshell(cmd)
Xchar	*cmd;
X{
X	if (cmd == NULL)
X		cmd = "cmd.exe";
X
X	system(cmd);
X	wait_return();
X}
X
X/*
X *	FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
X *
X *	The next couple of functions do system-specific stuff.
X *	They currently do nothing; I'm not familiar enough with
X *	system-specific programming on this system.
X *	If you fill it in for your system, please post the results
X *	and share with the rest of us.
X */
X
X
Xsetcolor (c)
X/*
X * Set the color to c, using the local system convention for numbering
X * colors or video attributes.
X *
X * If you implement this, remember to note the original color in
X * windinit(), before you do any setcolor() commands, and
X * do a setcolor() back to the original as part of windexit().
X */
X  int c:
X{
X}
X
X
Xsetrows (r)
X/*
X * Set the number of lines to r, if possible.  Otherwise
X * "do the right thing".  Return the number of lines actually set.
X *
X * If you implement this, remember to note the original number of rows
X * in windinit(), before you do any setrows() commands, and
X * do a setrows() back to the original as part of windexit().
X */
X  int r;
X{
X	/* Since we do nothing, just return the current number of lines */
X	return ( P(P_LI) );
X}
X
X
Xvbeep ()
X/*
X * Do a "visual bell".  This generally consists of flashing the screen
X * once in inverse video.
X */
X{
X	int	color, revco;
X
X	color = P( P_CO );		/* get current color */
X	revco = reverse_color (color);	/* system-specific */
X	setcolor (revco);
X	flushbuf ();
X	pause ();
X	setcolor (color);
X	windgoto (Cursrow, Curscol);
X	flushbuf ();
X}
X
Xreverse_color (co)
X/*
X * Returns the inverse video attribute or color of co.
X * The existing code below is VERY simple-minded.
X * Replace it with proper code for your system.
X */
X int co;
X{
X	if (co)		return (0);
X	else		return (1);
X}
X
X
X/********** End of do-it-yourself kit **********************/
X
END_OF_FILE
if test 7126 -ne `wc -c <'stevie/os2.c'`; then
    echo shar: \"'stevie/os2.c'\" unpacked with wrong size!
fi
# end of 'stevie/os2.c'
fi
if test -f 'stevie/tagcmd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stevie/tagcmd.c'\"
else
echo shar: Extracting \"'stevie/tagcmd.c'\" \(5019 characters\)
sed "s/^X//" >'stevie/tagcmd.c' <<'END_OF_FILE'
X/* #Header: /?????
X *
X * Routines to implement tags, and, especially, tag stacking.
X * Added by Dave Tutelman - 12/89.
X * The dotag() routine is a modification of the posted
X * version by Tony Andrews.
X * The untag() routine is new.
X */
X
X#include "stevie.h"
X
X#define	LSIZE	256	/* max. size of a line in the tags file */
X
X#ifdef TAGSTACK
X/*  We build a stack of file records, on which we push info about
X *  current file when dotag() is called.
X */
X#define	TAGSTACKSIZE	12		/* how many tag calls can we stack? */
Xstatic	struct filerecord {
X		char	*name;		/* file name pointer */
X		int	linenum;	/* line number when we left */
X} tagstack [TAGSTACKSIZE];
Xstatic	int	stackindex = 0;		/* here's how we keep track */
X#endif
X
Xextern	char	**files;
Xextern	int	curfile;
Xstatic	void	pushtags(), poptags();
X
X
X/*
X * dotag(tag, force) - goto tag.  If force=TRUE, dump pending changes.
X */
Xvoid
Xdotag(tag, force)
Xchar	*tag;
Xbool_t	force;
X{
X	FILE	*tp, *fopen();
X	char	lbuf[LSIZE];		/* line buffer */
X	char	pbuf[LSIZE];		/* search pattern buffer */
X	register char	*fname, *str;
X	register char	*p;
X
X	if ((tp = fopen("tags", "r")) == NULL) {
X		emsg("Can't open tags file");
X		return;
X	}
X
X	while (fgets(lbuf, LSIZE, tp) != NULL) {
X	
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
X			/*
X			 * Scan through the search string. If we see a magic
X			 * char, we have to quote it. This lets us use "real"
X			 * implementations of ctags.
X			 */
X			p = pbuf;
X			*p++ = *str++;		/* copy the '/' or '?' */
X			*p++ = *str++;		/* copy the '^' */
X
X			for (; *str != NUL ;str++) {
X				if (*str == '\\') {
X					*p++ = *str++;
X					*p++ = *str;
X				} else if (strchr("/?", *str) != NULL) {
X					if (str[1] != '\n') {
X						*p++ = '\\';
X						*p++ = *str;
X					} else
X						*p++ = *str;
X				} else if (strchr("^()*.", *str) != NULL) {
X					*p++ = '\\';
X					*p++ = *str;
X				} else
X					*p++ = *str;
X			}
X			*p = NUL;
X
X#ifdef TAGSTACK
X			/* Push current position onto stack, unless this
X			 * is a startup call using '-t' option. */
X			if (Filename!=NULL && *Filename!='\0')
X				pushtags ();
X#endif
X
X			/*
X			 * This looks out of order, but by calling stuffin()
X			 * before doecmd() we keep an extra screen update
X			 * from occuring. This stuffins() have no effect
X			 * until we get back to the main loop, anyway.
X			 */
X
X			stuffin(pbuf);		/* str has \n at end */
X			stuffin("\007");	/* CTRL('g') */
X
X			if (doecmd(fname, force)) {
X				fclose(tp);
X				return;
X			} else {
X#ifdef TAGSTACK
X				poptags ();	/* cancel stack entry */
X#endif
X				stuffin(NULL);	/* clear the input */
X			}
X		}
X	}
X	emsg("tag not found");
X	fclose(tp);
X}
X
X/*
X * dountag (spec) - undo the last ':ta' command, popping the tag stack.
X *	spec is the appended character, giving specifics:
X *	  '!'	dump pending changes.
X *	  'e'	came from K_CCIRCM "shortcut".  do :e# if stack empty.
X *	  ' '	do normal untag.
X *	  else	bad command.
X */
X
Xvoid
Xdountag (spec)
X  char spec;
X{
X#ifndef TAGSTACK
X	badcmd();	/* complain & return */
X}
X#else
X
X	char	force=0, shortcut=0;
X	char	*newfile;
X	char	buf [LSIZE];
X
X	switch (spec) {
X	  case '!':
X		force++;
X		break;
X	  case 'e':
X		shortcut++;
X		break;
X	  case ' ':
X	  case '\n':
X	  case '\r':
X	  case '\0':
X		break;
X	  default:
X		badcmd();
X		return;
X	}
X
X	/* Check the stack.  If empty, don't pop */
X	if (!stackindex) {
X		if (shortcut)		/* just edit altfile */
X			stuffin(":e #\n");
X		else
X			emsg("Tags stack empty");
X		return;
X	}
X
X	/* Get the top of the stack, and do the implied edit.
X	 * If it succeeds, switch; if not, back off */
X	newfile = tagstack [stackindex-1].name;
X	if (doecmd (newfile, force)) {
X		sprintf (buf, "%dG:f\n", tagstack [stackindex-1].linenum);
X		stuffin(buf);
X		poptags ();
X		return;
X	}
X	else
X		stuffin(NULL);
X}
X
X/*
X * pushtags () - push the current state onto the tagstack.
X */
X
Xstatic void
Xpushtags ()
X{
X	int	i;
X
X	/* If stack full, throw away oldest and push the rest.
X	 * This is clearly the best and most transparent way to behave,
X	 * much preferable to either complaining or losing new entry.
X	 */
X	if (stackindex >= TAGSTACKSIZE) {
X		for (i=0; i<TAGSTACKSIZE-1; i++) {
X			tagstack[i].name    = tagstack[i+1].name;
X			tagstack[i].linenum = tagstack[i+1].linenum;
X		}
X		stackindex--;
X	}
X
X	/* Get current state, and put it in stack.
X	 * Right now, the state is file name & line number.
X	 * This is less than perfect, in that line numbers may change if
X	 * you edit elsewhere in the file.  Eventually, I'd like to base
X	 * it on "hidden" marks, if I can implement them.  DMT
X	 */
X	tagstack [stackindex].name    = strsave (Filename);
X	tagstack [stackindex].linenum = cntllines (Filemem, Curschar);
X	stackindex++;
X}
X
X/*
X * poptags () - pop the tag stack.
X */
X
Xstatic void
Xpoptags ()
X{
X	if (!stackindex) {
X		emsg("Tags stack empty");
X		return;
X	}
X
X	stackindex--;
X	free (tagstack [stackindex].name);
X}
X
X#endif
X
X
END_OF_FILE
if test 5019 -ne `wc -c <'stevie/tagcmd.c'`; then
    echo shar: \"'stevie/tagcmd.c'\" unpacked with wrong size!
fi
# end of 'stevie/tagcmd.c'
fi
if test -f 'stevie/undo.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stevie/undo.c'\"
else
echo shar: Extracting \"'stevie/undo.c'\" \(6821 characters\)
sed "s/^X//" >'stevie/undo.c' <<'END_OF_FILE'
X/* $Header: /nw/tony/src/stevie/src/RCS/undo.c,v 1.7 89/08/06 09:51:06 tony Exp $
X *
X * Undo facility
X *
X * The routines in this file comprise a general undo facility for use
X * throughout the rest of the editor. The routine u_save() is called
X * before each edit operation to save the current contents of the lines
X * to be editted. Later, u_undo() can be called to return those lines
X * to their original state. The routine u_clear() should be called
X * whenever a new file is going to be editted to clear the undo buffer.
X */
X
X#include "stevie.h"
X
X/*
X * The next two variables mark the boundaries of the changed section
X * of the file. Lines BETWEEN the lower and upper bounds are changed
X * and originally contained the lines pointed to by u_lines. To undo
X * the last change, insert the lines in u_lines between the lower and
X * upper bounds.
X */
Xstatic	LINE	*u_lbound = NULL; /* line just prior to first changed line */
Xstatic	LINE	*u_ubound = NULL; /* line just after the last changed line */
X
Xstatic	LINE	*u_lline  = NULL; /* bounds of the saved lines */
Xstatic	LINE	*u_uline  = NULL;
X
Xstatic	int	u_col;
Xstatic	bool_t	u_valid = FALSE;  /* is the undo buffer valid */
X
X/*
X * Local forward declarations
X */
Xstatic	LINE	*copyline();
Xstatic	void	u_lsave();
Xstatic	void	u_lfree();
X
X/*
X * u_save(l, u) - save the current contents of part of the file
X *
X * The lines between 'l' and 'u' are about to be changed. This routine
X * saves their current contents into the undo buffer. The range l to u
X * is not inclusive because when we do an open, for example, there aren't
X * any lines in between. If no lines are to be saved, then l->next == u.
X */
Xvoid
Xu_save(l, u)
XLINE	*l, *u;
X{
X	LINE	*nl;			/* copy of the current line */
X
X	/*
X	 * If l or u is null, there's an error. We don't return an
X	 * indication to the caller. They should find the problem
X	 * while trying to perform whatever edit is being requested
X	 * (e.g. a join on the last line).
X	 */
X	if (l == NULL || u == NULL)
X		return;
X
X	u_clear();			/* clear the buffer, first */
X
X	u_lsave(l, u);		/* save to the "line undo" buffer, if needed */
X
X	u_lbound = l;
X	u_ubound = u;
X
X	if (l->next != u) {		/* there are lines in the middle */
X		l = l->next;
X		u = u->prev;
X
X		u_lline = nl = copyline(l);	/* copy the first line */
X		while (l != u) {
X			nl->next = copyline(l->next);
X			nl->next->prev = nl;
X			l = l->next;
X			nl = nl->next;
X		}
X		u_uline = nl;
X	} else
X		u_lline = u_uline = NULL;
X
X	u_valid = TRUE;
X	u_col = Cursvcol;
X}
X
X/*
X * u_saveline() - save the current line in the undo buffer
X */
Xvoid
Xu_saveline()
X{
X	u_save(Curschar->linep->prev, Curschar->linep->next);
X}
X
X/*
X * u_undo() - effect an 'undo' operation
X *
X * The last edit is undone by restoring the modified section of the file
X * to its original state. The lines we're going to trash are copied to
X * the undo buffer so that even an 'undo' can be undone. Rings the bell
X * if the undo buffer is empty.
X */
Xvoid
Xu_undo()
X{
X	LINE	*tl, *tu;
X
X	if (!u_valid) {
X		beep();
X		return;
X	}
X
X	/*
X	 * Get the first line of the thing we're undoing on the screen.
X	 */
X	Curschar->linep = u_lbound->next;
X	Curschar->index = 0;			/* for now */
X	if (Curschar->linep == Fileend->linep)
X		Curschar->linep = Curschar->linep->prev;
X	cursupdate();
X
X	/*
X	 * Save pointers to what's in the file now.
X	 */
X	if (u_lbound->next != u_ubound) {	/* there are lines to get */
X		tl = u_lbound->next;
X		tu = u_ubound->prev;
X		tl->prev = NULL;
X		tu->next = NULL;
X	} else
X		tl = tu = NULL;			/* no lines between bounds */
X
X	/*
X	 * Link the undo buffer into the right place in the file.
X	 */
X	if (u_lline != NULL) {		/* there are lines in the undo buf */
X
X		/*
X		 * If the top line of the screen is being undone, we need to
X		 * fix up Topchar to point to the new line that will be there.
X		 */
X		if (u_lbound->next == Topchar->linep)
X			Topchar->linep = u_lline;
X
X		u_lbound->next = u_lline;
X		u_lline->prev  = u_lbound;
X		u_ubound->prev = u_uline;
X		u_uline->next  = u_ubound;
X	} else {			/* no lines... link the bounds */
X		if (u_lbound->next == Topchar->linep)
X			Topchar->linep = u_ubound;
X		if (u_lbound == Filetop->linep)
X			Topchar->linep = u_ubound;
X			
X		u_lbound->next = u_ubound;
X		u_ubound->prev = u_lbound;
X	}
X
X	/*
X	 * If we swapped the top line, patch up Filemem appropriately.
X	 */
X	if (u_lbound == Filetop->linep)
X		Filemem->linep = Filetop->linep->next;
X
X	/*
X	 * Now save the old stuff in the undo buffer.
X	 */
X	u_lline = tl;
X	u_uline = tu;
X
X	renum();		/* have to renumber everything */
X
X	/*
X	 * Put the cursor on the first line of the 'undo' region.
X	 */
X	Curschar->linep = u_lbound->next;
X	Curschar->index = 0;
X	if (Curschar->linep == Fileend->linep)
X		Curschar->linep = Curschar->linep->prev;
X	*Curschar = *coladvance(Curschar, u_col);
X	cursupdate();
X	updatescreen();		/* now show the change */
X
X	u_lfree();		/* clear the "line undo" buffer */
X}
X
X/*
X * u_clear() - clear the undo buffer
X *
X * This routine is called to clear the undo buffer at times when the
X * pointers are about to become invalid, such as when a new file is
X * about to be editted.
X */
Xvoid
Xu_clear()
X{
X	LINE	*l, *nextl;
X
X	if (!u_valid)		/* nothing to do */
X		return;
X
X	for (l = u_lline; l != NULL ;l = nextl) {
X		nextl = l->next;
X		free(l->s);
X		free((char *)l);
X	}
X
X	u_lbound = u_ubound = u_lline = u_uline = NULL;
X	u_valid = FALSE;
X}
X
X/*
X * The following functions and data implement the "line undo" feature
X * performed by the 'U' command.
X */
X
Xstatic	LINE	*u_line;		/* pointer to the line we last saved */
Xstatic	LINE	*u_lcopy = NULL;	/* local copy of the original line */
X
X/*
X * u_lfree() - free the line save buffer
X */
Xstatic	void
Xu_lfree()
X{
X	if (u_lcopy != NULL) {
X		free(u_lcopy->s);
X		free((char *)u_lcopy);
X		u_lcopy = NULL;
X	}
X	u_line = NULL;
X}
X
X/*
X * u_lsave() - save the current line if necessary
X */
Xstatic	void
Xu_lsave(l, u)
XLINE	*l, *u;
X{
X
X	if (l->next != u->prev) {	/* not changing exactly one line */
X		u_lfree();
X		return;
X	}
X
X	if (l->next == u_line)		/* more edits on the same line */
X		return;
X
X	u_lfree();
X	u_line = l->next;
X	u_lcopy = copyline(l->next);
X}
X
X/*
X * u_lundo() - undo the current line (the 'U' command)
X */
Xvoid
Xu_lundo()
X{
X	if (u_lcopy != NULL) {
X		free(Curschar->linep->s);
X		Curschar->linep->s = u_lcopy->s;
X		Curschar->linep->size = u_lcopy->size;
X		free((char *)u_lcopy);
X	} else
X		beep();
X	Curschar->index = 0;
X
X	cursupdate();
X	updatescreen();		/* now show the change */
X
X	u_lcopy = NULL;	/* can't undo this kind of undo */
X	u_line = NULL;
X}
X
X/*
X * u_lcheck() - clear the "line undo" buffer if we've moved to a new line
X */
Xvoid
Xu_lcheck()
X{
X	if (Curschar->linep != u_line)
X		u_lfree();
X}
X
X/*
X * copyline(l) - copy the given line, and return a pointer to the copy
X */
Xstatic LINE *
Xcopyline(l)
XLINE	*l;
X{
X	LINE	*nl;		/* the new line */
X
X	nl = newline(strlen(l->s));
X	strcpy(nl->s, l->s);
X
X	return nl;
X}
END_OF_FILE
if test 6821 -ne `wc -c <'stevie/undo.c'`; then
    echo shar: \"'stevie/undo.c'\" unpacked with wrong size!
fi
# end of 'stevie/undo.c'
fi
echo shar: End of archive 4 \(of 13\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 13 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
