From:	CSBVAX::MRGATE!montnaro@sprite@SMTP 19-MAR-1987 20:27
To:	EVERHART
Subj:	v09i043:  MicroEMACS, version3.8b, Part11/14

Received: by sprite.steinmetz (3.2/1.1x Steinmetz)
	id AA05753; Thu, 19 Mar 87 20:20:26 EST
Date: Thu, 19 Mar 87 20:20:26 EST
From: Skip Montanaro <montnaro%sprite.tcpip@csbvax>
Posted-Date: Thu, 19 Mar 87 20:20:26 EST
Message-Id: <8703200120.AA05753@sprite.steinmetz>
To: everhart@arisia.decnet

Path: steinmetz!albany!rpics3b!rpics!seismo!rutgers!mit-eddie!mirror!sources-request
From: sources-request@mirror.TMC.COM
Newsgroups: mod.sources
Subject: v09i043:  MicroEMACS, version3.8b, Part11/14
Message-ID: <2367@mirror.TMC.COM>
Date: 17 Mar 87 23:47:50 GMT
Sender: rs@mirror.TMC.COM
Lines: 1840
Approved: rs@mirror.TMC.COM

Submitted by: ihnp4!itivax!duncan!lawrence (Daniel Lawrence)
Mod.sources: Volume 9, Issue 43
Archive-name: uemacs3.8b/Part11

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
#		"End of archive 11 (of 14)."
# Contents:  display.c emacs.tut
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"display.c\" \(23826 characters\)
if test -f display.c ; then 
  echo shar: Will not over-write existing file \"display.c\"
