[comp.sources.misc] v08i004: stevie 3.69 - part 2 of 8

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (08/20/89)

Posting-number: Volume 8, Issue 4
Submitted-by: tony@cs.utexas.edu@wldrdg.UUCP (Tony Andrews)
Archive-name: stevie3.68/part02

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	help.c
#	hexchars.c
#	keymap.h
#	linefunc.c
#	main.c
#	mark.c
#	misccmds.c
# This archive created: Sun Aug 13 11:45:56 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'help.c'" '(8540 characters)'
if test -f 'help.c'
then
	echo shar: will not over-write existing file "'help.c'"
else
sed 's/^X//' << \HE_HATES_THESE_CANS > 'help.c'
X/* $Header: /nw/tony/src/stevie/src/RCS/help.c,v 1.9 89/08/06 09:50:09 tony Exp $
X *
X * Routine to display a command summary.
X */
X
X#include "stevie.h"
X
Xextern	char	*Version;
X
Xstatic	int	helprow;
X
X#ifdef	HELP
X
Xstatic	void	longline();
X
Xbool_t
Xhelp()
X{
X
X/***********************************************************************
X * First Screen:   Positioning within file, Adjusting the Screen
X ***********************************************************************/
X
X	outstr(T_ED);
X	windgoto(helprow = 0, 0);
X
Xlongline("\
X   Positioning within file\n\
X   =======================\n\
X      ^F             Forward screenfull             Developed by:\n\
X      ^B             Backward screenfull                Tony Andrews\n");
Xlongline("\
X      ^D             scroll down half screen\n\
X      ^U             scroll up half screen          Based on a program by:\n");
Xlongline("\
X      G              Goto line (end default)            Tim Thompson\n\
X      ]]             next function\n\
X      [[             previous function\n\
X      /re            next occurence of regular expression 're'\n");
Xlongline("\
X      ?re            prior occurence of regular expression 're'\n\
X      n              repeat last / or ?\n\
X      N              reverse last / or ?\n\
X      %              find matching (, ), {, }, [, or ]\n");
Xlongline("\
X\n\
X   Adjusting the screen\n\
X   ====================\n\
X      ^L             Redraw the screen\n\
X      ^E             scroll window down 1 line\n\
X      ^Y             scroll window up 1 line\n");
Xlongline("\
X      z<RETURN>      redraw, current line at top\n\
X      z-             ... at bottom\n\
X      z.             ... at center\n");
X
X	windgoto(0, 52);
X	longline(Version);
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/***********************************************************************
X * Second Screen:   Character positioning
X ***********************************************************************/
X
X	outstr(T_ED);
X	windgoto(helprow = 0, 0);
X
Xlongline("\
X   Character Positioning\n\
X   =====================\n\
X      ^              first non-white\n\
X      0              beginning of line\n\
X      $              end of line\n\
X      h              backward\n");
Xlongline("\
X      l              forward\n\
X      ^H             same as h\n\
X      space          same as l\n\
X      fx             find 'x' forward\n");
Xlongline("\
X      Fx             find 'x' backward\n\
X      tx             upto 'x' forward\n\
X      Tx             upto 'x' backward\n\
X      ;              Repeat last f, F, t, or T\n");
Xlongline("\
X      ,              inverse of ;\n\
X      |              to specified column\n\
X      %              find 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/***********************************************************************
X * Third Screen:   Line Positioning, Marking and Returning
X ***********************************************************************/
X
X	outstr(T_ED);
X	windgoto(helprow = 0, 0);
X
Xlongline("\
X    Line Positioning\n\
X    ================\n\
X    H           home window line\n\
X    L           last window line\n\
X    M           middle window line\n");
Xlongline("\
X    +           next line, at first non-white\n\
X    -           previous line, at first non-white\n\
X    CR          return, same as +\n\
X    j           next line, same column\n\
X    k           previous line, same column\n");
X
Xlongline("\
X\n\
X    Marking and Returning\n\
X    =====================\n\
X    ``          previous context\n\
X    ''          ... at first non-white in line\n");
Xlongline("\
X    mx          mark position with letter 'x'\n\
X    `x          to mark 'x'\n\
X    'x          ... at first non-white in line\n");
X
Xlongline("\n\
X    Undo  &  Redo\n\
X    =============\n\
X    u           undo last change\n\
X    U           restore current line\n\
X    .           repeat last change\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 * Fourth Screen:   Insert & Replace, 
X ***********************************************************************/
X
X	outstr(T_ED);
X	windgoto(helprow = 0, 0);
X
Xlongline("\
X    Insert and Replace\n\
X    ==================\n\
X    a           append after cursor\n\
X    i           insert before cursor\n\
X    A           append at end of line\n\
X    I           insert before first non-blank\n");
Xlongline("\
X    o           open line below\n\
X    O           open line above\n\
X    rx          replace single char with 'x'\n\
X    R           replace characters\n");
X
Xlongline("\
X\n\
X    Words, sentences, paragraphs\n\
X    ============================\n\
X    w           word forward\n\
X    b           back word\n\
X    e           end of word\n\
X    )           to next sentence (not yet)\n\
X    }           to next paragraph (not yet)\n");
Xlongline("\
X    (           back sentence (not yet)\n\
X    {           back paragraph (not yet)\n\
X    W           blank delimited word\n\
X    B           back W\n\
X    E           to end of W\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/***********************************************************************
X * Fifth Screen:   Misc. operations, 
X ***********************************************************************/
X
X	outstr(T_ED);
X	windgoto(helprow = 0, 0);
X
Xlongline("\
X    Miscellaneous Commands\n\
X    ======================\n");
Xlongline("\
X    :w          write back changes\n\
X    :wq         write and quit\n\
X    :x          write if modified, and quit\n\
X    :q          quit\n\
X    :q!         quit, discard changes\n\
X    :e name     edit file 'name'\n");
Xlongline("\
X    :e!         reedit, discard changes\n\
X    :e #        edit alternate file\n\
X    :w name     write file 'name'\n");
Xlongline("\
X    :n          edit next file in arglist\n\
X    :N          edit prior file in arglist\n\
X    :n args     specify new arglist (not yet)\n\
X    :rew        rewind arglist\n\
X    :f          show current file and lines\n");
Xlongline("\
X    :f file     change current file name\n\
X    :g/pat/p|d  global command (print or delete only)\n\
X    :s/p1/p2/   text substitution (trailing 'g' optional)\n\
X");
Xlongline("\
X    :ta tag     to tag file entry 'tag'\n\
X    ^]          :ta, current word is tag\n\
X    :sh         run an interactive shell\n\
X    :!cmd       execute a shell command\n\
X");
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/***********************************************************************
X * Sixth Screen:   Operators, Misc. operations, Yank & Put
X ***********************************************************************/
X
X	outstr(T_ED);
X	windgoto(helprow = 0, 0);
X
Xlongline("\
X    Operators (double to affect lines)\n\
X    ==================================\n\
X    d           delete\n\
X    c           change\n");
Xlongline("\
X    <           left shift\n\
X    >           right shift\n\
X    y           yank to buffer\n\
X    !           filter lines\n");
X
Xlongline("\n\
X    Miscellaneous operations\n\
X    ========================\n\
X    C           change rest of line\n\
X    D           delete rest of line\n\
X    s           substitute chars\n");
Xlongline("\
X    S           substitute lines (not yet)\n\
X    J           join lines\n\
X    x           delete characters\n\
X    X           ... before cursor\n");
X
Xlongline("\n\
X    Yank and Put\n\
X    ============\n\
X    p           put back text\n\
X    P           put before\n\
X    Y           yank lines");
X
X	windgoto(helprow = Rows-1, 47);
X	longline("<Press any key>");
X
X	(void) vgetc();
X
X	return TRUE;
X}
X
Xstatic void
Xlongline(p)
Xchar	*p;
X{
X	register char	*s;
X
X	for ( s = p; *s ;s++ ) {
X		if ( *s == '\n' )
X			windgoto(++helprow, 0);
X		else
X			outchar(*s);
X	}
X}
X#else
X
Xbool_t
Xhelp()
X{
X	msg("Sorry, help not configured");
X	return FALSE;
X}
X#endif
HE_HATES_THESE_CANS
if test 8540 -ne "`wc -c < 'help.c'`"
then
	echo shar: error transmitting "'help.c'" '(should have been 8540 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'hexchars.c'" '(3109 characters)'
if test -f 'hexchars.c'
then
	echo shar: will not over-write existing file "'hexchars.c'"
else
sed 's/^X//' << \HE_HATES_THESE_CANS > 'hexchars.c'
X/* $Header: /nw/tony/src/stevie/src/RCS/hexchars.c,v 1.4 89/03/11 22:42:27 tony Exp $
X *
X * Contains information concerning the representation of characters for
X * visual output by the editor.
X */
X
X#include "stevie.h"
X
X/*
X * This file shows how to display characters on the screen. This is
X * approach is something of an overkill. It's a remnant from the
X * original code that isn't worth messing with for now. TABS are
X * special-cased depending on the value of the "list" parameter.
X */
X
Xstruct charinfo chars[] = {
X	/* 000 */	1, NULL,
X	/* 001 */	2, "^A",
X	/* 002 */	2, "^B",
X	/* 003 */	2, "^C",
X	/* 004 */	2, "^D",
X	/* 005 */	2, "^E",
X	/* 006 */	2, "^F",
X	/* 007 */	2, "^G",
X	/* 010 */	2, "^H",
X	/* 011 */	2, "^I",
X	/* 012 */	7, "[ERROR]",	/* shouldn't occur */
X	/* 013 */	2, "^K",
X	/* 014 */	2, "^L",
X	/* 015 */	2, "^M",
X	/* 016 */	2, "^N",
X	/* 017 */	2, "^O",
X	/* 020 */	2, "^P",
X	/* 021 */	2, "^Q",
X	/* 022 */	2, "^R",
X	/* 023 */	2, "^S",
X	/* 024 */	2, "^T",
X	/* 025 */	2, "^U",
X	/* 026 */	2, "^V",
X	/* 027 */	2, "^W",
X	/* 030 */	2, "^X",
X	/* 031 */	2, "^Y",
X	/* 032 */	2, "^Z",
X	/* 033 */	2, "^[",
X	/* 034 */	2, "^\\",
X	/* 035 */	2, "^]",
X	/* 036 */	2, "^^",
X	/* 037 */	2, "^_",
X	/* 040 */	1, NULL,
X	/* 041 */	1, NULL,
X	/* 042 */	1, NULL,
X	/* 043 */	1, NULL,
X	/* 044 */	1, NULL,
X	/* 045 */	1, NULL,
X	/* 046 */	1, NULL,
X	/* 047 */	1, NULL,
X	/* 050 */	1, NULL,
X	/* 051 */	1, NULL,
X	/* 052 */	1, NULL,
X	/* 053 */	1, NULL,
X	/* 054 */	1, NULL,
X	/* 055 */	1, NULL,
X	/* 056 */	1, NULL,
X	/* 057 */	1, NULL,
X	/* 060 */	1, NULL,
X	/* 061 */	1, NULL,
X	/* 062 */	1, NULL,
X	/* 063 */	1, NULL,
X	/* 064 */	1, NULL,
X	/* 065 */	1, NULL,
X	/* 066 */	1, NULL,
X	/* 067 */	1, NULL,
X	/* 070 */	1, NULL,
X	/* 071 */	1, NULL,
X	/* 072 */	1, NULL,
X	/* 073 */	1, NULL,
X	/* 074 */	1, NULL,
X	/* 075 */	1, NULL,
X	/* 076 */	1, NULL,
X	/* 077 */	1, NULL,
X	/* 100 */	1, NULL,
X	/* 101 */	1, NULL,
X	/* 102 */	1, NULL,
X	/* 103 */	1, NULL,
X	/* 104 */	1, NULL,
X	/* 105 */	1, NULL,
X	/* 106 */	1, NULL,
X	/* 107 */	1, NULL,
X	/* 110 */	1, NULL,
X	/* 111 */	1, NULL,
X	/* 112 */	1, NULL,
X	/* 113 */	1, NULL,
X	/* 114 */	1, NULL,
X	/* 115 */	1, NULL,
X	/* 116 */	1, NULL,
X	/* 117 */	1, NULL,
X	/* 120 */	1, NULL,
X	/* 121 */	1, NULL,
X	/* 122 */	1, NULL,
X	/* 123 */	1, NULL,
X	/* 124 */	1, NULL,
X	/* 125 */	1, NULL,
X	/* 126 */	1, NULL,
X	/* 127 */	1, NULL,
X	/* 130 */	1, NULL,
X	/* 131 */	1, NULL,
X	/* 132 */	1, NULL,
X	/* 133 */	1, NULL,
X	/* 134 */	1, NULL,
X	/* 135 */	1, NULL,
X	/* 136 */	1, NULL,
X	/* 137 */	1, NULL,
X	/* 140 */	1, NULL,
X	/* 141 */	1, NULL,
X	/* 142 */	1, NULL,
X	/* 143 */	1, NULL,
X	/* 144 */	1, NULL,
X	/* 145 */	1, NULL,
X	/* 146 */	1, NULL,
X	/* 147 */	1, NULL,
X	/* 150 */	1, NULL,
X	/* 151 */	1, NULL,
X	/* 152 */	1, NULL,
X	/* 153 */	1, NULL,
X	/* 154 */	1, NULL,
X	/* 155 */	1, NULL,
X	/* 156 */	1, NULL,
X	/* 157 */	1, NULL,
X	/* 160 */	1, NULL,
X	/* 161 */	1, NULL,
X	/* 162 */	1, NULL,
X	/* 163 */	1, NULL,
X	/* 164 */	1, NULL,
X	/* 165 */	1, NULL,
X	/* 166 */	1, NULL,
X	/* 167 */	1, NULL,
X	/* 170 */	1, NULL,
X	/* 171 */	1, NULL,
X	/* 172 */	1, NULL,
X	/* 173 */	1, NULL,
X	/* 174 */	1, NULL,
X	/* 175 */	1, NULL,
X	/* 176 */	1, NULL,
X	/* 177 */	2, "^?",
X};
HE_HATES_THESE_CANS
if test 3109 -ne "`wc -c < 'hexchars.c'`"
then
	echo shar: error transmitting "'hexchars.c'" '(should have been 3109 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'keymap.h'" '(936 characters)'
if test -f 'keymap.h'
then
	echo shar: will not over-write existing file "'keymap.h'"
else
sed 's/^X//' << \HE_HATES_THESE_CANS > 'keymap.h'
X/*
X * $Header: /nw/tony/src/stevie/src/RCS/keymap.h,v 1.2 89/03/11 22:42:30 tony Exp $
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_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_CGRAVE	0x88	/* control grave accent */
X
X#define	K_F1		0x91	/* function keys */
X#define	K_F2		0x92
X#define	K_F3		0x93
X#define	K_F4		0x94
X#define	K_F5		0x95
X#define	K_F6		0x96
X#define	K_F7		0x97
X#define	K_F8		0x98
X#define	K_F9		0x99
X#define	K_F10		0x9a
X
X#define	K_SF1		0xa1	/* shifted function keys */
X#define	K_SF2		0xa2
X#define	K_SF3		0xa3
X#define	K_SF4		0xa4
X#define	K_SF5		0xa5
X#define	K_SF6		0xa6
X#define	K_SF7		0xa7
X#define	K_SF8		0xa8
X#define	K_SF9		0xa9
X#define	K_SF10		0xaa
HE_HATES_THESE_CANS
if test 936 -ne "`wc -c < 'keymap.h'`"
then
	echo shar: error transmitting "'keymap.h'" '(should have been 936 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'linefunc.c'" '(1583 characters)'
if test -f 'linefunc.c'
then
	echo shar: will not over-write existing file "'linefunc.c'"
else
sed 's/^X//' << \HE_HATES_THESE_CANS > 'linefunc.c'
X/* $Header: /nw/tony/src/stevie/src/RCS/linefunc.c,v 1.2 89/03/11 22:42:32 tony Exp $
X *
X * Basic line-oriented motions.
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
X * referenced by 'curr'. Return NULL if there is no next line (at EOF).
X */
X
XLPTR *
Xnextline(curr)
XLPTR	*curr;
X{
X	static	LPTR	next;
X
X	if (curr->linep->next != Fileend->linep) {
X		next.index = 0;
X		next.linep = curr->linep->next;
X		return &next;
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
X * referenced by 'curr'. Return NULL if there is no prior line.
X */
X
XLPTR *
Xprevline(curr)
XLPTR	*curr;
X{
X	static	LPTR	prev;
X
X	if (curr->linep->prev != Filetop->linep) {
X		prev.index = 0;
X		prev.linep = curr->linep->prev;
X		return &prev;
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
XLPTR *
Xcoladvance(p, col)
XLPTR	*p;
Xregister int	col;
X{
X	static	LPTR	lp;
X	register int	c, in;
X
X	lp.linep = p->linep;
X	lp.index = p->index;
X
X	/* If we're on a blank ('\n' only) line, we can't do anything */
X	if (lp.linep->s[lp.index] == '\0')
X		return &lp;
X	/* try to advance to the specified column */
X	for ( c=0; col-- > 0; c++ ) {
X		/* Count a tab for what it's worth (if list mode not on) */
X		if ( gchar(&lp) == TAB && !P(P_LS) ) {
X			in = ((P(P_TS)-1) - c%P(P_TS));
X			col -= in;
X			c += in;
X		}
X		/* Don't go past the end of */
X		/* the file or the line. */
X		if (inc(&lp)) {
X			dec(&lp);
X			break;
X		}
X	}
X	return &lp;
X}
HE_HATES_THESE_CANS
if test 1583 -ne "`wc -c < 'linefunc.c'`"
then
	echo shar: error transmitting "'linefunc.c'" '(should have been 1583 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'main.c'" '(7199 characters)'
if test -f 'main.c'
then
	echo shar: will not over-write existing file "'main.c'"
else
sed 's/^X//' << \HE_HATES_THESE_CANS > 'main.c'
X/* $Header: /nw/tony/src/stevie/src/RCS/main.c,v 1.12 89/08/02 19:53:27 tony Exp $
X *
X * The main routine and routines to deal with the input buffer.
X */
X
X#include "stevie.h"
X
Xint Rows;		/* Number of Rows and Columns */
Xint Columns;		/* in the current window. */
X
Xchar *Realscreen = NULL;	/* What's currently on the screen, a single */
X				/* array of size Rows*Columns. */
Xchar *Nextscreen = NULL;	/* What's to be put on the screen. */
X
Xchar *Filename = NULL;	/* Current file name */
X
XLPTR *Filemem;		/* Pointer to the first line of the file */
X
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 byte.) */
X
XLPTR *Topchar;		/* Pointer to the byte in Filemem which is */
X			/* in 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 Cursrow, Curscol;	/* Current position of cursor */
X
Xint Cursvcol;		/* Current virtual column, the column number of */
X			/* the file's actual line, as opposed to the */
X			/* column number we're at on the screen.  This */
X			/* makes a difference on lines that span more */
X			/* than one screen line. */
X
Xint Curswant = 0;	/* The column we'd like to be at. This is used */
X			/* try to stay in the same column through up/down */
X			/* cursor motions. */
X
Xbool_t set_want_col;	/* If set, then update Curswant the next time */
X			/* through cursupdate() to the current virtual */
X			/* 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 = 0;	/* Set to 1 if something in the file has been */
X			/* changed and not written out. */
X
Xchar Redobuff[1024];	/* Each command should stuff characters into this */
X			/* buffer that will re-execute itself. */
X
Xchar Insbuff[1024];	/* Each insertion gets stuffed into this buffer. */
X
Xint Ninsert = 0;	/* Number of characters in the current insertion. */
Xchar *Insptr = NULL;
X
Xbool_t	got_int=FALSE;	/* set to TRUE when an interrupt occurs (if possible) */
X
Xbool_t	interactive = FALSE;	/* set TRUE when main() is ready to roll */
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
Xmain(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X	char	*initstr, *getenv();	/* 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	/*
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 	if (numfiles > 1)
X 		fprintf(stderr, "%d files to edit\n", numfiles);
X 
X	windinit();
X
X	/*
X	 * Allocate LPTR structures for all the various position pointers
X	 */
X 	if ((Filemem = (LPTR *) malloc(sizeof(LPTR))) == NULL ||
X 	    (Filetop = (LPTR *) malloc(sizeof(LPTR))) == NULL ||
X 	    (Fileend = (LPTR *) malloc(sizeof(LPTR))) == NULL ||
X 	    (Topchar = (LPTR *) malloc(sizeof(LPTR))) == NULL ||
X 	    (Botchar = (LPTR *) malloc(sizeof(LPTR))) == NULL ||
X 	    (Curschar = (LPTR *) malloc(sizeof(LPTR))) == NULL ||
X 	    (Insstart = (LPTR *) malloc(sizeof(LPTR))) == NULL ) {
X		fprintf(stderr, "Can't allocate data structures\n");
X		windexit(0);
X	}
X
X	screenalloc();
X	filealloc();		/* Initialize Filemem, Filetop, and Fileend */
X
X	screenclear();
X
X	if ((initstr = getenv("EXINIT")) != NULL) {
X		char *lp, buf[128];
X
X		if ((lp = getenv("LINES")) != NULL) {
X			sprintf(buf, "%s lines=%s", initstr, lp);
X			docmdln(buf);
X		} else
X			docmdln(initstr);
X	}
X
X	if (Filename != NULL) {
X		if (readfile(Filename, Filemem, FALSE))
X			filemess("[New File]");
X	} else if (tag == NULL)
X		msg("Empty Buffer");
X
X	setpcmark();
X
X	if (tag) {
X		stuffin(":ta ");
X		stuffin(tag);
X		stuffin("\n");
X
X	} else if (pat) {
X		stuffin(pat);
X		stuffin("\n");
X
X	} else if (line >= 0) {
X		if (line > 0)
X			stuffnum(line);
X		stuffin("G");
X	}
X
X	interactive = TRUE;
X
X	edit();
X
X	windexit(0);
X
X	return 1;		/* shouldn't be reached */
X}
X
X#define	RBSIZE	1024
Xstatic char getcbuff[RBSIZE];
Xstatic char *getcnext = NULL;
X
Xvoid
Xstuffin(s)
Xchar	*s;
X{
X	if (s == NULL) {		/* clear the stuff buffer */
X		getcnext = NULL;
X		return;
X	}
X
X	if (getcnext == NULL) {
X		strcpy(getcbuff,s);
X		getcnext = getcbuff;
X	} else
X		strcat(getcbuff,s);
X}
X
Xvoid
Xstuffnum(n)
Xint	n;
X{
X	char	buf[32];
X
X	sprintf(buf, "%d", n);
X	stuffin(buf);
X}
X
Xint
Xvgetc()
X{
X	register int	c;
X
X	/*
X	 * inchar() may map special keys by using stuffin(). If it does
X	 * so, it returns -1 so we know to loop here to get a real char.
X	 */
X	do {
X		if ( getcnext != NULL ) {
X			int nextc = *getcnext++;
X			if ( *getcnext == NUL ) {
X				*getcbuff = NUL;
X				getcnext = NULL;
X			}
X			return(nextc);
X		}
X		c = inchar();
X	} while (c == -1);
X
X	return c;
X}
X
X/*
X * anyinput
X *
X * Return non-zero if input is pending.
X */
X
Xbool_t
Xanyinput()
X{
X	return (getcnext != NULL);
X}
X
X/*
X * do_mlines() - process mode lines for the current file
X *
X * Returns immediately if the "ml" parameter isn't set.
X */
X#define	NMLINES	5	/* no. of lines at start/end to check for modelines */
X
Xvoid
Xdo_mlines()
X{
X	void	chk_mline();
X	int	i;
X	register LPTR	*p;
X
X	if (!P(P_ML))
X		return;
X
X	p = Filemem;
X	for (i=0; i < NMLINES ;i++) {
X		chk_mline(p->linep->s);
X		if ((p = nextline(p)) == NULL)
X			break;
X	}
X
X	if ((p = prevline(Fileend)) == NULL)
X		return;
X
X	for (i=0; i < NMLINES ;i++) {
X		chk_mline(p->linep->s);
X		if ((p = prevline(p)) == NULL)
X			break;
X	}
X}
X
X/*
X * chk_mline() - check a single line for a mode string
X */
Xstatic void
Xchk_mline(s)
Xregister char	*s;
X{
X	register char	*cs;		/* local copy of any modeline found */
X	register char	*e;
X
X	for (; *s != NUL ;s++) {
X		if (strncmp(s, "vi:", 3) == 0 || strncmp(s, "ex:", 3) == 0) {
X			cs = strsave(s+3);
X			if ((e = strchr(cs, ':')) != NULL) {
X				*e = NUL;
X				stuffin(mkstr(CTRL('o')));
X				docmdln(cs);
X			}
X			free(cs);
X		}
X	}
X}
HE_HATES_THESE_CANS
if test 7199 -ne "`wc -c < 'main.c'`"
then
	echo shar: error transmitting "'main.c'" '(should have been 7199 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'mark.c'" '(2186 characters)'
if test -f 'mark.c'
then
	echo shar: will not over-write existing file "'mark.c'"
else
sed 's/^X//' << \HE_HATES_THESE_CANS > 'mark.c'
X/* $Header: /nw/tony/src/stevie/src/RCS/mark.c,v 1.3 89/03/11 22:42:39 tony Exp $
X *
X * Routines to save and retrieve marks.
X */
X
X#include "stevie.h"
X
X#define	NMARKS	10		/* max. # of marks that can be saved */
X
Xstruct	mark {
X	char	name;
X	LPTR	pos;
X};
X
Xstatic	struct	mark	mlist[NMARKS];
Xstatic	struct	mark	pcmark;		/* previous context mark */
Xstatic	bool_t	pcvalid = FALSE;	/* true if pcmark is valid */
X
X/*
X * setmark(c) - set mark 'c' at current cursor position
X *
X * Returns TRUE on success, FALSE if no room for mark or bad name given.
X */
Xbool_t
Xsetmark(c)
Xregister char	c;
X{
X	register int	i;
X
X	if (!isalpha(c))
X		return FALSE;
X
X	/*
X	 * If there is already a mark of this name, then just use the
X	 * existing mark entry.
X	 */
X	for (i=0; i < NMARKS ;i++) {
X		if (mlist[i].name == c) {
X			mlist[i].pos = *Curschar;
X			return TRUE;
X		}
X	}
X
X	/*
X	 * There wasn't a mark of the given name, so find a free slot
X	 */
X	for (i=0; i < NMARKS ;i++) {
X		if (mlist[i].name == NUL) {	/* got a free one */
X			mlist[i].name = c;
X			mlist[i].pos = *Curschar;
X			return TRUE;
X		}
X	}
X	return FALSE;
X}
X
X/*
X * setpcmark() - set the previous context mark to the current position
X */
Xvoid
Xsetpcmark()
X{
X	pcmark.pos = *Curschar;
X	pcvalid = TRUE;
X}
X
X/*
X * getmark(c) - find mark for char 'c'
X *
X * Return pointer to LPTR or NULL if no such mark.
X */
XLPTR *
Xgetmark(c)
Xregister char	c;
X{
X	register int	i;
X
X	if (c == '\'' || c == '`')	/* previous context mark */
X		return pcvalid ? &(pcmark.pos) : (LPTR *) NULL;
X
X	for (i=0; i < NMARKS ;i++) {
X		if (mlist[i].name == c)
X			return &(mlist[i].pos);
X	}
X	return (LPTR *) NULL;
X}
X
X/*
X * clrall() - clear all marks
X *
X * Used mainly when trashing the entire buffer during ":e" type commands
X */
Xvoid
Xclrall()
X{
X	register int	i;
X
X	for (i=0; i < NMARKS ;i++)
X		mlist[i].name = NUL;
X	pcvalid = FALSE;
X}
X
X/*
X * clrmark(line) - clear any marks for 'line'
X *
X * Used any time a line is deleted so we don't have marks pointing to
X * non-existent lines.
X */
Xvoid
Xclrmark(line)
Xregister LINE	*line;
X{
X	register int	i;
X
X	for (i=0; i < NMARKS ;i++) {
X		if (mlist[i].pos.linep == line)
X			mlist[i].name = NUL;
X	}
X	if (pcvalid && (pcmark.pos.linep == line))
X		pcvalid = FALSE;
X}
HE_HATES_THESE_CANS
if test 2186 -ne "`wc -c < 'mark.c'`"
then
	echo shar: error transmitting "'mark.c'" '(should have been 2186 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'misccmds.c'" '(9492 characters)'
if test -f 'misccmds.c'
then
	echo shar: will not over-write existing file "'misccmds.c'"
else
sed 's/^X//' << \HE_HATES_THESE_CANS > 'misccmds.c'
X/* $Header: /nw/tony/src/stevie/src/RCS/misccmds.c,v 1.14 89/08/06 09:50:17 tony Exp $
X *
X * Various routines to perform specific editing operations or return
X * useful information about the file.
X */
X
X#include "stevie.h"
X
Xstatic	void	openfwd(), openbwd();
X
Xextern	bool_t	did_ai;
X
X/*
X * opencmd
X *
X * Add a blank line above or below the current line.
X */
X
Xvoid
Xopencmd(dir, can_ai)
Xint	dir;
Xint	can_ai;			/* if true, consider auto-indent */
X{
X	if (dir == FORWARD)
X		openfwd(can_ai);
X	else
X		openbwd(can_ai);
X}
X
Xstatic void
Xopenfwd(can_ai)
Xint	can_ai;
X{
X	register LINE	*l;
X	LPTR	*next;
X	register char	*s;	/* string to be moved to new line, if any */
X	int	newindex = 0;	/* index of the cursor on the new line */
X
X	/*
X	 * If we're in insert mode, we need to move the remainder of the
X	 * current line onto the new line. Otherwise the new line is left
X	 * blank.
X	 */
X	if (State == INSERT || State == REPLACE)
X		s = &Curschar->linep->s[Curschar->index];
X	else
X		s = "";
X
X	if ((next = nextline(Curschar)) == NULL)	/* open on last line */
X		next = Fileend;
X
X	/*
X	 * By asking for as much space as the prior line had we make sure
X	 * that we'll have enough space for any auto-indenting.
X	 */
X	if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
X		return;
X
X	if (*s != NUL)
X		strcpy(l->s, s);		/* copy string to new line */
X
X	else if (can_ai && P(P_AI) && !anyinput()) {
X		char	*p;
X
X		/*
X		 * Copy prior line, and truncate after white space
X		 */
X		strcpy(l->s, Curschar->linep->s);
X
X		for (p = l->s; *p == ' ' || *p == TAB ;p++)
X			;
X		*p = NUL;
X		newindex = p - l->s;
X
X		/*
X		 * If we just did an auto-indent, then we didn't type
X		 * anything on the prior line, and it should be truncated.
X		 */
X		if (did_ai)
X			Curschar->linep->s[0] = NUL;
X
X		did_ai = TRUE;
X	}
X
X	/* truncate current line at cursor */
X	if (State == INSERT || State == REPLACE)
X		*s = NUL;
X			
X
X	Curschar->linep->next = l;	/* link neighbors to new line */
X	next->linep->prev = l;
X
X	l->prev = Curschar->linep;	/* link new line to neighbors */
X	l->next = next->linep;
X
X	if (next == Fileend)			/* new line at end */
X		l->num = Curschar->linep->num + LINEINC;
X
X	else if ((l->prev->num) + 1 == l->next->num)	/* no gap, renumber */
X		renum();
X
X	else {					/* stick it in the middle */
X		unsigned long	lnum;
X		lnum = ((long)l->prev->num + (long)l->next->num) / 2;
X		l->num = lnum;
X	}
X
X	/*
X	 * Get the cursor to the start of the line, so that 'Cursrow'
X	 * gets set to the right physical line number for the stuff
X	 * that follows...
X	 */
X	Curschar->index = 0;
X	cursupdate();
X
X	/*
X	 * If we're doing an open on the last logical line, then
X	 * go ahead and scroll the screen up. Otherwise, just insert
X	 * a blank line at the right place. We use calls to plines()
X	 * in case the cursor is resting on a long line.
X	 */
X	if (Cursrow + plines(Curschar) == (Rows - 1))
X		scrollup(1);
X	else
X		s_ins(Cursrow+plines(Curschar), 1);
X
X	*Curschar = *nextline(Curschar);	/* cursor moves down */
X	Curschar->index = newindex;
X
X	updatescreen();		/* because Botchar is now invalid... */
X
X	cursupdate();		/* update Cursrow before insert */
X}
X
Xstatic void
Xopenbwd(can_ai)
Xint	can_ai;
X{
X	register LINE	*l;
X	LINE	*prev;
X	int	newindex = 0;
X
X	prev = Curschar->linep->prev;
X
X	if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
X		return;
X
X	Curschar->linep->prev = l;	/* link neighbors to new line */
X	prev->next = l;
X
X	l->next = Curschar->linep;	/* link new line to neighbors */
X	l->prev = prev;
X
X	if (can_ai && P(P_AI) && !anyinput()) {
X		char	*p;
X
X		/*
X		 * Copy current line, and truncate after white space
X		 */
X		strcpy(l->s, Curschar->linep->s);
X
X		for (p = l->s; *p == ' ' || *p == TAB ;p++)
X			;
X		*p = NUL;
X		newindex = p - l->s;
X
X		did_ai = TRUE;
X	}
X
X	Curschar->linep = Curschar->linep->prev;
X	Curschar->index = newindex;
X
X	if (prev == Filetop->linep)		/* new start of file */
X		Filemem->linep = l;
X
X	renum();	/* keep it simple - we don't do this often */
X
X	cursupdate();			/* update Cursrow before insert */
X	if (Cursrow != 0)
X		s_ins(Cursrow, 1);		/* insert a physical line */
X
X	updatescreen();
X}
X
Xint
Xcntllines(pbegin,pend)
Xregister LPTR	*pbegin, *pend;
X{
X	register LINE	*lp;
X	int	lnum = 1;
X
X	for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next)
X		lnum++;
X
X	return(lnum);
X}
X
X/*
X * plines(p) - return the number of physical screen lines taken by line 'p'
X */
Xint
Xplines(p)
XLPTR	*p;
X{
X	register int	col = 0;
X	register char	*s;
X
X	s = p->linep->s;
X
X	if (*s == NUL)		/* empty line */
X		return 1;
X
X	for (; *s != NUL ;s++) {
X		if ( *s == TAB && !P(P_LS))
X			col += P(P_TS) - (col % P(P_TS));
X		else
X			col += chars[(unsigned)(*s & 0xff)].ch_size;
X	}
X
X	/*
X	 * If list mode is on, then the '$' at the end of
X	 * the line takes up one extra column.
X	 */
X	if (P(P_LS))
X		col += 1;
X	/*
X	 * If 'number' mode is on, add another 8.
X	 */
X	if (P(P_NU))
X		col += 8;
X
X	return ((col + (Columns-1)) / Columns);
X}
X
Xvoid
Xfileinfo()
X{
X	extern	int	numfiles, curfile;
X	register long	l1, l2;
X
X	if (bufempty()) {
X 		l1 = 0;
X 		l2 = 1;			/* don't div by zero */
X 	} else {
X 		l1 = cntllines(Filemem, Curschar);
X 		l2 = cntllines(Filemem, Fileend) - 1;
X	}
X
X	if (numfiles > 1)
X		smsg("\"%s\"%s line %ld of %ld -- %ld %% -- (file %d of %d)",
X			(Filename != NULL) ? Filename : "No File",
X			Changed ? " [Modified]" : "",
X			l1, l2, (l1 * 100)/l2,
X			curfile+1, numfiles);
X	else
X		smsg("\"%s\"%s line %ld of %ld -- %ld %% --",
X			(Filename != NULL) ? Filename : "No File",
X			Changed ? " [Modified]" : "",
X			l1, l2, (l1 * 100)/l2);
X}
X
X/*
X * gotoline(n) - return a pointer to line 'n'
X *
X * Returns a pointer to the last line of the file if n is zero, or
X * beyond the end of the file.
X */
XLPTR *
Xgotoline(n)
Xregister int	n;
X{
X	static	LPTR	l;
X
X	l.index = 0;
X
X	if ( n == 0 )
X		l = *prevline(Fileend);
X	else {
X		LPTR	*p;
X
X		for (l = *Filemem; --n > 0 ;l = *p)
X			if ((p = nextline(&l)) == NULL)
X				break;
X	}
X	return &l;
X}
X
Xvoid
Xinschar(c)
Xint	c;
X{
X	register char	*p, *pend;
X
X	/* make room for the new char. */
X	if ( ! canincrease(1) )
X		return;
X
X	if (State != REPLACE) {
X		p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
X		pend = &Curschar->linep->s[Curschar->index];
X
X		for (; p > pend ;p--)
X			*p = *(p-1);
X
X		*p = c;
X
X	} else {	/* replace mode */
X		/*
X		 * Once we reach the end of the line, we are effectively
X		 * inserting new text, so make sure the string terminator
X		 * stays out there.
X		 */
X		if (gchar(Curschar) == NUL)
X			Curschar->linep->s[Curschar->index+1] = NUL;
X		pchar(Curschar, c);
X	}
X
X	/*
X	 * If we're in insert mode and showmatch mode is set, then
X	 * check for right parens and braces. If there isn't a match,
X	 * then beep. If there is a match AND it's on the screen, then
X	 * flash to it briefly. If it isn't on the screen, don't do anything.
X	 */
X	if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
X		LPTR	*lpos, csave;
X
X		if ((lpos = showmatch()) == NULL)	/* no match, so beep */
X			beep();
X		else if (LINEOF(lpos) >= LINEOF(Topchar)) {
X			updatescreen();		/* show the new char first */
X			csave = *Curschar;
X			*Curschar = *lpos;	/* move to matching char */
X			cursupdate();
X			windgoto(Cursrow, Curscol);
X			delay();		/* brief pause */
X			*Curschar = csave;	/* restore cursor position */
X			cursupdate();
X		}
X	}
X
X	inc(Curschar);
X	CHANGED;
X}
X
Xbool_t
Xdelchar(fixpos)
Xbool_t	fixpos;		/* if TRUE, fix the cursor position when done */
X{
X	register int	i;
X
X	/* Check for degenerate case; there's nothing in the file. */
X	if (bufempty())
X		return FALSE;
X
X	if (lineempty())	/* can't do anything */
X		return FALSE;
X
X	/* Delete the char. at Curschar by shifting everything */
X	/* in the line down. */
X	for ( i=Curschar->index+1; i < Curschar->linep->size ;i++)
X		Curschar->linep->s[i-1] = Curschar->linep->s[i];
X
X	/* If we just took off the last character of a non-blank line, */
X	/* we don't want to end up positioned at the newline. */
X	if (fixpos) {
X		if (gchar(Curschar)==NUL && Curschar->index>0 && State!=INSERT)
X			Curschar->index--;
X	}
X	CHANGED;
X
X	return TRUE;
X}
X
X
Xvoid
Xdelline(nlines, can_update)
Xint	nlines;
Xbool_t	can_update;
X{
X	register LINE	*p, *q;
X	int	doscreen;		/* if true, update the screen */
X
X	doscreen = can_update;
X	/*
X	 * There's no point in keeping the screen updated if we're
X	 * deleting more than a screen's worth of lines.
X	 */
X	if (nlines > (Rows - 1) && can_update) {
X		doscreen = FALSE;
X		s_del(Cursrow, Rows-1);	/* flaky way to clear rest of screen */
X	}
X
X	while ( nlines-- > 0 ) {
X
X		if (bufempty())			/* nothing to delete */
X			break;
X
X		if (buf1line()) {		/* just clear the line */
X			Curschar->linep->s[0] = NUL;
X			Curschar->index = 0;
X			break;
X		}
X
X		p = Curschar->linep->prev;
X		q = Curschar->linep->next;
X
X		if (p == Filetop->linep) {	/* first line of file so... */
X			Filemem->linep = q;	/* adjust start of file */
X			Topchar->linep = q;	/* and screen */
X		}
X		p->next = q;
X		q->prev = p;
X
X		clrmark(Curschar->linep);	/* clear marks for the line */
X
X		/*
X		 * Delete the correct number of physical lines on the screen
X		 */
X		if (doscreen)
X			s_del(Cursrow, plines(Curschar));
X
X		/*
X		 * If deleting the top line on the screen, adjust Topchar
X		 */
X		if (Topchar->linep == Curschar->linep)
X			Topchar->linep = q;
X
X		free(Curschar->linep->s);
X		free((char *) Curschar->linep);
X
X		Curschar->linep = q;
X		Curschar->index = 0;		/* is this right? */
X		CHANGED;
X
X		/* If we delete the last line in the file, back up */
X		if ( Curschar->linep == Fileend->linep) {
X			Curschar->linep = Curschar->linep->prev;
X			/* and don't try to delete any more lines */
X			break;
X		}
X	}
X}
HE_HATES_THESE_CANS
if test 9492 -ne "`wc -c < 'misccmds.c'`"
then
	echo shar: error transmitting "'misccmds.c'" '(should have been 9492 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--