Path: utzoo!utgpu!cs.utexas.edu!usc!zaphod.mps.ohio-state.edu!think.com!cayman!pgf From: pgf@cayman.COM (Paul Fox) Newsgroups: alt.sources Subject: Vile 15/17 - vi feel-alike (multi-window) Message-ID: <4534@cayman.COM> Date: 7 Jun 91 22:10:19 GMT Organization: Cayman Systems Inc., Cambridge Ma Lines: 2328 Submitted-by: pgf@cayman.com Archive-name: Vile/part15 #!/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 #include "estruct.h" #include "edef.h" #include 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 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 #include "estruct.h" #include "edef.h" X #if MSDOS & TURBO #include #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 X int STscancode = 0; #endif X #if VMS #include #include #include #include #include #include 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 #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 #include #include 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 /* for stty/gtty functions */ #include 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 /* to get at the typeahead */ #define TBUFSIZ 128 char tobuf[TBUFSIZ]; /* terminal output buffer */ #endif #endif X #if ULTRIX #include #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 #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@cayman.com, (617)494-1999 Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139