MicroEmacs, Version 3.7 (uEmacs3.7), Part01/12

sources-request at mirror.UUCP sources-request at mirror.UUCP
Sat Jul 26 09:06:31 AEST 1986


Submitted by: ihnp4!pur-ee!pur-phy!duncan!lawrence
Mod.sources: Volume 6, Issue 71
Archive-name: uEmacs3.7/Part01

[  This is the latest revision of one of two programs named "MicroEmacs";
   when discussing these on the net, or in contacting the authors, make
   sure to mention the version number -- in this case 3.7 -- as that is
   the easiest way to distinguish between them.  Lawrence will be posting
   uuencoded executables in net.micro.pc and net.micro.amiga; the file
   'readme' contains information on how to also get these from him
   directly.   --r$ ]

echo extracting - Makefile
sed 's/^X//' > Makefile << 'FRIDAY_NIGHT'
XCFLAGS=		-O -I/usr/tools/include/bland
X
XOFILES=		ansi.o basic.o bind.o buffer.o display.o file.o \
X		fileio.o hp150.o line.o lock.c main.o random.o region.o \
X		search.o spawn.o tcap.o termio.o vt52.o window.o word.o \
X		exec.o input.o isearch.o
X
XCFILES=		ansi.c basic.c bind.c buffer.c display.c  file.c \
X		fileio.c hp150.c line.c lock.c main.c random.c region.c \
X		search.c spawn.c tcap.c termio.c vt52.c window.c word.c \
X		exec.c input.c isearch.c
X
XHFILES=		estruct.h edef.h efunc.h epath.h
X
Xemacs:		$(OFILES)
X		$(CC) $(CFLAGS) $(OFILES) -ltermcap -lc -o emacs
X
X$(OFILES):	$(HFILES)
FRIDAY_NIGHT
echo extracting - ansi.c
sed 's/^X//' > ansi.c << 'FRIDAY_NIGHT'
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();
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        NCOL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        ansiopen,
X        ansiclose,
X        ttgetc,
X        ttputc,
X        ttflush,
X        ansimove,
X        ansieeol,
X        ansieeop,
X        ansibeep,
X	ansirev
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
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	revexist = TRUE;
X        ttopen();
X}
X
Xansiclose()
X
X{
X#if	COLOR
X	ansifcol(7);
X	ansibcol(0);
X#endif
X	ttclose();
X}
X#else
Xansihello()
X{
X}
X#endif
FRIDAY_NIGHT
echo extracting - azmap.cmd
sed 's/^X//' > azmap.cmd << 'FRIDAY_NIGHT'
X;	AZMAP.CMD:	MicroEMACS Macro file
X;			to translate an AZTEC C .SYM map file into
X;			the form needed to read it into ADDSYMS
X;			to be used with Pheonix's PFIX plus (C) debugger
X;
X;			written 6/5/86 by Daniel Lawrence
X
Xbegining-of-file
Xnewline
Xprevious-line
Xreplace-string ~n "~n 0000:"
Xbegining-of-line
Xkill-to-end-of-line
Xnewline
Xnewline
Xnewline
Xbegining-of-file
Xnewline
Xinsert-string "  Address         Publics by Name"
Xnewline
Xset-mark
Xend-of-file
Xcase-region-upper
Xbegining-of-file
Xreplace-string _~n ~n
X
FRIDAY_NIGHT
echo extracting - basic.c
sed 's/^X//' > basic.c << 'FRIDAY_NIGHT'
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 forwwards 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	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        if ((lastflag&CFCPCN) == 0)             /* Reset goal if last   */
X                curgoal = getccol(FALSE);       /* not C-P or C-N       */
X        thisflag |= CFCPCN;
X        dlp = curwp->w_dotp;
X        while (n-- && dlp!=curbp->b_linep)
X                dlp = lforw(dlp);
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        if ((lastflag&CFCPCN) == 0)             /* Reset goal if the    */
X                curgoal = getccol(FALSE);       /* last isn't C-P, C-N  */
X        thisflag |= CFCPCN;
X        dlp = curwp->w_dotp;
X        while (n-- && lback(dlp)!=curbp->b_linep)
X                dlp = lback(dlp);
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 begining of the current paragraph
X		   here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
X		   combination to delimit the begining 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 begining 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}
FRIDAY_NIGHT
echo extracting - bind.c
sed 's/^X//' > bind.c << 'FRIDAY_NIGHT'
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();	/* 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	ptr = &outseq[0];
X	while (*ptr)
X		(*term.t_putchar)(*ptr++);
X	(*term.t_putchar)(' ');		/* space it out */
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		(*term.t_putchar)(*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 int status;	/* status of I/O operations */
X	register WINDOW *wp;	/* scaning pointer to windows */
X	register BUFFER *bp;	/* buffer pointer to help */
X	register int i;		/* index into help file names */
X	char fname[NSTRING];	/* buffer to construct file name in */
X
X	/* first check if we are already here */
X	bp = bfind("emacs.hlp", FALSE, BFINVS);
X
X	if (bp == NULL) {
X		/* search through the list of help files */
X		for (i=2; i < NPNAMES; i++) {
X			strcpy(fname, pathname[i]);
X			strcat(fname, pathname[1]);
X			status = ffropen(fname);
X			if (status == FIOSUC)
X				break;
X		}
X
X		if (status == FIOFNF) {
X			mlwrite("[Help file is not online]");
X			return(FALSE);
X		}
X
X		/* close the file to prepare for to read it in */
X		ffclose();
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*/
X
Xbindtokey(f, n)
X
Xint f, n;	/* command arguments [IGNORED] */
X
X{
X	register 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	(*term.t_putchar)(' ');		/* space it out */
X	(*term.t_flush)();
X
X	/* get the command sequence to bind */
X	c = getckey((kfunc == meta) || (kfunc == cex));
X
X	/* change it to something we can print as well */
X	cmdstr(c, &outseq[0]);
X
X	/* and dump it out */
X	ptr = &outseq[0];
X	while (*ptr)
X		(*term.t_putchar)(*ptr++);
X
X	/* if the function is a prefix key */
X	if (kfunc == meta || kfunc == cex) {
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				found = TRUE;
X				break;
X			}
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
X		/* if we found it, just reset it
X		   otherwise, let it fall through and be added to the end */
X		if (found) {
X			ktp->k_code = c;
X			return(TRUE);
X		}
X	} else {
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
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*/
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	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	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	ptr = &outseq[0];
X	while (*ptr)
X		(*term.t_putchar)(*ptr++);
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		mlwrite("[Key not bound]");
X		return(FALSE);
X	}
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	register WINDOW *wp;	/* scnaning 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 buffer 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		/* 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
X		/* 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 begining */
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
Xgetckey(mflag)	/* get a command key sequence from the keyboard	*/
X
Xint mflag;	/* going for a meta sequence? */
X
X{
X	register int c;		/* character fetched */
X	register char *tp;	/* pointer into the token */
X	char tok[NSTRING];	/* command incoming */
X
X	/* check to see if we are executing a command line */
X	if (clexec) {
X		nxtarg(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		} else
X
X			/* next the function prefix */
X			if (*tp == 'F' && *(tp+1) == 'N') {
X				c |= SPEC;
X				tp += 2;
X			} else
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 */
X		if (c >= 'a' && c <= 'z')
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	register int status;	/* status of I/O operations */
X	register int i;		/* index into help file names */
X	char fname[NSTRING];	/* buffer to construct file name in */
X	char *sfroot;		/* root of startup file name */
X
X#if	(MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
X	char *homedir;		/* pointer to your home directory */
X	char *getenv();
X#endif
X
X	if (sfname[0] == 0)
X		sfroot = pathname[0];
X	else
X		sfroot = sfname;
X
X#if	(MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
X	/* get the HOME from the environment */
X	if ((homedir = getenv("HOME")) != NULL) {
X		/* build the file name */
X		strcpy(fname, homedir);
X		strcat(fname, "/");
X		strcat(fname, sfroot);
X
X		/* and test it */
X		status = ffropen(fname);
X		if (status == FIOSUC) {
X			ffclose();
X			return(dofile(fname));
X		}
X	}
X#endif
X
X	/* search through the list of startup files */
X	for (i=2; i < NPNAMES; i++) {
X		strcpy(fname, pathname[i]);
X		strcat(fname, sfroot);
X		status = ffropen(fname);
X		if (status == FIOSUC)
X			break;
X	}
X
X	/* if it isn't around, don't sweat it */
X	if (status == FIOFNF)
X		return(TRUE);
X
X	ffclose();	/* close the file to prepare for to read it in */
X
X	return(dofile(fname));
X}
X
FRIDAY_NIGHT
echo extracting - buffer.c
sed 's/^X//' > buffer.c << 'FRIDAY_NIGHT'
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
X{
X        register BUFFER *bp;
X
X	bp = curbp->b_bufp;
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	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	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
X * buffers. First update the special
X * buffer that holds the list. Next make
X * sure at least 1 window is displaying the
X * buffer list, splitting the screen if this
X * is what it takes. Lastly, repaint all of
X * the windows that are displaying the
X * list. Bound to "C-X C-B".
X */
Xlistbuffers(f, n)
X{
X        register WINDOW *wp;
X        register BUFFER *bp;
X        register int    s;
X
X        if ((s=makelist()) != 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).
X */
Xmakelist()
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                if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones.     */
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 begining */
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                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}
FRIDAY_NIGHT
echo es.1 completed!
: That's all folks!



More information about the Mod.sources mailing list