[comp.sources.misc] memacs 3.8i 1 of 11

allbery@ncoast.UUCP (06/15/87)

:
#!/bin/sh
# shar+ created from directory /usr2/davidsen/emacs38i
# 13:42 on Thu Jun 11, 1987 by davidsen
echo 'x - ansi.c (text)'
sed << 'E!O!F' 's/^X//' > ansi.c
X/*
X * The routines in this file provide support for ANSI style terminals
X * over a serial line. The serial I/O services are provided by routines in
X * "termio.c". It compiles into nothing if not an ANSI device.
X */
X
X#define	termdef	1			/* don't define "term" external */
X
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if     ANSI
X
X#if	AMIGA
X#define NROW    23                      /* Screen size.                 */
X#define NCOL    77                      /* Edit if you want to.         */
X#else
X#define NROW    25                      /* Screen size.                 */
X#define NCOL    80                      /* Edit if you want to.         */
X#endif
X#define	NPAUSE	100			/* # times thru update to pause */
X#define	MARGIN	8			/* size of minimim margin and	*/
X#define	SCRSIZ	64			/* scroll size for extended lines */
X#define BEL     0x07                    /* BEL character.               */
X#define ESC     0x1B                    /* ESC character.               */
X
Xextern  int     ttopen();               /* Forward references.          */
Xextern  int     ttgetc();
Xextern  int     ttputc();
Xextern  int     ttflush();
Xextern  int     ttclose();
Xextern  int     ansimove();
Xextern  int     ansieeol();
Xextern  int     ansieeop();
Xextern  int     ansibeep();
Xextern  int     ansiopen();
Xextern	int	ansirev();
Xextern	int	ansiclose();
Xextern	int	ansikopen();
Xextern	int	ansikclose();
Xextern	int	ansicres();
X
X#if	COLOR
Xextern	int	ansifcol();
Xextern	int	ansibcol();
X
Xint	cfcolor = -1;		/* current forground color */
Xint	cbcolor = -1;		/* current background color */
X#endif
X
X/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
XTERM    term    = {
X	NROW-1,
X        NROW-1,
X        NCOL,
X        NCOL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        ansiopen,
X        ansiclose,
X	ansikopen,
X	ansikclose,
X        ttgetc,
X        ttputc,
X        ttflush,
X        ansimove,
X        ansieeol,
X        ansieeop,
X        ansibeep,
X	ansirev,
X	ansicres
X#if	COLOR
X	, ansifcol,
X	ansibcol
X#endif
X};
X
X#if	COLOR
Xansifcol(color)		/* set the current output color */
X
Xint color;	/* color to set */
X
X{
X	if (color == cfcolor)
X		return;
X	ttputc(ESC);
X	ttputc('[');
X	ansiparm(color+30);
X	ttputc('m');
X	cfcolor = color;
X}
X
Xansibcol(color)		/* set the current background color */
X
Xint color;	/* color to set */
X
X{
X	if (color == cbcolor)
X		return;
X	ttputc(ESC);
X	ttputc('[');
X	ansiparm(color+40);
X	ttputc('m');
X        cbcolor = color;
X}
X#endif
X
Xansimove(row, col)
X{
X        ttputc(ESC);
X        ttputc('[');
X        ansiparm(row+1);
X        ttputc(';');
X        ansiparm(col+1);
X        ttputc('H');
X}
X
Xansieeol()
X{
X        ttputc(ESC);
X        ttputc('[');
X        ttputc('K');
X}
X
Xansieeop()
X{
X#if	COLOR
X	ansifcol(gfcolor);
X	ansibcol(gbcolor);
X#endif
X        ttputc(ESC);
X        ttputc('[');
X        ttputc('J');
X}
X
Xansirev(state)		/* change reverse video state */
X
Xint state;	/* TRUE = reverse, FALSE = normal */
X
X{
X#if	COLOR
X	int ftmp, btmp;		/* temporaries for colors */
X#endif
X
X	ttputc(ESC);
X	ttputc('[');
X	ttputc(state ? '7': '0');
X	ttputc('m');
X#if	COLOR
X	if (state == FALSE) {
X		ftmp = cfcolor;
X		btmp = cbcolor;
X		cfcolor = -1;
X		cbcolor = -1;
X		ansifcol(ftmp);
X		ansibcol(btmp);
X	}
X#endif
X}
X
Xansicres()	/* change screen resolution */
X
X{
X	return(TRUE);
X}
X
Xspal(dummy)		/* change pallette settings */
X
X{
X	/* none for now */
X}
X
Xansibeep()
X{
X        ttputc(BEL);
X        ttflush();
X}
X
Xansiparm(n)
Xregister int    n;
X{
X        register int q,r;
X
X        q = n/10;
X        if (q != 0) {
X		r = q/10;
X		if (r != 0) {
X			ttputc((r%10)+'0');
X		}
X		ttputc((q%10) + '0');
X        }
X        ttputc((n%10) + '0');
X}
X
Xansiopen()
X{
X#if     V7 | USG | BSD
X        register char *cp;
X        char *getenv();
X
X        if ((cp = getenv("TERM")) == NULL) {
X                puts("Shell variable TERM not defined!");
X                exit(1);
X        }
X        if (strcmp(cp, "vt100") != 0) {
X                puts("Terminal type not 'vt100'!");
X                exit(1);
X        }
X#endif
X	strcpy(sres, "NORMAL");
X	revexist = TRUE;
X        ttopen();
X}
X
Xansiclose()
X
X{
X#if	COLOR
X	ansifcol(7);
X	ansibcol(0);
X#endif
X	ttclose();
X}
X
Xansikopen()	/* open the keyboard (a noop here) */
X
X{
X}
X
Xansikclose()	/* close the keyboard (a noop here) */
X
X{
X}
X
X#if	FLABEL
Xfnclabel(f, n)		/* label a function key */
X
Xint f,n;	/* default flag, numeric argument [unused] */
X
X{
X	/* on machines with no function keys...don't bother */
X	return(TRUE);
X}
X#endif
X#else
Xansihello()
X{
X}
X#endif
E!O!F
newsize=`wc -c < ansi.c`
if [ $newsize -ne 4489 ]
then echo "File ansi.c was $newsize bytes, 4489 expected"
fi
echo 'x - basic.c (text)'
sed << 'E!O!F' 's/^X//' > basic.c
X/*
X * The routines in this file move the cursor around on the screen. They
X * compute a new value for the cursor, then adjust ".". The display code
X * always updates the cursor location, so only moves between lines, or
X * functions that adjust the top line in the window and invalidate the
X * framing, are hard.
X */
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X/*
X * Move the cursor to the
X * beginning of the current line.
X * Trivial.
X */
Xgotobol(f, n)
X{
X        curwp->w_doto  = 0;
X        return (TRUE);
X}
X
X/*
X * Move the cursor backwards by "n" characters. If "n" is less than zero call
X * "forwchar" to actually do the move. Otherwise compute the new cursor
X * location. Error if you try and move out of the buffer. Set the flag if the
X * line pointer for dot changes.
X */
Xbackchar(f, n)
Xregister int    n;
X{
X        register LINE   *lp;
X
X        if (n < 0)
X                return (forwchar(f, -n));
X        while (n--) {
X                if (curwp->w_doto == 0) {
X                        if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
X                                return (FALSE);
X                        curwp->w_dotp  = lp;
X                        curwp->w_doto  = llength(lp);
X                        curwp->w_flag |= WFMOVE;
X                } else
X                        curwp->w_doto--;
X        }
X        return (TRUE);
X}
X
X/*
X * Move the cursor to the end of the current line. Trivial. No errors.
X */
Xgotoeol(f, n)
X{
X        curwp->w_doto  = llength(curwp->w_dotp);
X        return (TRUE);
X}
X
X/*
X * Move the cursor forwards by "n" characters. If "n" is less than zero call
X * "backchar" to actually do the move. Otherwise compute the new cursor
X * location, and move ".". Error if you try and move off the end of the
X * buffer. Set the flag if the line pointer for dot changes.
X */
Xforwchar(f, n)
Xregister int    n;
X{
X        if (n < 0)
X                return (backchar(f, -n));
X        while (n--) {
X                if (curwp->w_doto == llength(curwp->w_dotp)) {
X                        if (curwp->w_dotp == curbp->b_linep)
X                                return (FALSE);
X                        curwp->w_dotp  = lforw(curwp->w_dotp);
X                        curwp->w_doto  = 0;
X                        curwp->w_flag |= WFMOVE;
X                } else
X                        curwp->w_doto++;
X        }
X        return (TRUE);
X}
X
Xgotoline(f, n)		/* move to a particular line.
X			   argument (n) must be a positive integer for
X			   this to actually do anything		*/
X
X{
X	register int status;	/* status return */
X	char arg[NSTRING];	/* buffer to hold argument */
X
X	/* get an argument if one doesnt exist */
X	if (f == FALSE) {
X		if ((status = mlreply("Line to GOTO: ", arg, "")) != TRUE) {
X			mlwrite("[Aborted]");
X			return(status);
X		}
X		n = atoi(arg);
X	}
X
X	if (n < 1)		/* if a bogus argument...then leave */
X		return(FALSE);
X
X	/* first, we go to the start of the buffer */
X        curwp->w_dotp  = lforw(curbp->b_linep);
X        curwp->w_doto  = 0;
X	return(forwline(f, n-1));
X}
X
X/*
X * Goto the beginning of the buffer. Massive adjustment of dot. This is
X * considered to be hard motion; it really isn't if the original value of dot
X * is the same as the new value of dot. Normally bound to "M-<".
X */
Xgotobob(f, n)
X{
X        curwp->w_dotp  = lforw(curbp->b_linep);
X        curwp->w_doto  = 0;
X        curwp->w_flag |= WFHARD;
X        return (TRUE);
X}
X
X/*
X * Move to the end of the buffer. Dot is always put at the end of the file
X * (ZJ). The standard screen code does most of the hard parts of update.
X * Bound to "M->".
X */
Xgotoeob(f, n)
X{
X        curwp->w_dotp  = curbp->b_linep;
X        curwp->w_doto  = 0;
X        curwp->w_flag |= WFHARD;
X        return (TRUE);
X}
X
X/*
X * Move forward by full lines. If the number of lines to move is less than
X * zero, call the backward line function to actually do it. The last command
X * controls how the goal column is set. Bound to "C-N". No errors are
X * possible.
X */
Xforwline(f, n)
X{
X        register LINE   *dlp;
X
X        if (n < 0)
X                return (backline(f, -n));
X
X	/* if we are on the last line as we start....fail the command */
X	if (curwp->w_dotp == curbp->b_linep)
X		return(FALSE);
X
X	/* if the last command was not note a line move,
X	   reset the goal column */
X        if ((lastflag&CFCPCN) == 0)
X                curgoal = getccol(FALSE);
X
X	/* flag this command as a line move */
X        thisflag |= CFCPCN;
X
X	/* and move the point down */
X        dlp = curwp->w_dotp;
X        while (n-- && dlp!=curbp->b_linep)
X                dlp = lforw(dlp);
X
X	/* reseting the current position */
X        curwp->w_dotp  = dlp;
X        curwp->w_doto  = getgoal(dlp);
X        curwp->w_flag |= WFMOVE;
X        return (TRUE);
X}
X
X/*
X * This function is like "forwline", but goes backwards. The scheme is exactly
X * the same. Check for arguments that are less than zero and call your
X * alternate. Figure out the new line and call "movedot" to perform the
X * motion. No errors are possible. Bound to "C-P".
X */
Xbackline(f, n)
X{
X        register LINE   *dlp;
X
X        if (n < 0)
X                return (forwline(f, -n));
X
X
X	/* if we are on the last line as we start....fail the command */
X	if (lback(curwp->w_dotp) == curbp->b_linep)
X		return(FALSE);
X
X	/* if the last command was not note a line move,
X	   reset the goal column */
X        if ((lastflag&CFCPCN) == 0)
X                curgoal = getccol(FALSE);
X
X	/* flag this command as a line move */
X        thisflag |= CFCPCN;
X
X	/* and move the point up */
X        dlp = curwp->w_dotp;
X        while (n-- && lback(dlp)!=curbp->b_linep)
X                dlp = lback(dlp);
X
X	/* reseting the current position */
X        curwp->w_dotp  = dlp;
X        curwp->w_doto  = getgoal(dlp);
X        curwp->w_flag |= WFMOVE;
X        return (TRUE);
X}
X
X#if	WORDPRO
Xgotobop(f, n)	/* go back to the beginning of the current paragraph
X		   here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
X		   combination to delimit the beginning of a paragraph	*/
X
Xint f, n;	/* default Flag & Numeric argument */
X
X{
X	register int suc;	/* success of last backchar */
X
X	if (n < 0)	/* the other way...*/
X		return(gotoeop(f, -n));
X
X	while (n-- > 0) {	/* for each one asked for */
X
X		/* first scan back until we are in a word */
X		suc = backchar(FALSE, 1);
X		while (!inword() && suc)
X			suc = backchar(FALSE, 1);
X		curwp->w_doto = 0;	/* and go to the B-O-Line */
X
X		/* and scan back until we hit a <NL><NL> or <NL><TAB>
X		   or a <NL><SPACE>					*/
X		while (lback(curwp->w_dotp) != curbp->b_linep)
X			if (llength(curwp->w_dotp) != 0 &&
X			    lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
X			    lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
X				curwp->w_dotp = lback(curwp->w_dotp);
X			else
X				break;
X
X		/* and then forward until we are in a word */
X		suc = forwchar(FALSE, 1);
X		while (suc && !inword())
X			suc = forwchar(FALSE, 1);
X	}
X	curwp->w_flag |= WFMOVE;	/* force screen update */
X	return(TRUE);
X}
X
Xgotoeop(f, n)	/* go forword to the end of the current paragraph
X		   here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
X		   combination to delimit the beginning of a paragraph	*/
X
Xint f, n;	/* default Flag & Numeric argument */
X
X{
X	register int suc;	/* success of last backchar */
X
X	if (n < 0)	/* the other way...*/
X		return(gotobop(f, -n));
X
X	while (n-- > 0) {	/* for each one asked for */
X
X		/* first scan forward until we are in a word */
X		suc = forwchar(FALSE, 1);
X		while (!inword() && suc)
X			suc = forwchar(FALSE, 1);
X		curwp->w_doto = 0;	/* and go to the B-O-Line */
X		if (suc)	/* of next line if not at EOF */
X			curwp->w_dotp = lforw(curwp->w_dotp);
X
X		/* and scan forword until we hit a <NL><NL> or <NL><TAB>
X		   or a <NL><SPACE>					*/
X		while (curwp->w_dotp != curbp->b_linep) {
X			if (llength(curwp->w_dotp) != 0 &&
X			    lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
X			    lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
X				curwp->w_dotp = lforw(curwp->w_dotp);
X			else
X				break;
X		}
X
X		/* and then backward until we are in a word */
X		suc = backchar(FALSE, 1);
X		while (suc && !inword()) {
X			suc = backchar(FALSE, 1);
X		}
X		curwp->w_doto = llength(curwp->w_dotp);	/* and to the EOL */
X	}
X	curwp->w_flag |= WFMOVE;	/* force screen update */
X	return(TRUE);
X}
X#endif
X
X/*
X * This routine, given a pointer to a LINE, and the current cursor goal
X * column, return the best choice for the offset. The offset is returned.
X * Used by "C-N" and "C-P".
X */
Xgetgoal(dlp)
Xregister LINE   *dlp;
X{
X        register int    c;
X        register int    col;
X        register int    newcol;
X        register int    dbo;
X
X        col = 0;
X        dbo = 0;
X        while (dbo != llength(dlp)) {
X                c = lgetc(dlp, dbo);
X                newcol = col;
X                if (c == '\t')
X                        newcol |= 0x07;
X                else if (c<0x20 || c==0x7F)
X                        ++newcol;
X                ++newcol;
X                if (newcol > curgoal)
X                        break;
X                col = newcol;
X                ++dbo;
X        }
X        return (dbo);
X}
X
X/*
X * Scroll forward by a specified number of lines, or by a full page if no
X * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
X * the overlap; this value is the default overlap value in ITS EMACS. Because
X * this zaps the top line in the display window, we have to do a hard update.
X */
Xforwpage(f, n)
Xregister int    n;
X{
X        register LINE   *lp;
X
X        if (f == FALSE) {
X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
X                if (n <= 0)                     /* Forget the overlap   */
X                        n = 1;                  /* if tiny window.      */
X        } else if (n < 0)
X                return (backpage(f, -n));
X#if     CVMVAS
X        else                                    /* Convert from pages   */
X                n *= curwp->w_ntrows;           /* to lines.            */
X#endif
X        lp = curwp->w_linep;
X        while (n-- && lp!=curbp->b_linep)
X                lp = lforw(lp);
X        curwp->w_linep = lp;
X        curwp->w_dotp  = lp;
X        curwp->w_doto  = 0;
X        curwp->w_flag |= WFHARD;
X        return (TRUE);
X}
X
X/*
X * This command is like "forwpage", but it goes backwards. The "2", like
X * above, is the overlap between the two windows. The value is from the ITS
X * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
X * reason.
X */
Xbackpage(f, n)
Xregister int    n;
X{
X        register LINE   *lp;
X
X        if (f == FALSE) {
X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
X                if (n <= 0)                     /* Don't blow up if the */
X                        n = 1;                  /* window is tiny.      */
X        } else if (n < 0)
X                return (forwpage(f, -n));
X#if     CVMVAS
X        else                                    /* Convert from pages   */
X                n *= curwp->w_ntrows;           /* to lines.            */
X#endif
X        lp = curwp->w_linep;
X        while (n-- && lback(lp)!=curbp->b_linep)
X                lp = lback(lp);
X        curwp->w_linep = lp;
X        curwp->w_dotp  = lp;
X        curwp->w_doto  = 0;
X        curwp->w_flag |= WFHARD;
X        return (TRUE);
X}
X
X/*
X * Set the mark in the current window to the value of "." in the window. No
X * errors are possible. Bound to "M-.".
X */
Xsetmark(f, n)
X{
X        curwp->w_markp = curwp->w_dotp;
X        curwp->w_marko = curwp->w_doto;
X        mlwrite("[Mark set]");
X        return (TRUE);
X}
X
X/*
X * Swap the values of "." and "mark" in the current window. This is pretty
X * easy, bacause all of the hard work gets done by the standard routine
X * that moves the mark about. The only possible error is "no mark". Bound to
X * "C-X C-X".
X */
Xswapmark(f, n)
X{
X        register LINE   *odotp;
X        register int    odoto;
X
X        if (curwp->w_markp == NULL) {
X                mlwrite("No mark in this window");
X                return (FALSE);
X        }
X        odotp = curwp->w_dotp;
X        odoto = curwp->w_doto;
X        curwp->w_dotp  = curwp->w_markp;
X        curwp->w_doto  = curwp->w_marko;
X        curwp->w_markp = odotp;
X        curwp->w_marko = odoto;
X        curwp->w_flag |= WFMOVE;
X        return (TRUE);
X}
E!O!F
newsize=`wc -c < basic.c`
if [ $newsize -ne 12175 ]
then echo "File basic.c was $newsize bytes, 12175 expected"
fi
echo 'x - bind.c (text)'
sed << 'E!O!F' 's/^X//' > bind.c
X/*	This file is for functions having to do with key bindings,
X	descriptions, help commands and startup file.
X
X	written 11-feb-86 by Daniel Lawrence
X								*/
X
X#include	<stdio.h>
X#include	"estruct.h"
X#include	"edef.h"
X#include	"epath.h"
X
Xextern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */
X
Xdeskey(f, n)	/* describe the command for a certain key */
X
X{
X	register int c;		/* command character to describe */
X	register char *ptr;	/* string pointer to scan output strings */
X	register KEYTAB *ktp;	/* pointer into the command table */
X	register int found;	/* matched command flag */
X	register NBIND *nptr;	/* pointer into the name binding table */
X	char outseq[80];	/* output buffer for command sequence */
X
X	/* prompt the user to type us a key to describe */
X	mlwrite(": describe-key ");
X
X	/* get the command sequence to describe */
X	c = getckey(FALSE);			/* get a command sequence */
X
X	/* change it to something we can print as well */
X	cmdstr(c, &outseq[0]);
X
X	/* and dump it out */
X	if (discmd) {
X		ptr = &outseq[0];
X		while (*ptr)
X			TTputc(*ptr++);
X		TTputc(' ');		/* space it out */
X	}
X
X	/* find the right ->function */
X	ktp = &keytab[0];
X	found = FALSE;
X	while (ktp->k_fp != NULL) {
X		if (ktp->k_code == c) {
X			found = TRUE;
X			break;
X		}
X		++ktp;
X	}
X
X	if (!found)
X		strcpy(outseq,"Not Bound");
X	else {
X		/* match it against the name binding table */
X		nptr = &names[0];
X		strcpy(outseq,"[Bad binding]");
X		while (nptr->n_func != NULL) {
X			if (nptr->n_func == ktp->k_fp) {
X				strcpy(outseq, nptr->n_name);
X				break;
X			}
X			++nptr;
X		}
X	}
X
X	/* output the command sequence */
X	ptr = &outseq[0];
X	while (*ptr)
X		TTputc(*ptr++);
X}
X
Xcmdstr(c, seq)	/* change a key command to a string we can print out */
X
Xint c;		/* sequence to translate */
Xchar *seq;	/* destination string for sequence */
X
X{
X	char *ptr;	/* pointer into current position in sequence */
X
X	ptr = seq;
X
X	/* apply meta sequence if needed */
X	if (c & META) {
X		*ptr++ = 'M';
X		*ptr++ = '-';
X	}
X
X	/* apply ^X sequence if needed */
X	if (c & CTLX) {
X		*ptr++ = '^';
X		*ptr++ = 'X';
X	}
X
X	/* apply SPEC sequence if needed */
X	if (c & SPEC) {
X		*ptr++ = 'F';
X		*ptr++ = 'N';
X	}
X
X	/* apply control sequence if needed */
X	if (c & CTRL) {
X		*ptr++ = '^';
X	}
X
X	c = c & 255;	/* strip the prefixes */
X
X	/* and output the final sequence */
X
X	*ptr++ = c;
X	*ptr = 0;	/* terminate the string */
X}
X
Xhelp(f, n)	/* give me some help!!!!
X		   bring up a fake buffer and read the help file
X		   into it with view mode			*/
X{
X	register WINDOW *wp;	/* scaning pointer to windows */
X	register BUFFER *bp;	/* buffer pointer to help */
X	char *fname;		/* ptr to file returned by flook() */
X
X	/* first check if we are already here */
X	bp = bfind("emacs.hlp", FALSE, BFINVS);
X
X	if (bp == NULL) {
X		fname = flook(pathname[1], FALSE);
X		if (fname == NULL) {
X			mlwrite("[Help file is not online]");
X			return(FALSE);
X		}
X	}
X
X	/* split the current window to make room for the help stuff */
X	if (splitwind(FALSE, 1) == FALSE)
X			return(FALSE);
X
X	if (bp == NULL) {
X		/* and read the stuff in */
X		if (getfile(fname, FALSE) == FALSE)
X			return(FALSE);
X	} else
X		swbuffer(bp);
X
X	/* make this window in VIEW mode, update all mode lines */
X	curwp->w_bufp->b_mode |= MDVIEW;
X	curwp->w_bufp->b_flag |= BFINVS;
X	wp = wheadp;
X	while (wp != NULL) {
X		wp->w_flag |= WFMODE;
X		wp = wp->w_wndp;
X	}
X	return(TRUE);
X}
X
Xint (*fncmatch(fname))() /* match fname to a function in the names table
X			    and return any match or NULL if none		*/
X
Xchar *fname;	/* name to attempt to match */
X
X{
X	register NBIND *ffp;	/* pointer to entry in name binding table */
X
X	/* scan through the table, returning any match */
X	ffp = &names[0];
X	while (ffp->n_func != NULL) {
X		if (strcmp(fname, ffp->n_name) == 0)
X			return(ffp->n_func);
X		++ffp;
X	}
X	return(NULL);
X}
X
X/* bindtokey:	add a new key to the key binding table		*/
X
Xbindtokey(f, n)
X
Xint f, n;	/* command arguments [IGNORED] */
X
X{
X	register unsigned int c;/* command key to bind */
X	register (*kfunc)();	/* ptr to the requexted function to bind to */
X	register char *ptr;	/* ptr to dump out input key string */
X	register KEYTAB *ktp;	/* pointer into the command table */
X	register int found;	/* matched command flag */
X	char outseq[80];	/* output buffer for keystroke sequence */
X	int (*getname())();
X
X	/* prompt the user to type in a key to bind */
X	mlwrite(": bind-to-key ");
X
X	/* get the function name to bind it to */
X	kfunc = getname();
X	if (kfunc == NULL) {
X		mlwrite("[No such function]");
X		return(FALSE);
X	}
X	if (discmd) {
X		TTputc(' ');		/* space it out */
X		TTflush();
X	}
X
X	/* get the command sequence to bind */
X	c = getckey((kfunc == meta) || (kfunc == cex) ||
X	            (kfunc == unarg) || (kfunc == ctrlg));
X
X	/* change it to something we can print as well */
X	cmdstr(c, &outseq[0]);
X
X	/* and dump it out */
X	if (discmd) {
X		ptr = &outseq[0];
X		while (*ptr)
X			TTputc(*ptr++);
X	}
X
X	/* if the function is a prefix key */
X	if (kfunc == meta || kfunc == cex ||
X	    kfunc == unarg || kfunc == ctrlg) {
X
X		/* search for an existing binding for the prefix key */
X		ktp = &keytab[0];
X		found = FALSE;
X		while (ktp->k_fp != NULL) {
X			if (ktp->k_fp == kfunc)
X				unbindchar(ktp->k_code);
X			++ktp;
X		}
X
X		/* reset the appropriate global prefix variable */
X		if (kfunc == meta)
X			metac = c;
X		if (kfunc == cex)
X			ctlxc = c;
X		if (kfunc == unarg)
X			reptc = c;
X		if (kfunc == ctrlg)
X			abortc = c;
X	}
X
X	/* search the table to see if it exists */
X	ktp = &keytab[0];
X	found = FALSE;
X	while (ktp->k_fp != NULL) {
X		if (ktp->k_code == c) {
X			found = TRUE;
X			break;
X		}
X		++ktp;
X	}
X
X	if (found) {	/* it exists, just change it then */
X		ktp->k_fp = kfunc;
X	} else {	/* otherwise we need to add it to the end */
X		/* if we run out of binding room, bitch */
X		if (ktp >= &keytab[NBINDS]) {
X			mlwrite("Binding table FULL!");
X			return(FALSE);
X		}
X
X		ktp->k_code = c;	/* add keycode */
X		ktp->k_fp = kfunc;	/* and the function pointer */
X		++ktp;			/* and make sure the next is null */
X		ktp->k_code = 0;
X		ktp->k_fp = NULL;
X	}
X	return(TRUE);
X}
X
X/* unbindkey:	delete a key from the key binding table	*/
X
Xunbindkey(f, n)
X
Xint f, n;	/* command arguments [IGNORED] */
X
X{
X	register int c;		/* command key to unbind */
X	register char *ptr;	/* ptr to dump out input key string */
X	char outseq[80];	/* output buffer for keystroke sequence */
X
X	/* prompt the user to type in a key to unbind */
X	mlwrite(": unbind-key ");
X
X	/* get the command sequence to unbind */
X	c = getckey(FALSE);		/* get a command sequence */
X
X	/* change it to something we can print as well */
X	cmdstr(c, &outseq[0]);
X
X	/* and dump it out */
X	if (discmd) {
X		ptr = &outseq[0];
X		while (*ptr)
X			TTputc(*ptr++);
X	}
X
X	/* if it isn't bound, bitch */
X	if (unbindchar(c) == FALSE) {
X		mlwrite("[Key not bound]");
X		return(FALSE);
X	}
X	return(TRUE);
X}
X
Xunbindchar(c)
X
Xint c;		/* command key to unbind */
X
X{
X	register KEYTAB *ktp;	/* pointer into the command table */
X	register KEYTAB *sktp;	/* saved pointer into the command table */
X	register int found;	/* matched command flag */
X
X	/* search the table to see if the key exists */
X	ktp = &keytab[0];
X	found = FALSE;
X	while (ktp->k_fp != NULL) {
X		if (ktp->k_code == c) {
X			found = TRUE;
X			break;
X		}
X		++ktp;
X	}
X
X	/* if it isn't bound, bitch */
X	if (!found)
X		return(FALSE);
X
X	/* save the pointer and scan to the end of the table */
X	sktp = ktp;
X	while (ktp->k_fp != NULL)
X		++ktp;
X	--ktp;		/* backup to the last legit entry */
X
X	/* copy the last entry to the current one */
X	sktp->k_code = ktp->k_code;
X	sktp->k_fp   = ktp->k_fp;
X
X	/* null out the last one */
X	ktp->k_code = 0;
X	ktp->k_fp = NULL;
X	return(TRUE);
X}
X
Xdesbind(f, n)	/* describe bindings
X		   bring up a fake buffer and list the key bindings
X		   into it with view mode			*/
X
X#if	APROP
X{
X	buildlist(TRUE, "");
X}
X
Xapro(f, n)	/* Apropos (List functions that match a substring) */
X
X{
X	char mstring[NSTRING];	/* string to match cmd names to */
X	int status;		/* status return */
X
X	status = mlreply("Apropos string: ", mstring, NSTRING - 1);
X	if (status != TRUE)
X		return(status);
X
X	return(buildlist(FALSE, mstring));
X}
X
Xbuildlist(type, mstring)  /* build a binding list (limited or full) */
X
Xint type;	/* true = full list,   false = partial list */
Xchar *mstring;	/* match string if a partial list */
X
X#endif
X{
X#if	ST520 & LATTICE
X#define	register		
X#endif
X	register WINDOW *wp;	/* scanning pointer to windows */
X	register KEYTAB *ktp;	/* pointer into the command table */
X	register NBIND *nptr;	/* pointer into the name binding table */
X	register BUFFER *bp;	/* buffer to put binding list into */
X	char *strp;		/* pointer int string to send */
X	int cpos;		/* current position to use in outseq */
X	char outseq[80];	/* output buffer for keystroke sequence */
X
X	/* split the current window to make room for the binding list */
X	if (splitwind(FALSE, 1) == FALSE)
X			return(FALSE);
X
X	/* and get a buffer for it */
X	bp = bfind("Binding list", TRUE, 0);
X	if (bp == NULL || bclear(bp) == FALSE) {
X		mlwrite("Can not display binding list");
X		return(FALSE);
X	}
X
X	/* let us know this is in progress */
X	mlwrite("[Building binding list]");
X
X	/* disconect the current buffer */
X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
X                curbp->b_dotp  = curwp->w_dotp;
X                curbp->b_doto  = curwp->w_doto;
X                curbp->b_markp = curwp->w_markp;
X                curbp->b_marko = curwp->w_marko;
X        }
X
X	/* connect the current window to this buffer */
X	curbp = bp;	/* make this buffer current in current window */
X	bp->b_mode = 0;		/* no modes active in binding list */
X	bp->b_nwnd++;		/* mark us as more in use */
X	wp = curwp;
X	wp->w_bufp = bp;
X	wp->w_linep = bp->b_linep;
X	wp->w_flag = WFHARD|WFFORCE;
X	wp->w_dotp = bp->b_dotp;
X	wp->w_doto = bp->b_doto;
X	wp->w_markp = NULL;
X	wp->w_marko = 0;
X
X	/* build the contents of this window, inserting it line by line */
X	nptr = &names[0];
X	while (nptr->n_func != NULL) {
X
X		/* add in the command name */
X		strcpy(outseq, nptr->n_name);
X		cpos = strlen(outseq);
X		
X#if	APROP
X		/* if we are executing an apropos command..... */
X		if (type == FALSE &&
X		    /* and current string doesn't include the search string */
X		    strinc(outseq, mstring) == FALSE)
X			goto fail;
X#endif
X		/* search down any keys bound to this */
X		ktp = &keytab[0];
X		while (ktp->k_fp != NULL) {
X			if (ktp->k_fp == nptr->n_func) {
X				/* padd out some spaces */
X				while (cpos < 25)
X					outseq[cpos++] = ' ';
X
X				/* add in the command sequence */
X				cmdstr(ktp->k_code, &outseq[cpos]);
X				while (outseq[cpos] != 0)
X					++cpos;
X
X				/* and add it as a line into the buffer */
X				strp = &outseq[0];
X				while (*strp != 0)
X					linsert(1, *strp++);
X				lnewline();
X
X				cpos = 0;	/* and clear the line */
X			}
X			++ktp;
X		}
X
X		/* if no key was bound, we need to dump it anyway */
X		if (cpos > 0) {
X			outseq[cpos] = 0;
X			strp = &outseq[0];
X			while (*strp != 0)
X				linsert(1, *strp++);
X			lnewline();
X		}
X
Xfail:		/* and on to the next name */
X		++nptr;
X	}
X
X	curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
X	curbp->b_flag &= ~BFCHG;	/* don't flag this as a change */
X	wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */
X	wp->w_doto = 0;
X	wp = wheadp;			/* and update ALL mode lines */
X	while (wp != NULL) {
X		wp->w_flag |= WFMODE;
X		wp = wp->w_wndp;
X	}
X	mlwrite("");	/* clear the mode line */
X	return(TRUE);
X}
X
X#if	APROP
Xstrinc(source, sub)	/* does source include sub? */
X
Xchar *source;	/* string to search in */
Xchar *sub;	/* substring to look for */
X
X{
X	char *sp;	/* ptr into source */
X	char *nxtsp;	/* next ptr into source */
X	char *tp;	/* ptr into substring */
X
X	/* for each character in the source string */
X	sp = source;
X	while (*sp) {
X		tp = sub;
X		nxtsp = sp;
X
X		/* is the substring here? */
X		while (*tp) {
X			if (*nxtsp++ != *tp)
X				break;
X			else
X				tp++;
X		}
X
X		/* yes, return a success */
X		if (*tp == 0)
X			return(TRUE);
X
X		/* no, onward */
X		sp++;
X	}
X	return(FALSE);
X}
X#endif
X
X/* get a command key sequence from the keyboard	*/
X
Xunsigned int getckey(mflag)
X
Xint mflag;	/* going for a meta sequence? */
X
X{
X	register unsigned int c;	/* character fetched */
X#if	MSC
X	register unsigned char *tp;	/* pointer into the token */
X#else
X	register char *tp;		/* pointer into the token */
X#endif
X	char tok[NSTRING];		/* command incoming */
X
X	/* check to see if we are executing a command line */
X	if (clexec) {
X		macarg(tok);	/* get the next token */
X
X		/* parse it up */
X		tp = &tok[0];
X		c = 0;
X
X		/* first, the META prefix */
X		if (*tp == 'M' && *(tp+1) == '-') {
X			c = META;
X			tp += 2;
X		}
X
X		/* next the function prefix */
X		if (*tp == 'F' && *(tp+1) == 'N') {
X			c |= SPEC;
X			tp += 2;
X		}
X
X		/* control-x as well... */
X		if (*tp == '^' && *(tp+1) == 'X') {
X			c |= CTLX;
X			tp += 2;
X		}
X
X		/* a control char? */
X		if (*tp == '^' && *(tp+1) != 0) {
X			c |= CTRL;
X			++tp;
X		}
X
X		/* make sure we are not lower case (not with function keys)*/
X		if (c >= 'a' && c <= 'z' && !(c & SPEC))
X			c -= 32;
X
X		/* the final sequence... */
X		c |= *tp;
X
X		return(c);
X	}
X
X	/* or the normal way */
X	if (mflag)
X		c = get1key();
X	else
X		c = getcmd();
X	return(c);
X}
X
X/* execute the startup file */
X
Xstartup(sfname)
X
Xchar *sfname;	/* name of startup file (null if default) */
X
X{
X	char *fname;	/* resulting file name to execute */
X
X	/* look up the startup file */
X	if (*sfname != 0)
X		fname = flook(sfname, TRUE);
X	else
X		fname = flook(pathname[0], TRUE);
X
X	/* if it isn't around, don't sweat it */
X	if (fname == NULL)
X		return(TRUE);
X
X	/* otherwise, execute the sucker */
X	return(dofile(fname));
X}
X
X/*	Look up the existance of a file along the normal or PATH
X	environment variable. Look first in the HOME directory if
X	asked and possible
X*/
X
Xchar *flook(fname, hflag)
X
Xchar *fname;	/* base file name to search for */
Xint hflag;	/* Look in the HOME environment variable first? */
X
X{
X	register char *home;	/* path to home directory */
X	register char *path;	/* environmental PATH variable */
X	register char *sp;	/* pointer into path spec */
X	register int i;		/* index */
X	register int status;	/* return status */
X	static char fspec[NSTRING];	/* full path spec to search */
X	char *getenv();
X
X#if	((MSDOS) & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
X
X	if (hflag) {
X		home = getenv("HOME");
X		if (home != NULL) {
X			/* build home dir file spec */
X			strcpy(fspec, home);
X			strcat(fspec, "/");
X			strcat(fspec, fname);
X
X			/* and try it out */
X			status = ffropen(fspec);
X			if (status == FIOSUC) {
X				ffclose();
X				return(fspec);
X			}
X		}
X	}
X
X	/* get the PATH variable */
X	path = getenv("PATH");
X	if (path != NULL)
X		while (*path) {
X
X			/* build next possible file spec */
X			sp = fspec;
X			while (*path && (*path != PATHCHR))
X				*sp++ = *path++;
X			*sp++ = '/';
X			*sp = 0;
X			strcat(fspec, fname);
X
X			/* and try it out */
X			status = ffropen(fspec);
X			if (status == FIOSUC) {
X				ffclose();
X				return(fspec);
X			}
X
X			if (*path == PATHCHR)
X				++path;
X		}
X#endif
X
X	/* look it up via the old table method */
X	for (i=2; i < NPNAMES; i++) {
X		strcpy(fspec, pathname[i]);
X		strcat(fspec, fname);
X
X		/* and try it out */
X		status = ffropen(fspec);
X		if (status == FIOSUC) {
X			ffclose();
X			return(fspec);
X		}
X	}
X
X	return(NULL);	/* no such luck */
X}
X
E!O!F
newsize=`wc -c < bind.c`
if [ $newsize -ne 15191 ]
then echo "File bind.c was $newsize bytes, 15191 expected"
fi
echo 'x - buffer.c (text)'
sed << 'E!O!F' 's/^X//' > buffer.c
X/*
X * Buffer management.
X * Some of the functions are internal,
X * and some are actually attached to user
X * keys. Like everyone else, they set hints
X * for the display system.
X */
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X/*
X * Attach a buffer to a window. The
X * values of dot and mark come from the buffer
X * if the use count is 0. Otherwise, they come
X * from some other window.
X */
Xusebuffer(f, n)
X{
X        register BUFFER *bp;
X        register int    s;
X        char            bufn[NBUFN];
X
X        if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
X                return (s);
X        if ((bp=bfind(bufn, TRUE, 0)) == NULL)
X                return (FALSE);
X	return(swbuffer(bp));
X}
X
Xnextbuffer(f, n)	/* switch to the next buffer in the buffer list */
X
Xint f, n;	/* default flag, numeric argument */
X{
X	register BUFFER *bp;	/* eligable buffer to switch to*/
X	register BUFFER *bbp;	/* eligable buffer to switch to*/
X
X	/* make sure the arg is legit */
X	if (f == FALSE)
X		n = 1;
X	if (n < 1)
X		return(FALSE);
X
X	bbp = curbp;
X	while (n-- > 0) {
X		/* advance to the next buffer */
X		bp = bbp->b_bufp;
X
X		/* cycle through the buffers to find an eligable one */
X		while (bp == NULL || bp->b_flag & BFINVS) {
X			if (bp == NULL)
X				bp = bheadp;
X			else
X				bp = bp->b_bufp;
X
X			/* don't get caught in an infinite loop! */
X			if (bp == bbp)
X				return(FALSE);
X
X		}		
X
X		bbp = bp;
X	}
X
X	return(swbuffer(bp));
X}
X
Xswbuffer(bp)	/* make buffer BP current */
X
XBUFFER *bp;
X
X{
X        register WINDOW *wp;
X
X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
X                curbp->b_dotp  = curwp->w_dotp;
X                curbp->b_doto  = curwp->w_doto;
X                curbp->b_markp = curwp->w_markp;
X                curbp->b_marko = curwp->w_marko;
X        }
X        curbp = bp;                             /* Switch.              */
X	if (curbp->b_active != TRUE) {		/* buffer not active yet*/
X		/* read it in and activate it */
X		readin(curbp->b_fname, TRUE);
X		curbp->b_dotp = lforw(curbp->b_linep);
X		curbp->b_doto = 0;
X		curbp->b_active = TRUE;
X	}
X        curwp->w_bufp  = bp;
X        curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
X        curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
X        if (bp->b_nwnd++ == 0) {                /* First use.           */
X                curwp->w_dotp  = bp->b_dotp;
X                curwp->w_doto  = bp->b_doto;
X                curwp->w_markp = bp->b_markp;
X                curwp->w_marko = bp->b_marko;
X                return (TRUE);
X        }
X        wp = wheadp;                            /* Look for old.        */
X        while (wp != NULL) {
X                if (wp!=curwp && wp->w_bufp==bp) {
X                        curwp->w_dotp  = wp->w_dotp;
X                        curwp->w_doto  = wp->w_doto;
X                        curwp->w_markp = wp->w_markp;
X                        curwp->w_marko = wp->w_marko;
X                        break;
X                }
X                wp = wp->w_wndp;
X        }
X        return (TRUE);
X}
X
X/*
X * Dispose of a buffer, by name.
X * Ask for the name. Look it up (don't get too
X * upset if it isn't there at all!). Get quite upset
X * if the buffer is being displayed. Clear the buffer (ask
X * if the buffer has been changed). Then free the header
X * line and the buffer header. Bound to "C-X K".
X */
Xkillbuffer(f, n)
X
X{
X	register BUFFER *bp;
X        register int    s;
X        char bufn[NBUFN];
X
X        if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
X                return(s);
X        if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
X                return (TRUE);
X	if(bp->b_flag & BFINVS)		/* Deal with special buffers	*/
X			return (TRUE);		/* by doing nothing.	*/
X	return(zotbuf(bp));
X}
X
Xzotbuf(bp)	/* kill the buffer pointed to by bp */
X
Xregister BUFFER *bp;
X
X{
X        register BUFFER *bp1;
X        register BUFFER *bp2;
X        register int    s;
X
X        if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
X                mlwrite("Buffer is being displayed");
X                return (FALSE);
X        }
X        if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
X                return (s);
X        free((char *) bp->b_linep);             /* Release header line. */
X        bp1 = NULL;                             /* Find the header.     */
X        bp2 = bheadp;
X        while (bp2 != bp) {
X                bp1 = bp2;
X                bp2 = bp2->b_bufp;
X        }
X        bp2 = bp2->b_bufp;                      /* Next one in chain.   */
X        if (bp1 == NULL)                        /* Unlink it.           */
X                bheadp = bp2;
X        else
X                bp1->b_bufp = bp2;
X        free((char *) bp);                      /* Release buffer block */
X        return (TRUE);
X}
X
Xnamebuffer(f,n)		/*	Rename the current buffer	*/
X
Xint f, n;		/* default Flag & Numeric arg */
X
X{
X	register BUFFER *bp;	/* pointer to scan through all buffers */
X	char bufn[NBUFN];	/* buffer to hold buffer name */
X
X	/* prompt for and get the new buffer name */
Xask:	if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
X		return(FALSE);
X
X	/* and check for duplicates */
X	bp = bheadp;
X	while (bp != NULL) {
X		if (bp != curbp) {
X			/* if the names the same */
X			if (strcmp(bufn, bp->b_bname) == 0)
X				goto ask;  /* try again */
X		}
X		bp = bp->b_bufp;	/* onward */
X	}
X
X	strcpy(curbp->b_bname, bufn);	/* copy buffer name to structure */
X	curwp->w_flag |= WFMODE;	/* make mode line replot */
X	mlerase();
X	return(TRUE);
X}
X
X/*
X	List all of the active buffers.  First update the special
X	buffer that holds the list.  Next make sure at least 1
X	window is displaying the buffer list, splitting the screen
X	if this is what it takes.  Lastly, repaint all of the
X	windows that are displaying the list.  Bound to "C-X C-B". 
X	A numeric argument forces it to list invisable buffers as
X	well.
X*/
X
Xlistbuffers(f, n)
X{
X        register WINDOW *wp;
X        register BUFFER *bp;
X        register int    s;
X
X        if ((s=makelist(f)) != TRUE)
X                return (s);
X        if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
X                if ((wp=wpopup()) == NULL)
X                        return (FALSE);
X                bp = wp->w_bufp;
X                if (--bp->b_nwnd == 0) {
X                        bp->b_dotp  = wp->w_dotp;
X                        bp->b_doto  = wp->w_doto;
X                        bp->b_markp = wp->w_markp;
X                        bp->b_marko = wp->w_marko;
X                }
X                wp->w_bufp  = blistp;
X                ++blistp->b_nwnd;
X        }
X        wp = wheadp;
X        while (wp != NULL) {
X                if (wp->w_bufp == blistp) {
X                        wp->w_linep = lforw(blistp->b_linep);
X                        wp->w_dotp  = lforw(blistp->b_linep);
X                        wp->w_doto  = 0;
X                        wp->w_markp = NULL;
X                        wp->w_marko = 0;
X                        wp->w_flag |= WFMODE|WFHARD;
X                }
X                wp = wp->w_wndp;
X        }
X        return (TRUE);
X}
X
X/*
X * This routine rebuilds the
X * text in the special secret buffer
X * that holds the buffer list. It is called
X * by the list buffers command. Return TRUE
X * if everything works. Return FALSE if there
X * is an error (if there is no memory). Iflag
X * indecates weather to list hidden buffers.
X */
Xmakelist(iflag)
X
Xint iflag;	/* list hidden buffer flag */
X
X{
X        register char   *cp1;
X        register char   *cp2;
X        register int    c;
X        register BUFFER *bp;
X        register LINE   *lp;
X        register int    s;
X	register int	i;
X        long nbytes;		/* # of bytes in current buffer */
X        char b[7+1];
X        char line[128];
X
X        blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
X        if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
X                return (s);
X        strcpy(blistp->b_fname, "");
X        if (addline("AC MODES        Size Buffer        File") == FALSE
X        ||  addline("-- -----        ---- ------        ----") == FALSE)
X                return (FALSE);
X        bp = bheadp;                            /* For all buffers      */
X
X	/* build line to report global mode settings */
X	cp1 = &line[0];
X	*cp1++ = ' ';
X	*cp1++ = ' ';
X	*cp1++ = ' ';
X
X	/* output the mode codes */
X	for (i = 0; i < NUMMODES; i++)
X		if (gmode & (1 << i))
X			*cp1++ = modecode[i];
X		else
X			*cp1++ = '.';
X	strcpy(cp1, "         Global Modes");
X	if (addline(line) == FALSE)
X		return(FALSE);
X
X	/* output the list of buffers */
X        while (bp != NULL) {
X		/* skip invisable buffers if iflag is false */
X                if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) {
X                        bp = bp->b_bufp;
X                        continue;
X                }
X                cp1 = &line[0];                 /* Start at left edge   */
X
X		/* output status of ACTIVE flag (has the file been read in? */
X                if (bp->b_active == TRUE)    /* "@" if activated       */
X                        *cp1++ = '@';
X                else
X                        *cp1++ = ' ';
X
X		/* output status of changed flag */
X                if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
X                        *cp1++ = '*';
X                else
X                        *cp1++ = ' ';
X                *cp1++ = ' ';                   /* Gap.                 */
X
X		/* output the mode codes */
X		for (i = 0; i < NUMMODES; i++) {
X			if (bp->b_mode & (1 << i))
X				*cp1++ = modecode[i];
X			else
X				*cp1++ = '.';
X		}
X                *cp1++ = ' ';                   /* Gap.                 */
X                nbytes = 0L;                    /* Count bytes in buf.  */
X                lp = lforw(bp->b_linep);
X                while (lp != bp->b_linep) {
X                        nbytes += (long)llength(lp)+1L;
X                        lp = lforw(lp);
X                }
X                ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
X                cp2 = &b[0];
X                while ((c = *cp2++) != 0)
X                        *cp1++ = c;
X                *cp1++ = ' ';                   /* Gap.                 */
X                cp2 = &bp->b_bname[0];          /* Buffer name          */
X                while ((c = *cp2++) != 0)
X                        *cp1++ = c;
X                cp2 = &bp->b_fname[0];          /* File name            */
X                if (*cp2 != 0) {
X                        while (cp1 < &line[2+1+5+1+6+1+NBUFN])
X                                *cp1++ = ' ';
X                        while ((c = *cp2++) != 0) {
X                                if (cp1 < &line[128-1])
X                                        *cp1++ = c;
X                        }
X                }
X                *cp1 = 0;                       /* Add to the buffer.   */
X                if (addline(line) == FALSE)
X                        return (FALSE);
X                bp = bp->b_bufp;
X        }
X        return (TRUE);                          /* All done             */
X}
X
Xltoa(buf, width, num)
X
Xchar   buf[];
Xint    width;
Xlong   num;
X
X{
X        buf[width] = 0;                         /* End of string.       */
X        while (num >= 10) {                     /* Conditional digits.  */
X                buf[--width] = (int)(num%10L) + '0';
X                num /= 10L;
X        }
X        buf[--width] = (int)num + '0';          /* Always 1 digit.      */
X        while (width != 0)                      /* Pad with blanks.     */
X                buf[--width] = ' ';
X}
X
X/*
X * The argument "text" points to
X * a string. Append this line to the
X * buffer list buffer. Handcraft the EOL
X * on the end. Return TRUE if it worked and
X * FALSE if you ran out of room.
X */
Xaddline(text)
Xchar    *text;
X{
X        register LINE   *lp;
X        register int    i;
X        register int    ntext;
X
X        ntext = strlen(text);
X        if ((lp=lalloc(ntext)) == NULL)
X                return (FALSE);
X        for (i=0; i<ntext; ++i)
X                lputc(lp, i, text[i]);
X        blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
X        lp->l_bp = blistp->b_linep->l_bp;
X        blistp->b_linep->l_bp = lp;
X        lp->l_fp = blistp->b_linep;
X        if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
X                blistp->b_dotp = lp;            /* move it to new line  */
X        return (TRUE);
X}
X
X/*
X * Look through the list of
X * buffers. Return TRUE if there
X * are any changed buffers. Buffers
X * that hold magic internal stuff are
X * not considered; who cares if the
X * list of buffer names is hacked.
X * Return FALSE if no buffers
X * have been changed.
X */
Xanycb()
X{
X        register BUFFER *bp;
X
X        bp = bheadp;
X        while (bp != NULL) {
X                if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
X                        return (TRUE);
X                bp = bp->b_bufp;
X        }
X        return (FALSE);
X}
X
X/*
X * Find a buffer, by name. Return a pointer
X * to the BUFFER structure associated with it.
X * If the buffer is not found
X * and the "cflag" is TRUE, create it. The "bflag" is
X * the settings for the flags in in buffer.
X */
XBUFFER  *
Xbfind(bname, cflag, bflag)
Xregister char   *bname;
X{
X        register BUFFER *bp;
X	register BUFFER *sb;	/* buffer to insert after */
X        register LINE   *lp;
X	char *malloc();
X
X        bp = bheadp;
X        while (bp != NULL) {
X                if (strcmp(bname, bp->b_bname) == 0)
X                        return (bp);
X                bp = bp->b_bufp;
X        }
X        if (cflag != FALSE) {
X                if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
X                        return (NULL);
X                if ((lp=lalloc(0)) == NULL) {
X                        free((char *) bp);
X                        return (NULL);
X                }
X		/* find the place in the list to insert this buffer */
X		if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
X			/* insert at the beginning */
X	                bp->b_bufp = bheadp;
X        	        bheadp = bp;
X        	} else {
X			sb = bheadp;
X			while (sb->b_bufp != NULL) {
X				if (strcmp(sb->b_bufp->b_bname, bname) > 0)
X					break;
X				sb = sb->b_bufp;
X			}
X
X			/* and insert it */
X       			bp->b_bufp = sb->b_bufp;
X        		sb->b_bufp = bp;
X       		}
X
X		/* and set up the other buffer fields */
X		bp->b_active = TRUE;
X                bp->b_dotp  = lp;
X                bp->b_doto  = 0;
X                bp->b_markp = NULL;
X                bp->b_marko = 0;
X                bp->b_flag  = bflag;
X		bp->b_mode  = gmode;
X                bp->b_nwnd  = 0;
X                bp->b_linep = lp;
X                strcpy(bp->b_fname, "");
X                strcpy(bp->b_bname, bname);
X#if	CRYPT
X		bp->b_key[0] = 0;
X#endif
X                lp->l_fp = lp;
X                lp->l_bp = lp;
X        }
X        return (bp);
X}
X
X/*
X * This routine blows away all of the text
X * in a buffer. If the buffer is marked as changed
X * then we ask if it is ok to blow it away; this is
X * to save the user the grief of losing text. The
X * window chain is nearly always wrong if this gets
X * called; the caller must arrange for the updates
X * that are required. Return TRUE if everything
X * looks good.
X */
Xbclear(bp)
Xregister BUFFER *bp;
X{
X        register LINE   *lp;
X        register int    s;
X
X        if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
X        && (bp->b_flag&BFCHG) != 0              /* Something changed    */
X        && (s=mlyesno("Discard changes")) != TRUE)
X                return (s);
X        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
X        while ((lp=lforw(bp->b_linep)) != bp->b_linep)
X                lfree(lp);
X        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
X        bp->b_doto  = 0;
X        bp->b_markp = NULL;                     /* Invalidate "mark"    */
X        bp->b_marko = 0;
X        return (TRUE);
X}
X
Xunmark(f, n)	/* unmark the current buffers change flag */
X
Xint f, n;	/* unused command arguments */
X
X{
X	curbp->b_flag &= ~BFCHG;
X	curwp->w_flag |= WFMODE;
X	return(TRUE);
X}
E!O!F
newsize=`wc -c < buffer.c`
if [ $newsize -ne 16060 ]
then echo "File buffer.c was $newsize bytes, 16060 expected"
fi
echo 'x - crypt.c (text)'
sed << 'E!O!F' 's/^X//' > crypt.c
X/*	Crypt:	Encryption routines for MicroEMACS
X		written by Dana Hoggatt and Daniel Lawrence
X*/
X
X#include	<stdio.h>
X#include	"estruct.h"
X#include	"edef.h"
X
X#if	CRYPT
Xsetkey(f, n)	/* reset encryption key of current buffer */
X
Xint f;		/* default flag */
Xint n;		/* numeric argument */
X
X{
X	register int status;	/* return status */
X	int odisinp;		/* original vlaue of disinp */
X	char key[NPAT];		/* new encryption string */
X
X	/* turn command input echo off */
X	odisinp = disinp;
X	disinp = FALSE;
X
X	/* get the string to use as an encrytion string */
X	status = mlreply("Encryption String: ", key, NPAT - 1);
X	disinp = odisinp;
X        if (status != TRUE)
X                return(status);
X
X	/* and encrypt it */
X	crypt((char *)NULL, 0);
X	crypt(key, strlen(key));
X
X	/* and save it off */
X	strcpy(curbp->b_key, key);
X	mlwrite(" ");		/* clear it off the bottom line */
X	return(TRUE);
X}
X
X/**********
X *
X *	crypt - in place encryption/decryption of a buffer
X *
X *	(C) Copyright 1986, Dana L. Hoggatt
X *	1216, Beck Lane, Lafayette, IN
X *
X *	When consulting directly with the author of this routine, 
X *	please refer to this routine as the "DLH-POLY-86-B CIPHER".  
X *
X *	This routine was written for Dan Lawrence, for use in V3.8 of
X *	MicroEMACS, a public domain text/program editor.  
X *
X *	I kept the following goals in mind when preparing this function:
X *
X *	    1.	All printable characters were to be encrypted back
X *		into the printable range, control characters and
X *		high-bit characters were to remain unaffected.  this
X *		way, encrypted would still be just as cheap to 
X *		transmit down a 7-bit data path as they were before.
X *
X *	    2.	The encryption had to be portable.  The encrypted 
X *		file from one computer should be able to be decrypted 
X *		on another computer.
X *
X *	    3.	The encryption had to be inexpensive, both in terms
X *		of speed and space.
X *
X *	    4.	The system needed to be secure against all but the
X *		most determined of attackers.
X *
X *	For encryption of a block of data, one calls crypt passing 
X *	a pointer to the data block and its length. The data block is 
X *	encrypted in place, that is, the encrypted output overwrites 
X *	the input.  Decryption is totally isomorphic, and is performed 
X *	in the same manner by the same routine.  
X *
X *	Before using this routine for encrypting data, you are expected 
X *	to specify an encryption key.  This key is an arbitrary string,
X *	to be supplied by the user.  To set the key takes two calls to 
X *	crypt().  First, you call 
X *
X *		crypt(NULL, vector)
X *
X *	This resets all internal control information.  Typically (and 
X *	specifically in the case on MICRO-emacs) you would use a "vector" 
X *	of 0.  Other values can be used to customize your editor to be 
X *	"incompatable" with the normally distributed version.  For 
X *	this purpose, the best results will be obtained by avoiding
X *	multiples of 95.
X *
X *	Then, you "encrypt" your password by calling 
X *
X *		crypt(pass, strlen(pass))
X *
X *	where "pass" is your password string.  Crypt() will destroy 
X *	the original copy of the password (it becomes encrypted), 
X *	which is good.  You do not want someone on a multiuser system 
X *	to peruse your memory space and bump into your password.  
X *	Still, it is a better idea to erase the password buffer to 
X *	defeat memory perusal by a more technical snooper.  
X *
X *	For the interest of cryptologists, at the heart of this 
X *	function is a Beaufort Cipher.  The cipher alphabet is the 
X *	range of printable characters (' ' to '~'), all "control" 
X *	and "high-bit" characters are left unaltered.
X *
X *	The key is a variant autokey, derived from a wieghted sum 
X *	of all the previous clear text and cipher text.  A counter 
X *	is used as salt to obiterate any simple cyclic behavior 
X *	from the clear text, and key feedback is used to assure 
X *	that the entire message is based on the original key, 
X *	preventing attacks on the last part of the message as if 
X *	it were a pure autokey system.
X *
X *	Overall security of encrypted data depends upon three 
X *	factors:  the fundamental cryptographic system must be 
X *	difficult to compromise; exhaustive searching of the key 
X *	space must be computationally expensive; keys and plaintext 
X *	must remain out of sight.  This system satisfies this set
X *	of conditions to within the degree desired for MicroEMACS.
X *
X *	Though direct methods of attack (against systems such as 
X *	this) do exist, they are not well known and will consume 
X *	considerable amounts of computing time.  An exhaustive
X *	search requires over a billion investigations, on average.
X *
X *	The choice, entry, storage, manipulation, alteration, 
X *	protection and security of the keys themselves are the 
X *	responsiblity of the user.  
X *
X **********/
X
Xcrypt(bptr, len)
Xregister char *bptr;	/* buffer of characters to be encrypted */
Xregister unsigned len;	/* number of characters in the buffer */
X{
X	register int cc;	/* current character being considered */
X
X	static long key = 0;	/* 29 bit encipherment key */
X	static int salt = 0;	/* salt to spice up key with */
X
X	if (!bptr) {		/* is there anything here to encrypt? */
X		key = len;	/* set the new key */
X		salt = len;	/* set the new salt */
X		return;
X	}
X	while (len--) {		/* for every character in the buffer */
X
X		cc = *bptr;	/* get a character out of the buffer */
X
X		/* only encipher printable characters */
X		if ((cc >= ' ') && (cc <= '~')) {
X
X/**  If the upper bit (bit 29) is set, feed it back into the key.  This 
X	assures us that the starting key affects the entire message.  **/
X
X			key &= 0x1FFFFFFFL;	/* strip off overflow */
X			if (key & 0x10000000L) {
X				key ^= 0x0040A001L;	/* feedback */
X			}
X
X/**  Down-bias the character, perform a Beaufort encipherment, and 
X	up-bias the character again.  We want key to be positive 
X	so that the left shift here will be more portable and the 
X	mod95() faster   **/
X
X			cc = mod95((int)(key % 95) - (cc - ' ')) + ' ';
X
X/**  the salt will spice up the key a little bit, helping to obscure 
X	any patterns in the clear text, particularly when all the 
X	characters (or long sequences of them) are the same.  We do 
X	not want the salt to go negative, or it will affect the key 
X	too radically.  It is always a good idea to chop off cyclics 
X	to prime values.  **/
X
X			if (++salt >= 20857) {	/* prime modulus */
X				salt = 0;
X			}
X
X/**  our autokey (a special case of the running key) is being 
X	generated by a wieghted checksum of clear text, cipher 
X	text, and salt.   **/
X
X			key = key + key + cc + *bptr + salt;
X		}
X		*bptr++ = cc;	/* put character back into buffer */
X	}
X	return;
X}
X
Xstatic int mod95(val)
X
Xregister int val;
X
X{
X	/*  The mathematical MOD does not match the computer MOD  */
X
X	/*  Yes, what I do here may look strange, but it gets the
X		job done, and portably at that.  */
X
X	while (val >= 9500)
X		val -= 9500;
X	while (val >= 950)
X		val -= 950;
X	while (val >= 95)
X		val -= 95;
X	while (val < 0)
X		val += 95;
X	return (val);
X}
X#else
Xnocrypt()
X{
X}
X#endif
E!O!F
newsize=`wc -c < crypt.c`
if [ $newsize -ne 6981 ]
then echo "File crypt.c was $newsize bytes, 6981 expected"
fi
echo 'x - dg10.c (text)'
sed << 'E!O!F' 's/^X//' > dg10.c
X/*
X * The routines in this file provide support for the Data General Model 10
X * Microcomputer.
X */
X
X#define	termdef	1			/* don't define "term" external */
X
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if     DG10
X
X#define NROW    24                      /* Screen size.                 */
X#define NCOL    80                      /* Edit if you want to.         */
X#define	NPAUSE	100			/* # times thru update to pause */
X#define	MARGIN	8			/* size of minimim margin and	*/
X#define	SCRSIZ	64			/* scroll size for extended lines */
X#define BEL     0x07                    /* BEL character.               */
X#define ESC     30                      /* DG10 ESC character.          */
X
Xextern  int     ttopen();               /* Forward references.          */
Xextern  int     ttgetc();
Xextern  int     ttputc();
Xextern  int     ttflush();
Xextern  int     ttclose();
Xextern	int	dg10kopen();
Xextern	int	dg10kclose();
Xextern  int     dg10move();
Xextern  int     dg10eeol();
Xextern  int     dg10eeop();
Xextern  int     dg10beep();
Xextern  int     dg10open();
Xextern	int	dg10rev();
Xextern	int	dg10close();
Xextern	int	dg10cres();
X
X#if	COLOR
Xextern	int	dg10fcol();
Xextern	int	dg10bcol();
X
Xint	cfcolor = -1;		/* current forground color */
Xint	cbcolor = -1;		/* current background color */
Xint	ctrans[] = {		/* emacs -> DG10 color translation table */
X	0, 4, 2, 6, 1, 5, 3, 7};
X#endif
X
X/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
XTERM    term    = {
X	NROW-1,
X        NROW-1,
X        NCOL,
X        NCOL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        dg10open,
X        dg10close,
X	dg10kopen,
X	dg10kclose,
X        ttgetc,
X        ttputc,
X        ttflush,
X        dg10move,
X        dg10eeol,
X        dg10eeop,
X        dg10beep,
X	dg10rev,
X	dg10cres
X#if	COLOR
X	, dg10fcol,
X	dg10bcol
X#endif
X};
X
X#if	COLOR
Xdg10fcol(color)		/* set the current output color */
X
Xint color;	/* color to set */
X
X{
X	if (color == cfcolor)
X		return;
X	ttputc(ESC);
X	ttputc(0101);
X	ttputc(ctrans[color]);
X	cfcolor = color;
X}
X
Xdg10bcol(color)		/* set the current background color */
X
Xint color;	/* color to set */
X
X{
X	if (color == cbcolor)
X		return;
X	ttputc(ESC);
X	ttputc(0102);
X	ttputc(ctrans[color]);
X        cbcolor = color;
X}
X#endif
X
Xdg10move(row, col)
X{
X	ttputc(16);
X        ttputc(col);
X	ttputc(row);
X}
X
Xdg10eeol()
X{
X        ttputc(11);
X}
X
Xdg10eeop()
X{
X#if	COLOR
X	dg10fcol(gfcolor);
X	dg10bcol(gbcolor);
X#endif
X        ttputc(ESC);
X        ttputc(0106);
X        ttputc(0106);
X}
X
Xdg10rev(state)		/* change reverse video state */
X
Xint state;	/* TRUE = reverse, FALSE = normal */
X
X{
X#if	COLOR
X	if (state == TRUE) {
X		dg10fcol(0);
X		dg10bcol(7);
X	}
X#else
X	ttputc(ESC);
X	ttputc(state ? 0104: 0105);
X#endif
X}
X
Xdg10cres()	/* change screen resolution */
X
X{
X	return(TRUE);
X}
X
Xspal()		/* change palette string */
X
X{
X	/*	Does nothing here	*/
X}
X
Xdg10beep()
X{
X        ttputc(BEL);
X        ttflush();
X}
X
Xdg10open()
X{
X	strcpy(sres, "NORMAL");
X	revexist = TRUE;
X        ttopen();
X}
X
Xdg10close()
X
X{
X#if	COLOR
X	dg10fcol(7);
X	dg10bcol(0);
X#endif
X	ttclose();
X}
X
Xdg10kopen()
X
X{
X}
X
Xdg10kclose()
X
X{
X}
X
X#if	FLABEL
Xfnclabel(f, n)		/* label a function key */
X
Xint f,n;	/* default flag, numeric argument [unused] */
X
X{
X	/* on machines with no function keys...don't bother */
X	return(TRUE);
X}
X#endif
X#else
Xdg10hello()
X{
X}
X#endif
E!O!F
newsize=`wc -c < dg10.c`
if [ $newsize -ne 3333 ]
then echo "File dg10.c was $newsize bytes, 3333 expected"
fi
	bill davidsen		(wedu@ge-crd.arpa)
  {chinet | philabs | sesimo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me