Vile 15/17 - vi feel-alike (multi-window)
Paul Fox
pgf at cayman.COM
Sat Jun 8 08:10:19 AEST 1991
#!/bin/sh
# this is vileshar.15 (part 15 of Vile)
# do not concatenate these parts, unpack them in order with /bin/sh
# file tags continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 15; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
echo 'x - continuing file tags'
sed 's/^X//' << 'SHAR_EOF' >> 'tags' &&
va_list display.c 1509
va_start display.c /^#define va_start(list) list = (char *) &va_alist$/
varinit eval.c /^varinit() \/* initialize the user variable list *\//
vcalloc vmalloc.c /^vcalloc(n,size,f,l)$/
vdump vmalloc.c /^vdump(id)$/
vfree vmalloc.c /^vfree(buffer,f,l)$/
vglobals globals.c /^vglobals(f,n)$/
viewfile file.c /^viewfile(f, n) \/* visit a file in VIEW mode *\/$/
visual main.c /^visual() { return unimpl(); }$/
vmalloc vmalloc.c /^vmalloc(size,f,l)$/
vmalloc.c vmalloc.c 1
void search.c /^#define void int$/
vrealloc vmalloc.c /^vrealloc(buffer,size,f,l)$/
vteeol display.c /^vteeol()$/
vtgetc display.c /^vtgetc(col)$/
vtinit display.c /^vtinit()$/
vtmove display.c /^vtmove(row, col)$/
vtputc display.c /^vtputc(c,list)$/
vtputsn display.c /^vtputsn(s,n)$/
vttidy display.c /^vttidy(f)$/
vverify estruct.h /^# define vverify(s) rvverify(s,__FILE__,__LINE__)$/
window.c window.c 1
winit window.c /^winit()$/
word.c word.c 1
wordcount word.c /^wordcount(f, n)$/
wordmov.c wordmov.c 1
wpopup window.c /^wpopup()$/
wrapword word.c /^wrapword()$/
writemsg random.c /^writemsg(f, n)$/
writeout file.c /^writeout(fn,bp,msgf)$/
writequit main.c /^writequit(f,n)$/
writereg file.c /^writereg(rp,fn,msgf)$/
writeregion file.c /^writeregion(f,n)$/
yankline random.c /^yankline(f, n)$/
yankregion region.c /^yankregion(f, n)$/
zotbuf buffer.c /^zotbuf(bp) \/* kill the buffer pointed to by bp *\/$/
SHAR_EOF
echo 'File tags is complete' &&
chmod 0444 tags ||
echo 'restore of tags failed'
Wc_c="`wc -c < 'tags'`"
test 57909 -eq "$Wc_c" ||
echo 'tags: original size 57909, current size' "$Wc_c"
# ============= tags.c ==============
echo 'x - extracting tags.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'tags.c' &&
#include "estruct.h"
#include "edef.h"
X
#if TAGS
X
#ifndef NULL
#define NULL 0
#endif
X
/* Look up vi-style tags in the file "tags".
X Invoked either by ":ta routine-name" or by "^]" while sitting
X on a string. In the latter case, the tag is the word under
X the cursor.
X written for vile by Paul Fox, (c)1990
X */
gototag(f,n)
{
X register int i = 0;
X register int s = TRUE;
X static char tname[NFILEN];
X
X if (clexec || isnamedcmd) {
X if ((s=mlreply("Tag name: ", tname, NFILEN)) != TRUE)
X return (s);
X } else {
X screen_string(tname,NFILEN,_ident);
X }
X if (s == TRUE)
X s = tags(tname);
X return s;
}
X
static BUFFER *tagbp;
X
tags(tag)
char *tag;
{
X BUFFER *ocurbp;
X register LINE *lp, *clp;
X register int i, s;
X char *tfp, *lplim;
X char tname[NFILEN];
X char tfname[NFILEN];
X char tagpat[NPAT];
X int lineno;
X int changedfile;
X LINE *odotp;
X int odoto;
X LINE *cheap_scan();
X
X strcpy(tname,tag);
X
X if (tagbp == NULL) {
X if (gettagsfile() == FALSE)
X return FALSE;
X }
X
X strcat(tname,"\t");
X
X lp = cheap_scan(tagbp,tname);
X if (lp == NULL) {
X TTbeep();
X mlwrite("No such tag: %s",tname);
X return FALSE;
X }
X
X tfp = lp->l_text + strlen(tname);
X lplim = &lp->l_text[lp->l_used];
X i = 0;
X while (i < NFILEN && tfp < lplim && *tfp != '\t') {
X tfname[i++] = *tfp++;
X }
X if (tfp >= lplim - 2) {
X mlwrite("Bad line in tags file.");
X return FALSE;
X }
X
X if (curbp && curwp) {
X lineno = 1;
X for(clp = lforw(curbp->b_linep);
X clp != curwp->w_dotp; clp = lforw(clp))
X lineno++;
X pushuntag(curbp->b_fname, lineno);
X }
X
X tfname[i] = 0;
X if (curbp == NULL || strcmp(tfname,curbp->b_fname)) {
X s = getfile(tfname,TRUE);
X if (s != TRUE) {
X tossuntag();
X return s;
X }
X changedfile = TRUE;
X } else {
X tname[strlen(tname)-1] = '\0'; /* get rid of tab we added */
X mlwrite("[Tag \"%s\" in current buffer]", tname);
X changedfile = FALSE;
X }
X
X /* it's an absolute move -- remember where we are */
X odotp = curwp->w_dotp;
X odoto = curwp->w_doto;
X
X i = 0;
X tfp++; /* skip the tab */
X if (isdigit(*tfp)) { /* then it's a line number */
X int lineno = 0;
X while (isdigit(*tfp)) {
X lineno = 10*lineno + *tfp - '0';
X tfp++;
X }
X s = gotoline(TRUE,lineno);
X if (s != TRUE && !changedfile)
X tossuntag();
X } else {
X tfp += 2; /* skip the "/^" */
X lplim -= 2; /* skip the "$/" */
X while (i < NPAT && tfp < lplim) {
X if (*tfp == '\\' && tfp < lplim - 1)
X tfp++; /* the backslash escapes the next char */
X tagpat[i++] = *tfp++;
X }
X tagpat[i] = 0;
X lp = cheap_scan(curbp,tagpat);
X if (lp == NULL) {
X mlwrite("Tag not present");
X if (!changedfile)
X tossuntag();
X return FALSE;
X }
X curwp->w_dotp = lp;
X curwp->w_flag |= WFMOVE;
X firstnonwhite(FALSE,1);
X s = TRUE;
X }
X /* if we moved, update the "last dot" mark */
X if (s == TRUE && curwp->w_dotp != odotp) {
X curwp->w_ldmkp = odotp;
X curwp->w_ldmko = odoto;
X }
X return s;
X
}
X
gettagsfile()
{
X int s;
X char *tagsfile;
X
X /* is there a "tags" buffer around? */
X if ((tagbp=bfind("tags", NO_CREAT, 0)) == NULL) {
X /* look up the tags file */
X tagsfile = flook("tags", FL_HERE);
X
X /* if it isn't around, don't sweat it */
X if (tagsfile == NULL)
X {
X mlwrite("No tags file available.");
X return(FALSE);
X }
X
X /* find the pointer to that buffer */
X if ((tagbp=bfind("tags", OK_CREAT, BFINVS)) == NULL) {
X mlwrite("No tags buffer");
X return(FALSE);
X }
X
X if ((s = readin(tagsfile, FALSE, tagbp, FALSE)) != TRUE) {
X return(s);
X }
X tagbp->b_flag |= BFINVS;
X }
X return TRUE;
}
X
LINE *
cheap_scan(bp,name)
BUFFER *bp;
char *name;
{
X LINE *lp;
X register int len;
X len = strlen(name);
X lp = lforw(bp->b_linep);
X while (lp != bp->b_linep) {
X if (llength(lp) >= len) {
X if (llength(lp) >= len &&
X !strncmp(lp->l_text, name, len))
X return lp;
X }
X lp = lforw(lp);
X }
X return NULL;
}
X
untagpop(f,n)
int f,n;
{
X int lineno;
X char fname[NFILEN];
X if (!f) n = 1;
X while (n-- && popuntag(fname,&lineno))
X ;
X if (lineno && fname[0]) {
X int s;
X s = getfile(fname,FALSE);
X if (s != TRUE)
X return s;
X return gotoline(TRUE,lineno);
X }
X TTbeep();
X mlwrite("No stacked un-tags");
X return FALSE;
}
X
X
struct untag {
X char *u_fname;
X int u_lineno;
X struct untag *u_stklink;
};
X
struct untag *untaghead = NULL;
X
pushuntag(fname,lineno)
char *fname;
int lineno;
{
X struct untag *utp;
X utp = (struct untag *)malloc(sizeof(struct untag));
X if (!utp)
X return;
X
X utp->u_fname = (char *)malloc(strlen(fname)+1);
X if (!utp->u_fname) {
X free(utp);
X return;
X }
X
X strcpy(utp->u_fname, fname);
X utp->u_lineno = lineno;
X utp->u_stklink = untaghead;
X untaghead = utp;
}
X
popuntag(fname,linenop)
char *fname;
int *linenop;
{
X register struct untag *utp;
X
X if (untaghead) {
X utp = untaghead;
X untaghead = utp->u_stklink;
X strcpy(fname, utp->u_fname);
X *linenop = utp->u_lineno;
X free(utp->u_fname);
X free(utp);
X return TRUE;
X }
X fname[0] = '\0';
X *linenop = 0;
X return FALSE;
X
}
X
/* discard without returning anything */
tossuntag()
{
X register struct untag *utp;
X
X if (untaghead) {
X utp = untaghead;
X untaghead = utp->u_stklink;
X free(utp);
X }
X return;
X
}
X
BUFFER *filesbp;
X
X
/* create a filelist from the contents of
X * the tags file. for "dir1/dir2/file" include both that and
X * "dir1/dir2/"
X */
makeflist()
{
X register LINE *tlp, *flp;
X register char *fnp;
X register int i;
X register int len;
X char fname[NFILEN];
X char *strchr();
X
X if (!(othmode & OTH_LAZY))
X return TRUE;
X
X if (!tagbp && gettagsfile() == FALSE)
X return FALSE;
X
X if (filesbp != NULL)
X return TRUE;
X
X /* create the file list buffer */
X filesbp = bfind("[files]", OK_CREAT, BFINVS);
X if (filesbp == NULL)
X return FALSE;
X filesbp->b_active = TRUE;
X
X /* loop through the tags file */
X tlp = lforw(tagbp->b_linep);
X while (tlp != tagbp->b_linep) {
X /* skip the tagname */
X i = 0;
X while (i < llength(tlp) && lgetc(tlp,i++) != '\t')
X ;
X /* we're going to store the pathnames reversed, so that
X the sorting puts all directories together (they'll
X all start with their trailing slash) and all
X files with matching basenames will be grouped
X together as well.
X */
X /* pull out the filename, in reverse */
X fnp = &fname[NFILEN-1];
X *fnp-- = '\0';
X while (i < llength(tlp) && fnp >= fname &&
X (*fnp = lgetc(tlp,i++)) != '\t') {
X fnp--;
X }
X fnp++; /* forward past the tab */
X
X /* insert into the file list */
X if (sortsearch(fnp, &fname[NFILEN-1]-fnp, filesbp,
X TRUE, NULL) == NULL)
X return FALSE;
X
X if (fnp = strchr(fnp, '/')) { /* first (really last) slash */
X /* insert the directory name into the file list again */
X if (sortsearch(fnp, &fname[NFILEN-1]-fnp, filesbp,
X TRUE, NULL) == NULL)
X return FALSE;
X }
X tlp = lforw(tlp);
X }
X return TRUE;
}
X
/* look for or insert a text string into the given buffer. start looking
X at the given line if non-null. */
sortsearch(text, len, bp, insert, lpp)
char *text;
int len;
BUFFER *bp;
int insert;
LINE **lpp;
{
X LINE *nlp, *lp;
X register int i, r, cmplen;
X
X if (lpp == NULL) {
X lp = lforw(bp->b_linep);
X } else {
X lp = *lpp;
X if (lp == NULL)
X lp = lforw(bp->b_linep);
X else
X lp = lforw(lp);
X }
X
X while (1) {
X cmplen = (len < llength(lp) && !insert) ? len : llength(lp);
X if ((r = strncmp(text, lp->l_text, cmplen)) > 0 ||
X lp == bp->b_linep) { /* stick line into buffer */
X if (!insert)
X return FALSE;
X if ((nlp=lalloc(len)) == NULL)
X return FALSE;
X memcpy(nlp->l_text, text, len);
X lp->l_bp->l_fp = nlp;
X nlp->l_bp = lp->l_bp;
X lp->l_bp = nlp;
X nlp->l_fp = lp;
X if (lpp)
X *lpp = nlp;
X return TRUE;
X } else if (r == 0) { /* it's already here, don't insert twice */
X if (lpp)
X *lpp = lp;
X return TRUE;
X }
X lp = lforw(lp);
X }
}
X
X
#else
taghello() { }
#endif
SHAR_EOF
chmod 0444 tags.c ||
echo 'restore of tags.c failed'
Wc_c="`wc -c < 'tags.c'`"
test 7806 -eq "$Wc_c" ||
echo 'tags.c: original size 7806, current size' "$Wc_c"
# ============= tcap.c ==============
echo 'x - extracting tcap.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'tcap.c' &&
/* tcap: Unix V5, V7 and BS4.2 Termcap video driver
X for MicroEMACS
*/
X
#define termdef 1 /* don't define "term" external */
X
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
#include <signal.h>
X
#if TERMCAP
X
#define MARGIN 8
#define SCRSIZ 64
#define NPAUSE 10 /* # times thru update to pause */
#define BEL 0x07
#define ESC 0x1B
X
extern int ttopen();
extern int ttgetc();
extern int ttputc();
extern int tgetnum();
extern int ttflush();
extern int ttclose();
extern int tcapkopen();
extern int tcapkclose();
extern int tcapmove();
extern int tcapeeol();
extern int tcapeeop();
extern int tcapbeep();
extern int tcaprev();
extern int tcapcres();
extern int tcapopen();
extern int tput();
extern char *tgoto();
#if COLOR
extern int tcapfcol();
extern int tcapbcol();
#endif
#if SCROLLCODE
extern int tcapscroll_reg();
extern int tcapscroll_delins();
#endif
X
#define TCAPSLEN 315
char tcapbuf[TCAPSLEN];
char *UP, PC, *CM, *CE, *CL, *SO, *SE;
X
#if SCROLLCODE
char *CS, *DL, *AL, *SF, *SR;
#endif
X
TERM term = {
X NULL, /* these four values are set dynamically at open time */
X NULL,
X NULL,
X NULL,
X MARGIN,
X SCRSIZ,
X NPAUSE,
X tcapopen,
X ttclose,
X tcapkopen,
X tcapkclose,
X ttgetc,
X ttputc,
X ttflush,
X tcapmove,
X tcapeeol,
X tcapeeop,
X tcapbeep,
X tcaprev,
X tcapcres
#if COLOR
X , tcapfcol,
X tcapbcol
#endif
#if SCROLLCODE
X , NULL /* set dynamically at open time */
#endif
};
X
tcapopen()
{
X char *getenv();
X char *t, *p, *tgetstr();
X char tcbuf[1024];
X char *tv_stype;
X char err_str[72];
X
X if ((tv_stype = getenv("TERM")) == NULL)
X {
X puts("Environment variable TERM not defined!");
X exit(1);
X }
X
X if ((tgetent(tcbuf, tv_stype)) != 1)
X {
X sprintf(err_str, "Unknown terminal type %s!", tv_stype);
X puts(err_str);
X exit(1);
X }
X
X /* Get screen size from system, or else from termcap. */
X getscreensize(&term.t_ncol, &term.t_nrow);
X
X if ((term.t_nrow <= 0) && (term.t_nrow=(short)tgetnum("li")) == -1) {
X puts("termcap entry incomplete (lines)");
X exit(1);
X }
X term.t_nrow -= 1;
X
X
X if ((term.t_ncol <= 0) &&(term.t_ncol=(short)tgetnum("co")) == -1){
X puts("Termcap entry incomplete (columns)");
X exit(1);
X }
X
#ifdef SIGWINCH
X term.t_mrow = 200;
X term.t_mcol = 200;
#else
X term.t_mrow = term.t_nrow;
X term.t_mcol = term.t_ncol;
#endif
X p = tcapbuf;
X t = tgetstr("pc", &p);
X if(t)
X PC = *t;
X
X CL = tgetstr("cl", &p);
X CM = tgetstr("cm", &p);
X CE = tgetstr("ce", &p);
X UP = tgetstr("up", &p);
X SE = tgetstr("se", &p);
X SO = tgetstr("so", &p);
X if (SO != NULL)
X revexist = TRUE;
X
X if(CL == NULL || CM == NULL || UP == NULL)
X {
X puts("Incomplete termcap entry\n");
X exit(1);
X }
X
X if (CE == NULL) /* will we be able to use clear to EOL? */
X eolexist = FALSE;
#if SCROLLCODE
X CS = tgetstr("cs", &p);
X SF = tgetstr("sf", &p);
X SR = tgetstr("sr", &p);
X DL = tgetstr("dl", &p);
X AL = tgetstr("al", &p);
X
X if (CS && SR) {
X if (SF == NULL) /* assume '\n' scrolls forward */
X SF = "\n";
X term.t_scroll = tcapscroll_reg;
X } else if (DL && AL) {
X term.t_scroll = tcapscroll_delins;
X } else {
X term.t_scroll = NULL;
X }
#endif
X
X if (p >= &tcapbuf[TCAPSLEN])
X {
X puts("Terminal description too big!\n");
X exit(1);
X }
X ttopen();
}
X
tcapkopen()
{
X strcpy(sres, "NORMAL");
}
X
tcapkclose()
{
}
X
tcapmove(row, col)
register int row, col;
{
X putpad(tgoto(CM, col, row));
}
X
tcapeeol()
{
X putpad(CE);
}
X
tcapeeop()
{
X putpad(CL);
}
X
tcaprev(state) /* change reverse video status */
int state; /* FALSE = normal video, TRUE = reverse video */
{
X static int revstate = -1;
X if (state == revstate)
X return;
X revstate = state;
X if (state) {
X if (SO != NULL)
X putpad(SO);
X } else {
X if (SE != NULL)
X putpad(SE);
X }
}
X
tcapcres() /* change screen resolution */
{
X return(TRUE);
}
X
#if SCROLLCODE
X
/* move howmany lines starting at from to to */
tcapscroll_reg(from,to,howmany)
{
X int i;
X if (to == from) return;
X if (to < from) {
X tcapscrollregion(to, from + howmany - 1);
X tcapmove(from + howmany - 1,0);
X for (i = from - to; i > 0; i--)
X putpad(SF);
X } else { /* from < to */
X tcapscrollregion(from, to + howmany - 1);
X tcapmove(from,0);
X for (i = to - from; i > 0; i--)
X putpad(SR);
X }
X tcapscrollregion(0, term.t_nrow);
}
X
/*
PRETTIER_SCROLL is prettier but slower -- it scrolls
X a line at a time instead of all at once.
*/
X
/* move howmany lines starting at from to to */
tcapscroll_delins(from,to,howmany)
{
X int i;
X if (to == from) return;
#if PRETTIER_SCROLL
X if (abs(from-to) > 1) {
X tcapscroll_delins(from, (from<to) ? to-1:to+1, howmany);
X if (from < to)
X from = to-1;
X else
X from = to+1;
X }
#endif
X if (to < from) {
X tcapmove(to,0);
X for (i = from - to; i > 0; i--)
X putpad(DL);
X tcapmove(to+howmany,0);
X for (i = from - to; i > 0; i--)
X putpad(AL);
X } else {
X tcapmove(from+howmany,0);
X for (i = to - from; i > 0; i--)
X putpad(DL);
X tcapmove(from,0);
X for (i = to - from; i > 0; i--)
X putpad(AL);
X }
}
X
/* cs is set up just like cm, so we use tgoto... */
tcapscrollregion(top,bot)
{
X putpad(tgoto(CS, bot, top));
}
X
#endif
X
spal(dummy) /* change palette string */
{
X /* Does nothing here */
}
X
#if COLOR
tcapfcol() /* no colors here, ignore this */
{
}
X
tcapbcol() /* no colors here, ignore this */
{
}
#endif
X
tcapbeep()
{
X ttputc(BEL);
}
X
putpad(str)
char *str;
{
X tputs(str, 1, ttputc);
}
X
putnpad(str, n)
char *str;
{
X tputs(str, n, ttputc);
}
X
X
#if FLABEL
fnclabel(f, n) /* label a function key */
int f,n; /* default flag, numeric argument [unused] */
{
X /* on machines with no function keys...don't bother */
X return(TRUE);
}
#endif
#else
X
hello()
{
}
X
#endif
SHAR_EOF
chmod 0444 tcap.c ||
echo 'restore of tcap.c failed'
Wc_c="`wc -c < 'tcap.c'`"
test 6065 -eq "$Wc_c" ||
echo 'tcap.c: original size 6065, current size' "$Wc_c"
# ============= termio.c ==============
echo 'x - extracting termio.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'termio.c' &&
/*
X * The functions in this file negotiate with the operating system for
X * characters, and write characters in a barely buffered fashion on the display.
X * All operating systems.
X */
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
X
#if MSDOS & TURBO
#include <conio.h>
#endif
X
#if AMIGA
#define NEW 1006L
#define AMG_MAXBUF 1024L
static long terminal;
static char scrn_tmp[AMG_MAXBUF+1];
static long scrn_tmp_p = 0;
#endif
X
#if ST520 & MEGAMAX
#include <osbind.h>
X int STscancode = 0;
#endif
X
#if VMS
#include <stsdef.h>
#include <ssdef.h>
#include <descrip.h>
#include <iodef.h>
#include <ttdef.h>
#include <tt2def.h>
X
#define NIBUF 128 /* Input buffer size */
#define NOBUF 1024 /* MM says bug buffers win! */
#define EFN 0 /* Event flag */
X
char obuf[NOBUF]; /* Output buffer */
int nobuf; /* # of bytes in above */
char ibuf[NIBUF]; /* Input buffer */
int nibuf; /* # of bytes in above */
int ibufi; /* Read index */
int oldmode[3]; /* Old TTY mode bits */
int newmode[3]; /* New TTY mode bits */
short iochan; /* TTY I/O channel */
#endif
X
#if CPM
#include <bdos.h>
#endif
X
#if MSDOS & (LATTICE | MSC | TURBO | AZTEC | MWC86)
union REGS rg; /* cpu register for use of DOS calls */
int nxtchar = -1; /* character held from type ahead */
#endif
X
#if RAINBOW
#include "rainbow.h"
#endif
X
#if USG /* System V */
#include <signal.h>
#include <termio.h>
#include <fcntl.h>
int kbdflgs; /* saved keyboard fd flags */
int kbdpoll; /* in O_NDELAY mode */
int kbdqp; /* there is a char in kbdq */
char kbdq; /* char we've already read */
struct termio otermio; /* original terminal characteristics */
struct termio ntermio; /* charactoristics to use inside */
#endif
X
#if V7 | BSD
#undef CTRL
#include <sgtty.h> /* for stty/gtty functions */
#include <signal.h>
struct sgttyb ostate; /* saved tty state */
struct sgttyb nstate; /* values for editor mode */
struct sgttyb rnstate; /* values for raw editor mode */
int olstate; /* Saved local mode values */
int nlstate; /* new local mode values */
struct ltchars oltchars; /* Saved terminal special character set */
struct ltchars nltchars = { -1, -1, -1, -1, -1, -1 }; /* a lot of nothing */
struct tchars otchars; /* Saved terminal special character set */
struct tchars ntchars; /* = { -1, -1, -1, -1, -1, -1 }; */
#if BSD
#include <sys/ioctl.h> /* to get at the typeahead */
#define TBUFSIZ 128
char tobuf[TBUFSIZ]; /* terminal output buffer */
#endif
#endif
X
#if ULTRIX
#include <sys/termios.h>
#endif
X
extern CMDFUNC f_backchar;
X
/*
X * This function is called once to set up the terminal device streams.
X * On VMS, it translates TT until it finds the terminal, then assigns
X * a channel to it and sets it raw. On CPM it is a no-op.
X */
ttopen()
{
#if AMIGA
X char oline[NSTRING];
#if AZTEC
X extern Enable_Abort; /* Turn off ctrl-C interrupt */
X
X Enable_Abort = 0; /* for the Manx compiler */
#endif
X strcpy(oline, "RAW:0/0/640/200/");
X strcat(oline, PROGNAME);
X strcat(oline, " ");
X strcat(oline, VERSION);
X strcat(oline, "/Amiga");
X terminal = Open(oline, NEW);
#endif
#if VMS
X struct dsc$descriptor idsc;
X struct dsc$descriptor odsc;
X char oname[40];
X int iosb[2];
X int status;
X
X odsc.dsc$a_pointer = "TT";
X odsc.dsc$w_length = strlen(odsc.dsc$a_pointer);
X odsc.dsc$b_dtype = DSC$K_DTYPE_T;
X odsc.dsc$b_class = DSC$K_CLASS_S;
X idsc.dsc$b_dtype = DSC$K_DTYPE_T;
X idsc.dsc$b_class = DSC$K_CLASS_S;
X do {
X idsc.dsc$a_pointer = odsc.dsc$a_pointer;
X idsc.dsc$w_length = odsc.dsc$w_length;
X odsc.dsc$a_pointer = &oname[0];
X odsc.dsc$w_length = sizeof(oname);
X status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
X if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
X exit(status);
X if (oname[0] == 0x1B) {
X odsc.dsc$a_pointer += 4;
X odsc.dsc$w_length -= 4;
X }
X } while (status == SS$_NORMAL);
X status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
X if (status != SS$_NORMAL)
X exit(status);
X status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
X oldmode, sizeof(oldmode), 0, 0, 0, 0);
X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X exit(status);
X newmode[0] = oldmode[0];
X newmode[1] = oldmode[1] | TT$M_NOECHO;
X newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
X newmode[2] = oldmode[2] | TT2$M_PASTHRU;
X status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
X newmode, sizeof(newmode), 0, 0, 0, 0);
X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X exit(status);
X term.t_nrow = (newmode[1]>>24) - 1;
X term.t_ncol = newmode[0]>>16;
X
#endif
#if CPM
#endif
X
#if MSDOS & (HP150 == 0) & LATTICE
X /* kill the ctrl-break interupt */
X rg.h.ah = 0x33; /* control-break check dos call */
X rg.h.al = 1; /* set the current state */
X rg.h.dl = 0; /* set it OFF */
X intdos(&rg, &rg); /* go for it! */
#endif
X
#if USG
X ioctl(0, TCGETA, &otermio); /* save old settings */
X ntermio = otermio;
X /* setup new settings, preserve flow control, and allow BREAK */
X ntermio.c_iflag = BRKINT|(otermio.c_iflag & IXON|IXANY|IXOFF);
X ntermio.c_oflag = 0;
X ntermio.c_lflag = ISIG;
X ntermio.c_cc[VMIN] = 1;
X ntermio.c_cc[VTIME] = 0;
X ntermio.c_cc[VSWTCH] = -1;
#ifdef SIGTSTP /* suspension under sys5 -- is this a standard? */
#if POSIX /* ODT uses this... */
X ntermio.c_cc[VSUSP] = -1;
X ntermio.c_cc[VSTART] = -1;
X ntermio.c_cc[VSTOP] = -1;
#else
X ntermio.c_cc[V_SUSP] = -1;
X ntermio.c_cc[V_DSUSP] = -1;
#endif
#endif
X intrc = ntermio.c_cc[VINTR];
X killc = ntermio.c_cc[VKILL];
X backspc = ntermio.c_cc[VERASE];
X ioctl(0, TCSETA, &ntermio); /* and activate them */
X kbdflgs = fcntl( 0, F_GETFL, 0 );
X kbdpoll = FALSE;
#endif
X
#if V7 | BSD
X ioctl(0,TIOCGETP,&ostate); /* save old state */
X killc = ostate.sg_kill;
X backspc = ostate.sg_erase;
X
X nstate = ostate;
X nstate.sg_flags |= CBREAK;
X nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */
X ioctl(0,TIOCSETP,&nstate); /* set new state */
X
X rnstate = nstate;
X rnstate.sg_flags &= ~CBREAK;
X rnstate.sg_flags |= RAW;
X
X ioctl(0, TIOCGETC, &otchars); /* Save old characters */
X intrc = otchars.t_intrc;
X
X ntchars = otchars;
X ntchars.t_brkc = -1;
X ntchars.t_eofc = -1;
X ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */
X
X ioctl(0, TIOCGLTC, &oltchars); /* Save old characters */
X ioctl(0, TIOCSLTC, &nltchars); /* Place new character into K */
X
#if BSD
X ioctl(0, TIOCLGET, &olstate);
X nlstate = olstate;
X nlstate |= LLITOUT;
X ioctl(0, TIOCLSET, &nlstate);
X /* provide a smaller terminal output buffer so that
X the type ahead detection works better (more often) */
X setbuffer(stdout, &tobuf[0], TBUFSIZ);
X setbuf(stdin, NULL);
#endif
#endif
X
#if UNIX && defined(SIGTSTP)
X {
X extern int rtfrmshell(); /* return from suspended shell */
X signal(SIGTSTP,SIG_DFL); /* set signals so that we can */
X signal(SIGCONT,rtfrmshell); /* suspend & restart */
X signal(SIGTTOU,SIG_IGN); /* ignore output prevention */
X }
#endif
X /* make sure backspace is bound to backspace */
X asciitbl[backspc] = &f_backchar;
X
X /* make sure backspace is considered a backspace by the code */
X _chartypes_[backspc] |= _bspace;
X
X /* on all screens we are not sure of the initial position */
X /* of the cursor */
X ttrow = 999;
X ttcol = 999;
}
X
/*
X * This function gets called just before we go back home to the command
X * interpreter. On VMS it puts the terminal back in a reasonable state.
X * Another no-operation on CPM.
X */
ttclose()
{
#if AMIGA
#if LATTICE
X amg_flush();
X Close(terminal);
#endif
#if AZTEC
X amg_flush();
X Enable_Abort = 1; /* Fix for Manx */
X Close(terminal);
#endif
#endif
X
#if VMS
X int status;
X int iosb[1];
X
X ttflush();
X status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
X oldmode, sizeof(oldmode), 0, 0, 0, 0);
X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X exit(status);
X status = SYS$DASSGN(iochan);
X if (status != SS$_NORMAL)
X exit(status);
#endif
#if CPM
#endif
#if MSDOS & (HP150 == 0) & LATTICE
X /* restore the ctrl-break interupt */
X rg.h.ah = 0x33; /* control-break check dos call */
X rg.h.al = 1; /* set the current state */
X rg.h.dl = 1; /* set it ON */
X intdos(&rg, &rg); /* go for it! */
#endif
X
X ttclean(TRUE);
}
X
ttclean(f)
{
X if (f) {
X movecursor(term.t_nrow, ttcol); /* don't care about column */
X ttputc('\n');
X ttputc('\r');
X }
X TTflush();
#if UNIX
#if USG
X ioctl(0, TCSETAF, &otermio);
X fcntl(0, F_SETFL, kbdflgs);
#endif
#if V7 | BSD
X ioctl(0,TIOCSETP,&ostate);
X ioctl(0, TIOCSETC, &otchars);
X ioctl(0, TIOCSLTC, &oltchars);
#if BSD
X ioctl(0, TIOCLSET, &olstate);
#endif
#endif
#else
X TTclose();
X TTkclose();
#endif
}
X
ttunclean()
{
#if USG
X ioctl(0, TCSETAF, &ntermio);
#endif
#if V7 | BSD
X ioctl(0, TIOCSETP,&nstate);
X ioctl(0, TIOCSETC, &ntchars);
X ioctl(0, TIOCSLTC, &nltchars);
#if BSD
X ioctl(0, TIOCLSET, &nlstate);
#endif
#endif
}
X
/*
X * Write a character to the display. On VMS, terminal output is buffered, and
X * we just put the characters in the big array, after checking for overflow.
X * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
X * MS-DOS (use the very very raw console output routine).
X */
ttputc(c)
#if AMIGA | (ST520 & MEGAMAX)
X char c;
#endif
{
#if AMIGA
X scrn_tmp[scrn_tmp_p++] = c;
X if(scrn_tmp_p>=AMG_MAXBUF)
X amg_flush();
#endif
#if ST520 & MEGAMAX
X Bconout(2,c);
#endif
#if VMS
X if (nobuf >= NOBUF)
X ttflush();
X obuf[nobuf++] = c;
#endif
X
#if CPM
X bios(BCONOUT, c, 0);
#endif
X
#if MSDOS & MWC86
X putcnb(c);
#endif
X
#if MSDOS & (LATTICE | AZTEC) & ~IBMPC
X bdos(6, c, 0);
#endif
X
#if RAINBOW
X Put_Char(c); /* fast video */
#endif
X
X
#if V7 | USG | BSD
X fputc(c, stdout);
#endif
}
X
#if AMIGA
amg_flush()
{
X if(scrn_tmp_p)
X Write(terminal,scrn_tmp,scrn_tmp_p);
X scrn_tmp_p = 0;
}
#endif
X
/*
X * Flush terminal buffer. Does real work where the terminal output is buffered
X * up. A no-operation on systems where byte at a time terminal I/O is done.
X */
ttflush()
{
#if AMIGA
X amg_flush();
#endif
#if VMS
X int status;
X int iosb[2];
X
X status = SS$_NORMAL;
X if (nobuf != 0) {
X status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
X iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
X if (status == SS$_NORMAL)
X status = iosb[0] & 0xFFFF;
X nobuf = 0;
X }
X return (status);
#endif
X
#if CPM
#endif
X
#if MSDOS
#endif
X
#if V7 | USG | BSD
X fflush(stdout);
#endif
}
X
extern int tungotc;
X
/*
X * Read a character from the terminal, performing no editing and doing no echo
X * at all. More complex in VMS that almost anyplace else, which figures. Very
X * simple on CPM, because the system can do exactly what you want.
X */
ttgetc()
{
X int c;
#if AMIGA
X char ch;
X
X amg_flush();
X Read(terminal, &ch, 1L);
X return(255 & (int)ch);
#endif
#if ST520 & MEGAMAX
X long ch;
X
/*
X * blink the cursor only if nothing is happening, this keeps the
X * cursor on steadily during movement making it easier to track
X */
X STcurblink(TRUE); /* the cursor blinks while we wait */
X ch = Bconin(2);
X STcurblink(FALSE); /* the cursor is steady while we work */
X STscancode = (ch >> 16) & 0xff;
X return(255 & (int)ch);
#endif
#if VMS
X int status;
X int iosb[2];
X int term[2];
X
X while (ibufi >= nibuf) {
X ibufi = 0;
X term[0] = 0;
X term[1] = 0;
X status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
X iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
X if (status != SS$_NORMAL)
X exit(status);
X status = iosb[0] & 0xFFFF;
X if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
X exit(status);
X nibuf = (iosb[0]>>16) + (iosb[1]>>16);
X if (nibuf == 0) {
X status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
X iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
X if (status != SS$_NORMAL
X || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
X exit(status);
X nibuf = (iosb[0]>>16) + (iosb[1]>>16);
X }
X }
X return (ibuf[ibufi++] & 0xFF); /* Allow multinational */
#endif
X
#if CPM
X return (biosb(BCONIN, 0, 0));
#endif
X
#if RAINBOW
X
X while ((c = Read_Keyboard()) < 0);
X
X if ((c & Function_Key) == 0)
X if (!((c & 0xFF) == 015 || (c & 0xFF) == 0177))
X c &= 0xFF;
X
X return c;
#endif
X
#if MSDOS & MWC86
X return (getcnb());
#endif
X
#if MSDOS & (LATTICE | MSC | TURBO | AZTEC)
X
X /* if a char already is ready, return it */
X if (nxtchar >= 0) {
X c = nxtchar;
X nxtchar = -1;
X return(c);
X }
X
X /* call the dos to get a char */
X rg.h.ah = 7; /* dos Direct Console Input call */
X intdos(&rg, &rg);
X c = rg.h.al; /* grab the char */
X return(c & 0xff);
#endif
X
#if V7 | BSD
X /*stty(0, &rnstate); /* set raw mode */
X c = fgetc(stdin);
X if (c == -1)
X /* this doesn't work -- read doesn't return on interrupt */
X c = kcod2key(intrc);
X else
X c &= 0x7f;
X /*stty(0, &nstate); /* set mode */
X return c;
#endif
X
#if USG
X if( kbdqp ) {
X kbdqp = FALSE;
X } else {
X if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
X return FALSE; /* what ?? i don't understand -- pgf */
X kbdpoll = FALSE;
X if (read(0, &kbdq, 1) < 0) {
X return -1;
X }
X }
X return ( kbdq & 0x7f );
#endif
}
X
X
#if NeWS
/* typahead: Check to see if any characters are already in the
X keyboard buffer
*/
typahead()
{
X return(inhibit_update) ;
}
#endif
X
#if TYPEAH & (~ST520 | ~LATTICE ) & ~NeWS
X
/* typahead: Check to see if any characters are already in the
X keyboard buffer
*/
typahead()
{
X long x;
X
#if MSDOS & (MSC | TURBO)
X if (tungotc > 0)
X return TRUE;
X
X if (kbhit() != 0)
X return(TRUE);
X else
X return(FALSE);
#endif
X
#if MSDOS & (LATTICE | AZTEC | MWC86)
X int c; /* character read */
X int flags; /* cpu flags from dos call */
X
X if (nxtchar >= 0)
X return(TRUE);
X
X if (tungotc > 0)
X return TRUE;
X
X
X rg.h.ah = 6; /* Direct Console I/O call */
X rg.h.dl = 255; /* does console input */
#if LATTICE | AZTEC
X flags = intdos(&rg, &rg);
#else
X intcall(&rg, &rg, 0x21);
X flags = rg.x.flags;
#endif
X c = rg.h.al; /* grab the character */
X
X /* no character pending */
X if ((flags & 0x40) != 0)
X return(FALSE);
X
X /* save the character and return true */
X nxtchar = c;
X return(TRUE);
#endif
X
#if BSD
X if (tungotc > 0)
X return TRUE;
X
X return((ioctl(0,FIONREAD,&x) < 0) ? 0 : (int)x);
#endif
X
#if USG
X if (tungotc > 0)
X return TRUE;
X
X if( !kbdqp )
X {
X if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
X return(FALSE);
X kbdpoll = TRUE; /* I think */
X kbdqp = (1 == read( 0, &kbdq, 1 ));
X }
X return ( kbdqp );
#endif
X
}
#endif
X
SHAR_EOF
chmod 0444 termio.c ||
echo 'restore of termio.c failed'
Wc_c="`wc -c < 'termio.c'`"
test 16097 -eq "$Wc_c" ||
echo 'termio.c: original size 16097, current size' "$Wc_c"
# ============= tipc.c ==============
echo 'x - extracting tipc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'tipc.c' &&
/*
X * The routines in this file provide support for the TI-PC and other
X * compatible terminals. It goes directly to the graphics RAM to do
X * screen output. It compiles into nothing if not a TI-PC driver
X */
X
#define termdef 1 /* don't define "term" external */
X
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
X
#if TIPC
X
#define NROW 25 /* Screen size. */
#define NCOL 80 /* Edit if you want to. */
#define MARGIN 8 /* size of minimim margin and */
#define SCRSIZ 64 /* scroll size for extended lines */
#define NPAUSE 200 /* # times thru update to pause */
#define BEL 0x07 /* BEL character. */
#define ESC 0x1B /* ESC character. */
#define SPACE 32 /* space character */
#define SCADD 0xDE000L /* address of screen RAM */
X
#define CHAR_ENABLE 0x08 /* TI attribute to show char */
#define TI_REVERSE 0x10 /* TI attribute to reverse char */
#define BLACK 0+CHAR_ENABLE /* TI attribute for Black */
#define BLUE 1+CHAR_ENABLE /* TI attribute for Blue */
#define RED 2+CHAR_ENABLE /* TI attribute for Red */
#define MAGENTA 3+CHAR_ENABLE /* TI attribute for Magenta */
#define GREEN 4+CHAR_ENABLE /* TI attribute for Green */
#define CYAN 5+CHAR_ENABLE /* TI attribute for Cyan */
#define YELLOW 6+CHAR_ENABLE /* TI attribute for Yellow */
#define WHITE 7+CHAR_ENABLE /* TI attribute for White */
X
X
extern int ttopen(); /* Forward references. */
extern int ttgetc();
extern int ttputc();
extern int ttflush();
extern int ttclose();
extern int timove();
extern int tieeol();
extern int tieeop();
extern int tibeep();
extern int tiopen();
extern int tirev();
extern int ticres();
extern int ticlose();
extern int tiputc();
X
#if COLOR
extern int tifcol();
extern int tibcol();
X
int cfcolor = -1; /* current forground color */
int cbcolor = -1; /* current background color */
int ctrans[] = /* ansi to ti color translation table */
X {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE};
#endif
X
/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
TERM term = {
X NROW-1,
X NROW-1,
X NCOL,
X NCOL,
X MARGIN,
X SCRSIZ,
X NPAUSE,
X tiopen,
X ticlose,
X ttgetc,
X tiputc,
X ttflush,
X timove,
X tieeol,
X tieeop,
X tibeep,
X tirev,
X ticres
#if COLOR
X , tifcol,
X tibcol
#endif
};
X
extern union REGS rg;
X
#if COLOR
setatt( attr )
int attr;
{
X rg.h.ah = 0x16; /* set the forground character attribute */
X rg.h.bl = attr;
X int86( 0x49, &rg, &rg );
}
X
tifcol(color) /* set the current output color */
X
int color; /* color to set */
X
{
X cfcolor = ctrans[color];
X setatt ( cfcolor );
}
X
tibcol(color) /* set the current background color */
X
int color; /* color to set */
X
{
X cbcolor = ctrans[color];
}
#endif
X
timove(row, col)
{
X rg.h.ah = 2; /* set cursor position function code */
X rg.h.dh = col;
X rg.h.dl = row;
X int86(0x49, &rg, &rg);
}
X
tieeol() /* erase to the end of the line */
X
{
X int ccol; /* current column cursor lives */
X int crow; /* row */
X
X /* find the current cursor position */
X rg.h.ah = 3; /* read cursor position function code */
X int86(0x49, &rg, &rg);
X ccol = rg.h.dh; /* record current column */
X crow = rg.h.dl; /* and row */
X
X rg.h.ah = 0x09; /* Write character at cursor position */
X rg.h.al = ' '; /* Space */
X rg.h.bl = cfcolor;
X rg.x.cx = NCOL-ccol; /* Number of characters to write */
X int86(0x49, &rg, &rg);
X
}
X
tiputc(ch) /* put a character at the current position in the
X current colors */
X
int ch;
X
{
X rg.h.ah = 0x0E; /* write char to screen with current attrs */
X rg.h.al = ch;
X int86(0x49, &rg, &rg);
}
X
tieeop() /* Actually a clear screen */
{
X
X rg.h.ah = 0x13; /* Clear Text Screen and Home Cursor */
X int86(0x49, &rg, &rg);
}
X
tirev(state) /* change reverse video state */
X
int state; /* TRUE = reverse, FALSE = normal */
X
{
X setatt( state ? cbcolor : cfcolor );
}
X
ticres() /* change screen resolution */
X
{
X return(TRUE);
}
X
spal() /* change palette string */
X
{
X /* Does nothing here */
}
X
tibeep()
{
X bdos(6, BEL, 0);
}
X
tiopen()
{
X strcpy(sres, "NORMAL");
X revexist = TRUE;
X ttopen();
}
X
ticlose()
X
{
#if COLOR
X tifcol(7);
X tibcol(0);
#endif
X ttclose();
}
#else
tihello()
{
}
#endif
X
SHAR_EOF
chmod 0444 tipc.c ||
echo 'restore of tipc.c failed'
Wc_c="`wc -c < 'tipc.c'`"
test 5308 -eq "$Wc_c" ||
echo 'tipc.c: original size 5308, current size' "$Wc_c"
# ============= undo.c ==============
echo 'x - extracting undo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'undo.c' &&
X
/* these routines take care of undo operations */
/* code by Paul Fox, original algorithm mostly by Julia Harper May, 89 */
X
#include "estruct.h"
#include "edef.h"
X
#ifndef NULL
#define NULL 0
#endif
X
X
/* the undo strategy is this:
X 1) For any deleted line, push it onto the undo list.
X 2) On any change to a line, make a copy of it, push the copy to
X the undo list, and mark the original as having been copied.
X Do not copy/push lines that are marked as having been copied.
X Push a tag matching up the copy with the original. Later,
X when the copy has been put into the file, we can
X go back through the undo stack, find lines there pointing
X at the original, and make them point at the copy. ugh.
X This wouldn't be necessary if we used line no's as the pointers,
X instead of real pointers.
X
X On the actual undo, we pop these things one by one. There should
X either be no lines where it goes (it was deleted), or exactly
X one line where it goes (it was changed/copied). That makes it
X easy to undo the changes one by one. Of course, we need to build
X a different, inverse stack as we go, so that undo can be undone.
X
X The "copied" flag in the LINE structure is unioned with the stack
X link pointer on the undo stack, since they aren't both needed at once.
X
*/
X
X
#define CURSTK(bp) (&(bp->b_udstks[bp->b_udstkindx]))
#define ALTSTK(bp) (&(bp->b_udstks[1^(bp->b_udstkindx)]))
#define CURDOTP(bp) (bp->b_uddotps[bp->b_udstkindx])
#define ALTDOTP(bp) (bp->b_uddotps[1^(bp->b_udstkindx)])
#define CURDOTO(bp) (bp->b_uddotos[bp->b_udstkindx])
#define ALTDOTO(bp) (bp->b_uddotos[1^(bp->b_udstkindx)])
#define SWITCHSTKS(bp) (bp->b_udstkindx = 1 ^ bp->b_udstkindx)
X
short needundocleanup;
LINE *copyline();
X
/* push the line onto the right undo stack. */
toss_to_undo(lp)
LINE *lp;
{
X if (needundocleanup)
X preundocleanup();
X pushline(lp,CURSTK(curbp));
X if ((ALTDOTP(curbp) == NULL) || (ALTDOTP(curbp) == lp)) {
X /* need to save a dot -- either the next line or
X the previous one */
X if (lp->l_fp == curbp->b_linep) {
X ALTDOTP(curbp) = lp->l_bp;
X ALTDOTO(curbp) = firstchar(lp->l_bp);
X } else {
X ALTDOTP(curbp) = lp->l_fp;
X ALTDOTO(curbp) = firstchar(lp->l_fp);
X }
X }
X dumpuline(lp);
}
X
/* push a copy of a line onto the right undo stack */
/* push a patch so we can later fix up any references to this line that */
/* might already be in the stack. */
/* This unforutunate breach of stak protocol is because we'd rather push the */
/* _copy_ than the origianal. When the undo happens, the later pops will */
/* point at the _original_ (which will by then be on the other undo stack) */
/* unless we fix them now. */
copy_for_undo(lp)
LINE *lp;
{
X register LINE *nlp;
X
X if (needundocleanup)
X preundocleanup();
X
X if (liscopied(lp))
X return(TRUE);
X
X /* take care of the normal undo stack */
X nlp = copyline(lp);
X if (nlp == NULL)
X return(FALSE);
X pushline(nlp,CURSTK(curbp));
X
X make_undo_patch(lp,nlp,LINEUNDOPATCH);
X
X lsetcopied(lp);
X
X setupuline(lp);
X
X if (ALTDOTP(curbp) == NULL) {
X ALTDOTP(curbp) = lp;
X ALTDOTO(curbp) = curwp->w_doto;
X }
X return (TRUE);
}
X
/* push an unreal line onto the right undo stack */
/* lp should be the new line, _after_ insertion, so l_fp and l_bp are right */
tag_for_undo(lp)
LINE *lp;
{
X register LINE *nlp;
X
X if (needundocleanup)
X preundocleanup();
X
X if (liscopied(lp))
X return(TRUE);
X
X nlp = lalloc(-1);
X if (nlp == NULL)
X return(FALSE);
X llength(nlp) = LINENOTREAL;
X nlp->l_fp = lp->l_fp;
X nlp->l_bp = lp->l_bp;
X pushline(nlp,CURSTK(curbp));
X lsetcopied(lp);
X if (ALTDOTP(curbp) == NULL) {
X ALTDOTP(curbp) = lp;
X ALTDOTO(curbp) = curwp->w_doto;
X }
X return (TRUE);
}
X
pushline(lp,stk)
LINE *lp,**stk;
{
X lp->l_nxtundo = *stk;
X *stk = lp;
}
X
LINE *
popline(stk)
LINE **stk;
{
X LINE *lp;
X lp = *stk;
X if (lp != NULL) {
X *stk = lp->l_nxtundo;
X lp->l_nxtundo = NULL;
X }
X return (lp);
}
X
make_undo_patch(olp,nlp,type)
LINE *olp,*nlp;
{
X register LINE *plp;
X /* push on a tag that matches up the copy with the original */
X plp = lalloc(-1);
X if (plp == NULL)
X return(FALSE);
X llength(plp) = type;
X plp->l_fp = olp; /* l_fp is the original line */
X plp->l_bp = nlp; /* l_bp is the copy */
X pushline(plp,CURSTK(curbp));
}
X
patchstk(newlp,oldlp)
LINE *newlp, *oldlp;
{
X register LINE *tlp;
X for (tlp = *CURSTK(curbp); tlp != NULL ; tlp = tlp->l_nxtundo) {
X if (!lispatch(tlp)) {
X if (tlp->l_fp == oldlp)
X tlp->l_fp = newlp;
X if (tlp->l_bp == oldlp)
X tlp->l_bp = newlp;
X }
X }
}
X
LINE *
copyline(lp)
register LINE *lp;
{
X int i;
X register LINE *nlp;
X
X nlp = lalloc(lp->l_used);
X if (nlp == NULL)
X return(NULL);
X /* copy the text and forward and back pointers. everything else
X matches already */
X nlp->l_fp = lp->l_fp;
X nlp->l_bp = lp->l_bp;
X /* copy the rest */
X memcpy(nlp->l_text, lp->l_text, llength(lp));
X return nlp;
}
X
X
/* before any undoable command (except undo itself), clean the undo list */
/* clean the copied flag on the line we're the copy of */
freeundostacks(bp)
register BUFFER *bp;
{
X register LINE *lp;
X int i;
X
X for (i = 0; i <= 1; i++, SWITCHSTKS(bp)) {
X while ((lp = popline(CURSTK(bp))) != NULL) {
X lfree(lp);
X }
X }
X
X /* clear the flags in the buffer */
X /* there may be a way to clean these less drastically, by
X using the information on the stacks above, but I
X couldn't figure it out. -pgf */
X lp = lforw(bp->b_linep);
X while (lp != bp->b_linep) {
X lsetnotcopied(lp);
X lp = lforw(lp);
X }
X
}
X
undo(f,n)
{
X LINE *lp, *alp;
X int nopops = TRUE;
X
X if (curbp->b_mode & MDVIEW)
X return(rdonly());
X
X while ((lp = popline(CURSTK(curbp))) != NULL) {
X nopops = FALSE;
#if NEWUNDO
X if (lismarkpatch(lp)) {
X register LINE *tlp;
X resetuline(lp->l_bp,lp->l_fp);
X tlp = lp->l_fp;
X lp->l_fp = lp->l_bp;
X lp->l_bp = tlp;
X pushline(lp,ALTSTK(curbp));
X continue;
X }
#endif
X if (lislinepatch(lp)) {
X patchstk(lp->l_bp, lp->l_fp);
X lfree(lp);
X continue;
X }
X lchange(WFHARD|WFINS|WFKILLS);
X if (lp->l_bp->l_fp != lp->l_fp) { /* theres something there */
X if (lp->l_bp->l_fp->l_fp == lp->l_fp) {
X /* then there is exactly one line there */
X /* alp is the line to remove */
X /* lp is the line we're putting in */
X alp = lp->l_bp->l_fp;
X repointstuff(lp,alp);
X /* remove it */
X lp->l_bp->l_fp = alp->l_fp;
X alp->l_fp->l_bp = alp->l_bp;
X } else { /* there is more than one line there */
X mlwrite("Bug! no stacked line for an insert");
X /* cleanup ? naw, a bugs a bug */
X return(FALSE);
X }
X } else { /* there is no line where we're going */
X /* create an "unreal" tag line to push */
X alp = lalloc(-1);
X if (alp == NULL)
X return(FALSE);
X llength(alp) = LINENOTREAL;
X alp->l_fp = lp->l_fp;
X alp->l_bp = lp->l_bp;
X }
X
X /* insert real lines into the buffer
X throw away the markers */
X if (lisreal(lp)) {
X lp->l_bp->l_fp = lp;
X lp->l_fp->l_bp = lp;
X } else {
X lfree(lp);
X }
X
X pushline(alp,ALTSTK(curbp));
X }
X
X if (nopops) {
X TTbeep();
X return (FALSE);
X }
X
X
X curwp->w_dotp = CURDOTP(curbp);
X curwp->w_doto = CURDOTO(curbp);
X if (curwp->w_doto >= llength(curwp->w_dotp))
X curwp->w_doto = llength(curwp->w_dotp) - 1;
X else if (curwp->w_doto < firstchar(curwp->w_dotp))
X curwp->w_doto = firstchar(curwp->w_dotp);
X
X SWITCHSTKS(curbp);
X
X vverify("undo");
X
X return TRUE;
}
X
mayneedundo()
{
X needundocleanup = TRUE;
}
X
preundocleanup()
{
X freeundostacks(curbp);
X CURDOTP(curbp) = curwp->w_dotp;
X CURDOTO(curbp) = curwp->w_doto;
X ALTDOTP(curbp) = NULL;
X ALTDOTO(curbp) = curwp->w_doto;
X needundocleanup = FALSE;
}
X
lineundo(f,n)
{
X register LINE *ulp; /* the Undo line */
X register LINE *lp; /* the line we may replace */
X register WINDOW *wp;
X register char *ntext;
X
X ulp = curbp->b_ulinep;
X if (ulp == NULL) {
X TTbeep();
X return FALSE;
X }
X
X lp = ulp->l_nxtundo;
X
X if (ulp->l_fp != lp->l_fp ||
X ulp->l_bp != lp->l_bp) {
X /* then the change affected more than one line */
X dumpuline(ulp);
X return FALSE;
X }
X
X /* avoid losing our undo stacks needlessly */
X if (linesmatch(ulp,lp) == TRUE)
X return TRUE;
X
X curwp->w_dotp = lp;
X preundocleanup();
X
X
X ntext = malloc(ulp->l_size);
X if (ntext == NULL)
X return (FALSE);
X
X copy_for_undo(lp);
X
X memcpy(ntext, ulp->l_text, llength(ulp));
X free(lp->l_text);
X lp->l_text = ntext;
X lp->l_used = ulp->l_used;
X lp->l_size = ulp->l_size;
X
X /* let's be defensive about this */
X wp = wheadp;
X while (wp != NULL) {
X if (wp->w_dotp == lp)
X wp->w_doto = 0;
X if (wp->w_mkp == lp)
X wp->w_mko = 0;
X if (wp->w_ldmkp == lp)
X wp->w_ldmko = 0;
X wp = wp->w_wndp;
X }
X if (CURDOTP(curbp) == lp)
X CURDOTO(curbp) = 0;
X if (curbp->b_nmmarks != NULL) {
X /* fix the named marks */
X int i;
X struct MARK *mp;
X for (i = 0; i < 26; i++) {
X mp = &(curbp->b_nmmarks[i]);
X if (mp->markp == lp)
X mp->marko = 0;
X }
X }
X
X curwp->w_flag |= WFEDIT;
X
X vverify("lineundo");
X return TRUE;
X
}
X
repointstuff(nlp,olp)
register LINE *nlp,*olp;
{
X register WINDOW *wp;
X
X /* fix anything important that points to it */
X wp = wheadp;
X while (wp != NULL) {
X if (wp->w_linep == olp)
X if (lisreal(nlp)) {
X wp->w_linep = nlp;
X } else {
X wp->w_linep = olp->l_fp;
X }
X if (wp->w_mkp == olp) {
X if (lisreal(nlp)) {
X wp->w_mkp = nlp;
X } else {
X wp->w_mkp = olp->l_fp;
X }
X wp->w_mko = 0;
X }
X if (wp->w_ldmkp == olp) {
X if (lisreal(nlp)) {
X wp->w_ldmkp = nlp;
X } else {
X wp->w_ldmkp = olp->l_fp;
X }
X wp->w_ldmko = 0;
X }
X wp = wp->w_wndp;
X }
#if 0
no code for ALTDOTO, but this was ifdef'ed out before I put that in... pgf
X if (ALTDOTP(curbp) == olp) {
X if (lisreal(nlp)) {
X ALTDOTP(curbp) = nlp;
X } else {
X mlwrite("Bug: preundodot points at newly inserted line!");
X }
X }
#endif
X if (CURDOTP(curbp) == olp) {
X if (lisreal(nlp)) {
X CURDOTP(curbp) = nlp;
X } else {
X mlwrite("Bug: preundodot points at newly inserted line!");
X }
X }
X if (curbp->b_nmmarks != NULL) {
X /* fix the named marks */
X int i;
X struct MARK *mp;
X for (i = 0; i < 26; i++) {
X mp = &(curbp->b_nmmarks[i]);
X if (mp->markp == olp) {
X if (lisreal(nlp)) {
X mp->markp = nlp;
X mp->marko = 0;
X } else {
X mlwrite("Sorry, lost the mark.");
X }
X }
X }
X }
#if !NEWUNDO
X resetuline(olp,nlp);
#endif
}
X
linesmatch(lp1,lp2)
register LINE *lp1,*lp2;
{
X int i;
X if (llength(lp1) != llength(lp2))
X return FALSE;
X return !memcmp(lp1->l_text, lp2->l_text, llength(lp1));
}
X
dumpuline(lp)
LINE *lp;
{
X if ((curbp->b_ulinep != NULL) &&
X (curbp->b_ulinep->l_nxtundo == lp)) {
X lfree(curbp->b_ulinep);
X curbp->b_ulinep = NULL;
X }
}
X
setupuline(lp)
LINE *lp;
{
X /* take care of the U line */
X if ((curbp->b_ulinep == NULL) || (curbp->b_ulinep->l_nxtundo != lp)) {
X if (curbp->b_ulinep != NULL)
X lfree(curbp->b_ulinep);
X curbp->b_ulinep = copyline(lp);
X if (curbp->b_ulinep != NULL)
X curbp->b_ulinep->l_nxtundo = lp;
X }
}
X
resetuline(olp,nlp)
register LINE *olp,*nlp;
{
X if (curbp->b_ulinep != NULL && curbp->b_ulinep->l_nxtundo == olp) {
X if (lisreal(nlp)) {
X curbp->b_ulinep->l_nxtundo = nlp;
X } else {
X mlwrite("Bug: b_ulinep pointed at inserted line!");
X }
X }
}
X
firstchar(lp)
LINE *lp;
{
X int off = 0;
X while ( off != llength(lp) && isspace(lgetc(lp, off)) )
X off++;
X return off;
}
SHAR_EOF
chmod 0444 undo.c ||
echo 'restore of undo.c failed'
Wc_c="`wc -c < 'undo.c'`"
test 11158 -eq "$Wc_c" ||
echo 'undo.c: original size 11158, current size' "$Wc_c"
# ============= vile.hlp ==============
echo 'x - extracting vile.hlp (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vile.hlp' &&
X
Getting along with vile
-----------------------
X Use Ctrl-D and Ctrl-U to scroll through this help information.
X
X Type Ctrl-O to make this the only window on the screen.
X
X The only vile commands described herein are those not
X present in vi, or differing greatly from those in vi.
X There is a section at the bottom describing other differences
X between vile and vi.
X
X First, to leave vile, use any of the following:
X :q
X :quit
X :exit
X :wq (writes the file before quitting)
X :q! (quits without writing changes!)
X Q
X ZZ (will write all unwritten buffers)
X ^X-^C (don't know why. _They_ don't put in ":q" for _us_!)
X
X To get help (probably just this text), use any of:
X :h
X :help
X ^X-^H
X ^A-^H
X
General Remarks
---------------
X Vile holds text in "buffers". Usually, these correspond to a file
X that you are editing, but not always. For instance, a buffer
X might be used to display this help text, or to hold the output
X of a shell command that you have run. Buffers have names, and
X these usually match the names of the files they contain.
X
X Buffers are sometimes displayed in windows. A buffer may be
X displayed in more than one window at the same time. There is
X no such thing as a hidden window. All existing windows are on
X the screen. There may, however, be hidden buffers, which are not
X currently associated with any window.
X
X All yank/delete registers (the default unnamed register, the numbered
X registers ("1-"9) that hold line-deletes, and the named registers
X ("a-"z)) are global to the editor, and not attached to any single
X buffer. Thus you can delete text in one buffer and put it back in
X another.
X
X Undo operations are attached to a buffer, not a window. Thus if
X you have two windows to the same buffer, and make a change in one,
X you can undo it in the other.
X
Buffer manipulation commands:
-----------------------------
X _ Show a history list of the up to 9 most recently visited
X buffers. Follow this command with a digit to select that
X buffer, or simply repeat it ("__") as a synonym for "_1".
X Modified buffers are preceded by a '*' in the history list.
X There are many different ways to get the previous file:
X __
X _1
X 1_
X :p
X :e#
X ^^ (ctrl-^) (but many keyboards can't produce this)
X
X :e Edit a file. If the file is already in a buffer, that buffer
X will be recalled into the current window.
X
X :e! Re-edit a file. A different filename can be given, but the
X buffer name will not change to match it.
X
X ^X-e Edit the file whose pathname appears under the cursor. That
X is, if you are editing a makefile, you could edit one of the
X source files by placing the cursor at the start of its name
X and using this command.
X
X :n Go to the next buffer. "next" means least recently used.
X
X :rename Rename the current buffer. Prompts for a new name. Does
X not affect the filename associated with the buffer. Use ":f"
X to do that.
X This command is useful for renaming the "[Output]" buffer, if
X you wish to preserve its contents, but run a new command.
X
X :b Edit a buffer. Recalls the named buffer. Does not look for
X a file of that name. Will find "invisible" buffers.
X
X :ki Kill a buffer. Remove the buffer and its contents from the
X editor. Will ask if changes to the buffer should be discarded.
X Currently, a buffer that is being displayed cannot be killed.
X
X * Display a list of all buffers, or make that display go away
X if it's already present. Leave your finger on the key, and
X it's easy to create and destroy the list. The buffers are
X numbered; the numbers correspond to the history numbers
X shown and used by the '_' command, described above. (If
X the buffer number is greater than 9, then the "nn_" form of
X the '_' command must be used, since '_' will only accept a
SHAR_EOF
true || echo 'restore of vile.hlp failed'
echo 'End of Vile part 15'
echo 'File vile.hlp is continued in part 16'
echo 16 > _shar_seq_.tmp
exit 0
--
paul fox, pgf at cayman.com, (617)494-1999
Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
More information about the Alt.sources
mailing list