else
sed "s/^X//" >display.c <<'END_OF_display.c'
X/*
X * The functions in this file handle redisplay. There are two halves, the
X * ones that update the virtual display screen, and the ones that make the
X * physical display screen the same as the virtual display screen. These
X * functions use hints that are left in the windows by the commands.
X *
X */
X
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if	MEGAMAX & ST520
Xoverlay	"display"
X#endif
X
Xtypedef struct  VIDEO {
X        int	v_flag;                 /* Flags */
X#if	COLOR
X	int	v_fcolor;		/* current forground color */
X	int	v_bcolor;		/* current background color */
X	int	v_rfcolor;		/* requested forground color */
X	int	v_rbcolor;		/* requested background color */
X#endif
X        char    v_text[1];              /* Screen data. */
X}       VIDEO;
X
X#define VFCHG   0x0001                  /* Changed flag			*/
X#define	VFEXT	0x0002			/* extended (beyond column 80)	*/
X#define	VFREV	0x0004			/* reverse video status		*/
X#define	VFREQ	0x0008			/* reverse video request	*/
X#define	VFCOL	0x0010			/* color change requested	*/
X
XVIDEO   **vscreen;                      /* Virtual screen. */
X#if	MEMMAP == 0
XVIDEO   **pscreen;                      /* Physical screen. */
X#endif
X
X/*
X * Initialize the data structures used by the display code. The edge vectors
X * used to access the screens are set up. The operating system's terminal I/O
X * channel is set up. All the other things get initialized at compile time.
X * The original window has "WFCHG" set, so that it will get completely
X * redrawn on the first call to "update".
X */
Xvtinit()
X{
X    register int i;
X    register VIDEO *vp;
X    char *malloc();
X
X    TTopen();		/* open the screen */
X    TTkopen();		/* open the keyboard */
X    TTrev(FALSE);
X    vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
X
X    if (vscreen == NULL)
X        exit(1);
X
X#if	MEMMAP == 0
X    pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
X
X    if (pscreen == NULL)
X        exit(1);
X#endif
X
X    for (i = 0; i < term.t_nrow; ++i)
X        {
X        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
X
X        if (vp == NULL)
X            exit(1);
X
X	vp->v_flag = 0;
X#if	COLOR
X	vp->v_rfcolor = 7;
X	vp->v_rbcolor = 0;
X#endif
X        vscreen[i] = vp;
X#if	MEMMAP == 0
X        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
X
X        if (vp == NULL)
X            exit(1);
X
X	vp->v_flag = 0;
X        pscreen[i] = vp;
X#endif
X        }
X}
X
X/*
X * Clean up the virtual terminal system, in anticipation for a return to the
X * operating system. Move down to the last line and clear it out (the next
X * system prompt will be written in the line). Shut down the channel to the
X * terminal.
X */
Xvttidy()
X{
X    mlerase();
X    movecursor(term.t_nrow, 0);
X    TTflush();
X    TTclose();
X    TTkclose();
X}
X
X/*
X * Set the virtual cursor to the specified row and column on the virtual
X * screen. There is no checking for nonsense values; this might be a good
X * idea during the early stages.
X */
Xvtmove(row, col)
X{
X    vtrow = row;
X    vtcol = col;
X}
X
X/* Write a character to the virtual screen. The virtual row and
X   column are updated. If we are not yet on left edge, don't print
X   it yet. If the line is too long put a "$" in the last column.
X   This routine only puts printing characters into the virtual
X   terminal buffers. Only column overflow is checked.
X*/
X
Xvtputc(c)
X
Xint c;
X
X{
X	register VIDEO *vp;	/* ptr to line being updated */
X
X	vp = vscreen[vtrow];
X
X	if (c == '\t') {
X		do {
X			vtputc(' ');
X		} while (((vtcol + taboff)&0x07) != 0);
X	} else if (vtcol >= term.t_ncol) {
X		++vtcol;
X		vp->v_text[term.t_ncol - 1] = '$';
X	} else if (c < 0x20 || c == 0x7F) {
X		vtputc('^');
X		vtputc(c ^ 0x40);
X	} else {
X		if (vtcol >= 0)
X			vp->v_text[vtcol] = c;
X		++vtcol;
X	}
X}
X
X/*
X * Erase from the end of the software cursor to the end of the line on which
X * the software cursor is located.
X */
Xvteeol()
X{
X    register VIDEO      *vp;
X
X    vp = vscreen[vtrow];
X    while (vtcol < term.t_ncol)
X        vp->v_text[vtcol++] = ' ';
X}
X
X/* upscreen:	user routine to force a screen update
X		always finishes complete update		*/
X
Xupscreen(f, n)
X
X{
X	update(TRUE);
X	return(TRUE);
X}
X
X/*
X * Make sure that the display is right. This is a three part process. First,
X * scan through all of the windows looking for dirty ones. Check the framing,
X * and refresh the screen. Second, make sure that "currow" and "curcol" are
X * correct for the current window. Third, make the virtual and physical
X * screens the same.
X */
Xupdate(force)
X
Xint force;	/* force update past type ahead? */
X
X{
X	register WINDOW *wp;
X
X#if	TYPEAH
X	if (force == FALSE && typahead())
X		return(TRUE);
X#endif
X#if	VISMAC == 0
X	if (force == FALSE && kbdmode == PLAY)
X		return(TRUE);
X#endif
X
X	/* update any windows that need refreshing */
X	wp = wheadp;
X	while (wp != NULL) {
X		if (wp->w_flag) {
X			/* if the window has changed, service it */
X			reframe(wp);	/* check the framing */
X			if ((wp->w_flag & ~WFMODE) == WFEDIT)
X				updone(wp);	/* update EDITed line */
X			else if (wp->w_flag & ~WFMOVE)
X				updall(wp);	/* update all lines */
X			if (wp->w_flag & WFMODE)
X				modeline(wp);	/* update modeline */
X			wp->w_flag = 0;
X			wp->w_force = 0;
X		}
X		/* on to the next window */
X		wp = wp->w_wndp;
X	}
X
X	/* recalc the current hardware cursor location */
X	updpos();
X
X#if	MEMMAP
X	/* update the cursor and flush the buffers */
X	movecursor(currow, curcol - lbound);
X#endif
X
X	/* check for lines to de-extend */
X	upddex();
X
X	/* if screen is garbage, re-plot it */
X	if (sgarbf != FALSE)
X		updgar();
X
X	/* update the virtual screen to the physical screen */
X	updupd(force);
X
X	/* update the cursor and flush the buffers */
X	movecursor(currow, curcol - lbound);
X	TTflush();
X	return(TRUE);
X}
X
X/*	reframe:	check to see if the cursor is on in the window
X			and re-frame it if needed or wanted		*/
X
Xreframe(wp)
X
XWINDOW *wp;
X
X{
X	register LINE *lp;
X	register int i;
X
X	/* if not a requested reframe, check for a needed one */
X	if ((wp->w_flag & WFFORCE) == 0) {
X		lp = wp->w_linep;
X		for (i = 0; i < wp->w_ntrows; i++) {
X
X			/* if the line is in the window, no reframe */
X			if (lp == wp->w_dotp)
X				return(TRUE);
X
X			/* if we are at the end of the file, reframe */
X			if (lp == wp->w_bufp->b_linep)
X				break;
X
X			/* on to the next line */
X			lp = lforw(lp);
X		}
X	}
X
X	/* reaching here, we need a window refresh */
X	i = wp->w_force;
X
X	/* how far back to reframe? */
X	if (i > 0) {		/* only one screen worth of lines max */
X		if (--i >= wp->w_ntrows)
X			i = wp->w_ntrows - 1;
X	} else if (i < 0) {	/* negative update???? */
X		i += wp->w_ntrows;
X		if (i < 0)
X			i = 0;
X	} else
X		i = wp->w_ntrows / 2;
X
X	/* backup to new line at top of window */
X	lp = wp->w_dotp;
X	while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
X		--i;
X		lp = lback(lp);
X	}
X
X	/* and reset the current line at top of window */
X	wp->w_linep = lp;
X	wp->w_flag |= WFHARD;
X	wp->w_flag &= ~WFFORCE;
X	return(TRUE);
X}
X
X/*	updone:	update the current line	to the virtual screen		*/
X
Xupdone(wp)
X
XWINDOW *wp;	/* window to update current line in */
X
X{
X	register LINE *lp;	/* line to update */
X	register int sline;	/* physical screen line to update */
X	register int i;
X
X	/* search down the line we want */
X	lp = wp->w_linep;
X	sline = wp->w_toprow;
X	while (lp != wp->w_dotp) {
X		++sline;
X		lp = lforw(lp);
X	}
X
X	/* and update the virtual line */
X	vscreen[sline]->v_flag |= VFCHG;
X	vscreen[sline]->v_flag &= ~VFREQ;
X	vtmove(sline, 0);
X	for (i=0; i < llength(lp); ++i)
X		vtputc(lgetc(lp, i));
X#if	COLOR
X	vscreen[sline]->v_rfcolor = wp->w_fcolor;
X	vscreen[sline]->v_rbcolor = wp->w_bcolor;
X#endif
X	vteeol();
X}
X
X/*	updall:	update all the lines in a window on the virtual screen */
X
Xupdall(wp)
X
XWINDOW *wp;	/* window to update lines in */
X
X{
X	register LINE *lp;	/* line to update */
X	register int sline;	/* physical screen line to update */
X	register int i;
X
X	/* search down the lines, updating them */
X	lp = wp->w_linep;
X	sline = wp->w_toprow;
X	while (sline < wp->w_toprow + wp->w_ntrows) {
X
X		/* and update the virtual line */
X		vscreen[sline]->v_flag |= VFCHG;
X		vscreen[sline]->v_flag &= ~VFREQ;
X		vtmove(sline, 0);
X		if (lp != wp->w_bufp->b_linep) {
X			/* if we are not at the end */
X			for (i=0; i < llength(lp); ++i)
X				vtputc(lgetc(lp, i));
X			lp = lforw(lp);
X		}
X
X		/* on to the next one */
X#if	COLOR
X		vscreen[sline]->v_rfcolor = wp->w_fcolor;
X		vscreen[sline]->v_rbcolor = wp->w_bcolor;
X#endif
X		vteeol();
X		++sline;
X	}
X
X}
X
X/*	updpos:	update the position of the hardware cursor and handle extended
X		lines. This is the only update for simple moves.	*/
X
Xupdpos()
X
X{
X	register LINE *lp;
X	register int c;
X	register int i;
X
X	/* find the current row */
X	lp = curwp->w_linep;
X	currow = curwp->w_toprow;
X	while (lp != curwp->w_dotp) {
X		++currow;
X		lp = lforw(lp);
X	}
X
X	/* find the current column */
X	curcol = 0;
X	i = 0;
X	while (i < curwp->w_doto) {
X		c = lgetc(lp, i++);
X		if (c == '\t')
X			curcol |= 0x07;
X		else
X			if (c < 0x20 || c == 0x7f)
X				++curcol;
X
X		++curcol;
X	}
X
X	/* if extended, flag so and update the virtual line image */
X	if (curcol >=  term.t_ncol - 1) {
X		vscreen[currow]->v_flag |= (VFEXT | VFCHG);
X		updext();
X	} else
X		lbound = 0;
X}
X
X/*	upddex:	de-extend any line that derserves it		*/
X
Xupddex()
X
X{
X	register WINDOW *wp;
X	register LINE *lp;
X	register int i,j;
X
X	wp = wheadp;
X
X	while (wp != NULL) {
X		lp = wp->w_linep;
X		i = wp->w_toprow;
X
X		while (i < wp->w_toprow + wp->w_ntrows) {
X			if (vscreen[i]->v_flag & VFEXT) {
X				if ((wp != curwp) || (lp != wp->w_dotp) ||
X				   (curcol < term.t_ncol - 1)) {
X					vtmove(i, 0);
X					for (j = 0; j < llength(lp); ++j)
X						vtputc(lgetc(lp, j));
X					vteeol();
X
X					/* this line no longer is extended */
X					vscreen[i]->v_flag &= ~VFEXT;
X					vscreen[i]->v_flag |= VFCHG;
X				}
X			}
X			lp = lforw(lp);
X			++i;
X		}
X		/* and onward to the next window */
X		wp = wp->w_wndp;
X	}
X}
X
X/*	updgar:	if the screen is garbage, clear the physical screen and
X		the virtual screen and force a full update		*/
X
Xupdgar()
X
X{
X	register char *txt;
X	register int i,j;
X
X	for (i = 0; i < term.t_nrow; ++i) {
X		vscreen[i]->v_flag |= VFCHG;
X#if	REVSTA
X		vscreen[i]->v_flag &= ~VFREV;
X#endif
X#if	COLOR
X		vscreen[i]->v_fcolor = gfcolor;
X		vscreen[i]->v_bcolor = gbcolor;
X#endif
X#if	MEMMAP == 0
X		txt = pscreen[i]->v_text;
X		for (j = 0; j < term.t_ncol; ++j)
X			txt[j] = ' ';
X#endif
X	}
X
X	movecursor(0, 0);		 /* Erase the screen. */
X	(*term.t_eeop)();
X	sgarbf = FALSE;			 /* Erase-page clears */
X	mpresf = FALSE;			 /* the message area. */
X#if	COLOR
X	mlerase();			/* needs to be cleared if colored */
X#endif
X}
X
X/*	updupd:	update the physical screen from the virtual screen	*/
X
Xupdupd(force)
X
Xint force;	/* forced update flag */
X
X{
X	register VIDEO *vp1;
X	register int i;
X
X	for (i = 0; i < term.t_nrow; ++i) {
X		vp1 = vscreen[i];
X
X		/* for each line that needs to be updated*/
X		if ((vp1->v_flag & VFCHG) != 0) {
X#if	TYPEAH
X			if (force == FALSE && typahead())
X				return(TRUE);
X#endif
X#if	MEMMAP
X			updateline(i, vp1);
X#else
X			updateline(i, vp1, pscreen[i]);
X#endif
X		}
X	}
X	return(TRUE);
X}
X
X/*	updext: update the extended line which the cursor is currently
X		on at a column greater than the terminal width. The line
X		will be scrolled right or left to let the user see where
X		the cursor is
X								*/
X
Xupdext()
X
X{
X	register int rcursor;	/* real cursor location */
X	register LINE *lp;	/* pointer to current line */
X	register int j;		/* index into line */
X
X	/* calculate what column the real cursor will end up in */
X	rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
X	taboff = lbound = curcol - rcursor + 1;
X
X	/* scan through the line outputing characters to the virtual screen */
X	/* once we reach the left edge					*/
X	vtmove(currow, -lbound);	/* start scanning offscreen */
X	lp = curwp->w_dotp;		/* line to output */
X	for (j=0; j<llength(lp); ++j)	/* until the end-of-line */
X		vtputc(lgetc(lp, j));
X
X	/* truncate the virtual line, restore tab offset */
X	vteeol();
X	taboff = 0;
X
X	/* and put a '$' in column 1 */
X	vscreen[currow]->v_text[0] = '$';
X}
X
X/*
X * Update a single line. This does not know how to use insert or delete
X * character sequences; we are using VT52 functionality. Update the physical
X * row and column variables. It does try an exploit erase to end of line. The
X * RAINBOW version of this routine uses fast video.
X */
X#if	MEMMAP
X/*	UPDATELINE specific code for the IBM-PC and other compatables */
X
Xupdateline(row, vp1)
X
Xint row;		/* row of screen to update */
Xstruct VIDEO *vp1;	/* virtual screen image */
X
X{
X#if	COLOR
X	scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
X	vp1->v_fcolor = vp1->v_rfcolor;
X	vp1->v_bcolor = vp1->v_rbcolor;
X#else
X	if (vp1->v_flag & VFREQ)
X		scwrite(row, vp1->v_text, 0, 7);
X	else
X		scwrite(row, vp1->v_text, 7, 0);
X#endif
X	vp1->v_flag &= ~(VFCHG | VFCOL);	/* flag this line as changed */
X
X}
X
X#else
X
Xupdateline(row, vp1, vp2)
X
Xint row;		/* row of screen to update */
Xstruct VIDEO *vp1;	/* virtual screen image */
Xstruct VIDEO *vp2;	/* physical screen image */
X
X{
X#if RAINBOW
X/*	UPDATELINE specific code for the DEC rainbow 100 micro	*/
X
X    register char *cp1;
X    register char *cp2;
X    register int nch;
X
X    /* since we don't know how to make the rainbow do this, turn it off */
X    flags &= (~VFREV & ~VFREQ);
X
X    cp1 = &vp1->v_text[0];                    /* Use fast video. */
X    cp2 = &vp2->v_text[0];
X    putline(row+1, 1, cp1);
X    nch = term.t_ncol;
X
X    do
X        {
X        *cp2 = *cp1;
X        ++cp2;
X        ++cp1;
X        }
X    while (--nch);
X    *flags &= ~VFCHG;
X#else
X/*	UPDATELINE code for all other versions		*/
X
X	register char *cp1;
X	register char *cp2;
X	register char *cp3;
X	register char *cp4;
X	register char *cp5;
X	register int nbflag;	/* non-blanks to the right flag? */
X	int rev;		/* reverse video flag */
X	int req;		/* reverse video request flag */
X
X
X	/* set up pointers to virtual and physical lines */
X	cp1 = &vp1->v_text[0];
X	cp2 = &vp2->v_text[0];
X
X#if	COLOR
X	TTforg(vp1->v_rfcolor);
X	TTbacg(vp1->v_rbcolor);
X#endif
X
X#if	REVSTA | COLOR
X	/* if we need to change the reverse video status of the
X	   current line, we need to re-write the entire line     */
X	rev = (vp1->v_flag & VFREV) == VFREV;
X	req = (vp1->v_flag & VFREQ) == VFREQ;
X	if ((rev != req)
X#if	COLOR
X	    || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
X#endif
X#if	HP150
X	/* the HP150 has some reverse video problems */
X	    || req || rev
X#endif
X			) {
X		movecursor(row, 0);	/* Go to start of line. */
X		/* set rev video if needed */
X		if (rev != req)
X			(*term.t_rev)(req);
X
X		/* scan through the line and dump it to the screen and
X		   the virtual screen array				*/
X		cp3 = &vp1->v_text[term.t_ncol];
X		while (cp1 < cp3) {
X			TTputc(*cp1);
X			++ttcol;
X			*cp2++ = *cp1++;
X		}
X		/* turn rev video off */
X		if (rev != req)
X			(*term.t_rev)(FALSE);
X
X		/* update the needed flags */
X		vp1->v_flag &= ~VFCHG;
X		if (req)
X			vp1->v_flag |= VFREV;
X		else
X			vp1->v_flag &= ~VFREV;
X#if	COLOR
X		vp1->v_fcolor = vp1->v_rfcolor;
X		vp1->v_bcolor = vp1->v_rbcolor;
X#endif
X		return(TRUE);
X	}
X#endif
X
X	/* advance past any common chars at the left */
X	while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) {
X		++cp1;
X		++cp2;
X	}
X
X/* This can still happen, even though we only call this routine on changed
X * lines. A hard update is always done when a line splits, a massive
X * change is done, or a buffer is displayed twice. This optimizes out most
X * of the excess updating. A lot of computes are used, but these tend to
X * be hard operations that do a lot of update, so I don't really care.
X */
X	/* if both lines are the same, no update needs to be done */
X	if (cp1 == &vp1->v_text[term.t_ncol]) {
X 		vp1->v_flag &= ~VFCHG;		/* flag this line is changed */
X		return(TRUE);
X	}
X
X	/* find out if there is a match on the right */
X	nbflag = FALSE;
X	cp3 = &vp1->v_text[term.t_ncol];
X	cp4 = &vp2->v_text[term.t_ncol];
X
X	while (cp3[-1] == cp4[-1]) {
X		--cp3;
X		--cp4;
X		if (cp3[0] != ' ')		/* Note if any nonblank */
X			nbflag = TRUE;		/* in right match. */
X	}
X
X	cp5 = cp3;
X
X	/* Erase to EOL ? */
X	if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
X		while (cp5!=cp1 && cp5[-1]==' ')
X			--cp5;
X
X		if (cp3-cp5 <= 3)		/* Use only if erase is */
X			cp5 = cp3;		/* fewer characters. */
X	}
X
X	movecursor(row, cp1 - &vp1->v_text[0]);	/* Go to start of line. */
X#if	REVSTA
X	TTrev(rev);
X#endif
X
X	while (cp1 != cp5) {		/* Ordinary. */
X		TTputc(*cp1);
X		++ttcol;
X		*cp2++ = *cp1++;
X	}
X
X	if (cp5 != cp3) {		/* Erase. */
X		TTeeol();
X		while (cp1 != cp3)
X			*cp2++ = *cp1++;
X	}
X#if	REVSTA
X	TTrev(FALSE);
X#endif
X	vp1->v_flag &= ~VFCHG;		/* flag this line as updated */
X	return(TRUE);
X#endif
X}
X#endif
X
X/*
X * Redisplay the mode line for the window pointed to by the "wp". This is the
X * only routine that has any idea of how the modeline is formatted. You can
X * change the modeline format by hacking at this routine. Called by "update"
X * any time there is a dirty window.
X */
Xmodeline(wp)
X    WINDOW *wp;
X{
X    register char *cp;
X    register int c;
X    register int n;		/* cursor position count */
X    register BUFFER *bp;
X    register i;			/* loop index */
X    register lchar;		/* character to draw line in buffer with */
X    register firstm;		/* is this the first mode? */
X    char tline[NLINE];		/* buffer for part of mode line */
X
X    n = wp->w_toprow+wp->w_ntrows;      	/* Location. */
X    vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
X#if	COLOR
X    vscreen[n]->v_rfcolor = 0;			/* black on */
X    vscreen[n]->v_rbcolor = 7;			/* white.....*/
X#endif
X    vtmove(n, 0);                       	/* Seek to right line. */
X    if (wp == curwp)				/* mark the current buffer */
X	lchar = '=';
X    else
X#if	REVSTA
X	if (revexist)
X		lchar = ' ';
X	else
X#endif
X		lchar = '-';
X
X    vtputc(lchar);
X    bp = wp->w_bufp;
X
X    if ((bp->b_flag&BFCHG) != 0)                /* "*" if changed. */
X        vtputc('*');
X    else
X        vtputc(lchaX
X    n  = 2;
X    strcpy(tline, " MicroEMACS ");		/* Buffer name. */
X    strcat(tline, VERSION);
X    strcat(tline, " (");
X
X    /* display the modes */
X
X	firstm = TRUE;
X	for (i = 0; i < NUMMODES; i++)	/* add in the mode flags */
X		if (wp->w_bufp->b_mode & (1 << i)) {
X			if (firstm != TRUE)
X				strcat(tline, " ");
X			firstm = FALSE;
X			strcat(tline, modename[i]);
X		}
X	strcat(tline,") ");
X
X    cp = &tline[0];
X    while ((c = *cp++) != 0)
X        {
X        vtputc(c);
X        ++n;
X        }
X
X#if 0
X    vtputc(lchar);
X    vtputc((wp->w_flag&WFCOLR) != 0  ? 'C' : lchar);
X    vtputc((wp->w_flag&WFMODE) != 0  ? 'M' : lchar);
X    vtputc((wp->w_flag&WFHARD) != 0  ? 'H' : lchar);
X    vtputc((wp->w_flag&WFEDIT) != 0  ? 'E' : lchar);
X    vtputc((wp->w_flag&WFMOVE) != 0  ? 'V' : lchar);
X    vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar);
X    vtputc(lchar);
X    n += 8;
X#endif
X
X    vtputc(lchar);
X    vtputc(lchar);
X    vtputc(' ');
X    n += 3;
X    cp = &bp->b_bname[0];
X
X    while ((c = *cp++) != 0)
X        {
X        vtputc(c);
X        ++n;
X        }
X
X    vtputc(' ');
X    vtputc(lchar);
X    vtputc(lchar);
X    n += 3;
X
X    if (bp->b_fname[0] != 0)            /* File name. */
X        {
X	vtputc(' ');
X	++n;
X        cp = "File: ";
X
X        while ((c = *cp++) != 0)
X            {
X            vtputc(c);
X            ++n;
X            }
X
X        cp = &bp->b_fname[0];
X
X        while ((c = *cp++) != 0)
X            {
X            vtputc(c);
X            ++n;
X            }
X
X        vtputc(' ');
X        ++n;
X        }
X
X    while (n < term.t_ncol)             /* Pad to full width. */
X        {
X        vtputc(lchar);
X        ++n;
X        }
X}
X
Xupmode()	/* update all the mode lines */
X
X{
X	register WINDOW *wp;
X
X	wp = wheadp;
X	while (wp != NULL) {
X		wp->w_flag |= WFMODE;
X		wp = wp->w_wndp;
X	}
X}
X
X/*
X * Send a command to the terminal to move the hardware cursor to row "row"
X * and column "col". The row and column arguments are origin 0. Optimize out
X * random calls. Update "ttrow" and "ttcol".
X */
Xmovecursor(row, col)
X    {
X    if (row!=ttrow || col!=ttcol)
X        {
X        ttrow = row;
X        ttcol = col;
X        TTmove(row, col);
X        }
X    }
X
X/*
X * Erase the message line. This is a special routine because the message line
X * is not considered to be part of the virtual screen. It always works
X * immediately; the terminal buffer is flushed via a call to the flusher.
X */
Xmlerase()
X    {
X    int i;
X    
X    movecursor(term.t_nrow, 0);
X#if	COLOR
X     TTforg(7);
X     TTbacg(0);
X#endif
X    if (eolexist == TRUE)
X	    TTeeol();
X    else {
X        for (i = 0; i < term.t_ncol - 1; i++)
X            TTputc(' ');
X        movecursor(term.t_nrow, 1);	/* force the move! */
X        movecursor(term.t_nrow, 0);
X    }
X    TTflush();
X    mpresf = FALSE;
X    }
X
X/*
X * Write a message into the message line. Keep track of the physical cursor
X * position. A small class of printf like format items is handled. Assumes the
X * stack grows down; this assumption is made by the "++" in the argument scan
X * loop. Set the "message line" flag TRUE.
X */
X
Xmlwrite(fmt, arg)
X    char *fmt;
X    {
X    register int c;
X    register char *ap;
X
X#if	COLOR
X	TTforg(7);
X	TTbacg(0);
X#endif
X    if (eolexist == FALSE) {
X        mlerase();
X        TTflush();
X    }
X
X    movecursor(term.t_nrow, 0);
X    ap = (char *) &arg;
X    while ((c = *fmt++) != 0) {
X        if (c != '%') {
X            TTputc(c);
X            ++ttcol;
X            }
X        else
X            {
X            c = *fmt++;
X            switch (c) {
X                case 'd':
X                    mlputi(*(int *)ap, 10);
X                    ap += sizeof(int);
X                    break;
X
X                case 'o':
X                    mlputi(*(int *)ap,  8);
X                    ap += sizeof(int);
X                    break;
X
X                case 'x':
X                    mlputi(*(int *)ap, 16);
X                    ap += sizeof(int);
X                    break;
X
X                case 'D':
X                    mlputli(*(long *)ap, 10);
X                    ap += sizeof(long);
X                    break;
X
X                case 's':
X                    mlputs(*(char **)ap);
X                    ap += sizeof(char *);
X                    break;
X
X		case 'f':
X		    mlputf(*(int *)ap);
X		    ap += sizeof(int);
X		    break;
X
X                default:
X                    TTputc(c);
X                    ++ttcol;
X                }
X            }
X        }
X    if (eolexist == TRUE)
X        TTeeol();
X    TTflush();
X    mpresf = TRUE;
X    }
X
X/*
X * Write out a string. Update the physical cursor position. This assumes that
X * the characters in the string all have width "1"; if this is not the case
X * things will get screwed up a little.
X */
Xmlputs(s)
X    char *s;
X    {
X    register int c;
X
X    while ((c = *s++) != 0)
X        {
X        TTputc(c);
X        ++ttcol;
X        }
X    }
X
X/*
X * Write out an integer, in the specified radix. Update the physical cursor
X * position.
X */
Xmlputi(i, r)
X    {
X    register int q;
X    static char hexdigits[] = "0123456789ABCDEF";
X
X    if (i < 0)
X        {
X        i = -i;
X        TTputc('-');
X        }
X
X    q = i/r;
X
X    if (q != 0)
X        mlputi(q, r);
X
X    TTputc(hexdigits[i%r]);
X    ++ttcol;
X    }
X
X/*
X * do the same except as a long integer.
X */
Xmlputli(l, r)
X    long l;
X    {
X    register long q;
X
X    if (l < 0)
X        {
X        l = -l;
X        TTputc('-');
X        }
X
X    q = l/r;
X
X    if (q != 0)
X        mlputli(q, r);
X
X    TTputc((int)(l%r)+'0');
X    ++ttcol;
X    }
X
X/*
X *	write out a scaled integer with two decimal places
X */
X
Xmlputf(s)
X
Xint s;	/* scaled integer to output */
X
X{
X	int i;	/* integer portion of number */
X	int f;	/* fractional portion of number */
X
X	/* break it up */
X	i = s / 100;
X	f = s % 100;
X
X	/* send out the integer portion */
X	mlputi(i, 10);
X	TTputc('.');
X	TTputc((f / 10) + '0');
X	TTputc((f % 10) + '0');
X	ttcol += 3;
X}	
X
X#if RAINBOW
X
Xputline(row, col, buf)
X    int row, col;
X    char buf[];
X    {
X    int n;
X
X    n = strlen(buf);
X    if (col + n - 1 > term.t_ncol)
X        n = term.t_ncol - col + 1;
X    Put_Data(row, col, n, buf);
X    }
X#endif
X
END_OF_display.c
if test 23826 -ne `wc -c <display.c`; then
    echo shar: \"display.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: Extracting \"emacs.tut\" \(29549 characters\)
