[comp.sources.misc] memacs 3.8i 11 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 - window.c (text)'
sed << 'E!O!F' 's/^X//' > window.c
X/*
X * Window management. Some of the functions are internal, and some are
X * attached to keys that the user actually types.
X */
X
X#include        <stdio.h>
X#include        "estruct.h"
X#include	"edef.h"
X
X#if	MEGAMAX & ST520
Xoverlay	"window"
X#endif
X
X/*
X * Reposition dot in the current window to line "n". If the argument is
X * positive, it is that line. If it is negative it is that line from the
X * bottom. If it is 0 the window is centered (this is what the standard
X * redisplay code does). With no argument it defaults to 0. Bound to M-!.
X */
Xreposition(f, n)
X    {
X    if (f == FALSE)	/* default to 0 to center screen */
X	n = 0;
X    curwp->w_force = n;
X    curwp->w_flag |= WFFORCE;
X    return (TRUE);
X    }
X
X/*
X * Refresh the screen. With no argument, it just does the refresh. With an
X * argument it recenters "." in the current window. Bound to "C-L".
X */
Xrefresh(f, n)
X    {
X    if (f == FALSE)
X        sgarbf = TRUE;
X    else
X        {
X        curwp->w_force = 0;             /* Center dot. */
X        curwp->w_flag |= WFFORCE;
X        }
X
X    return (TRUE);
X    }
X
X/*
X * The command make the next window (next => down the screen) the current
X * window. There are no real errors, although the command does nothing if
X * there is only 1 window on the screen. Bound to "C-X C-N".
X *
X * with an argument this command finds the <n>th window from the top
X *
X */
Xnextwind(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X	register WINDOW *wp;
X	register int nwindows;		/* total number of windows */
X
X	if (f) {
X
X		/* first count the # of windows */
X		wp = wheadp;
X		nwindows = 1;
X		while (wp->w_wndp != NULL) {
X			nwindows++;
X			wp = wp->w_wndp;
X		}
X
X		/* if the argument is negative, it is the nth window
X		   from the bottom of the screen			*/
X		if (n < 0)
X			n = nwindows + n + 1;
X
X		/* if an argument, give them that window from the top */
X		if (n > 0 && n <= nwindows) {
X			wp = wheadp;
X			while (--n)
X				wp = wp->w_wndp;
X		} else {
X			mlwrite("Window number out of range");
X			return(FALSE);
X		}
X	} else
X		if ((wp = curwp->w_wndp) == NULL)
X			wp = wheadp;
X	curwp = wp;
X	curbp = wp->w_bufp;
X	upmode();
X	return (TRUE);
X}
X
X/*
X * This command makes the previous window (previous => up the screen) the
X * current window. There arn't any errors, although the command does not do a
X * lot if there is 1 window.
X */
Xprevwind(f, n)
X{
X	register WINDOW *wp1;
X	register WINDOW *wp2;
X
X	/* if we have an argument, we mean the nth window from the bottom */
X	if (f)
X		return(nextwind(f, -n));
X
X	wp1 = wheadp;
X	wp2 = curwp;
X
X	if (wp1 == wp2)
X		wp2 = NULL;
X
X	while (wp1->w_wndp != wp2)
X		wp1 = wp1->w_wndp;
X
X	curwp = wp1;
X	curbp = wp1->w_bufp;
X	upmode();
X	return (TRUE);
X}
X
X/*
X * This command moves the current window down by "arg" lines. Recompute the
X * top line in the window. The move up and move down code is almost completely
X * the same; most of the work has to do with reframing the window, and picking
X * a new dot. We share the code by having "move down" just be an interface to
X * "move up". Magic. Bound to "C-X C-N".
X */
Xmvdnwind(f, n)
X
Xint n;
X
X{
X	return (mvupwind(f, -n));
X}
X
X/*
X * Move the current window up by "arg" lines. Recompute the new top line of
X * the window. Look to see if "." is still on the screen. If it is, you win.
X * If it isn't, then move "." to center it in the new framing of the window
X * (this command does not really move "."; it moves the frame). Bound to
X * "C-X C-P".
X */
Xmvupwind(f, n)
X    int n;
X    {
X    register LINE *lp;
X    register int i;
X
X    lp = curwp->w_linep;
X
X    if (n < 0)
X        {
X        while (n++ && lp!=curbp->b_linep)
X            lp = lforw(lp);
X        }
X    else
X        {
X        while (n-- && lback(lp)!=curbp->b_linep)
X            lp = lback(lp);
X        }
X
X    curwp->w_linep = lp;
X    curwp->w_flag |= WFHARD;            /* Mode line is OK. */
X
X    for (i = 0; i < curwp->w_ntrows; ++i)
X        {
X        if (lp == curwp->w_dotp)
X            return (TRUE);
X        if (lp == curbp->b_linep)
X            break;
X        lp = lforw(lp);
X        }
X
X    lp = curwp->w_linep;
X    i  = curwp->w_ntrows/2;
X
X    while (i-- && lp != curbp->b_linep)
X        lp = lforw(lp);
X
X    curwp->w_dotp  = lp;
X    curwp->w_doto  = 0;
X    return (TRUE);
X    }
X
X/*
X * This command makes the current window the only window on the screen. Bound
X * to "C-X 1". Try to set the framing so that "." does not have to move on the
X * display. Some care has to be taken to keep the values of dot and mark in
X * the buffer structures right if the distruction of a window makes a buffer
X * become undisplayed.
X */
Xonlywind(f, n)
X{
X        register WINDOW *wp;
X        register LINE   *lp;
X        register int    i;
X
X        while (wheadp != curwp) {
X                wp = wheadp;
X                wheadp = wp->w_wndp;
X                if (--wp->w_bufp->b_nwnd == 0) {
X                        wp->w_bufp->b_dotp  = wp->w_dotp;
X                        wp->w_bufp->b_doto  = wp->w_doto;
X                        wp->w_bufp->b_markp = wp->w_markp;
X                        wp->w_bufp->b_marko = wp->w_marko;
X                }
X                free((char *) wp);
X        }
X        while (curwp->w_wndp != NULL) {
X                wp = curwp->w_wndp;
X                curwp->w_wndp = wp->w_wndp;
X                if (--wp->w_bufp->b_nwnd == 0) {
X                        wp->w_bufp->b_dotp  = wp->w_dotp;
X                        wp->w_bufp->b_doto  = wp->w_doto;
X                        wp->w_bufp->b_markp = wp->w_markp;
X                        wp->w_bufp->b_marko = wp->w_marko;
X                }
X                free((char *) wp);
X        }
X        lp = curwp->w_linep;
X        i  = curwp->w_toprow;
X        while (i!=0 && lback(lp)!=curbp->b_linep) {
X                --i;
X                lp = lback(lp);
X        }
X        curwp->w_toprow = 0;
X        curwp->w_ntrows = term.t_nrow-1;
X        curwp->w_linep  = lp;
X        curwp->w_flag  |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Delete the current window, placing its space in the window above,
X * or, if it is the top window, the window below. Bound to C-X 0.
X */
X
Xdelwind(f,n)
X
Xint f, n;	/* arguments are ignored for this command */
X
X{
X	register WINDOW *wp;	/* window to recieve deleted space */
X	register WINDOW *lwp;	/* ptr window before curwp */
X	register int target;	/* target line to search for */
X
X	/* if there is only one window, don't delete it */
X	if (wheadp->w_wndp == NULL) {
X		mlwrite("Can not delete this window");
X		return(FALSE);
X	}
X
X	/* find window before curwp in linked list */
X	wp = wheadp;
X	lwp = NULL;
X	while (wp != NULL) {
X		if (wp == curwp)
X			break;
X		lwp = wp;
X		wp = wp->w_wndp;
X	}
X
X	/* find recieving window and give up our space */
X	wp = wheadp;
X	if (curwp->w_toprow == 0) {
X		/* find the next window down */
X		target = curwp->w_ntrows + 1;
X		while (wp != NULL) {
X			if (wp->w_toprow == target)
X				break;
X			wp = wp->w_wndp;
X		}
X		if (wp == NULL)
X			return(FALSE);
X		wp->w_toprow = 0;
X		wp->w_ntrows += target;
X	} else {
X		/* find the next window up */
X		target = curwp->w_toprow - 1;
X		while (wp != NULL) {
X			if ((wp->w_toprow + wp->w_ntrows) == target)
X				break;
X			wp = wp->w_wndp;
X		}
X		if (wp == NULL)
X			return(FALSE);
X		wp->w_ntrows += 1 + curwp->w_ntrows;
X	}
X
X	/* get rid of the current window */
X	if (--curwp->w_bufp->b_nwnd == 0) {
X		curwp->w_bufp->b_dotp = curwp->w_dotp;
X		curwp->w_bufp->b_doto = curwp->w_doto;
X		curwp->w_bufp->b_markp = curwp->w_markp;
X		curwp->w_bufp->b_marko = curwp->w_marko;
X	}
X	if (lwp == NULL)
X		wheadp = curwp->w_wndp;
X	else
X		lwp->w_wndp = curwp->w_wndp;
X	free((char *)curwp);
X	curwp = wp;
X	wp->w_flag |= WFHARD;
X	curbp = wp->w_bufp;
X	upmode();
X	return(TRUE);
X}
X
X/*
X
XSplit the current window.  A window smaller than 3 lines cannot be
Xsplit.  An argument of 1 forces the cursor into the upper window, an
Xargument of two forces the cursor to the lower window.  The only other
Xerror that is possible is a "malloc" failure allocating the structure
Xfor the new window.  Bound to "C-X 2". 
X
X */
Xsplitwind(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X        register WINDOW *wp;
X        register LINE   *lp;
X        register int    ntru;
X        register int    ntrl;
X        register int    ntrd;
X        register WINDOW *wp1;
X        register WINDOW *wp2;
X	char *malloc();
X
X        if (curwp->w_ntrows < 3) {
X                mlwrite("Cannot split a %d line window", curwp->w_ntrows);
X                return (FALSE);
X        }
X        if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
X                mlwrite("Cannot allocate WINDOW block");
X                return (FALSE);
X        }
X        ++curbp->b_nwnd;                        /* Displayed twice.     */
X        wp->w_bufp  = curbp;
X        wp->w_dotp  = curwp->w_dotp;
X        wp->w_doto  = curwp->w_doto;
X        wp->w_markp = curwp->w_markp;
X        wp->w_marko = curwp->w_marko;
X        wp->w_flag  = 0;
X        wp->w_force = 0;
X#if	COLOR
X	/* set the colors of the new window */
X	wp->w_fcolor = gfcolor;
X	wp->w_bcolor = gbcolor;
X#endif
X        ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
X        ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
X        lp = curwp->w_linep;
X        ntrd = 0;
X        while (lp != curwp->w_dotp) {
X                ++ntrd;
X                lp = lforw(lp);
X        }
X        lp = curwp->w_linep;
X        if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
X                /* Old is upper window. */
X                if (ntrd == ntru)               /* Hit mode line.       */
X                        lp = lforw(lp);
X                curwp->w_ntrows = ntru;
X                wp->w_wndp = curwp->w_wndp;
X                curwp->w_wndp = wp;
X                wp->w_toprow = curwp->w_toprow+ntru+1;
X                wp->w_ntrows = ntrl;
X        } else {                                /* Old is lower window  */
X                wp1 = NULL;
X                wp2 = wheadp;
X                while (wp2 != curwp) {
X                        wp1 = wp2;
X                        wp2 = wp2->w_wndp;
X                }
X                if (wp1 == NULL)
X                        wheadp = wp;
X                else
X                        wp1->w_wndp = wp;
X                wp->w_wndp   = curwp;
X                wp->w_toprow = curwp->w_toprow;
X                wp->w_ntrows = ntru;
X                ++ntru;                         /* Mode line.           */
X                curwp->w_toprow += ntru;
X                curwp->w_ntrows  = ntrl;
X                while (ntru--)
X                        lp = lforw(lp);
X        }
X        curwp->w_linep = lp;                    /* Adjust the top lines */
X        wp->w_linep = lp;                       /* if necessary.        */
X        curwp->w_flag |= WFMODE|WFHARD;
X        wp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Enlarge the current window. Find the window that loses space. Make sure it
X * is big enough. If so, hack the window descriptions, and ask redisplay to do
X * all the hard work. You don't just set "force reframe" because dot would
X * move. Bound to "C-X Z".
X */
Xenlargewind(f, n)
X{
X        register WINDOW *adjwp;
X        register LINE   *lp;
X        register int    i;
X
X        if (n < 0)
X                return (shrinkwind(f, -n));
X        if (wheadp->w_wndp == NULL) {
X                mlwrite("Only one window");
X                return (FALSE);
X        }
X        if ((adjwp=curwp->w_wndp) == NULL) {
X                adjwp = wheadp;
X                while (adjwp->w_wndp != curwp)
X                        adjwp = adjwp->w_wndp;
X        }
X        if (adjwp->w_ntrows <= n) {
X                mlwrite("Impossible change");
X                return (FALSE);
X        }
X        if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
X                lp = adjwp->w_linep;
X                for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
X                        lp = lforw(lp);
X                adjwp->w_linep  = lp;
X                adjwp->w_toprow += n;
X        } else {                                /* Shrink above.        */
X                lp = curwp->w_linep;
X                for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
X                        lp = lback(lp);
X                curwp->w_linep  = lp;
X                curwp->w_toprow -= n;
X        }
X        curwp->w_ntrows += n;
X        adjwp->w_ntrows -= n;
X        curwp->w_flag |= WFMODE|WFHARD;
X        adjwp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Shrink the current window. Find the window that gains space. Hack at the
X * window descriptions. Ask the redisplay to do all the hard work. Bound to
X * "C-X C-Z".
X */
Xshrinkwind(f, n)
X{
X        register WINDOW *adjwp;
X        register LINE   *lp;
X        register int    i;
X
X        if (n < 0)
X                return (enlargewind(f, -n));
X        if (wheadp->w_wndp == NULL) {
X                mlwrite("Only one window");
X                return (FALSE);
X        }
X        if ((adjwp=curwp->w_wndp) == NULL) {
X                adjwp = wheadp;
X                while (adjwp->w_wndp != curwp)
X                        adjwp = adjwp->w_wndp;
X        }
X        if (curwp->w_ntrows <= n) {
X                mlwrite("Impossible change");
X                return (FALSE);
X        }
X        if (curwp->w_wndp == adjwp) {           /* Grow below.          */
X                lp = adjwp->w_linep;
X                for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
X                        lp = lback(lp);
X                adjwp->w_linep  = lp;
X                adjwp->w_toprow -= n;
X        } else {                                /* Grow above.          */
X                lp = curwp->w_linep;
X                for (i=0; i<n && lp!=curbp->b_linep; ++i)
X                        lp = lforw(lp);
X                curwp->w_linep  = lp;
X                curwp->w_toprow += n;
X        }
X        curwp->w_ntrows -= n;
X        adjwp->w_ntrows += n;
X        curwp->w_flag |= WFMODE|WFHARD;
X        adjwp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*	Resize the current window to the requested size	*/
X
Xresize(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X	int clines;	/* current # of lines in window */
X	
X	/* must have a non-default argument, else ignore call */
X	if (f == FALSE)
X		return(TRUE);
X
X	/* find out what to do */
X	clines = curwp->w_ntrows;
X
X	/* already the right size? */
X	if (clines == n)
X		return(TRUE);
X
X	return(enlargewind(TRUE, n - clines));
X}
X
X/*
X * Pick a window for a pop-up. Split the screen if there is only one window.
X * Pick the uppermost window that isn't the current window. An LRU algorithm
X * might be better. Return a pointer, or NULL on error.
X */
XWINDOW  *
Xwpopup()
X{
X        register WINDOW *wp;
X
X        if (wheadp->w_wndp == NULL              /* Only 1 window        */
X        && splitwind(FALSE, 0) == FALSE)        /* and it won't split   */
X                return (NULL);
X        wp = wheadp;                            /* Find window to use   */
X        while (wp!=NULL && wp==curwp)
X                wp = wp->w_wndp;
X        return (wp);
X}
X
Xscrnextup(f, n)		/* scroll the next window up (back) a page */
X
X{
X	nextwind(FALSE, 1);
X	backpage(f, n);
X	prevwind(FALSE, 1);
X}
X
Xscrnextdw(f, n)		/* scroll the next window down (forward) a page */
X
X{
X	nextwind(FALSE, 1);
X	forwpage(f, n);
X	prevwind(FALSE, 1);
X}
X
Xsavewnd(f, n)		/* save ptr to current window */
X
X{
X	swindow = curwp;
X	return(TRUE);
X}
X
Xrestwnd(f, n)		/* restore the saved screen */
X
X{
X	register WINDOW *wp;
X
X	/* find the window */
X	wp = wheadp;
X	while (wp != NULL) {
X		if (wp == swindow) {
X			curwp = wp;
X			curbp = wp->w_bufp;
X			upmode();
X			return (TRUE);
X		}
X		wp = wp->w_wndp;
X	}
X
X	mlwrite("[No such window exists]");
X	return(FALSE);
X}
X
Xnewsize(f, n)	/* resize the screen, re-writing the screen */
X
Xint f;	/* default flag */
Xint n;	/* numeric argument */
X
X{
X	WINDOW *wp;	/* current window being examined */
X	WINDOW *nextwp;	/* next window to scan */
X	WINDOW *lastwp;	/* last window scanned */
X	int lastline;	/* screen line of last line of current window */
X
X	/* if the command defaults, assume the largest */
X	if (f == FALSE)
X		n = term.t_mrow + 1;
X
X	/* make sure it's in range */
X	if (n < 3 || n > term.t_mrow + 1) {
X		mlwrite("%%Screen size out of range");
X		return(FALSE);
X	}
X
X	if (term.t_nrow == n - 1)
X		return(TRUE);
X	else if (term.t_nrow < n - 1) {
X
X		/* go to the last window */
X		wp = wheadp;
X		while (wp->w_wndp != NULL)
X			wp = wp->w_wndp;
X
X		/* and enlarge it as needed */
X		wp->w_ntrows = n - wp->w_toprow - 2;
X		wp->w_flag |= WFHARD|WFMODE;
X
X	} else {
X
X		/* rebuild the window structure */
X		nextwp = wheadp;
X		wp = NULL;
X		lastwp = NULL;
X		while (nextwp != NULL) {
X			wp = nextwp;
X			nextwp = wp->w_wndp;
X	
X			/* get rid of it if it is too low */
X			if (wp->w_toprow > n - 2) {
X
X				/* save the point/mark if needed */
X				if (--wp->w_bufp->b_nwnd == 0) {
X					wp->w_bufp->b_dotp = wp->w_dotp;
X					wp->w_bufp->b_doto = wp->w_doto;
X					wp->w_bufp->b_markp = wp->w_markp;
X					wp->w_bufp->b_marko = wp->w_marko;
X				}
X	
X				/* update curwp and lastwp if needed */
X				if (wp == curwp)
X					curwp = wheadp;
X					curbp = curwp->w_bufp;
X				if (lastwp != NULL)
X					lastwp->w_wndp = NULL;
X
X				/* free the structure */
X				free((char *)wp);
X				wp = NULL;
X
X			} else {
X				/* need to change this window size? */
X				lastline = wp->w_toprow + wp->w_ntrows - 1;
X				if (lastline >= n - 2) {
X					wp->w_ntrows = n - wp->w_toprow - 2;
X					wp->w_flag |= WFHARD|WFMODE;
X				}
X			}
X	
X			lastwp = wp;
X		}
X	}
X
X	/* screen is garbage */
X	term.t_nrow = n - 1;
X	sgarbf = TRUE;
X	return(TRUE);
X}
X
Xnewwidth(f, n)	/* resize the screen, re-writing the screen */
X
Xint f;	/* default flag */
Xint n;	/* numeric argument */
X
X{
X	/* if the command defaults, assume the largest */
X	if (f == FALSE)
X		n = term.t_mcol;
X
X	/* make sure it's in range */
X	if (n < 10 || n > term.t_mcol) {
X		mlwrite("%%Screen width out of range");
X		return(FALSE);
X	}
X
X	/* otherwise, just re-width it (no big deal) */
X	term.t_ncol = n;
X	term.t_margin = n / 10;
X	term.t_scrsiz = n - (term.t_margin * 2);
X	curwp->w_flag |= WFHARD | WFMOVE | WFMODE;
X	sgarbf = TRUE;
X	return(TRUE);
X}
E!O!F
newsize=`wc -c < window.c`
if [ $newsize -ne 18032 ]
then echo "File window.c was $newsize bytes, 18032 expected"
fi
echo 'x - word.c (text)'
sed << 'E!O!F' 's/^X//' > word.c
X/*
X * The routines in this file implement commands that work word or a
X * paragraph at a time.  There are all sorts of word mode commands.  If I
X * do any sentence mode commands, they are likely to be put in this file. 
X */
X
X#if	MEGAMAX & ST520
Xoverlay	"word"
X#endif
X
X#include        <stdio.h>
X#include        "estruct.h"
X#include	"edef.h"
X
X/* Word wrap on n-spaces. Back-over whatever precedes the point on the current
X * line and stop on the first word-break or the beginning of the line. If we
X * reach the beginning of the line, jump back to the end of the word and start
X * a new line.  Otherwise, break the line at the word-break, eat it, and jump
X * back to the end of the word.
X * Returns TRUE on success, FALSE on errors.
X */
Xwrapword(f, n)
X
Xint f;		/* default flag */
Xint n;		/* numeric argument */
X
X{
X        register int cnt;	/* size of word wrapped to next line */
X	register int c;		/* charector temporary */
X
X	/* backup from the <NL> 1 char */
X        if (!backchar(0, 1))
X	        return(FALSE);
X
X	/* back up until we aren't in a word,
X	   make sure there is a break in the line */
X        cnt = 0;
X	while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
X				&& (c != '\t')) {
X                cnt++;
X                if (!backchar(0, 1))
X                        return(FALSE);
X		/* if we make it to the beginning, start a new line */
X		if (curwp->w_doto == 0) {
X			gotoeol(FALSE, 0);
X			return(lnewline());
X		}
X        }
X
X	/* delete the forward white space */
X        if (!forwdel(0, 1))
X                return(FALSE);
X
X	/* put in a end of line */
X        if (!lnewline())
X                return(FALSE);
X
X	/* and past the first word */
X	while (cnt-- > 0) {
X		if (forwchar(FALSE, 1) == FALSE)
X			return(FALSE);
X	}
X        return(TRUE);
X}
X
X/*
X * Move the cursor backward by "n" words. All of the details of motion are
X * performed by the "backchar" and "forwchar" routines. Error if you try to
X * move beyond the buffers.
X */
Xbackword(f, n)
X{
X        if (n < 0)
X                return (forwword(f, -n));
X        if (backchar(FALSE, 1) == FALSE)
X                return (FALSE);
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (backchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X                while (inword() != FALSE) {
X                        if (backchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X        }
X        return (forwchar(FALSE, 1));
X}
X
X/*
X * Move the cursor forward by the specified number of words. All of the motion
X * is done by "forwchar". Error if you try and move beyond the buffer's end.
X */
Xforwword(f, n)
X{
X        if (n < 0)
X                return (backword(f, -n));
X        while (n--) {
X#if	NFWORD
X                while (inword() != FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X#endif
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X#if	NFWORD == 0
X                while (inword() != FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X#endif
X        }
X	return(TRUE);
X}
X
X/*
X * Move the cursor forward by the specified number of words. As you move,
X * convert any characters to upper case. Error if you try and move beyond the
X * end of the buffer. Bound to "M-U".
X */
Xupperword(f, n)
X{
X        register int    c;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X                while (inword() != FALSE) {
X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
X                        if (c>='a' && c<='z') {
X                                c -= 'a'-'A';
X                                lputc(curwp->w_dotp, curwp->w_doto, c);
X                                lchange(WFHARD);
X                        }
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X        }
X        return (TRUE);
X}
X
X/*
X * Move the cursor forward by the specified number of words. As you move
X * convert characters to lower case. Error if you try and move over the end of
X * the buffer. Bound to "M-L".
X */
Xlowerword(f, n)
X{
X        register int    c;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X                while (inword() != FALSE) {
X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
X                        if (c>='A' && c<='Z') {
X                                c += 'a'-'A';
X                                lputc(curwp->w_dotp, curwp->w_doto, c);
X                                lchange(WFHARD);
X                        }
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X        }
X        return (TRUE);
X}
X
X/*
X * Move the cursor forward by the specified number of words. As you move
X * convert the first character of the word to upper case, and subsequent
X * characters to lower case. Error if you try and move past the end of the
X * buffer. Bound to "M-C".
X */
Xcapword(f, n)
X{
X        register int    c;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X                if (inword() != FALSE) {
X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
X                        if (c>='a' && c<='z') {
X                                c -= 'a'-'A';
X                                lputc(curwp->w_dotp, curwp->w_doto, c);
X                                lchange(WFHARD);
X                        }
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        while (inword() != FALSE) {
X                                c = lgetc(curwp->w_dotp, curwp->w_doto);
X                                if (c>='A' && c<='Z') {
X                                        c += 'a'-'A';
X                                        lputc(curwp->w_dotp, curwp->w_doto, c);
X                                        lchange(WFHARD);
X                                }
X                                if (forwchar(FALSE, 1) == FALSE)
X                                        return (FALSE);
X                        }
X                }
X        }
X        return (TRUE);
X}
X
X/*
X * Kill forward by "n" words. Remember the location of dot. Move forward by
X * the right number of words. Put dot back where it was and issue the kill
X * command for the right number of characters. Bound to "M-D".
X */
Xdelfword(f, n)
X{
X        register LINE   *dotp;
X        register int    doto;
X        long size;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
X                kdelete();              /* last wasn't a kill.  */
X        thisflag |= CFKILL;
X        dotp = curwp->w_dotp;
X        doto = curwp->w_doto;
X        size = 0;
X        while (n--) {
X#if	NFWORD
X		if (curwp->w_doto == llength(curwp->w_dotp)) {
X			if (forwchar(FALSE,1) == FALSE)
X				return(FALSE);
X			++size;
X		}
X
X		if (inword()) {
X			while (inword() != FALSE) {
X				if (forwchar(FALSE,1) == FALSE)
X					return(FALSE);
X				++size;
X			}
X	
X	                while ((iswhite()) &&
X					(curwp->w_doto != llength(curwp->w_dotp))) {
X	                        if (forwchar(FALSE, 1) == FALSE)
X	                                return (FALSE);
X	                        ++size;
X	                }
X		}
X		else {
X			while ((inword() == FALSE) &&
X					(curwp->w_doto != llength(curwp->w_dotp))) {
X				if (forwchar(FALSE,1) == FALSE)
X					return(FALSE);
X				++size;
X			}
X		}
X#else
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X
X                while (inword() != FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X#endif
X        }
X        curwp->w_dotp = dotp;
X        curwp->w_doto = doto;
X        return (ldelete(size, TRUE));
X}
X
X/*
X * Kill backwards by "n" words. Move backwards by the desired number of words,
X * counting the characters. When dot is finally moved to its resting place,
X * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
X */
Xdelbword(f, n)
X{
X        long size;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
X                kdelete();              /* last wasn't a kill.  */
X        thisflag |= CFKILL;
X        if (backchar(FALSE, 1) == FALSE)
X                return (FALSE);
X        size = 0;
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (backchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X                while (inword() != FALSE) {
X                        if (backchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X        }
X        if (forwchar(FALSE, 1) == FALSE)
X                return (FALSE);
X        return (ldelete(size, TRUE));
X}
X
X/*
X * Return TRUE if the character at dot is a character that is considered to be
X * part of a word. The word character list is hard coded. Should be setable.
X */
Xinword()
X{
X        register int    c;
X
X        if (curwp->w_doto == llength(curwp->w_dotp))
X                return (FALSE);
X        c = lgetc(curwp->w_dotp, curwp->w_doto);
X        if (c>='a' && c<='z')
X                return (TRUE);
X        if (c>='A' && c<='Z')
X                return (TRUE);
X        if (c>='0' && c<='9')
X                return (TRUE);
X        if (c=='$' || c=='_')                   /* For identifiers      */
X                return (TRUE);
X        return (FALSE);
X}
X
X/*
X *  return TRUE if the current character is whitespace,
X *  else return FALSE.
X */
X
Xiswhite()
X{
X        register int    c;
X
X        if (curwp->w_doto == llength(curwp->w_dotp))
X                return (FALSE);
X        c = lgetc(curwp->w_dotp, curwp->w_doto);
X	if (c == ' ' || c == '\t') return (TRUE);
X        return (FALSE);
X}
X
X#if	WORDPRO
Xfillpara(f, n)	/* Fill the current paragraph according to the current
X		   fill column						*/
X
Xint f, n;	/* deFault flag and Numeric argument */
X
X{
X	register int c;			/* current char durring scan	*/
X	register int wordlen;		/* length of current word	*/
X	register int clength;		/* position on line during fill	*/
X	register int i;			/* index during word copy	*/
X	register int newlength;		/* tentative new line length	*/
X	register int eopflag;		/* Are we at the End-Of-Paragraph? */
X	register int firstflag;		/* first word? (needs no space)	*/
X	register LINE *eopline;		/* pointer to line just past EOP */
X	register int dotflag;		/* was the last char a period?	*/
X	char wbuf[NSTRING];		/* buffer for current word	*/
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X	if (fillcol == 0) {	/* no fill column set */
X		mlwrite("No fill column set");
X		return(FALSE);
X	}
X
X	/* record the pointer to the line just past the EOP */
X	gotoeop(FALSE, 1);
X	eopline = lforw(curwp->w_dotp);
X
X	/* and back top the beginning of the paragraph */
X	gotobop(FALSE, 1);
X
X	/* initialize various info */
X	clength = curwp->w_doto;
X	if (clength && curwp->w_dotp->l_text[0] == TAB)
X		clength = 8;
X	wordlen = 0;
X	dotflag = FALSE;
X
X	/* scan through lines, filling words */
X	firstflag = TRUE;
X	eopflag = FALSE;
X	while (!eopflag) {
X		/* get the next character in the paragraph */
X		if (curwp->w_doto == llength(curwp->w_dotp)) {
X			c = ' ';
X			if (lforw(curwp->w_dotp) == eopline)
X				eopflag = TRUE;
X		} else
X			c = lgetc(curwp->w_dotp, curwp->w_doto);
X
X		/* and then delete it */
X		ldelete(1L, FALSE);
X
X		/* if not a separator, just add it in */
X		if (c != ' ' && c != '\t') {
X			dotflag = (c == '.');		/* was it a dot */
X			if (wordlen < NSTRING - 1)
X				wbuf[wordlen++] = c;
X		} else if (wordlen) {
X			/* at a word break with a word waiting */
X			/* calculate tantitive new length with word added */
X			newlength = clength + 1 + wordlen;
X			if (newlength <= fillcol) {
X				/* add word to current line */
X				if (!firstflag) {
X					linsert(1, ' '); /* the space */
X					++clength;
X				}
X				firstflag = FALSE;
X			} else {
X				/* start a new line */
X				lnewline();
X				clength = 0;
X			}
X
X			/* and add the word in in either case */
X			for (i=0; i<wordlen; i++) {
X				linsert(1, wbuf[i]);
X				++clength;
X			}
X			if (dotflag) {
X				linsert(1, ' ');
X				++clength;
X			}
X			wordlen = 0;
X		}
X	}
X	/* and add a last newline for the end of our new paragraph */
X	lnewline();
X	return(TRUE);
X}
X
Xkillpara(f, n)	/* delete n paragraphs starting with the current one */
X
Xint f;	/* default flag */
Xint n;	/* # of paras to delete */
X
X{
X	register int status;	/* returned status of functions */
X
X	while (n--) {		/* for each paragraph to delete */
X
X		/* mark out the end and beginning of the para to delete */
X		gotoeop(FALSE, 1);
X
X		/* set the mark here */
X	        curwp->w_markp = curwp->w_dotp;
X	        curwp->w_marko = curwp->w_doto;
X
X		/* go to the beginning of the paragraph */
X		gotobop(FALSE, 1);
X		curwp->w_doto = 0;	/* force us to the beginning of line */
X	
X		/* and delete it */
X		if ((status = killregion(FALSE, 1)) != TRUE)
X			return(status);
X
X		/* and clean up the 2 extra lines */
X		ldelete(2L, TRUE);
X	}
X	return(TRUE);
X}
X
X
X/*	wordcount:	count the # of words in the marked region,
X			along with average word sizes, # of chars, etc,
X			and report on them.			*/
X
Xwordcount(f, n)
X
Xint f, n;	/* ignored numeric arguments */
X
X{
X	register LINE *lp;	/* current line to scan */
X	register int offset;	/* current char to scan */
X	long size;		/* size of region left to count */
X	register int ch;	/* current character to scan */
X	register int wordflag;	/* are we in a word now? */
X	register int lastword;	/* were we just in a word? */
X	long nwords;		/* total # of words */
X	long nchars;		/* total number of chars */
X	int nlines;		/* total number of lines in region */
X	int avgch;		/* average number of chars/word */
X	int status;		/* status return code */
X	REGION region;		/* region to look at */
X
X	/* make sure we have a region to count */
X        if ((status = getregion(&region)) != TRUE)
X                return(status);
X	lp = region.r_linep;
X	offset = region.r_offset;
X	size = region.r_size;
X
X	/* count up things */
X	lastword = FALSE;
X	nchars = 0L;
X	nwords = 0L;
X	nlines = 0;
X	while (size--) {
X
X		/* get the current character */
X		if (offset == llength(lp)) {	/* end of line */
X			ch = '\n';
X			lp = lforw(lp);
X			offset = 0;
X			++nlines;
X		} else {
X			ch = lgetc(lp, offset);
X			++offset;
X		}
X
X		/* and tabulate it */
X		wordflag = ((ch >= 'a' && ch <= 'z') ||
X			    (ch >= 'A' && ch <= 'Z') ||
X			    (ch >= '0' && ch <= '9') ||
X			    (ch == '$' || ch == '_'));
X		if (wordflag == TRUE && lastword == FALSE)
X			++nwords;
X		lastword = wordflag;
X		++nchars;
X	}
X
X	/* and report on the info */
X	if (nwords > 0L)
X		avgch = (int)((100L * nchars) / nwords);
X	else
X		avgch = 0;
X
X	mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
X		nwords, nchars, nlines + 1, avgch);
X	return(TRUE);
X}
X#endif
E!O!F
newsize=`wc -c < word.c`
if [ $newsize -ne 16421 ]
then echo "File word.c was $newsize bytes, 16421 expected"
fi
echo 'x - word.old (text)'
sed << 'E!O!F' 's/^X//' > word.old
X/*
X * The routines in this file implement commands that work word or a
X * paragraph at a time.  There are all sorts of word mode commands.  If I
X * do any sentence mode commands, they are likely to be put in this file. 
X */
X
X#if	MEGAMAX & ST520
Xoverlay	"word"
X#endif
X
X#include        <stdio.h>
X#include        "estruct.h"
X#include	"edef.h"
X
X/* Word wrap on n-spaces. Back-over whatever precedes the point on the current
X * line and stop on the first word-break or the beginning of the line. If we
X * reach the beginning of the line, jump back to the end of the word and start
X * a new line.  Otherwise, break the line at the word-break, eat it, and jump
X * back to the end of the word.
X * Returns TRUE on success, FALSE on errors.
X */
Xwrapword(f, n)
X
Xint f;		/* default flag */
Xint n;		/* numeric argument */
X
X{
X        register int cnt;	/* size of word wrapped to next line */
X	register int c;		/* charector temporary */
X
X	/* backup from the <NL> 1 char */
X        if (!backchar(0, 1))
X	        return(FALSE);
X
X	/* back up until we aren't in a word,
X	   make sure there is a break in the line */
X        cnt = 0;
X	while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
X				&& (c != '\t')) {
X                cnt++;
X                if (!backchar(0, 1))
X                        return(FALSE);
X		/* if we make it to the beginning, start a new line */
X		if (curwp->w_doto == 0) {
X			gotoeol(FALSE, 0);
X			return(lnewline());
X		}
X        }
X
X	/* delete the forward white space */
X        if (!forwdel(0, 1))
X                return(FALSE);
X
X	/* put in a end of line */
X        if (!lnewline())
X                return(FALSE);
X
X	/* and past the first word */
X	while (cnt-- > 0) {
X		if (forwchar(FALSE, 1) == FALSE)
X			return(FALSE);
X	}
X        return(TRUE);
X}
X
X/*
X * Move the cursor backward by "n" words. All of the details of motion are
X * performed by the "backchar" and "forwchar" routines. Error if you try to
X * move beyond the buffers.
X */
Xbackword(f, n)
X{
X        if (n < 0)
X                return (forwword(f, -n));
X        if (backchar(FALSE, 1) == FALSE)
X                return (FALSE);
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (backchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X                while (inword() != FALSE) {
X                        if (backchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X        }
X        return (forwchar(FALSE, 1));
X}
X
X/*
X * Move the cursor forward by the specified number of words. All of the motion
X * is done by "forwchar". Error if you try and move beyond the buffer's end.
X */
Xforwword(f, n)
X{
X        if (n < 0)
X                return (backword(f, -n));
X        while (n--) {
X#if	NFWORD
X                while (inword() != FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X#endif
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X#if	NFWORD == 0
X                while (inword() != FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X#endif
X        }
X	return(TRUE);
X}
X
X/*
X * Move the cursor forward by the specified number of words. As you move,
X * convert any characters to upper case. Error if you try and move beyond the
X * end of the buffer. Bound to "M-U".
X */
Xupperword(f, n)
X{
X        register int    c;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X                while (inword() != FALSE) {
X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
X                        if (c>='a' && c<='z') {
X                                c -= 'a'-'A';
X                                lputc(curwp->w_dotp, curwp->w_doto, c);
X                                lchange(WFHARD);
X                        }
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X        }
X        return (TRUE);
X}
X
X/*
X * Move the cursor forward by the specified number of words. As you move
X * convert characters to lower case. Error if you try and move over the end of
X * the buffer. Bound to "M-L".
X */
Xlowerword(f, n)
X{
X        register int    c;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X                while (inword() != FALSE) {
X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
X                        if (c>='A' && c<='Z') {
X                                c += 'a'-'A';
X                                lputc(curwp->w_dotp, curwp->w_doto, c);
X                                lchange(WFHARD);
X                        }
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X        }
X        return (TRUE);
X}
X
X/*
X * Move the cursor forward by the specified number of words. As you move
X * convert the first character of the word to upper case, and subsequent
X * characters to lower case. Error if you try and move past the end of the
X * buffer. Bound to "M-C".
X */
Xcapword(f, n)
X{
X        register int    c;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                }
X                if (inword() != FALSE) {
X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
X                        if (c>='a' && c<='z') {
X                                c -= 'a'-'A';
X                                lputc(curwp->w_dotp, curwp->w_doto, c);
X                                lchange(WFHARD);
X                        }
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        while (inword() != FALSE) {
X                                c = lgetc(curwp->w_dotp, curwp->w_doto);
X                                if (c>='A' && c<='Z') {
X                                        c += 'a'-'A';
X                                        lputc(curwp->w_dotp, curwp->w_doto, c);
X                                        lchange(WFHARD);
X                                }
X                                if (forwchar(FALSE, 1) == FALSE)
X                                        return (FALSE);
X                        }
X                }
X        }
X        return (TRUE);
X}
X
X/*
X * Kill forward by "n" words. Remember the location of dot. Move forward by
X * the right number of words. Put dot back where it was and issue the kill
X * command for the right number of characters. Bound to "M-D".
X */
Xdelfword(f, n)
X{
X        register LINE   *dotp;
X        register int    doto;
X        long size;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
X                kdelete();              /* last wasn't a kill.  */
X        thisflag |= CFKILL;
X        dotp = curwp->w_dotp;
X        doto = curwp->w_doto;
X        size = 0;
X        while (n--) {
X#if	NFWORD
X		if (curwp->w_doto == llength(curwp->w_dotp)) {
X			if (forwchar(FALSE,1) == FALSE)
X				return(FALSE);
X			++size;
X		}
X
X		while (inword() != FALSE) {
X			if (forwchar(FALSE,1) == FALSE)
X				return(FALSE);
X			++size;
X		}
X
X                while ((inword() == FALSE) &&
X				(curwp->w_doto != llength(curwp->w_dotp))) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X#else
X                while (inword() == FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X
X                while (inword() != FALSE) {
X                        if (forwchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X#endif
X        }
X        curwp->w_dotp = dotp;
X        curwp->w_doto = doto;
X        return (ldelete(size, TRUE));
X}
X
X/*
X * Kill backwards by "n" words. Move backwards by the desired number of words,
X * counting the characters. When dot is finally moved to its resting place,
X * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
X */
Xdelbword(f, n)
X{
X        long size;
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X        if (n < 0)
X                return (FALSE);
X        if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
X                kdelete();              /* last wasn't a kill.  */
X        thisflag |= CFKILL;
X        if (backchar(FALSE, 1) == FALSE)
X                return (FALSE);
X        size = 0;
X        while (n--) {
X                while (inword() == FALSE) {
X                        if (backchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X                while (inword() != FALSE) {
X                        if (backchar(FALSE, 1) == FALSE)
X                                return (FALSE);
X                        ++size;
X                }
X        }
X        if (forwchar(FALSE, 1) == FALSE)
X                return (FALSE);
X        return (ldelete(size, TRUE));
X}
X
X/*
X * Return TRUE if the character at dot is a character that is considered to be
X * part of a word. The word character list is hard coded. Should be setable.
X */
Xinword()
X{
X        register int    c;
X
X        if (curwp->w_doto == llength(curwp->w_dotp))
X                return (FALSE);
X        c = lgetc(curwp->w_dotp, curwp->w_doto);
X        if (c>='a' && c<='z')
X                return (TRUE);
X        if (c>='A' && c<='Z')
X                return (TRUE);
X        if (c>='0' && c<='9')
X                return (TRUE);
X        if (c=='$' || c=='_')                   /* For identifiers      */
X                return (TRUE);
X        return (FALSE);
X}
X
X#if	WORDPRO
Xfillpara(f, n)	/* Fill the current paragraph according to the current
X		   fill column						*/
X
Xint f, n;	/* deFault flag and Numeric argument */
X
X{
X	register int c;			/* current char durring scan	*/
X	register int wordlen;		/* length of current word	*/
X	register int clength;		/* position on line during fill	*/
X	register int i;			/* index during word copy	*/
X	register int newlength;		/* tentative new line length	*/
X	register int eopflag;		/* Are we at the End-Of-Paragraph? */
X	register int firstflag;		/* first word? (needs no space)	*/
X	register LINE *eopline;		/* pointer to line just past EOP */
X	register int dotflag;		/* was the last char a period?	*/
X	char wbuf[NSTRING];		/* buffer for current word	*/
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X	if (fillcol == 0) {	/* no fill column set */
X		mlwrite("No fill column set");
X		return(FALSE);
X	}
X
X	/* record the pointer to the line just past the EOP */
X	gotoeop(FALSE, 1);
X	eopline = lforw(curwp->w_dotp);
X
X	/* and back top the beginning of the paragraph */
X	gotobop(FALSE, 1);
X
X	/* initialize various info */
X	clength = curwp->w_doto;
X	if (clength && curwp->w_dotp->l_text[0] == TAB)
X		clength = 8;
X	wordlen = 0;
X	dotflag = FALSE;
X
X	/* scan through lines, filling words */
X	firstflag = TRUE;
X	eopflag = FALSE;
X	while (!eopflag) {
X		/* get the next character in the paragraph */
X		if (curwp->w_doto == llength(curwp->w_dotp)) {
X			c = ' ';
X			if (lforw(curwp->w_dotp) == eopline)
X				eopflag = TRUE;
X		} else
X			c = lgetc(curwp->w_dotp, curwp->w_doto);
X
X		/* and then delete it */
X		ldelete(1L, FALSE);
X
X		/* if not a separator, just add it in */
X		if (c != ' ' && c != '\t') {
X			dotflag = (c == '.');		/* was it a dot */
X			if (wordlen < NSTRING - 1)
X				wbuf[wordlen++] = c;
X		} else if (wordlen) {
X			/* at a word break with a word waiting */
X			/* calculate tantitive new length with word added */
X			newlength = clength + 1 + wordlen;
X			if (newlength <= fillcol) {
X				/* add word to current line */
X				if (!firstflag) {
X					linsert(1, ' '); /* the space */
X					++clength;
X				}
X				firstflag = FALSE;
X			} else {
X				/* start a new line */
X				lnewline();
X				clength = 0;
X			}
X
X			/* and add the word in in either case */
X			for (i=0; i<wordlen; i++) {
X				linsert(1, wbuf[i]);
X				++clength;
X			}
X			if (dotflag) {
X				linsert(1, ' ');
X				++clength;
X			}
X			wordlen = 0;
X		}
X	}
X	/* and add a last newline for the end of our new paragraph */
X	lnewline();
X	return(TRUE);
X}
X
Xkillpara(f, n)	/* delete n paragraphs starting with the current one */
X
Xint f;	/* default flag */
Xint n;	/* # of paras to delete */
X
X{
X	register int status;	/* returned status of functions */
X
X	while (n--) {		/* for each paragraph to delete */
X
X		/* mark out the end and beginning of the para to delete */
X		gotoeop(FALSE, 1);
X
X		/* set the mark here */
X	        curwp->w_markp = curwp->w_dotp;
X	        curwp->w_marko = curwp->w_doto;
X
X		/* go to the beginning of the paragraph */
X		gotobop(FALSE, 1);
X		curwp->w_doto = 0;	/* force us to the beginning of line */
X	
X		/* and delete it */
X		if ((status = killregion(FALSE, 1)) != TRUE)
X			return(status);
X
X		/* and clean up the 2 extra lines */
X		ldelete(2L, TRUE);
X	}
X	return(TRUE);
X}
X
X
X/*	wordcount:	count the # of words in the marked region,
X			along with average word sizes, # of chars, etc,
X			and report on them.			*/
X
Xwordcount(f, n)
X
Xint f, n;	/* ignored numeric arguments */
X
X{
X	register LINE *lp;	/* current line to scan */
X	register int offset;	/* current char to scan */
X	long size;		/* size of region left to count */
X	register int ch;	/* current character to scan */
X	register int wordflag;	/* are we in a word now? */
X	register int lastword;	/* were we just in a word? */
X	long nwords;		/* total # of words */
X	long nchars;		/* total number of chars */
X	int nlines;		/* total number of lines in region */
X	int avgch;		/* average number of chars/word */
X	int status;		/* status return code */
X	REGION region;		/* region to look at */
X
X	/* make sure we have a region to count */
X        if ((status = getregion(&region)) != TRUE)
X                return(status);
X	lp = region.r_linep;
X	offset = region.r_offset;
X	size = region.r_size;
X
X	/* count up things */
X	lastword = FALSE;
X	nchars = 0L;
X	nwords = 0L;
X	nlines = 0;
X	while (size--) {
X
X		/* get the current character */
X		if (offset == llength(lp)) {	/* end of line */
X			ch = '\n';
X			lp = lforw(lp);
X			offset = 0;
X			++nlines;
X		} else {
X			ch = lgetc(lp, offset);
X			++offset;
X		}
X
X		/* and tabulate it */
X		wordflag = ((ch >= 'a' && ch <= 'z') ||
X			    (ch >= 'A' && ch <= 'Z') ||
X			    (ch >= '0' && ch <= '9') ||
X			    (ch == '$' || ch == '_'));
X		if (wordflag == TRUE && lastword == FALSE)
X			++nwords;
X		lastword = wordflag;
X		++nchars;
X	}
X
X	/* and report on the info */
X	if (nwords > 0L)
X		avgch = (int)((100L * nchars) / nwords);
X	else
X		avgch = 0;
X
X	mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
X		nwords, nchars, nlines + 1, avgch);
X	return(TRUE);
X}
X#endif
E!O!F
newsize=`wc -c < word.old`
if [ $newsize -ne 15895 ]
then echo "File word.old was $newsize bytes, 15895 expected"
fi
echo 'x - z309.c (text)'
sed << 'E!O!F' 's/^X//' > z309.c
X/*
X * The routines in this file provide support for the Zenith Z-100 PC
X * family.  It goes directly to the graphics RAM to do screen output. 
X * It compiles into nothing if not a Zenith driver.
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     Z309
X
X/* set NROW to 25 for 25-line interlaced mode */
X#define NROW    50                      /* Screen size.                 */
X#define NCOL    80                      /* Edit if you want to.         */
X#define	MARGIN	8			/* size of minimim margin and	*/
X#define	SCRSIZ	64			/* scroll size for extended lines */
X#define	NPAUSE	200			/* # times thru update to pause */
X#define BEL     0x07                    /* BEL character.               */
X#define ESC     0x1B                    /* ESC character.               */
X#define	SPACE	32			/* space character		*/
X
X#define	SCADC	0xb8000000L		/* CGA address of screen RAM	*/
X#define	SCADM	0xb0000000L		/* MONO address of screen RAM	*/
X
X#define	CDMONO	0			/* monochrome text card		*/
X#define	CDCGA50	1			/* 50-line color graphics card	*/
X#define CDCGI25 2			/* 25-line interlaced CGA text	*/
X#define CDCGA25 3			/* 25-line color graphics card	*/
X#define	CDSENSE	9			/* detect the card type		*/
X
Xint dtype = CDCGA50;			/* current display type		*/
Xlong scadd;				/* address of screen ram	*/
Xint *scptr[NROW];			/* pointer to screen lines	*/
Xint sline[NCOL];			/* screen line image		*/
Xextern union REGS rg;			/* cpu register for use of DOS calls */
X
Xextern  int     ttopen();               /* Forward references.          */
Xextern  int     ttgetc();
Xextern  int     ttputc();
Xextern  int     ttflush();
Xextern  int     ttclose();
Xextern  int     z309move();
Xextern  int     z309eeol();
Xextern  int     z309eeop();
Xextern  int     z309beep();
Xextern  int     z309open();
Xextern	int	z309rev();
Xextern	int	z309cres();
Xextern	int	z309close();
Xextern	int	z309putc();
Xextern	int	z309kopen();
Xextern	int	z309kclose();
X
X#if	COLOR
Xextern	int	z309fcol();
Xextern	int	z309bcol();
X
Xint	cfcolor = -1;		/* current forground color */
Xint	cbcolor = -1;		/* current background color */
Xint	ctrans[] =		/* ansi to z309 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        z309open,
X        z309close,
X	z309kopen,
X	z309kclose,
X        ttgetc,
X	z309putc,
X        ttflush,
X        z309move,
X        z309eeol,
X        z309eeop,
X        z309beep,
X	z309rev,
X	z309cres
X#if	COLOR
X	, z309fcol,
X	z309bcol
X#endif
X};
X
Xextern union REGS rg;
X
X#if	COLOR
Xz309fcol(color)		/* set the current output color */
X
Xint color;	/* color to set */
X
X{
X	cfcolor = ctrans[color];
X}
X
Xz309bcol(color)		/* set the current background color */
X
Xint color;	/* color to set */
X
X{
X        cbcolor = ctrans[color];
X}
X#endif
Xz309move(row, col)
X{
X	rg.h.ah = 2;		/* set cursor position function code */
X	rg.h.dl = col;
X	rg.h.dh = row;
X	rg.h.bh = 0;		/* set screen page number */
X	int86(0x10, &rg, &rg);
X}
X
Xz309eeol()	/* erase to the end of the line */
X
X{
X	int attr;	/* attribute byte mask to place in RAM */
X	int *lnptr;	/* pointer to the destination line */
X	int i;
X	int ccol;	/* current column cursor lives */
X	int crow;	/*	   row	*/
X
X	/* find the current cursor position */
X	rg.h.ah = 3;		/* read cursor position function code */
X	rg.h.bh = 0;		/* current video page */
X	int86(0x10, &rg, &rg);
X	ccol = rg.h.dl;		/* record current column */
X	crow = rg.h.dh;		/* and row */
X
X	/* build the attribute byte and setup the screen pointer */
X#if	COLOR
X	if (dtype != CDMONO)
X		attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
X	else
X		attr = 0x0700;
X#else
X	attr = 0x0700;
X#endif
X	lnptr = &sline[0];
X	for (i=0; i < term.t_ncol; i++)
X		*lnptr++ = SPACE | attr;
X
X#if 0	/* Heath/Zenith builds flicker-less CGAs */
X	if (flickcode) {
X		/* wait for vertical retrace to be off */
X		while ((inp(0x3da) & 8))
X			;
X	
X		/* and to be back on */
X		while ((inp(0x3da) & 8) == 0)
X			;
X	}
X#endif
X
X	/* and send the string out */
X	movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2);
X
X}
X
Xz309putc(ch)	/* put a character at the current position in the
X		   current colors */
X
Xint ch;
X
X{
X	rg.h.ah = 14;		/* write char to screen with current attrs */
X	rg.h.al = ch;
X#if	COLOR
X	if (dtype != CDMONO)
X		rg.h.bl = cfcolor;
X	else
X		rg.h.bl = 0x07;
X#else
X	rg.h.bl = 0x07;
X#endif
X	int86(0x10, &rg, &rg);
X}
X
Xz309eeop()
X{
X	int attr;		/* attribute to fill screen with */
X
X	rg.h.ah = 6;		/* scroll page up function code */
X	rg.h.al = 0;		/* # lines to scroll (clear it) */
X	rg.x.cx = 0;		/* upper left corner of scroll */
X/*HERE*/	rg.x.dx = 0x184f;	/* lower right corner of scroll */
X#if	COLOR
X	if (dtype != CDMONO)
X		attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
X	else
X		attr = 0;
X#else
X	attr = 0;
X#endif
X	rg.h.bh = attr;
X	int86(0x10, &rg, &rg);
X}
X
Xz309rev(state)		/* change reverse video state */
X
Xint state;	/* TRUE = reverse, FALSE = normal */
X
X{
X	/* This never gets used under the z309-PC driver */
X}
X
Xz309cres(res)	/* change screen resolution */
X
Xchar *res;	/* resolution to change to */
X
X{
X	if (strcmp(res, "CGA50") == 0) {
X		scinit(CDCGA50);
X		return(TRUE);
X	} else if (strcmp(res, "MONO") == 0) {
X		scinit(CDMONO);
X		return(TRUE);
X	} else
X		return(FALSE);
X}
X
Xz309beep()
X{
X#if	MWC86
X	putcnb(BEL);
X#else
X	bdos(6, BEL, 0);
X#endif
X}
X
Xz309open()
X{
X	scinit(CDSENSE);
X	revexist = TRUE;
X        ttopen();
X}
X
Xz309close()
X
X{
X	rg.h.ah = 101;
X	rg.h.al = 1;	/* 25-line interlace mode */
X	int86(0x10, &rg, &rg); 
X#if	COLOR
X	z309fcol(7);
X	z309bcol(0);
X#endif
X	ttclose();
X}
X
Xz309kopen()	/* open the keyboard */
X
X{
X}
X
Xz309kclose()	/* close the keyboard */
X
X{
X}
X
Xscinit(type)	/* initialize the screen head pointers */
X
Xint type;	/* type of adapter to init for */
X
X{
X	union {
X		long laddr;	/* long form of address */
X		int *paddr;	/* pointer form of address */
X	} addr;
X	int i;
X
X	/* if asked...find out what display is connected */
X	int86(0x11, &rg, &rg);
X	dtype = CDCGA50;
X	scadd = SCADC;
X	strcpy(sres, "CGA50");
X	if ((((rg.x.ax >> 4) & 11) == 3) || type == CDMONO) {
X		strcpy(sres, "MONO");
X		dtype = CDMONO;
X		scadd = SCADM;
X	}
X	else {
X		rg.h.ah = 101;
X/* set al = 1 for 25-line interlace mode */		
X		rg.h.al = 2;	/* 50-line interlace mode */
X		int86(0x10, &rg, &rg); 
X	}
X
X	/* initialize the screen pointer array */
X	for (i = 0; i < NROW; i++) {
X		addr.laddr = scadd + (long)(NCOL * i * 2);
X		scptr[i] = addr.paddr;
X	}
X}
X
Xscwrite(row, outstr, forg, bacg)	/* write a line out*/
X
Xint row;	/* row of screen to place outstr on */
Xchar *outstr;	/* string to write out (must be term.t_ncol long) */
Xint forg;	/* forground color of string to write */
Xint bacg;	/* background color */
X
X{
X	int attr;	/* attribute byte mask to place in RAM */
X	int *lnptr;	/* pointer to the destination line */
X	int i;
X
X	/* build the attribute byte and setup the screen pointer */
X#if	COLOR
X	if (dtype != CDMONO)
X		attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
X	else
X		attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
X#else
X	attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
X#endif
X	lnptr = &sline[0];
X	for (i=0; i<term.t_ncol; i++)
X		*lnptr++ = (outstr[i] & 255) | attr;
X
X#if 0	/* Heath/Zenith builds flicker-less CGAs */
X	if (flickcode) {
X		/* wait for vertical retrace to be off */
X		while ((inp(0x3da) & 8))
X			;
X	
X		/* and to be back on */
X		while ((inp(0x3da) & 8) == 0)
X			;
X	}
X#endif	
X
X	/* and send the string out */
X	movmem(&sline[0], scptr[row],term.t_ncol*2);
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
Xz309hello()
X{
X}
X#endif
E!O!F
newsize=`wc -c < z309.c`
if [ $newsize -ne 7806 ]
then echo "File z309.c was $newsize bytes, 7806 expected"
fi
	bill davidsen		(wedu@ge-crd.arpa)
  {chinet | philabs | sesimo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me