v15i038: Stevie, an "aspiring" VI clone for Unix, OS/2, Amiga, Part02/04
Rich Salz
rsalz at uunet.uu.net
Tue Jun 7 00:48:56 AEST 1988
Submitted-by: onecom!wldrdg!tony (Tony Andrews)
Posting-number: Volume 15, Issue 38
Archive-name: stevie/part02
#! /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 2 (of 4)."
# Contents: cmdline.c edit.c help.c main.c misccmds.c
# Wrapped by rsalz at fig.bbn.com on Sun Jun 5 11:45:43 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cmdline.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'cmdline.c'\"
else
echo shar: Extracting \"'cmdline.c'\" \(11004 characters\)
sed "s/^X//" >'cmdline.c' <<'END_OF_FILE'
X/*
X * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
X *
X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
X *
X */
X
X#include "stevie.h"
X
static char *altfile = NULL; /* alternate file */
static int altline; /* line # in alternate file */
X
static char *nowrtmsg = "No write since last change (use ! to override)";
X
extern char **files; /* used for "n" and "rew" */
extern int numfiles, curfile;
X
X/*
X * The next two variables contain the bounds of any range given in a
X * command. If no range was given, both contain null line pointers.
X * If only a single line was given, u_pos will contain a null line
X * pointer.
X */
static LPTR l_pos, u_pos;
X
static bool_t interactive; /* TRUE if we're reading a real command line */
X
X#define CMDSZ 100 /* size of the command buffer */
X
static bool_t doecmd();
static void badcmd(), doshell(), get_range();
static LPTR *get_line();
X
X#ifdef MEGAMAX
overlay "cmdline"
X#endif
X
X/*
X * readcmdline() - accept a command line starting with ':', '/', or '?'
X *
X * readcmdline() accepts and processes colon commands and searches. If
X * 'cmdline' is null, the command line is read here. Otherwise, cmdline
X * points to a complete command line that should be used. This is used
X * in main() to handle initialization commands in the environment variable
X * "EXINIT".
X */
void
readcmdline(firstc, cmdline)
int firstc; /* either ':', '/', or '?' */
char *cmdline; /* optional command string */
X{
X int c;
X char buff[CMDSZ];
X char *p, *q, *cmd, *arg;
X
X /*
X * Clear the range variables.
X */
X l_pos.linep = (struct line *) NULL;
X u_pos.linep = (struct line *) NULL;
X
X interactive = (cmdline == NULL);
X
X if (interactive)
X gotocmd(1,1,firstc);
X p = buff;
X if ( firstc != ':' )
X *p++ = firstc;
X
X if (interactive) {
X /* collect the command string, handling '\b' and @ */
X for ( ; ; ) {
X c = vgetc();
X if ( c=='\n'||c=='\r'||c==EOF )
X break;
X if ( c=='\b' ) {
X if ( p > buff ) {
X p--;
X /* this is gross, but it relies
X * only on 'gotocmd'
X */
X gotocmd(1,0,firstc==':'?':':0);
X for ( q=buff; q<p; q++ )
X outchar(*q);
X } else {
X msg("");
X return; /* back to cmd mode */
X }
X continue;
X }
X if ( c=='@' ) {
X p = buff;
X gotocmd(1,1,firstc);
X continue;
X }
X outchar(c);
X *p++ = c;
X }
X *p = '\0';
X } else {
X if (strlen(cmdline) > CMDSZ-2) /* should really do something */
X return; /* better here... */
X strcpy(p, cmdline);
X }
X
X /* skip any initial white space */
X for ( cmd = buff; *cmd != NUL && isspace(*cmd); cmd++ )
X ;
X
X /* search commands */
X c = *cmd;
X if ( c == '/' || c == '?' ) {
X cmd++;
X if ( *cmd == c ) {
X /* the command was '//' or '??' */
X repsearch();
X return;
X }
X /* If there is a matching '/' or '?' at the end, toss it */
X p = strchr(cmd, NUL);
X if ( *(p-1) == c && *(p-2) != '\\' )
X *(p-1) = NUL;
X dosearch((c == '/') ? FORWARD : BACKWARD, cmd);
X return;
X }
X
X /*
X * Parse a range, if present (and update the cmd pointer).
X */
X get_range(&cmd);
X
X /* isolate the command and find any argument */
X for ( p=cmd; *p != NUL && ! isspace(*p); p++ )
X ;
X if ( *p == NUL )
X arg = NULL;
X else {
X *p = NUL;
X for (p++; *p != NUL && isspace(*p) ;p++)
X ;
X arg = p;
X if ( *arg == '\0' )
X arg = NULL;
X }
X if ( strcmp(cmd,"q!")==0 )
X getout();
X if ( strcmp(cmd,"q")==0 ) {
X if ( Changed )
X emsg(nowrtmsg);
X else
X getout();
X return;
X }
X if ( strcmp(cmd,"w")==0 ) {
X if ( arg == NULL ) {
X if (Filename != NULL) {
X writeit(Filename, &l_pos, &u_pos);
X UNCHANGED;
X } else
X emsg("No output file");
X }
X else
X writeit(arg, &l_pos, &u_pos);
X return;
X }
X if ( strcmp(cmd,"wq")==0 ) {
X if (Filename != NULL) {
X if ( writeit(Filename, NULL, NULL) )
X getout();
X } else
X emsg("No output file");
X return;
X }
X if ( strcmp(cmd, "x") == 0 ) {
X if (Changed) {
X if (Filename != NULL) {
X if (!writeit(Filename, NULL, NULL))
X return;
X } else {
X emsg("No output file");
X return;
X }
X }
X getout();
X }
X if ( strcmp(cmd,"f")==0 && arg==NULL ) {
X fileinfo();
X return;
X }
X if ( *cmd == 'n' ) {
X if ( (curfile + 1) < numfiles ) {
X /*
X * stuff ":e[!] FILE\n"
X */
X stuffin(":e");
X if (cmd[1] == '!')
X stuffin("!");
X stuffin(" ");
X stuffin(files[++curfile]);
X stuffin("\n");
X } else
X emsg("No more files!");
X return;
X }
X if ( *cmd == 'p' ) {
X if ( curfile > 0 ) {
X /*
X * stuff ":e[!] FILE\n"
X */
X stuffin(":e");
X if (cmd[1] == '!')
X stuffin("!");
X stuffin(" ");
X stuffin(files[--curfile]);
X stuffin("\n");
X } else
X emsg("No more files!");
X return;
X }
X if ( strncmp(cmd, "rew", 3) == 0) {
X if (numfiles <= 1) /* nothing to rewind */
X return;
X curfile = 0;
X /*
X * stuff ":e[!] FILE\n"
X */
X stuffin(":e");
X if (cmd[3] == '!')
X stuffin("!");
X stuffin(" ");
X stuffin(files[0]);
X stuffin("\n");
X return;
X }
X if ( strcmp(cmd,"e") == 0 || strcmp(cmd,"e!") == 0 ) {
X doecmd(arg, cmd[1] == '!');
X return;
X }
X if ( strcmp(cmd,"f") == 0 ) {
X Filename = strsave(arg);
X filemess("");
X return;
X }
X if ( strcmp(cmd,"r") == 0 || strcmp(cmd,".r") == 0 ) {
X if ( arg == NULL ) {
X badcmd();
X return;
X }
X if (readfile(arg, Curschar, 1)) {
X emsg("Can't open file");
X return;
X }
X updatescreen();
X CHANGED;
X return;
X }
X if ( strcmp(cmd,".=")==0 ) {
X char messbuff[80];
X sprintf(messbuff,"line %d", cntllines(Filemem,Curschar));
X msg(messbuff);
X return;
X }
X if ( strcmp(cmd,"$=")==0 ) {
X char messbuff[8];
X sprintf(messbuff, "%d", cntllines(Filemem, Fileend)-1);
X msg(messbuff);
X return;
X }
X if ( strncmp(cmd,"ta", 2) == 0 ) {
X dotag(arg, cmd[2] == '!');
X return;
X }
X if ( strcmp(cmd,"set")==0 ) {
X doset(arg, interactive);
X return;
X }
X if ( strcmp(cmd,"help")==0 ) {
X if (help()) {
X screenclear();
X updatescreen();
X }
X return;
X }
X if ( strcmp(cmd, "version") == 0) {
X extern char *Version;
X
X msg(Version);
X return;
X }
X if ( strcmp(cmd, "sh") == 0) {
X doshell();
X return;
X }
X /*
X * If we got a line, but no command, then go to the line.
X */
X if (*cmd == NUL && l_pos.linep != NULL) {
X *Curschar = l_pos;
X cursupdate();
X return;
X }
X
X badcmd();
X}
X
X/*
X * get_range - parse a range specifier
X *
X * Ranges are of the form:
X *
X * addr[,addr]
X *
X * where 'addr' is:
X *
X * $ [+- NUM]
X * 'x [+- NUM] (where x denotes a currently defined mark)
X * . [+- NUM]
X * NUM
X *
X * The pointer *cp is updated to point to the first character following
X * the range spec. If an initial address is found, but no second, the
X * upper bound is equal to the lower.
X */
static void
get_range(cp)
char **cp;
X{
X LPTR *l;
X char *p;
X
X if ((l = get_line(cp)) == NULL)
X return;
X
X l_pos = *l;
X
X for (p = *cp; *p != NUL && isspace(*p) ;p++)
X ;
X
X *cp = p;
X
X if (*p != ',') { /* is there another line spec ? */
X u_pos = l_pos;
X return;
X }
X
X *cp = ++p;
X
X if ((l = get_line(cp)) == NULL) {
X u_pos = l_pos;
X return;
X }
X
X u_pos = *l;
X}
X
static LPTR *
get_line(cp)
char **cp;
X{
X static LPTR pos;
X LPTR *lp;
X char *p, c;
X int lnum;
X
X pos.index = 0; /* shouldn't matter... check back later */
X
X p = *cp;
X /*
X * Determine the basic form, if present.
X */
X switch (c = *p++) {
X
X case '$':
X pos.linep = Fileend->linep->prev;
X break;
X
X case '.':
X pos.linep = Curschar->linep;
X break;
X
X case '\'':
X if ((lp = getmark(*p++)) == NULL) {
X emsg("Unknown mark");
X return (LPTR *) NULL;
X }
X pos = *lp;
X break;
X
X case '0': case '1': case '2': case '3': case '4':
X case '5': case '6': case '7': case '8': case '9':
X for (lnum = c - '0'; isdigit(*p) ;p++)
X lnum = (lnum * 10) + (*p - '0');
X
X pos = *gotoline(lnum);
X break;
X
X default:
X return (LPTR *) NULL;
X }
X
X while (*p != NUL && isspace(*p))
X p++;
X
X if (*p == '-' || *p == '+') {
X bool_t neg = (*p++ == '-');
X
X for (lnum = 0; isdigit(*p) ;p++)
X lnum = (lnum * 10) + (*p - '0');
X
X if (neg)
X lnum = -lnum;
X
X pos = *gotoline( cntllines(Filemem, &pos) + lnum );
X }
X
X *cp = p;
X return &pos;
X}
X
static void
badcmd()
X{
X if (interactive)
X emsg("Unrecognized command");
X}
X
X#define LSIZE 512 /* max. size of a line in the tags file */
X
X/*
X * dotag(tag, force) - goto tag
X */
void
dotag(tag, force)
char *tag;
bool_t force;
X{
X FILE *tp, *fopen();
X char lbuf[LSIZE];
X char *fname, *str;
X
X if ((tp = fopen("tags", "r")) == NULL) {
X emsg("Can't open tags file");
X return;
X }
X
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 if (doecmd(fname, force)) {
X stuffin(str); /* str has \n at end */
X stuffin("\007"); /* CTRL('G') */
X fclose(tp);
X return;
X }
X }
X }
X emsg("tag not found");
X fclose(tp);
X}
X
static bool_t
doecmd(arg, force)
char *arg;
bool_t force;
X{
X int line = 1; /* line # to go to in new file */
X
X if (!force && Changed) {
X emsg(nowrtmsg);
X return FALSE;
X }
X if ( arg != NULL ) {
X /*
X * First detect a ":e" on the current file. This is mainly
X * for ":ta" commands where the destination is within the
X * current file.
X */
X if (Filename != NULL && strcmp(arg, Filename) == 0) {
X if (!Changed || (Changed && !force))
X return TRUE;
X }
X if (strcmp(arg, "#") == 0) { /* alternate */
X char *s = Filename;
X
X if (altfile == NULL) {
X emsg("No alternate file");
X return FALSE;
X }
X Filename = altfile;
X altfile = s;
X line = altline;
X altline = cntllines(Filemem, Curschar);
X } else {
X altfile = Filename;
X altline = cntllines(Filemem, Curschar);
X Filename = strsave(arg);
X }
X }
X if (Filename == NULL) {
X emsg("No filename");
X return FALSE;
X }
X
X /* clear mem and read file */
X freeall();
X filealloc();
X UNCHANGED;
X
X readfile(Filename, Filemem, 0);
X *Topchar = *Curschar;
X if (line != 1) {
X stuffnum(line);
X stuffin("G");
X }
X setpcmark();
X updatescreen();
X return TRUE;
X}
X
static void
doshell()
X{
X char *sh, *getenv();
X
X if ((sh = getenv("SHELL")) == NULL) {
X emsg("Shell variable not set");
X return;
X }
X gotocmd(TRUE, FALSE, 0);
X
X if (system(sh) < 0) {
X emsg("Exec failed");
X return;
X }
X
X wait_return();
X}
X
void
gotocmd(clr, fresh, firstc)
bool_t clr, fresh;
char firstc;
X{
X int n;
X
X windgoto(Rows-1,0);
X if ( clr )
X outstr(T_EL); /* clear the bottom line */
X if ( firstc )
X outchar(firstc);
X}
X
X/*
X * msg(s) - displays the string 's' on the status line
X */
void
msg(s)
char *s;
X{
X gotocmd(TRUE, TRUE, 0);
X outstr(s);
X}
X
void
smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
char *s;
int a1, a2, a3, a4, a5, a6, a7, a8, a9;
X{
X char sbuf[80];
X
X sprintf(sbuf, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X msg(sbuf);
X}
X
X/*
X * emsg() - display an error message
X *
X * Rings the bell, if appropriate, and calls message() to do the real work
X */
void
emsg(s)
char *s;
X{
X if (P(P_EB))
X beep();
X msg(s);
X}
X
void
wait_return()
X{
X char c;
X
X outstr("Press RETURN to continue");
X do {
X c = vgetc();
X } while (c != '\r' && c != '\n');
X
X screenclear();
X updatescreen();
X}
END_OF_FILE
if test 11004 -ne `wc -c <'cmdline.c'`; then
echo shar: \"'cmdline.c'\" unpacked with wrong size!
fi
# end of 'cmdline.c'
fi
if test -f 'edit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'edit.c'\"
else
echo shar: Extracting \"'edit.c'\" \(6480 characters\)
sed "s/^X//" >'edit.c' <<'END_OF_FILE'
X/*
X * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
X *
X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
X *
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 */
bool_t did_ai = FALSE;
X
void
edit()
X{
X int c;
X 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 for ( ;; ) {
X
X /* Figure out where the cursor is based on Curschar. */
X cursupdate();
X
X windgoto(Cursrow,Curscol);
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' */
X if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && 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 switch (c) { /* We're in insert mode */
X
X case ESC: /* an escape ends input mode */
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 *Uncurschar = *Insstart;
X Undelchars = Ninsert;
X /* Undobuff[0] = '\0'; */
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 delchar(TRUE);
X Insptr--;
X Ninsert--;
X cursupdate();
X updateline();
X break;
X
X case CR:
X case NL:
X *Insptr++ = NL;
X Ninsert++;
X opencmd(FORWARD, TRUE); /* open a new line */
X cursupdate();
X updatescreen();
X break;
X
X default:
X did_ai = FALSE;
X insertchar(c);
X break;
X }
X }
X }
X}
X
X/*
X * Special characters in this context are those that need processing other
X * than the simple insertion that can be performed here. This includes ESC
X * which terminates the insert, and CR/NL which need special processing to
X * open up a new line. This routine tries to optimize insertions performed
X * by the "redo" command, so it needs to know when it should stop and defer
X * processing to the "normal" mechanism.
X */
X#define ISSPECIAL(c) ((c) == NL || (c) == CR || (c) == ESC)
X
void
insertchar(c)
int c;
X{
X char *p;
X
X if ( ! anyinput() ) {
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 }
X else {
X /* If there's any pending input, grab it all at once. */
X p = Insptr;
X *Insptr++ = c;
X Ninsert++;
X for (c = vpeekc(); !ISSPECIAL(c) ;c = vpeekc()) {
X c = vgetc();
X *Insptr++ = c;
X Ninsert++;
X }
X *Insptr = '\0';
X insstr(p);
X }
X updateline();
X}
X
void
getout()
X{
X windgoto(Rows-1,0);
X putchar('\r');
X putchar('\n');
X windexit(0);
X}
X
void
scrolldown(nlines)
int 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 if (Curschar->linep == Botchar->linep->prev)
X *Curschar = *prevline(Curschar);
X }
X s_ins(0, done);
X}
X
void
scrollup(nlines)
int 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
bool_t
oneright()
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}
X
bool_t
oneleft()
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}
X
void
beginline(flag)
bool_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
bool_t
oneup(n)
X{
X LPTR p, *np;
X 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
bool_t
onedown(n)
X{
X LPTR p, *np;
X 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 6480 -ne `wc -c <'edit.c'`; then
echo shar: \"'edit.c'\" unpacked with wrong size!
fi
# end of 'edit.c'
fi
if test -f 'help.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'help.c'\"
else
echo shar: Extracting \"'help.c'\" \(8348 characters\)
sed "s/^X//" >'help.c' <<'END_OF_FILE'
X/*
X * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
X *
X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
X *
X */
X
X#include "stevie.h"
X
char *Version = "STEVIE - Version 3.10";
X
static int helprow;
X
X#ifdef HELP
X
X#ifdef MEGAMAX
overlay "help"
X#endif
X
static void longline();
X
bool_t
help()
X{
X
X/***********************************************************************
X * First Screen: Positioning within file, Adjusting the Screen
X ***********************************************************************/
X
X outstr(T_ED);
X windgoto(helprow = 0, 0);
X
longline("\
X Positioning within file\n\
X =======================\n\
X ^F Forward screenfull Original version by:\n\
X ^B Backward screenfull Tim Thompson\n");
longline("\
X ^D scroll down half screen\n\
X ^U scroll up half screen Extensive hacks by:\n");
longline("\
X G Goto line (end default) Tony Andrews\n\
X ]] next function\n\
X [[ previous function\n\
X /re next occurence of regular expression 're'\n");
longline("\
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");
longline("\
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");
longline("\
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
longline("\
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");
longline("\
X l forward\n\
X ^H same as h\n\
X space same as l\n\
X fx find 'x' forward\n");
longline("\
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");
longline("\
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
longline("\
X Line Positioning\n\
X =====================\n\
X H home window line\n\
X L last window line\n\
X M middle window line\n");
longline("\
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
longline("\
X\n\
X Marking and Returning\n\
X =====================\n\
X `` previous context\n\
X '' ... at first non-white in line\n");
longline("\
X mx mark position with letter 'x'\n\
X `x to mark 'x'\n\
X 'x ... at first non-white in line\n");
X
X windgoto(helprow = Rows-2, 47);
X longline("<Press space bar to continue>\n");
X windgoto(helprow = Rows-1, 47);
X longline("<Any other key will quit>");
X
X if ( vgetc() != ' ' )
X return TRUE;
X/***********************************************************************
X * Fourth Screen: Insert & Replace,
X ***********************************************************************/
X
X outstr(T_ED);
X windgoto(helprow = 0, 0);
X
longline("\
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");
longline("\
X o open line below\n\
X O open line above\n\
X rx replace single char with 'x'\n\
X R replace characters (not yet)\n");
X
longline("\
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");
longline("\
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
longline("\
X Undo & Redo\n\
X =============\n\
X u undo last change (partially done)\n\
X U restore current line (not yet)\n\
X . repeat last change\n");
X
longline("\
X\n\
X File manipulation\n\
X =================\n");
longline("\
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");
longline("\
X :e! reedit, discard changes\n\
X :e # edit alternate file\n\
X :w name write file 'name'\n");
longline("\
X :n edit next 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");
longline("\
X :f file change current file name\n\
X :ta tag to tag file entry 'tag'\n\
X ^] :ta, current word is tag\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 * Sixth Screen: Operators, Misc. operations, Yank & Put
X ***********************************************************************/
X
X outstr(T_ED);
X windgoto(helprow = 0, 0);
X
longline("\
X Operators (double to affect lines)\n\
X ==================================\n\
X d delete\n\
X c change\n");
longline("\
X < left shift\n\
X > right shift\n\
X y yank to buffer\n");
X
longline("\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");
longline("\
X S substitute lines (not yet)\n\
X J join lines\n\
X x delete characters\n\
X X ... before cursor\n");
X
longline("\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 vgetc();
X
X return TRUE;
X}
X
static void
longline(p)
char *p;
X{
X char *s;
X
X for ( s = p; *s ;s++ ) {
X if ( *s == '\n' )
X windgoto(++helprow, 0);
X else
X outchar(*s);
X }
X}
X#else
X
bool_t
help()
X{
X msg("Sorry, help not configured");
X return FALSE;
X}
X#endif
END_OF_FILE
if test 8348 -ne `wc -c <'help.c'`; then
echo shar: \"'help.c'\" unpacked with wrong size!
fi
# end of 'help.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(6750 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/*
X * STEVIE - ST Editor for VI Enthusiasts ...Tim Thompson...twitch!tjt...
X *
X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
X *
X */
X
X#include "stevie.h"
X
int Rows; /* Number of Rows and Columns */
int Columns; /* in the current window. */
X
char *Realscreen = NULL; /* What's currently on the screen, a single */
X /* array of size Rows*Columns. */
char *Nextscreen = NULL; /* What's to be put on the screen. */
X
char *Filename = NULL; /* Current file name */
X
LPTR *Filemem; /* The contents of the file, as a single array. */
X
LPTR *Fileend; /* Pointer to the end of the file in Filemem. */
X /* (It points to the byte AFTER the last byte.) */
X
LPTR *Topchar; /* Pointer to the byte in Filemem which is */
X /* in the upper left corner of the screen. */
X
LPTR *Botchar; /* Pointer to the byte in Filemem which is */
X /* just off the bottom of the screen. */
X
LPTR *Curschar; /* Pointer to byte in Filemem at which the */
X /* cursor is currently placed. */
X
int Cursrow, Curscol; /* Current position of cursor */
X
int 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
int 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
bool_t set_want_col; /* If set, then update Curswant the next time */
X /* through cursupdate() to the current virtual */
X /* column. */
X
int State = NORMAL; /* This is the current state of the command */
X /* interpreter. */
X
int Prenum = 0; /* The (optional) number before a command. */
X
LPTR *Insstart; /* This is where the latest insert/append */
X /* mode started. */
X
bool_t Changed = 0; /* Set to 1 if something in the file has been */
X /* changed and not written out. */
X
bool_t Debug = 0;
X
char Redobuff[1024]; /* Each command should stuff characters into this */
X /* buffer that will re-execute itself. */
X
char Undobuff[1024]; /* Each command should stuff characters into this */
X /* buffer that will undo its effects. */
X
char Insbuff[1024]; /* Each insertion gets stuffed into this buffer. */
X
LPTR *Uncurschar; /* Curschar is restored to this before undoing. */
X
int Ninsert = 0; /* Number of characters in the current insertion. */
int Undelchars = 0; /* Number of characters to delete, when undoing. */
char *Insptr = NULL;
X
char **files; /* list of input files */
int numfiles; /* number of input files */
int curfile; /* number of the current file */
X
static void
usage()
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
main(argc,argv)
int argc;
char *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 windinit();
X
X /*
X * Allocate LPTR structures for all the various position pointers
X */
X if ((Filemem = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
X fprintf(stderr, "Can't allocate data structures\n");
X windexit(0);
X }
X if ((Fileend = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
X fprintf(stderr, "Can't allocate data structures\n");
X windexit(0);
X }
X if ((Topchar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
X fprintf(stderr, "Can't allocate data structures\n");
X windexit(0);
X }
X if ((Botchar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
X fprintf(stderr, "Can't allocate data structures\n");
X windexit(0);
X }
X if ((Curschar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
X fprintf(stderr, "Can't allocate data structures\n");
X windexit(0);
X }
X if ((Insstart = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
X fprintf(stderr, "Can't allocate data structures\n");
X windexit(0);
X }
X if ((Uncurschar = (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 & 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 readcmdline(':', buf);
X } else
X readcmdline(':', initstr);
X }
X
X if (Filename != NULL) {
X if (readfile(Filename, Filemem, FALSE))
X filemess("[New File]");
X } else
X msg("Empty Buffer");
X
X setpcmark();
X
X updatescreen();
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 edit();
X
X windexit(0);
X}
X
X#define RBSIZE 1280 /* should be a little bigger than YBSIZE */
static char getcbuff[RBSIZE];
static char *getcnext = NULL;
X
void
stuffin(s)
char *s;
X{
X if ( getcnext == NULL ) {
X strcpy(getcbuff,s);
X getcnext = getcbuff;
X } else
X strcat(getcbuff,s);
X}
X
void
stuffnum(n)
int n;
X{
X char buf[32];
X
X sprintf(buf, "%d", n);
X stuffin(buf);
X}
X
void
addtobuff(s,c1,c2,c3,c4,c5,c6)
char *s;
char c1, c2, c3, c4, c5, c6;
X{
X char *p = s;
X if ( (*p++ = c1) == NUL )
X return;
X if ( (*p++ = c2) == NUL )
X return;
X if ( (*p++ = c3) == NUL )
X return;
X if ( (*p++ = c4) == NUL )
X return;
X if ( (*p++ = c5) == NUL )
X return;
X if ( (*p++ = c6) == NUL )
X return;
X}
X
int
vgetc()
X{
X if ( getcnext != NULL ) {
X int nextc = *getcnext++;
X if ( *getcnext == NUL ) {
X *getcbuff = NUL;
X getcnext = NULL;
X }
X return(nextc);
X }
X return(inchar());
X}
X
int
vpeekc()
X{
X if ( getcnext != NULL )
X return(*getcnext);
X return(-1);
X}
X
X/*
X * anyinput
X *
X * Return non-zero if input is pending.
X */
X
bool_t
anyinput()
X{
X return (getcnext != NULL);
X}
END_OF_FILE
if test 6750 -ne `wc -c <'main.c'`; then
echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'misccmds.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'misccmds.c'\"
else
echo shar: Extracting \"'misccmds.c'\" \(8039 characters\)
sed "s/^X//" >'misccmds.c' <<'END_OF_FILE'
X/*
X * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
X *
X * Extensive modifications by: Tony Andrews onecom!wldrdg!tony
X *
X */
X
X#include "stevie.h"
X
static void openfwd(), openbwd();
X
extern int did_ai;
X
X/*
X * opencmd
X *
X * Add a blank line above or below the current line.
X */
X
void
opencmd(dir, can_ai)
int dir;
int can_ai; /* if true, consider auto-indent */
X{
X if (dir == FORWARD)
X openfwd(can_ai);
X else
X openbwd(can_ai);
X}
X
static void
openfwd(can_ai)
int can_ai;
X{
X LINE *l;
X LPTR *next;
X char *s; /* string to be moved to new line, if any */
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)
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#if 0
X else if (can_ai && P(P_AI)) {
X /*
X * Auto-indent removed due to buggy implementation...
X */
X did_ai = TRUE;
X }
X#endif
X
X if (State == INSERT) /* truncate current line at cursor */
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 *Curschar = *nextline(Curschar); /* cursor moves down */
X Curschar->index = 0;
X
X s_ins(Cursrow+1, 1); /* insert a physical line */
X
X updatescreen(); /* because Botchar is now invalid... */
X
X cursupdate(); /* update Cursrow before insert */
X}
X
static void
openbwd(can_ai)
int can_ai;
X{
X LINE *l;
X LPTR *prev;
X
X prev = prevline(Curschar);
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 if (prev != NULL)
X prev->linep->next = l;
X
X l->next = Curschar->linep; /* link new line to neighbors */
X if (prev != NULL)
X l->prev = prev->linep;
X
X#if 0
X if (can_ai && P(P_AI)) {
X did_ai = TRUE;
X }
X#endif
X
X *Curschar = *prevline(Curschar); /* cursor moves up */
X Curschar->index = 0;
X
X if (prev == NULL) /* 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
int
cntllines(pbegin,pend)
LPTR *pbegin, *pend;
X{
X 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 */
int
plines(p)
LPTR *p;
X{
X register int col;
X register char *s;
X
X s = p->linep->s;
X
X if (*s == NUL) /* empty line */
X return 1;
X
X /*
X * If list mode is on, then the '$' at the end of
X * the line takes up one extra column.
X */
X col = P(P_LS) ? 1 : 0;
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 return ((col + (Columns-1)) / Columns);
X}
X
void
fileinfo()
X{
X long l1, l2;
X char buf[80];
X
X if (bufempty()) {
X msg("Buffer Empty");
X return;
X }
X
X l1 = cntllines(Filemem, Curschar);
X l2 = cntllines(Filemem, Fileend) - 1;
X sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
X (Filename != NULL) ? Filename : "No File",
X Changed ? " [Modified]" : "",
X l1, l2, (l1 * 100)/l2);
X msg(buf);
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 */
LPTR *
gotoline(n)
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
void
inschar(c)
int c;
X{
X register char *p, *pend;
X
X /* make room for the new char. */
X if ( ! canincrease(1) )
X return;
X
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 /*
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
void
insstr(s)
register char *s;
X{
X register char *p, *endp;
X register int k, n = strlen(s);
X
X /* Move everything in the file over to make */
X /* room for the new string. */
X if (!canincrease(n))
X return;
X
X endp = &Curschar->linep->s[Curschar->index];
X p = Curschar->linep->s + strlen(Curschar->linep->s) + 1 + n;
X
X for (; p>endp ;p--)
X *p = *(p-n);
X
X p = &Curschar->linep->s[Curschar->index];
X for ( k=0; k<n; k++ ) {
X *p++ = *s++;
X inc(Curschar);
X }
X CHANGED;
X}
X
bool_t
delchar(fixpos)
bool_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
void
delline(nlines)
X{
X register LINE *p, *q;
X int doscreen = TRUE; /* if true, update the screen */
X
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)) {
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 == NULL) { /* first line of file so... */
X Filemem->linep = q; /* adjust start of file */
X Topchar->linep = q; /* and screen */
X } else
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(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}
END_OF_FILE
if test 8039 -ne `wc -c <'misccmds.c'`; then
echo shar: \"'misccmds.c'\" unpacked with wrong size!
fi
# end of 'misccmds.c'
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 4 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list