if test -f emacs.tut ; then 
  echo shar: Will not over-write existing file \"emacs.tut\"
else
sed "s/^X//" >emacs.tut <<'END_OF_emacs.tut'
XYou are looking at the MicroEMACS tutorial.  Comments on this document may
Xbe referred to Daniel Lawrance.
X
XNOTE:  This tutorial attempts to help you "learn by doing".  The characters
X       ">>" at the left margin of your screen indicate directions for you to
X       try using a command.
X
XEMACS commands generally involve the CONTROL key (sometimes labelled CTRL
Xor CTL) or the META key (generally labelled ESCAPE).  Rather than write out
XCONTROL or META each time we want you to prefix a character, we'll use the
Xfollowing abbreviations:
X
X   ^<chr>    Hold the CONTROL key while pressing the character <chr>.
X             Thus, ^F would be:  hold the CONTROL key and press F.
X
X>>  Now type ^V (View Next Screen) to move to the next screen.
X    Remember:  hold the CONTROL key and press V.
X
X   ESC-<chr>  Press the ESCAPE key and release it, then press the
X              character <chr>.  Note:  The command will have the
X              same meaning for upper or lower case characters (<chr>).
X
XIMPORTANT NOTE:  If you must exit at some point, type ^X^C.
X
XFor the time being, you'll be expected to type ^V whenever you finish reading
Xthe current screen.
X
XNote that there is an overlap when going from screen to screen; this provides
Xsome continuity when moving through the file.
X
XThe first thing that you need to know is how to move around from place to
Xplace in the file.  You already know how to move forward a screen with ^V.
XTo move back a screen, type ^Z.
X
X>>  Try typing ^Z and then ^V to move back and forth between screens a few
X    times.
X
X
XSUMMARY
X-------
X
XThe following commands are useful for viewing screens:
X
X     ^V       Move forward one screen
X     ^Z       Move back one screen
X     ESC-^L   Clear screen and redisplay everything, putting the text
X              near the cursor at the center of the screen.
X
X>>  Find the cursor and remember what text is near it.  Type an ESC-^L.
X    Find the cursor again and see what text is near it now.
X
X
XBASIC CURSOR CONTROL
X--------------------
X
XGetting from screen to screen is useful, but how do you reposition yourself
Xwithin a given screen to a specific place?  There are several ways you can
Xdo this.  One way (not the best, but the most basic) is to use the commands
Xprevious, backward, forward and next.  As you can imagine these commands
X(which are given to EMACS as ^P, ^B, ^F, and ^N  respectively) move the
Xcursor from where it currently is to a new place in the given direction.
XHere, in a more graphical form, are the commands:
X
X                          Previous line, ^P
X                                  :
X                                  :
X   Backward, ^B .... Current cursor position .... Forward, ^F
X                                  :
X                                  :
X                          Next line, ^N
X
XYou'll probably find it easy to think of these by letter.  P for previous,
XN for next, B for backward and F for forward.  These are the basic cursor
Xpositioning commands and you'll be using them ALL the time so it would be
Xof great benefit if you learn them now.
X
X>>  Do a few ^N's to bring the cursor down to this line.
X
X>>  Move into the line with ^F's and then up with several ^P's.  Note what
X    ^P does when the cursor is in the middle of the line.
X
X>>  Try ^B at the beginning of a line.  Note what happened to the cursor.
X    Do a few more ^B's.  Then do ^F's back to the end of the line and beyond.
X
XWhen you go off the top or bottom of the screen, the text beyond the edge is
Xshifted onto the screen so that your instructions can be carried out while
Xkeeping the cursor on the screen.
X
X>>  Move the cursor off the bottom of the screen with ^N's and see what
X    happens.  Note the new position of the cursor.
X
XIf moving by characters is too slow, you can move by words.  ESC-F moves
Xforward a word and ESC-B moves back a word.
X
X>>  Type a few ESC-F's and ESC-B's.  Intersperse them with ^F's and ^B's.
X
XNotice the parallel between ^F and ^B on the one hand, and ESC-F and ESC-B on
Xthe other hand.  Very often META characters are used for operations related
Xto English text whereas CONTROL characters operate on the basic textual units
Xthat are independent of what you are editing (characters, lines, etc.).
X
XTwo other commands which are useful are ^A and ^E.  These commands move the
Xcursor to the beginning (^A) and the end (^E) of the line.
X
X>>  Try a couple of ^A's, and then a couple of ^E's.  Note that the cursor
X    does not move when either of these commands is repeated continuously.
X
XTwo other simple cursor motion commands are ESC-< (less than), which moves
Xto the beginning of the file, and ESC-> (greater than), which moves to the
Xend of the file.  If you need the shift key to type a "<", then you must
Xalso use the shift key to type ESC-<.  Otherwise, you would be typing ESC-, .
X
XThe location of the cursor within the text is also called "point".  To
Xparaphrase, the cursor shows on the screen where point is located in the
Xtext.
X
XHere is a summary of simple moving operations, including the word and
Xline moving commands:
X
X     ^F        Move forward a character
X     ^B        Move back a character
X
X     ESC-F     Move forward a word
X     ESC-B     Move back a word
X
X     ^N        Move to next line
X     ^P        Move to previous line
X
X     ESC-N     Move to next paragraph
X     ESC-P     Move to previous paragraph
X
X     ^A        Move to beginning of line
X     ^E        Move to end of line
X
X     ESC-<     Go to beginning of file
X     ESC->     Go to end of file
X
X>>  Try all of these commands now a few times for practice as these are
X    the most often used commands.  Since the last two will take you away
X    from this screen, use ^V's and ^Z's to return here.
X
XLike all other commands in EMACS, these commands can be given arguments
Xwhich cause them to be executed repeatedly.  The way you give a command
Xa repeat count is by pressing META (ESC) and then the number before you
Xenter the command.  As a special case, typing ^U is equivalent to ESC-4.
X
XFor instance, ESC-8 ^F moves forward eight characters.
X
X>>  Try giving a suitable argument to ^N or ^P to come as close as you
X    can to this line in one jump.
X
XThis also applies to the screen moving commands, ^V and ^Z.  When given
Xan argument, they scroll the screen up or down by that many screens.
X
X>>  Try typing ESC-3 ^V now.
X
XIf you would like to scroll up, you can give an argument to ^Z.
X
X
XABORTING COMMANDS
X-----------------
X
XThe EMACS command used to abort any command which requests input is
X^G.  For example, you can use ^G to discard a numeric argument or at
Xthe beginning of a command that you don't want to finish.
X
X>>  Type ESC-100 to make a numeric argument of 100, then type ^G.
X    Now type ^F.  How many characters does it move?  If you have
X    typed an ESC by mistake, you can get rid of it with ^G^G.
X
X
XERRORS
X------
XSometimes you may do something which EMACS doesn't allow.  If it is
Xsomething simple, such as typing a CONTROL key sequence which is not
Xassociated with any command, EMACS will just beep at you.  Otherwise,
XEMACS will also display an informative error message at the bottom of
Xthe screen.
X
XSome versions of EMACS do not have all the features described in this
Xtutorial implemented yet.  If you come across such an unimplemented
Xfeature, you may get an error message when you try to use it.  Just
Xpress any cursor movement key and proceed to the next section of the
Xtutorial.
X
X
XNOTE:  Several of the exercises in the following sections allow you to use
X       options which will make changes to this tutorial. Do no worry about
X       these changes affecting the tutorial - this is only a copy of the
X       master tutorial and you will not be instructed to save the changes
X       made to it.
X
X
XCURSOR KEYS
X-----------
X
XThe cursor keypad, usually located on the right side of the keyboard,
Xhas been bound to some of the more useful screen movement commands.
XThe mappings are as follows:
X
X     Cursor-Right    ^F        Move forward a character
X     Cursor-Left     ^B        Move back a character
X
X
X     ^Cursor-Right   ESC-F     Move forward a word
X     ^Cursor-Left    ESC-B     Move back a word
X
X
X     Cursor-Down     ^N        Move to next line
X     Cursor-Up       ^P        Move to previous line
X
X
X     Pg-Dn           ^V        Move to next screen
X     Pg-Up           ^Z        Move to previous screen
X
X
X     Home            ESC-<     Go to beginning of file
X     End             ESC->     Go to end of file
X
X
X     Insert          ^C        Insert single space
X     Delete          ^D        Delete current character
X
XA map of the keypad layout looks something like this:
X
X                   -------------------------------------------------
X                   | 7             | 8             | 9             |
X                   | Home          | ^             | Pg Up         |
X                   |        ESC-<  | |         ^P  |           ^Z  |
X                   -------------------------------------------------
X                   | 4             | 5             | 6             |
X                   | <--       ^B  |               | -->       ^F  |
X                   -------------------------------------------------
X                   | 1             | 2             | 3             |
X                   | End           | |             | Pg Dn         |
X                   |        ESC->  | v         ^N  |           ^V  |
X       -------------------------------------------------------------
X       | 0                           | .                           |
X       | Insert                  ^C  | Delete                  ^D  |
X       -------------------------------------------------------------
X
X>>  Practice using the cursor keypad.
X
X
XMODE LINE
X---------
X
XThe line above the function key display at the bottom of the screen
Xis referred to as the "communication line".  This is where EMACS
Xinteractively communicates with you.  Later you will see how EMACS
Xprompts you for information on this line, such as to initiate a
Xsearch.  EMACS can report things to you on this line as well.
X
X>>  Type ^X= and see what appears in the communication line. Don't worry
X    about what all this information means - it is just an example of how
X    EMACS lets you know more about the file you are editing.
X
XThe line immediately above the communication line is referred to as the
X"mode line".  The mode line looks something like
X
X=* MicroEMACS 3.7 () == emacs.tut == File: emacs.tut ===========================
X
XThis is a very useful "information" line.
X
X  -  The asterisk (star) indicates that changes have been made to the file.
X     Immediately after opening or saving a file, there is no star.
X
X  -  Any words inside the parentheses indicate the "modes" EMACS is
X     currently in.  Modes will be discussed in the next section.
X
X  -  The string following the () is the buffername, i.e., the name EMACS
X     gives to the buffer, and it is usually related to the filename.
X
X  -  The string following "File:" is the name of the file you are
X     currently editing.
X
X>>  Look at the mode line and identify the items discussed above.
X
X
XMODES
X-----
X
XListed within the parentheses are the "modes" which are associated with
Xthe current buffer.  Modes are a feature of EMACS which assist in the
Xediting of different languages, i.e., C, and text.  Presently, there are
Xno modes associated with this buffer.  This means EMACS will do exactly
Xwhat you think it will when using it - no "bonuses".  You can find out
Xmore about the current buffer and mode status by typing ^X^B.  Refer to
Xthe EMACS manual for a further discussion of buffers and modes.
X
XAs you become more familiar with EMACS and the use of buffers, "mode"
Xtakes on additional meaning.  When more than one buffer is in use, a
Xmode is referred to as "local" or "global".  These terms indicate how a
Xmode will affect the current buffer and other existing or to be added
Xbuffers.
X
XA "local" mode is valid only within the scope of the current buffer.
XOther existing buffers and buffers which will be added are not affected
Xby local modes.
X
XThe commands to add and delete local modes are
X
X     ^XM       Add a local mode
X     ^X^M      Delete a local mode
X
XEach of the above commands will prompt you for a mode.  To activate
X(deactivate) a mode, type the name of a valid (active) mode (refer to
XEMACS manual for a complete list of the valid modes) and follow it by
Xpressing <Return>, the carriage-return key.
X
X>>  Type ^XM WRAP - note the change in the mode line.  Move the cursor
X    to a blank line on this screen and begin typing the sequence "asdf ".
X    Continue typing this sequence and note what happens when the right
X    margin is encountered.
X
XThe previous exercise allowed you to enter text with the "WRAP" mode
Xactive.  As you can see, "WRAP" instructs EMACS to break between words
Xwhen a line gets too long.  However, in order for this mode to be
Xeffective, spaces must be inserted between words.
X
XThe right margin is usually set at 72 characters but it can be changed.
XTo change the margin type ESC nn ^XF where "nn" is the column number of
Xthe new right-hand margin.
X
X>>  Type ESC 40 ^XF.  Then begin typing "asdf " and notice where the
X    line now breaks.  To return to the default right-hand margin, type
X    ESC 72 ^XF.
X
X>>  Type ^X^M WRAP to "turn off" the local mode "WRAP".
X
XA "global" mode affects only those buffers which will be ADDED after the
X"add/delete global mode" command is executed - not the current or other
Xexisting buffers.  Currently there is no global mode set.
X
XThe commands to add and delete global modes are
X
X     ESC-M     Add a global mode
X     ESC-^M    Delete a global mode
X
XNote:  All modes can be local.  However, global modes allow you to
X       activate those modes which usually apply to most of the buffers
X       in use.
X
XAs with local modes, each of the above commands will prompt you for
Xa mode.  To activate (deactivate) a mode, enter the name of a valid
X(active) mode.
X
X>>  Type ESC-M OVER.  This mode tells EMACS to write over the text on
X    the current line.  Is there any change in the mode line? Now move to
X    the line of "asdf " you entered and start typing.  Note that nothing
X    happens.  Remember that global modes affect only those modes which
X    will be added - not those already existing.
X
X>>  Type ESC-^M OVER to "turn off" the global overwrite mode.
X
X
XINSERTING AND DELETING
X----------------------
X
XIf you want to type text, just start typing.  Characters which you
Xcan see, such as A, 7, *, etc. are taken by EMACS as text and are
Ximmediately inserted.  Type <Return> to insert a line separator,
Xi.e., a single linefeed character.
X
XYou can delete the last character you typed by typing either <Delete>
Xor ^H.  On some keyboards, there is a dedicated key for creating a ^H.
XIf so, it is usually labelled as either "Backspace" or "<--".  <Delete>
Xis a key on the keyboard, which may be labelled "Rubout" instead of
X"Delete" on some terminals.  More generally, <Delete> deletes the
Xcharacter immediately before the current cursor position.
X
X>>  Now type a few characters and then delete them by typing <Delete>
X    a few times.
X
X>>  Now start typing text until you reach the right margin, then continue
X    to type.  When a line of text gets too big for one line on the screen,
X    the line of text is "continued" off the edge of the screen.  The dollar
X    sign at the right margin indicates a line which has been continued.
X    EMACS scrolls the line over so you can see what you are editing.  The
X    "$" at the left or right edge of the screen indicates that the current
X    line extends off in that direction.
X
XThis concept is easier to understand by doing rather than by reading about
Xit so it is suggested that the following exercises be done.
X
X>>  The following line actually goes off the edge.  Try typing enough ESC-F's
X    so that you move off the right hand end of this line.  This is a long line of text.  Note the "$" at each edge.  Keep typing E
SC-F's and watch where EMACS decides to scroll the line.  Now, type ESC-B's until EMACS decides to scroll the line again.
X
X>>  Go to the line you entered which the text continued off the edge of
X    the screen.  Use ^D's to delete the text until the text line fits on
X    one screen line again.  The continuation "$" will go away.
X
X>>  Move the cursor to the beginning of a line and type <Delete>.  This
X    deletes the line separator before the line and merges the line onto
X    the previous line.  The resulting line may be too long to fit on the
X    screen, in which case it has a continuation indicator.
X
X>>  Press <Return> to insert the separator again.
X
XInternally, EMACS will allow you to have lines of nearly any length, limited
Xonly by the amount of memory available.  Externally, however, EMACS can only
Xread or write lines, to or from a file, which are less than or equal to 255
Xcharacters.
X
XRemember that most EMACS commands can be given a repeat count.  Note that
Xthis includes characters which insert themselves.
X
X>>  Try that now -- type ESC-8 * and see what happens.
X
XIf you want to insert spaces in a line, type ^C.
X
X>>  Move to a line and move the cursor with ^F's; then insert spaces with ^C.
X    Use ^D to remove the spaces.
X
XIf you want to create a blank line between two lines, move to the second
Xof the two lines and type ^O.
X
X>>  Try moving to a line and typing ^O now.
X
XYou've now learned the most basic way of typing something in EMACS and
Xcorrecting errors.  You can delete characters, words or lines as well.
XHere is a summary of the delete operations:
X
X     <Delete>      Delete the character just before the cursor
X     ^H            Delete the character just before the cursor
X     ^D            Delete the character the cursor is under
X
X     ESC-<Delete>  Kill the word immediately before the cursor
X     ESC-^H        Kill the word immediately before the cursor
X     ESC-D         Kill the word from the cursor position
X
X     ^K            Kill from the cursor position to end of line
X
XNotice that <Delete> and ^D vs ESC-<Delete> and ESC-D extend the parallel
Xstarted by ^F and ESC-F (well, <Delete> isn't really a control character,
Xbut let's not worry about that).
X
XNow suppose you kill something, and then you decide that you want to get
Xit back?  Well, whenever you kill something bigger than a character, EMACS
Xsaves it for you.  To yank it back, use ^Y.  Note that you don't have to
Xbe in the same place to do ^Y.  This is a good way to move text around.
XAlso note the difference between "Killing" and "Deleting" - "Killed" text
Xcan be yanked back, and "Deleted" text cannot.  Generally, the commands
Xthat can destroy a lot of text save it, while the ones that attack only
Xone character do not save it.
X
X>>  Type ^N a couple times to position the cursor at some line on this
X    screen.  Now kill that line with ^K.
X
XNote that a single ^K kills the contents of the line, and a second ^K
Xkills the line itself, and makes all the other lines move up.  If you
Xgive ^K a repeat count, it kills that many lines AND their contents.
X
XThe text that has just disappeared is saved so that you can retrieve it.
XTo retrieve the last killed text and put it where the cursor currently
Xis, type ^Y.
X
X>>  Try it.  Type ^Y to yank the text back.
X
XThink of ^Y as if you were yanking something back that someone took away
Xfrom you.  Notice that if you do several ^K's in a row the text that is
Xkilled is all saved together so that one ^Y will yank all of the lines.
X
X>>  Try it.  Type ^K several times.
X
X>>  To retrieve that killed text:  Type ^Y.  Move the cursor down a few
X    lines and type ^Y again.  You now know how to copy text.
X
XWhat do you do if you have some text you want to yank back, and then
Xyou kill something else?  ^Y would yank the more recent kill.
X
X>>  Kill a line, move around, kill another line.  Then do ^Y to get back
X    the second killed line.
X
X
XSEARCHING
X---------
X
XEMACS can do searches for strings (these are groups of contiguous
Xcharacters or words) either forward through the file or backward
Xthrough it.
X
X>>  Now type ^S to start a search.  Type the word "cursor", then ESC.
X
X>>  Type ^S ESC to find the next occurrence of "cursor".
X
XThe ^S starts a search that looks for any occurrence of the search
Xstring AFTER the current cursor position.  But what if you want to
Xsearch for something earlier in the text?  To do this one should
Xtype ^R for Reverse search.  Everything that applies to ^S applies
Xto ^R except that the direction of the search is reversed.
X
X
XTEXT REPLACEMENT
X----------------
X
X>>  Move the cursor to the blank line two lines below this one.
X    Then type ESC-R changed ESC altered ESC .
X
X    Notice how this line has changed; you have replaced the word
X    "changed" with "altered" wherever it occurs in the file after
X    the cursor.  After all the substitutions have been made or
X    the end of file has been reached, a message informing you of
X    the number of substitutions which have been made appears in
X    the communication line.
X
XThe more customary command for replacing strings is the interactive
Xcommand query-replace-search (ESC-^R), which has several options.  In
Xessence, it shows each occurrence of the first string and asks you if
Xyou want to replace it or not.  Type a "?" when it asks to replace the
Xstring to list the various options for query-replace-search.  For a
Xmore detailed discussion of this command refer to the EMACS manual.
X
X
XFILES
X-----
X
XIn order to make the text changes permanent, you must save them to a file.
XIf you do not save them, the changes will "disappear" when you leave EMACS.
XAs you make changes, i.e., corrections, deletions, insertions, etc., they
Xare actually written to a "scratch" copy of the file and the changes to
Xthis file will not affect the "master" copy of the file until a file save
Xis specified. This allows you to decide if changes made to the file should
Xbe made permanent or discarded.
X
XRemember:  The file name appears on the mode line.
X
X=* MicroEMACS 3.7 () == emacs.tut == File: emacs.tut ===========================
X                                     ---------------
X
XThe commands for finding and saving files are unlike the other commands
Xyou have learned so far in that they consist of two characters - a ^X
Xfollowed by another character which specifies the file command to be
Xexecuted.
X
XTo find a file, type ^X^F.  EMACS will then prompt you from the
Xcommunication line for the name of the file.  In response to the prompt,
Xtype the file name followed by a <Return> to indicate the file name has
Xbeen entered.  This command will tell EMACS to go find this file and
Xload it.  Its contents will then be displayed on the screen and you will
Xbe able to edit the file's contents.
X
XTo save any changes made to the file, type ^X^S.  This tells EMACS to
Xcreate a new version of the file which includes the changes you have
Xmade.  When the save is complete, the number of lines saved will be
Xdisplayed in the communication line.
X
XIf you edit a file and at some point decide to quit (i.e., ^X^C) without
Xsaving the changes, EMACS will remind you that changes have been made to
Xthe file and ask you if you really want to quit.  Enter "N" to return to
XEMACS or "Y" to exit EMACS without saving the changes.
X
XTo create a file, just edit it "as if" it already existed.  Then start
Xtyping in the text.  When you ask to "save" the file, EMACS will really
Xcreate the file with the text that you have entered.  From then on, you
Xcan consider yourself to be editing an existing file.
X
XIt is not easy for you to test editing a file and continue with the
Xtutorial.  But you can always come back into the tutorial by starting
Xit over and skipping forward.  So, when you feel ready, you should
Xtry editing a file named "FOO", putting some text in it, and saving
Xit; then exit EMACS and look at the file to be sure that it worked.
X
X
XEXTENDING THE COMMAND SET
X-------------------------
X
XThere are many, many more EMACS commands than could possibly be put on all
Xthe CONTROL and META characters.  EMACS gets around this with the X (eXtend)
Xcommand.  There are two forms of this command:
X
X     ^X       Character eXtend.  Followed by one character.
X     ESC-X    Named command eXtend.  Followed by a long name.
X
XThese are commands that are generally useful but used less than the commands
Xyou have already learned about.  You have already seen two of them: the file
Xcommands ^X^F to Find and ^X^S to Save.  Another example is the command to
Xtell EMACS that you'd like to stop editing.  The command to do this is ^X^C.
X
XThere are many ^X commands.  Right now, the most helpful ones will be
X
X     ^X^F   Find file.
X     ^X^S   Save file.
X     ^X^C   Quit EMACS.  This does not save your files automatically;
X              however, if your files have been modified, EMACS asks if
X              you really want to quit.  The standard way to save and
X              exit is ^X^S ^X^C.
X
XNamed eXtended commands are commands which are used even less frequently,
Xor commands which are used only in certain modes.  These commands are
Xusually called "functions".  An example is the function "apropos", which
Xprompts for a keyword and then gives the names of all the functions that
Xare apropos for that keyword.  When you type ESC-X, EMACS prompts you from
Xthe communication line with ":" and you should type the name of the
Xfunction you wish to call; in this case, "apropos".  Just type "apr<Space>"
Xand EMACS will complete the name.  EMACS will ask you for a keyword or
Xphrase and you type the string that you want information on.
X
X>>  Type ESC-X, followed by "apropos<Return>" or "apr<Space>".  Then
X    type "file" followed by a <Return>.  Note: ESC-A is equivalent to
X    the ECS-X "apropos" command.
X
X>>  To remove the "window" that was added, type ^X0 (zero).
X
X
XFUNCTION KEYS
X-------------
X
XBy now, you should be familiar with the format and meaning of some of
Xthe more common CONTROL and META commands.  Because several of these
Xcommands are used frequently, they have been bound to the function
Xkeys, which are usually located on the left-hand side of the keyboard
Xand labelled F1..F10.  By pressing the appropriate function key, one
Xcan replace several keystrokes with a single keystroke, thus saving
Xyou time as you become familiar with their use.
X
XThe highlighted portion at the top of the screen lists the commands
Xwhich are associated with each function key.  Each function key supports
Xtwo commands specified by fn or Fn where n = 1, 2,...10.  The default
Xcommands are represented by fn and are defined on the left side of the
Xscreen; these commands are executed by pressing the appropriate function
Xkey.  The secondary commands are represented by Fn and are defined on
Xthe right side of the screen; these commands are executed by pressing
Xthe <Shift> key and the appropriate function key at the same time.
X
X>>  Press f1 would ESC.  Note the position of the cursor - "would"
X    was located just as if ^S would ESC had been entered.  Enter
X    ^S would ESC to see for yourself.
X
X>>  Press F1 (<Shift> f1).  Note the different appearance of the screen.
X    You have toggled the function key list, i.e., "turned it off".  To
X    "turn it on", press F1 again.
X
X>>  Try using some of the other function keys to become familiar with
X    their use.  NOTE:  Do NOT use f9 with this file as it would save
X    any changes you may have made while using the tutorial.
X
X
XGETTING MORE HELP
X-----------------
X
XIn this tutorial we have tried to supply just enough information to get
Xyou started using EMACS.  There is so much available in EMACS that it
Xwould be impossible to explain it all here.  However, you may want to
Xlearn more about EMACS since it has numerous desirable features that you
Xdon't know about yet.
X
XThe most basic HELP feature is the describe-key function which is
Xavailable by typing ^X? and then a command character.  EMACS prints
Xone line in the communication line to tell what function is bound
Xto that key.
X
X>>  Type ^X?^P.  The message in the communication line should
X    be something like "^P is bound to previous-line".
X
XNOTE:  Multi-character commands such as ^X^Z and ESC-V are also
X       allowed after ^X? .
X
X###  The describe-command function does not work - December 1986  ###
X###  Skip to the next section                                     ###
X
XThe describe-command function (ESC-?) will prompt for the name of a
Xfunction and print out the section from the manual about that command.
XWhen you are finished reading it, type a space or a ^G (quit) to bring
Xyour text back on the screen.
X
XNow let's get more information about the previous-line command.
X
X>>  Type ESC-?^P.  When you are finished reading the output, type <Space>.
X
XThe "name of the function" is important for people who are customizing
XEMACS.  It is what appears in the EMACS CHART as the documentation for
Xthe command character.
X
X
XCONCLUSION
X----------
X
XRemember:  To EXIT use ^X^C.
X
XThis tutorial is meant to be understandable to all new users, so if
Xyou found something unclear, don't sit and blame yourself - complain!
X
XYou'll probably find that if you use EMACS for a few days you won't be
Xable to give it up.  Initially it may give you trouble.  But remember,
Xthis is the case with any editor, especially one that can do many, many
Xthings - and EMACS can do practically everything.
X
X
XACKNOWLEDGEMENTS
X----------------
X
XThis is a modified version of the "JOVE Tutorial" by Jonathan Payne
X(19 January 86).  That document was in turn a modified version of
Xthe tutorial "Teach-Emacs" from MIT as modified by Steve Zimmerman
Xat CCA-UNIX (31 October 85).
X
XUpdate - February 1986 by Dana Hoggatt.
X
XUpdate - December 1986 by Kim Leburg.
END_OF_emacs.tut
if test 29549 -ne `wc -c <emacs.tut`; then
    echo shar: \"emacs.tut\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 11 \(of 14\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 14 archives.
    echo "See the readme file"
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
