home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-02-03 | 58.6 KB | 2,388 lines |
- Path: xanth!mcnc!gatech!mandrill!hal!ncoast!allbery
- From: BLARSON@ECLA.USC.EDU (Bob Larson)
- Newsgroups: comp.sources.misc
- Subject: v03i027: mg 2a part 3 of 15
- Message-ID: <12401299340.47.BLARSON@ECLA.USC.EDU>
- Date: 26 May 88 04:51:52 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: BLARSON@ECLA.USC.EDU (Bob Larson)
- Lines: 2376
- Approved: allbery@ncoast.UUCP
-
- comp.sources.misc: Volume 3, Issue 27
- Submitted-By: "Bob Larson" <BLARSON@ECLA.USC.EDU>
- Archive-Name: mg2a/Part3
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- #----cut here-----cut here-----cut here-----cut here----#
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # dired.c
- # display.c
- # extend.c
- # file.c
- # This archive created: Sun May 22 02:23:34 1988
- # By: blarson
- cat << \SHAR_EOF > dired.c
- /* dired module for mg 2a */
- /* by Robert A. Larson */
-
- #include "def.h"
-
- #ifndef NO_DIRED
-
- BUFFER *dired_();
-
- /*ARGSUSED*/
- dired(f, n)
- int f, n;
- {
- char dirname[NFILEN];
- BUFFER *bp;
-
- dirname[0] = '\0';
- if(eread("Dired: ", dirname, NFILEN, EFNEW | EFCR) == ABORT)
- return ABORT;
- if((bp = dired_(dirname)) == NULL) return FALSE;
- curbp = bp;
- return showbuffer(bp, curwp, WFHARD | WFMODE);
- }
-
- /*ARGSUSED*/
- d_otherwindow(f, n)
- int f, n;
- {
- char dirname[NFILEN];
- BUFFER *bp;
- WINDOW *wp;
-
- dirname[0] = '\0';
- if(eread("Dired other window: ", dirname, NFILEN, EFNEW | EFCR) == ABORT)
- return ABORT;
- if((bp = dired_(dirname)) == NULL) return FALSE;
- if((wp = popbuf(bp)) == NULL) return FALSE;
- curbp = bp;
- curwp = wp;
- return TRUE;
- }
-
- /*ARGSUSED*/
- d_del(f, n)
- int f, n;
- {
- if(n < 0) return FALSE;
- while(n--) {
- if(llength(curwp->w_dotp) > 0)
- lputc(curwp->w_dotp, 0, 'D');
- if(lforw(curwp->w_dotp) != curbp->b_linep)
- curwp->w_dotp = lforw(curwp->w_dotp);
- }
- curwp->w_flag |= WFEDIT | WFMOVE;
- curwp->w_doto = 0;
- return TRUE;
- }
-
- /*ARGSUSED*/
- d_undel(f, n)
- int f, n;
- {
- if(n < 0) return d_undelbak(f, -n);
- while(n--) {
- if(llength(curwp->w_dotp) > 0)
- lputc(curwp->w_dotp, 0, ' ');
- if(lforw(curwp->w_dotp) != curbp->b_linep)
- curwp->w_dotp = lforw(curwp->w_dotp);
- }
- curwp->w_flag |= WFEDIT | WFMOVE;
- curwp->w_doto = 0;
- return TRUE;
- }
-
- /*ARGSUSED*/
- d_undelbak(f, n)
- int f, n;
- {
- if(n < 0) return d_undel(f, -n);
- while(n--) {
- if(llength(curwp->w_dotp) > 0)
- lputc(curwp->w_dotp, 0, ' ');
- if(lback(curwp->w_dotp) != curbp->b_linep)
- curwp->w_dotp = lback(curwp->w_dotp);
- }
- curwp->w_doto = 0;
- curwp->w_flag |= WFEDIT | WFMOVE;
- return TRUE;
- }
-
- /*ARGSUSED*/
- d_findfile(f, n)
- int f, n;
- {
- char fname[NFILEN];
- register BUFFER *bp;
- register int s;
- BUFFER *findbuffer();
-
- if((s = d_makename(curwp->w_dotp, fname)) == ABORT) return FALSE;
- if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL) return FALSE;
- curbp = bp;
- if (showbuffer(bp, curwp, WFHARD) != TRUE) return FALSE;
- if (bp->b_fname[0] != 0) return TRUE;
- return readin(fname);
- }
-
- /*ARGSUSED*/
- d_ffotherwindow(f, n)
- int f, n;
- {
- char fname[NFILEN];
- register BUFFER *bp;
- register int s;
- register WINDOW *wp;
- BUFFER *findbuffer();
-
- if((s = d_makename(curwp->w_dotp, fname)) == ABORT) return FALSE;
- if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL) return FALSE;
- if ((wp = popbuf(bp)) == NULL) return FALSE;
- curbp = bp;
- curwp = wp;
- if (bp->b_fname[0] != 0) return TRUE; /* never true for dired buffers */
- return readin(fname);
- }
-
- /*ARGSUSED*/
- d_expunge(f, n)
- int f, n;
- {
- register LINE *lp, *nlp;
- char fname[NFILEN];
- VOID lfree();
-
- for(lp = lforw(curbp->b_linep); lp != curbp->b_linep; lp = nlp) {
- nlp = lforw(lp);
- if(llength(lp) && lgetc(lp, 0) == 'D') {
- switch(d_makename(lp, fname)) {
- case ABORT:
- ewprintf("Bad line in dired buffer");
- return FALSE;
- case FALSE:
- if(unlink(fname) < 0) {
- ewprintf("Could not delete '%s'", fname);
- return FALSE;
- }
- break;
- case TRUE:
- if(unlinkdir(fname) < 0) {
- ewprintf("Could not delete directory '%s'", fname);
- return FALSE;
- }
- break;
- }
- lfree(lp);
- curwp->w_flag |= WFHARD;
- }
- }
- return TRUE;
- }
-
- /*ARGSUSED*/
- d_copy(f, n)
- int f, n;
- {
- char frname[NFILEN], toname[NFILEN];
- int stat;
-
- if(d_makename(curwp->w_dotp, frname) != FALSE) {
- ewprintf("Not a file");
- return FALSE;
- }
- if((stat = eread("Copy %s to: ", toname, NFILEN, EFNEW | EFCR, frname))
- != TRUE) return stat;
- return copy(frname, toname) >= 0;
- }
-
- /*ARGSUSED*/
- d_rename(f, n)
- int f, n;
- {
- char frname[NFILEN], toname[NFILEN];
- int stat;
-
- if(d_makename(curwp->w_dotp, frname) != FALSE) {
- ewprintf("Not a file");
- return FALSE;
- }
- if((stat = eread("Rename %s to: ", toname, NFILEN, EFNEW | EFCR, frname))
- != TRUE) return stat;
- return rename(frname, toname) >= 0;
- }
- #endif
-
-
- SHAR_EOF
- cat << \SHAR_EOF > display.c
- /*
- * The functions in this file handle redisplay. The
- * redisplay system knows almost nothing about the editing
- * process; the editing functions do, however, set some
- * hints to eliminate a lot of the grinding. There is more
- * that can be done; the "vtputc" interface is a real
- * pig. Two conditional compilation flags; the GOSLING
- * flag enables dynamic programming redisplay, using the
- * algorithm published by Jim Gosling in SIGOA. The MEMMAP
- * changes things around for memory mapped video. With
- * both off, the terminal is a VT52.
- */
- #include "def.h"
- #include "kbd.h"
-
- /*
- * You can change these back to the types
- * implied by the name if you get tight for space. If you
- * make both of them "int" you get better code on the VAX.
- * They do nothing if this is not Gosling redisplay, except
- * for change the size of a structure that isn't used.
- * A bit of a cheat.
- */
- /* These defines really belong in sysdef.h */
- #ifndef XCHAR
- # define XCHAR int
- # define XSHORT int
- #endif
-
- #ifdef STANDOUT_GLITCH
- extern int SG; /* number of standout glitches */
- #endif
-
- /*
- * A video structure always holds
- * an array of characters whose length is equal to
- * the longest line possible. Only some of this is
- * used if "ncol" isn't the same as "NCOL".
- */
- typedef struct {
- short v_hash; /* Hash code, for compares. */
- short v_flag; /* Flag word. */
- short v_color; /* Color of the line. */
- XSHORT v_cost; /* Cost of display. */
- char v_text[NCOL]; /* The actual characters. */
- } VIDEO;
-
- #define VFCHG 0x0001 /* Changed. */
- #define VFHBAD 0x0002 /* Hash and cost are bad. */
- #define VFEXT 0x0004 /* extended line (beond ncol) */
-
- /*
- * SCORE structures hold the optimal
- * trace trajectory, and the cost of redisplay, when
- * the dynamic programming redisplay code is used.
- * If no fancy redisplay, this isn't used. The trace index
- * fields can be "char", and the score a "short", but
- * this makes the code worse on the VAX.
- */
- typedef struct {
- XCHAR s_itrace; /* "i" index for track back. */
- XCHAR s_jtrace; /* "j" index for trace back. */
- XSHORT s_cost; /* Display cost. */
- } SCORE;
-
- int sgarbf = TRUE; /* TRUE if screen is garbage. */
- int vtrow = 0; /* Virtual cursor row. */
- int vtcol = 0; /* Virtual cursor column. */
- int tthue = CNONE; /* Current color. */
- int ttrow = HUGE; /* Physical cursor row. */
- int ttcol = HUGE; /* Physical cursor column. */
- int tttop = HUGE; /* Top of scroll region. */
- int ttbot = HUGE; /* Bottom of scroll region. */
- int lbound = 0; /* leftmost bound of the current line */
- /* being displayed */
-
- VIDEO *vscreen[NROW-1]; /* Edge vector, virtual. */
- VIDEO *pscreen[NROW-1]; /* Edge vector, physical. */
- VIDEO video[2*(NROW-1)]; /* Actual screen data. */
- VIDEO blanks; /* Blank line image. */
-
- /*
- * Some predeclerations to make ANSI compilers happy
- */
- VOID vtinit();
- VOID vttidy();
- VOID vtmove();
- VOID vtputc();
- VOID vtpute();
- VOID vteeol();
- VOID update();
- VOID updext();
- VOID ucopy();
- VOID uline();
- VOID modeline();
- VOID hash();
- VOID setscores();
- VOID traceback();
-
- #ifdef GOSLING
- /*
- * This matrix is written as an array because
- * we do funny things in the "setscores" routine, which
- * is very compute intensive, to make the subscripts go away.
- * It would be "SCORE score[NROW][NROW]" in old speak.
- * Look at "setscores" to understand what is up.
- */
- SCORE score[NROW*NROW];
- #endif
-
- /*
- * Initialize the data structures used
- * by the display code. The edge vectors used
- * to access the screens are set up. The operating
- * system's terminal I/O channel is set up. Fill the
- * "blanks" array with ASCII blanks. The rest is done
- * at compile time. The original window is marked
- * as needing full update, and the physical screen
- * is marked as garbage, so all the right stuff happens
- * on the first call to redisplay.
- */
- VOID
- vtinit() {
- register VIDEO *vp;
- register int i;
-
- ttopen();
- ttinit();
- vp = &video[0];
- for (i=0; i<NROW-1; ++i) {
- vscreen[i] = vp;
- ++vp;
- pscreen[i] = vp;
- ++vp;
- }
- blanks.v_color = CTEXT;
- for (i=0; i<NCOL; ++i)
- blanks.v_text[i] = ' ';
- }
-
- /*
- * Tidy up the virtual display system
- * in anticipation of a return back to the host
- * operating system. Right now all we do is position
- * the cursor to the last line, erase the line, and
- * close the terminal channel.
- */
- VOID
- vttidy() {
- ttcolor(CTEXT);
- ttnowindow(); /* No scroll window. */
- ttmove(nrow-1, 0); /* Echo line. */
- tteeol();
- tttidy();
- ttflush();
- ttclose();
- }
-
- /*
- * Move the virtual cursor to an origin
- * 0 spot on the virtual display screen. I could
- * store the column as a character pointer to the spot
- * on the line, which would make "vtputc" a little bit
- * more efficient. No checking for errors.
- */
- VOID
- vtmove(row, col) {
- vtrow = row;
- vtcol = col;
- }
-
- /*
- * Write a character to the virtual display,
- * dealing with long lines and the display of unprintable
- * things like control characters. Also expand tabs every 8
- * columns. This code only puts printing characters into
- * the virtual display image. Special care must be taken when
- * expanding tabs. On a screen whose width is not a multiple
- * of 8, it is possible for the virtual cursor to hit the
- * right margin before the next tab stop is reached. This
- * makes the tab code loop if you are not careful.
- * Three guesses how we found this.
- */
- VOID
- vtputc(c) register int c; {
- register VIDEO *vp;
-
- vp = vscreen[vtrow];
- if (vtcol >= ncol)
- vp->v_text[ncol-1] = '$';
- else if (c == '\t'
- #ifdef NOTAB
- && !(curbp->b_flag & BFNOTAB)
- #endif
- ) {
- do {
- vtputc(' ');
- } while (vtcol<ncol && (vtcol&0x07)!=0);
- } else if (ISCTRL(c)) {
- vtputc('^');
- vtputc(CCHR(c));
- } else
- vp->v_text[vtcol++] = c;
- }
-
- /* Put a character to the virtual screen in an extended line. If we are
- * not yet on left edge, don't print it yet. Check for overflow on
- * the right margin.
- */
- VOID
- vtpute(c)
- int c;
- {
- register VIDEO *vp;
-
- vp = vscreen[vtrow];
-
- if (vtcol >= ncol) vp->v_text[ncol - 1] = '$';
- else if (c == '\t'
- #ifdef NOTAB
- && !(curbp->b_flag & BFNOTAB)
- #endif
- ) {
- do {
- vtpute(' ');
- }
- while (((vtcol + lbound)&0x07) != 0 && vtcol < ncol);
- } else if (ISCTRL(c) != FALSE) {
- vtpute('^');
- vtpute(CCHR(c));
- } else {
- if (vtcol >= 0) vp->v_text[vtcol] = c;
- ++vtcol;
- }
- }
-
- /* Erase from the end of the
- * software cursor to the end of the
- * line on which the software cursor is
- * located. The display routines will decide
- * if a hardware erase to end of line command
- * should be used to display this.
- */
- VOID
- vteeol() {
- register VIDEO *vp;
-
- vp = vscreen[vtrow];
- while (vtcol < ncol)
- vp->v_text[vtcol++] = ' ';
- }
-
- /*
- * Make sure that the display is
- * right. This is a three part process. First,
- * scan through all of the windows looking for dirty
- * ones. Check the framing, and refresh the screen.
- * Second, make sure that "currow" and "curcol" are
- * correct for the current window. Third, make the
- * virtual and physical screens the same.
- */
- VOID
- update() {
- register LINE *lp;
- register WINDOW *wp;
- register VIDEO *vp1;
- VIDEO *vp2;
- register int i;
- register int j;
- register int c;
- register int hflag;
- register int currow;
- register int curcol;
- register int offs;
- register int size;
- VOID traceback ();
- VOID uline ();
-
- if (typeahead()) return;
- if (sgarbf) { /* must update everything */
- wp = wheadp;
- while(wp != NULL) {
- wp->w_flag |= WFMODE | WFHARD;
- wp = wp->w_wndp;
- }
- }
- hflag = FALSE; /* Not hard. */
- wp = wheadp;
- while (wp != NULL) {
- if (wp->w_flag != 0) { /* Need update. */
- if ((wp->w_flag&WFFORCE) == 0) {
- lp = wp->w_linep;
- for (i=0; i<wp->w_ntrows; ++i) {
- if (lp == wp->w_dotp)
- goto out;
- if (lp == wp->w_bufp->b_linep)
- break;
- lp = lforw(lp);
- }
- }
- i = wp->w_force; /* Reframe this one. */
- if (i > 0) {
- --i;
- if (i >= wp->w_ntrows)
- i = wp->w_ntrows-1;
- } else if (i < 0) {
- i += wp->w_ntrows;
- if (i < 0)
- i = 0;
- } else
- i = wp->w_ntrows/2;
- lp = wp->w_dotp;
- while (i!=0 && lback(lp)!=wp->w_bufp->b_linep) {
- --i;
- lp = lback(lp);
- }
- wp->w_linep = lp;
- wp->w_flag |= WFHARD; /* Force full. */
- out:
- lp = wp->w_linep; /* Try reduced update. */
- i = wp->w_toprow;
- if ((wp->w_flag&~WFMODE) == WFEDIT) {
- while (lp != wp->w_dotp) {
- ++i;
- lp = lforw(lp);
- }
- vscreen[i]->v_color = CTEXT;
- vscreen[i]->v_flag |= (VFCHG|VFHBAD);
- vtmove(i, 0);
- for (j=0; j<llength(lp); ++j)
- vtputc(lgetc(lp, j));
- vteeol();
- } else if ((wp->w_flag&(WFEDIT|WFHARD)) != 0) {
- hflag = TRUE;
- while (i < wp->w_toprow+wp->w_ntrows) {
- vscreen[i]->v_color = CTEXT;
- vscreen[i]->v_flag |= (VFCHG|VFHBAD);
- vtmove(i, 0);
- if (lp != wp->w_bufp->b_linep) {
- for (j=0; j<llength(lp); ++j)
- vtputc(lgetc(lp, j));
- lp = lforw(lp);
- }
- vteeol();
- ++i;
- }
- }
- if ((wp->w_flag&WFMODE) != 0)
- modeline(wp);
- wp->w_flag = 0;
- wp->w_force = 0;
- }
- wp = wp->w_wndp;
- }
- lp = curwp->w_linep; /* Cursor location. */
- currow = curwp->w_toprow;
- while (lp != curwp->w_dotp) {
- ++currow;
- lp = lforw(lp);
- }
- curcol = 0;
- i = 0;
- while (i < curwp->w_doto) {
- c = lgetc(lp, i++);
- if (c == '\t'
- #ifdef NOTAB
- && !(curbp->b_flag & BFNOTAB)
- #endif
- ) curcol |= 0x07;
- else if (ISCTRL(c) != FALSE)
- ++curcol;
- ++curcol;
- }
- if (curcol >= ncol - 1) { /* extended line. */
- /* flag we are extended and changed */
- vscreen[currow]->v_flag |= VFEXT | VFCHG;
- updext(currow, curcol); /* and output extended line */
- } else lbound = 0; /* not extended line */
-
- /* make sure no lines need to be de-extended because the cursor is
- no longer on them */
-
- wp = wheadp;
-
- while (wp != NULL) {
- lp = wp->w_linep;
- i = wp->w_toprow;
- while (i < wp->w_toprow + wp->w_ntrows) {
- if (vscreen[i]->v_flag & VFEXT) {
- /* always flag extended lines as changed */
- vscreen[i]->v_flag |= VFCHG;
- if ((wp != curwp) || (lp != wp->w_dotp) ||
- (curcol < ncol - 1)) {
- vtmove(i, 0);
- for (j = 0; j < llength(lp); ++j)
- vtputc(lgetc(lp, j));
- vteeol();
- /* this line no longer is extended */
- vscreen[i]->v_flag &= ~VFEXT;
- }
- }
- lp = lforw(lp);
- ++i;
- }
- /* if garbaged then fix up mode lines */
- if (sgarbf != FALSE) vscreen[i]->v_flag |= VFCHG;
- /* and onward to the next window */
- wp = wp->w_wndp;
- }
-
- if (sgarbf != FALSE) { /* Screen is garbage. */
- sgarbf = FALSE; /* Erase-page clears */
- epresf = FALSE; /* the message area. */
- tttop = HUGE; /* Forget where you set */
- ttbot = HUGE; /* scroll region. */
- tthue = CNONE; /* Color unknown. */
- ttmove(0, 0);
- tteeop();
- for (i=0; i<nrow-1; ++i) {
- uline(i, vscreen[i], &blanks);
- ucopy(vscreen[i], pscreen[i]);
- }
- ttmove(currow, curcol - lbound);
- ttflush();
- return;
- }
- #ifdef GOSLING
- if (hflag != FALSE) { /* Hard update? */
- for (i=0; i<nrow-1; ++i) { /* Compute hash data. */
- hash(vscreen[i]);
- hash(pscreen[i]);
- }
- offs = 0; /* Get top match. */
- while (offs != nrow-1) {
- vp1 = vscreen[offs];
- vp2 = pscreen[offs];
- if (vp1->v_color != vp2->v_color
- || vp1->v_hash != vp2->v_hash)
- break;
- uline(offs, vp1, vp2);
- ucopy(vp1, vp2);
- ++offs;
- }
- if (offs == nrow-1) { /* Might get it all. */
- ttmove(currow, curcol - lbound);
- ttflush();
- return;
- }
- size = nrow-1; /* Get bottom match. */
- while (size != offs) {
- vp1 = vscreen[size-1];
- vp2 = pscreen[size-1];
- if (vp1->v_color != vp2->v_color
- || vp1->v_hash != vp2->v_hash)
- break;
- uline(size-1, vp1, vp2);
- ucopy(vp1, vp2);
- --size;
- }
- if ((size -= offs) == 0) /* Get screen size. */
- panic("Illegal screen size in update");
- setscores(offs, size); /* Do hard update. */
- traceback(offs, size, size, size);
- for (i=0; i<size; ++i)
- ucopy(vscreen[offs+i], pscreen[offs+i]);
- ttmove(currow, curcol - lbound);
- ttflush();
- return;
- }
- #endif
- for (i=0; i<nrow-1; ++i) { /* Easy update. */
- vp1 = vscreen[i];
- vp2 = pscreen[i];
- if ((vp1->v_flag&VFCHG) != 0) {
- uline(i, vp1, vp2);
- ucopy(vp1, vp2);
- }
- }
- ttmove(currow, curcol - lbound);
- ttflush();
- }
-
- /*
- * Update a saved copy of a line,
- * kept in a VIDEO structure. The "vvp" is
- * the one in the "vscreen". The "pvp" is the one
- * in the "pscreen". This is called to make the
- * virtual and physical screens the same when
- * display has done an update.
- */
- VOID
- ucopy(vvp, pvp) register VIDEO *vvp; register VIDEO *pvp; {
-
- vvp->v_flag &= ~VFCHG; /* Changes done. */
- pvp->v_flag = vvp->v_flag; /* Update model. */
- pvp->v_hash = vvp->v_hash;
- pvp->v_cost = vvp->v_cost;
- pvp->v_color = vvp->v_color;
- bcopy(vvp->v_text, pvp->v_text, ncol);
- }
-
- /* updext: update the extended line which the cursor is currently
- * on at a column greater than the terminal width. The line
- * will be scrolled right or left to let the user see where
- * the cursor is
- */
- VOID
- updext(currow, curcol)
- int currow, curcol;
- {
- register LINE *lp; /* pointer to current line */
- register int j; /* index into line */
-
- /* calculate what column the left bound should be */
- /* (force cursor into middle half of screen) */
- lbound = curcol - (curcol % (ncol>>1)) - (ncol>>2);
- /* scan through the line outputing characters to the virtual screen */
- /* once we reach the left edge */
- vtmove(currow, -lbound); /* start scanning offscreen */
- lp = curwp->w_dotp; /* line to output */
- for (j=0; j<llength(lp); ++j) /* until the end-of-line */
- vtpute(lgetc(lp, j));
- vteeol(); /* truncate the virtual line */
- vscreen[currow]->v_text[0] = '$'; /* and put a '$' in column 1 */
- }
-
- /*
- * Update a single line. This routine only
- * uses basic functionality (no insert and delete character,
- * but erase to end of line). The "vvp" points at the VIDEO
- * structure for the line on the virtual screen, and the "pvp"
- * is the same for the physical screen. Avoid erase to end of
- * line when updating CMODE color lines, because of the way that
- * reverse video works on most terminals.
- */
- VOID uline(row, vvp, pvp) VIDEO *vvp; VIDEO *pvp; {
- #ifdef MEMMAP
- putline(row+1, 1, &vvp->v_text[0]);
- #else
- register char *cp1;
- register char *cp2;
- register char *cp3;
- char *cp4;
- char *cp5;
- register int nbflag;
-
- if (vvp->v_color != pvp->v_color) { /* Wrong color, do a */
- ttmove(row, 0); /* full redraw. */
- #ifdef STANDOUT_GLITCH
- if (pvp->v_color != CTEXT && SG >= 0) tteeol();
- #endif
- ttcolor(vvp->v_color);
- #ifdef STANDOUT_GLITCH
- cp1 = &vvp->v_text[SG > 0 ? SG : 0];
- /* the odd code for SG==0 is to avoid putting the invisable
- * glitch character on the next line.
- * (Hazeltine executive 80 model 30)
- */
- cp2 = &vvp->v_text[ncol - (SG >= 0 ? (SG!=0 ? SG : 1) : 0)];
- #else
- cp1 = &vvp->v_text[0];
- cp2 = &vvp->v_text[ncol];
- #endif
- while (cp1 != cp2) {
- ttputc(*cp1++);
- ++ttcol;
- }
- #ifndef MOVE_STANDOUT
- ttcolor(CTEXT);
- #endif
- return;
- }
- cp1 = &vvp->v_text[0]; /* Compute left match. */
- cp2 = &pvp->v_text[0];
- while (cp1!=&vvp->v_text[ncol] && cp1[0]==cp2[0]) {
- ++cp1;
- ++cp2;
- }
- if (cp1 == &vvp->v_text[ncol]) /* All equal. */
- return;
- nbflag = FALSE;
- cp3 = &vvp->v_text[ncol]; /* Compute right match. */
- cp4 = &pvp->v_text[ncol];
- while (cp3[-1] == cp4[-1]) {
- --cp3;
- --cp4;
- if (cp3[0] != ' ') /* Note non-blanks in */
- nbflag = TRUE; /* the right match. */
- }
- cp5 = cp3; /* Is erase good? */
- if (nbflag==FALSE && vvp->v_color==CTEXT) {
- while (cp5!=cp1 && cp5[-1]==' ')
- --cp5;
- /* Alcyon hack */
- if ((int)(cp3-cp5) <= tceeol)
- cp5 = cp3;
- }
- /* Alcyon hack */
- ttmove(row, (int)(cp1-&vvp->v_text[0]));
- #ifdef STANDOUT_GLITCH
- if (vvp->v_color != CTEXT && SG > 0) {
- if(cp1 < &vvp->v_text[SG]) cp1 = &vvp->v_text[SG];
- if(cp5 > &vvp->v_text[ncol-SG]) cp5 = &vvp->v_text[ncol-SG];
- } else if (SG < 0)
- #endif
- ttcolor(vvp->v_color);
- while (cp1 != cp5) {
- ttputc(*cp1++);
- ++ttcol;
- }
- if (cp5 != cp3) /* Do erase. */
- tteeol();
- #endif
- }
-
- /*
- * Redisplay the mode line for
- * the window pointed to by the "wp".
- * This is the only routine that has any idea
- * of how the modeline is formatted. You can
- * change the modeline format by hacking at
- * this routine. Called by "update" any time
- * there is a dirty window.
- * Note that if STANDOUT_GLITCH is defined, first and last SG characters
- * may never be seen.
- */
- VOID
- modeline(wp) register WINDOW *wp; {
- register int n;
- register BUFFER *bp;
- int mode;
-
- n = wp->w_toprow+wp->w_ntrows; /* Location. */
- vscreen[n]->v_color = CMODE; /* Mode line color. */
- vscreen[n]->v_flag |= (VFCHG|VFHBAD); /* Recompute, display. */
- vtmove(n, 0); /* Seek to right line. */
- bp = wp->w_bufp;
- vtputc('-'); vtputc('-');
- if ((bp->b_flag&BFCHG) != 0) { /* "*" if changed. */
- vtputc('*'); vtputc('*');
- } else {
- vtputc('-'); vtputc('-');
- }
- vtputc('-');
- n = 5;
- n += vtputs("Mg: ");
- if (bp->b_bname[0] != '\0')
- n += vtputs(&(bp->b_bname[0]));
- while (n < 42) { /* Pad out with blanks */
- vtputc(' ');
- ++n;
- }
- vtputc('(');
- ++n;
- for(mode=0;;) {
- n += vtputs(bp->b_modes[mode]->p_name);
- if(++mode > bp->b_nmodes) break;
- vtputc('-');
- ++n;
- }
- vtputc(')');
- ++n;
- while (n < ncol) { /* Pad out. */
- vtputc('-');
- ++n;
- }
- }
- /*
- * output a string to the mode line, report how long it was.
- */
- vtputs(s) register char *s; {
- register int n = 0;
-
- while (*s != '\0') {
- vtputc(*s++);
- ++n;
- }
- return n;
- }
- #ifdef GOSLING
- /*
- * Compute the hash code for
- * the line pointed to by the "vp". Recompute
- * it if necessary. Also set the approximate redisplay
- * cost. The validity of the hash code is marked by
- * a flag bit. The cost understand the advantages
- * of erase to end of line. Tuned for the VAX
- * by Bob McNamara; better than it used to be on
- * just about any machine.
- */
- VOID
- hash(vp) register VIDEO *vp; {
- register int i;
- register int n;
- register char *s;
-
- if ((vp->v_flag&VFHBAD) != 0) { /* Hash bad. */
- s = &vp->v_text[ncol-1];
- for (i=ncol; i!=0; --i, --s)
- if (*s != ' ')
- break;
- n = ncol-i; /* Erase cheaper? */
- if (n > tceeol)
- n = tceeol;
- vp->v_cost = i+n; /* Bytes + blanks. */
- for (n=0; i!=0; --i, --s)
- n = (n<<5) + n + *s;
- vp->v_hash = n; /* Hash code. */
- vp->v_flag &= ~VFHBAD; /* Flag as all done. */
- }
- }
-
- /*
- * Compute the Insert-Delete
- * cost matrix. The dynamic programming algorithm
- * described by James Gosling is used. This code assumes
- * that the line above the echo line is the last line involved
- * in the scroll region. This is easy to arrange on the VT100
- * because of the scrolling region. The "offs" is the origin 0
- * offset of the first row in the virtual/physical screen that
- * is being updated; the "size" is the length of the chunk of
- * screen being updated. For a full screen update, use offs=0
- * and size=nrow-1.
- *
- * Older versions of this code implemented the score matrix by
- * a two dimensional array of SCORE nodes. This put all kinds of
- * multiply instructions in the code! This version is written to
- * use a linear array and pointers, and contains no multiplication
- * at all. The code has been carefully looked at on the VAX, with
- * only marginal checking on other machines for efficiency. In
- * fact, this has been tuned twice! Bob McNamara tuned it even
- * more for the VAX, which is a big issue for him because of
- * the 66 line X displays.
- *
- * On some machines, replacing the "for (i=1; i<=size; ++i)" with
- * i = 1; do { } while (++i <=size)" will make the code quite a
- * bit better; but it looks ugly.
- */
- VOID
- setscores(offs, size) {
- register SCORE *sp;
- SCORE *sp1;
- register int tempcost;
- register int bestcost;
- register int j;
- register int i;
- register VIDEO **vp;
- VIDEO **pp, **vbase, **pbase;
-
- vbase = &vscreen[offs-1]; /* By hand CSE's. */
- pbase = &pscreen[offs-1];
- score[0].s_itrace = 0; /* [0, 0] */
- score[0].s_jtrace = 0;
- score[0].s_cost = 0;
- sp = &score[1]; /* Row 0, inserts. */
- tempcost = 0;
- vp = &vbase[1];
- for (j=1; j<=size; ++j) {
- sp->s_itrace = 0;
- sp->s_jtrace = j-1;
- tempcost += tcinsl;
- tempcost += (*vp)->v_cost;
- sp->s_cost = tempcost;
- ++vp;
- ++sp;
- }
- sp = &score[NROW]; /* Column 0, deletes. */
- tempcost = 0;
- for (i=1; i<=size; ++i) {
- sp->s_itrace = i-1;
- sp->s_jtrace = 0;
- tempcost += tcdell;
- sp->s_cost = tempcost;
- sp += NROW;
- }
- sp1 = &score[NROW+1]; /* [1, 1]. */
- pp = &pbase[1];
- for (i=1; i<=size; ++i) {
- sp = sp1;
- vp = &vbase[1];
- for (j=1; j<=size; ++j) {
- sp->s_itrace = i-1;
- sp->s_jtrace = j;
- bestcost = (sp-NROW)->s_cost;
- if (j != size) /* Cd(A[i])=0 @ Dis. */
- bestcost += tcdell;
- tempcost = (sp-1)->s_cost;
- tempcost += (*vp)->v_cost;
- if (i != size) /* Ci(B[j])=0 @ Dsj. */
- tempcost += tcinsl;
- if (tempcost < bestcost) {
- sp->s_itrace = i;
- sp->s_jtrace = j-1;
- bestcost = tempcost;
- }
- tempcost = (sp-NROW-1)->s_cost;
- if ((*pp)->v_color != (*vp)->v_color
- || (*pp)->v_hash != (*vp)->v_hash)
- tempcost += (*vp)->v_cost;
- if (tempcost < bestcost) {
- sp->s_itrace = i-1;
- sp->s_jtrace = j-1;
- bestcost = tempcost;
- }
- sp->s_cost = bestcost;
- ++sp; /* Next column. */
- ++vp;
- }
- ++pp;
- sp1 += NROW; /* Next row. */
- }
- }
-
- /*
- * Trace back through the dynamic programming cost
- * matrix, and update the screen using an optimal sequence
- * of redraws, insert lines, and delete lines. The "offs" is
- * the origin 0 offset of the chunk of the screen we are about to
- * update. The "i" and "j" are always started in the lower right
- * corner of the matrix, and imply the size of the screen.
- * A full screen traceback is called with offs=0 and i=j=nrow-1.
- * There is some do-it-yourself double subscripting here,
- * which is acceptable because this routine is much less compute
- * intensive then the code that builds the score matrix!
- */
- VOID traceback(offs, size, i, j) {
- register int itrace;
- register int jtrace;
- register int k;
- register int ninsl;
- register int ndraw;
- register int ndell;
-
- if (i==0 && j==0) /* End of update. */
- return;
- itrace = score[(NROW*i) + j].s_itrace;
- jtrace = score[(NROW*i) + j].s_jtrace;
- if (itrace == i) { /* [i, j-1] */
- ninsl = 0; /* Collect inserts. */
- if (i != size)
- ninsl = 1;
- ndraw = 1;
- while (itrace!=0 || jtrace!=0) {
- if (score[(NROW*itrace) + jtrace].s_itrace != itrace)
- break;
- jtrace = score[(NROW*itrace) + jtrace].s_jtrace;
- if (i != size)
- ++ninsl;
- ++ndraw;
- }
- traceback(offs, size, itrace, jtrace);
- if (ninsl != 0) {
- ttcolor(CTEXT);
- ttinsl(offs+j-ninsl, offs+size-1, ninsl);
- }
- do { /* B[j], A[j] blank. */
- k = offs+j-ndraw;
- uline(k, vscreen[k], &blanks);
- } while (--ndraw);
- return;
- }
- if (jtrace == j) { /* [i-1, j] */
- ndell = 0; /* Collect deletes. */
- if (j != size)
- ndell = 1;
- while (itrace!=0 || jtrace!=0) {
- if (score[(NROW*itrace) + jtrace].s_jtrace != jtrace)
- break;
- itrace = score[(NROW*itrace) + jtrace].s_itrace;
- if (j != size)
- ++ndell;
- }
- if (ndell != 0) {
- ttcolor(CTEXT);
- ttdell(offs+i-ndell, offs+size-1, ndell);
- }
- traceback(offs, size, itrace, jtrace);
- return;
- }
- traceback(offs, size, itrace, jtrace);
- k = offs+j-1;
- uline(k, vscreen[k], pscreen[offs+i-1]);
- }
- #endif
- SHAR_EOF
- cat << \SHAR_EOF > extend.c
- /*
- * Extended (M-X) commands, rebinding, and
- * startup file processing.
- */
- #include "def.h"
- #include "kbd.h"
-
- #ifndef NO_MACRO
- #include "macro.h"
- #endif
-
- #ifdef FKEYS
- #include "key.h"
- #ifndef NO_STARTUP
- #ifndef BINDKEY
- #define BINDKEY /* bindkey is used by FKEYS startup code */
- #endif
- #endif
- #endif
-
- extern char *strncpy();
- extern int rescan();
-
- /* insert a string, mainly for use from macros (created by selfinsert) */
- /*ARGSUSED*/
- insert(f, n)
- int f, n;
- {
- register char *cp;
- char buf[128];
- #ifndef NO_MACRO
- register int count;
- int c;
-
- if(inmacro) {
- while(--n >= 0) {
- for(count = 0; count < maclcur->l_used; count++) {
- if((((c=maclcur->l_text[count]) == '\n') ? lnewline()
- : linsert(1, c)) != TRUE) return FALSE;
- }
- }
- maclcur = maclcur->l_fp;
- return TRUE;
- }
- if(n==1) thisflag |= CFINS; /* CFINS means selfinsert can tack on end */
- #endif
- if(eread("Insert: ", buf, sizeof(buf), EFNEW) == FALSE) return FALSE;
- while(--n >= 0) {
- cp = buf;
- while(*cp) {
- if(((*cp == '\n') ? lnewline() : linsert(1, *cp)) != TRUE)
- return FALSE;
- cp++;
- }
- }
- return TRUE;
- }
-
- /*
- * Bind a key to a function. Cases range from the trivial (replacing an
- * existing binding) to the extremly complex (creating a new prefix in a
- * map_element that already has one, so the map_element must be split,
- * but the keymap doesn't have enough room for another map_element, so
- * the keymap is reallocated). No attempt is made to reclaim space no
- * longer used, if this is a problem flags must be added to indicate
- * malloced verses static storage in both keymaps and map_elements.
- * Structure assignments would come in real handy, but K&R based compilers
- * don't have them. Care is taken so running out of memory will leave
- * the keymap in a usable state.
- */
- static int remap(curmap, c, funct, pref_map)
- register KEYMAP *curmap;/* pointer to the map being changed */
- int c; /* character being changed */
- PF funct; /* function being changed to */
- KEYMAP *pref_map; /* if funct==prefix, map to bind to or NULL for new */
- /* extern MAP_ELEMENT *ele; must be set before calling */
- {
- register int i;
- int n1, n2, nold;
- KEYMAP *mp;
- PF *pfp;
- MAP_ELEMENT *mep;
- static KEYMAP *realocmap();
-
- if(ele >= &curmap->map_element[curmap->map_num] || c < ele->k_base) {
- if(ele > &curmap->map_element[0] && (funct!=prefix ||
- (ele-1)->k_prefmap==NULL)) {
- n1 = c - (ele-1)->k_num;
- } else n1 = HUGE;
- if(ele < &curmap->map_element[curmap->map_num] && (funct!=prefix ||
- ele->k_prefmap==NULL)) {
- n2 = ele->k_base - c;
- } else n2 = HUGE;
- if(n1 <= MAPELEDEF && n1 <= n2) {
- ele--;
- if((pfp = (PF *)malloc((unsigned)(c - ele->k_base+1)
- * sizeof(PF))) == NULL) {
- ewprintf("Out of memory");
- return FALSE;
- }
- nold = ele->k_num - ele->k_base + 1;
- for(i=0; i < nold; i++)
- pfp[i] = ele->k_funcp[i];
- while(--n1) pfp[i++] = curmap->map_default;
- pfp[i] = funct;
- ele->k_num = c;
- ele->k_funcp = pfp;
- } else if(n2 <= MAPELEDEF) {
- if((pfp = (PF *)malloc((unsigned)(ele->k_num - c + 1)
- * sizeof(PF))) == NULL) {
- ewprintf("Out of memory");
- return FALSE;
- }
- nold = ele->k_num - ele->k_base + 1;
- for(i=0; i < nold; i++)
- pfp[i+n2] = ele->k_funcp[i];
- while(--n2) pfp[n2] = curmap->map_default;
- pfp[0] = funct;
- ele->k_base = c;
- ele->k_funcp = pfp;
- } else {
- if(curmap->map_num >= curmap->map_max &&
- (curmap = realocmap(curmap)) == NULL) return FALSE;
- if((pfp = (PF *)malloc(sizeof(PF))) == NULL) {
- ewprintf("Out of memory");
- return FALSE;
- }
- pfp[0] = funct;
- for(mep = &curmap->map_element[curmap->map_num]; mep > ele; mep--) {
- mep->k_base = (mep-1)->k_base;
- mep->k_num = (mep-1)->k_num;
- mep->k_funcp = (mep-1)->k_funcp;
- mep->k_prefmap = (mep-1)->k_prefmap;
- }
- ele->k_base = c;
- ele->k_num = c;
- ele->k_funcp = pfp;
- ele->k_prefmap = NULL;
- curmap->map_num++;
- }
- if(funct == prefix) {
- if(pref_map != NULL) {
- ele->k_prefmap = pref_map;
- } else {
- if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
- (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
- ewprintf("Out of memory");
- ele->k_funcp[c - ele->k_base] = curmap->map_default;
- return FALSE;
- }
- mp->map_num = 0;
- mp->map_max = MAPINIT;
- mp->map_default = rescan;
- ele->k_prefmap = mp;
- }
- }
- } else {
- n1 = c - ele->k_base;
- if(ele->k_funcp[n1] == funct && (funct!=prefix || pref_map==NULL ||
- pref_map==ele->k_prefmap))
- return TRUE; /* no change */
- if(funct!=prefix || ele->k_prefmap==NULL) {
- if(ele->k_funcp[n1] == prefix)
- ele->k_prefmap = (KEYMAP *)NULL;
- ele->k_funcp[n1] = funct; /* easy case */
- if(funct==prefix) {
- if(pref_map!=NULL)
- ele->k_prefmap = pref_map;
- else {
- if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
- (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
- ewprintf("Out of memory");
- ele->k_funcp[c - ele->k_base] = curmap->map_default;
- return FALSE;
- }
- mp->map_num = 0;
- mp->map_max = MAPINIT;
- mp->map_default = rescan;
- ele->k_prefmap = mp;
- }
- }
- } else {
- /* this case is the splits */
- /* determine which side of the break c goes on */
- /* 0 = after break; 1 = before break */
- n2 = 1;
- for(i=0; n2 && i < n1; i++)
- n2 &= ele->k_funcp[i] != prefix;
- if(curmap->map_num >= curmap->map_max &&
- (curmap = realocmap(curmap)) == NULL) return FALSE;
- if((pfp = (PF *)malloc((unsigned)(ele->k_num - c + !n2)
- * sizeof(PF))) == NULL) {
- ewprintf("Out of memory");
- return FALSE;
- }
- ele->k_funcp[n1] = prefix;
- for(i=n1+n2; i <= ele->k_num - ele->k_base; i++)
- pfp[i-n1-n2] = ele->k_funcp[i];
- for(mep = &curmap->map_element[curmap->map_num]; mep > ele; mep--) {
- mep->k_base = (mep-1)->k_base;
- mep->k_num = (mep-1)->k_num;
- mep->k_funcp = (mep-1)->k_funcp;
- mep->k_prefmap = (mep-1)->k_prefmap;
- }
- ele->k_num = c - !n2;
- (ele+1)->k_base = c + n2;
- (ele+1)->k_funcp = pfp;
- ele += !n2;
- ele->k_prefmap = NULL;
- curmap->map_num++;
- if(pref_map == NULL) {
- if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
- (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
- ewprintf("Out of memory");
- ele->k_funcp[c - ele->k_base] = curmap->map_default;
- return FALSE;
- }
- mp->map_num = 0;
- mp->map_max = MAPINIT;
- mp->map_default = rescan;
- ele->k_prefmap = mp;
- } else ele->k_prefmap = pref_map;
- }
- }
- return TRUE;
- }
-
- /* reallocate a keymap, used above */
- static KEYMAP *realocmap(curmap)
- register KEYMAP *curmap;
- {
- register KEYMAP *mp;
- register int i;
- static VOID fixmap();
- extern int nmaps;
-
- if((mp = (KEYMAP *)malloc((unsigned)(sizeof(KEYMAP)+
- (curmap->map_max+(MAPGROW-1))*sizeof(MAP_ELEMENT)))) == NULL) {
- ewprintf("Out of memory");
- return NULL;
- }
- mp->map_num = curmap->map_num;
- mp->map_max = curmap->map_max + MAPGROW;
- mp->map_default = curmap->map_default;
- for(i=curmap->map_num; i--; ) {
- mp->map_element[i].k_base = curmap->map_element[i].k_base;
- mp->map_element[i].k_num = curmap->map_element[i].k_num;
- mp->map_element[i].k_funcp = curmap->map_element[i].k_funcp;
- mp->map_element[i].k_prefmap = curmap->map_element[i].k_prefmap;
- }
- for(i=nmaps; i--; ) {
- if(map_table[i].p_map == curmap) map_table[i].p_map = mp;
- else fixmap(curmap, mp, map_table[i].p_map);
- }
- ele = &mp->map_element[ele - &curmap->map_element[0]];
- return mp;
- }
-
- /* fix references to a reallocated keymap (recursive) */
- static VOID fixmap(curmap, mp, mt)
- register KEYMAP *mt;
- register KEYMAP *curmap;
- KEYMAP *mp;
- {
- register int i;
-
- for(i = mt->map_num; i--; ) {
- if(mt->map_element[i].k_prefmap != NULL) {
- if(mt->map_element[i].k_prefmap == curmap)
- mt->map_element[i].k_prefmap = mp;
- else fixmap(curmap, mp, mt->map_element[i].k_prefmap);
- }
- }
- }
-
- /*
- * do the input for local-set-key, global-set-key and define-key
- * then call remap to do the work.
- */
-
- static int dobind(curmap, p, unbind)
- register KEYMAP *curmap;
- char *p;
- int unbind;
- {
- PF funct;
- char prompt[80];
- char *pep;
- int c;
- int s;
- KEYMAP *pref_map = NULL;
-
- #ifndef NO_MACRO
- if(macrodef) {
- /* keystrokes arn't collected. Not hard, but pretty useless */
- /* would not work for function keys in any case */
- ewprintf("Can't rebind key in macro");
- return FALSE;
- }
- #ifndef NO_STARTUP
- if(inmacro) {
- for(s=0; s < maclcur->l_used - 1; s++) {
- if(doscan(curmap, c=CHARMASK(maclcur->l_text[s])) != prefix) {
- if(remap(curmap, c, prefix, (KEYMAP *)NULL) != TRUE) {
- return FALSE;
- }
- }
- curmap = ele->k_prefmap;
- }
- (VOID) doscan(curmap, c=maclcur->l_text[s]);
- maclcur = maclcur->l_fp;
- } else {
- #endif
- #endif
- (VOID) strcpy(prompt, p);
- pep = prompt + strlen(prompt);
- for(;;) {
- ewprintf("%s", prompt);
- pep[-1] = ' ';
- pep = keyname(pep, c = getkey(FALSE));
- if(doscan(curmap,c) != prefix) break;
- *pep++ = '-';
- *pep = '\0';
- curmap = ele->k_prefmap;
- }
- #ifndef NO_STARTUP
- }
- #endif
- if(unbind) funct = rescan;
- else {
- if ((s=eread("%s to command: ", prompt, 80, EFFUNC|EFNEW, prompt))
- != TRUE) return s;
- if (((funct = name_function(prompt)) == prefix) ?
- (pref_map = name_map(prompt)) == NULL : funct==NULL) {
- ewprintf("[No match]");
- return FALSE;
- }
- }
- return remap(curmap, c, funct, pref_map);
- }
-
- /*
- * bindkey: bind key sequence to a function in
- * the specified map. Used by excline so it can bind function keys.
- * To close to release to change calling sequence, should just pass
- * KEYMAP *curmap rather than KEYMAP **mapp.
- */
- #ifdef BINDKEY
- bindkey(mapp, fname, keys, kcount)
- KEYMAP **mapp;
- char *fname;
- KCHAR *keys;
- int kcount;
- {
- KEYMAP *curmap = *mapp;
- PF funct;
- int c;
- KEYMAP *pref_map = NULL;
-
- if(fname == NULL) funct = rescan;
- else if (((funct = name_function(fname)) == prefix) ?
- (pref_map = name_map(fname)) == NULL : funct==NULL) {
- ewprintf("[No match: %s]", fname);
- return FALSE;
- }
- while(--kcount) {
- if(doscan(curmap, c = *keys++) != prefix) {
- if(remap(curmap, c, prefix, (KEYMAP *)NULL) != TRUE)
- return FALSE;
- }
- curmap = ele->k_prefmap;
- }
- (VOID) doscan(curmap, c = *keys);
- return remap(curmap, c, funct, pref_map);
- }
- #endif
-
- /*
- * This function modifies the fundamental keyboard map.
- */
- /*ARGSUSED*/
- bindtokey(f, n)
- {
- return dobind(map_table[0].p_map, "Global set key: ", FALSE);
- }
-
- /*
- * This function modifies the current mode's keyboard map.
- */
- /*ARGSUSED*/
- localbind(f, n)
- {
- return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local set key: ",
- FALSE);
- }
-
- /*
- * This function redefines a key in any keymap.
- */
- /*ARGSUSED*/
- define_key(f, n)
- {
- static char buf[48] = "Define key map: ";
- MAPS *mp;
- char *strncat();
-
- buf[16] = '\0';
- if(eread(buf, &buf[16], 48 - 16, EFNEW) != TRUE) return FALSE;
- if((mp = name_mode(&buf[16])) == NULL) {
- ewprintf("Unknown map %s", &buf[16]);
- return FALSE;
- }
- (VOID) strncat(&buf[16], " key: ", 48-16-1);
- return dobind(mp->p_map, buf, FALSE);
- }
-
- unbindtokey(f, n)
- int f, n;
- {
- return dobind(map_table[0].p_map, "Global unset key: ", TRUE);
- }
-
- localunbind(f, n)
- int f, n;
- {
- return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local unset key: ",
- TRUE);
- }
-
- /*
- * Extended command. Call the message line
- * routine to read in the command name and apply autocompletion
- * to it. When it comes back, look the name up in the symbol table
- * and run the command if it is found.
- * Print an error if there is anything wrong.
- */
- extend(f, n)
- {
- PF funct;
- int s;
- char xname[NXNAME];
-
- if(!(f & FFARG)) s = eread("M-x ", xname, NXNAME, EFNEW|EFFUNC);
- else s = eread("%d M-x ", xname, NXNAME, EFNEW|EFFUNC, n);
- if(s != TRUE) return s;
- if((funct = name_function(xname)) != NULL) {
- #ifndef NO_MACRO
- if(macrodef) {
- LINE *lp = maclcur;
- macro[macrocount-1].m_funct = funct;
- maclcur = lp->l_bp;
- maclcur->l_fp = lp->l_fp;
- free((char *)lp);
- }
- #endif
- return (*funct)(f, n);
- }
- ewprintf("[No match]");
- return FALSE;
- }
-
- #ifndef NO_STARTUP
- /*
- * Define the commands needed to do startup-file processing.
- * This code is mostly a kludge just so we can get startup-file processing.
- *
- * If you're serious about having this code, you should rewrite it.
- * To wit:
- * It has lots of funny things in it to make the startup-file look
- * like a GNU startup file; mostly dealing with parens and semicolons.
- * This should all vanish.
- *
- * We define eval-expression because it's easy. It can make
- * *-set-key or define-key set an arbitrary key sequence, so it isn't
- * useless.
- */
-
- /*
- * evalexpr - get one line from the user, and run it.
- */
- /*ARGSUSED*/
- evalexpr(f, n)
- {
- int s;
- char exbuf[128];
-
- if ((s = ereply("Eval: ", exbuf, 128)) != TRUE)
- return s;
- return excline(exbuf);
- }
- /*
- * evalbuffer - evaluate the current buffer as line commands. Useful
- * for testing startup files.
- */
- /*ARGSUSED*/
- evalbuffer(f, n)
- {
- register LINE *lp;
- register BUFFER *bp = curbp;
- register int s;
- static char excbuf[128];
-
- for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
- if (llength(lp) >= 128) return FALSE;
- (VOID) strncpy(excbuf, ltext(lp), llength(lp));
- excbuf[llength(lp)] = '\0'; /* make sure it's terminated */
- if ((s = excline(excbuf)) != TRUE) return s;
- }
- return TRUE;
- }
- /*
- * evalfile - go get a file and evaluate it as line commands. You can
- * go get your own startup file if need be.
- */
- /*ARGSUSED*/
- evalfile(f, n)
- {
- register int s;
- char fname[NFILEN];
-
- if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
- return s;
- return load(fname);
- }
-
- /*
- * load - go load the file name we got passed.
- */
- load(fname) char *fname; {
- int s = TRUE;
- int nbytes;
- char excbuf[128];
-
- if ((fname = adjustname(fname)) == NULL)
- return FALSE; /* just to be careful */
-
- if (ffropen(fname) != FIOSUC) return FALSE;
- while ((s = ffgetline(excbuf, sizeof(excbuf)-1, &nbytes)) == FIOSUC) {
- excbuf[nbytes] = '\0';
- if (excline(excbuf) != TRUE) {
- s = FIOERR;
- ewprintf("Error loading file %s", fname);
- break;
- }
- }
- (VOID) ffclose();
- excbuf[nbytes] = '\0';
- if(s!=FIOEOF || (nbytes && excline(excbuf)!=TRUE))
- return FALSE;
- return TRUE;
- }
-
- /*
- * excline - run a line from a load file or eval-expression.
- * if FKEYS is defined, duplicate functionallity of dobind so function
- * key values don't have to fit in type char.
- */
- excline(line)
- register char *line;
- {
- register char *funcp, *argp = NULL;
- register int c;
- int status;
- int f, n;
- LINE *lp, *np;
- PF fp;
- #ifdef FKEYS
- int bind;
- KEYMAP *curmap;
- MAPS *mp;
- #define BINDARG 0 /* this arg is key to bind (local/global set key) */
- #define BINDNO 1 /* not binding or non-quoted BINDARG */
- #define BINDNEXT 2 /* next arg " (define-key) */
- #define BINDDO 3 /* already found key to bind */
- #define BINDEXT 1 /* space for trailing \0 */
- #else
- #define BINDEXT 0
- #endif
- PF name_function();
- LINE *lalloc();
- static char *skipwhite(), *parsetoken();
-
- if(macrodef || inmacro) {
- ewprintf("Not now!");
- return FALSE;
- }
-
- f = 0;
- n = 1;
- funcp = skipwhite(line);
- if (*funcp == '\0') return TRUE; /* No error on blank lines */
- line = parsetoken(funcp);
- if (*line != '\0') {
- *line++ = '\0';
- line = skipwhite(line);
- if ((*line >= '0' && *line <= '9') || *line == '-') {
- argp = line;
- line = parsetoken(line);
- }
- }
-
- if (argp != NULL) {
- f = FFARG;
- n = atoi(argp);
- }
- if((fp = name_function(funcp)) == NULL) {
- ewprintf("Unknown function: %s", funcp);
- return FALSE;
- }
- #ifdef FKEYS
- if(fp == bindtokey || fp == unbindtokey) {
- bind = BINDARG;
- curmap = map_table[0].p_map;
- } else if(fp == localbind || fp == localunbind) {
- bind = BINDARG;
- curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
- } else if(fp == define_key) bind = BINDNEXT;
- else bind = BINDNO;
- #endif
- /* Pack away all the args now... */
- if((np = lalloc(0))==FALSE) return FALSE;
- np->l_fp = np->l_bp = maclcur = np;
- while (*line != '\0') {
- argp = skipwhite(line);
- if (*argp == '\0') break;
- line = parsetoken(argp);
- if (*argp != '"') {
- if (*argp == '\'') ++argp;
- if((lp = lalloc((int)(line-argp)+BINDEXT))==NULL) {
- status = FALSE;
- goto cleanup;
- }
- bcopy(argp, ltext(lp), (int)(line-argp));
- #ifdef FKEYS
- lp->l_used--; /* don't count BINDEXT! */
- if(bind == BINDARG) bind = BINDNO;
- #endif
- } else { /* Quoted strings special */
- ++argp;
- #ifdef FKEYS
- if(bind != BINDARG) {
- #endif
- if((lp = lalloc((int)(line-argp)+BINDEXT))==NULL) {
- status = FALSE;
- goto cleanup;
- }
- lp->l_used = 0;
- #ifdef FKEYS
- } else {
- key.k_count = 0;
- }
- #endif
- while (*argp != '"' && *argp != '\0') {
- if (*argp != '\\') c = *argp++;
- else {
- switch(*++argp) {
- case 't': case 'T':
- c = CCHR('I');
- break;
- case 'n': case 'N':
- c = CCHR('J');
- break;
- case 'r': case 'R':
- c = CCHR('M');
- break;
- case 'e': case 'E':
- c = CCHR('[');
- break;
- case '^':
- /* split into two statements due to bug in OSK cpp */
- c = CHARMASK(*++argp);
- c = ISLOWER(c) ?
- CCHR(TOUPPER(c)) : CCHR(c);
- break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- c = *argp - '0';
- if(argp[1] <= '7' && argp[1] >= '0') {
- c <<= 3;
- c += *++argp - '0';
- if(argp[1] <= '7' && argp[1] >= '0') {
- c <<= 3;
- c += *++argp - '0';
- }
- }
- break;
- #ifdef FKEYS
- case 'f': case 'F':
- c = *++argp - '0';
- if(ISDIGIT(argp[1])) {
- c *= 10;
- c += *++argp - '0';
- }
- c += KFIRST;
- break;
- #endif
- default:
- c = CHARMASK(*argp);
- break;
- }
- argp++;
- }
- #ifdef FKEYS
- if(bind == BINDARG)
- key.k_chars[key.k_count++] = c;
- else
- #endif
- lp->l_text[lp->l_used++] = c;
- }
- if(*line) line++;
- }
- #ifdef FKEYS
- switch(bind) {
- case BINDARG:
- bind = BINDDO;
- break;
- case BINDNEXT:
- lp->l_text[lp->l_used] = '\0';
- if((mp = name_mode(lp->l_text)) == NULL) {
- ewprintf("No such mode: %s", lp->l_text);
- status = FALSE;
- free((char *)lp);
- goto cleanup;
- }
- curmap = mp->p_map;
- free((char *)lp);
- bind = BINDARG;
- break;
- default:
- #endif
- lp->l_fp = np->l_fp;
- lp->l_bp = np;
- np->l_fp = lp;
- np = lp;
- #ifdef FKEYS
- }
- #endif
- }
- #ifdef FKEYS
- switch(bind) {
- default:
- ewprintf("Bad args to set key");
- status = FALSE;
- break;
- case BINDDO:
- if(fp != unbindtokey && fp != localunbind) {
- lp->l_text[lp->l_used] = '\0';
- status = bindkey(&curmap, lp->l_text, key.k_chars, key.k_count);
- } else status = bindkey(&curmap, (char *)NULL, key.k_chars, key.k_count);
- break;
- case BINDNO:
- #endif
- inmacro = TRUE;
- maclcur = maclcur->l_fp;
- status = (*fp)(f, n);
- inmacro = FALSE;
- #ifdef FKEYS
- }
- #endif
- cleanup:
- lp = maclcur->l_fp;
- while(lp!=maclcur) {
- np = lp->l_fp;
- free((char *)lp);
- lp = np;
- }
- free((char *)lp);
- return status;
- }
-
- /*
- * a pair of utility functions for the above
- */
- static char *
- skipwhite(s)
- register char *s;
- {
- while(*s == ' ' || *s == '\t' || *s == ')' || *s == '(') s++;
- if (*s == ';') *s = '\0' ;
- return s;
- }
-
- static char *
- parsetoken(s)
- register char *s;
- {
- if (*s != '"') {
- while(*s && *s!=' ' && *s!='\t' && *s!=')' && *s!='(') s++;
- if(*s==';') *s='\0';
- } else
- do { /* Strings get special treatment */
- /* Beware: You can \ out the end of the string! */
- if (*s == '\\') ++s;
- } while (*++s != '"' && *s != '\0');
- return s;
- }
- #endif
- SHAR_EOF
- cat << \SHAR_EOF > file.c
- /*
- * File commands.
- */
- #include "def.h"
-
- BUFFER *findbuffer();
- VOID makename();
- VOID upmodes();
- static char *itos();
-
- /*
- * insert a file into the current buffer. Real easy - just call the
- * insertfile routine with the file name.
- */
- /*ARGSUSED*/
- fileinsert(f, n)
- {
- register int s;
- char fname[NFILEN];
-
- if ((s=ereply("Insert file: ", fname, NFILEN)) != TRUE)
- return (s);
- return insertfile(adjustname(fname), (char *) NULL);
- /* don't set buffer name */
- }
-
- /*
- * Select a file for editing.
- * Look around to see if you can find the
- * fine in another buffer; if you can find it
- * just switch to the buffer. If you cannot find
- * the file, create a new buffer, read in the
- * text, and switch to the new buffer.
- */
- /*ARGSUSED*/
- filevisit(f, n)
- {
- register BUFFER *bp;
- int s;
- char fname[NFILEN];
- char *adjf;
-
- if ((s=ereply("Find file: ", fname, NFILEN)) != TRUE)
- return s;
- adjf = adjustname(fname);
- if ((bp = findbuffer(adjf)) == NULL) return FALSE;
- curbp = bp;
- if (showbuffer(bp, curwp, WFHARD) != TRUE) return FALSE;
- if (bp->b_fname[0] == 0)
- return readin(adjf); /* Read it in. */
- return TRUE;
- }
-
- /*
- * Pop to a file in the other window. Same as last function, just
- * popbuf instead of showbuffer.
- */
- /*ARGSUSED*/
- poptofile(f, n)
- {
- register BUFFER *bp;
- register WINDOW *wp;
- int s;
- char fname[NFILEN];
- char *adjf;
-
- if ((s=ereply("Find file in other window: ", fname, NFILEN)) != TRUE)
- return s;
- adjf = adjustname(fname);
- if ((bp = findbuffer(adjf)) == NULL) return FALSE;
- if ((wp = popbuf(bp)) == NULL) return FALSE;
- curbp = bp;
- curwp = wp;
- if (bp->b_fname[0] == 0)
- return readin(adjf); /* Read it in. */
- return TRUE;
- }
-
- /*
- * given a file name, either find the buffer it uses, or create a new
- * empty buffer to put it in.
- */
- BUFFER *
- findbuffer(fname)
- char *fname;
- {
- register BUFFER *bp;
- char bname[NBUFN], *cp;
- unsigned count = 1;
-
- for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
- if (fncmp(bp->b_fname, fname) == 0)
- return bp;
- }
- makename(bname, fname); /* New buffer name. */
- cp = bname + strlen(bname);
- while(bfind(bname, FALSE) != NULL) {
- *cp = '<'; /* add "<count>" to then name */
- (VOID) strcpy(itos(cp, ++count)+1, ">");
- }
- return bfind(bname, TRUE);
- }
-
- /*
- * Put the decimal representation of num into a buffer. Hacked to be
- * faster, smaller, and less general.
- */
- static char *itos(bufp, num)
- char *bufp;
- unsigned num;
- {
- if (num >= 10) {
- bufp = itos(bufp, num/10);
- num %= 10;
- }
- *++bufp = '0' + num;
- return bufp;
- }
-
- /*
- * Read the file "fname" into the current buffer.
- * Make all of the text in the buffer go away, after checking
- * for unsaved changes. This is called by the "read" command, the
- * "visit" command, and the mainline (for "uemacs file").
- */
- readin(fname) char *fname; {
- register int status;
- register WINDOW *wp;
-
- if (bclear(curbp) != TRUE) /* Might be old. */
- return TRUE;
- status = insertfile(fname, fname) ;
- curbp->b_flag &= ~BFCHG; /* No change. */
- for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
- if (wp->w_bufp == curbp) {
- wp->w_dotp = wp->w_linep = lforw(curbp->b_linep);
- wp->w_doto = 0;
- wp->w_markp = NULL;
- wp->w_marko = 0;
- }
- }
- return status;
- }
- /*
- * insert a file in the current buffer, after dot. Set mark
- * at the end of the text inserted, point at the beginning.
- * Return a standard status. Print a summary (lines read,
- * error message) out as well. If the
- * BACKUP conditional is set, then this routine also does the read
- * end of backup processing. The BFBAK flag, if set in a buffer,
- * says that a backup should be taken. It is set when a file is
- * read in, but not on a new file (you don't need to make a backup
- * copy of nothing).
- */
- insertfile(fname, newname) char fname[], newname[]; {
- register LINE *lp1;
- register LINE *lp2;
- register WINDOW *wp;
- int nbytes;
- LINE *olp; /* Line we started at */
- int opos; /* and offset into it */
- int s, nline;
- BUFFER *bp;
- char line[NLINE];
-
- bp = curbp; /* Cheap. */
- if (newname != (char *) NULL)
- (VOID) strcpy(bp->b_fname, newname);
- if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
- goto out;
- if (s == FIOFNF) { /* File not found. */
- if (newname != NULL)
- ewprintf("(New file)");
- else ewprintf("(File not found)");
- goto out;
- }
- opos = curwp->w_doto;
- /* Open a new line, at point, and start inserting after it */
- (VOID) lnewline();
- olp = lback(curwp->w_dotp);
- if(olp == curbp->b_linep) {
- /* if at end of buffer, create a line to insert before */
- (VOID) lnewline();
- curwp->w_dotp = lback(curwp->w_dotp);
- }
- nline = 0; /* Don't count fake line at end */
- while ((s=ffgetline(line, NLINE, &nbytes)) != FIOERR) {
- switch(s) {
- case FIOSUC:
- ++nline;
- /* and continue */
- case FIOEOF: /* the last line of the file */
- if ((lp1=lalloc(nbytes)) == NULL) {
- s = FIOERR; /* Keep message on the */
- goto endoffile; /* display. */
- }
- bcopy(line, <ext(lp1)[0], nbytes);
- lineread: lp2 = lback(curwp->w_dotp);
- lp2->l_fp = lp1;
- lp1->l_fp = curwp->w_dotp;
- lp1->l_bp = lp2;
- curwp->w_dotp->l_bp = lp1;
- if(s==FIOEOF) goto endoffile;
- break;
- case FIOLONG: { /* a line to long to fit in our buffer */
- char *cp;
- char *cp2;
- int i;
-
- nbytes = 0;
- for(;;) {
- if((cp = malloc((unsigned)(nbytes + NLINE))) == NULL) {
- ewprintf("Could not allocate %d bytes",
- nbytes + NLINE);
- s = FIOERR;
- if(nbytes) free(cp2);
- goto endoffile;
- }
- if(nbytes) {
- bcopy(cp2, cp, nbytes);
- free(cp2);
- }
- bcopy(line, cp+nbytes, NLINE);
- nbytes += NLINE;
- switch(s = ffgetline(line, NLINE, &i)) {
- case FIOERR:
- free(cp);
- goto endoffile;
- case FIOLONG:
- cp2 = cp;
- break;
- case FIOEOF:
- case FIOSUC:
- if((lp1=lalloc(nbytes+i)) == NULL) {
- s = FIOERR;
- free(cp);
- goto endoffile;
- }
- bcopy(cp, <ext(lp1)[0], nbytes);
- bcopy(line, <ext(lp1)[nbytes], i);
- goto lineread;
- }
- }
- }
- default:
- ewprintf("Unknown code %d reading file", s);
- s = FIOERR;
- break;
- }
- }
- endoffile:
- (VOID) ffclose(); /* Ignore errors. */
- if (s==FIOEOF) { /* Don't zap an error. */
- if (nline == 1) ewprintf("(Read 1 line)");
- else ewprintf("(Read %d lines)", nline);
- }
- /* Set mark at the end of the text */
- curwp->w_dotp = curwp->w_markp = lback(curwp->w_dotp);
- curwp->w_marko = llength(curwp->w_markp);
- (VOID) ldelnewline();
- curwp->w_dotp = olp;
- curwp->w_doto = opos;
- if(olp == curbp->b_linep) curwp->w_dotp = lforw(olp);
- #ifndef NO_BACKUP
- if (newname != NULL)
- bp->b_flag |= BFCHG | BFBAK; /* Need a backup. */
- else bp->b_flag |= BFCHG;
- #else
- bp->b_flag |= BFCHG;
- #endif
- /* if the insert was at the end of buffer, set lp1 to the end of
- * buffer line, and lp2 to the beginning of the newly inserted
- * text. (Otherwise lp2 is set to NULL.) This is
- * used below to set pointers in other windows correctly if they
- * are also at the end of buffer.
- */
- lp1 = bp->b_linep;
- if (curwp->w_markp == lp1) {
- lp2 = curwp->w_dotp;
- } else {
- (VOID) ldelnewline(); /* delete extranious newline */
- out: lp2 = NULL;
- }
- for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
- if (wp->w_bufp == curbp) {
- wp->w_flag |= WFMODE|WFEDIT;
- if (wp != curwp && lp2 != NULL) {
- if (wp->w_dotp == lp1) wp->w_dotp = lp2;
- if (wp->w_markp == lp1) wp->w_markp = lp2;
- if (wp->w_linep == lp1) wp->w_linep = lp2;
- }
- }
- }
- return s != FIOERR; /* False if error. */
- }
-
- /*
- * Take a file name, and from it
- * fabricate a buffer name. This routine knows
- * about the syntax of file names on the target system.
- * BDC1 left scan delimiter.
- * BDC2 optional second left scan delimiter.
- * BDC3 optional right scan delimiter.
- */
- VOID
- makename(bname, fname) char bname[]; char fname[]; {
- register char *cp1;
- register char *cp2;
-
- cp1 = &fname[0];
- while (*cp1 != 0)
- ++cp1;
- --cp1; /* insure at least 1 character ! */
- #ifdef BDC2
- while (cp1!=&fname[0] && cp1[-1]!=BDC1 && cp1[-1]!=BDC2)
- --cp1;
- #else
- while (cp1!=&fname[0] && cp1[-1]!=BDC1)
- --cp1;
- #endif
- cp2 = &bname[0];
- #ifdef BDC3
- while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=BDC3)
- *cp2++ = *cp1++;
- #else
- while (cp2!=&bname[NBUFN-1] && *cp1!=0)
- *cp2++ = *cp1++;
- #endif
- *cp2 = 0;
- }
-
- /*
- * Ask for a file name, and write the
- * contents of the current buffer to that file.
- * Update the remembered file name and clear the
- * buffer changed flag. This handling of file names
- * is different from the earlier versions, and
- * is more compatable with Gosling EMACS than
- * with ITS EMACS.
- */
- /*ARGSUSED*/
- filewrite(f, n)
- {
- register int s;
- char fname[NFILEN];
- char *adjfname;
-
- if ((s=ereply("Write file: ", fname, NFILEN)) != TRUE)
- return (s);
- adjfname = adjustname(fname);
- if ((s=writeout(curbp, adjfname)) == TRUE) {
- (VOID) strcpy(curbp->b_fname, adjfname);
- #ifndef NO_BACKUP
- curbp->b_flag &= ~(BFBAK | BFCHG);
- #else
- curbp->b_flag &= ~BFCHG;
- #endif
- upmodes(curbp);
- }
- return s;
- }
-
- /*
- * Save the contents of the current buffer back into
- * its associated file.
- */
- #ifndef NO_BACKUP
- #ifndef MAKEBACKUP
- #define MAKEBACKUP TRUE
- #endif
- static int makebackup = MAKEBACKUP;
- #endif
-
- /*ARGSUSED*/
- filesave(f, n)
- {
- return buffsave(curbp);
- }
-
- /*
- * Save the contents of the buffer argument into its associated file.
- * Do nothing if there have been no changes
- * (is this a bug, or a feature). Error if there is no remembered
- * file name. If this is the first write since the read or visit,
- * then a backup copy of the file is made.
- * Allow user to select whether or not to make backup files
- * by looking at the value of makebackup.
- */
- buffsave(bp) BUFFER *bp; {
- register int s;
-
- if ((bp->b_flag&BFCHG) == 0) { /* Return, no changes. */
- ewprintf("(No changes need to be saved)");
- return TRUE;
- }
- if (bp->b_fname[0] == '\0') { /* Must have a name. */
- ewprintf("No file name");
- return (FALSE);
- }
- #ifndef NO_BACKUP
- if (makebackup && (bp->b_flag&BFBAK)) {
- s = fbackupfile(bp->b_fname);
- if (s == ABORT) /* Hard error. */
- return FALSE;
- if (s == FALSE /* Softer error. */
- && (s=eyesno("Backup error, save anyway")) != TRUE)
- return s;
- }
- #endif
- if ((s=writeout(bp, bp->b_fname)) == TRUE) {
- #ifndef NO_BACKUP
- bp->b_flag &= ~(BFCHG | BFBAK);
- #else
- bp->b_flag &= ~BFCHG;
- #endif
- upmodes(bp);
- }
- return s;
- }
-
- #ifndef NO_BACKUP
- /* Since we don't have variables (we probably should)
- * this is a command processor for changing the value of
- * the make backup flag. If no argument is given,
- * sets makebackup to true, so backups are made. If
- * an argument is given, no backup files are made when
- * saving a new version of a file. Only used when BACKUP
- * is #defined.
- */
- /*ARGSUSED*/
- makebkfile(f, n)
- {
- if(f & FFARG) makebackup = n > 0;
- else makebackup = !makebackup;
- ewprintf("Backup files %sabled", makebackup ? "en" : "dis");
- return TRUE;
- }
- #endif
-
- /*
- * This function performs the details of file
- * writing; writing the file in buffer bp to
- * file fn. Uses the file management routines
- * in the "fileio.c" package. Most of the grief
- * is checking of some sort.
- */
- writeout(bp, fn) register BUFFER *bp; char *fn; {
- register int s;
-
- if ((s=ffwopen(fn)) != FIOSUC) /* Open writes message. */
- return (FALSE);
- s = ffputbuf(bp);
- if (s == FIOSUC) { /* No write error. */
- s = ffclose();
- if (s==FIOSUC)
- ewprintf("Wrote %s", fn);
- } else /* Ignore close error */
- (VOID) ffclose(); /* if a write error. */
- return s == FIOSUC;
- }
-
- /*
- * Tag all windows for bp (all windows if bp NULL) as needing their
- * mode line updated.
- */
- VOID
- upmodes(bp) register BUFFER *bp; {
- register WINDOW *wp;
-
- for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
- if (bp == NULL || curwp->w_bufp == bp) wp->w_flag |= WFMODE;
- }
- SHAR_EOF
- # End of shell archive
- exit 0
- -------
-