[openfirmware] r897 - in clients/emacs: . x86

svn at openfirmware.info svn at openfirmware.info
Fri Aug 29 00:25:58 CEST 2008


Author: wmb
Date: 2008-08-29 00:25:57 +0200 (Fri, 29 Aug 2008)
New Revision: 897

Added:
   clients/emacs/ansi.c
   clients/emacs/basic.c
   clients/emacs/bind.c
   clients/emacs/buffer.c
   clients/emacs/dg10.c
   clients/emacs/display.c
   clients/emacs/ebind.h
   clients/emacs/edef.h
   clients/emacs/efunc.h
   clients/emacs/emacs.hlp
   clients/emacs/emacs.key
   clients/emacs/emacs.rc
   clients/emacs/emacs.tut
   clients/emacs/emacs2.mss
   clients/emacs/emacsfm.rc
   clients/emacs/emacsobp.rc
   clients/emacs/epath.h
   clients/emacs/estruct.h
   clients/emacs/estructp.h
   clients/emacs/exec.c
   clients/emacs/file.c
   clients/emacs/fileio.c
   clients/emacs/hp150.c
   clients/emacs/ibmpc.c
   clients/emacs/input.c
   clients/emacs/isearch.c
   clients/emacs/line.c
   clients/emacs/lock.c
   clients/emacs/main.c
   clients/emacs/makefile
   clients/emacs/makefile.obp
   clients/emacs/me.man
   clients/emacs/menu.cmd
   clients/emacs/menu1
   clients/emacs/ofwtermio.c
   clients/emacs/random.c
   clients/emacs/readme
   clients/emacs/readme.dl
   clients/emacs/region.c
   clients/emacs/search.c
   clients/emacs/spawn.c
   clients/emacs/tags
   clients/emacs/tcap.c
   clients/emacs/termio.c
   clients/emacs/vmsvt.c
   clients/emacs/vt52.c
   clients/emacs/window.c
   clients/emacs/word.c
   clients/emacs/x86/Makefile
   clients/emacs/x86/config.h
   clients/emacs/x86/emacs.lds
   clients/emacs/x86/emacs.rc
Log:
Checked in EMACS client program files.


Added: clients/emacs/ansi.c
===================================================================
--- clients/emacs/ansi.c	                        (rev 0)
+++ clients/emacs/ansi.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,227 @@
+/*
+ * The routines in this file provide support for ANSI style terminals
+ * over a serial line. The serial I/O services are provided by routines in
+ * "termio.c". It compiles into nothing if not an ANSI device.
+ */
+
+#define	termdef	1			/* don't define "term" external */
+
+#include	"estruct.h"
+#include        "edef.h"
+
+#if     ANSI
+
+#if	AMIGA
+#define NROW    23                      /* Screen size.                 */
+#define NCOL    77                      /* Edit if you want to.         */
+#else
+/*
+ * PCs really have 25 lines, but the VT100 terminal emulator in the
+ * MS Windows "Terminal" accessory does really bad things if you tell
+ * it to go to line 25
+ */
+#define NROW    24                      /* Screen size.                 */
+#define NCOL    80                      /* Edit if you want to.         */
+#endif
+#define	NPAUSE	100			/* # times thru update to pause */
+#define	MARGIN	8			/* size of minimim margin and	*/
+#define	SCRSIZ	64			/* scroll size for extended lines */
+#define BEL     0x07                    /* BEL character.               */
+#define ESC     0x1B                    /* ESC character.               */
+
+extern  int     ttopen();               /* Forward references.          */
+extern  int     ttgetc();
+extern  int     ttputc();
+extern  int     ttflush();
+extern  int     ttclose();
+extern  int     ansimove();
+extern  int     ansieeol();
+extern  int     ansieeop();
+extern  int     ansibeep();
+extern  int     ansiopen();
+extern	int	ansirev();
+extern	int	ansiclose();
+
+#if	COLOR
+extern	int	ansifcol();
+extern	int	ansibcol();
+
+int	cfcolor = -1;		/* current forground color */
+int	cbcolor = -1;		/* current background color */
+#endif
+
+/*
+ * Standard terminal interface dispatch table. Most of the fields point into
+ * "termio" code.
+ */
+TERM    term    = {
+        NROW-1,
+        NCOL,
+	MARGIN,
+	SCRSIZ,
+	NPAUSE,
+        ansiopen,
+        ansiclose,
+        ttgetc,
+        ttputc,
+        ttflush,
+        ansimove,
+        ansieeol,
+        ansieeop,
+        ansibeep,
+	ansirev
+#if	COLOR
+	, ansifcol,
+	ansibcol
+#endif
+};
+
+#if	COLOR
+ansifcol(color)		/* set the current output color */
+
+int color;	/* color to set */
+
+{
+	if (color == cfcolor)
+		return;
+	ttputc(ESC);
+	ttputc('[');
+	ansiparm(color+30);
+	ttputc('m');
+	cfcolor = color;
+}
+
+ansibold()
+{
+	ttputc(ESC);
+	ttputc('[');
+	ttputc('1');
+	ttputc('m');
+}
+
+ansibcol(color)		/* set the current background color */
+
+int color;	/* color to set */
+
+{
+	if (color == cbcolor)
+		return;
+	ttputc(ESC);
+	ttputc('[');
+	ansiparm(color+40);
+	ttputc('m');
+        cbcolor = color;
+}
+#endif
+
+ansimove(row, col)
+{
+        ttputc(ESC);
+        ttputc('[');
+        ansiparm(row+1);
+        ttputc(';');
+        ansiparm(col+1);
+        ttputc('H');
+}
+
+ansieeol()
+{
+        ttputc(ESC);
+        ttputc('[');
+        ttputc('K');
+}
+
+ansieeop()
+{
+#if	COLOR
+	ansifcol(gfcolor);
+	ansibcol(gbcolor);
+#endif
+        ttputc(ESC);
+        ttputc('[');
+        ttputc('J');
+}
+
+ansirev(state)		/* change reverse video state */
+
+int state;	/* TRUE = reverse, FALSE = normal */
+
+{
+#if	COLOR
+	int ftmp, btmp;		/* temporaries for colors */
+
+	if (state == FALSE) {
+		ftmp = cfcolor;
+		btmp = cbcolor;
+		cfcolor = -1;
+		cbcolor = -1;
+		ansifcol(ftmp);
+		ansibcol(btmp);
+	}
+#else
+	ttputc(ESC);
+	ttputc('[');
+	ttputc(state ? '7': '0');
+	ttputc('m');
+#endif
+}
+
+ansibeep()
+{
+        ttputc(BEL);
+        ttflush();
+}
+
+ansiparm(n)
+register int    n;
+{
+        register int q,r;
+
+        q = n/10;
+        if (q != 0) {
+		r = q/10;
+		if (r != 0) {
+			ttputc((r%10)+'0');
+		}
+		ttputc((q%10) + '0');
+        }
+        ttputc((n%10) + '0');
+}
+
+ansiopen()
+{
+#if     V7 | USG | BSD
+        register char *cp;
+        char *getenv();
+
+        if ((cp = getenv("TERM")) == NULL) {
+                puts("Shell variable TERM not defined!");
+                exit(1);
+        }
+        if (strcmp(cp, "vt100") != 0) {
+                puts("Terminal type not 'vt100'!");
+                exit(1);
+        }
+#endif
+#if	OFW
+	term.t_nrow = stdout_rows() - 1;
+	term.t_ncol = stdout_columns();
+#endif
+	revexist = TRUE;
+        ttopen();
+}
+
+ansiclose()
+
+{
+#if	COLOR
+	ansifcol(7);
+	ansibcol(0);
+#endif
+	ttclose();
+}
+#else
+ansihello()
+{
+}
+#endif

Added: clients/emacs/basic.c
===================================================================
--- clients/emacs/basic.c	                        (rev 0)
+++ clients/emacs/basic.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,382 @@
+/*
+ * The routines in this file move the cursor around on the screen. They
+ * compute a new value for the cursor, then adjust ".". The display code
+ * always updates the cursor location, so only moves between lines, or
+ * functions that adjust the top line in the window and invalidate the
+ * framing, are hard.
+ */
+#include	"estruct.h"
+#include        "edef.h"
+
+/*
+ * Move the cursor to the
+ * beginning of the current line.
+ * Trivial.
+ */
+gotobol(f, n)
+{
+        curwp->w_doto  = 0;
+        return (TRUE);
+}
+
+/*
+ * Move the cursor backwards by "n" characters. If "n" is less than zero call
+ * "forwchar" to actually do the move. Otherwise compute the new cursor
+ * location. Error if you try and move out of the buffer. Set the flag if the
+ * line pointer for dot changes.
+ */
+backchar(f, n)
+register int    n;
+{
+        register LINE   *lp;
+
+        if (n < 0)
+                return (forwchar(f, -n));
+        while (n--) {
+                if (curwp->w_doto == 0) {
+                        if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
+                                return (FALSE);
+                        curwp->w_dotp  = lp;
+                        curwp->w_doto  = llength(lp);
+                        curwp->w_flag |= WFMOVE;
+                } else
+                        curwp->w_doto--;
+        }
+        return (TRUE);
+}
+
+/*
+ * Move the cursor to the end of the current line. Trivial. No errors.
+ */
+gotoeol(f, n)
+{
+        curwp->w_doto  = llength(curwp->w_dotp);
+        return (TRUE);
+}
+
+/*
+ * Move the cursor forwwards by "n" characters. If "n" is less than zero call
+ * "backchar" to actually do the move. Otherwise compute the new cursor
+ * location, and move ".". Error if you try and move off the end of the
+ * buffer. Set the flag if the line pointer for dot changes.
+ */
+forwchar(f, n)
+register int    n;
+{
+        if (n < 0)
+                return (backchar(f, -n));
+        while (n--) {
+                if (curwp->w_doto == llength(curwp->w_dotp)) {
+                        if (curwp->w_dotp == curbp->b_linep)
+                                return (FALSE);
+                        curwp->w_dotp  = lforw(curwp->w_dotp);
+                        curwp->w_doto  = 0;
+                        curwp->w_flag |= WFMOVE;
+                } else
+                        curwp->w_doto++;
+        }
+        return (TRUE);
+}
+
+gotoline(f, n)		/* move to a particular line.
+			   argument (n) must be a positive integer for
+			   this to actually do anything		*/
+
+{
+	if (n < 1)		/* if a bogus argument...then leave */
+		return(FALSE);
+
+	/* first, we go to the start of the buffer */
+        curwp->w_dotp  = lforw(curbp->b_linep);
+        curwp->w_doto  = 0;
+	return(forwline(f, n-1));
+}
+
+/*
+ * Goto the beginning of the buffer. Massive adjustment of dot. This is
+ * considered to be hard motion; it really isn't if the original value of dot
+ * is the same as the new value of dot. Normally bound to "M-<".
+ */
+gotobob(f, n)
+{
+        curwp->w_dotp  = lforw(curbp->b_linep);
+        curwp->w_doto  = 0;
+        curwp->w_flag |= WFHARD;
+        return (TRUE);
+}
+
+/*
+ * Move to the end of the buffer. Dot is always put at the end of the file
+ * (ZJ). The standard screen code does most of the hard parts of update.
+ * Bound to "M->".
+ */
+gotoeob(f, n)
+{
+        curwp->w_dotp  = curbp->b_linep;
+        curwp->w_doto  = 0;
+        curwp->w_flag |= WFHARD;
+        return (TRUE);
+}
+
+/*
+ * Move forward by full lines. If the number of lines to move is less than
+ * zero, call the backward line function to actually do it. The last command
+ * controls how the goal column is set. Bound to "C-N". No errors are
+ * possible.
+ */
+forwline(f, n)
+{
+        register LINE   *dlp;
+
+        if (n < 0)
+                return (backline(f, -n));
+        if ((lastflag&CFCPCN) == 0)             /* Reset goal if last   */
+                curgoal = getccol(FALSE);       /* not C-P or C-N       */
+        thisflag |= CFCPCN;
+        dlp = curwp->w_dotp;
+        while (n-- && dlp!=curbp->b_linep)
+                dlp = lforw(dlp);
+        curwp->w_dotp  = dlp;
+        curwp->w_doto  = getgoal(dlp);
+        curwp->w_flag |= WFMOVE;
+        return (TRUE);
+}
+
+/*
+ * This function is like "forwline", but goes backwards. The scheme is exactly
+ * the same. Check for arguments that are less than zero and call your
+ * alternate. Figure out the new line and call "movedot" to perform the
+ * motion. No errors are possible. Bound to "C-P".
+ */
+backline(f, n)
+{
+        register LINE   *dlp;
+
+        if (n < 0)
+                return (forwline(f, -n));
+        if ((lastflag&CFCPCN) == 0)             /* Reset goal if the    */
+                curgoal = getccol(FALSE);       /* last isn't C-P, C-N  */
+        thisflag |= CFCPCN;
+        dlp = curwp->w_dotp;
+        while (n-- && lback(dlp)!=curbp->b_linep)
+                dlp = lback(dlp);
+        curwp->w_dotp  = dlp;
+        curwp->w_doto  = getgoal(dlp);
+        curwp->w_flag |= WFMOVE;
+        return (TRUE);
+}
+
+#if	WORDPRO
+gotobop(f, n)	/* go back to the begining of the current paragraph
+		   here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
+		   combination to delimit the begining of a paragraph	*/
+
+int f, n;	/* default Flag & Numeric argument */
+
+{
+	register int suc;	/* success of last backchar */
+
+	if (n < 0)	/* the other way...*/
+		return(gotoeop(f, -n));
+
+	while (n-- > 0) {	/* for each one asked for */
+
+		/* first scan back until we are in a word */
+		suc = backchar(FALSE, 1);
+		while (!inword() && suc)
+			suc = backchar(FALSE, 1);
+		curwp->w_doto = 0;	/* and go to the B-O-Line */
+
+		/* and scan back until we hit a <NL><NL> or <NL><TAB>
+		   or a <NL><SPACE>					*/
+		while (lback(curwp->w_dotp) != curbp->b_linep)
+			if (llength(curwp->w_dotp) != 0 &&
+			    lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
+			    lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
+				curwp->w_dotp = lback(curwp->w_dotp);
+			else
+				break;
+
+		/* and then forward until we are in a word */
+		suc = forwchar(FALSE, 1);
+		while (suc && !inword())
+			suc = forwchar(FALSE, 1);
+	}
+	curwp->w_flag |= WFMOVE;	/* force screen update */
+	return(TRUE);
+}
+
+gotoeop(f, n)	/* go forword to the end of the current paragraph
+		   here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
+		   combination to delimit the begining of a paragraph	*/
+
+int f, n;	/* default Flag & Numeric argument */
+
+{
+	register int suc;	/* success of last backchar */
+
+	if (n < 0)	/* the other way...*/
+		return(gotobop(f, -n));
+
+	while (n-- > 0) {	/* for each one asked for */
+
+		/* first scan forward until we are in a word */
+		suc = forwchar(FALSE, 1);
+		while (!inword() && suc)
+			suc = forwchar(FALSE, 1);
+		curwp->w_doto = 0;	/* and go to the B-O-Line */
+		if (suc)	/* of next line if not at EOF */
+			curwp->w_dotp = lforw(curwp->w_dotp);
+
+		/* and scan forword until we hit a <NL><NL> or <NL><TAB>
+		   or a <NL><SPACE>					*/
+		while (curwp->w_dotp != curbp->b_linep) {
+			if (llength(curwp->w_dotp) != 0 &&
+			    lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
+			    lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
+				curwp->w_dotp = lforw(curwp->w_dotp);
+			else
+				break;
+		}
+
+		/* and then backward until we are in a word */
+		suc = backchar(FALSE, 1);
+		while (suc && !inword()) {
+			suc = backchar(FALSE, 1);
+		}
+		curwp->w_doto = llength(curwp->w_dotp);	/* and to the EOL */
+	}
+	curwp->w_flag |= WFMOVE;	/* force screen update */
+	return(TRUE);
+}
+#endif
+
+/*
+ * This routine, given a pointer to a LINE, and the current cursor goal
+ * column, return the best choice for the offset. The offset is returned.
+ * Used by "C-N" and "C-P".
+ */
+getgoal(dlp)
+register LINE   *dlp;
+{
+        register int    c;
+        register int    col;
+        register int    newcol;
+        register int    dbo;
+
+        col = 0;
+        dbo = 0;
+        while (dbo != llength(dlp)) {
+                c = lgetc(dlp, dbo);
+                newcol = col;
+                if (c == '\t')
+                        newcol |= 0x07;
+                else if (c<0x20 || c==0x7F)
+                        ++newcol;
+                ++newcol;
+                if (newcol > curgoal)
+                        break;
+                col = newcol;
+                ++dbo;
+        }
+        return (dbo);
+}
+
+/*
+ * Scroll forward by a specified number of lines, or by a full page if no
+ * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
+ * the overlap; this value is the default overlap value in ITS EMACS. Because
+ * this zaps the top line in the display window, we have to do a hard update.
+ */
+forwpage(f, n)
+register int    n;
+{
+        register LINE   *lp;
+
+        if (f == FALSE) {
+                n = curwp->w_ntrows - 2;        /* Default scroll.      */
+                if (n <= 0)                     /* Forget the overlap   */
+                        n = 1;                  /* if tiny window.      */
+        } else if (n < 0)
+                return (backpage(f, -n));
+#if     CVMVAS
+        else                                    /* Convert from pages   */
+                n *= curwp->w_ntrows;           /* to lines.            */
+#endif
+        lp = curwp->w_linep;
+        while (n-- && lp!=curbp->b_linep)
+                lp = lforw(lp);
+        curwp->w_linep = lp;
+        curwp->w_dotp  = lp;
+        curwp->w_doto  = 0;
+        curwp->w_flag |= WFHARD;
+        return (TRUE);
+}
+
+/*
+ * This command is like "forwpage", but it goes backwards. The "2", like
+ * above, is the overlap between the two windows. The value is from the ITS
+ * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
+ * reason.
+ */
+backpage(f, n)
+register int    n;
+{
+        register LINE   *lp;
+
+        if (f == FALSE) {
+                n = curwp->w_ntrows - 2;        /* Default scroll.      */
+                if (n <= 0)                     /* Don't blow up if the */
+                        n = 1;                  /* window is tiny.      */
+        } else if (n < 0)
+                return (forwpage(f, -n));
+#if     CVMVAS
+        else                                    /* Convert from pages   */
+                n *= curwp->w_ntrows;           /* to lines.            */
+#endif
+        lp = curwp->w_linep;
+        while (n-- && lback(lp)!=curbp->b_linep)
+                lp = lback(lp);
+        curwp->w_linep = lp;
+        curwp->w_dotp  = lp;
+        curwp->w_doto  = 0;
+        curwp->w_flag |= WFHARD;
+        return (TRUE);
+}
+
+/*
+ * Set the mark in the current window to the value of "." in the window. No
+ * errors are possible. Bound to "M-.".
+ */
+setmark(f, n)
+{
+        curwp->w_markp = curwp->w_dotp;
+        curwp->w_marko = curwp->w_doto;
+        mlwrite("[Mark set]");
+        return (TRUE);
+}
+
+/*
+ * Swap the values of "." and "mark" in the current window. This is pretty
+ * easy, bacause all of the hard work gets done by the standard routine
+ * that moves the mark about. The only possible error is "no mark". Bound to
+ * "C-X C-X".
+ */
+swapmark(f, n)
+{
+        register LINE   *odotp;
+        register int    odoto;
+
+        if (curwp->w_markp == NULL) {
+                mlwrite("No mark in this window");
+                return (FALSE);
+        }
+        odotp = curwp->w_dotp;
+        odoto = curwp->w_doto;
+        curwp->w_dotp  = curwp->w_markp;
+        curwp->w_doto  = curwp->w_marko;
+        curwp->w_markp = odotp;
+        curwp->w_marko = odoto;
+        curwp->w_flag |= WFMOVE;
+        return (TRUE);
+}

Added: clients/emacs/bind.c
===================================================================
--- clients/emacs/bind.c	                        (rev 0)
+++ clients/emacs/bind.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,609 @@
+/*	This file is for functions having to do with key bindings,
+	descriptions, help commands and startup file.
+
+	written 11-feb-86 by Daniel Lawrence
+								*/
+
+#include	"estruct.h"
+#include	"edef.h"
+#include	"epath.h"
+
+extern int foo;
+extern int meta(), cex();	/* dummy prefix binding functions */
+
+deskey(f, n)	/* describe the command for a certain key */
+
+{
+	register int c;		/* command character to describe */
+	register char *ptr;	/* string pointer to scan output strings */
+	register KEYTAB *ktp;	/* pointer into the command table */
+	register int found;	/* matched command flag */
+	register NBIND *nptr;	/* pointer into the name binding table */
+	char outseq[80];	/* output buffer for command sequence */
+
+	/* prompt the user to type us a key to describe */
+	mlwrite(": describe-key ");
+
+	/* get the command sequence to describe */
+	c = getckey(FALSE);			/* get a command sequence */
+
+	/* change it to something we can print as well */
+	cmdstr(c, &outseq[0]);
+
+	/* and dump it out */
+	ptr = &outseq[0];
+	while (*ptr)
+		(*term.t_putchar)(*ptr++);
+	(*term.t_putchar)(' ');		/* space it out */
+
+	/* find the right ->function */
+	ktp = &keytab[0];
+	found = FALSE;
+	while (ktp->k_fp != NULL) {
+		if (ktp->k_code == c) {
+			found = TRUE;
+			break;
+		}
+		++ktp;
+	}
+
+	if (!found)
+		strcpy(outseq,"Not Bound");
+	else {
+		/* match it against the name binding table */
+		nptr = &names[0];
+		strcpy(outseq,"[Bad binding]");
+		while (nptr->n_func != NULL) {
+			if (nptr->n_func == ktp->k_fp) {
+				strcpy(outseq, nptr->n_name);
+				break;
+			}
+			++nptr;
+		}
+	}
+
+	/* output the command sequence */
+	ptr = &outseq[0];
+	while (*ptr)
+		(*term.t_putchar)(*ptr++);
+}
+
+cmdstr(c, seq)	/* change a key command to a string we can print out */
+
+int c;		/* sequence to translate */
+char *seq;	/* destination string for sequence */
+
+{
+	char *ptr;	/* pointer into current position in sequence */
+
+	ptr = seq;
+
+	/* apply meta sequence if needed */
+	if (c & META) {
+		*ptr++ = 'M';
+		*ptr++ = '-';
+	}
+
+	/* apply ^X sequence if needed */
+	if (c & CTLX) {
+		*ptr++ = '^';
+		*ptr++ = 'X';
+	}
+
+	/* apply SPEC sequence if needed */
+	if (c & SPEC) {
+		*ptr++ = 'F';
+		*ptr++ = 'N';
+	}
+
+	/* apply control sequence if needed */
+	if (c & CTRL) {
+		*ptr++ = '^';
+	}
+
+	c = c & 255;	/* strip the prefixes */
+
+	/* and output the final sequence */
+
+	*ptr++ = c;
+	*ptr = 0;	/* terminate the string */
+}
+
+#if	(MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW
+char *homedir;		/* pointer to your home directory */
+char *getenv();
+char *gethomedir(void);
+#endif
+
+help(f, n)	/* give me some help!!!!
+		   bring up a fake buffer and read the help file
+		   into it with view mode			*/
+{
+	register int status;	/* status of I/O operations */
+	register WINDOW *wp;	/* scaning pointer to windows */
+	register BUFFER *bp;	/* buffer pointer to help */
+	register int i;		/* index into help file names */
+	char fname[NSTRING];	/* buffer to construct file name in */
+
+	/* first check if we are already here */
+	bp = bfind("emacs.hlp", FALSE, BFINVS);
+
+	if (bp == NULL) {
+#if	(MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW
+		/* Look in the Emacs home directory */
+#if OFW
+		if ((homedir = getenv("EMACSHOME")) != NULL
+		  ||(homedir = gethomedir()) != NULL) {
+#else
+		if ((homedir = getenv("EMACSHOME")) != NULL) {
+#endif
+			/* build the file name */
+			strcpy(fname, homedir);
+#if ! OFW
+			if ( *homedir
+			    && homedir[strlen(homedir)-1] != '/'
+			    && homedir[strlen(homedir)-1] != '\\'
+		    	)
+				strcat(fname, "/");
+#endif
+			strcat(fname, pathname[1]);
+
+			/* and test it */
+			status = ffropen(fname);
+			if (status == FIOSUC)
+				goto okay;
+		}
+#endif
+
+		/* search through the list of help files */
+		for (i=2; i < NPNAMES; i++) {
+			strcpy(fname, pathname[i]);
+			strcat(fname, pathname[1]);
+			status = ffropen(fname);
+			if (status == FIOSUC)
+				goto okay;
+		}
+
+		if (status == FIOFNF) {
+			mlwrite("[Help file is not online]");
+			return(FALSE);
+		}
+
+okay:
+		/* close the file to prepare for to read it in */
+		ffclose();
+	}
+
+	/* split the current window to make room for the help stuff */
+	if (splitwind(FALSE, 1) == FALSE)
+			return(FALSE);
+
+	if (bp == NULL) {
+		/* and read the stuff in */
+		if (getfile(fname, FALSE) == FALSE)
+			return(FALSE);
+	} else
+		swbuffer(bp);
+
+	/* make this window in VIEW mode, update all mode lines */
+	curwp->w_bufp->b_mode |= MDVIEW;
+	curwp->w_bufp->b_flag |= BFINVS;
+	wp = wheadp;
+	while (wp != NULL) {
+		wp->w_flag |= WFMODE;
+		wp = wp->w_wndp;
+	}
+	return(TRUE);
+}
+
+int (*fncmatch(fname))() /* match fname to a function in the names table
+			    and return any match or NULL if none		*/
+
+char *fname;	/* name to attempt to match */
+
+{
+	register NBIND *ffp;	/* pointer to entry in name binding table */
+
+	/* scan through the table, returning any match */
+	ffp = &names[0];
+	while (ffp->n_func != NULL) {
+		if (strcmp(fname, ffp->n_name) == 0)
+			return(ffp->n_func);
+		++ffp;
+	}
+	return(NULL);
+}
+
+/* bindtokey:	add a new key to the key binding table
+*/
+
+bindtokey(f, n)
+
+int f, n;	/* command arguments [IGNORED] */
+
+{
+	register int c;		/* command key to bind */
+	register (*kfunc)();	/* ptr to the requexted function to bind to */
+	register char *ptr;	/* ptr to dump out input key string */
+	register KEYTAB *ktp;	/* pointer into the command table */
+	register int found;	/* matched command flag */
+	char outseq[80];	/* output buffer for keystroke sequence */
+	int (*getname())();
+
+	/* prompt the user to type in a key to bind */
+	mlwrite(": bind-to-key ");
+
+	/* get the function name to bind it to */
+	kfunc = getname();
+	if (kfunc == NULL) {
+		mlwrite("[No such function]");
+		return(FALSE);
+	}
+	(*term.t_putchar)(' ');		/* space it out */
+	(*term.t_flush)();
+
+	/* get the command sequence to bind */
+	c = getckey((kfunc == meta) || (kfunc == cex));
+
+	/* change it to something we can print as well */
+	cmdstr(c, &outseq[0]);
+
+	/* and dump it out */
+	ptr = &outseq[0];
+	while (*ptr)
+		(*term.t_putchar)(*ptr++);
+
+	/* if the function is a prefix key */
+	if (kfunc == meta || kfunc == cex) {
+
+		/* search for an existing binding for the prefix key */
+		ktp = &keytab[0];
+		found = FALSE;
+		while (ktp->k_fp != NULL) {
+			if (ktp->k_fp == kfunc) {
+				found = TRUE;
+				break;
+			}
+			++ktp;
+		}
+
+		/* reset the appropriate global prefix variable */
+		if (kfunc == meta)
+			metac = c;
+		if (kfunc == cex)
+			ctlxc = c;
+
+		/* if we found it, just reset it
+		   otherwise, let it fall through and be added to the end */
+		if (found) {
+			ktp->k_code = c;
+			return(TRUE);
+		}
+	} else {
+
+		/* search the table to see if it exists */
+		ktp = &keytab[0];
+		found = FALSE;
+		while (ktp->k_fp != NULL) {
+			if (ktp->k_code == c) {
+				found = TRUE;
+				break;
+			}
+			++ktp;
+		}
+	}
+
+	if (found) {	/* it exists, just change it then */
+		ktp->k_fp = kfunc;
+	} else {	/* otherwise we need to add it to the end */
+		/* if we run out of binding room, bitch */
+		if (ktp >= &keytab[NBINDS]) {
+			mlwrite("Binding table FULL!");
+			return(FALSE);
+		}
+
+		ktp->k_code = c;	/* add keycode */
+		ktp->k_fp = kfunc;	/* and the function pointer */
+		++ktp;			/* and make sure the next is null */
+		ktp->k_code = 0;
+		ktp->k_fp = NULL;
+	}
+	return(TRUE);
+}
+
+/* unbindkey:	delete a key from the key binding table
+*/
+
+unbindkey(f, n)
+
+int f, n;	/* command arguments [IGNORED] */
+
+{
+	register int c;		/* command key to unbind */
+	register char *ptr;	/* ptr to dump out input key string */
+	register KEYTAB *ktp;	/* pointer into the command table */
+	register KEYTAB *sktp;	/* saved pointer into the command table */
+	register int found;	/* matched command flag */
+	char outseq[80];	/* output buffer for keystroke sequence */
+
+	/* prompt the user to type in a key to unbind */
+	mlwrite(": unbind-key ");
+
+	/* get the command sequence to unbind */
+	c = getckey(FALSE);		/* get a command sequence */
+
+	/* change it to something we can print as well */
+	cmdstr(c, &outseq[0]);
+
+	/* and dump it out */
+	ptr = &outseq[0];
+	while (*ptr)
+		(*term.t_putchar)(*ptr++);
+
+	/* search the table to see if the key exists */
+	ktp = &keytab[0];
+	found = FALSE;
+	while (ktp->k_fp != NULL) {
+		if (ktp->k_code == c) {
+			found = TRUE;
+			break;
+		}
+		++ktp;
+	}
+
+	/* if it isn't bound, bitch */
+	if (!found) {
+		mlwrite("[Key not bound]");
+		return(FALSE);
+	}
+
+	/* save the pointer and scan to the end of the table */
+	sktp = ktp;
+	while (ktp->k_fp != NULL)
+		++ktp;
+	--ktp;		/* backup to the last legit entry */
+
+	/* copy the last entry to the current one */
+	sktp->k_code = ktp->k_code;
+	sktp->k_fp   = ktp->k_fp;
+
+	/* null out the last one */
+	ktp->k_code = 0;
+	ktp->k_fp = NULL;
+	return(TRUE);
+}
+
+desbind(f, n)	/* describe bindings
+		   bring up a fake buffer and list the key bindings
+		   into it with view mode			*/
+{
+	register WINDOW *wp;	/* scnaning pointer to windows */
+	register KEYTAB *ktp;	/* pointer into the command table */
+	register NBIND *nptr;	/* pointer into the name binding table */
+	register BUFFER *bp;	/* buffer to put binding list into */
+	char *strp;		/* pointer int string to send */
+	int cpos;		/* current position to use in outseq */
+	char outseq[80];	/* output buffer for keystroke sequence */
+
+	/* split the current window to make room for the binding list */
+	if (splitwind(FALSE, 1) == FALSE)
+			return(FALSE);
+
+	/* and get a buffer for it */
+	bp = bfind("Binding list", TRUE, 0);
+	if (bp == NULL || bclear(bp) == FALSE) {
+		mlwrite("Can not display binding list");
+		return(FALSE);
+	}
+
+	/* let us know this is in progress */
+	mlwrite("[Building buffer list]");
+
+	/* disconect the current buffer */
+        if (--curbp->b_nwnd == 0) {             /* Last use.            */
+                curbp->b_dotp  = curwp->w_dotp;
+                curbp->b_doto  = curwp->w_doto;
+                curbp->b_markp = curwp->w_markp;
+                curbp->b_marko = curwp->w_marko;
+        }
+
+	/* connect the current window to this buffer */
+	curbp = bp;	/* make this buffer current in current window */
+	bp->b_mode = 0;		/* no modes active in binding list */
+	bp->b_nwnd++;		/* mark us as more in use */
+	wp = curwp;
+	wp->w_bufp = bp;
+	wp->w_linep = bp->b_linep;
+	wp->w_flag = WFHARD|WFFORCE;
+	wp->w_dotp = bp->b_dotp;
+	wp->w_doto = bp->b_doto;
+	wp->w_markp = NULL;
+	wp->w_marko = 0;
+
+	/* build the contents of this window, inserting it line by line */
+	nptr = &names[0];
+	while (nptr->n_func != NULL) {
+
+		/* add in the command name */
+		strcpy(outseq, nptr->n_name);
+		cpos = strlen(outseq);
+		
+		/* search down any keys bound to this */
+		ktp = &keytab[0];
+		while (ktp->k_fp != NULL) {
+			if (ktp->k_fp == nptr->n_func) {
+				/* padd out some spaces */
+				while (cpos < 25)
+					outseq[cpos++] = ' ';
+
+				/* add in the command sequence */
+				cmdstr(ktp->k_code, &outseq[cpos]);
+				while (outseq[cpos] != 0)
+					++cpos;
+
+				/* and add it as a line into the buffer */
+				strp = &outseq[0];
+				while (*strp != 0)
+					linsert(1, *strp++);
+				lnewline();
+
+				cpos = 0;	/* and clear the line */
+			}
+			++ktp;
+		}
+
+		/* if no key was bound, we need to dump it anyway */
+		if (cpos > 0) {
+			outseq[cpos] = 0;
+			strp = &outseq[0];
+			while (*strp != 0)
+				linsert(1, *strp++);
+			lnewline();
+		}
+
+		/* and on to the next name */
+		++nptr;
+	}
+
+	curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
+	curbp->b_flag &= ~BFCHG;	/* don't flag this as a change */
+	wp->w_dotp = lforw(bp->b_linep);/* back to the begining */
+	wp->w_doto = 0;
+	wp = wheadp;			/* and update ALL mode lines */
+	while (wp != NULL) {
+		wp->w_flag |= WFMODE;
+		wp = wp->w_wndp;
+	}
+	mlwrite("");	/* clear the mode line */
+	return(TRUE);
+}
+
+getckey(mflag)	/* get a command key sequence from the keyboard	*/
+
+int mflag;	/* going for a meta sequence? */
+
+{
+	register int c;		/* character fetched */
+	register char *tp;	/* pointer into the token */
+	char tok[NSTRING];	/* command incoming */
+
+	/* check to see if we are executing a command line */
+	if (clexec) {
+		nxtarg(tok);	/* get the next token */
+
+		/* parse it up */
+		tp = &tok[0];
+		c = 0;
+
+		/* first, the META prefix */
+		if (*tp == 'M' && *(tp+1) == '-') {
+			c = META;
+			tp += 2;
+		} else
+
+			/* next the function prefix */
+			if (*tp == 'F' && *(tp+1) == 'N') {
+				c |= SPEC;
+				tp += 2;
+			} else
+
+				/* control-x as well... */
+				if (*tp == '^' && *(tp+1) == 'X') {
+					c |= CTLX;
+					tp += 2;
+				}
+
+		/* a control char? */
+		if (*tp == '^' & *(tp+1) != 0) {
+			c |= CTRL;
+			++tp;
+		}
+
+		/* make sure we are not lower case */
+		if (c >= 'a' && c <= 'z')
+			c -= 32;
+
+		/* the final sequence... */
+		c |= *tp;
+
+		return(c);
+	}
+
+	/* or the normal way */
+	if (mflag)
+		c = get1key();
+	else
+		c = getcmd();
+	return(c);
+}
+
+/* execute the startup file */
+
+startup(sfname)
+
+char *sfname;	/* name of startup file (null if default) */
+
+{
+	register int status;	/* status of I/O operations */
+	register int i;		/* index into help file names */
+	char fname[NSTRING];	/* buffer to construct file name in */
+	char *sfroot;		/* root of startup file name */
+
+#if	(MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW
+	char *getenv();
+	char *homedir;		/* pointer to your home directory */
+#endif
+
+	if (sfname[0] == 0)
+		sfroot = pathname[0];
+	else
+		sfroot = sfname;
+
+#if	(MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD | OFW
+	/* get the HOME from the environment */
+#if OFW
+	if ((homedir = getenv("HOME")     ) != NULL
+	 || (homedir = getenv("EMACSHOME")) != NULL
+	 || (homedir = gethomedir()       ) != NULL) {
+#else
+	if ((homedir = getenv("HOME")     ) != NULL
+	 || (homedir = getenv("EMACSHOME")) != NULL) {
+#endif
+		/* build the file name */
+		strcpy(fname, homedir);
+#if ! OFW
+		if ( *homedir
+		    && homedir[strlen(homedir)-1] != '/'
+		    && homedir[strlen(homedir)-1] != '\\'
+		    )
+			strcat(fname, "/");
+#endif
+		strcat(fname, sfroot);
+
+		/* and test it */
+		status = ffropen(fname);
+		if (status == FIOSUC) {
+			ffclose();
+			return(dofile(fname));
+		}
+	}
+#endif
+
+	/* search through the list of startup files */
+	for (i=2; i < NPNAMES; i++) {
+		strcpy(fname, pathname[i]);
+		strcat(fname, sfroot);
+		status = ffropen(fname);
+		if (status == FIOSUC)
+			break;
+	}
+
+	/* if it isn't around, don't sweat it */
+	if (status == FIOFNF)
+		return(TRUE);
+
+	ffclose();	/* close the file to prepare to read it in */
+
+	return(dofile(fname));
+}
+

Added: clients/emacs/buffer.c
===================================================================
--- clients/emacs/buffer.c	                        (rev 0)
+++ clients/emacs/buffer.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,495 @@
+/*
+ * Buffer management.
+ * Some of the functions are internal,
+ * and some are actually attached to user
+ * keys. Like everyone else, they set hints
+ * for the display system.
+ */
+#include	"estruct.h"
+#include        "edef.h"
+
+/*
+ * Attach a buffer to a window. The
+ * values of dot and mark come from the buffer
+ * if the use count is 0. Otherwise, they come
+ * from some other window.
+ */
+usebuffer(f, n)
+{
+        register BUFFER *bp;
+        register int    s;
+        char            bufn[NBUFN];
+
+        if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
+                return (s);
+        if ((bp=bfind(bufn, TRUE, 0)) == NULL)
+                return (FALSE);
+	return(swbuffer(bp));
+}
+
+nextbuffer(f, n)	/* switch to the next buffer in the buffer list */
+
+{
+        register BUFFER *bp;
+
+	bp = curbp->b_bufp;
+	/* cycle through the buffers to find an eligable one */
+	while (bp == NULL || bp->b_flag & BFINVS) {
+		if (bp == NULL)
+			bp = bheadp;
+		else
+			bp = bp->b_bufp;
+	}
+	return(swbuffer(bp));
+}
+
+swbuffer(bp)	/* make buffer BP current */
+
+BUFFER *bp;
+
+{
+        register WINDOW *wp;
+
+        if (--curbp->b_nwnd == 0) {             /* Last use.            */
+                curbp->b_dotp  = curwp->w_dotp;
+                curbp->b_doto  = curwp->w_doto;
+                curbp->b_markp = curwp->w_markp;
+                curbp->b_marko = curwp->w_marko;
+        }
+        curbp = bp;                             /* Switch.              */
+	if (curbp->b_active != TRUE) {		/* buffer not active yet*/
+		/* read it in and activate it */
+		readin(curbp->b_fname, TRUE);
+		curbp->b_dotp = lforw(curbp->b_linep);
+		curbp->b_doto = 0;
+		curbp->b_active = TRUE;
+	}
+        curwp->w_bufp  = bp;
+        curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
+        curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
+        if (bp->b_nwnd++ == 0) {                /* First use.           */
+                curwp->w_dotp  = bp->b_dotp;
+                curwp->w_doto  = bp->b_doto;
+                curwp->w_markp = bp->b_markp;
+                curwp->w_marko = bp->b_marko;
+                return (TRUE);
+        }
+        wp = wheadp;                            /* Look for old.        */
+        while (wp != NULL) {
+                if (wp!=curwp && wp->w_bufp==bp) {
+                        curwp->w_dotp  = wp->w_dotp;
+                        curwp->w_doto  = wp->w_doto;
+                        curwp->w_markp = wp->w_markp;
+                        curwp->w_marko = wp->w_marko;
+                        break;
+                }
+                wp = wp->w_wndp;
+        }
+        return (TRUE);
+}
+
+/*
+ * Dispose of a buffer, by name.
+ * Ask for the name. Look it up (don't get too
+ * upset if it isn't there at all!). Get quite upset
+ * if the buffer is being displayed. Clear the buffer (ask
+ * if the buffer has been changed). Then free the header
+ * line and the buffer header. Bound to "C-X K".
+ */
+killbuffer(f, n)
+
+{
+	register BUFFER *bp;
+        register int    s;
+        char bufn[NBUFN];
+
+        if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
+                return(s);
+        if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
+                return (TRUE);
+	return(zotbuf(bp));
+}
+
+zotbuf(bp)	/* kill the buffer pointed to by bp */
+
+register BUFFER *bp;
+
+{
+        register BUFFER *bp1;
+        register BUFFER *bp2;
+        register int    s;
+
+        if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
+                mlwrite("Buffer is being displayed");
+                return (FALSE);
+        }
+        if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
+                return (s);
+        free((char *) bp->b_linep);             /* Release header line. */
+        bp1 = NULL;                             /* Find the header.     */
+        bp2 = bheadp;
+        while (bp2 != bp) {
+                bp1 = bp2;
+                bp2 = bp2->b_bufp;
+        }
+        bp2 = bp2->b_bufp;                      /* Next one in chain.   */
+        if (bp1 == NULL)                        /* Unlink it.           */
+                bheadp = bp2;
+        else
+                bp1->b_bufp = bp2;
+        free((char *) bp);                      /* Release buffer block */
+        return (TRUE);
+}
+
+namebuffer(f,n)		/*	Rename the current buffer	*/
+
+int f, n;		/* default Flag & Numeric arg */
+
+{
+	register BUFFER *bp;	/* pointer to scan through all buffers */
+	char bufn[NBUFN];	/* buffer to hold buffer name */
+
+	/* prompt for and get the new buffer name */
+ask:	if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
+		return(FALSE);
+
+	/* and check for duplicates */
+	bp = bheadp;
+	while (bp != NULL) {
+		if (bp != curbp) {
+			/* if the names the same */
+			if (strcmp(bufn, bp->b_bname) == 0)
+				goto ask;  /* try again */
+		}
+		bp = bp->b_bufp;	/* onward */
+	}
+
+	strcpy(curbp->b_bname, bufn);	/* copy buffer name to structure */
+	curwp->w_flag |= WFMODE;	/* make mode line replot */
+	mlerase();
+	return(TRUE);
+}
+
+/*
+ * List all of the active
+ * buffers. First update the special
+ * buffer that holds the list. Next make
+ * sure at least 1 window is displaying the
+ * buffer list, splitting the screen if this
+ * is what it takes. Lastly, repaint all of
+ * the windows that are displaying the
+ * list. Bound to "C-X C-B".
+ */
+listbuffers(f, n)
+{
+        register WINDOW *wp;
+        register BUFFER *bp;
+        register int    s;
+
+        if ((s=makelist()) != TRUE)
+                return (s);
+        if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
+                if ((wp=wpopup()) == NULL)
+                        return (FALSE);
+                bp = wp->w_bufp;
+                if (--bp->b_nwnd == 0) {
+                        bp->b_dotp  = wp->w_dotp;
+                        bp->b_doto  = wp->w_doto;
+                        bp->b_markp = wp->w_markp;
+                        bp->b_marko = wp->w_marko;
+                }
+                wp->w_bufp  = blistp;
+                ++blistp->b_nwnd;
+        }
+        wp = wheadp;
+        while (wp != NULL) {
+                if (wp->w_bufp == blistp) {
+                        wp->w_linep = lforw(blistp->b_linep);
+                        wp->w_dotp  = lforw(blistp->b_linep);
+                        wp->w_doto  = 0;
+                        wp->w_markp = NULL;
+                        wp->w_marko = 0;
+                        wp->w_flag |= WFMODE|WFHARD;
+                }
+                wp = wp->w_wndp;
+        }
+        return (TRUE);
+}
+
+/*
+ * This routine rebuilds the
+ * text in the special secret buffer
+ * that holds the buffer list. It is called
+ * by the list buffers command. Return TRUE
+ * if everything works. Return FALSE if there
+ * is an error (if there is no memory).
+ */
+makelist()
+{
+        register char   *cp1;
+        register char   *cp2;
+        register int    c;
+        register BUFFER *bp;
+        register LINE   *lp;
+        register int    s;
+	register int	i;
+        long	nbytes;		/* # of bytes in current buffer */
+        char            b[7+1];
+        char            line[128];
+
+        blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
+        if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
+                return (s);
+        strcpy(blistp->b_fname, "");
+        if (addline("AC MODES      Size Buffer        File") == FALSE
+        ||  addline("-- -----      ---- ------        ----") == FALSE)
+                return (FALSE);
+        bp = bheadp;                            /* For all buffers      */
+
+	/* build line to report global mode settings */
+	cp1 = &line[0];
+	*cp1++ = ' ';
+	*cp1++ = ' ';
+	*cp1++ = ' ';
+
+	/* output the mode codes */
+	for (i = 0; i < NUMMODES; i++)
+		if (gmode & (1 << i))
+			*cp1++ = modecode[i];
+		else
+			*cp1++ = '.';
+	strcpy(cp1, "         Global Modes");
+	if (addline(line) == FALSE)
+		return(FALSE);
+
+	/* output the list of buffers */
+        while (bp != NULL) {
+                if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones.     */
+                        bp = bp->b_bufp;
+                        continue;
+                }
+                cp1 = &line[0];                 /* Start at left edge   */
+
+		/* output status of ACTIVE flag (has the file been read in? */
+                if (bp->b_active == TRUE)    /* "@" if activated       */
+                        *cp1++ = '@';
+                else
+                        *cp1++ = ' ';
+
+		/* output status of changed flag */
+                if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
+                        *cp1++ = '*';
+                else
+                        *cp1++ = ' ';
+                *cp1++ = ' ';                   /* Gap.                 */
+
+		/* output the mode codes */
+		for (i = 0; i < NUMMODES; i++) {
+			if (bp->b_mode & (1 << i))
+				*cp1++ = modecode[i];
+			else
+				*cp1++ = '.';
+		}
+                *cp1++ = ' ';                   /* Gap.                 */
+                nbytes = 0L;                    /* Count bytes in buf.  */
+                lp = lforw(bp->b_linep);
+                while (lp != bp->b_linep) {
+                        nbytes += (long)llength(lp)+1L;
+                        lp = lforw(lp);
+                }
+                eltoa(b, 7, nbytes);            /* 6 digit buffer size. */
+                cp2 = &b[0];
+                while ((c = *cp2++) != 0)
+                        *cp1++ = c;
+                *cp1++ = ' ';                   /* Gap.                 */
+                cp2 = &bp->b_bname[0];          /* Buffer name          */
+                while ((c = *cp2++) != 0)
+                        *cp1++ = c;
+                cp2 = &bp->b_fname[0];          /* File name            */
+                if (*cp2 != 0) {
+                        while (cp1 < &line[2+1+5+1+6+1+NBUFN])
+                                *cp1++ = ' ';
+                        while ((c = *cp2++) != 0) {
+                                if (cp1 < &line[128-1])
+                                        *cp1++ = c;
+                        }
+                }
+                *cp1 = 0;                       /* Add to the buffer.   */
+                if (addline(line) == FALSE)
+                        return (FALSE);
+                bp = bp->b_bufp;
+        }
+        return (TRUE);                          /* All done             */
+}
+
+eltoa(buf, width, num)
+
+char   buf[];
+int    width;
+long   num;
+
+{
+        buf[width] = 0;                         /* End of string.       */
+        while (num >= 10) {                     /* Conditional digits.  */
+                buf[--width] = (int)(num%10L) + '0';
+                num /= 10L;
+        }
+        buf[--width] = (int)num + '0';          /* Always 1 digit.      */
+        while (width != 0)                      /* Pad with blanks.     */
+                buf[--width] = ' ';
+}
+
+/*
+ * The argument "text" points to
+ * a string. Append this line to the
+ * buffer list buffer. Handcraft the EOL
+ * on the end. Return TRUE if it worked and
+ * FALSE if you ran out of room.
+ */
+addline(text)
+char    *text;
+{
+        register LINE   *lp;
+        register int    i;
+        register int    ntext;
+
+        ntext = strlen(text);
+        if ((lp=lalloc(ntext)) == NULL)
+                return (FALSE);
+        for (i=0; i<ntext; ++i)
+                lputc(lp, i, text[i]);
+        blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
+        lp->l_bp = blistp->b_linep->l_bp;
+        blistp->b_linep->l_bp = lp;
+        lp->l_fp = blistp->b_linep;
+        if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
+                blistp->b_dotp = lp;            /* move it to new line  */
+        return (TRUE);
+}
+
+/*
+ * Look through the list of
+ * buffers. Return TRUE if there
+ * are any changed buffers. Buffers
+ * that hold magic internal stuff are
+ * not considered; who cares if the
+ * list of buffer names is hacked.
+ * Return FALSE if no buffers
+ * have been changed.
+ */
+anycb()
+{
+        register BUFFER *bp;
+
+        bp = bheadp;
+        while (bp != NULL) {
+                if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
+                        return (TRUE);
+                bp = bp->b_bufp;
+        }
+        return (FALSE);
+}
+
+/*
+ * Find a buffer, by name. Return a pointer
+ * to the BUFFER structure associated with it.
+ * If the buffer is not found
+ * and the "cflag" is TRUE, create it. The "bflag" is
+ * the settings for the flags in in buffer.
+ */
+BUFFER  *
+bfind(bname, cflag, bflag)
+register char   *bname;
+{
+        register BUFFER *bp;
+	register BUFFER *sb;	/* buffer to insert after */
+        register LINE   *lp;
+
+        bp = bheadp;
+        while (bp != NULL) {
+                if (strcmp(bname, bp->b_bname) == 0)
+                        return (bp);
+                bp = bp->b_bufp;
+        }
+        if (cflag != FALSE) {
+                if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
+                        return (NULL);
+                if ((lp=lalloc(0)) == NULL) {
+                        free((char *) bp);
+                        return (NULL);
+                }
+		/* find the place in the list to insert this buffer */
+		if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
+			/* insert at the begining */
+	                bp->b_bufp = bheadp;
+        	        bheadp = bp;
+        	} else {
+			sb = bheadp;
+			while (sb->b_bufp != NULL) {
+				if (strcmp(sb->b_bufp->b_bname, bname) > 0)
+					break;
+				sb = sb->b_bufp;
+			}
+
+			/* and insert it */
+       			bp->b_bufp = sb->b_bufp;
+        		sb->b_bufp = bp;
+       		}
+
+		/* and set up the other buffer fields */
+		bp->b_active = TRUE;
+                bp->b_dotp  = lp;
+                bp->b_doto  = 0;
+                bp->b_markp = NULL;
+                bp->b_marko = 0;
+                bp->b_flag  = bflag;
+		bp->b_mode  = gmode;
+                bp->b_nwnd  = 0;
+                bp->b_linep = lp;
+                strcpy(bp->b_fname, "");
+                strcpy(bp->b_bname, bname);
+                lp->l_fp = lp;
+                lp->l_bp = lp;
+        }
+        return (bp);
+}
+
+/*
+ * This routine blows away all of the text
+ * in a buffer. If the buffer is marked as changed
+ * then we ask if it is ok to blow it away; this is
+ * to save the user the grief of losing text. The
+ * window chain is nearly always wrong if this gets
+ * called; the caller must arrange for the updates
+ * that are required. Return TRUE if everything
+ * looks good.
+ */
+bclear(bp)
+register BUFFER *bp;
+{
+        register LINE   *lp;
+        register int    s;
+
+        if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
+        && (bp->b_flag&BFCHG) != 0              /* Something changed    */
+        && (s=mlyesno("Discard changes")) != TRUE)
+                return (s);
+        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
+        while ((lp=lforw(bp->b_linep)) != bp->b_linep)
+                lfree(lp);
+        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
+        bp->b_doto  = 0;
+        bp->b_markp = NULL;                     /* Invalidate "mark"    */
+        bp->b_marko = 0;
+        return (TRUE);
+}
+
+unmark(f, n)	/* unmark the current buffers change flag */
+
+int f, n;	/* unused command arguments */
+
+{
+	curbp->b_flag &= ~BFCHG;
+	curwp->w_flag |= WFMODE;
+	return(TRUE);
+}

Added: clients/emacs/dg10.c
===================================================================
--- clients/emacs/dg10.c	                        (rev 0)
+++ clients/emacs/dg10.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,162 @@
+/*
+ * The routines in this file provide support for the Data General Model 10
+ * Microcomputer.
+ */
+
+#define	termdef	1			/* don't define "term" external */
+
+#include	"estruct.h"
+#include        "edef.h"
+
+#if     DG10
+
+#define NROW    24                      /* Screen size.                 */
+#define NCOL    80                      /* Edit if you want to.         */
+#define	NPAUSE	100			/* # times thru update to pause */
+#define	MARGIN	8			/* size of minimim margin and	*/
+#define	SCRSIZ	64			/* scroll size for extended lines */
+#define BEL     0x07                    /* BEL character.               */
+#define ESC     30                      /* DG10 ESC character.          */
+
+extern  int     ttopen();               /* Forward references.          */
+extern  int     ttgetc();
+extern  int     ttputc();
+extern  int     ttflush();
+extern  int     ttclose();
+extern  int     dg10move();
+extern  int     dg10eeol();
+extern  int     dg10eeop();
+extern  int     dg10beep();
+extern  int     dg10open();
+extern	int	dg10rev();
+extern	int	dg10close();
+
+#if	COLOR
+extern	int	dg10fcol();
+extern	int	dg10bcol();
+
+int	cfcolor = -1;		/* current forground color */
+int	cbcolor = -1;		/* current background color */
+int	ctrans[] = {		/* emacs -> DG10 color translation table */
+	0, 4, 2, 6, 1, 5, 3, 7};
+#endif
+
+/*
+ * Standard terminal interface dispatch table. Most of the fields point into
+ * "termio" code.
+ */
+TERM    term    = {
+        NROW-1,
+        NCOL,
+	MARGIN,
+	SCRSIZ,
+	NPAUSE,
+        dg10open,
+        dg10close,
+        ttgetc,
+        ttputc,
+        ttflush,
+        dg10move,
+        dg10eeol,
+        dg10eeop,
+        dg10beep,
+	dg10rev
+#if	COLOR
+	, dg10fcol,
+	dg10bcol
+#endif
+};
+
+#if	COLOR
+dg10fcol(color)		/* set the current output color */
+
+int color;	/* color to set */
+
+{
+	if (color == cfcolor)
+		return;
+	ttputc(ESC);
+	ttputc(0101);
+	ttputc(ctrans[color]);
+	cfcolor = color;
+}
+
+dg10bcol(color)		/* set the current background color */
+
+int color;	/* color to set */
+
+{
+	if (color == cbcolor)
+		return;
+	ttputc(ESC);
+	ttputc(0102);
+	ttputc(ctrans[color]);
+        cbcolor = color;
+}
+#endif
+
+dg10move(row, col)
+{
+	ttputc(16);
+        ttputc(col);
+	ttputc(row);
+}
+
+dg10eeol()
+{
+        ttputc(11);
+}
+
+dg10eeop()
+{
+#if	COLOR
+	dg10fcol(gfcolor);
+	dg10bcol(gbcolor);
+#endif
+        ttputc(ESC);
+        ttputc(0106);
+        ttputc(0106);
+}
+
+dg10rev(state)		/* change reverse video state */
+
+int state;	/* TRUE = reverse, FALSE = normal */
+
+{
+#if	COLOR
+	if (state == TRUE) {
+		dg10fcol(0);
+		dg10bcol(7);
+	}
+#else
+	ttputc(ESC);
+	ttputc(state ? 0104: 0105);
+#endif
+}
+
+dg10beep()
+{
+        ttputc(BEL);
+        ttflush();
+}
+
+dg10open()
+{
+	revexist = TRUE;
+        ttopen();
+}
+
+dg10close()
+
+{
+#if	COLOR
+	dg10fcol(7);
+	dg10bcol(0);
+#endif
+	ttclose();
+}
+#else
+dg10hello()
+{
+}
+#endif

Added: clients/emacs/display.c
===================================================================
--- clients/emacs/display.c	                        (rev 0)
+++ clients/emacs/display.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,1119 @@
+/*
+ * The functions in this file handle redisplay. There are two halves, the
+ * ones that update the virtual display screen, and the ones that make the
+ * physical display screen the same as the virtual display screen. These
+ * functions use hints that are left in the windows by the commands.
+ *
+ */
+
+#include	"estruct.h"
+#include        "edef.h"
+
+#define WFDEBUG 0                       /* Window flag debug. */
+
+typedef struct  VIDEO {
+        int	v_flag;                 /* Flags */
+#if	COLOR
+	int	v_fcolor;		/* current forground color */
+	int	v_bcolor;		/* current background color */
+	int	v_rfcolor;		/* requested forground color */
+	int	v_rbcolor;		/* requested background color */
+#endif
+        char    v_text[1];              /* Screen data. */
+}       VIDEO;
+
+#define VFCHG   0x0001                  /* Changed flag			*/
+#define	VFEXT	0x0002			/* extended (beyond column 80)	*/
+#define	VFREV	0x0004			/* reverse video status		*/
+#define	VFREQ	0x0008			/* reverse video request	*/
+#define	VFCOL	0x0010			/* color change requested	*/
+
+VIDEO   **vscreen;                      /* Virtual screen. */
+#if	IBMPC == 0
+VIDEO   **pscreen;                      /* Physical screen. */
+#endif
+
+/*
+ * Initialize the data structures used by the display code. The edge vectors
+ * used to access the screens are set up. The operating system's terminal I/O
+ * channel is set up. All the other things get initialized at compile time.
+ * The original window has "WFCHG" set, so that it will get completely
+ * redrawn on the first call to "update".
+ */
+vtinit()
+{
+    register int i;
+    register VIDEO *vp;
+
+    (*term.t_open)();
+    (*term.t_rev)(FALSE);
+    vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
+
+    if (vscreen == NULL)
+	errexit();
+
+#if	IBMPC == 0
+    pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
+
+    if (pscreen == NULL)
+	errexit();
+#endif
+
+    for (i = 0; i < term.t_nrow; ++i)
+        {
+        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
+
+        if (vp == NULL)
+	    errexit();
+
+	vp->v_flag = 0;
+#if	COLOR
+	vp->v_rfcolor = 7;
+	vp->v_rbcolor = 0;
+#endif
+        vscreen[i] = vp;
+#if	IBMPC == 0
+        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
+
+        if (vp == NULL)
+	    errexit();
+
+	vp->v_flag = 0;
+        pscreen[i] = vp;
+#endif
+        }
+}
+
+/*
+ * Clean up the virtual terminal system, in anticipation for a return to the
+ * operating system. Move down to the last line and clear it out (the next
+ * system prompt will be written in the line). Shut down the channel to the
+ * terminal.
+ */
+vttidy()
+{
+    mlerase();
+    movecursor(term.t_nrow, 0);
+    (*term.t_flush)();
+    (*term.t_close)();
+}
+
+/*
+ * Set the virtual cursor to the specified row and column on the virtual
+ * screen. There is no checking for nonsense values; this might be a good
+ * idea during the early stages.
+ */
+vtmove(row, col)
+{
+    vtrow = row;
+    vtcol = col;
+}
+
+/*
+ * Write a character to the virtual screen. The virtual row and column are
+ * updated. If the line is too long put a "$" in the last column. This routine
+ * only puts printing characters into the virtual terminal buffers. Only
+ * column overflow is checked.
+ */
+vtputc(c)
+    int c;
+{
+    register VIDEO      *vp;
+
+    vp = vscreen[vtrow];
+
+    if (vtcol >= term.t_ncol) {
+        vtcol = (vtcol + 0x07) & ~0x07;
+        vp->v_text[term.t_ncol - 1] = '$';
+    } else if (c == '\t')
+        {
+        do
+            {
+            vtputc(' ');
+            }
+        while ((vtcol&0x07) != 0);
+        }
+    else if (c < 0x20 || c == 0x7F)
+        {
+        vtputc('^');
+        vtputc(c ^ 0x40);
+        }
+    else
+	vp->v_text[vtcol++] = c;
+}
+
+/*	put a character to the virtual screen in an extended line. If we are
+	not yet on left edge, don't print it yet. check for overflow on
+	the right margin						*/
+
+vtpute(c)
+
+int c;
+
+{
+    register VIDEO      *vp;
+
+    vp = vscreen[vtrow];
+
+    if (vtcol >= term.t_ncol) {
+        vtcol = (vtcol + 0x07) & ~0x07;
+        vp->v_text[term.t_ncol - 1] = '$';
+    } else if (c == '\t')
+        {
+        do
+            {
+            vtpute(' ');
+            }
+        while (((vtcol + lbound)&0x07) != 0);
+        }
+    else if (c < 0x20 || c == 0x7F)
+        {
+        vtpute('^');
+        vtpute(c ^ 0x40);
+        }
+    else {
+	if (vtcol >= 0)
+		vp->v_text[vtcol] = c;
+	++vtcol;
+    }
+}
+
+/*
+ * Erase from the end of the software cursor to the end of the line on which
+ * the software cursor is located.
+ */
+vteeol()
+{
+    register VIDEO      *vp;
+
+    vp = vscreen[vtrow];
+    while (vtcol < term.t_ncol)
+        vp->v_text[vtcol++] = ' ';
+}
+
+/* upscreen:	user routine to force a screen update
+		always finishes complete update		*/
+
+upscreen(f, n)
+
+{
+	update(TRUE);
+	return(TRUE);
+}
+
+/*
+ * Make sure that the display is right. This is a three part process. First,
+ * scan through all of the windows looking for dirty ones. Check the framing,
+ * and refresh the screen. Second, make sure that "currow" and "curcol" are
+ * correct for the current window. Third, make the virtual and physical
+ * screens the same.
+ */
+update(force)
+
+int force;	/* force update past type ahead? */
+
+{
+	register WINDOW *wp;
+
+#if	TYPEAH
+	if (force == FALSE && typahead())
+		return(TRUE);
+#endif
+
+	/* update any windows that need refreshing */
+	wp = wheadp;
+	while (wp != NULL) {
+		if (wp->w_flag) {
+			/* if the window has changed, service it */
+			reframe(wp);	/* check the framing */
+			if ((wp->w_flag & ~WFMODE) == WFEDIT)
+				updone(wp);	/* update EDITed line */
+			else if (wp->w_flag & ~WFMOVE)
+				updall(wp);	/* update all lines */
+#if	~WFDEBUG
+			if (wp->w_flag & WFMODE)
+				modeline(wp);	/* update modeline */
+#endif
+			wp->w_flag = 0;
+			wp->w_force = 0;
+		}
+#if	WFDEBUG
+		modeline();
+#endif
+		/* on to the next window */
+		wp = wp->w_wndp;
+	}
+
+	/* recalc the current hardware cursor location */
+	updpos();
+
+#if	IBMPC
+	/* update the cursor and flush the buffers */
+	movecursor(currow, curcol - lbound);
+#endif
+
+	/* check for lines to de-extend */
+	upddex();
+
+	/* if screen is garbage, re-plot it */
+	if (sgarbf != FALSE)
+		updgar();
+
+	/* update the virtual screen to the physical screen */
+	updupd(force);
+
+	/* update the cursor and flush the buffers */
+	movecursor(currow, curcol - lbound);
+	(*term.t_flush)();
+	return(TRUE);
+}
+
+/*	reframe:	check to see if the cursor is on in the window
+			and re-frame it if needed or wanted		*/
+
+reframe(wp)
+
+WINDOW *wp;
+
+{
+	register LINE *lp;
+	register int i;
+
+	/* if not a requested reframe, check for a needed one */
+	if ((wp->w_flag & WFFORCE) == 0) {
+		lp = wp->w_linep;
+		for (i = 0; i < wp->w_ntrows; i++) {
+
+			/* if the line is in the window, no reframe */
+			if (lp == wp->w_dotp)
+				return(TRUE);
+
+			/* if we are at the end of the file, reframe */
+			if (lp == wp->w_bufp->b_linep)
+				break;
+
+			/* on to the next line */
+			lp = lforw(lp);
+		}
+	}
+
+	/* reaching here, we need a window refresh */
+	i = wp->w_force;
+
+	/* how far back to reframe? */
+	if (i > 0) {		/* only one screen worth of lines max */
+		if (--i >= wp->w_ntrows)
+			i = wp->w_ntrows - 1;
+	} else if (i < 0) {	/* negative update???? */
+		i += wp->w_ntrows;
+		if (i < 0)
+			i = 0;
+	} else
+		i = wp->w_ntrows / 2;
+
+	/* backup to new line at top of window */
+	lp = wp->w_dotp;
+	while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
+		--i;
+		lp = lback(lp);
+	}
+
+	/* and reset the current line at top of window */
+	wp->w_linep = lp;
+	wp->w_flag |= WFHARD;
+	wp->w_flag &= ~WFFORCE;
+	return(TRUE);
+}
+
+/*	updone:	update the current line	to the virtual screen		*/
+
+updone(wp)
+
+WINDOW *wp;	/* window to update current line in */
+
+{
+	register LINE *lp;	/* line to update */
+	register int sline;	/* physical screen line to update */
+	register int i;
+
+	/* search down the line we want */
+	lp = wp->w_linep;
+	sline = wp->w_toprow;
+	while (lp != wp->w_dotp) {
+		++sline;
+		lp = lforw(lp);
+	}
+
+	/* and update the virtual line */
+	vscreen[sline]->v_flag |= VFCHG;
+	vscreen[sline]->v_flag &= ~VFREQ;
+	vtmove(sline, 0);
+	for (i=0; i < llength(lp); ++i)
+		vtputc(lgetc(lp, i));
+#if	COLOR
+	vscreen[sline]->v_rfcolor = wp->w_fcolor;
+	vscreen[sline]->v_rbcolor = wp->w_bcolor;
+#endif
+	vteeol();
+}
+
+/*	updall:	update all the lines in a window on the virtual screen */
+
+updall(wp)
+
+WINDOW *wp;	/* window to update lines in */
+
+{
+	register LINE *lp;	/* line to update */
+	register int sline;	/* physical screen line to update */
+	register int i;
+
+	/* search down the lines, updating them */
+	lp = wp->w_linep;
+	sline = wp->w_toprow;
+	while (sline < wp->w_toprow + wp->w_ntrows) {
+
+		/* and update the virtual line */
+		vscreen[sline]->v_flag |= VFCHG;
+		vscreen[sline]->v_flag &= ~VFREQ;
+		vtmove(sline, 0);
+		if (lp != wp->w_bufp->b_linep) {
+			/* if we are not at the end */
+			for (i=0; i < llength(lp); ++i)
+				vtputc(lgetc(lp, i));
+			lp = lforw(lp);
+		}
+
+		/* on to the next one */
+#if	COLOR
+		vscreen[sline]->v_rfcolor = wp->w_fcolor;
+		vscreen[sline]->v_rbcolor = wp->w_bcolor;
+#endif
+		vteeol();
+		++sline;
+	}
+
+}
+
+/*	updpos:	update the position of the hardware cursor and handle extended
+		lines. This is the only update for simple moves.	*/
+
+updpos()
+
+{
+	register LINE *lp;
+	register int c;
+	register int i;
+
+	/* find the current row */
+	lp = curwp->w_linep;
+	currow = curwp->w_toprow;
+	while (lp != curwp->w_dotp) {
+		++currow;
+		lp = lforw(lp);
+	}
+
+	/* find the current column */
+	curcol = 0;
+	i = 0;
+	while (i < curwp->w_doto) {
+		c = lgetc(lp, i++);
+		if (c == '\t')
+			curcol |= 0x07;
+		else
+			if (c < 0x20 || c == 0x7f)
+				++curcol;
+
+		++curcol;
+	}
+
+	/* if extended, flag so and update the virtual line image */
+	if (curcol >=  term.t_ncol - 1) {
+		vscreen[currow]->v_flag |= (VFEXT | VFCHG);
+		updext();
+	} else
+		lbound = 0;
+}
+
+/*	upddex:	de-extend any line that derserves it		*/
+
+upddex()
+
+{
+	register WINDOW *wp;
+	register LINE *lp;
+	register int i,j;
+
+	wp = wheadp;
+
+	while (wp != NULL) {
+		lp = wp->w_linep;
+		i = wp->w_toprow;
+
+		while (i < wp->w_toprow + wp->w_ntrows) {
+			if (vscreen[i]->v_flag & VFEXT) {
+				if ((wp != curwp) || (lp != wp->w_dotp) ||
+				   (curcol < term.t_ncol - 1)) {
+					vtmove(i, 0);
+					for (j = 0; j < llength(lp); ++j)
+						vtputc(lgetc(lp, j));
+					vteeol();
+
+					/* this line no longer is extended */
+					vscreen[i]->v_flag &= ~VFEXT;
+					vscreen[i]->v_flag |= VFCHG;
+				}
+			}
+			lp = lforw(lp);
+			++i;
+		}
+		/* and onward to the next window */
+		wp = wp->w_wndp;
+	}
+}
+
+/*	updgar:	if the screen is garbage, clear the physical screen and
+		the virtual screen and force a full update		*/
+
+updgar()
+
+{
+	register char *txt;
+	register int i,j;
+
+	for (i = 0; i < term.t_nrow; ++i) {
+		vscreen[i]->v_flag |= VFCHG;
+#if	REVSTA
+		vscreen[i]->v_flag &= ~VFREV;
+#endif
+#if	COLOR
+		vscreen[i]->v_fcolor = gfcolor;
+		vscreen[i]->v_bcolor = gbcolor;
+#endif
+#if	IBMPC == 0
+		txt = pscreen[i]->v_text;
+		for (j = 0; j < term.t_ncol; ++j)
+			txt[j] = ' ';
+#endif
+	}
+
+	movecursor(0, 0);		 /* Erase the screen. */
+	(*term.t_eeop)();
+	sgarbf = FALSE;			 /* Erase-page clears */
+	mpresf = FALSE;			 /* the message area. */
+#if	COLOR
+	mlerase();			/* needs to be cleared if colored */
+#endif
+}
+
+/*	updupd:	update the physical screen from the virtual screen	*/
+
+updupd(force)
+
+int force;	/* forced update flag */
+
+{
+	register VIDEO *vp1;
+	register int i;
+
+	for (i = 0; i < term.t_nrow; ++i) {
+		vp1 = vscreen[i];
+
+		/* for each line that needs to be updated*/
+		if ((vp1->v_flag & VFCHG) != 0) {
+#if	TYPEAH
+			if (force == FALSE && typahead())
+				return(TRUE);
+#endif
+#if	IBMPC
+			updateline(i, vp1);
+#else
+			updateline(i, vp1, pscreen[i]);
+#endif
+		}
+	}
+
+#if	OFW
+	/* Restore the colors to those for the current line */
+	(*term.t_setfor)(vscreen[currow]->v_rfcolor);
+	(*term.t_setback)(vscreen[currow]->v_rbcolor);
+#endif
+
+	return(TRUE);
+}
+
+/*	updext: update the extended line which the cursor is currently
+		on at a column greater than the terminal width. The line
+		will be scrolled right or left to let the user see where
+		the cursor is
+								*/
+
+updext()
+
+{
+	register int rcursor;	/* real cursor location */
+	register LINE *lp;	/* pointer to current line */
+	register int j;		/* index into line */
+
+	/* calculate what column the real cursor will end up in */
+	rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
+	lbound = curcol - rcursor + 1;
+
+	/* scan through the line outputing characters to the virtual screen */
+	/* once we reach the left edge					*/
+	vtmove(currow, -lbound);	/* start scanning offscreen */
+	lp = curwp->w_dotp;		/* line to output */
+	for (j=0; j<llength(lp); ++j)	/* until the end-of-line */
+		vtpute(lgetc(lp, j));
+
+	/* truncate the virtual line */
+	vteeol();
+
+	/* and put a '$' in column 1 */
+	vscreen[currow]->v_text[0] = '$';
+}
+
+/*
+ * Update a single line. This does not know how to use insert or delete
+ * character sequences; we are using VT52 functionality. Update the physical
+ * row and column variables. It does try an exploit erase to end of line. The
+ * RAINBOW version of this routine uses fast video.
+ */
+#if	IBMPC
+/*	UPDATELINE specific code for the IBM-PC and other compatables */
+
+updateline(row, vp1)
+
+int row;		/* row of screen to update */
+struct VIDEO *vp1;	/* virtual screen image */
+
+{
+#if	COLOR
+	scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
+	vp1->v_fcolor = vp1->v_rfcolor;
+	vp1->v_bcolor = vp1->v_rbcolor;
+#else
+	if (vp1->v_flag & VFREQ)
+		scwrite(row, vp1->v_text, 0, 7);
+	else
+		scwrite(row, vp1->v_text, 7, 0);
+#endif
+	vp1->v_flag &= ~(VFCHG | VFCOL);	/* flag this line as changed */
+
+}
+
+#else
+
+updateline(row, vp1, vp2)
+
+int row;		/* row of screen to update */
+struct VIDEO *vp1;	/* virtual screen image */
+struct VIDEO *vp2;	/* physical screen image */
+
+{
+#if RAINBOW
+/*	UPDATELINE specific code for the DEC rainbow 100 micro	*/
+
+    register char *cp1;
+    register char *cp2;
+    register int nch;
+
+    /* since we don't know how to make the rainbow do this, turn it off */
+    flags &= (~VFREV & ~VFREQ);
+
+    cp1 = &vp1->v_text[0];                    /* Use fast video. */
+    cp2 = &vp2->v_text[0];
+    putline(row+1, 1, cp1);
+    nch = term.t_ncol;
+
+    do
+        {
+        *cp2 = *cp1;
+        ++cp2;
+        ++cp1;
+        }
+    while (--nch);
+    *flags &= ~VFCHG;
+#else
+/*	UPDATELINE code for all other versions		*/
+
+	register char *cp1;
+	register char *cp2;
+	register char *cp3;
+	register char *cp4;
+	register char *cp5;
+	register int nbflag;	/* non-blanks to the right flag? */
+	int rev;		/* reverse video flag */
+	int req;		/* reverse video request flag */
+
+
+	/* set up pointers to virtual and physical lines */
+	cp1 = &vp1->v_text[0];
+	cp2 = &vp2->v_text[0];
+
+#if	COLOR
+	(*term.t_setfor)(vp1->v_rfcolor);
+	(*term.t_setback)(vp1->v_rbcolor);
+#endif
+
+#if	REVSTA | COLOR
+	/* if we need to change the reverse video status of the
+	   current line, we need to re-write the entire line     */
+	rev = (vp1->v_flag & VFREV) == VFREV;
+	req = (vp1->v_flag & VFREQ) == VFREQ;
+	if ((rev != req)
+#if	COLOR
+	    || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
+#endif
+			) {
+		movecursor(row, 0);	/* Go to start of line. */
+		/* set rev video if needed */
+		if (rev != req)
+			(*term.t_rev)(req);
+
+		/* scan through the line and dump it to the screen and
+		   the virtual screen array				*/
+		cp3 = &vp1->v_text[term.t_ncol];
+		while (cp1 < cp3) {
+			(*term.t_putchar)(*cp1);
+			++ttcol;
+			*cp2++ = *cp1++;
+		}
+		/* turn rev video off */
+		if (rev != req)
+			(*term.t_rev)(FALSE);
+
+		/* update the needed flags */
+		vp1->v_flag &= ~VFCHG;
+		if (req)
+			vp1->v_flag |= VFREV;
+		else
+			vp1->v_flag &= ~VFREV;
+#if	COLOR
+		vp1->v_fcolor = vp1->v_rfcolor;
+		vp1->v_bcolor = vp1->v_rbcolor;
+#endif
+		return(TRUE);
+	}
+#endif
+
+	/* advance past any common chars at the left */
+	while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) {
+		++cp1;
+		++cp2;
+	}
+
+/* This can still happen, even though we only call this routine on changed
+ * lines. A hard update is always done when a line splits, a massive
+ * change is done, or a buffer is displayed twice. This optimizes out most
+ * of the excess updating. A lot of computes are used, but these tend to
+ * be hard operations that do a lot of update, so I don't really care.
+ */
+	/* if both lines are the same, no update needs to be done */
+	if (cp1 == &vp1->v_text[term.t_ncol])
+		return(TRUE);
+
+	/* find out if there is a match on the right */
+	nbflag = FALSE;
+	cp3 = &vp1->v_text[term.t_ncol];
+	cp4 = &vp2->v_text[term.t_ncol];
+
+	while (cp3[-1] == cp4[-1]) {
+		--cp3;
+		--cp4;
+		if (cp3[0] != ' ')		/* Note if any nonblank */
+			nbflag = TRUE;		/* in right match. */
+	}
+
+	cp5 = cp3;
+
+	/* Erase to EOL ? */
+	if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
+		while (cp5!=cp1 && cp5[-1]==' ')
+			--cp5;
+
+		if (cp3-cp5 <= 3)		/* Use only if erase is */
+			cp5 = cp3;		/* fewer characters. */
+	}
+
+	movecursor(row, cp1 - &vp1->v_text[0]);	/* Go to start of line. */
+#if	REVSTA
+	(*term.t_rev)((vp1->v_flag & VFREV) == VFREV);
+#endif
+
+	while (cp1 != cp5) {		/* Ordinary. */
+		(*term.t_putchar)(*cp1);
+		++ttcol;
+		*cp2++ = *cp1++;
+	}
+
+	if (cp5 != cp3) {		/* Erase. */
+		(*term.t_eeol)();
+		while (cp1 != cp3)
+			*cp2++ = *cp1++;
+	}
+#if	REVSTA
+	(*term.t_rev)(FALSE);
+#endif
+	vp1->v_flag &= ~VFCHG;		/* flag this line is changed */
+	return(TRUE);
+#endif
+}
+#endif
+
+/*
+ * Redisplay the mode line for the window pointed to by the "wp". This is the
+ * only routine that has any idea of how the modeline is formatted. You can
+ * change the modeline format by hacking at this routine. Called by "update"
+ * any time there is a dirty window.
+ */
+modeline(wp)
+    WINDOW *wp;
+{
+    register char *cp;
+    register int c;
+    register int n;		/* cursor position count */
+    register BUFFER *bp;
+    register i;			/* loop index */
+    register lchar;		/* character to draw line in buffer with */
+    register firstm;		/* is this the first mode? */
+    char tline[NLINE];		/* buffer for part of mode line */
+
+    n = wp->w_toprow+wp->w_ntrows;      	/* Location. */
+    vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
+#if	COLOR
+    vscreen[n]->v_rfcolor = 0;			/* black on */
+    vscreen[n]->v_rbcolor = 7;			/* white.....*/
+#endif
+    vtmove(n, 0);                       	/* Seek to right line. */
+    if (wp == curwp)				/* mark the current buffer */
+	lchar = '=';
+    else
+#if	REVSTA
+	if (revexist)
+		lchar = ' ';
+	else
+#endif
+		lchar = '-';
+
+    vtputc(lchar);
+    bp = wp->w_bufp;
+
+    if ((bp->b_flag&BFCHG) != 0)                /* "*" if changed. */
+        vtputc('*');
+    else
+        vtputc(lchar);
+
+    n  = 2;
+    strcpy(tline, " MicroEMACS 3.7 (");		/* Buffer name. */
+
+    /* display the modes */
+
+	firstm = TRUE;
+	for (i = 0; i < NUMMODES; i++)	/* add in the mode flags */
+		if (wp->w_bufp->b_mode & (1 << i)) {
+			if (firstm != TRUE)
+				strcat(tline, " ");
+			firstm = FALSE;
+			strcat(tline, modename[i]);
+		}
+	strcat(tline,") ");
+
+    cp = &tline[0];
+    while ((c = *cp++) != 0)
+        {
+        vtputc(c);
+        ++n;
+        }
+
+#if WFDEBUG
+    vtputc(lchar);
+    vtputc((wp->w_flag&WFCOLR) != 0  ? 'C' : lchar);
+    vtputc((wp->w_flag&WFMODE) != 0  ? 'M' : lchar);
+    vtputc((wp->w_flag&WFHARD) != 0  ? 'H' : lchar);
+    vtputc((wp->w_flag&WFEDIT) != 0  ? 'E' : lchar);
+    vtputc((wp->w_flag&WFMOVE) != 0  ? 'V' : lchar);
+    vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar);
+    vtputc(lchar);
+    n += 8;
+#endif
+
+    vtputc(lchar);
+    vtputc(lchar);
+    vtputc(' ');
+    n += 3;
+    cp = &bp->b_bname[0];
+
+    while ((c = *cp++) != 0)
+        {
+        vtputc(c);
+        ++n;
+        }
+
+    vtputc(' ');
+    vtputc(lchar);
+    vtputc(lchar);
+    n += 3;
+
+    if (bp->b_fname[0] != 0)            /* File name. */
+        {
+	vtputc(' ');
+	++n;
+        cp = "File: ";
+
+        while ((c = *cp++) != 0)
+            {
+            vtputc(c);
+            ++n;
+            }
+
+        cp = &bp->b_fname[0];
+
+        while ((c = *cp++) != 0)
+            {
+            vtputc(c);
+            ++n;
+            }
+
+        vtputc(' ');
+        ++n;
+        }
+
+    while (n < term.t_ncol)             /* Pad to full width. */
+        {
+        vtputc(lchar);
+        ++n;
+        }
+}
+
+upmode()	/* update all the mode lines */
+
+{
+	register WINDOW *wp;
+
+	wp = wheadp;
+	while (wp != NULL) {
+		wp->w_flag |= WFMODE;
+		wp = wp->w_wndp;
+	}
+}
+
+/*
+ * Send a command to the terminal to move the hardware cursor to row "row"
+ * and column "col". The row and column arguments are origin 0. Optimize out
+ * random calls. Update "ttrow" and "ttcol".
+ */
+movecursor(row, col)
+    {
+    if (row!=ttrow || col!=ttcol)
+        {
+        ttrow = row;
+        ttcol = col;
+        (*term.t_move)(row, col);
+        }
+    }
+
+/*
+ * Erase the message line. This is a special routine because the message line
+ * is not considered to be part of the virtual screen. It always works
+ * immediately; the terminal buffer is flushed via a call to the flusher.
+ */
+mlerase()
+    {
+    int i;
+    
+    movecursor(term.t_nrow, 0);
+#if	COLOR
+     (*term.t_setfor)(7);
+     (*term.t_setback)(0);
+#endif
+    if (eolexist == TRUE)
+	    (*term.t_eeol)();
+    else {
+        for (i = 0; i < term.t_ncol - 1; i++)
+            (*term.t_putchar)(' ');
+        movecursor(term.t_nrow, 1);	/* force the move! */
+        movecursor(term.t_nrow, 0);
+    }
+    (*term.t_flush)();
+    mpresf = FALSE;
+    }
+
+/*
+ * Write a message into the message line. Keep track of the physical cursor
+ * position. A small class of printf like format items is handled. Assumes the
+ * stack grows down; this assumption is made by the "++" in the argument scan
+ * loop. Set the "message line" flag TRUE.
+ */
+
+mlwrite(fmt, arg)
+    char *fmt;
+    {
+    register int c;
+    register char *ap;
+
+#if	COLOR
+	(*term.t_setfor)(7);
+	(*term.t_setback)(0);
+#endif
+    if (eolexist == FALSE) {
+        mlerase();
+        (*term.t_flush)();
+    }
+
+    movecursor(term.t_nrow, 0);
+    ap = (char *) &arg;
+    while ((c = *fmt++) != 0) {
+        if (c != '%') {
+            (*term.t_putchar)(c);
+            ++ttcol;
+            }
+        else
+            {
+            c = *fmt++;
+            switch (c) {
+                case 'd':
+                    mlputi(*(int *)ap, 10);
+                    ap += sizeof(int);
+                    break;
+
+                case 'o':
+                    mlputi(*(int *)ap,  8);
+                    ap += sizeof(int);
+                    break;
+
+                case 'x':
+                    mlputi(*(int *)ap, 16);
+                    ap += sizeof(int);
+                    break;
+
+                case 'D':
+                    mlputli(*(long *)ap, 10);
+                    ap += sizeof(long);
+                    break;
+
+                case 's':
+                    mlputs(*(char **)ap);
+                    ap += sizeof(char *);
+                    break;
+
+		case 'f':
+		    mlputf(*(int *)ap);
+		    ap += sizeof(int);
+		    break;
+
+                default:
+                    (*term.t_putchar)(c);
+                    ++ttcol;
+                }
+            }
+        }
+    if (eolexist == TRUE)
+        (*term.t_eeol)();
+    (*term.t_flush)();
+    mpresf = TRUE;
+    }
+
+/*
+ * Write out a string. Update the physical cursor position. This assumes that
+ * the characters in the string all have width "1"; if this is not the case
+ * things will get screwed up a little.
+ */
+mlputs(s)
+    char *s;
+    {
+    register int c;
+
+    while ((c = *s++) != 0)
+        {
+        (*term.t_putchar)(c);
+        ++ttcol;
+        }
+    }
+
+/*
+ * Write out an integer, in the specified radix. Update the physical cursor
+ * position.
+ */
+mlputi(i, r)
+    {
+    register int q;
+    static char hexdigits[] = "0123456789ABCDEF";
+
+    if (i < 0)
+        {
+        i = -i;
+        (*term.t_putchar)('-');
+        }
+
+    q = i/r;
+
+    if (q != 0)
+        mlputi(q, r);
+
+    (*term.t_putchar)(hexdigits[i%r]);
+    ++ttcol;
+    }
+
+/*
+ * do the same except as a long integer.
+ */
+mlputli(l, r)
+    long l;
+    {
+    register long q;
+
+    if (l < 0)
+        {
+        l = -l;
+        (*term.t_putchar)('-');
+        }
+
+    q = l/r;
+
+    if (q != 0)
+        mlputli(q, r);
+
+    (*term.t_putchar)((int)(l%r)+'0');
+    ++ttcol;
+    }
+
+/*
+ *	write out a scaled integer with two decimal places
+ */
+
+mlputf(s)
+
+int s;	/* scaled integer to output */
+
+{
+	int i;	/* integer portion of number */
+	int f;	/* fractional portion of number */
+
+	/* break it up */
+	i = s / 100;
+	f = s % 100;
+
+	/* send out the integer portion */
+	mlputi(i, 10);
+	(*term.t_putchar)('.');
+	(*term.t_putchar)((f / 10) + '0');
+	(*term.t_putchar)((f % 10) + '0');
+	ttcol += 3;
+}	
+
+#if RAINBOW
+
+putline(row, col, buf)
+    int row, col;
+    char buf[];
+    {
+    int n;
+
+    n = strlen(buf);
+    if (col + n - 1 > term.t_ncol)
+        n = term.t_ncol - col + 1;
+    Put_Data(row, col, n, buf);
+    }
+#endif
+

Added: clients/emacs/ebind.h
===================================================================
--- clients/emacs/ebind.h	                        (rev 0)
+++ clients/emacs/ebind.h	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,357 @@
+/*	EBIND:		Initial default key to function bindings for
+			MicroEMACS 3.7
+*/
+
+/*
+ * Command table.
+ * This table  is *roughly* in ASCII order, left to right across the
+ * characters of the command. This expains the funny location of the
+ * control-X commands.
+ */
+KEYTAB  keytab[NBINDS] = {
+	{CTRL|'A',		gotobol},
+	{CTRL|'B',		backchar},
+	{CTRL|'C',		insspace},
+	{CTRL|'D',		forwdel},
+	{CTRL|'E',		gotoeol},
+	{CTRL|'F',		forwchar},
+	{CTRL|'G',		ctrlg},
+	{CTRL|'H',		backdel},
+	{CTRL|'I',		tab},
+	{CTRL|'J',		indent},
+	{CTRL|'K',		killtext},
+	{CTRL|'L',		refresh},
+	{CTRL|'M',		newline},
+	{CTRL|'N',		forwline},
+	{CTRL|'O',		openline},
+	{CTRL|'P',		backline},
+	{CTRL|'Q',		quote},
+	{CTRL|'R',		backsearch},
+	{CTRL|'S',		forwsearch},
+	{CTRL|'T',		twiddle},
+	{CTRL|'V',		forwpage},
+	{CTRL|'W',		killregion},
+	{CTRL|'X',		cex},
+	{CTRL|'Y',		yank},
+	{CTRL|'Z',		backpage},
+	{CTRL|']',		meta},
+	{CTLX|CTRL|'B',		listbuffers},
+	{CTLX|CTRL|'C',		quit},          /* Hard quit.           */
+	{CTLX|CTRL|'F',		filefind},
+	{CTLX|CTRL|'I',		insfile},
+	{CTLX|CTRL|'L',		lowerregion},
+	{CTLX|CTRL|'M',		delmode},
+	{CTLX|CTRL|'N',		mvdnwind},
+	{CTLX|CTRL|'O',		deblank},
+	{CTLX|CTRL|'P',		mvupwind},
+	{CTLX|CTRL|'R',		fileread},
+	{CTLX|CTRL|'S',		filesave},
+	{CTLX|CTRL|'U',		upperregion},
+	{CTLX|CTRL|'V',		viewfile},
+	{CTLX|CTRL|'W',		filewrite},
+	{CTLX|CTRL|'X',		swapmark},
+	{CTLX|CTRL|'Z',		shrinkwind},
+	{CTLX|'?',		deskey},
+	{CTLX|'!',		spawn},
+	{CTLX|'@',		pipe},
+	{CTLX|'#',		filter},
+	{CTLX|'=',		showcpos},
+	{CTLX|'(',		ctlxlp},
+	{CTLX|')',		ctlxrp},
+	{CTLX|'^',		enlargewind},
+	{CTLX|'0',		delwind},
+	{CTLX|'1',		onlywind},
+	{CTLX|'2',		splitwind},
+	{CTLX|'B',		usebuffer},
+	{CTLX|'C',		spawncli},
+#if	BSD
+	{CTLX|'D',		bktoshell},
+#endif
+	{CTLX|'E',		ctlxe},
+	{CTLX|'F',		setfillcol},
+	{CTLX|'K',		killbuffer},
+	{CTLX|'M',		setmode},
+	{CTLX|'N',		filename},
+	{CTLX|'O',		nextwind},
+	{CTLX|'P',		prevwind},
+#if	ISRCH
+	{CTLX|'R',		risearch},
+	{CTLX|'S',		fisearch},
+#endif
+	{CTLX|'W',		resize},
+	{CTLX|'X',		nextbuffer},
+	{CTLX|'Z',		enlargewind},
+#if	WORDPRO
+	{META|CTRL|'C',		wordcount},
+#endif
+	{META|CTRL|'H',		delbword},
+	{META|CTRL|'K',		unbindkey},
+	{META|CTRL|'L',		reposition},
+	{META|CTRL|'M',		delgmode},
+	{META|CTRL|'N',		namebuffer},
+	{META|CTRL|'R',		qreplace},
+	{META|CTRL|'V',		scrnextdw},
+#if	WORDPRO
+	{META|CTRL|'W',		killpara},
+#endif
+	{META|CTRL|'Z',		scrnextup},
+	{META|' ',		setmark},
+	{META|'?',		help},
+	{META|'!',		reposition},
+	{META|'.',		setmark},
+	{META|'>',		gotoeob},
+	{META|'<',		gotobob},
+	{META|'~',		unmark},
+	{META|'B',		backword},
+	{META|'C',		capword},
+	{META|'D',		delfword},
+	{META|'F',		forwword},
+	{META|'G',		gotoline},
+	{META|'K',		bindtokey},
+	{META|'L',		lowerword},
+	{META|'M',		setgmode},
+#if	WORDPRO
+	{META|'N',		gotoeop},
+	{META|'P',		gotobop},
+	{META|'Q',		fillpara},
+#endif
+	{META|'R',		sreplace},
+#if	BSD
+	{META|'S',		bktoshell},
+#endif
+	{META|'U',		upperword},
+	{META|'V',		backpage},
+	{META|'W',		copyregion},
+	{META|'X',		namedcmd},
+	{META|'Z',		quickexit},
+	{META|0x7F,              delbword},
+
+#if	OFW
+	{SPEC|0x48,		gotobob},
+	{SPEC|0x41,		backline},
+	{SPEC|0x3f,		backpage},
+	{SPEC|0x44,		backchar},
+	{SPEC|0x43,		forwchar},
+	{SPEC|0x4b,		gotoeob},
+	{SPEC|0x42,		forwline},
+	{SPEC|0x2f,		forwpage},
+	{SPEC|0x40,		insspace},
+/*	{SPEC|83,		forwdel},
+	{SPEC|115,		backword},
+	{SPEC|116,		forwword},
+	{SPEC|132,		gotobop},
+	{SPEC|118,		gotoeop}, */
+	{SPEC|0x50,		cbuf1},
+	{SPEC|0x51,		cbuf2},
+	{SPEC|0x77,		cbuf3},
+	{SPEC|0x78,		cbuf4},
+	{SPEC|0x74,		cbuf5},
+	{SPEC|0x75,		cbuf6},
+	{SPEC|0x71,		cbuf7},
+	{SPEC|0x72,		cbuf8},
+	{SPEC|0x70,		cbuf9},
+	{SPEC|0x4d,		cbuf10},
+#endif
+
+#if	MSDOS & (HP150 == 0) & (WANGPC == 0)
+	{SPEC|CTRL|'_',		forwhunt},
+	{SPEC|CTRL|'S',		backhunt},
+	{SPEC|71,		gotobob},
+	{SPEC|72,		backline},
+	{SPEC|73,		backpage},
+	{SPEC|75,		backchar},
+	{SPEC|77,		forwchar},
+	{SPEC|79,		gotoeob},
+	{SPEC|80,		forwline},
+	{SPEC|81,		forwpage},
+	{SPEC|82,		insspace},
+	{SPEC|83,		forwdel},
+	{SPEC|115,		backword},
+	{SPEC|116,		forwword},
+	{SPEC|132,		gotobop},
+	{SPEC|118,		gotoeop},
+	{SPEC|84,		cbuf1},
+	{SPEC|85,		cbuf2},
+	{SPEC|86,		cbuf3},
+	{SPEC|87,		cbuf4},
+	{SPEC|88,		cbuf5},
+	{SPEC|89,		cbuf6},
+	{SPEC|90,		cbuf7},
+	{SPEC|91,		cbuf8},
+	{SPEC|92,		cbuf9},
+	{SPEC|93,		cbuf10},
+#endif
+
+#if	HP150
+	{SPEC|32,		backline},
+	{SPEC|33,		forwline},
+	{SPEC|35,		backchar},
+	{SPEC|34,		forwchar},
+	{SPEC|44,		gotobob},
+	{SPEC|46,		forwpage},
+	{SPEC|47,		backpage},
+	{SPEC|82,		nextwind},
+	{SPEC|68,		openline},
+	{SPEC|69,		killtext},
+	{SPEC|65,		forwdel},
+	{SPEC|64,		ctlxe},
+	{SPEC|67,		refresh},
+	{SPEC|66,		reposition},
+	{SPEC|83,		help},
+	{SPEC|81,		deskey},
+#endif
+
+#if	AMIGA
+	{SPEC|'?',		help},
+	{SPEC|'A',		backline},
+	{SPEC|'B',		forwline},
+	{SPEC|'C',		forwchar},
+	{SPEC|'D',		backchar},
+	{SPEC|'T',		backpage},
+	{SPEC|'S',		forwpage},
+	{SPEC|'a',		backword},
+	{SPEC|'`',		forwword},
+	{SPEC|'P',		cbuf1},
+	{SPEC|'Q',		cbuf2},
+	{SPEC|'R',		cbuf3},
+	{SPEC|'S',		cbuf4},
+	{SPEC|'T',		cbuf5},
+	{SPEC|'U',		cbuf6},
+	{SPEC|'V',		cbuf7},
+	{SPEC|'W',		cbuf8},
+	{SPEC|'X',		cbuf9},
+	{SPEC|'Y',		cbuf10},
+
+#endif
+
+#if  WANGPC
+	SPEC|0xE0,              quit,           /* Cancel */
+	SPEC|0xE1,              help,           /* Help */
+	SPEC|0xF1,              help,           /* ^Help */
+	SPEC|0xE3,              ctrlg,          /* Print */
+	SPEC|0xF3,              ctrlg,          /* ^Print */
+	SPEC|0xC0,              backline,       /* North */
+	SPEC|0xD0,              gotobob,        /* ^North */
+	SPEC|0xC1,              forwchar,       /* East */
+	SPEC|0xD1,              gotoeol,        /* ^East */
+	SPEC|0xC2,              forwline,       /* South */
+	SPEC|0xD2,              gotobop,        /* ^South */
+	SPEC|0xC3,              backchar,       /* West */
+	SPEC|0xD3,              gotobol,        /* ^West */
+	SPEC|0xC4,              ctrlg,          /* Home */
+	SPEC|0xD4,              gotobob,        /* ^Home */
+	SPEC|0xC5,              filesave,       /* Execute */
+	SPEC|0xD5,              ctrlg,          /* ^Execute */
+	SPEC|0xC6,              insfile,        /* Insert */
+	SPEC|0xD6,              ctrlg,          /* ^Insert */
+	SPEC|0xC7,              forwdel,        /* Delete */
+	SPEC|0xD7,              killregion,     /* ^Delete */
+	SPEC|0xC8,              backpage,       /* Previous */
+	SPEC|0xD8,              prevwind,       /* ^Previous */
+	SPEC|0xC9,              forwpage,       /* Next */
+	SPEC|0xD9,              nextwind,       /* ^Next */
+	SPEC|0xCB,              ctrlg,          /* Erase */
+	SPEC|0xDB,              ctrlg,          /* ^Erase */
+	SPEC|0xDC,              ctrlg,          /* ^Tab */
+	SPEC|0xCD,              ctrlg,          /* BackTab */
+	SPEC|0xDD,              ctrlg,          /* ^BackTab */
+	SPEC|0x80,              ctrlg,          /* Indent */
+	SPEC|0x90,              ctrlg,          /* ^Indent */
+	SPEC|0x81,              ctrlg,          /* Page */
+	SPEC|0x91,              ctrlg,          /* ^Page */
+	SPEC|0x82,              ctrlg,          /* Center */
+	SPEC|0x92,              ctrlg,          /* ^Center */
+	SPEC|0x83,              ctrlg,          /* DecTab */
+	SPEC|0x93,              ctrlg,          /* ^DecTab */
+	SPEC|0x84,              ctrlg,          /* Format */
+	SPEC|0x94,              ctrlg,          /* ^Format */
+	SPEC|0x85,              ctrlg,          /* Merge */
+	SPEC|0x95,              ctrlg,          /* ^Merge */
+	SPEC|0x86,              setmark,        /* Note */
+	SPEC|0x96,              ctrlg,          /* ^Note */
+	SPEC|0x87,              ctrlg,          /* Stop */
+	SPEC|0x97,              ctrlg,          /* ^Stop */
+	SPEC|0x88,              forwsearch,     /* Srch */
+	SPEC|0x98,              backsearch,     /* ^Srch */
+	SPEC|0x89,              sreplace,       /* Replac */
+	SPEC|0x99,              qreplace,       /* ^Replac */
+	SPEC|0x8A,              ctrlg,          /* Copy */
+	SPEC|0x9A,              ctrlg,          /* ^Copy */
+	SPEC|0x8B,              ctrlg,          /* Move */
+	SPEC|0x9B,              ctrlg,          /* ^Move */
+	SPEC|0x8C,              namedcmd,       /* Command */
+	SPEC|0x9C,              spawn,          /* ^Command */
+	SPEC|0x8D,              ctrlg,          /* ^ */
+	SPEC|0x9D,              ctrlg,          /* ^^ */
+	SPEC|0x8E,              ctrlg,          /* Blank */
+	SPEC|0x9E,              ctrlg,          /* ^Blank */
+	SPEC|0x8F,              gotoline,       /* GoTo */
+	SPEC|0x9F,              usebuffer,      /* ^GoTo */
+#endif
+ 
+	{0x7F,			backdel},
+	{0,			NULL}
+};
+
+#if RAINBOW
+
+#include "rainbow.h"
+
+/*
+ * Mapping table from the LK201 function keys to the internal EMACS character.
+ */
+
+short lk_map[][2] = {
+	Up_Key,                         CTRL+'P',
+	Down_Key,                       CTRL+'N',
+	Left_Key,                       CTRL+'B',
+	Right_Key,                      CTRL+'F',
+	Shift+Left_Key,                 META+'B',
+	Shift+Right_Key,                META+'F',
+	Control+Left_Key,               CTRL+'A',
+	Control+Right_Key,              CTRL+'E',
+	Prev_Scr_Key,                   META+'V',
+	Next_Scr_Key,                   CTRL+'V',
+	Shift+Up_Key,                   META+'<',
+	Shift+Down_Key,                 META+'>',
+	Cancel_Key,                     CTRL+'G',
+	Find_Key,                       CTRL+'S',
+	Shift+Find_Key,                 CTRL+'R',
+	Insert_Key,                     CTRL+'Y',
+	Options_Key,                    CTRL+'D',
+	Shift+Options_Key,              META+'D',
+	Remove_Key,                     CTRL+'W',
+	Shift+Remove_Key,               META+'W',
+	Select_Key,                     CTRL+'@',
+	Shift+Select_Key,               CTLX+CTRL+'X',
+	Interrupt_Key,                  CTRL+'U',
+	Keypad_PF2,                     META+'L',
+	Keypad_PF3,                     META+'C',
+	Keypad_PF4,                     META+'U',
+	Shift+Keypad_PF2,               CTLX+CTRL+'L',
+	Shift+Keypad_PF4,               CTLX+CTRL+'U',
+	Keypad_1,                       CTLX+'1',
+	Keypad_2,                       CTLX+'2',
+	Do_Key,                         CTLX+'E',
+	Keypad_4,                       CTLX+CTRL+'B',
+	Keypad_5,                       CTLX+'B',
+	Keypad_6,                       CTLX+'K',
+	Resume_Key,                     META+'!',
+	Control+Next_Scr_Key,           CTLX+'N',
+	Control+Prev_Scr_Key,           CTLX+'P',
+	Control+Up_Key,                 CTLX+CTRL+'P',
+	Control+Down_Key,               CTLX+CTRL+'N',
+	Help_Key,                       CTLX+'=',
+	Shift+Do_Key,                   CTLX+'(',
+	Control+Do_Key,                 CTLX+')',
+	Keypad_0,                       CTLX+'Z',
+	Shift+Keypad_0,                 CTLX+CTRL+'Z',
+	Main_Scr_Key,                   CTRL+'C',
+	Keypad_Enter,                   CTLX+'!',
+	Exit_Key,                       CTLX+CTRL+'C',
+	Shift+Exit_Key,                 CTRL+'Z'
+};
+
+#define lk_map_size     (sizeof(lk_map)/2)
+#endif
+

Added: clients/emacs/edef.h
===================================================================
--- clients/emacs/edef.h	                        (rev 0)
+++ clients/emacs/edef.h	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,140 @@
+/*	EDEF:		Global variable definitions for
+			MicroEMACS 3.2
+
+			written by Dave G. Conroy
+			modified by Steve Wilhite, George Jones
+			greatly modified by Daniel Lawrence
+*/
+
+/* some global fuction declarations */
+
+/* char *malloc(); */
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef	maindef
+
+/* for MAIN.C */
+
+/* initialized global definitions */
+
+int     fillcol = 72;                   /* Current fill column          */
+short   kbdm[NKBDM] = {CTLX|')'};       /* Macro                        */
+char    pat[NPAT];                      /* Search pattern		*/
+char	rpat[NPAT];			/* replacement pattern		*/
+char	sarg[NSTRING] = "";		/* string argument for line exec*/
+int	eolexist = TRUE;		/* does clear to EOL exist	*/
+int	revexist = FALSE;		/* does reverse video exist?	*/
+char	*modename[] = {			/* name of modes		*/
+	"WRAP", "CMODE", "SPELL", "EXACT", "VIEW", "OVER", "MAGIC"};
+char	modecode[] = "WCSEVOM";		/* letters to represent modes	*/
+int	gmode = 0;			/* global editor mode		*/
+int	gfcolor = 7;			/* global forgrnd color (white)	*/
+int	gbcolor	= 0;			/* global backgrnd color (black)*/
+int     sgarbf  = TRUE;                 /* TRUE if screen is garbage	*/
+int     mpresf  = FALSE;                /* TRUE if message in last line */
+int	clexec	= FALSE;		/* command line execution flag	*/
+int	mstore	= FALSE;		/* storing text to macro flag	*/
+struct	BUFFER *bstore = NULL;		/* buffer to store macro text to*/
+int     vtrow   = 0;                    /* Row location of SW cursor */
+int     vtcol   = 0;                    /* Column location of SW cursor */
+int     ttrow   = HUGE;                 /* Row location of HW cursor */
+int     ttcol   = HUGE;                 /* Column location of HW cursor */
+int	lbound	= 0;			/* leftmost column of current line
+					   being displayed */
+int	metac = CTRL | '[';		/* current meta character */
+int	ctlxc = CTRL | 'X';		/* current control X prefix char */
+int	quotec = 0x11;			/* quote char during mlreply() */
+char	*cname[] = {			/* names of colors		*/
+	"BLACK", "RED", "GREEN", "YELLOW", "BLUE",
+	"MAGENTA", "CYAN", "WHITE"};
+KILL *kbufp  = NULL;		/* current kill buffer chunk pointer	*/
+KILL *kbufh  = NULL;		/* kill buffer header pointer		*/
+int kused = KBLOCK;		/* # of bytes used in kill buffer	*/
+WINDOW *swindow = NULL;		/* saved window pointer			*/
+
+/* uninitialized global definitions */
+
+int     currow;                 /* Cursor row                   */
+int     curcol;                 /* Cursor column                */
+int     thisflag;               /* Flags, this command          */
+int     lastflag;               /* Flags, last command          */
+int     curgoal;                /* Goal for C-P, C-N            */
+WINDOW  *curwp;                 /* Current window               */
+BUFFER  *curbp;                 /* Current buffer               */
+WINDOW  *wheadp;                /* Head of list of windows      */
+BUFFER  *bheadp;                /* Head of list of buffers      */
+BUFFER  *blistp;                /* Buffer for C-X C-B           */
+short   *kbdmip;                /* Input pointer for above      */
+short   *kbdmop;                /* Output pointer for above     */
+
+BUFFER  *bfind();               /* Lookup a buffer by name      */
+WINDOW  *wpopup();              /* Pop up window creation       */
+LINE    *lalloc();              /* Allocate a line              */
+
+#else
+
+/* for all the other .C files */
+
+/* initialized global external declarations */
+
+extern  int     fillcol;                /* Fill column                  */
+extern  short   kbdm[];                 /* Holds kayboard macro data    */
+extern  char    pat[];                  /* Search pattern               */
+extern	char	rpat[];			/* Replacement pattern		*/
+extern	char	sarg[];			/* string argument for line exec*/
+extern	int	eolexist;		/* does clear to EOL exist?	*/
+extern	int	revexist;		/* does reverse video exist?	*/
+extern	char *modename[];		/* text names of modes		*/
+extern	char	modecode[];		/* letters to represent modes	*/
+extern	KEYTAB keytab[];		/* key bind to functions table	*/
+extern	NBIND names[];			/* name to function table	*/
+extern	int	gmode;			/* global editor mode		*/
+extern	int	gfcolor;		/* global forgrnd color (white)	*/
+extern	int	gbcolor;		/* global backgrnd color (black)*/
+extern  int     sgarbf;                 /* State of screen unknown      */
+extern  int     mpresf;                 /* Stuff in message line        */
+extern	int	clexec;			/* command line execution flag	*/
+extern	int	mstore;			/* storing text to macro flag	*/
+extern	struct	BUFFER *bstore;		/* buffer to store macro text to*/
+extern	int     vtrow;                  /* Row location of SW cursor */
+extern	int     vtcol;                  /* Column location of SW cursor */
+extern	int     ttrow;                  /* Row location of HW cursor */
+extern	int     ttcol;                  /* Column location of HW cursor */
+extern	int	lbound;			/* leftmost column of current line
+					   being displayed */
+extern	int	metac;			/* current meta character */
+extern	int	ctlxc;			/* current control X prefix char */
+extern	int	quotec;			/* quote char during mlreply() */
+extern	char	*cname[];		/* names of colors		*/
+extern KILL *kbufp;			/* current kill buffer chunk pointer */
+extern KILL *kbufh;			/* kill buffer header pointer	*/
+extern int kused;			/* # of bytes used in KB        */
+extern WINDOW *swindow;			/* saved window pointer		*/
+
+/* initialized global external declarations */
+
+extern  int     currow;                 /* Cursor row                   */
+extern  int     curcol;                 /* Cursor column                */
+extern  int     thisflag;               /* Flags, this command          */
+extern  int     lastflag;               /* Flags, last command          */
+extern  int     curgoal;                /* Goal for C-P, C-N            */
+extern  WINDOW  *curwp;                 /* Current window               */
+extern  BUFFER  *curbp;                 /* Current buffer               */
+extern  WINDOW  *wheadp;                /* Head of list of windows      */
+extern  BUFFER  *bheadp;                /* Head of list of buffers      */
+extern  BUFFER  *blistp;                /* Buffer for C-X C-B           */
+extern  short   *kbdmip;                /* Input pointer for above      */
+extern  short   *kbdmop;                /* Output pointer for above     */
+
+extern  BUFFER  *bfind();               /* Lookup a buffer by name      */
+extern  WINDOW  *wpopup();              /* Pop up window creation       */
+extern  LINE    *lalloc();              /* Allocate a line              */
+
+#endif
+
+/* terminal table defined only in TERM.C */
+
+#ifndef	termdef
+extern  TERM    term;                   /* Terminal information.        */
+#endif

Added: clients/emacs/efunc.h
===================================================================
--- clients/emacs/efunc.h	                        (rev 0)
+++ clients/emacs/efunc.h	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,352 @@
+/*	EFUNC.H:	MicroEMACS function declarations and names
+
+		This file list all the C code functions used by MicroEMACS
+	and the names to use to bind keys to them. To add functions,
+	declare it here in both the extern function list and the name
+	binding table.
+
+*/
+
+/*	External function declarations		*/
+
+extern  int     ctrlg();                /* Abort out of things          */
+extern  int     quit();                 /* Quit                         */
+extern  int     ctlxlp();               /* Begin macro                  */
+extern  int     ctlxrp();               /* End macro                    */
+extern  int     ctlxe();                /* Execute macro                */
+extern  int     fileread();             /* Get a file, read only        */
+extern  int     filefind();		/* Get a file, read write       */
+extern  int     filewrite();            /* Write a file                 */
+extern  int     filesave();             /* Save current file            */
+extern  int     filename();             /* Adjust file name             */
+extern  int     getccol();              /* Get current column           */
+extern  int     gotobol();              /* Move to start of line        */
+extern  int     forwchar();             /* Move forward by characters   */
+extern  int     gotoeol();              /* Move to end of line          */
+extern  int     backchar();             /* Move backward by characters  */
+extern  int     forwline();             /* Move forward by lines        */
+extern  int     backline();             /* Move backward by lines       */
+extern  int     forwpage();             /* Move forward by pages        */
+extern  int     backpage();             /* Move backward by pages       */
+extern  int     gotobob();              /* Move to start of buffer      */
+extern  int     gotoeob();              /* Move to end of buffer        */
+extern  int     setfillcol();           /* Set fill column.             */
+extern  int     setmark();              /* Set mark                     */
+extern  int     swapmark();             /* Swap "." and mark            */
+extern  int     forwsearch();           /* Search forward               */
+extern  int     backsearch();           /* Search backwards             */
+extern	int	sreplace();		/* search and replace		*/
+extern	int	qreplace();		/* search and replace w/query	*/
+extern  int     showcpos();             /* Show the cursor position     */
+extern  int     nextwind();             /* Move to the next window      */
+extern  int     prevwind();             /* Move to the previous window  */
+extern  int     onlywind();             /* Make current window only one */
+extern  int     splitwind();            /* Split current window         */
+extern  int     mvdnwind();             /* Move window down             */
+extern  int     mvupwind();             /* Move window up               */
+extern  int     enlargewind();          /* Enlarge display window.      */
+extern  int     shrinkwind();           /* Shrink window.               */
+extern  int     listbuffers();          /* Display list of buffers      */
+extern  int     usebuffer();            /* Switch a window to a buffer  */
+extern  int     killbuffer();           /* Make a buffer go away.       */
+extern  int     reposition();           /* Reposition window            */
+extern  int     refresh();              /* Refresh the screen           */
+extern  int     twiddle();              /* Twiddle characters           */
+extern  int     tab();                  /* Insert tab                   */
+extern  int     newline();              /* Insert CR-LF                 */
+extern  int     indent();               /* Insert CR-LF, then indent    */
+extern  int     openline();             /* Open up a blank line         */
+extern  int     deblank();              /* Delete blank lines           */
+extern  int     quote();                /* Insert literal               */
+extern  int     backword();             /* Backup by words              */
+extern  int     forwword();             /* Advance by words             */
+extern  int     forwdel();              /* Forward delete               */
+extern  int     backdel();              /* Backward delete              */
+extern  int     killtext();             /* Kill forward                 */
+extern  int     yank();                 /* Yank back from killbuffer.   */
+extern  int     upperword();            /* Upper case word.             */
+extern  int     lowerword();            /* Lower case word.             */
+extern  int     upperregion();          /* Upper case region.           */
+extern  int     lowerregion();          /* Lower case region.           */
+extern  int     capword();              /* Initial capitalize word.     */
+extern  int     delfword();             /* Delete forward word.         */
+extern  int     delbword();             /* Delete backward word.        */
+extern  int     killregion();           /* Kill region.                 */
+extern  int     copyregion();           /* Copy region to kill buffer.  */
+extern  int     spawncli();             /* Run CLI in a subjob.         */
+extern  int     spawn();                /* Run a command in a subjob.   */
+#if	BSD
+extern	int	bktoshell();		/* suspend emacs to parent shell*/
+extern	int	rtfrmshell();		/* return from a suspended state*/
+#endif
+extern  int     quickexit();            /* low keystroke style exit.    */
+extern	int	setmode();		/* set an editor mode		*/
+extern	int	delmode();		/* delete a mode		*/
+extern	int	gotoline();		/* go to a numbered line	*/
+extern	int	namebuffer();		/* rename the current buffer	*/
+#if	WORDPRO
+extern	int	gotobop();		/* go to begining/paragraph	*/
+extern	int	gotoeop();		/* go to end/paragraph		*/
+extern	int	fillpara();		/* fill current paragraph	*/
+#endif
+extern	int	help();			/* get the help file here	*/
+extern	int	deskey();		/* describe a key's binding	*/
+extern	int	viewfile();		/* find a file in view mode	*/
+extern	int	insfile();		/* insert a file		*/
+extern	int	scrnextup();		/* scroll next window back	*/
+extern	int	scrnextdw();		/* scroll next window down	*/
+extern	int	bindtokey();		/* bind a function to a key	*/
+extern	int	unbindkey();		/* unbind a key's function	*/
+extern	int	namedcmd();		/* execute named command	*/
+extern	int	desbind();		/* describe bindings		*/
+extern	int	execcmd();		/* execute a command line	*/
+extern	int	execbuf();		/* exec commands from a buffer	*/
+extern	int	execfile();		/* exec commands from a file	*/
+extern	int	nextbuffer();		/* switch to the next buffer	*/
+#if	WORDPRO
+extern	int	killpara();		/* kill the current paragraph	*/
+#endif
+extern	int	setgmode();		/* set a global mode		*/
+extern	int	delgmode();		/* delete a global mode		*/
+extern	int	insspace();		/* insert a space forword	*/
+extern	int	forwhunt();		/* hunt forward for next match	*/
+extern	int	backhunt();		/* hunt backwards for next match*/
+extern	int	pipe();			/* pipe command into buffer	*/
+extern	int	filter();		/* filter buffer through dos	*/
+extern	int	delwind();		/* delete the current window	*/
+extern	int	cbuf1();		/* execute numbered comd buffer */
+extern	int	cbuf2();
+extern	int	cbuf3();
+extern	int	cbuf4();
+extern	int	cbuf5();
+extern	int	cbuf6();
+extern	int	cbuf7();
+extern	int	cbuf8();
+extern	int	cbuf9();
+extern	int	cbuf10();
+extern	int	cbuf11();
+extern	int	cbuf12();
+extern	int	cbuf13();
+extern	int	cbuf14();
+extern	int	cbuf15();
+extern	int	cbuf16();
+extern	int	cbuf17();
+extern	int	cbuf18();
+extern	int	cbuf19();
+extern	int	cbuf20();
+extern	int	cbuf21();
+extern	int	cbuf22();
+extern	int	cbuf23();
+extern	int	cbuf24();
+extern	int	cbuf25();
+extern	int	cbuf26();
+extern	int	cbuf27();
+extern	int	cbuf28();
+extern	int	cbuf29();
+extern	int	cbuf30();
+extern	int	cbuf31();
+extern	int	cbuf32();
+extern	int	cbuf33();
+extern	int	cbuf34();
+extern	int	cbuf35();
+extern	int	cbuf36();
+extern	int	cbuf37();
+extern	int	cbuf38();
+extern	int	cbuf39();
+extern	int	cbuf40();
+extern	int	storemac();		/* store text for macro		*/
+extern	int	resize();		/* resize current window	*/
+extern	int	clrmes();		/* clear the message line	*/
+extern	int	meta();			/* meta prefix dummy function	*/
+extern	int	cex();			/* ^X prefix dummy function	*/
+extern	int	istring();		/* insert string in text	*/
+extern	int	unmark();		/* unmark current buffer	*/
+#if	ISRCH
+extern	int	fisearch();		/* forward incremental search	*/
+extern	int	risearch();		/* reverse incremental search	*/
+#endif
+#if	WORDPRO
+extern	int	wordcount();		/* count words in region	*/
+#endif
+extern	int	savewnd();		/* save current window		*/
+extern	int	restwnd();		/* restore current window	*/
+extern	int	upscreen();		/* force screen update		*/
+extern	int	writemsg();		/* write text on message line	*/
+
+/*	Name to function binding table
+
+		This table gives the names of all the bindable functions
+	end their C function address. These are used for the bind-to-key
+	function.
+*/
+
+NBIND	names[] = {
+	{"add-mode",			setmode},
+	{"add-global-mode",		setgmode},
+	{"backward-character",		backchar},
+	{"begin-macro",			ctlxlp},
+	{"begining-of-file",		gotobob},
+	{"begining-of-line",		gotobol},
+	{"bind-to-key",			bindtokey},
+	{"buffer-position",		showcpos},
+	{"case-region-lower",		lowerregion},
+	{"case-region-upper",		upperregion},
+	{"case-word-capitalize",	capword},
+	{"case-word-lower",		lowerword},
+	{"case-word-upper",		upperword},
+	{"change-file-name",		filename},
+	{"clear-and-redraw",		refresh},
+	{"clear-message-line",		clrmes},
+	{"copy-region",			copyregion},
+#if	WORDPRO
+	{"count-words",			wordcount},
+#endif
+	{"ctlx-prefix",			cex},
+	{"delete-blank-lines",		deblank},
+	{"delete-buffer",		killbuffer},
+	{"delete-mode",			delmode},
+	{"delete-global-mode",		delgmode},
+	{"delete-next-character",	forwdel},
+	{"delete-next-word",		delfword},
+	{"delete-other-windows",	onlywind},
+	{"delete-previous-character",	backdel},
+	{"delete-previous-word",	delbword},
+	{"delete-window",		delwind},
+	{"describe-bindings",		desbind},
+	{"describe-key",		deskey},
+	{"end-macro",			ctlxrp},
+	{"end-of-file",			gotoeob},
+	{"end-of-line",			gotoeol},
+	{"exchange-point-and-mark",	swapmark},
+	{"execute-buffer",		execbuf},
+	{"execute-command-line",	execcmd},
+	{"execute-file",		execfile},
+	{"execute-macro",		ctlxe},
+	{"execute-macro-1",		cbuf1},
+	{"execute-macro-2",		cbuf2},
+	{"execute-macro-3",		cbuf3},
+	{"execute-macro-4",		cbuf4},
+	{"execute-macro-5",		cbuf5},
+	{"execute-macro-6",		cbuf6},
+	{"execute-macro-7",		cbuf7},
+	{"execute-macro-8",		cbuf8},
+	{"execute-macro-9",		cbuf9},
+	{"execute-macro-10",		cbuf10},
+	{"execute-macro-11",		cbuf11},
+	{"execute-macro-12",		cbuf12},
+	{"execute-macro-13",		cbuf13},
+	{"execute-macro-14",		cbuf14},
+	{"execute-macro-15",		cbuf15},
+	{"execute-macro-16",		cbuf16},
+	{"execute-macro-17",		cbuf17},
+	{"execute-macro-18",		cbuf18},
+	{"execute-macro-19",		cbuf19},
+	{"execute-macro-20",		cbuf20},
+	{"execute-macro-21",		cbuf21},
+	{"execute-macro-22",		cbuf22},
+	{"execute-macro-23",		cbuf23},
+	{"execute-macro-24",		cbuf24},
+	{"execute-macro-25",		cbuf25},
+	{"execute-macro-26",		cbuf26},
+	{"execute-macro-27",		cbuf27},
+	{"execute-macro-28",		cbuf28},
+	{"execute-macro-29",		cbuf29},
+	{"execute-macro-30",		cbuf30},
+	{"execute-macro-31",		cbuf31},
+	{"execute-macro-32",		cbuf32},
+	{"execute-macro-33",		cbuf33},
+	{"execute-macro-34",		cbuf34},
+	{"execute-macro-35",		cbuf35},
+	{"execute-macro-36",		cbuf36},
+	{"execute-macro-37",		cbuf37},
+	{"execute-macro-38",		cbuf38},
+	{"execute-macro-39",		cbuf39},
+	{"execute-macro-40",		cbuf40},
+	{"execute-named-command",	namedcmd},
+	{"exit-emacs",			quit},
+#if	WORDPRO
+	{"fill-paragraph",		fillpara},
+#endif
+	{"filter-buffer",		filter},
+	{"find-file",			filefind},
+	{"forward-character",		forwchar},
+	{"goto-line",			gotoline},
+	{"grow-window",			enlargewind},
+	{"handle-tab",			tab},
+	{"hunt-forward",		forwhunt},
+	{"hunt-backward",		backhunt},
+	{"help",			help},
+	{"i-shell",			spawncli},
+#if	ISRCH
+	{"incremental-search",		fisearch},
+#endif
+	{"insert-file",			insfile},
+	{"insert-space",		insspace},
+	{"insert-string",		istring},
+#if	WORDPRO
+	{"kill-paragraph",		killpara},
+#endif
+	{"kill-region",			killregion},
+	{"kill-to-end-of-line",		killtext},
+	{"list-buffers",		listbuffers},
+	{"meta-prefix",			meta},
+	{"move-window-down",		mvdnwind},
+	{"move-window-up",		mvupwind},
+	{"name-buffer",			namebuffer},
+	{"newline",			newline},
+	{"newline-and-indent",		indent},
+	{"next-buffer",			nextbuffer},
+	{"next-line",			forwline},
+	{"next-page",			forwpage},
+#if	WORDPRO
+	{"next-paragraph",		gotoeop},
+#endif
+	{"next-window",			nextwind},
+	{"next-word",			forwword},
+	{"open-line",			openline},
+	{"pipe-command",		pipe},
+	{"previous-line",		backline},
+	{"previous-page",		backpage},
+#if	WORDPRO
+	{"previous-paragraph",		gotobop},
+#endif
+	{"previous-window",		prevwind},
+	{"previous-word",		backword},
+	{"query-replace-string",	qreplace},
+	{"quick-exit",			quickexit},
+	{"quote-character",		quote},
+	{"read-file",			fileread},
+	{"redraw-display",		reposition},
+	{"resize-window",		resize},
+	{"restore-window",		restwnd},
+	{"replace-string",		sreplace},
+#if	ISRCH
+	{"reverse-incremental-search",	risearch},
+#endif
+	{"save-file",			filesave},
+	{"save-window",			savewnd},
+	{"scroll-next-up",		scrnextup},
+	{"scroll-next-down",		scrnextdw},
+	{"search-forward",		forwsearch},
+	{"search-reverse",		backsearch},
+	{"select-buffer",		usebuffer},
+	{"set-fill-column",		setfillcol},
+	{"set-mark",			setmark},
+	{"shell-command",		spawn},
+	{"shrink-window",		shrinkwind},
+	{"split-current-window",	splitwind},
+	{"store-macro",			storemac},
+#if	BSD
+	{"suspend-emacs",		bktoshell},
+#endif
+	{"transpose-characters",	twiddle},
+	{"unbind-key",			unbindkey},
+	{"unmark-buffer",		unmark},
+	{"update-screen",		upscreen},
+	{"view-file",			viewfile},
+	{"write-file",			filewrite},
+	{"write-message",		writemsg},
+	{"yank",			yank},
+
+	{"",			NULL}
+};

Added: clients/emacs/emacs.hlp
===================================================================
--- clients/emacs/emacs.hlp	                        (rev 0)
+++ clients/emacs/emacs.hlp	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,195 @@
+=>		MicroEMACS 3.7 Help screens		(07/02/86)
+
+	M-  means to use the <ESC> key prior to using another key
+	^A  means to use the control key at the same time as the A key
+
+^V or [Pg Dn]     Scroll down		M-< or <HOME>	Begining of file
+^Z or [Pg Up]     Scroll up		M-> or <END>	End of file
+
+-----------------------------------------------------------------------
+=>		(1) MOVING THE CURSOR
+
+^F  Forward character   M-F    Forward word		Keypad arrows
+^B  Backward character  M-B    Backward word		are active!
+^A  Front of line	M-G    Goto a line
+^E  End of line		
+^N  Next line		M-N    Front of paragraph
+^P  Previous line	M-P    End of paragraph
+-----------------------------------------------------------------------
+=>		(2) DELETING & INSERTING
+
+<--             Delete previous character
+^D or <DELETE>  Delete next character
+^C or <INSERT>  Insert a space
+M-<--           Delete previous word
+M-D             Delete next word
+^K              Close (delete) to end of line
+-----------------------------------------------------------------------
+=>		(2a) MORE DELETING & INSERTING
+
+<RETURN>   Insert a newline             <TAB>  Advance to next tab stop
+^J         Insert a newline and indent  M-^W   Delete paragraph
+^O         Open (insert) line
+^W         Delete region between mark (set using M-<spacebar>) and cursor
+M-W        Copy region to kill buffer
+^X ^O      Delete blank lines around cursor
+-----------------------------------------------------------------------
+=>		(3) SEARCHING
+
+^S	Search forward from cursor position.
+^R	Reverse search from cursor position.
+^X S	Forward incremental search
+^X R	Reverse incremental search
+-----------------------------------------------------------------------
+=>		(4) REPLACING
+
+M-R   Replace all instances of first typed-in string with second
+          typed-in string.  End each string with ESC.
+M-^R  Replace with query.  Answer with:
+	^G  cancel			.   exit to entry point
+	!   replace the rest		Y    replace & continue
+	?   Get a list of options	N   no replacement & continue
+-----------------------------------------------------------------------
+=>		(5) CAPITALIZING & TRANSPOSING
+
+M-U	UPPERCASE word
+M-C	Capitalize word		^T	Transpose characters
+M-L	lowercase word
+^X ^L	lowercase region
+^X ^U	uppercase region
+^Q	Quote next entry, so that control codes may be entered into text
+-----------------------------------------------------------------------
+=>		(6) REGIONS & THE KILL BUFFER
+
+M-<spacebar>	set MARK at current position
+^X ^X		eXchange mark and cursor
+
+A REGION will then be continuously-defined as the area between the mark and
+the current cursor position.  The KILL BUFFER is the text which has been
+most recently saved or deleted.
+-----------------------------------------------------------------------
+=>		(7) COPYING AND MOVING
+
+^W  Delete (Wipe) region		M-W	copy region to KILL buffer
+^Y  Yankback save buffer at cursor
+Generally, the procedure for copying or moving text is:
+    1)  Mark a REGION using M-<spacebar> at beginning and cursor at end.
+    2)  Delete it (with ^W) or copy it (with M-W) into the KILL buffer.
+    3)  Move the cursor to the desired location and yank it back (with ^Y).
+-----------------------------------------------------------------------
+=>		(8) MODES OF OPERATION
+^X M	Add mode in buffer              M-M    Add global mode
+^X ^M   Delete mode in buffer           M-^M   Delete global mode
+OVER		Replaces (overwrites) rather than inserts characters
+WRAP		Turns on word wrap (automatic carraige return).
+VIEW		Allows viewing file without insertion and deletion.
+CMODE		Automatic indenting for C program entry
+EXACT/MAGIC	Changes how search and replace commands work (see next page)
+-----------------------------------------------------------------------
+=>		(9) SEARCH AND REPLACE MODES
+
+EXACT	Uppper/lower case is not ignored in searches
+MAGIC   Regular pattern matching characters are active
+           ?   Matches any one character
+           *   Matches any sequence of characters
+	[EXACT MODE NOT READY YET ---- 6/5/86]
+
+-----------------------------------------------------------------------
+=>		(10) ON-SCREEN FORMATTING
+
+^X F		Set fill column
+Mn-<tab>	Set tab spacing to n charecters between tabs stops
+M-Q		Format paragraph so that text lies between margins
+^X =		Position report -- displays line number, char count,
+                                   file size and character under cursor
+M-^C		Count words/lines/chars in marked region
+-----------------------------------------------------------------------
+=>		(11) MULTIPLE WINDOWS
+
+Many WINDOWS may be active at once on the screen.  All windows may show
+different parts of the same buffer, or each may display a different one.
+^X 2	Split the current window in two	^X O	Change to next window
+^X 0    delete current window           ^X P    Change to previous window
+^X 1	delete all other windows        M-^V    Page down next window
+                                  	M-^Z	Page up other window
+-----------------------------------------------------------------------
+=>		(12) CONTROLLING WINDOWS
+
+^X ^    Enlarge current window   M-<n> ^X W   Resize window to <n> lines
+^X ^Z   Shrink current window
+^X ^N   Move window down
+^X ^P   Move window up
+M-^L    Reposition window
+^L      Refresh the screen
+-----------------------------------------------------------------------
+=>		(13) MULTIPLE BUFFERS
+A BUFFER is a named area containing a document being edited.  Many buffers
+may be activated at once.
+^X B	Switch to another buffer.  <CR> = use just-previous buffer
+^X X	Switch to next buffer in buffer list
+M-^N    Change name of current buffer
+^X K	Delete a non-displayed buffer.
+^X ^B	Display buffer directory in a window
+-----------------------------------------------------------------------
+=>		(14) READING FROM DISK
+
+^X ^F	Find file; read into a new buffer created from filename.
+	(This is the usual way to begin editing a new file.)
+^X ^R	Read file into current buffer, erasing its previous contents.
+	No new buffer will be created.
+^X ^I	Insert file into current buffer at cursor's location.
+^X ^V	Find a file to make current in VIEW mode
+-----------------------------------------------------------------------
+=>		(15) SAVING TO DISK
+
+^X ^S	Save current buffer to disk
+^X ^W	Write current buffer to disk
+^X N    Change file name of current buffer
+M-Z	Write out all changed buffers and exit MicroEMACS
+
+
+-----------------------------------------------------------------------
+=>		(16) ACCESSING THE OPERATING SYSTEM
+
+^X !	Send one command to the operating system and return
+^X @	Pipe DOS command results to buffer
+^X #	Filter buffer through DOS filter program
+^X C	Start a new command processor under MicroEMACS
+^X D	Suspend MicroEMACS into the background (UNIX BSD4.2 only)
+^X ^C	Exit MicroEMACS
+-----------------------------------------------------------------------
+=>		(17) KEY BINDINGS AND COMMANDS
+
+M-K	Bind a key to a command
+M-^K	Unbind a key from a command
+^X ?	Describe command bound to a key
+M-X	Execute a named (and possibly unbound) command
+{Describe-bindings}
+	Display a list of all commands and key bindings to a buffer
+-----------------------------------------------------------------------
+=>		(18) COMMAND EXECUTION
+Commands can be specified as command lines in the form:
+	<optional repeat count> {command-name} <optional arguments>
+{Execute-command-line}	execute a typed in command line
+{Execute-buffer}	executes commands lines in a buffer
+{Execute-file}		executes command lines from a file
+{clear-message-line}	clears the message line during execution
+   M-~			clears the change flag for a buffer
+-----------------------------------------------------------------------
+=>		(19) MACRO EXECUTION
+
+^X (	Start recording keyboard macro
+^X )	Stop recording keyboard macro
+^X E	Execute keyboard macro
+M-<n> {store-macro}	Start recording named macro
+      [end]		Stop recording named macro
+{execute-macro-n}	Execute macro n (where n is from 1 to 20)
+-----------------------------------------------------------------------
+=>		(20) SPECIAL KEYS
+
+^G		Cancel current command and return to top level of processing.
+^U or		Universal repeat.  May be followed by an integer (default = 4)
+M-<digit>	and repeats the next command that many times.
+M-X		Execute a named (and possibly unbound) command
+
+

Added: clients/emacs/emacs.key
===================================================================
--- clients/emacs/emacs.key	                        (rev 0)
+++ clients/emacs/emacs.key	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,94 @@
+		Default Key Bindings for MicroEmacs 3.7		(06/05/86)
+		========================================
+
+ ^A   Move to start of line           
+ ^B   Move backward by characters     ESC B   Backup by words
+ ^C   Insert space                    ESC C   Initial capitalize word
+ ^D   Forward delete                  ESC D   Delete forward word
+ ^E   Goto end of line                     
+ ^F   Move forward by characters      ESC F   Advance by words
+ ^G   Abort out of things             ESC G   Go to a line
+ ^H   Backward delete                 
+ ^I   Insert tab/Set tab stops
+ ^J   Insert CR-LF, then indent                     
+ ^K   Kill forward                    ESC K   Bind Key to function
+ ^L   Refresh the screen              ESC L   Lower case word
+ ^M   Insert CR-LF                    ESC M   Add global mode
+ ^N   Move forward by lines           ESC N   Goto End paragraph
+ ^O   Open up a blank line            
+ ^P   Move backward by lines          ESC P   Goto Begining of paragraph
+ ^Q   Insert literal                  ESC Q   Fill current paragraph
+ ^R   Search backwards                ESC R   Search and replace
+ ^S   Search forward
+ ^T   Transpose characters                     
+ ^U   Repeat command four times       ESC U   Upper case word
+ ^V   Move forward by pages           ESC V   Move backward by pages
+ ^W   Kill region                     ESC W   Copy region to kill buffer
+ ^Y   Yank back from killbuffer       ESC X   Execute named command
+ ^Z   Move backward by pages          ESC Z   Save all buffers and exit
+
+ ESC ^C   Count words in region       ESC ~   Unmark current buffer
+ ESC ^H   Delete backward word        ESC !   Reposition window
+ ESC ^K   Unbind Key from function    ESC <   Move to start of buffer
+ ESC ^L   Reposition window           ESC >   Move to end of buffer
+ ESC ^M   Delete global mode          ESC .   Set mark
+ ESC ^N   Rename current buffer       ESC space    Set mark
+ ESC ^R   Search & replace w/query    ESC rubout   Delete backward word
+ ESC ^V   Scroll next window down         rubout   Backward delete       
+ ESC ^W   Delete Paragraph
+ ESC ^Z   Scroll next window up
+
+ ^X ?   Describe a key             ^X !   Run 1 command in a subjob
+ ^X =   Show the cursor position   ^X @   Pipe DOS command to buffer
+ ^X ^   Enlarge display window     ^X #   Filter buffer thru DOS filter
+ ^X 0   Delete current window      ^X (   Begin macro
+ ^X 1   Delete other windows       ^X )   End macro
+ ^X 2   Split current window
+
+ ^X ^B   Display buffer list       ^X B   Switch a window to a buffer
+ ^X ^C   Exit MicroEMACS           ^X C   Start a new command processer
+                                   ^X D   Suspend MicroEMACS (BSD4.2 only)
+                                   ^X E   Execute macro
+ ^X ^F   Find file                 ^X F   Set fill column
+ ^X ^I   Insert file
+                                   ^X K   Delete buffer
+ ^X ^L   Lower case region
+ ^X ^M   Delete Mode               ^X M   Add a mode
+ ^X ^N   Move window down          ^X N   Rename current filename
+ ^X ^O   Delete blank lines        ^X O   Move to the next window
+ ^X ^P   Move window up            ^X P   Move to the previous window
+ ^X ^R   Get a file from disk      ^X R   Incremental reverse search
+ ^X ^S   Save current file         ^X S   Incremental forward search
+ ^X ^U   Upper case region
+ ^X ^V   View file
+ ^X ^W   Write a file to disk      ^X W   resize Window
+ ^X ^X   Swap "." and mark         ^X X   Use next buffer
+ ^X ^Z   Shrink window             ^X Z   Enlarge display window
+
+Only under PCDOS:
+ <ALT>-S Hunt forward        SHIFT <F1> - <F10>
+ <ALT>-R Hunt backward           Execute macroes 1 - 10
+
+Unbound commands:
+=================
+describe-bindings	pull the list of current bindings into a window
+clear-message-line      clears the message line (for in macroes)
+execute-buffer		execute a buffer od command lines
+execute-command-line	execute a command line (n <command> <args>)
+execute-file		execute a file of command lines
+execute-named-command	execute a command by name (w/command completion)
+execute-macro-[1-20]	execute macroes 1 thru 20
+hunt-forward		find next occurance of search string
+hunt-backward		find last occurance of search string
+
+Usable Modes
+============
+WRAP     Lines going past right margin "wrap" to a new line
+VIEW     Read-Only mode where no modifications are allowed
+CMODE    Change behavior of some commands to work with C better
+EXACT    Exact case matching on search strings
+OVER     Overwrite typed characters instead of inserting them
+MAGIC    Use regular expresion matching in searches [NOT READY YET]
+
+WHITE/CYAN/MAGENTA/YELLOW/BLUE/RED/GREEN/BLACK	Sets foreground color
+white/cyan/magenta/yellow/blue/red/green/black	Sets background color

Added: clients/emacs/emacs.rc
===================================================================
--- clients/emacs/emacs.rc	                        (rev 0)
+++ clients/emacs/emacs.rc	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,97 @@
+;	EMACS.RC:	Startup file for MicroEMACS 3.4
+;
+;			This file is executed everytime the
+;			editor is entered
+
+;	***** Rebind the Function key group
+
+bind-to-key execute-macro-11		FN;
+bind-to-key execute-named-command	FN<
+bind-to-key hunt-forward		FN=
+bind-to-key hunt-backward		FN>
+bind-to-key next-window			FN?
+bind-to-key execute-macro		FN@
+bind-to-key find-file			FNA
+bind-to-key view-file			FNB
+bind-to-key save-file			FNC
+bind-to-key exit-emacs			FND
+
+;	set screen colors
+add-global-mode "blue"
+
+;	Enter Help
+11 store-macro
+	help
+	8 resize-window
+	bind-to-key execute-macro-12 FNI
+	bind-to-key execute-macro-13 FNQ
+	bind-to-key execute-macro-14 FN;
+	add-mode "red"
+	begining-of-file
+	2 forward-character
+	clear-message-line
+[end]
+
+;	bring up the function key window
+1 store-macro
+	2 split-current-window
+	select-buffer "Function Keys"
+	add-mode "red"
+	begining-of-file
+	2 resize-window
+	insert-string "F1 help on/off F2  exec cmd    F3 hunt       F4  back hunt     F5  next window"
+	newline
+	insert-string "F6 exec macro  F7  find file   F8 view file  F9  save file     F10 exit emacs"
+	begining-of-file
+	unmark-buffer
+	bind-to-key execute-macro-15 FNT
+	next-window
+[end]
+
+; reselect function key window
+15 store-macro
+	2 split-current-window
+	select-buffer "Function Keys"
+	begining-of-file
+	2 resize-window
+	add-mode "red"
+	next-window
+[end]
+
+;	consult file
+3 store-macro
+	2 split-current-window
+	previous-window
+	view-file "@File to Consult: "
+	8 resize-window
+	add-mode "green"
+	add-mode "Black"
+	next-window
+[end]
+
+;	Exit Help
+14 store-macro
+	bind-to-key previous-page FNI
+	bind-to-key next-page FNQ
+	bind-to-key execute-macro-11 FN;
+	delete-window
+	clear-message-line
+[end]
+
+;	last help page
+12 store-macro
+	begining-of-line
+	search-reverse "=>"
+	1 redraw-display
+[end]
+
+;	next help page
+13 store-macro
+	begining-of-line
+	2 forward-character
+	search-forward "=>"
+	1 redraw-display
+[end]
+
+execute-macro-1
+

Added: clients/emacs/emacs.tut
===================================================================
--- clients/emacs/emacs.tut	                        (rev 0)
+++ clients/emacs/emacs.tut	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,636 @@
+You are looking at the MICRO-EMACS tutorial.  Comments on this document
+may be refered to Dana Hoggatt or Dan Lawrance.
+
+EMACS commands generally involve the CONTROL key (sometimes labelled CTRL or 
+CTL) or the META key (generally labelled ESCAPE).  Rather than write out META 
+or CONTROL each time we want you to prefix a character, we'll use the following
+abbreviations:
+
+   ^<chr>   means hold the CONTROL key while typing the character <chr>
+            Thus, ^F would be: hold the CONTROL key and type F.
+
+   ESC-<chr>  means type the ESCAPE key and release it, then type the 
+              character <chr>.  The <chr> can be upper or lower case 
+              and it will have the same meaning.
+
+Important note: if you must exit at some point, type ^X ^C.  
+
+This tutorial attempts to help you "learn by doing".  The characters ">>" 
+at the left margin of your screen indicate directions for you to try using 
+a command.  For instance:
+
+>>  Now type ^V (View next screen) to move to the next screen.
+    (go ahead, do it by depressing the control key and V together).
+
+From now on, you'll be expected to type ^V whenever you finish reading the 
+current screen.
+
+Note that there is an overlap when going from screen to screen; this
+provides some continuity when moving through the file.
+
+The first thing that you need to know is how to move around from place to 
+place in the file.  You already know how to move forward a screen, with ^V.  
+To move backwards a screen, type ^Z. (depress the CTRL key and type Z).
+
+>>  Try typing ^Z and then ^V to move back and forth a few times.
+
+
+SUMMARY
+-------
+
+The following commands are useful for viewing screenfuls:
+
+     ^V      Move forward one screenful
+     ^Z      Move backward one screenful
+     <ESC>^L Clear screen and redisplay everything
+             putting the text near the cursor at the center.
+
+>> find the cursor and remember what text is near it.
+   Then type a <ESC>^L.
+   Find the cursor again and see what text is near it now.
+
+
+BASIC CURSOR CONTROL
+--------------------
+
+Getting from screenful to screenful is useful, but how do you reposition 
+yourself within a given screen to a specific place?  There are several ways 
+you can do this.  One way (not the best, but the most basic) is to use the 
+commands previous, backward, forward and next.  As you can imagine these 
+commands (which are given to EMACS as ^P, ^B, ^F, and ^N  respectively) move 
+the cursor from where it currently is to a new place in the given direction.  
+Here, in a more graphical form are the commands:
+ 
+                          Previous line, ^P
+                                  :
+                                  :
+   Backward, ^B .... Current cursor position .... Forward, ^F
+                                  :
+                                  :
+                          Next line, ^N
+
+You'll probably find it easy to think of these by letter.  P for
+previous, N for next, B for backward and F for forward.  These are
+the basic cursor positioning commands and you'll be using them ALL
+the time so it would be of great benefit if you learn them now.
+
+>> Do a few ^N's to bring the cursor down to this line.
+
+>> Move into the line with ^F's and then up with several ^P's.
+   See what ^P does when the cursor is in the middle of the line.
+
+Lines are separated by a single Linefeed character, which is what
+Unix calls a Newline.
+
+>> Try to ^B at the beginning of a line.  Do a few more ^B's.
+   Then do ^F's back to the end of the line and beyond.
+
+When you go off the top or bottom of the screen, the text beyond
+the edge is shifted onto the screen so that your instructions can
+be carried out while keeping the cursor on the screen.
+
+>> Try to move the cursor off the bottom of the screen with ^N and
+   see what happens.
+
+If moving by characters is too slow, you can move by words.  ESC-F
+(Meta-F) moves forward a word and ESC-B moves back a word.
+
+>> Type a few ESC-F's and ESC-B's.  Intersperse them with ^F's and ^B's.
+
+Notice the parallel between ^F and ^B on the one hand, and ESC-F and ESC-B on 
+the other hand.  Very often Meta characters are used for operations related 
+to English text whereas Control characters operate on the basic textual units 
+that are independent of what you are editing (characters, lines, etc).  There 
+is a similar parallel between lines and sentences: ^A and ^E move to the 
+beginning or end of a line. and ESC-A and ESC-E move to the beginning or end 
+of a sentence.
+
+###  Note:  ESC-A and ESC-E are not implimented yet (DLH - 1/22/86)  ###
+
+>> Try a couple of ^A's, and then a couple of ^E's.
+   Try a couple of ESC-A's, and then a couple of ESC-E's.
+
+See how repeated ^A's do nothing, but repeated ESC-A's
+keep moving farther.  Do you think that this is right?
+
+Two other simple cursor motion commands are ESC-< (Meta Less-than),
+which moves to the beginning of the file, and ESC-> (Meta Greater-than),
+which moves to the end of the file.  You probably don't need to try
+them, since finding this spot again will be boring.  If you need the
+shift key to type a "<", then you must also use the shift key to type
+ESC-<.  Otherwise, you would be typing ESC-, .
+
+The location of the cursor within the text is also called "point".  To 
+paraphrase, the cursor shows on the screen where point is located in the text.
+
+Here is a summary of simple moving operations including
+the word and sentence moving commands:
+
+     ^F        Move forward a character
+     ^B        Move backward a character
+
+     ESC-F     Move forward a word
+     ESC-B     Move backward a word
+
+     ^N        Move to next line
+     ^P        Move to previous line
+
+     ESC-N     Move to next paragraph
+     ESC-P     Move to previous paragraph 
+
+     ^A        Move to beginning of line
+     ^E        Move to end of line
+
+     ESC-A     Move back to beginning of sentence  (not functional)
+     ESC-E     Move forward to end of sentence     (not functional)
+
+     ESC-<     Go to beginning of file
+     ESC->     Go to end of file
+
+>> Try all of these commands now a few times for practice.
+   Since the last two will take you away from this screen,
+   you can come back here with ^Z's and ^V's.  These are
+   the most often used commands.
+
+Like all other commands in EMACS, these commands can be given
+arguments which cause them to be executed repeatedly.  The way you
+give a command a repeat count is by typing META and then the digits
+before you type the command.  (Remember META is ususally called ESCAPE)
+
+For instance, META 8 ^F moves forward eight characters.
+
+>> Try giving a suitable argument to ^N or ^P to come as close
+   as you can to this line in one jump.
+
+This also applies to the screen moving commands, ^V and ^Z.  When
+given an argument, they scroll the screen up or down by that many
+screenfuls.  As a special case, typing just ^U is equivalent to ESC-4.
+
+>> Try typing ESC-3 ^V now.
+
+If you would like to scroll it down, you can give an argument to ^Z.
+
+
+QUITTING FROM COMMANDS
+----------------------
+
+The character in EMACS used to quit out of all commands which request
+input is ^G.  For example, you can use ^G to discard a numeric argument
+or the beginning of a command that you don't want to finish.
+
+>> Type ESC-100 to make a numeric arg of 100, then type ^G.
+   Now type ^F.  How many characters does it move?
+   If you have typed an <ESC> by mistake, you can get rid of it
+   with a ^G.
+
+
+IBM CURSOR KEYS
+---------------
+
+On the IBM-PC version, the cursor keypad has been bound to some of the
+more useful screen movement commands. The mappings are as follows:
+
+     Cursor-Right    ^F        Move forward a character
+     Cursor-Left     ^B        Move backward a character
+
+     ^Cursor-Right   ESC-F     Move forward a word
+     ^Cursor-Left    ESC-B     Move backward a word
+
+     Cursor-Down     ^N        Move to next line
+     Cursor-UP       ^P        Move to previous line
+
+     Pg-Dn           ^V        Move to next screen
+     Pg-Up           ^Z        Move to previous screen
+
+     Home            ESC-<     Go to beginning of file
+     End             ESC->     Go to end of file
+
+     Insert          ^O        Open up a new line
+     Delete          ^K        Kill to end of line
+
+Usage of the ^O and ^K commands is described later in the tutorial. A
+map of the key layout looks something like this:
+
+              -------------------------------------------------
+              | 7             | 8             | 9             |
+              | Home          | ^             | Pg Up         |
+              |               | |             |               |
+              |     ESC-<     |      ^P       |     ^Z        |
+              -------------------------------------------------
+              | 4             | 5             | 6             |
+              | <--           |               | -->           |
+              |               |               |               |
+              |      ^B       |               |      ^F       |
+              -------------------------------------------------
+              | 1             | 2             | 3             |
+              | End           | |             | Pg Dn         |
+              |               | v             |               |
+              |     ESC->     |      ^N       |      ^V       |
+  -------------------------------------------------------------
+  | 0                         | .                             |
+  | Insert                    | Delete                        |
+  |                           |                               |
+  |             ^O            |             ^K                |
+  -------------------------------------------------------------
+
+>> if you have an IBM-PC, practice using the cursor keypad.
+
+
+
+ERRORS
+------
+
+Sometimes you may do something which EMACS doesn't allow. If it is
+something simple, such as typing a control key sequence which is not
+associated with any command, EMACS will just beep at you. Otherwise,
+EMACS will also display an informative error message at the bottom of
+the screen.
+
+Some versions of EMACS do not have all the features described in this
+tutorial implemented yet.  If you come across such an unimplemented
+feature, you may get an error message when you try to use it.  Just
+type a space and proceed on to the next section of the tutorial.
+
+
+INSERTING AND DELETING
+----------------------
+
+If you want to type text, just do it.  Characters which you can see, such 
+as A, 7, *, etc. are taken by EMACS as text and are immediately inserted.  
+Type <Return> (the carriage-return key) to insert a line separator.
+
+You can delete the last character you typed by typing either <Delete> or ^H.  
+On some keyboards, there is a dedicated key for creating a ^H.  If so, it is 
+usually labeled as either "Backspace" or "<--".  <Delete> is a key on the 
+keyboard, which may be labeled "Rubout" instead of "Delete" on some terminals.
+More generally, <Delete> deletes the character immediately before the current 
+cursor position.
+
+>> Do this now, type a few characters and then delete them by typing
+   <Delete> a few times.  Don't worry about this file being changed;
+   you won't affect the master tutorial.  This is just a copy of it.
+
+>> Now start typing text until you reach the right margin, and keep
+   typing.  When a line of text gets too big for one line on the
+   screen, the line of text is "continued" off the edge of the screen
+   The dollar sign at the right margin indicates a line which has
+   been continued.  EMACS scrolls the line over so you can see what you 
+   are editing.  The '$' at the left or right edge of the screen indicates 
+   that the current line extends off in that direction.  
+
+>> The following line actually goes off the edge.  Trying typing enough ^F's
+   so that you move off the right hand end of this line.  This is a long line of text.  Note the "$"s at each edge.  Keep typing ^F's and watch where EMACS decides to scroll the line.  Now, type ^B's until EMACS decides to scroll the line again.
+
+This is one of those gizmos which is easier to understand by playing with it 
+than by reading about it.
+
+>> Use ^D's or <Delete>s to delete the text until the text line fits on 
+   one screen line again.  The continuation "$" will go away.
+
+>> Move the cursor to the beginning of a line and type <Delete>.  This
+   deletes the line separator before the line and merges the line onto
+   the previous line.  The resulting line may be too long to fit, in
+   which case it has a continuation indication.
+
+>> Type <Return> to insert the separator again.
+
+Internally, EMACS will allow you to have lines of nearly any length, limited 
+only by the amount of memory available.  Externally, however, EMACS can only 
+read or write lines, to or from a file, which are less than or equal to 255 
+characters.
+
+Remember that most EMACS commands can be given a repeat count;  Note
+that this includes characters which insert themselves.
+
+>>  Try that now -- type META 8 * and see what happens.
+
+If you want to create a blank line in between two lines, move to the
+second of the two lines and type ^O.
+
+>>  Try moving to a line and typing ^O now.
+
+You've now learned the most basic way of typing something in
+EMACS and correcting errors.  You can delete by words or lines
+as well.  Here is a summary of the delete operations:
+
+     <Delete>      delete the character just before the cursor
+     ^H            delete the character just before the cursor
+     ^D            delete the next character after the cursor
+
+     ESC-<Delete>  kill the word immediately before the cursor
+     ESC-^H        kill the word immediately before the cursor
+     ESC-D         kill the next word after the cursor
+
+     ^K            kill from the cursor position to end of line
+
+Notice that <Delete> and ^D vs ESC-<Delete> and ESC-D extend the parallel
+started by ^F and ESC-F (well, <Delete> isn't really a control
+character, but let's not worry about that).
+
+Now suppose you kill something, and then you decide that you want to get 
+it back?  Well, whenever you kill something bigger than a character, EMACS 
+saves it for you.  To yank it back, use ^Y.  Note that you don't have to 
+be in the same place to do ^Y; This is a good way to move text around.  
+Also note that the difference between "Killing" and "Deleting" something 
+is that "Killed" things can be yanked back, and "Deleted" things cannot.  
+Generally, the commands that can destroy a lot of text save it, while the 
+ones that attack only one character, or nothing but blank lines and spaces, 
+do not save.
+
+For instance, type ^N a couple times to postion the cursor
+at some line on this screen.
+
+>> Do this now, move the cursor and kill that line with ^K.
+
+Note that a single ^K kills the contents of the line, and a second
+^K kills the line itself, and make all the other lines move up.  If
+you give ^K a repeat count, it kills that many lines AND their contents.
+
+The text that has just disappeared is saved so that you can
+retrieve it.  To retrieve the last killed text and put it where
+the cursor currently is, type ^Y.
+
+>> Try it; type ^Y to yank the text back.
+
+Think of ^Y as if you were yanking something back that someone took away 
+from you.  Notice that if you do several ^K's in a row the text that is 
+killed is all saved together so that one ^Y will yank all of the lines.
+
+>> Do this now, type ^K several times.
+
+Now to retrieve that killed text:
+
+>> Type ^Y.  Then move the cursor down a few lines and type ^Y
+   again.  You now see how to copy some text.
+
+What do you do if you have some text you want to yank back, and then
+you kill something else?  ^Y would yank the more recent kill.
+
+>> Kill a line, move around, kill another line.
+   Then do ^Y to get back the second killed line.
+
+
+FILES
+-----
+
+In order to make the text you edit permanent, you must put it in a file.
+Otherwise, it will go away when you leave EMACS.  While you are editing a
+file in EMACS, your changes are actually being made to a private
+"scratch" copy of the file.  However, the changes still don't become
+permanent until you "save" the file.  This is so you can have control to
+avoid leaving a half-changed file around when you don't want to.
+
+If you look near the botton of the screen you will see a line that
+looks like this:
+
+    =* MicroEMACS 3.1 (NORMAL) == emacs.tut == File: emacs.tut ==========
+                                               ---------------
+
+Note that EMACS indicates the name of the file you are currently editing.
+This is the name of your own temporary copy of the text of the EMACS
+tutorial; the file you are now editing.  Whatever file you edit, that
+file's name will appear in that precise spot.
+
+The commands for finding and saving files are unlike the other commands you
+have learned in that they consist of two characters. They both start with the
+character Control-X.  There is a whole series of commands that start with
+Control-X; many of them have to do with files, buffers, and related things,
+and all of them consist of Control-X followed by some other character.  As
+with ESC, the character is interpreted the same regardless of case.
+
+Another thing about the command for finding a file is that you have to say
+what file name you want.  We say the command "reads an argument from the
+terminal" (in this case, the argument is the name of the file).  After you
+type the command
+
+     ^X ^F   Find a file
+
+EMACS will ask you for the file name.  You should end the name with
+the Return key.  After this command, you will see the contents of the
+file in your EMACS.  You can edit the contents.  When you wish to make
+the changes permanent, issue the command
+
+     ^X ^S   Save the file
+
+A new version of the file will be created.  When the operation is
+finished, EMACS prints the name and number of lines saved.
+
+If you forget to save and edit a different file and then decide to quit,
+EMACS will remind you that you made changes that have not been save and
+then ask you whether you really want to quit.  (If you don't save them,
+they will be thrown away.  That might be what you want!)  You should
+answer with a "N" to save them or a "Y" to throw the changes away.
+
+To make a new file, just edit it "as if" it already existed.  Then start 
+typing in the text.  When you ask to "save" the file, EMACS will really 
+create the file with the text that you have inserted.  From then on, you 
+can consider yourself to be editing an already existing file.
+
+It is not easy for you to try out editing a file and continue with the 
+tutorial.  But you can always come back into the tutorial by starting it 
+over and skipping forward.  So, when you feel ready, you should try editing 
+a file named "FOO", putting some text in it, and saving it; then exit from 
+EMACS and look at the file to be sure that it worked.
+
+
+EXTENDING THE COMMAND SET
+-------------------------
+
+###   The mechanisms for extending the command set and setting   ###
+###   the key bindings has not been installed yet.  Skip forward ###
+###   to the next section (TEXT REPLACEMENT).    DLH  (1/22/86)  ###
+
+There are many, many more EMACS commands than could possibly be put
+on all the control and meta characters.  EMACS gets around this with
+the X (eXtend) command.  This comes in two flavors:
+
+     ^X       Character eXtend.  Followed by one character.
+     ESC-X    Named command eXtend.  Followed by a long name.
+
+These are commands that are generally useful but used less than the commands 
+you have already learned about.  You have already seen two of them: the file 
+commands ^X ^F to Find and ^X ^S to Save.  Another example is the command to 
+tell EMACS that you'd like to stop editing.  The command to do this is ^X ^C.
+
+There are many ^X commands.  The ones you need immediately are:
+
+     ^X ^F     Find file.
+     ^X ^S     Save file.
+     ^X ^C     Quit EMACS.  This does not save your files auto-
+                 matically, though if your files have been modi-
+                 fied, EMACS asks if you really want to quit.  The
+                 standard way to save and exit is ^X ^S ^X ^C.
+
+Named eXtended commands are commands which are used even less
+frequently, or commands which are used only in certain modes. These
+commands are usually called "functions". An example is the function
+"apropos", which prompts for a keyword and then gives the names of all
+the functions that apropos for that keyword. When you type ESC-X, EMACS
+prompts you at the bottom of the screen with ":" and you should type the
+name of the function you wish to call; in this case, "apropos". Just
+type "apr<Space>" and EMACS will complete the name. EMACS will ask you
+for a keyword or phrase and you type the string that you want ask about.
+
+>> Try typing ESC-X, followed by "apropos" or "apr" and then Return.
+   Then try typing "file" followed by a Return.
+
+
+TEXT REPLACEMENT
+---- -----------
+
+>> Move the cursor to the blank line two lines below this one.
+   Then type ESC-r changed<Escape>altered<Escape>.
+
+   Notice how this line has changed: you've replaced
+   the word c-h-a-n-g-e-d with "altered" wherever it occurs
+   after the cursor.
+
+The more customary command for replacing strings is the interactive
+command query-replace-search, which has several options. In essence, it
+shows each occurance of the first string and asks you if you want to
+replace it or not. You can also choose to edit around the string, or go
+on and replace all occurances without asking further. It is described in
+detail in the EMACS manual.  Also, typing a '?' when it asks you if you
+wish to replace will list out the various options.
+
+
+MODE LINE
+---------
+
+The bottom line of the screen is known as the communications line.  This
+is where EMACS interactively communicates with you.  You have already
+seen how emacs prompts you for information (like when searching).  EMACS
+can also report things to you as well.
+
+>> Type ^X = and see what you get in the communications line.
+
+The line immediately above the communications line is called the MODE
+LINE. The mode line says something like
+
+    =* MicroEMACS 3.1 (NORMAL) == emacs.tut == File: emacs.tut ==========
+
+This is a very useful "information" line.
+
+The star means that you have made changes to the text.  Right after
+you visit or save a file, there is no star.
+
+The buffername is the name EMACS gave to the buffer, and it is usually
+related to the filename. You already know what the filename means -- it
+is the file you have edited.
+
+The part of the mode line inside the parentheses is to tell you what
+modes you are in. The default mode is NORMAL which is what you are in
+now. It is an example of a "major mode". There are several major modes
+in EMACS for editing different languages and text, such as C mode, Text
+mode, etc. At any time one and only one major mode is active, and its
+name can always be found in the mode line just where "NORMAL" is now.
+
+Each major mode makes a few commands behave differently. For example,
+there are commands for creating comments in a program, and since each
+programming language has a different idea of what a should look like,
+each major mode has to insert comments differently. Each major mode is
+controlled by a EMACS variable which can be manipulated and queried with
+the "set" and "print" extended commands.
+
+Major modes are called major because there are also minor modes. They
+are called minor because they aren't alternatives to the major modes,
+just minor modifications of them. Each minor mode can be turned on or
+off by itself, regardless of what major mode you are in, and regardless
+of the other minor modes. So you can use no minor modes, or one minor
+mode, or any combination of several minor modes.
+
+One minor mode which is very useful, especially for editing English
+text, is WRAP mode. When this mode is on, EMACS breaks the line in
+between words automatically whenever the line gets too long. You can
+turn this mode on by doing ^X M wrap <return>. When the mode is on, you
+can turn it off by doing ^X ^M wrap <Return>.
+
+>> Type "^X ^M wrap <Return>" now.  Then insert a line of "asdf " over 
+   again until you see it divide into two lines.  You must put in spaces 
+   between them because Auto Fill breaks lines only at spaces.  Note that 
+   "WRAP" appears in the mode line, indicating that you are in WRAP mode.
+
+The margin is usually set at 72 characters, but it can be shanged.  
+Simply type ESC nn ^X F, where "nn" is the column number for the right 
+hand margin.  
+
+
+SEARCHING
+---------
+
+EMACS can do searches for strings (these are groups of contiguous
+characters or words) either forward through the file or backward
+through it.  
+
+>> Now type ^S to start a search.  Type the word 'cursor', then ESCAPE.
+
+>> Type ^S ESCAPE to find the next occurrence of "cursor".
+
+The ^S starts a search that looks for any occurrence of the search
+string AFTER the current cursor position.  But what if you want to
+search for something earlier in the text?  To do this one should
+type ^R for Reverse search.  Everything that applies to ^S applies
+to ^R except that the direction of the search is reversed.
+
+
+GETTING MORE HELP
+-----------------
+
+In this tutorial we have tried to supply just enough information to
+get you started using EMACS.  There is so much available in EMACS that
+it would be impossible to explain it all here.  However, you may want
+to learn more about EMACS since it has numerous desirable features
+that you don't know about yet.
+
+###   The on-line help features have not been implimented yet.  DLH   ###
+
+The most basic HELP feature is the describe-key function which is
+available by typing ^X ? and then a command character. EMACS prints one
+line line on the bottom of the screen tell what function is bound to
+that key.
+
+The describe-command function ESC-? will prompt for the name of a function
+and print out the section from the manual about that command. When you
+are finished reading it, type a Space or a ^G (quit) to bring your text
+back on the screen.
+
+>> Type ^X ? Control-P.  The message at the bottom of the screen should
+   be something like "^P is bound to previous-line".
+
+Multi-character commands such as ^X ^Z and <ESC>V are also allowed
+after ^X ?.
+
+Now lets get more information about the previous-line command.
+
+>> Type ESC-? previous-line.  When you are finished reading the
+   output, type a Space.
+
+The "name of the function" is important for people who are customizing
+EMACS.  It is what appears in the EMACS CHART as the documentation for
+the command character.
+
+
+CONCLUSION
+----------
+
+Remember, to exit use ^X ^C.
+
+This tutorial is meant to be understandable to all new users, so if
+you found something unclear, don't sit and blame yourself - complain!
+
+You'll probably find that if you use EMACS for a few days you won't
+be able to give it up.  Initially it may give you trouble.  But remember
+that this is the case with any editor, especially one that can do many,
+many things.  And EMACS can do practically everything.
+
+
+Acknowledgements
+----------------
+
+This is a modified version of the "JOVE Tutorial" by Jonathan Payne 
+(19 January 86). That document was in turn a modified version of the
+tutorial "Teach-Emacs" from MIT as modified by Steve Zimmerman at
+CCA-UNIX (31 October 85).
+
+This document was last updated on 2-7-86 by Dana Hoggatt.
+

Added: clients/emacs/emacs2.mss
===================================================================
--- clients/emacs/emacs2.mss	                        (rev 0)
+++ clients/emacs/emacs2.mss	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,790 @@
+
+ at style(indent 8 chars, spacing 1 lines)
+ at begin(center)
+ at b(MicroEMACS 3.7)
+
+ at i(Screen Editor)
+written by Dave Conroy
+and Daniel Lawrence
+ at end(center)
+
+
+ at begin(quotation)
+	This software is in the public domain and may be freely copied
+and used by one and all. We would ask that if it is incorporated into
+other software that proper credit be given to its authors.
+ at end(quotation)
+
+ at flushleft(@b[Introduction])
+
+	MicroEMACS 3.7 is a screen editor for programming and word
+processing.  It is availible for the IBM-PC and its clones, UNIX V7,
+UNIX BSD4.2, UNIX V5, VMS, the HP150, the Wang-PC and the Commodore
+AMIGA.  It requires between 40 to 70K of space to run on these machines. 
+Some of its capabilities include:
+
+ at begin(verbatim)
+	Multiple windows on screen at one time
+
+	Multiple files in the editor at once
+
+	Limited on screen formating of text
+
+	User changable command set
+
+	User written editing macroes
+
+	Compatability across all supported environments
+ at end(verbatim)
+
+	This manual is designed as a reference manual. All the commands
+in MicroEMACS are listed, in functional groups, along with detailed
+descriptions of what each commands does.
+ at newpage
+ at flushleft(@b[How to Start])
+
+	MicroEMACS is invoked from the operating system command level
+with a command of the form:
+
+ at begin(verbatim)
+	emacs {options} <filelist>
+
+where options may be:
+
+-v		all the following files are in view mode (read only)
+-e		all the following files can be edited
+-g<n>		go directly to line <n> of the first file
+-s<string>	go to the end of the first occurance of <string>
+		in the first file
+
+@@<sfile>	execute macro file <sfile> instead of the
+		standard startup file
+
+and <filelist> is a list of files to be edited.
+
+for example:
+
+	emacs @@start1.cmd -g56 test.c -v head.h def.h
+
+ at end(verbatim)
+
+	means to first execute macro file start1.cmd instead of the
+standard startup file, emacs.rc and then read in test.c, position the
+cursor to line 56, and be ready to read in files head.h and def.h in
+view (read-only) mode.  In the simple case, MicroEMACS is usually run by
+typing:
+
+ at flushleft(	emacs <file>)
+
+	where <file> is the name of the file to be edited.
+ at newpage
+ at flushleft(@b[How to type in commands])
+
+	Most commands in MicroEMACS are a single keystroke, or a
+keystroke preceded by a command prefix.  Control commands appear in the
+documentation like ^A which means to depress the <Ctrl> key and while
+holding down it down, type the A character.  Meta-commands appear as
+M-A which means to strike the Meta key (<ESC> on most computers) and
+then after realeasing it, type the A character.  Control-X commands
+usually appear as ^X-A which means to hold down the control key and type
+the X character then type the A character.  Both meta commands and
+control-x commands can be control characters as well, for example,
+^X-^O (the delete-blank-lines command) means to hold down <Ctrl>, type
+X, keep holding down <Ctrl> and type the O character.
+
+	Many commands in MicroEMACS can be executed a number of times.
+In order to make one command repeat many times, type Meta (<ESC>)
+followed by a number, and then the command. for example:
+
+ at verbatim(	M 12 ^K)
+
+	will delete 12 lines starting at the cursor and going down. 
+Sometimes, the repeat count is used as an argument to the command as in
+the set-tab command where the repeat count is used to set the spacing of
+the tab stops. 
+
+ at flushleft(@b[The Command List])
+
+	The following is a list of all the commands in MicroEMACS. 
+Listed is the command name, the default (normal) keystrokes used to
+invoke it, and alternative keys for the IBM-PC, and a description of
+what the command does.
+
+ at begin(verbatim)
+ at b[(1) MOVING THE CURSOR]
+
+ at i(previous-page)	^Z	<Pg Up>
+
+	Move one screen towards the begining of the file.
+
+ at i(next-page)		^V	<Pg Dn>
+
+	Move one screen towards the end of the file.
+
+ at i(begining-of-file)	M-<	<Home>
+
+	Place the cursor at the begining of the file.
+
+ at i(end-of-file)		M->	<End>
+
+	Place the cursor at the end of the file.
+
+ at i(forward-character)	^F	(6 on the keypad)
+
+	Move the cursor one character to the right.  Go down to
+the begining of the next line if the cursor was already at the
+end of the current line. 
+
+ at i(backward-character)	^B	(4 on the keypad)
+
+	Move the cursor one character to the left.  Go to the
+end of the previous line if the cursor was at the begining of
+the current line. 
+
+ at i(next-word)		M-F	(^6 on the keypad)
+
+	Place the cursor at the begining of the next word.
+
+ at i(previous-word)	M-B	(^4 on the keypad)
+
+	Place the cursor at the begining of the previous word.
+
+ at i(begining-of-line)	^A
+
+	Move cursor to the begining of the current line.
+
+ at i(end-of-line)		^E
+
+	Move the cursor to the end of the current line.
+
+ at i(next-line)		^N	(2 on the keypad)
+
+	Move the cursor down one line.
+
+ at i(previous-line)	^P	(8 on the keypad)
+
+	Move the cursor up one line.
+
+ at i(goto-line)		M-G
+
+	Goto a specific line in the file. IE    M 65 M-G    would
+put the cursor on the 65th line of the current buffer.
+
+ at i(next-paragraph)	M-N
+
+	Put the cursor at the first end of paragraph after the cursor.
+
+ at i(previous-paragraph)	M-P
+
+	Put the cursor at the first begining of paragraph before the
+cursor.
+
+ at b[(2) DELETING & INSERTING]
+
+ at i(delete-previous-character)	^H	<--
+
+	Delete the character immedietly to the left of the
+cursor.  If the cursor is at the begining of a line, this will
+join the current line on the end of the previous one. 
+
+ at i(delete-next-character)	^D	<Del>
+
+	Delete the character the cursor is on.  If the cursor is
+at the end of a line, the next line is put at the end of the
+current one. 
+
+ at i(delete-previous word)	M-^H	M- <--
+
+	Delete the word before the cursor.
+
+ at i(delete-next-word)		M-^D
+
+	Delete the word starting at the cursor.
+
+ at i(kill-to-end-of-line)
+
+	When used with no argument, this command deletes all
+text from the cursor to the end of a line.  When used on a blank
+line, it deletes the blank line.  When used with an argument, it
+deletes the specified number of lines. 
+
+ at i(insert-space)	^C	<Ins>
+
+	Insert a space before the character the cursor is on.
+
+ at i(newline)		<return>
+
+	Insert a newline into the text, move the cursor down to the
+begining of the next physical line, carrying any text that was after
+it with it.
+
+ at i(newline-and-indent)	^J
+
+	Insert a newline into the text, and indent the new line the
+same as the previous line.
+
+ at i(handle-tab)		^I	-->
+
+	With no argument, move the cursor to the begining of the
+next tab stop.  With an argument of zero, use real tab
+characters when tabbing.  With a non-zero argument, use spaces
+to tab every argument positions. 
+
+ at i(delete-blank-lines)	^X-^O
+
+	Delete all the blank lines before and after the current cursor
+position.
+
+ at i(kill-paragraph)	M-^W
+
+	Delete the paragraph that the cursor is currently in.
+
+ at i(kill-region)		^W
+
+	Delete all the characters from the cursor to the mark set with
+the set-mark command.
+
+ at i(copy-region)
+
+	Copy all the characters between the cursor and the mark
+set with the set-mark command into the kill buffer (so they can
+later be yanked elsewhere). 
+
+ at i(open-line)		^O
+
+	Insert a newline at the cursor, but do not move the cursor.
+
+ at b[(3) SEARCHING]
+
+ at i(search-forward)	^S
+
+	Seearch for a string from the current cursor position to
+the end of the file.  The string is typed on on the bottom line of
+the screen, and terminated with the <ESC> key. Special characters
+can be typed in by preceeding them with a ^Q. A single ^Q
+indicates a null string.  On successive searches, hitting <ESC>
+alone causes the last search string to be reused.
+
+ at i(search-reverse)	^R
+
+	This command searches backwards in the file. In all other ways
+it is like search-forward.
+
+ at i(incremental-search)	^X-S
+
+	This command is similar to forward-search, but it processes the
+search as each character of the input string is typed in. This allows
+the user to only use as many keystrokes as are needed to uniquely
+specify the string being searched. Several control characters are active
+while isearching:
+
+	^S or ^X	Skip to the next occurence of the current string
+	^R		skip to the last occurence of the current string
+	^H		back up to the last match (posibly deleting
+			the last character on the search string)
+	^G		abort the search, return to start
+	<ESC>		end the search, stay here
+
+ at i(reverse-incremental-search)	^X-R
+
+	This command is the same as incremental-search, but it starts in
+the reverse direction.
+
+ at i(hunt-forward)	unbound		(<ALT>S on the IBM PC)
+
+	This command repeats the last search with the last search string
+
+ at i(hunt-backward)	unbound		(<ALT>R on the IBM PC)
+
+	THe last search string is looked for starting at the cursor and
+going backwards.
+
+ at b[(4) REPLACING]
+
+ at i(replace-string)	M-R
+
+	This command allows you to replace all occurences of one string
+with another string. The replacement starts at the current location of
+the cursor and goes to the end of the current buffer. A numeric argument
+will limit the number of strings replaced.
+
+ at i(query-replace-string)	M-^R
+
+	Like the replace-string command, this command will replace one
+string with another. However, it allows you to step through each string
+and ask you if you wish to make the replacement. When the computer asks
+if you wish to make the replacement, the following answers are allowed:
+
+	Y	Make the replacement and continue on to the next string
+	N	Don't make the replacement, then continue
+	!	Replace the rest of the strings without asking
+	^G	Stop the command
+	.	Go back to place the command started
+	?	get a list of options
+
+
+ at b[(5) CAPITALIZING & TRANSPOSING]
+
+ at i(case-word-upper)	M-U
+
+	Change the following word into upper case.
+
+ at i(case-word-capitalize)	M-C
+
+	Capitolize the following word.
+
+ at i(case-word-lower)	M-L
+
+	Change the following word to lower case.
+
+ at i(case-region-upper)	^X-^U
+
+	Change all the alphabetic characters in a marked region to upper
+case.
+
+ at i(case-region-lower)	^X-^L
+
+	Change all the alphabetic characters in a marked region to lower
+case.
+
+ at i(transpose-characters)	^T
+
+	Swap the last and second last characters behind the cursor.
+
+ at i(quote-character)	^Q
+
+	Insert the next typed character, ignoring the fact that it may
+be a command character.
+
+ at b[(6) REGIONS & THE KILL BUFFER]
+
+ at i(set-mark)	M-<SPACE>
+
+	This command is used to delimit the begining of a marked region. 
+Many commands are effective for a region of text.  A region is defined
+as the text between the mark and the current cursor position.  To delete
+a section of text, for example, one moves the cursor to the begining of
+the text to be deleted, issues the set-mark command by typing M-<SPACE>,
+moves the cursor to the end of the text to be deleted, and then deletes
+it by using the kill-region (^W) command.  Only one mark can be set in
+one window or one buffer at a time, and MicroEMACS will try to remember
+a mark set in an offscreen buffer when it is called back on screen. 
+
+ at i(exchange-point-and-mark)	^X-^X
+
+	This command moves the cursor to the current marked position in
+the current window and moves the mark to where the cursor was.  This is
+very usefull in finding where a mark was, or in returning to a position
+previously marked.
+
+ at b[(7) COPYING AND MOVING]
+
+ at i(kill-region)		^W
+
+	This command is used to copy the current region (as defined by
+the current mark and the cursor) into the kill buffer.
+
+ at i(yank)		^Y
+
+	This copies the contents of the kill buffer into the text at the
+current cursor position.  This does not clear the kill buffer, and thus
+may be used to make multiple copies of a section of text.
+
+ at i(copy-region)		M-W
+
+	This command copies the contents of the current region into the
+kill buffer without deleting it from the current buffer.
+
+ at b(8) MODES OF OPERATION]
+
+ at i(add-mode)		^X-M
+
+	Add a mode to the current buffer
+
+ at i(delete-mode)		^X-^M
+
+	Delete a mode from the current buffer
+
+ at i(add-global-mode)	M-M
+
+	Add a mode to the global modes which get inherited by any new
+buffers that are created while editing.
+
+ at i(delete-global-mode)	M-^M
+
+	Delete a mode from the global mode list.  This mode list is
+displayed as the first line in the output produced by the list-buffers
+command.
+
+ at b(		MODES)
+
+	Modes are assigned to all buffers that exist during an editing
+session.  These modes effect the way text is inserted, and the operation
+of some commands. Legal modes are:
+
+
+ at i(OVER)	Overwrite Mode
+
+	In this mode, typed characters replace existing characters
+rather than being inserted into existing lines.  Newlines still insert
+themselves, but all other characters will write over existing characters
+on the current line being edited.  This mode is very usefull for editing
+charts, figures, and tables.
+
+ at i(WRAP)	Word Wrap Mode
+
+	In this mode, when the cursor crosses the current fill column
+(which defaults to 72) it will, at the next wordbreak, automatically
+insert a newline, dragging the last word down with it.  This makes
+typing prose much easier since the newline (<RETURN>) only needs to be
+used between paragraphs.
+
+ at i(VIEW)	File Viewing Mode
+
+	In this mode, no commands which can change the text are allowed.
+
+ at i(CMODE)	C Program Editing Mode
+
+	This mode is for editing programs written in the 'C' programming
+language.  When the newline is used, the editor will attempt to place
+the cursor at the proper indentation level on the next line.  Close
+braces are automatically undented for the user, and also pre-processor
+commands are automatically set flush with the left margin.  When a close
+parenthesis or brace is typed, if the matching open is on screen, the
+cursor briefly moves to it, and then back. (Typing any key will abort
+this fence matching, executing the next command immediatly)
+
+ at i(EXACT)	Exact Case Matching on Searching MODE
+
+	Normally case is insignificant during the various search
+commands.  This forces all matching to take character case into account.
+
+ at i(MAGIC)	Regular expresion pattern matching Mode
+
+	This feature is not yet implimented.  While it may be set as a
+mode, it will have no effect at the moment.  When it is ready, it will
+cause all search commands to accept various pattern characters to allow
+regular exspression search and replaces.
+
+ at b[(10) ON-SCREEN FORMATTING]
+
+ at i(set-fill-column)	^X-F
+
+	Sets the column used by WRAP mode and the fill-paragraph command.
+
+ at i(handle-tab)		<TAB>
+
+	Given a numeric argument, the tab key resets the normal behavior
+of the tab key.  An argument of zero causes the tab key to generate
+hardware tabs (at each 8 columns).  A non-zero argument will cause the
+tab key to generate enough spaces to reach a culumn of a multiple of the
+argument given.  This also resets the spacing used while in CMODE.
+
+ at i(fill-paragraph)	M-Q
+
+	This takes all the text in the current paragraph (as defined by
+surrounding blank lines, or a leading indent) and attempt to fill it
+from the left margin to the current fill column.
+
+ at i(buffer-position)
+
+	This command reports on the current and total lines and
+characters of the current buffer.  It also gives the hexidecimal code of
+the character currently under the cursor.
+
+ at b[(11) MULTIPLE WINDOWS]
+
+ at i(split-current-window)	^X-2
+
+	If possible, this command splits the current window into two
+near equal windows, each displaying the buffer displayed by the original
+window. A numeric argument of 1 forces the upper window to be the new
+current window, and an argument of 2 forces the lower window to be the
+new current window.
+
+ at i(delete-window)		^X-0
+
+	this command attempts to delete the current window, retrieving
+the lines for use in the window above or below it.
+
+ at i(delete-other-windows)	^X-1
+
+	All other windows are deleted by this command.  The current
+window becomes the only window, using the entire availible screen.
+
+ at i(next-window)		^X-O
+
+	Make the next window down the current window.  With an argument,
+this makes the nth window from the top current.
+
+ at i(previous-window)	^X-P
+
+	Make the next window up the current window.  With an argument,
+this makes tghe nth window from the bottom the current window.
+
+ at i(scroll-next-down)	M-^V
+
+	Scroll the next window down a page.
+
+ at i(scroll-next-up)	M-^Z
+
+	Scroll the next window up a page.
+
+ at b[(12) CONTROLLING WINDOWS]
+
+ at i(grow-window)		^X-^
+
+	Enlarge the current window by the argument number of lines (1 by
+default).
+
+ at i(shrink-window)	^X-^Z
+
+	Shrink the current window by the argument number of lines (1 by
+default).
+
+ at i(resize-window)	^X-W
+
+	CHnage the size of the current window to the number of lines
+specified by the argument, if possible.
+
+ at i(move-window-down)	^X-^N
+
+	Move the window into the current buffer down by one line.
+
+ at i(move-window-up)	^X-^P
+
+	Move the window into the current buffer up by one line.
+
+ at i(redraw-display)	M-^L
+
+	Redraw the current window with the current line in the middle of
+the window, of with an argument, with the current line on the nth line
+of the current window.
+
+ at i(clear-and-redraw)	^L
+
+	Clear the screen and redraw the entire display.  Usefull on
+timesharing systems where messages and other things can garbage the display.
+
+ at b[(13) MULTIPLE BUFFERS]
+
+ at i(select-buffer)	^X-B
+
+	Switch to using another buffer in the current window.  MicroEMACS
+will prompt you for the name of the buffer to use.
+
+ at i(next-buffer)		^X-X
+
+	Switch to using the next buffer in the buffer list in the
+current window.
+
+ at i(name-buffer)		M-^N
+
+	Change the name of the current buffer.
+
+ at i(kill-buffer)		^X-K
+
+	Dispose of an undisplayed buffer in the editor and reclaim the
+space. This does not delete the file the buffer was read from.
+
+ at i(list-buffers)	^X-^B
+
+	Split the current window and in one half bring up a list of all
+the buffers currently existing in the editor.  The active modes, change
+flag, and active flag for each buffer is also displayed.  (The change
+flag is an * if the buffer has been changed and not written out.  the
+active flag is not an * if the file had been specified on the command
+line, but has not been read in yet since nothing has switched to that
+buffer.)
+
+ at i[(14) READING FROM DISK]
+
+ at i(find-file)		^X-^F
+
+	FInd the named file. If it is already in a buffer, make that
+buffer active in the current window, otherwise attemt tocreate a new
+buffer and read the file into it.
+
+ at i(read-file)		^X-^R
+
+	Read the named file into the current buffer (overwriting the
+previous contents of the current buffer. If the change flag is set, a
+confirmation will be asked).
+
+ at i(insert-file)		^X-^I
+
+	Insert the named file into the current position of the current
+buffer.
+
+ at i(view-file)		^X-^V
+
+	Like find-file, this command either finds the file in a buffer,
+or creates a new buffer and reads the file in. In addition, this leaves
+that buffer in VIEW mode.
+
+ at i[(15) SAVING TO DISK]
+
+ at i(save-file)		^X-^S
+
+	If the contents of the current buffer have been changed, write
+it back to the file it was read from.
+
+ at i(write-file)		^X-^W
+
+	Write the contents of the current file to the named file, this
+also changed the file name associated with the current buffer to the new
+file name.
+
+ at i(change-file-name)	^X-N
+
+	Change the name associated with the current buffer to the file
+name given.
+
+ at i(quick-exit)		M-Z
+
+	Write out all changed buffers to the files they were read from
+and exit the editor.
+
+ at b[(16) ACCESSING THE OPERATING SYSTEM]
+
+ at i(shell-command)	^X-!
+
+	Send one command to execute to the operating system command
+processor, or shell.  Upon completion, MicroEMACS will wait for a
+keystroke to redraw the screen. 
+
+ at i(pipe-command)	^X-@
+
+	Execute one operating system command and pipe the resulting
+output into a buffer by the name of "command".
+
+ at i(filter-buffer)	^X-#
+
+	Execute one operating system command, using the contents of the
+current buffer as input, and sending the results back to the same
+buffer, replacing the original text.
+
+ at i(i-shell)		^X-C
+
+	Push up to a new command processor or shell.  Upon exiting the
+shell, MicroEMACS will redraw its screen and continue editing.
+
+ at i(suspend-emacs)	^X-D		[only under BSD4.2]
+
+	This command suspends the editing processor and puts it into the
+background.  The "fg" command will restart MicroEMACS.
+
+ at i(exit-emacs)		^X-^C
+
+	Exit MicroEMACS back to the operating system.  If there are any
+unwritten, changed buffers, the editor will promt to discard changes.
+
+ at b[(17) KEY BINDINGS AND COMMANDS]
+
+ at i(bind-to-key)		M-K
+
+	This command takes one of the named commands and binds it to a
+key.  From then on, whenever that key is struck, the bound command is
+executed.
+
+ at i(unbind-key)		M-^K
+
+	This unbinds a command from a key.
+
+ at i(describe-key)	^X-?
+
+	This command will allow you to type a key and it will then
+report the name of the command bound to that key.
+
+ at i(execute-named-command)	M-X
+
+	This command will prompt you for the name of a command to
+execute.  Typing <SPACE> part way thought will tell the editor to
+attempt to complete the name on its own.  If it then beeps, there is no
+such command to complete.
+
+ at i(describe-bindings)		UNBOUND
+
+	This command splits the current window, and in one of the
+windows makes a list of all the named commands, and the keys currently
+bound to them.
+
+ at b[(18) COMMAND EXECUTION]
+
+	Commands can also be executed as command scripts.  This allows
+comands and their arguments to be stored in files and executed.  The
+general form of a command script line is:
+
+	<optional repeat count> {command-name} <optional arguments>
+
+ at i(execute-command-line)	UNBOUND
+
+	Execute a typed in script line.
+
+ at i(execute-buffer)		UNBOUND
+
+	Executes script lines in the named buffer.  If the buffer is off
+screen and an error occurs during execution, the cursor will be left on
+the line causing the error.
+
+ at i(execute-file)		UNBOUND
+
+	Executes script lines from a file.  This is the normal way to
+execute a special script.
+
+ at i(clear-message-line)		UNBOUND
+
+	Clears the message line during script execution.  This is
+usefull so as not to leave a confusion message from the last commands
+in a script.
+
+ at i(unmark-buffer)		UNBOUND
+
+	Remove the change flag from the current buffer.  This is very
+usefull in scripts where you are creating help windows, and don't want
+MicroEMACS to complain about not saving them to a file.
+
+ at i(insert-string)		UNBOUND
+
+	Insert a string into the current buffer.  This allows you to
+build up text within a buffer without reading it in from a file.  Some
+special characters are allowd, as follows:
+
+	~n	newline
+	~t	tab
+	~b	backspace
+	~f	formfeed
+
+
+ at b[(19) MACRO EXECUTION]
+
+	Also availible is one keyboard macro, which allows you to record
+a number of commands as they are executed and play them back.
+
+ at i(begin-macro)		^X (
+
+	Start recording keyboard macro
+
+ at i(end-macro)		^X )
+
+	Stop recording keyboard macro
+
+ at i(execute-macro)	^X E
+
+	Execute keyboard macro
+
+ at i(store-macro)		UNBOUND
+
+	This command is used to store script lines in a hiffen buffer by
+the name of "[Macro nn]" where <nn> is a number from 1 to 40 and
+coresponds to the argument given this command.  All script lines then
+encountered will be stored in this buffer rather than being executed.  A
+script line consisting of only "[end]" tells the editor that the macro
+is complete, and stops recording script lines in the buffer.
+
+ at i(execute-macro-nn)	UNBOUND		[shift-<F1> thru shift-<F10>]
+
+	This is the command to execute a script stored in one of the
+hidden macro buffers.  On the IBM-PC the first ten of these are bound to
+shift-<F1> thru shift-<F10>.
+ at end(verbatim)

Added: clients/emacs/emacsfm.rc
===================================================================
--- clients/emacs/emacsfm.rc	                        (rev 0)
+++ clients/emacs/emacsfm.rc	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,126 @@
+;	EMACS.RC:	Startup file for MicroEMACS 3.4
+;
+;			This file is executed everytime the
+;			editor is entered
+;
+;	This version of the files contains bindings that more closely
+;	match the EMACS documentation in the Forthmacs User's Manual.
+
+; Set up Forthmacs-compatible bindings
+
+; I find that the location of the ESC key on most PC keyboards is too far
+; from the home keys for effective use with EMACS.  I am accustomed to the
+; ESC key being in the location where the PC puts the ` key.  I therefore
+; prefer to bind the ` key to be the meta prefix, instead of the real ESC
+; key.  This works well if you can train yourself not to look for the
+; ESC label on the key cap, and just touch type ` without looking.
+
+; bind-to-key meta-prefix			`
+
+bind-to-key find-file			^X^V
+bind-to-key delete-window               ^X^D
+bind-to-key next-window			^XN
+; bind-to-key incremental-search		^S
+; bind-to-key reverse-incremental-search	^R
+bind-to-key search-forward		^S
+bind-to-key search-forward		^\
+bind-to-key search-reverse		^R
+bind-to-key save-file			^XS
+bind-to-key apropos			M-?
+bind-to-key select-buffer		^X^O
+bind-to-key delete-buffer		^XK
+bind-to-key move-window-down		^Z
+bind-to-key move-window-up		M-Z
+
+
+;	***** Rebind the Function key group
+
+bind-to-key execute-macro-11		FN;
+bind-to-key execute-named-command	FN<
+bind-to-key hunt-forward		FN=
+bind-to-key hunt-backward		FN>
+bind-to-key next-window			FN?
+bind-to-key execute-macro		FN@
+bind-to-key find-file			FNA
+bind-to-key view-file			FNB
+bind-to-key save-file			FNC
+bind-to-key exit-emacs			FND
+
+;	set screen colors
+add-global-mode "blue"
+
+;	Enter Help
+11 store-macro
+	help
+	8 resize-window
+	bind-to-key execute-macro-12 FNI
+	bind-to-key execute-macro-13 FNQ
+	bind-to-key execute-macro-14 FN;
+	add-mode "red"
+	begining-of-file
+	2 forward-character
+	clear-message-line
+[end]
+
+;	bring up the function key window
+1 store-macro
+	2 split-current-window
+	select-buffer "Function Keys"
+	add-mode "red"
+	begining-of-file
+	2 resize-window
+	insert-string "F1 help on/off F2  exec cmd    F3 hunt       F4  back hunt     F5  next window"
+	newline
+	insert-string "F6 exec macro  F7  find file   F8 view file  F9  save file     F10 exit emacs"
+	begining-of-file
+	unmark-buffer
+	bind-to-key execute-macro-15 FNT
+	next-window
+[end]
+
+; reselect function key window
+15 store-macro
+	2 split-current-window
+	select-buffer "Function Keys"
+	begining-of-file
+	2 resize-window
+	add-mode "red"
+	next-window
+[end]
+
+;	consult file
+3 store-macro
+	2 split-current-window
+	previous-window
+	view-file "@File to Consult: "
+	8 resize-window
+	add-mode "green"
+	add-mode "Black"
+	next-window
+[end]
+
+;	Exit Help
+14 store-macro
+	bind-to-key previous-page FNI
+	bind-to-key next-page FNQ
+	bind-to-key execute-macro-1 FN;
+	delete-window
+	clear-message-line
+[end]
+
+;	last help page
+12 store-macro
+	begining-of-line
+	search-reverse "=>"
+	1 redraw-display
+[end]
+
+;	next help page
+13 store-macro
+	begining-of-line
+	2 forward-character
+	search-forward "=>"
+	1 redraw-display
+[end]
+
+execute-macro-1

Added: clients/emacs/emacsobp.rc
===================================================================
--- clients/emacs/emacsobp.rc	                        (rev 0)
+++ clients/emacs/emacsobp.rc	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,56 @@
+;	EMACS.RC:	Startup file for MicroEMACS 3.4
+;
+;			This file is executed everytime the
+;			editor is entered
+;
+;	This version of the file contains bindings for Open Firmware.
+
+; Set up bindings
+
+; bind-to-key meta-prefix			`
+
+bind-to-key find-file			^X^V
+bind-to-key delete-window               ^X^D
+bind-to-key next-window			^XN
+bind-to-key search-forward		^S
+bind-to-key search-forward		^\
+bind-to-key search-reverse		^R
+bind-to-key save-file			^XS
+bind-to-key apropos			M-?
+bind-to-key select-buffer		^X^O
+bind-to-key delete-buffer		^XK
+bind-to-key move-window-down		^Z
+bind-to-key move-window-up		M-Z
+
+
+;	set screen colors
+add-global-mode "blue"
+add-global-mode "WHITE"
+
+;	consult file
+3 store-macro
+	2 split-current-window
+	previous-window
+	view-file "@File to Consult: "
+	8 resize-window
+	add-mode "green"
+	add-mode "Black"
+	next-window
+[end]
+
+;	last help page
+12 store-macro
+	begining-of-line
+	search-reverse "=>"
+	1 redraw-display
+[end]
+
+;	next help page
+13 store-macro
+	begining-of-line
+	2 forward-character
+	search-forward "=>"
+	1 redraw-display
+[end]
+
+execute-macro-1

Added: clients/emacs/epath.h
===================================================================
--- clients/emacs/epath.h	                        (rev 0)
+++ clients/emacs/epath.h	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,61 @@
+/*	PATH:	This file contains certain info needed to locate the
+		MicroEMACS files on a system dependant basis.
+
+									*/
+
+/*	possible names and paths of help files under different OSs	*/
+
+char *pathname[] =
+
+#if	OFW
+{
+	"emacs.rc",
+	"emacs.hlp",
+	"",
+	"/disk:\\",
+        "rom:"
+};
+#endif
+
+#if	AMIGA
+{
+	".emacsrc",
+	"emacs.hlp",
+	"",
+	":c/",
+	":t/"
+};
+#endif
+
+#if	MSDOS
+{
+	"emacs.rc",
+	"emacs.hlp",
+	"",
+	"\\",
+	"\\bin\\",
+	"\\fm\\emacs\\",
+	"c:\\fm\\emacs\\"
+};
+#endif
+
+#if	V7 | BSD | USG
+{
+	".emacsrc",
+	"emacs.hlp",
+	"/usr/local/",
+	"/usr/lib/",
+	""
+};
+#endif
+
+#if	VMS
+{
+	"emacs.rc",
+	"emacs.hlp",
+	"",
+	"sys$sysdevice:[vmstools]"
+};
+#endif
+
+#define	NPNAMES	(sizeof(pathname)/sizeof(char *))

Added: clients/emacs/estruct.h
===================================================================
--- clients/emacs/estruct.h	                        (rev 0)
+++ clients/emacs/estruct.h	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,247 @@
+/*	ESTRUCT:	Structure and preprocesser defined for
+			MicroEMACS 3.7
+
+			written by Dave G. Conroy
+			modified by Steve Wilhite, George Jones
+			greatly modified by Daniel Lawrence
+*/
+
+#include "config.h"
+
+/*	System dependant library redefinitions, structures and includes	*/
+
+#if	MSDOS & AZTEC
+#undef	fputc
+#undef	fgetc
+#define	fputc	aputc
+#define	fgetc	agetc
+#define	int86	sysint
+#define	inp	inportb
+
+struct XREG {
+	int ax,bx,cx,dx,si,di;
+};
+
+struct HREG {
+	char al,ah,bl,bh,cl,ch,dl,dh;
+};
+
+union REGS {
+	struct XREG x;
+	struct HREG h;
+};
+#endif
+
+#if	MSDOS & LATTICE
+#undef	CPM
+#undef	LATTICE
+#include	<dos.h>
+#undef	CPM
+#endif
+
+/*	internal constants	*/
+
+#define	NBINDS	200			/* max # of bound keys		*/
+#define NFILEN  80                      /* # of bytes, file name        */
+#define NBUFN   16                      /* # of bytes, buffer name      */
+#define NLINE   256                     /* # of bytes, line             */
+#define	NSTRING	256			/* # of bytes, string buffers	*/
+#define NKBDM   256                     /* # of strokes, keyboard macro */
+#define NPAT    80                      /* # of bytes, pattern          */
+#define HUGE    1000                    /* Huge number                  */
+#define	NLOCKS	100			/* max # of file locks active	*/
+#define	NCOLORS	8			/* number of supported colors	*/
+#define	KBLOCK	250			/* sizeof kill buffer chunks	*/
+#define	NBLOCK	16			/* line block chunk size	*/
+
+#define AGRAVE  0x60                    /* M- prefix,   Grave (LK201)   */
+#define METACH  0x1B                    /* M- prefix,   Control-[, ESC  */
+#define CTMECH  0x1C                    /* C-M- prefix, Control-\       */
+#define EXITCH  0x1D                    /* Exit level,  Control-]       */
+#define CTRLCH  0x1E                    /* C- prefix,   Control-^       */
+#define HELPCH  0x1F                    /* Help key,    Control-_       */
+
+#define CTRL    0x0100                  /* Control flag, or'ed in       */
+#define META    0x0200                  /* Meta flag, or'ed in          */
+#define CTLX    0x0400                  /* ^X flag, or'ed in            */
+#define	SPEC	0x0800			/* special key (function keys)	*/
+
+#define FALSE   0                       /* False, no, bad, etc.         */
+#define TRUE    1                       /* True, yes, good, etc.        */
+#define ABORT   2                       /* Death, ^G, abort, etc.       */
+
+#define FIOSUC  0                       /* File I/O, success.           */
+#define FIOFNF  1                       /* File I/O, file not found.    */
+#define FIOEOF  2                       /* File I/O, end of file.       */
+#define FIOERR  3                       /* File I/O, error.             */
+#define	FIOLNG	4			/*line longer than allowed len	*/
+
+#define CFCPCN  0x0001                  /* Last command was C-P, C-N    */
+#define CFKILL  0x0002                  /* Last command was a kill      */
+
+#define	BELL	0x07			/* a bell character		*/
+#define	TAB	0x09			/* a tab character		*/
+
+/*
+ * There is a window structure allocated for every active display window. The
+ * windows are kept in a big list, in top to bottom screen order, with the
+ * listhead at "wheadp". Each window contains its own values of dot and mark.
+ * The flag field contains some bits that are set by commands to guide
+ * redisplay; although this is a bit of a compromise in terms of decoupling,
+ * the full blown redisplay is just too expensive to run for every input
+ * character.
+ */
+typedef struct  WINDOW {
+        struct  WINDOW *w_wndp;         /* Next window                  */
+        struct  BUFFER *w_bufp;         /* Buffer displayed in window   */
+        struct  LINE *w_linep;          /* Top line in the window       */
+        struct  LINE *w_dotp;           /* Line containing "."          */
+        short   w_doto;                 /* Byte offset for "."          */
+        struct  LINE *w_markp;          /* Line containing "mark"       */
+        short   w_marko;                /* Byte offset for "mark"       */
+        char    w_toprow;               /* Origin 0 top row of window   */
+        char    w_ntrows;               /* # of rows of text in window  */
+        char    w_force;                /* If NZ, forcing row.          */
+        char    w_flag;                 /* Flags.                       */
+#if	COLOR
+	char	w_fcolor;		/* current forground color	*/
+	char	w_bcolor;		/* current background color	*/
+#endif
+}       WINDOW;
+
+#define WFFORCE 0x01                    /* Window needs forced reframe  */
+#define WFMOVE  0x02                    /* Movement from line to line   */
+#define WFEDIT  0x04                    /* Editing within a line        */
+#define WFHARD  0x08                    /* Better to a full display     */
+#define WFMODE  0x10                    /* Update mode line.            */
+#define	WFCOLR	0x20			/* Needs a color change		*/
+
+/*
+ * Text is kept in buffers. A buffer header, described below, exists for every
+ * buffer in the system. The buffers are kept in a big list, so that commands
+ * that search for a buffer by name can find the buffer header. There is a
+ * safe store for the dot and mark in the header, but this is only valid if
+ * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
+ * the buffer is kept in a circularly linked list of lines, with a pointer to
+ * the header line in "b_linep".
+ * 	Buffers may be "Inactive" which means the files accosiated with them
+ * have not been read in yet. These get read in at "use buffer" time.
+ */
+typedef struct  BUFFER {
+        struct  BUFFER *b_bufp;         /* Link to next BUFFER          */
+        struct  LINE *b_dotp;           /* Link to "." LINE structure   */
+        short   b_doto;                 /* Offset of "." in above LINE  */
+        struct  LINE *b_markp;          /* The same as the above two,   */
+        short   b_marko;                /* but for the "mark"           */
+        struct  LINE *b_linep;          /* Link to the header LINE      */
+	char	b_active;		/* window activated flag	*/
+        char    b_nwnd;                 /* Count of windows on buffer   */
+        char    b_flag;                 /* Flags                        */
+	char	b_mode;			/* editor mode of this buffer	*/
+        char    b_fname[NFILEN];        /* File name                    */
+        char    b_bname[NBUFN];         /* Buffer name                  */
+}       BUFFER;
+
+#define BFINVS  0x01                    /* Internal invisable buffer    */
+#define BFCHG   0x02                    /* Changed since last write     */
+
+/*	mode flags	*/
+#define	NUMMODES	7		/* # of defined modes		*/
+
+#define	MDWRAP	0x0001			/* word wrap			*/
+#define	MDCMOD	0x0002			/* C indentation and fence match*/
+#define	MDSPELL	0x0004			/* spell error parcing		*/
+#define	MDEXACT	0x0008			/* Exact matching for searches	*/
+#define	MDVIEW	0x0010			/* read-only buffer		*/
+#define MDOVER	0x0020			/* overwrite mode		*/
+#define MDMAGIC	0x0040			/* regular expresions in search */
+
+/*
+ * The starting position of a region, and the size of the region in
+ * characters, is kept in a region structure.  Used by the region commands.
+ */
+typedef struct  {
+        struct  LINE *r_linep;          /* Origin LINE address.         */
+        short   r_offset;               /* Origin LINE offset.          */
+        long	r_size;                 /* Length in characters.        */
+}       REGION;
+
+/*
+ * All text is kept in circularly linked lists of "LINE" structures. These
+ * begin at the header line (which is the blank line beyond the end of the
+ * buffer). This line is pointed to by the "BUFFER". Each line contains a the
+ * number of bytes in the line (the "used" size), the size of the text array,
+ * and the text. The end of line is not stored as a byte; it's implied. Future
+ * additions will include update hints, and a list of marks into the line.
+ */
+typedef struct  LINE {
+        struct  LINE *l_fp;             /* Link to the next line        */
+        struct  LINE *l_bp;             /* Link to the previous line    */
+        short   l_size;                 /* Allocated size               */
+        short   l_used;                 /* Used size                    */
+        char    l_text[1];              /* A bunch of characters.       */
+}       LINE;
+
+#define lforw(lp)       ((lp)->l_fp)
+#define lback(lp)       ((lp)->l_bp)
+#define lgetc(lp, n)    ((lp)->l_text[(n)]&0xFF)
+#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
+#define llength(lp)     ((lp)->l_used)
+
+/*
+ * The editor communicates with the display using a high level interface. A
+ * "TERM" structure holds useful variables, and indirect pointers to routines
+ * that do useful operations. The low level get and put routines are here too.
+ * This lets a terminal, in addition to having non standard commands, have
+ * funny get and put character code too. The calls might get changed to
+ * "termp->t_field" style in the future, to make it possible to run more than
+ * one terminal type.
+ */
+typedef struct  {
+        short   t_nrow;                 /* Number of rows.              */
+        short   t_ncol;                 /* Number of columns.           */
+	short	t_margin;		/* min margin for extended lines*/
+	short	t_scrsiz;		/* size of scroll region "	*/
+	int	t_pause;		/* # times thru update to pause */
+        int     (*t_open)();            /* Open terminal at the start.  */
+        int     (*t_close)();           /* Close terminal at end.       */
+        int     (*t_getchar)();         /* Get character from keyboard. */
+        int     (*t_putchar)();         /* Put character to display.    */
+        int     (*t_flush)();           /* Flush output buffers.        */
+        int     (*t_move)();            /* Move the cursor, origin 0.   */
+        int     (*t_eeol)();            /* Erase to end of line.        */
+        int     (*t_eeop)();            /* Erase to end of page.        */
+        int     (*t_beep)();            /* Beep.                        */
+	int	(*t_rev)();		/* set reverse video state	*/
+#if	COLOR
+	int	(*t_setfor)();		/* set forground color		*/
+	int	(*t_setback)();		/* set background color		*/
+#endif
+}       TERM;
+
+/*	structure for the table of initial key bindings		*/
+
+typedef struct  {
+        short   k_code;                 /* Key code                     */
+        int     (*k_fp)();              /* Routine to handle it         */
+}       KEYTAB;
+
+/*	structure for the name binding table		*/
+
+typedef struct {
+	char *n_name;		/* name of function key */
+	int (*n_func)();	/* function name is bound to */
+}	NBIND;
+
+/*	The editor holds deleted text chunks in the KILL buffer. The
+	kill buffer is logically a stream of ascii characters, however
+	due to its unpredicatable size, it gets implemented as a linked
+	list of chunks. (The d_ prefix is for "deleted" text, as k_
+	was taken up by the keycode structure			*/
+
+typedef	struct KILL {
+	struct KILL *d_next;	/* link to next chunk, NULL if last */
+	char d_chunk[KBLOCK];	/* deleted text */
+} KILL;
+
+#define NULL  0

Added: clients/emacs/estructp.h
===================================================================
--- clients/emacs/estructp.h	                        (rev 0)
+++ clients/emacs/estructp.h	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,302 @@
+/*	ESTRUCT:	Structure and preprocesser defined for
+			MicroEMACS 3.7
+
+			written by Dave G. Conroy
+			modified by Steve Wilhite, George Jones
+			greatly modified by Daniel Lawrence
+*/
+
+#undef	LATTICE		/* don't use their definitions...use ours	*/
+#undef	MSDOS
+#undef	CPM
+#undef	AMIGA
+
+/*	Machine/OS definitions			*/
+
+#define AMIGA   0                       /* AmigaDOS			*/
+#define ST520   0                       /* ST520, TOS                   */
+#define MSDOS   1                       /* MS-DOS                       */
+#define V7      0                       /* V7 UN*X or Coherent or BSD4.2*/
+#define	BSD	0			/* UNIX BSD 4.2	and ULTRIX	*/
+#define	USG	0			/* UNIX system V		*/
+#define VMS     0                       /* VAX/VMS                      */
+#define CPM     0                       /* CP/M-86                      */
+
+/*	Compiler definitions			*/
+#define MWC86   0	/* marc williams compiler */
+#define	LATTICE	0	/* either lattice compiler */
+#define	LAT2	0	/* Lattice 2.15 */
+#define	LAT3	0	/* Lattice 3.0 */
+#define	AZTEC	0	/* Aztec C 3.20e */
+#define	MSC	1	/* MicroSoft C compile version 3 */
+
+/*	Profiling options	*/
+#define	APROF	0	/* turn Aztec C profiling on? */
+#define	NBUCK	100	/* number of buckets to profile */
+
+/*   Special keyboard definitions            */
+ 
+#define WANGPC	0			/* WangPC - mostly escape sequences     */
+ 
+/*	Terminal Output definitions		*/
+
+#define ANSI    0			/* ansi escape sequences	*/
+#define	HP150	0			/* HP150 screen driver		*/
+#define	VMSVT	0			/* various VMS terminal entries	*/
+#define VT52    0                       /* VT52 terminal (Zenith).      */
+#define VT100   0                       /* Handle VT100 style keypad.   */
+#define LK201   0                       /* Handle LK201 style keypad.   */
+#define RAINBOW 0                       /* Use Rainbow fast video.      */
+#define TERMCAP 0                       /* Use TERMCAP                  */
+#define	IBMPC	1			/* IBM-PC specific driver	*/
+#define	DG10	0			/* Data General system/10	*/
+
+/*	Configuration options	*/
+
+#define CVMVAS  1	/* arguments to page forward/back in pages	*/
+#define	NFWORD	1	/* forward word jumps to begining of word	*/
+#define	CLRMSG	0	/* space clears the message line with no insert	*/
+#define	TYPEAH	1	/* type ahead causes update to be skipped	*/
+#define	FILOCK	0	/* file locking under unix BSD 4.2		*/
+#define	REVSTA	1	/* Status line appears in reverse video		*/
+#define	COLOR	1	/* color commands and windows			*/
+#define	ACMODE	1	/* auto CMODE on .C and .H files		*/
+#define	CFENCE	1	/* fench matching in CMODE			*/
+#define	ISRCH	1	/* Incremental searches like ITS EMACS		*/
+#define	WORDPRO	1	/* Advanced word processing features		*/
+
+/*	System dependant library redefinitions, structures and includes	*/
+
+#if	MSDOS & AZTEC
+#undef	fputc
+#undef	fgetc
+#define	fputc	aputc
+#define	fgetc	agetc
+#define	int86	sysint
+#define	inp	inportb
+
+struct XREG {
+	int ax,bx,cx,dx,si,di;
+};
+
+struct HREG {
+	char al,ah,bl,bh,cl,ch,dl,dh;
+};
+
+union REGS {
+	struct XREG x;
+	struct HREG h;
+};
+#endif
+
+#if	MSDOS & LATTICE
+#undef	CPM
+#undef	LATTICE
+#include	<dos.h>
+#undef	CPM
+#endif
+
+/*	internal constants	*/
+
+#define	NBINDS	200			/* max # of bound keys		*/
+#define NFILEN  80                      /* # of bytes, file name        */
+#define NBUFN   16                      /* # of bytes, buffer name      */
+#define NLINE   256                     /* # of bytes, line             */
+#define	NSTRING	256			/* # of bytes, string buffers	*/
+#define NKBDM   256                     /* # of strokes, keyboard macro */
+#define NPAT    80                      /* # of bytes, pattern          */
+#define HUGE    1000                    /* Huge number                  */
+#define	NLOCKS	100			/* max # of file locks active	*/
+#define	NCOLORS	8			/* number of supported colors	*/
+#define	KBLOCK	250			/* sizeof kill buffer chunks	*/
+#define	NBLOCK	16			/* line block chunk size	*/
+
+#define AGRAVE  0x60                    /* M- prefix,   Grave (LK201)   */
+#define METACH  0x1B                    /* M- prefix,   Control-[, ESC  */
+#define CTMECH  0x1C                    /* C-M- prefix, Control-\       */
+#define EXITCH  0x1D                    /* Exit level,  Control-]       */
+#define CTRLCH  0x1E                    /* C- prefix,   Control-^       */
+#define HELPCH  0x1F                    /* Help key,    Control-_       */
+
+#define CTRL    0x0100                  /* Control flag, or'ed in       */
+#define META    0x0200                  /* Meta flag, or'ed in          */
+#define CTLX    0x0400                  /* ^X flag, or'ed in            */
+#define	SPEC	0x0800			/* special key (function keys)	*/
+
+#define FALSE   0                       /* False, no, bad, etc.         */
+#define TRUE    1                       /* True, yes, good, etc.        */
+#define ABORT   2                       /* Death, ^G, abort, etc.       */
+
+#define FIOSUC  0                       /* File I/O, success.           */
+#define FIOFNF  1                       /* File I/O, file not found.    */
+#define FIOEOF  2                       /* File I/O, end of file.       */
+#define FIOERR  3                       /* File I/O, error.             */
+#define	FIOLNG	4			/*line longer than allowed len	*/
+
+#define CFCPCN  0x0001                  /* Last command was C-P, C-N    */
+#define CFKILL  0x0002                  /* Last command was a kill      */
+
+#define	BELL	0x07			/* a bell character		*/
+#define	TAB	0x09			/* a tab character		*/
+
+/*
+ * There is a window structure allocated for every active display window. The
+ * windows are kept in a big list, in top to bottom screen order, with the
+ * listhead at "wheadp". Each window contains its own values of dot and mark.
+ * The flag field contains some bits that are set by commands to guide
+ * redisplay; although this is a bit of a compromise in terms of decoupling,
+ * the full blown redisplay is just too expensive to run for every input
+ * character.
+ */
+typedef struct  WINDOW {
+        struct  WINDOW *w_wndp;         /* Next window                  */
+        struct  BUFFER *w_bufp;         /* Buffer displayed in window   */
+        struct  LINE *w_linep;          /* Top line in the window       */
+        struct  LINE *w_dotp;           /* Line containing "."          */
+        short   w_doto;                 /* Byte offset for "."          */
+        struct  LINE *w_markp;          /* Line containing "mark"       */
+        short   w_marko;                /* Byte offset for "mark"       */
+        char    w_toprow;               /* Origin 0 top row of window   */
+        char    w_ntrows;               /* # of rows of text in window  */
+        char    w_force;                /* If NZ, forcing row.          */
+        char    w_flag;                 /* Flags.                       */
+#if	COLOR
+	char	w_fcolor;		/* current forground color	*/
+	char	w_bcolor;		/* current background color	*/
+#endif
+}       WINDOW;
+
+#define WFFORCE 0x01                    /* Window needs forced reframe  */
+#define WFMOVE  0x02                    /* Movement from line to line   */
+#define WFEDIT  0x04                    /* Editing within a line        */
+#define WFHARD  0x08                    /* Better to a full display     */
+#define WFMODE  0x10                    /* Update mode line.            */
+#define	WFCOLR	0x20			/* Needs a color change		*/
+
+/*
+ * Text is kept in buffers. A buffer header, described below, exists for every
+ * buffer in the system. The buffers are kept in a big list, so that commands
+ * that search for a buffer by name can find the buffer header. There is a
+ * safe store for the dot and mark in the header, but this is only valid if
+ * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
+ * the buffer is kept in a circularly linked list of lines, with a pointer to
+ * the header line in "b_linep".
+ * 	Buffers may be "Inactive" which means the files accosiated with them
+ * have not been read in yet. These get read in at "use buffer" time.
+ */
+typedef struct  BUFFER {
+        struct  BUFFER *b_bufp;         /* Link to next BUFFER          */
+        struct  LINE *b_dotp;           /* Link to "." LINE structure   */
+        short   b_doto;                 /* Offset of "." in above LINE  */
+        struct  LINE *b_markp;          /* The same as the above two,   */
+        short   b_marko;                /* but for the "mark"           */
+        struct  LINE *b_linep;          /* Link to the header LINE      */
+	char	b_active;		/* window activated flag	*/
+        char    b_nwnd;                 /* Count of windows on buffer   */
+        char    b_flag;                 /* Flags                        */
+	char	b_mode;			/* editor mode of this buffer	*/
+        char    b_fname[NFILEN];        /* File name                    */
+        char    b_bname[NBUFN];         /* Buffer name                  */
+}       BUFFER;
+
+#define BFINVS  0x01                    /* Internal invisable buffer    */
+#define BFCHG   0x02                    /* Changed since last write     */
+
+/*	mode flags	*/
+#define	NUMMODES	7		/* # of defined modes		*/
+
+#define	MDWRAP	0x0001			/* word wrap			*/
+#define	MDCMOD	0x0002			/* C indentation and fence match*/
+#define	MDSPELL	0x0004			/* spell error parcing		*/
+#define	MDEXACT	0x0008			/* Exact matching for searches	*/
+#define	MDVIEW	0x0010			/* read-only buffer		*/
+#define MDOVER	0x0020			/* overwrite mode		*/
+#define MDMAGIC	0x0040			/* regular expresions in search */
+
+/*
+ * The starting position of a region, and the size of the region in
+ * characters, is kept in a region structure.  Used by the region commands.
+ */
+typedef struct  {
+        struct  LINE *r_linep;          /* Origin LINE address.         */
+        short   r_offset;               /* Origin LINE offset.          */
+        long	r_size;                 /* Length in characters.        */
+}       REGION;
+
+/*
+ * All text is kept in circularly linked lists of "LINE" structures. These
+ * begin at the header line (which is the blank line beyond the end of the
+ * buffer). This line is pointed to by the "BUFFER". Each line contains a the
+ * number of bytes in the line (the "used" size), the size of the text array,
+ * and the text. The end of line is not stored as a byte; it's implied. Future
+ * additions will include update hints, and a list of marks into the line.
+ */
+typedef struct  LINE {
+        struct  LINE *l_fp;             /* Link to the next line        */
+        struct  LINE *l_bp;             /* Link to the previous line    */
+        short   l_size;                 /* Allocated size               */
+        short   l_used;                 /* Used size                    */
+        char    l_text[1];              /* A bunch of characters.       */
+}       LINE;
+
+#define lforw(lp)       ((lp)->l_fp)
+#define lback(lp)       ((lp)->l_bp)
+#define lgetc(lp, n)    ((lp)->l_text[(n)]&0xFF)
+#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
+#define llength(lp)     ((lp)->l_used)
+
+/*
+ * The editor communicates with the display using a high level interface. A
+ * "TERM" structure holds useful variables, and indirect pointers to routines
+ * that do useful operations. The low level get and put routines are here too.
+ * This lets a terminal, in addition to having non standard commands, have
+ * funny get and put character code too. The calls might get changed to
+ * "termp->t_field" style in the future, to make it possible to run more than
+ * one terminal type.
+ */
+typedef struct  {
+        short   t_nrow;                 /* Number of rows.              */
+        short   t_ncol;                 /* Number of columns.           */
+	short	t_margin;		/* min margin for extended lines*/
+	short	t_scrsiz;		/* size of scroll region "	*/
+	int	t_pause;		/* # times thru update to pause */
+        int     (*t_open)();            /* Open terminal at the start.  */
+        int     (*t_close)();           /* Close terminal at end.       */
+        int     (*t_getchar)();         /* Get character from keyboard. */
+        int     (*t_putchar)();         /* Put character to display.    */
+        int     (*t_flush)();           /* Flush output buffers.        */
+        int     (*t_move)();            /* Move the cursor, origin 0.   */
+        int     (*t_eeol)();            /* Erase to end of line.        */
+        int     (*t_eeop)();            /* Erase to end of page.        */
+        int     (*t_beep)();            /* Beep.                        */
+	int	(*t_rev)();		/* set reverse video state	*/
+#if	COLOR
+	int	(*t_setfor)();		/* set forground color		*/
+	int	(*t_setback)();		/* set background color		*/
+#endif
+}       TERM;
+
+/*	structure for the table of initial key bindings		*/
+
+typedef struct  {
+        short   k_code;                 /* Key code                     */
+        int     (*k_fp)();              /* Routine to handle it         */
+}       KEYTAB;
+
+/*	structure for the name binding table		*/
+
+typedef struct {
+	char *n_name;		/* name of function key */
+	int (*n_func)();	/* function name is bound to */
+}	NBIND;
+
+/*	The editor holds deleted text chunks in the KILL buffer. The
+	kill buffer is logically a stream of ascii characters, however
+	due to its unpredicatable size, it gets implemented as a linked
+	list of chunks. (The d_ prefix is for "deleted" text, as k_
+	was taken up by the keycode structure			*/
+
+typedef	struct KILL {
+	struct KILL *d_next;	/* link to next chunk, NULL if last */
+	char d_chunk[KBLOCK];	/* deleted text */
+} KILL;

Added: clients/emacs/exec.c
===================================================================
--- clients/emacs/exec.c	                        (rev 0)
+++ clients/emacs/exec.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,727 @@
+/*	This file is for functions dealing with execution of
+	commands, command lines, buffers, files and startup files
+
+	written 1986 by Daniel Lawrence				*/
+
+#include	"estruct.h"
+#include	"edef.h"
+
+/* namedcmd:	execute a named command even if it is not bound
+*/
+
+namedcmd(f, n)
+
+int f, n;	/* command arguments [passed through to command executed] */
+
+{
+	register (*kfunc)();	/* ptr to the requexted function to bind to */
+	int (*getname())();
+
+	/* prompt the user to type a named command */
+	mlwrite(": ");
+
+	/* and now get the function name to execute */
+	kfunc = getname();
+	if (kfunc == NULL) {
+		mlwrite("[No such function]");
+		return(FALSE);
+	}
+
+	/* and then execute the command */
+	return((*kfunc)(f, n));
+}
+
+/*	execcmd:	Execute a command line command to be typed in
+			by the user					*/
+
+execcmd(f, n)
+
+int f, n;	/* default Flag and Numeric argument */
+
+{
+	register int status;		/* status return */
+	char cmdstr[NSTRING];		/* string holding command to execute */
+
+	/* get the line wanted */
+	if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
+		return(status);
+
+	return(docmd(cmdstr));
+}
+
+/*	docmd:	take a passed string as a command line and translate
+		it to be executed as a command. This function will be
+		used by execute-command-line and by all source and
+		startup files.
+
+	format of the command line is:
+
+		{# arg} <command-name> {<argument string(s)>}
+
+	Macro storing is turned off by a line:
+
+		[end]
+*/
+
+docmd(cline)
+
+char *cline;	/* command line to execute */
+
+{
+	register char *tp;	/* pointer to current position in token */
+	register int f;		/* default argument flag */
+	register int n;		/* numeric repeat value */
+	register int i;
+	int sign;		/* sign of numeric argument */
+	int (*fnc)();		/* function to execute */
+	int status;		/* return status of function */
+	int oldcle;		/* old contents of clexec flag */
+	int llen;		/* length of cline */
+	struct LINE *lp;	/* a line pointer */
+	char token[NSTRING];	/* next token off of command line */
+	int (*fncmatch())();
+
+	/* check to see if this line turns macro storage off */
+	if (strcmp(cline, "[end]") == 0) {
+		mstore = FALSE;
+		bstore = NULL;
+		return(TRUE);
+	}
+
+	/* if macro store is on, just salt this away */
+	if (mstore) {
+		/* trim leading indentation */
+		while (cline[0] == ' ' || cline[0] == '\t')
+			strcpy(cline, &cline[1]);
+
+		/* allocate the space for the line */
+		llen = strlen(cline);
+		if ((lp=lalloc(llen)) == NULL) {
+			mlwrite("Out of memory while storing macro");
+			return (FALSE);
+		}
+
+		/* copy the text into the new line */
+		for (i=0; i<llen; ++i)
+			lputc(lp, i, cline[i]);
+
+		/* attach the line to the end of the buffer */
+       		bstore->b_linep->l_bp->l_fp = lp;
+		lp->l_bp = bstore->b_linep->l_bp;
+		bstore->b_linep->l_bp = lp;
+		lp->l_fp = bstore->b_linep;
+		return (TRUE);
+	}
+	
+	/* first set up the default command values */
+	f = FALSE;
+	n = 1;
+
+	strcpy(sarg, cline);	/* move string to string argument buffer */
+	if ((status = nxtarg(token)) != TRUE)	/* and grab the first token */
+		return(status);
+
+	/* check for and process numeric leadin argument */
+	if ((token[0] >= '0' && token[0] <= '9') || token[0] == '-') {
+		f = TRUE;
+		n = 0;
+		tp = &token[0];
+
+		/* check for a sign! */
+		sign = 1;
+		if (*tp == '-') {
+			++tp;
+			sign = -1;
+		}
+
+		/* calc up the digits in the token string */
+		while(*tp) {
+			if (*tp >= '0' && *tp <= '9')
+				n = n * 10 + *tp - '0';
+			++tp;
+		}
+		n *= sign;	/* adjust for the sign */
+
+		/* and now get the command to execute */
+		if ((status = nxtarg(token)) != TRUE)
+			return(status);		
+	}
+
+	/* and match the token to see if it exists */
+	if ((fnc = fncmatch(token)) == NULL) {
+		mlwrite("[No such Function]");
+		return(FALSE);
+	}
+	
+	/* save the arguments and go execute the command */
+	oldcle = clexec;		/* save old clexec flag */
+	clexec = TRUE;			/* in cline execution */
+	status = (*fnc)(f, n);		/* call the function */
+	clexec = oldcle;		/* restore clexec flag */
+	return(status);
+}
+
+/* gettok:	chop a token off a string
+		return a pointer past the token
+*/
+
+char *gettok(src, tok)
+
+char *src, *tok;	/* source string, destination token string */
+
+{
+	register int quotef;	/* is the current string quoted? */
+
+	/* first scan past any whitespace in the source string */
+	while (*src == ' ' || *src == '\t')
+		++src;
+
+	/* if quoted, record it */
+	quotef = (*src == '"');
+	if (quotef)
+		++src;
+
+	/* scan through the source string */
+	while (*src) {
+		/* process special characters */
+		if (*src == '~') {
+			++src;
+			if (*src == 0)
+				break;
+			switch (*src++) {
+				case 'r':	*tok++ = 13; break;
+				case 'n':	*tok++ = 10; break;
+				case 't':	*tok++ = 9;  break;
+				case 'b':	*tok++ = 8;  break;
+				case 'f':	*tok++ = 12; break;
+				case '@':	*tok++ = 192;break;
+				default:	*tok++ = *(src-1);
+			}
+		} else {
+			/* check for the end of the token */
+			if (quotef) {
+				if (*src == '"')
+					break;
+			} else {
+				if (*src == ' ' || *src == '\t')
+					break;
+			}
+
+			/* record the character */
+			*tok++ = *src++;
+		}
+	}
+
+	/* terminate the token and exit */
+	if (*src)
+		++src;
+	*tok = 0;
+	return(src);
+}
+
+/* nxtarg:	grab the next token out of sarg, return it, and
+		chop it of sarg					*/
+
+nxtarg(tok)
+
+char *tok;	/* buffer to put token into */
+
+{
+	register char *newsarg;	/* pointer to new begining of sarg */
+	register oldexec;	/* saved execution flag */
+	register BUFFER *bp;	/* ptr to buffer to get arg from */
+	register int status;
+	char *gettok();
+
+	newsarg = gettok(sarg, tok);	/* grab the token */
+	strcpy(sarg, newsarg);		/* and chop it of sarg */
+
+	/* check for an interactive argument */
+	if (*tok == '@') {		/* get interactive argument */
+		oldexec = clexec;	/* save execution flag */
+		clexec = FALSE;
+		status = mlreply(&tok[1], &tok[0], NSTRING);
+		clexec = oldexec;
+		if (status != TRUE)
+			return(status);
+	}
+
+	/* check for a quoted "@" in the first position */
+	if ((unsigned char)*tok == 192)
+		*tok = '@';
+
+	/* check for an argument from a buffer */
+	if (*tok == '#') {
+
+		/* get the referenced buffer */
+		bp = bfind(&tok[1], FALSE, 0);
+		if (bp == NULL)
+			return(FALSE);
+
+		/* make sure we are not at the end */
+		if (bp->b_linep == bp->b_dotp)
+			return(FALSE);
+
+		/* grab the line as an argument */
+		strncpy(tok, bp->b_dotp->l_text, bp->b_dotp->l_used);
+		tok[bp->b_dotp->l_used] = 0;
+
+		/* and step the buffer's line ptr ahead a line */
+		bp->b_dotp = bp->b_dotp->l_fp;
+		bp->b_doto = 0;
+	}
+
+	return(TRUE);
+}
+
+/*	storemac:	Set up a macro buffer and flag to store all
+			executed command lines there			*/
+
+storemac(f, n)
+
+int f;		/* default flag */
+int n;		/* macro number to use */
+
+{
+	register struct BUFFER *bp;	/* pointer to macro buffer */
+	char bname[NBUFN];		/* name of buffer to use */
+
+	/* must have a numeric argument to this function */
+	if (f == FALSE) {
+		mlwrite("No macro specified");
+		return(FALSE);
+	}
+
+	/* range check the macro number */
+	if (n < 1 || n > 40) {
+		mlwrite("Macro number out of range");
+		return(FALSE);
+	}
+
+	/* construct the macro buffer name */
+	strcpy(bname, "[Macro xx]");
+	bname[7] = '0' + (n / 10);
+	bname[8] = '0' + (n % 10);
+
+	/* set up the new macro buffer */
+	if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
+		mlwrite("Can not create macro");
+		return(FALSE);
+	}
+
+	/* and make sure it is empty */
+	bclear(bp);
+
+	/* and set the macro store pointers to it */
+	mstore = TRUE;
+	bstore = bp;
+	return(TRUE);
+}
+
+/*	execbuf:	Execute the contents of a buffer of commands	*/
+
+execbuf(f, n)
+
+int f, n;	/* default flag and numeric arg */
+
+{
+        register BUFFER *bp;		/* ptr to buffer to execute */
+        register int status;		/* status return */
+        char bufn[NBUFN];		/* name of buffer to execute */
+
+	/* find out what buffer the user wants to execute */
+        if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE)
+                return(status);
+
+	/* find the pointer to that buffer */
+        if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
+		mlwrite("No such buffer");
+                return(FALSE);
+        }
+
+	/* and now execute it as asked */
+	while (n-- > 0)
+		if ((status = dobuf(bp)) != TRUE)
+			return(status);
+	return(TRUE);
+}
+
+/*	dobuf:	execute the contents of the buffer pointed to
+		by the passed BP				*/
+
+dobuf(bp)
+
+BUFFER *bp;	/* buffer to execute */
+
+{
+        register int status;		/* status return */
+	register LINE *lp;		/* pointer to line to execute */
+	register LINE *hlp;		/* pointer to line header */
+	register int linlen;		/* length of line to execute */
+	register WINDOW *wp;		/* ptr to windows to scan */
+	char eline[NSTRING];		/* text of line to execute */
+
+	/* starting at the beginning of the buffer */
+	hlp = bp->b_linep;
+	lp = hlp->l_fp;
+	while (lp != hlp) {
+		/* calculate the line length and make a local copy */
+		linlen = lp->l_used;
+		if (linlen > NSTRING - 1)
+			linlen = NSTRING - 1;
+		strncpy(eline, lp->l_text, linlen);
+		eline[linlen] = 0;	/* make sure it ends */
+
+		/* if it is not a comment, execute it */
+		if (eline[0] != ';' && eline[0] != 0) {
+			status = docmd(eline);
+			if (status != TRUE) {	/* a command error */
+				/* look if buffer is showing */
+				wp = wheadp;
+				while (wp != NULL) {
+					if (wp->w_bufp == bp) {
+						/* and point it */
+						wp->w_dotp = lp;
+						wp->w_doto = 0;
+						wp->w_flag |= WFHARD;
+					}
+					wp = wp->w_wndp;
+				}
+				/* in any case set the buffer . */
+				bp->b_dotp = lp;
+				bp->b_doto = 0;
+				return(status);
+			}
+		}
+		lp = lp->l_fp;		/* on to the next line */
+	}
+        return(TRUE);
+}
+
+execfile(f, n)	/* execute a series of commands in a file
+*/
+
+int f, n;	/* default flag and numeric arg to pass on to file */
+
+{
+	register int status;	/* return status of name query */
+	char *fname[NSTRING];	/* name of file to execute */
+
+	if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE)
+		return(status);
+
+	/* otherwise, execute it */
+	while (n-- > 0)
+		if ((status=dofile(fname)) != TRUE)
+			return(status);
+
+	return(TRUE);
+}
+
+/*	dofile:	yank a file into a buffer and execute it
+		if there are no errors, delete the buffer on exit */
+
+dofile(fname)
+
+char *fname;	/* file name to execute */
+
+{
+	register BUFFER *bp;	/* buffer to place file to exeute */
+	register BUFFER *cb;	/* temp to hold current buf while we read */
+	register int status;	/* results of various calls */
+	char bname[NBUFN];	/* name of buffer */
+
+	makename(bname, fname);		/* derive the name of the buffer */
+	if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
+		return(FALSE);
+
+	bp->b_mode = MDVIEW;	/* mark the buffer as read only */
+	cb = curbp;		/* save the old buffer */
+	curbp = bp;		/* make this one current */
+	/* and try to read in the file to execute */
+	if ((status = readin(fname, FALSE)) != TRUE) {
+		curbp = cb;	/* restore the current buffer */
+		return(status);
+	}
+
+	/* go execute it! */
+	curbp = cb;		/* restore the current buffer */
+	if ((status = dobuf(bp)) != TRUE)
+		return(status);
+
+	/* if not displayed, remove the now unneeded buffer and exit */
+	if (bp->b_nwnd == 0)
+		zotbuf(bp);
+	return(TRUE);
+}
+
+/*	cbuf:	Execute the contents of a numbered buffer	*/
+
+cbuf(f, n, bufnum)
+
+int f, n;	/* default flag and numeric arg */
+int bufnum;	/* number of buffer to execute */
+
+{
+        register BUFFER *bp;		/* ptr to buffer to execute */
+        register int status;		/* status return */
+	static char bufname[] = "[Macro xx]";
+
+	/* make the buffer name */
+	bufname[7] = '0' + (bufnum / 10);
+	bufname[8] = '0' + (bufnum % 10);
+
+	/* find the pointer to that buffer */
+        if ((bp=bfind(bufname, FALSE, 0)) == NULL) {
+        	mlwrite("Macro not defined");
+                return(FALSE);
+        }
+
+	/* and now execute it as asked */
+	while (n-- > 0)
+		if ((status = dobuf(bp)) != TRUE)
+			return(status);
+	return(TRUE);
+}
+
+cbuf1(f, n)
+
+{
+	cbuf(f, n, 1);
+}
+
+cbuf2(f, n)
+
+{
+	cbuf(f, n, 2);
+}
+
+cbuf3(f, n)
+
+{
+	cbuf(f, n, 3);
+}
+
+cbuf4(f, n)
+
+{
+	cbuf(f, n, 4);
+}
+
+cbuf5(f, n)
+
+{
+	cbuf(f, n, 5);
+}
+
+cbuf6(f, n)
+
+{
+	cbuf(f, n, 6);
+}
+
+cbuf7(f, n)
+
+{
+	cbuf(f, n, 7);
+}
+
+cbuf8(f, n)
+
+{
+	cbuf(f, n, 8);
+}
+
+cbuf9(f, n)
+
+{
+	cbuf(f, n, 9);
+}
+
+cbuf10(f, n)
+
+{
+	cbuf(f, n, 10);
+}
+
+cbuf11(f, n)
+
+{
+	cbuf(f, n, 11);
+}
+
+cbuf12(f, n)
+
+{
+	cbuf(f, n, 12);
+}
+
+cbuf13(f, n)
+
+{
+	cbuf(f, n, 13);
+}
+
+cbuf14(f, n)
+
+{
+	cbuf(f, n, 14);
+}
+
+cbuf15(f, n)
+
+{
+	cbuf(f, n, 15);
+}
+
+cbuf16(f, n)
+
+{
+	cbuf(f, n, 16);
+}
+
+cbuf17(f, n)
+
+{
+	cbuf(f, n, 17);
+}
+
+cbuf18(f, n)
+
+{
+	cbuf(f, n, 18);
+}
+
+cbuf19(f, n)
+
+{
+	cbuf(f, n, 19);
+}
+
+cbuf20(f, n)
+
+{
+	cbuf(f, n, 20);
+}
+
+cbuf21(f, n)
+
+{
+	cbuf(f, n, 21);
+}
+
+cbuf22(f, n)
+
+{
+	cbuf(f, n, 22);
+}
+
+cbuf23(f, n)
+
+{
+	cbuf(f, n, 23);
+}
+
+cbuf24(f, n)
+
+{
+	cbuf(f, n, 24);
+}
+
+cbuf25(f, n)
+
+{
+	cbuf(f, n, 25);
+}
+
+cbuf26(f, n)
+
+{
+	cbuf(f, n, 26);
+}
+
+cbuf27(f, n)
+
+{
+	cbuf(f, n, 27);
+}
+
+cbuf28(f, n)
+
+{
+	cbuf(f, n, 28);
+}
+
+cbuf29(f, n)
+
+{
+	cbuf(f, n, 29);
+}
+
+cbuf30(f, n)
+
+{
+	cbuf(f, n, 30);
+}
+
+cbuf31(f, n)
+
+{
+	cbuf(f, n, 31);
+}
+
+cbuf32(f, n)
+
+{
+	cbuf(f, n, 32);
+}
+
+cbuf33(f, n)
+
+{
+	cbuf(f, n, 33);
+}
+
+cbuf34(f, n)
+
+{
+	cbuf(f, n, 34);
+}
+
+cbuf35(f, n)
+
+{
+	cbuf(f, n, 35);
+}
+
+cbuf36(f, n)
+
+{
+	cbuf(f, n, 36);
+}
+
+cbuf37(f, n)
+
+{
+	cbuf(f, n, 37);
+}
+
+cbuf38(f, n)
+
+{
+	cbuf(f, n, 38);
+}
+
+cbuf39(f, n)
+
+{
+	cbuf(f, n, 39);
+}
+
+cbuf40(f, n)
+
+{
+	cbuf(f, n, 40);
+}
+
+

Added: clients/emacs/file.c
===================================================================
--- clients/emacs/file.c	                        (rev 0)
+++ clients/emacs/file.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,503 @@
+/*
+ * The routines in this file
+ * handle the reading and writing of
+ * disk files. All of details about the
+ * reading and writing of the disk are
+ * in "fileio.c".
+ */
+#include	"estruct.h"
+#include        "edef.h"
+
+/*
+ * Read a file into the current
+ * buffer. This is really easy; all you do it
+ * find the name of the file, and call the standard
+ * "read a file into the current buffer" code.
+ * Bound to "C-X C-R".
+ */
+fileread(f, n)
+{
+        register int    s;
+        char fname[NFILEN];
+
+        if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
+                return(s);
+        return(readin(fname, TRUE));
+}
+
+/*
+ * Insert a file into the current
+ * buffer. This is really easy; all you do it
+ * find the name of the file, and call the standard
+ * "insert a file into the current buffer" code.
+ * Bound to "C-X C-I".
+ */
+insfile(f, n)
+{
+        register int    s;
+        char fname[NFILEN];
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE)
+                return(s);
+        return(ifile(fname));
+}
+
+/*
+ * Select a file for editing.
+ * Look around to see if you can find the
+ * fine in another buffer; if you can find it
+ * just switch to the buffer. If you cannot find
+ * the file, create a new buffer, read in the
+ * text, and switch to the new buffer.
+ * Bound to C-X C-F.
+ */
+filefind(f, n)
+{
+        char fname[NFILEN];	/* file user wishes to find */
+        register int s;		/* status return */
+
+        if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE)
+                return(s);
+	return(getfile(fname, TRUE));
+}
+
+viewfile(f, n)	/* visit a file in VIEW mode */
+{
+        char fname[NFILEN];	/* file user wishes to find */
+        register int s;		/* status return */
+	register WINDOW *wp;	/* scan for windows that need updating */
+
+        if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE)
+                return (s);
+	s = getfile(fname, FALSE);
+	if (s) {	/* if we succeed, put it in view mode */
+		curwp->w_bufp->b_mode |= MDVIEW;
+
+		/* scan through and update mode lines of all windows */
+		wp = wheadp;
+		while (wp != NULL) {
+			wp->w_flag |= WFMODE;
+			wp = wp->w_wndp;
+		}
+	}
+	return(s);
+}
+
+getfile(fname, lockfl)
+
+char fname[];		/* file name to find */
+int lockfl;		/* check the file for locks? */
+
+{
+        register BUFFER *bp;
+        register LINE   *lp;
+        register int    i;
+        register int    s;
+        char bname[NBUFN];	/* buffer name to put file */
+
+        for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
+                if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) {
+			swbuffer(bp);
+                        lp = curwp->w_dotp;
+                        i = curwp->w_ntrows/2;
+                        while (i-- && lback(lp)!=curbp->b_linep)
+                                lp = lback(lp);
+                        curwp->w_linep = lp;
+                        curwp->w_flag |= WFMODE|WFHARD;
+                        mlwrite("[Old buffer]");
+                        return (TRUE);
+                }
+        }
+        makename(bname, fname);                 /* New buffer name.     */
+        while ((bp=bfind(bname, FALSE, 0)) != NULL) {
+                s = mlreply("Buffer name: ", bname, NBUFN);
+                if (s == ABORT)                 /* ^G to just quit      */
+                        return (s);
+                if (s == FALSE) {               /* CR to clobber it     */
+                        makename(bname, fname);
+                        break;
+                }
+        }
+        if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
+                mlwrite("Cannot create buffer");
+                return (FALSE);
+        }
+        if (--curbp->b_nwnd == 0) {             /* Undisplay.           */
+                curbp->b_dotp = curwp->w_dotp;
+                curbp->b_doto = curwp->w_doto;
+                curbp->b_markp = curwp->w_markp;
+                curbp->b_marko = curwp->w_marko;
+        }
+        curbp = bp;                             /* Switch to it.        */
+        curwp->w_bufp = bp;
+        curbp->b_nwnd++;
+        return(readin(fname, lockfl));          /* Read it in.          */
+}
+
+/*
+ * Read file "fname" into the current
+ * buffer, blowing away any text found there. Called
+ * by both the read and find commands. Return the final
+ * status of the read. Also called by the mainline,
+ * to read in a file specified on the command line as
+ * an argument. If the filename ends in a ".c", CMODE is
+ * set for the current buffer.
+ */
+readin(fname, lockfl)
+
+char    fname[];	/* name of file to read */
+int	lockfl;		/* check for file locks? */
+
+{
+        register LINE   *lp1;
+        register LINE   *lp2;
+        register int    i;
+        register WINDOW *wp;
+        register BUFFER *bp;
+        register int    s;
+        register int    nbytes;
+        register int    nline;
+	register char	*sptr;		/* pointer into filename string */
+	int		lflag;		/* any lines longer than allowed? */
+        char            line[NLINE];
+
+#if	FILOCK
+	if (lockfl && lockchk(fname) == ABORT)
+		return(ABORT);
+#endif
+        bp = curbp;                             /* Cheap.               */
+        if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
+                return (s);
+        bp->b_flag &= ~(BFINVS|BFCHG);
+#if	ACMODE
+	if (strlen(fname) > 1) {		/* check if a 'C' file	*/
+		sptr = fname + strlen(fname) - 2;
+		if (*sptr == '.' &&
+		   (*(sptr + 1) == 'c' || *(sptr + 1) == 'h'))
+			bp->b_mode |= MDCMOD;
+	}
+#endif
+        strcpy(bp->b_fname, fname);
+        if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
+                goto out;
+        if (s == FIOFNF) {                      /* File not found.      */
+                mlwrite("[New file]");
+                goto out;
+        }
+        mlwrite("[Reading file]");
+        nline = 0;
+	lflag = FALSE;
+        while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
+		if (s == FIOLNG)
+			lflag = TRUE;
+                nbytes = strlen(line);
+                if ((lp1=lalloc(nbytes)) == NULL) {
+                        s = FIOERR;             /* Keep message on the  */
+                        break;                  /* display.             */
+                }
+                lp2 = lback(curbp->b_linep);
+                lp2->l_fp = lp1;
+                lp1->l_fp = curbp->b_linep;
+                lp1->l_bp = lp2;
+                curbp->b_linep->l_bp = lp1;
+                for (i=0; i<nbytes; ++i)
+                        lputc(lp1, i, line[i]);
+                ++nline;
+        }
+        ffclose();                              /* Ignore errors.       */
+        if (s == FIOEOF) {                      /* Don't zap message!   */
+                if (nline == 1)
+                        mlwrite("[Read 1 line]");
+                else
+                        mlwrite("[Read %d lines]", nline);
+        }
+	if (lflag)
+		mlwrite("[Read %d line(s), Long lines wrapped]",nline);
+out:
+        for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
+                if (wp->w_bufp == curbp) {
+                        wp->w_linep = lforw(curbp->b_linep);
+                        wp->w_dotp  = lforw(curbp->b_linep);
+                        wp->w_doto  = 0;
+                        wp->w_markp = NULL;
+                        wp->w_marko = 0;
+                        wp->w_flag |= WFMODE|WFHARD;
+                }
+        }
+        if (s == FIOERR || s == FIOFNF)		/* False if error.      */
+                return(FALSE);
+        return (TRUE);
+}
+
+/*
+ * Take a file name, and from it
+ * fabricate a buffer name. This routine knows
+ * about the syntax of file names on the target system.
+ * I suppose that this information could be put in
+ * a better place than a line of code.
+ */
+makename(bname, fname)
+char    bname[];
+char    fname[];
+{
+        register char   *cp1;
+        register char   *cp2;
+
+        cp1 = &fname[0];
+        while (*cp1 != 0)
+                ++cp1;
+
+#if     AMIGA
+        while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
+                --cp1;
+#endif
+#if     VMS
+        while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
+                --cp1;
+#endif
+#if     CPM
+        while (cp1!=&fname[0] && cp1[-1]!=':')
+                --cp1;
+#endif
+#if     MSDOS
+        while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
+                --cp1;
+#endif
+#if     V7 | USG | BSD
+        while (cp1!=&fname[0] && cp1[-1]!='/')
+                --cp1;
+#endif
+#if     OFW
+        while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\' && cp1[-1]!='/'
+	       && cp1[-1]!=',')
+                --cp1;
+#endif
+        cp2 = &bname[0];
+        while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
+                *cp2++ = *cp1++;
+        *cp2 = 0;
+}
+
+/*
+ * Ask for a file name, and write the
+ * contents of the current buffer to that file.
+ * Update the remembered file name and clear the
+ * buffer changed flag. This handling of file names
+ * is different from the earlier versions, and
+ * is more compatable with Gosling EMACS than
+ * with ITS EMACS. Bound to "C-X C-W".
+ */
+filewrite(f, n)
+{
+        register WINDOW *wp;
+        register int    s;
+        char            fname[NFILEN];
+
+        if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE)
+                return (s);
+        if ((s=writeout(fname)) == TRUE) {
+                strcpy(curbp->b_fname, fname);
+                curbp->b_flag &= ~BFCHG;
+                wp = wheadp;                    /* Update mode lines.   */
+                while (wp != NULL) {
+                        if (wp->w_bufp == curbp)
+                                wp->w_flag |= WFMODE;
+                        wp = wp->w_wndp;
+                }
+        }
+        return (s);
+}
+
+/*
+ * Save the contents of the current
+ * buffer in its associatd file. No nothing
+ * if nothing has changed (this may be a bug, not a
+ * feature). Error if there is no remembered file
+ * name for the buffer. Bound to "C-X C-S". May
+ * get called by "C-Z".
+ */
+filesave(f, n)
+{
+        register WINDOW *wp;
+        register int    s;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
+                return (TRUE);
+        if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
+                mlwrite("No file name");
+                return (FALSE);
+        }
+        if ((s=writeout(curbp->b_fname)) == TRUE) {
+                curbp->b_flag &= ~BFCHG;
+                wp = wheadp;                    /* Update mode lines.   */
+                while (wp != NULL) {
+                        if (wp->w_bufp == curbp)
+                                wp->w_flag |= WFMODE;
+                        wp = wp->w_wndp;
+                }
+        }
+        return (s);
+}
+
+/*
+ * This function performs the details of file
+ * writing. Uses the file management routines in the
+ * "fileio.c" package. The number of lines written is
+ * displayed. Sadly, it looks inside a LINE; provide
+ * a macro for this. Most of the grief is error
+ * checking of some sort.
+ */
+writeout(fn)
+char    *fn;
+{
+        register int    s;
+        register LINE   *lp;
+        register int    nline;
+
+        if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
+                return (FALSE);
+	mlwrite("[Writing..]");			/* tell us were writing */
+        lp = lforw(curbp->b_linep);             /* First line.          */
+        nline = 0;                              /* Number of lines.     */
+        while (lp != curbp->b_linep) {
+                if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
+                        break;
+                ++nline;
+                lp = lforw(lp);
+        }
+        if (s == FIOSUC) {                      /* No write error.      */
+                s = ffclose();
+                if (s == FIOSUC) {              /* No close error.      */
+                        if (nline == 1)
+                                mlwrite("[Wrote 1 line]");
+                        else
+                                mlwrite("[Wrote %d lines]", nline);
+                }
+        } else                                  /* Ignore close error   */
+                ffclose();                      /* if a write error.    */
+        if (s != FIOSUC)                        /* Some sort of error.  */
+                return (FALSE);
+        return (TRUE);
+}
+
+/*
+ * The command allows the user
+ * to modify the file name associated with
+ * the current buffer. It is like the "f" command
+ * in UNIX "ed". The operation is simple; just zap
+ * the name in the BUFFER structure, and mark the windows
+ * as needing an update. You can type a blank line at the
+ * prompt if you wish.
+ */
+filename(f, n)
+{
+        register WINDOW *wp;
+        register int    s;
+        char            fname[NFILEN];
+
+        if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT)
+                return (s);
+        if (s == FALSE)
+                strcpy(curbp->b_fname, "");
+        else
+                strcpy(curbp->b_fname, fname);
+        wp = wheadp;                            /* Update mode lines.   */
+        while (wp != NULL) {
+                if (wp->w_bufp == curbp)
+                        wp->w_flag |= WFMODE;
+                wp = wp->w_wndp;
+        }
+	curbp->b_mode &= ~MDVIEW;	/* no longer read only mode */
+        return (TRUE);
+}
+
+/*
+ * Insert file "fname" into the current
+ * buffer, Called by insert file command. Return the final
+ * status of the read.
+ */
+ifile(fname)
+char    fname[];
+{
+        register LINE   *lp0;
+        register LINE   *lp1;
+        register LINE   *lp2;
+        register int    i;
+        register BUFFER *bp;
+        register int    s;
+        register int    nbytes;
+        register int    nline;
+	int		lflag;		/* any lines longer than allowed? */
+        char            line[NLINE];
+
+        bp = curbp;                             /* Cheap.               */
+        bp->b_flag |= BFCHG;			/* we have changed	*/
+	bp->b_flag &= ~BFINVS;			/* and are not temporary*/
+        if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
+                goto out;
+        if (s == FIOFNF) {                      /* File not found.      */
+                mlwrite("[No such file]");
+		return(FALSE);
+        }
+        mlwrite("[Inserting file]");
+
+	/* back up a line and save the mark here */
+	curwp->w_dotp = lback(curwp->w_dotp);
+	curwp->w_doto = 0;
+	curwp->w_markp = curwp->w_dotp;
+	curwp->w_marko = 0;
+
+        nline = 0;
+	lflag = FALSE;
+        while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
+		if (s == FIOLNG)
+			lflag = TRUE;
+                nbytes = strlen(line);
+                if ((lp1=lalloc(nbytes)) == NULL) {
+                        s = FIOERR;             /* Keep message on the  */
+                        break;                  /* display.             */
+                }
+		lp0 = curwp->w_dotp;	/* line previous to insert */
+		lp2 = lp0->l_fp;	/* line after insert */
+
+		/* re-link new line between lp0 and lp2 */
+		lp2->l_bp = lp1;
+		lp0->l_fp = lp1;
+		lp1->l_bp = lp0;
+		lp1->l_fp = lp2;
+
+		/* and advance and write out the current line */
+		curwp->w_dotp = lp1;
+                for (i=0; i<nbytes; ++i)
+                        lputc(lp1, i, line[i]);
+                ++nline;
+        }
+        ffclose();                              /* Ignore errors.       */
+	curwp->w_markp = lforw(curwp->w_markp);
+        if (s == FIOEOF) {                      /* Don't zap message!   */
+                if (nline == 1)
+                        mlwrite("[Inserted 1 line]");
+                else
+                        mlwrite("[Inserted %d lines]", nline);
+        }
+	if (lflag)
+		mlwrite("[Inserted %d line(s), Long lines wrapped]",nline);
+out:
+	/* advance to the next line and mark the window for changes */
+	curwp->w_dotp = lforw(curwp->w_dotp);
+	curwp->w_flag |= WFHARD | WFMODE;
+
+	/* copy window parameters back to the buffer structure */
+	curbp->b_dotp = curwp->w_dotp;
+	curbp->b_doto = curwp->w_doto;
+	curbp->b_markp = curwp->w_markp;
+	curbp->b_marko = curwp->w_marko;
+
+        if (s == FIOERR)                        /* False if error.      */
+                return (FALSE);
+        return (TRUE);
+}

Added: clients/emacs/fileio.c
===================================================================
--- clients/emacs/fileio.c	                        (rev 0)
+++ clients/emacs/fileio.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,127 @@
+/*
+ * The routines in this file read and write ASCII files from the disk. All of
+ * the knowledge about files are here. A better message writing scheme should
+ * be used.
+ */
+#include	"stdio.h"
+#include	"estruct.h"
+#include        "edef.h"
+
+FILE    *ffp;                           /* File pointer, all functions. */
+
+/*
+ * Open a file for reading.
+ */
+ffropen(fn)
+char    *fn;
+{
+        if ((ffp=fopen(fn, "r")) == NULL)
+                return (FIOFNF);
+        return (FIOSUC);
+}
+
+/*
+ * Open a file for writing. Return TRUE if all is well, and FALSE on error
+ * (cannot create).
+ */
+ffwopen(fn)
+char    *fn;
+{
+#if     VMS
+        register int    fd;
+
+        if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
+        || (ffp=fdopen(fd, "w")) == NULL) {
+#else
+        if ((ffp=fopen(fn, "w")) == NULL) {
+#endif
+                mlwrite("Cannot open file for writing");
+                return (FIOERR);
+        }
+        return (FIOSUC);
+}
+
+/*
+ * Close a file. Should look at the status in all systems.
+ */
+ffclose()
+{
+#if	MSDOS
+	fputc(26, ffp);		/* add a ^Z at the end of the file */
+#endif
+	
+#if     V7 | USG | BSD | (MSDOS & (LATTICE | MSC))
+        if (fclose(ffp) != FALSE) {
+                mlwrite("Error closing file");
+                return(FIOERR);
+        }
+        return(FIOSUC);
+#else
+        fclose(ffp);
+        return (FIOSUC);
+#endif
+}
+
+/*
+ * Write a line to the already opened file. The "buf" points to the buffer,
+ * and the "nbuf" is its length, less the free newline. Return the status.
+ * Check only at the newline.
+ */
+ffputline(buf, nbuf)
+char    buf[];
+{
+        register int    i;
+
+        for (i = 0; i < nbuf; ++i)
+                fputc(buf[i]&0xFF, ffp);
+
+        fputc('\n', ffp);
+
+        if (ferror(ffp)) {
+                mlwrite("Write I/O error");
+                return (FIOERR);
+        }
+
+        return (FIOSUC);
+}
+
+/*
+ * Read a line from a file, and store the bytes in the supplied buffer. The
+ * "nbuf" is the length of the buffer. Complain about long lines and lines
+ * at the end of the file that don't have a newline present. Check for I/O
+ * errors too. Return status.
+ */
+ffgetline(buf, nbuf)
+register char   buf[];
+{
+        register int    c;
+        register int    i;
+
+        i = 0;
+
+        while ((c = fgetc(ffp)) != EOF && c != '\n') {
+                if (i >= nbuf-2) {
+			buf[nbuf - 2] = c;	/* store last char read */
+			buf[nbuf - 1] = 0;	/* and terminate it */
+                        mlwrite("File has long line");
+                        return (FIOLNG);
+                }
+                buf[i++] = c;
+        }
+
+        if (c == EOF) {
+                if (ferror(ffp)) {
+                        mlwrite("File read error");
+                        return (FIOERR);
+                }
+
+                if (i != 0) {
+                        mlwrite("File has funny line at EOF");
+                        return (FIOERR);
+                }
+                return (FIOEOF);
+        }
+
+        buf[i] = 0;
+        return (FIOSUC);
+}

Added: clients/emacs/hp150.c
===================================================================
--- clients/emacs/hp150.c	                        (rev 0)
+++ clients/emacs/hp150.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,361 @@
+/*
+ * The routines in this file provide support for HP150 screens
+ * and routines to access the Keyboard through KEYCODE mode.
+ * It compiles into nothing if not an HP150 screen device.
+ * added by Daniel Lawrence
+ */
+
+#define	termdef	1			/* don't define "term" external */
+
+#include        "estruct.h"
+#include	"edef.h"
+
+#if     HP150
+
+#define NROW    24                      /* Screen size.                 */
+#define NCOL    80                      /* Edit if you want to.         */
+#define	MARGIN	8			/* size of minimim margin and	*/
+#define	SCRSIZ	64			/* scroll size for extended lines */
+#define	NPAUSE	15			/* # times thru update to pause */
+#define BEL     0x07                    /* BEL character.               */
+#define ESC     0x1B                    /* ESC character.               */
+
+extern  int     openhp();               /* Forward references.          */
+extern  int     ttgetc();
+extern  int     ttputc();
+extern  int     ttflush();
+extern	int	hpflush();
+extern  int     closehp();
+extern  int     hp15move();
+extern  int     hp15eeol();
+extern  int     hp15eeop();
+extern  int     hp15beep();
+extern	int	gethpkey();
+extern	int	hp15rev();
+#if	COLOR
+extern	int	hp15fcol();
+extern	int	hp15bcol();
+#endif
+
+/* weird to ascii translation table */
+
+char trans[][2] = {
+	0x24,	9,	/* tab */
+	0x25,	13,	/* ret */
+	0x27,	8,	/* backspace */
+	0x30,	48,	/* zero */
+	0x31,	49,	/* one */
+	0x32,	50,	/* two */
+	0x33,	51,	/* three */
+	0x34,	52,	/* four */
+	0x35,	53,	/* five */
+	0x36,	54,	/* six */
+	0x37,	55,	/* seven */
+	0x38,	56,	/* eight */
+	0x39,	57,	/* nine */
+	0x50,	13,	/* enter */
+	0x54,	27,	/* break -> ESC */
+	0x55,	27,	/* esc */
+	0x58,	24,	/* stop -> ^X */
+	0x70,	45,	/* N-minus */
+	0x71,	42,	/* N-asterisk */
+	0x72,	43,	/* N-plus */
+	0x73,	47,	/* N-slash */
+	0x74,	44,	/* N-comma */
+	0x75,	13,	/* N-enter */
+	0x76,	9,	/* N-tab */
+	0x77,	46	/* N-period */
+};
+
+#define NTRANS	sizeof(trans) / 2
+
+union REGS r;		/* register set for bios and dos (AGIOS) calls */
+int capslock = 0;	/* caps lock flag */
+
+/*
+ * Standard terminal interface dispatch table. Most of the fields point into
+ * "termio" code.
+ */
+TERM    term    = {
+        NROW-1,
+        NCOL,
+	MARGIN,
+	SCRSIZ,
+	NPAUSE,
+	openhp,
+        closehp,
+	gethpkey,
+        ttputc,
+        hpflush,
+        hp15move,
+        hp15eeol,
+        hp15eeop,
+        hp15beep,
+        hp15rev
+#if	COLOR
+	, hp15fcol,
+	hp15bcol
+#endif
+};
+
+hp15move(row, col)
+{
+        ttputc(ESC);
+        ttputc('&');
+        ttputc('a');
+        hp15parm(col);
+        ttputc('c');
+        hp15parm(row);
+        ttputc('R');
+}
+
+hpflush()
+
+{
+
+}
+
+hp15eeol()
+{
+        ttputc(ESC);
+        ttputc('K');
+}
+
+hp15eeop()
+{
+        ttputc(ESC);
+        ttputc('J');
+}
+
+hp15rev(status)		/* change the reverse video status */
+
+int status;	/* TRUE = on, FALSE = off */
+
+{
+	ttputc(ESC);
+	ttputc('&');
+	ttputc('d');
+	ttputc(status ? 'B': '@');
+}
+
+hp15beep()
+{
+        ttputc(BEL);
+        ttflush();
+}
+
+hp15parm(n)
+register int    n;
+{
+        register int    q;
+
+        q = n/10;
+        if (q != 0)
+                hp15parm(q);
+        ttputc((n%10) + '0');
+}
+
+#if	COLOR
+hp15fcol()	/* we really can't do colors here, so just ignore it */
+{
+}
+
+hp15bcol()	/* we really can't do colors here, so just ignore it */
+{
+}
+#endif
+
+gethpkey()	/* get a key from the HP keyboard while in keycode mode */
+
+{
+	static int keepflag = 0;	/* kept ahead char flag */
+	static int keepchar = 0;	/* kept ehead flag */
+	int c;
+	int devid;			/* device ID */
+	int ctype;			/* type of character gotten */
+	int shiftb;			/* state of shift keys */
+	int i;
+	
+	/* if we are in an extended char sequence, finish it */
+	if (keepflag != 0) {
+		keepflag = 0;
+		return(keepchar);
+	}
+
+	/* grab the next 4 char sequence */
+next:	shiftb = ttgetc();
+	devid = ttgetc();
+	c = ttgetc();
+	ttgetc();		/* skip null byte */
+	
+	/* make sure we are from the keyboard */
+	if (devid != 192)
+		goto next;
+
+	/* if normal ascii, return it */
+	if ((shiftb & 0x80) == 0) {
+		if (capslock && c >= 'a' && c <= 'z')
+			c -= 32;
+		return(c);
+	}
+
+	/* check specifically for the caps lock key */
+	if (c == 0x56) {
+		capslock = ~capslock;
+		goto next;
+	}
+
+	/* check to see if it needs translation */
+	for (i=0; i < NTRANS; i++)
+		if (trans[i][0] == c)
+			return((int)trans[i][1]);
+
+	/* other wise, shove it in the keep char and return the leadin code */
+	keepchar = c;
+	keepflag = 1;
+	return(0);
+}
+
+openhp()		/* open the HP150 keyboard for input */
+
+{
+	revexist = TRUE;
+
+	/* define key charectoristics with AGIOS call (0, 40) */
+	defkey();
+
+	/* Turn on RAW mode with MSDOS call 44h */
+	rawon();
+
+	/* Turn off Control-C checking  MS-DOS 33h */
+	ckeyoff();
+
+	/* Turn on keycode mode with AGIOS call (0,43) */
+	keycon();
+}
+
+closehp()		/* close the HP150 keyboard for input */
+
+{
+	/* define key charectoristics with AGIOS call (0, 40) */
+	undefkey();
+	
+	/* Turn off RAW mode with MSDOS call 44h */
+	rawoff();
+
+	/* Turn on Control-C checking  MS-DOS 33h */
+	ckeyon();
+
+	/* Turn off keycode mode with AGIOS call (0,43) */
+	keycoff();
+}
+
+rawon()		/* put the HP150 keyboard into RAW mode */
+
+{
+	/* get the IO control info */
+
+	r.x.ax = 0x4400;	/* IO ctrl get device information */
+	r.x.bx = 0x0001;	/* File handle; 1 for console */
+	intdos(&r, &r);		/* go fer it */
+
+	r.h.dh = 0;		/* clear high byte for put */
+	r.h.dl |= 0x20;		/* set raw bit */
+
+	/* and put it back */
+
+	r.x.ax = 0x4401;	/* IO ctrl put device information */
+	r.x.bx = 0x0001;	/* File handle; 1 for console */
+	intdos(&r, &r);		/* go fer it */
+}
+
+rawoff()	/* put the HP150 keyboard into COOKED mode */
+
+{
+	/* get the IO control info */
+
+	r.x.ax = 0x4400;	/* IO ctrl get device information */
+	r.x.bx = 0x0001;	/* File handle; 1 for console */
+	intdos(&r, &r);		/* go fer it */
+
+	r.h.dh = 0;		/* clear high byte for put */
+	r.h.dl &= 0xdf;		/* set raw bit */
+
+	/* and put it back */
+
+	r.x.ax = 0x4401;	/* IO ctrl put device information */
+	r.x.bx = 0x0001;	/* File handle; 1 for console */
+	intdos(&r, &r);		/* go fer it */
+}
+
+
+ckeyoff()	/* turn control-C trapping off */
+
+{
+	r.h.ah = 0x33;	/* ctrl-break check */
+	r.h.al = 1;	/* set the state of the ctrl-break check */
+	r.h.dl = 0;	/* turn it off */
+	intdos(&r, &r);
+}
+
+ckeyon()	/* turn control-C trapping on */
+
+{
+	r.h.ah = 0x33;	/* ctrl-break check */
+	r.h.al = 1;	/* set the state of the ctrl-break check */
+	r.h.dl = 1;	/* turn it on */
+	intdos(&r, &r);
+}
+
+agios(buf, len)	/* perform an AGIOS call */
+
+char *buf;	/* sequence of bytes in command */
+int len;	/* length of command in bytes */
+
+{
+	r.x.ax = 0x4403;	/* I/O ctrl write */
+	r.x.bx = 1;		/* console handle */
+	r.x.cx = len;		/* buffer length */
+	r.x.dx = (unsigned)buf;	/* buffer address */
+	return(intdos(&r, &r));	/* do it */
+}
+
+keycon()	/* turn keycode mode on */
+
+{
+	static char cmd[] = {43, 0, 1};
+
+	return(agios(&cmd[0], 3));
+}
+
+keycoff()	/* turn keycode mode off */
+
+{
+	static char cmd[] = {43, 0, 0};
+
+	return(agios(&cmd[0], 3));
+}
+
+defkey()	/* change all special keys to intercept mode */
+
+{
+	static char cmd[] = {40, 0, 2, 0, 0xfe, 0};
+
+	return(agios(&cmd[0], 6));
+}
+
+undefkey()	/* change all special keys to intercept mode */
+
+{
+	static char cmd[] = {40, 0, 0, 0, 0xfe, 0};
+
+	return(agios(&cmd[0], 6));
+}
+
+#else
+
+h15hello()
+
+{
+}
+#endif

Added: clients/emacs/ibmpc.c
===================================================================
--- clients/emacs/ibmpc.c	                        (rev 0)
+++ clients/emacs/ibmpc.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,299 @@
+/*
+ * The routines in this file provide support for the IBM-PC and other
+ * compatible terminals. It goes directly to the graphics RAM to do
+ * screen output. It compiles into nothing if not an IBM-PC driver
+ */
+
+#define	termdef	1			/* don't define "term" external */
+
+#include	"estruct.h"
+#include        "edef.h"
+#ifdef __ZTC__
+#include	<dos.h>
+#endif
+
+#ifdef DOS386
+#define WORD	short
+#define SCREEN	_far
+#include <dos.h>
+#else
+#define WORD	int
+#define SCREEN
+#define far_out	movmem
+#endif
+
+#if     IBMPC
+
+#define NROW    25                      /* Screen size.                 */
+#define NCOL    80                      /* Edit if you want to.         */
+#define	MARGIN	8			/* size of minimim margin and	*/
+#define	SCRSIZ	64			/* scroll size for extended lines */
+#define	NPAUSE	200			/* # times thru update to pause */
+#define BEL     0x07                    /* BEL character.               */
+#define ESC     0x1B                    /* ESC character.               */
+#define	SPACE	32			/* space character		*/
+#define	SCADD	0xb8000000L		/* address of screen RAM	*/
+
+WORD SCREEN *scptr[NROW];		/* pointer to screen lines	*/
+WORD sline[NCOL];			/* screen line image		*/
+
+extern  int     ttopen();               /* Forward references.          */
+extern  int     ttgetc();
+extern  int     ttputc();
+extern  int     ttflush();
+extern  int     ttclose();
+extern  int     ibmmove();
+extern  int     ibmeeol();
+extern  int     ibmeeop();
+extern  int     ibmbeep();
+extern  int     ibmopen();
+extern	int	ibmrev();
+extern	int	ibmclose();
+extern	int	ibmputc();
+
+#if	COLOR
+extern	int	ibmfcol();
+extern	int	ibmbcol();
+
+int	cfcolor = -1;		/* current forground color */
+int	cbcolor = -1;		/* current background color */
+int	ctrans[] =		/* ansi to ibm color translation table */
+	{0, 4, 2, 6, 1, 5, 3, 7};
+#endif
+
+/*
+ * Standard terminal interface dispatch table. Most of the fields point into
+ * "termio" code.
+ */
+TERM    term    = {
+        NROW-1,
+        NCOL,
+	MARGIN,
+	SCRSIZ,
+	NPAUSE,
+        ibmopen,
+        ibmclose,
+        ttgetc,
+	ibmputc,
+        ttflush,
+        ibmmove,
+        ibmeeol,
+        ibmeeop,
+        ibmbeep,
+	ibmrev
+#if	COLOR
+	, ibmfcol,
+	ibmbcol
+#endif
+};
+
+extern union REGS rg;
+
+#if	COLOR
+ibmfcol(color)		/* set the current output color */
+
+int color;	/* color to set */
+
+{
+	cfcolor = ctrans[color];
+}
+
+ibmbcol(color)		/* set the current background color */
+
+int color;	/* color to set */
+
+{
+        cbcolor = ctrans[color];
+}
+#endif
+
+ibmmove(row, col)
+{
+	rg.h.ah = 2;		/* set cursor position function code */
+	rg.h.dl = col;
+	rg.h.dh = row;
+	rg.h.bh = 0;		/* set screen page number */
+	int86(0x10, &rg, &rg);
+}
+
+ibmeeol()	/* erase to the end of the line */
+
+{
+	int attr;	/* attribute byte mask to place in RAM */
+	WORD *lnptr;	/* pointer to the destination line */
+	int i;
+	int ccol;	/* current column cursor lives */
+	int crow;	/*	   row	*/
+
+	/* find the current cursor position */
+	rg.h.ah = 3;		/* read cursor position function code */
+	rg.h.bh = 0;		/* current video page */
+	int86(0x10, &rg, &rg);
+	ccol = rg.h.dl;		/* record current column */
+	crow = rg.h.dh;		/* and row */
+
+	/* build the attribute byte and setup the screen pointer */
+#if	COLOR
+	attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
+#else
+	attr = 0x0700;
+#endif
+	lnptr = &sline[0];
+	for (i=0; i < NCOL; i++)
+		*lnptr++ = SPACE | attr;
+
+	/* wait for vertical retrace to be off */
+	while ((inp(0x3da) & 8))
+		;
+
+	/* and to be back on */
+	while ((inp(0x3da) & 8) == 0)
+		;
+
+	/* and send the string out */
+	far_out(&sline[0], scptr[crow]+ccol, (NCOL-ccol)*2);
+
+}
+
+ibmputc(ch)	/* put a character at the current position in the
+		   current colors */
+
+int ch;
+
+{
+	rg.h.ah = 14;		/* write char to screen with current attrs */
+	rg.h.al = ch;
+#if	COLOR
+	rg.h.bl = cfcolor;
+#else
+	rg.h.bl = 0x07;
+#endif
+	int86(0x10, &rg, &rg);
+}
+
+ibmeeop()
+{
+	int attr;		/* attribute to fill screen with */
+
+	rg.h.ah = 6;		/* scroll page up function code */
+	rg.h.al = 0;		/* # lines to scroll (clear it) */
+	rg.x.cx = 0;		/* upper left corner of scroll */
+	rg.x.dx = 0x174f;	/* lower right corner of scroll */
+#if	COLOR
+	attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
+#else
+	attr = 0;
+#endif
+	rg.h.bh = attr;
+	int86(0x10, &rg, &rg);
+}
+
+ibmrev(state)		/* change reverse video state */
+
+int state;	/* TRUE = reverse, FALSE = normal */
+
+{
+	/* This never gets used under the IBM-PC driver */
+}
+
+ibmbeep()
+{
+	bdos(6, BEL, 0);
+}
+
+ibmopen()
+{
+	scinit();
+	revexist = TRUE;
+        ttopen();
+}
+
+ibmclose()
+
+{
+#if	COLOR
+	ibmfcol(7);
+	ibmbcol(0);
+#endif
+	ttclose();
+}
+
+scinit()	/* initialize the screen head pointers */
+
+{
+	union {
+		long laddr;	/* long form of address */
+		int *paddr;	/* pointer form of address */
+	} addr;
+	int i;
+
+#ifdef DOS386
+	scptr[0] = (short _far *)_x386_mk_protected_ptr(SCADD >> 12);
+
+	/* Coerce the selector to the current privilege level */
+	scptr[0] = MK_FP(FP_SEG(scptr[0]) | (getDS() & 3), FP_OFF(scptr[0]));
+
+	for (i = 1; i < NROW; i++)
+		scptr[i] = scptr[i-1] + NCOL;
+#else
+	/* initialize the screen pointer array */
+	for (i = 0; i < NROW; i++) {
+		addr.laddr = SCADD + (long)(NCOL * i * 2);
+		scptr[i] = addr.paddr;
+	}
+#endif
+
+}
+
+scwrite(row, outstr, forg, bacg)	/* write a line out*/
+
+int row;	/* row of screen to place outstr on */
+char *outstr;	/* string to write out (must be NCOL long) */
+int forg;	/* forground color of string to write */
+int bacg;	/* background color */
+
+{
+	int attr;	/* attribute byte mask to place in RAM */
+	WORD *lnptr;	/* pointer to the destination line */
+	int i;
+
+	/* build the attribute byte and setup the screen pointer */
+#if	COLOR
+	attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
+#else
+	attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
+#endif
+	lnptr = &sline[0];
+	for (i=0; i<NCOL; i++)
+		*lnptr++ = (outstr[i] & 255) | attr;
+
+	/* wait for vertical retrace to be off */
+	while ((inp(0x3da) & 8))
+		;
+
+	/* and to be back on */
+	while ((inp(0x3da) & 8) == 0)
+		;
+
+	/* and send the string out */
+	far_out(&sline[0], scptr[row],NCOL*2);
+}
+#ifdef DOS386
+far_out(source, dest, size)
+
+char *source;	/* mem location to move memory from */
+char _far *dest;	/* memory location to move text to */
+int size;	/* number of bytes to move */
+
+{
+	register int i;
+
+	for (i=0; i < size; i++)
+		*dest++ = *source++;
+}
+#endif
+#else
+ibmhello()
+{
+}
+#endif

Added: clients/emacs/input.c
===================================================================
--- clients/emacs/input.c	                        (rev 0)
+++ clients/emacs/input.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,507 @@
+/*	INPUT:	Various input routines for MicroEMACS 3.7
+		written by Daniel Lawrence
+		5/9/86						*/
+
+#include	"estruct.h"
+#include	"edef.h"
+
+/*
+ * Ask a yes or no question in the message line. Return either TRUE, FALSE, or
+ * ABORT. The ABORT status is returned if the user bumps out of the question
+ * with a ^G. Used any time a confirmation is required.
+ */
+
+mlyesno(prompt)
+
+char *prompt;
+
+{
+	char c;			/* input character */
+	char buf[NPAT];		/* prompt to user */
+
+	for (;;) {
+		/* build and prompt the user */
+		strcpy(buf, prompt);
+		strcat(buf, " [y/n]? ");
+		mlwrite(buf);
+
+		/* get the responce */
+		c = (*term.t_getchar)();
+
+		if (c == BELL)		/* Bail out! */
+			return(ABORT);
+
+		if (c=='y' || c=='Y')
+			return(TRUE);
+
+		if (c=='n' || c=='N')
+			return(FALSE);
+	}
+}
+
+/*
+ * Write a prompt into the message line, then read back a response. Keep
+ * track of the physical position of the cursor. If we are in a keyboard
+ * macro throw the prompt away, and return the remembered response. This
+ * lets macros run at full speed. The reply is always terminated by a carriage
+ * return. Handle erase, kill, and abort keys.
+ */
+
+mlreply(prompt, buf, nbuf)
+    char *prompt;
+    char *buf;
+{
+	return(mlreplyt(prompt,buf,nbuf,'\n'));
+}
+
+/*	A more generalized prompt/reply function allowing the caller
+	to specify the proper terminator. If the terminator is not
+	a return ('\n') it will echo as "<NL>"
+							*/
+mlreplyt(prompt, buf, nbuf, eolchar)
+
+char *prompt;
+char *buf;
+char eolchar;
+
+{
+	register int cpos;	/* current character position in string */
+	register int i;
+	register int c;
+	register int quotef;	/* are we quoting the next char? */
+	register int status;	/* status return value */
+
+
+	cpos = 0;
+	quotef = FALSE;
+
+	if (kbdmop != NULL) {
+		while ((c = *kbdmop++) != '\0')
+			buf[cpos++] = c;
+
+		buf[cpos] = 0;
+
+		if (buf[0] == 0)
+			return(FALSE);
+
+		return(TRUE);
+	}
+
+	/* check to see if we are executing a command line */
+	if (clexec) {
+		status = nxtarg(buf);
+		buf[nbuf-1] = 0;	/* make sure we null terminate it */
+		return(status);
+	}
+
+	mlwrite(prompt);
+
+	for (;;) {
+	/* get a character from the user. if it is a <ret>, change it
+	   to a <NL>							*/
+		c = (*term.t_getchar)();
+		if (c == 0x0d)
+			c = '\n';
+
+		if (c == eolchar && quotef == FALSE) {
+			buf[cpos++] = 0;
+
+			if (kbdmip != NULL) {
+				if (kbdmip+cpos > &kbdm[NKBDM-3]) {
+					ctrlg(FALSE, 0);
+					(*term.t_flush)();
+					return(ABORT);
+				}
+
+				for (i=0; i<cpos; ++i)
+					*kbdmip++ = buf[i];
+				}
+
+				(*term.t_move)(term.t_nrow, 0);
+				ttcol = 0;
+				(*term.t_flush)();
+
+				if (buf[0] == 0)
+					return(FALSE);
+
+				return(TRUE);
+
+			} else if (c == 0x07 && quotef == FALSE) {
+				/* Bell, abort */
+				(*term.t_putchar)('^');
+				(*term.t_putchar)('G');
+				ttcol += 2;
+				ctrlg(FALSE, 0);
+				(*term.t_flush)();
+				return(ABORT);
+
+			} else if ((c==0x7F || c==0x08) && quotef==FALSE) {
+				/* rubout/erase */
+				if (cpos != 0) {
+					(*term.t_putchar)('\b');
+					(*term.t_putchar)(' ');
+					(*term.t_putchar)('\b');
+					--ttcol;
+
+					if (buf[--cpos] < 0x20) {
+						(*term.t_putchar)('\b');
+						(*term.t_putchar)(' ');
+						(*term.t_putchar)('\b');
+						--ttcol;
+					}
+
+					if (buf[cpos] == '\n') {
+						(*term.t_putchar)('\b');
+						(*term.t_putchar)('\b');
+						(*term.t_putchar)(' ');
+						(*term.t_putchar)(' ');
+						(*term.t_putchar)('\b');
+						(*term.t_putchar)('\b');
+						--ttcol;
+						--ttcol;
+					}
+
+					(*term.t_flush)();
+				}
+
+			} else if (c == 0x15 && quotef == FALSE) {
+				/* C-U, kill */
+				while (cpos != 0) {
+					(*term.t_putchar)('\b');
+					(*term.t_putchar)(' ');
+					(*term.t_putchar)('\b');
+					--ttcol;
+
+					if (buf[--cpos] < 0x20) {
+						(*term.t_putchar)('\b');
+						(*term.t_putchar)(' ');
+						(*term.t_putchar)('\b');
+						--ttcol;
+					}
+				}
+
+				(*term.t_flush)();
+
+			} else if (c == quotec && quotef == FALSE) {
+				quotef = TRUE;
+			} else {
+				quotef = FALSE;
+				if (cpos < nbuf-1) {
+					buf[cpos++] = c;
+
+					if ((c < ' ') && (c != '\n')) {
+						(*term.t_putchar)('^');
+						++ttcol;
+						c ^= 0x40;
+					}
+
+					if (c != '\n')
+						(*term.t_putchar)(c);
+					else {	/* put out <NL> for <ret> */
+						(*term.t_putchar)('<');
+						(*term.t_putchar)('N');
+						(*term.t_putchar)('L');
+						(*term.t_putchar)('>');
+						ttcol += 3;
+					}
+				++ttcol;
+				(*term.t_flush)();
+			}
+		}
+	}
+}
+
+/* get a command name from the command line. Command completion means
+   that pressing a <SPACE> will attempt to complete an unfinished command
+   name if it is unique.
+*/
+
+int (*getname())()
+
+{
+	register int cpos;	/* current column on screen output */
+	register int c;
+	register char *sp;	/* pointer to string for output */
+	register NBIND *ffp;	/* first ptr to entry in name binding table */
+	register NBIND *cffp;	/* current ptr to entry in name binding table */
+	register NBIND *lffp;	/* last ptr to entry in name binding table */
+	char buf[NSTRING];	/* buffer to hold tentative command name */
+	int (*fncmatch())();
+
+	/* starting at the begining of the string buffer */
+	cpos = 0;
+
+	/* if we are executing a keyboard macro, fill our buffer from there,
+	   and attempt a straight match */
+	if (kbdmop != NULL) {
+		while ((c = *kbdmop++) != '\0')
+			buf[cpos++] = c;
+
+		buf[cpos] = 0;
+
+		/* return the result of a match */
+		return(fncmatch(&buf[0]));
+	}
+
+	/* if we are executing a command line get the next arg and match it */
+	if (clexec) {
+		if (nxtarg(buf) != TRUE)
+			return(FALSE);
+		return(fncmatch(&buf[0]));
+	}
+
+	/* build a name string from the keyboard */
+	while (TRUE) {
+		c = (*term.t_getchar)();
+
+		/* if we are at the end, just match it */
+		if (c == 0x0d) {
+			buf[cpos] = 0;
+
+			/* save keyboard macro string if needed */
+			if (kbdtext(&buf[0]) == ABORT)
+				return( (int (*)()) NULL);
+
+			/* and match it off */
+			return(fncmatch(&buf[0]));
+
+		} else if (c == 0x07) {	/* Bell, abort */
+			(*term.t_putchar)('^');
+			(*term.t_putchar)('G');
+			ttcol += 2;
+			ctrlg(FALSE, 0);
+			(*term.t_flush)();
+			return( (int (*)()) NULL);
+
+		} else if (c == 0x7F || c == 0x08) {	/* rubout/erase */
+			if (cpos != 0) {
+				(*term.t_putchar)('\b');
+				(*term.t_putchar)(' ');
+				(*term.t_putchar)('\b');
+				--ttcol;
+				--cpos;
+				(*term.t_flush)();
+			}
+
+		} else if (c == 0x15) {	/* C-U, kill */
+			while (cpos != 0) {
+				(*term.t_putchar)('\b');
+				(*term.t_putchar)(' ');
+				(*term.t_putchar)('\b');
+				--cpos;
+				--ttcol;
+			}
+
+			(*term.t_flush)();
+
+		} else if (c == ' ') {
+/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
+	/* attempt a completion */
+	buf[cpos] = 0;		/* terminate it for us */
+	ffp = &names[0];	/* scan for matches */
+	while (ffp->n_func != NULL) {
+		if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) {
+			/* a possible match! More than one? */
+			if ((ffp + 1)->n_func == NULL ||
+			   (strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0)) {
+				/* no...we match, print it */
+				sp = ffp->n_name + cpos;
+				while (*sp)
+					(*term.t_putchar)(*sp++);
+				(*term.t_flush)();
+				return(ffp->n_func);
+			} else {
+/* << << << << << << << << << << << << << << << << << */
+	/* try for a partial match against the list */
+
+	/* first scan down until we no longer match the current input */
+	lffp = (ffp + 1);
+	while ((lffp+1)->n_func != NULL) {
+		if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0)
+			break;
+		++lffp;
+	}
+
+	/* and now, attempt to partial complete the string, char at a time */
+	while (TRUE) {
+		/* add the next char in */
+		buf[cpos] = ffp->n_name[cpos];
+
+		/* scan through the candidates */
+		cffp = ffp + 1;
+		while (cffp <= lffp) {
+			if (cffp->n_name[cpos] != buf[cpos])
+				goto onward;
+			++cffp;
+		}
+
+		/* add the character */
+		(*term.t_putchar)(buf[cpos++]);
+	}
+/* << << << << << << << << << << << << << << << << << */
+			}
+		}
+		++ffp;
+	}
+
+	/* no match.....beep and onward */
+	(*term.t_beep)();
+onward:;
+	(*term.t_flush)();
+/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
+		} else {
+			if (cpos < NSTRING-1 && c > ' ') {
+				buf[cpos++] = c;
+				(*term.t_putchar)(c);
+			}
+
+			++ttcol;
+			(*term.t_flush)();
+		}
+	}
+}
+
+kbdtext(buf)	/* add this text string to the current keyboard macro
+		   definition						*/
+
+char *buf;	/* text to add to keyboard macro */
+
+{
+	/* if we are defining a keyboard macro, save it */
+	if (kbdmip != NULL) {
+		if (kbdmip+strlen(buf) > &kbdm[NKBDM-4]) {
+			ctrlg(FALSE, 0);
+			(*term.t_flush)();
+			return(ABORT);
+		}
+
+		/* copy string in and null terminate it */
+		while (*buf)
+			*kbdmip++ = *buf++;
+		*kbdmip++ = 0;
+	}
+	return(TRUE);
+}
+
+/*	GET1KEY:	Get one keystroke. The only prefixs legal here
+			are the SPEC and CTRL prefixes.
+								*/
+
+get1key()
+
+{
+	int    c;
+#if	AMIGA
+	int	d;
+#endif
+
+	/* get a keystroke */
+        c = (*term.t_getchar)();
+#if 0
+        (*term.t_putchar)("0123456789abcdef"[(c>>4)&0xf]);
+        (*term.t_putchar)("0123456789abcdef"[c&0xf]);
+        (*term.t_putchar)('\r');
+        (*term.t_putchar)('\n');
+#endif
+
+#if RAINBOW
+
+        if (c & Function_Key)
+                {
+                int i;
+
+                for (i = 0; i < lk_map_size; i++)
+                        if (c == lk_map[i][0])
+                                return lk_map[i][1];
+                }
+        else if (c == Shift + 015) return CTRL | 'J';
+        else if (c == Shift + 0x7F) return META | 0x7F;
+#endif
+
+#if	MSDOS
+	if (c == 0) {				/* Apply SPEC prefix	*/
+	        c = (*term.t_getchar)();
+	        if (c>=0x00 && c<=0x1F)		/* control key? */
+        	        c = CTRL | (c+'@');
+		return(SPEC | c);
+	}
+#endif
+
+#if	AMIGA
+	/* apply SPEC prefix */
+	if ((unsigned)c == 155) {
+		c = (*term.t_getchar)();
+
+		/* first try to see if it is a cursor key */
+		if ((c >= 'A' && c <= 'D') || c == 'S' || c == 'T')
+			return(SPEC | c);
+
+		/* next, a 2 char sequence */
+		d = (*term.t_getchar)();
+		if (d == '~')
+			return(SPEC | c);
+
+		/* decode a 3 char sequence */
+		c = d + 32;
+		/* if a shifted function key, eat the tilde */
+		if (d >= '0' && d <= '9')
+			d = (*term.t_getchar)();
+		return(SPEC | c);
+	}
+#endif
+
+#if  WANGPC
+	if (c == 0x1F) {			/* Apply SPEC prefix    */
+	        c = (*term.t_getchar)();
+		return(SPEC | c);
+	}
+#endif
+
+#if	OFW
+	if (c == 0x9b) {			/* Apply SPEC prefix	*/
+	        c = (*term.t_getchar)();
+		if (c == 'O')			/* Function key		*/
+		    c = (*term.t_getchar)();
+		return(SPEC | c);
+	}
+#endif
+
+        if (c>=0x00 && c<=0x1F)                 /* C0 control -> C-     */
+                c = CTRL | (c+'@');
+        return (c);
+}
+
+/*	GETCMD:	Get a command from the keyboard. Process all applicable
+		prefix keys
+							*/
+getcmd()
+
+{
+	int c;		/* fetched keystroke */
+
+	/* get initial character */
+	c = get1key();
+
+	/* process META prefix */
+	if (c == metac) {
+		c = get1key();
+	        if (c>='a' && c<='z')		/* Force to upper */
+        	        c -= 0x20;
+	        if (c>=0x00 && c<=0x1F)		/* control key */
+	        	c = CTRL | (c+'@');
+		return(META | c);
+	}
+
+	/* process CTLX prefix */
+	if (c == ctlxc) {
+		c = get1key();
+	        if (c>='a' && c<='z')		/* Force to upper */
+        	        c -= 0x20;
+	        if (c>=0x00 && c<=0x1F)		/* control key */
+	        	c = CTRL | (c+'@');
+		return(CTLX | c);
+	}
+
+	/* otherwise, just return it */
+	return(c);
+}

Added: clients/emacs/isearch.c
===================================================================
--- clients/emacs/isearch.c	                        (rev 0)
+++ clients/emacs/isearch.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,543 @@
+/*
+ * The functions in this file implement commands that perform incremental
+ * searches in the forward and backward directions.  This "ISearch" command
+ * is intended to emulate the same command from the original EMACS 
+ * implementation (ITS).  Contains references to routines internal to
+ * SEARCH.C.
+ *
+ * REVISION HISTORY:
+ *
+ *	D. R. Banks 9-May-86
+ *	- added ITS EMACSlike ISearch
+ */
+
+#include	"estruct.h"
+#include        "edef.h"
+
+/*	string search input parameters	*/
+
+#define	PTBEG	1	/* leave the point at the beginning on search */
+#define	PTEND	2	/* leave the point at the end on search */
+
+#define	CMDBUFLEN 256	/* Length of our command buffer */
+
+extern int forscan();			/* Handy search routine */
+extern int eq();			/* Compare chars, match case */
+
+/* A couple of "own" variables for re-eat */
+
+int	(*saved_get_char)();		/* Get character routine */
+int	eaten_char = -1;		/* Re-eaten char */
+
+/* A couple more "own" variables for the command string */
+
+char	cmd_buff[CMDBUFLEN];	/* Save the command args here */
+int	cmd_offset;			/* Current offset into command buff */
+int	cmd_reexecute = -1;		/* > 0 if re-executing command */
+
+/* Some character constants within ISearch */
+
+#define	IS_ABORT	0x07	/* Abort the isearch */
+#define IS_BACKSP	0x08	/* Delete previous char */
+#define	IS_TAB		0x09	/* Tab character (allowed search char) */
+#define IS_NEWLINE	0x0D	/* New line from keyboard (Carriage return) */
+#define	IS_QUOTE	0x11	/* Quote next character */
+#define IS_REVERSE	0x12	/* Search backward */
+#define	IS_FORWARD	0x13	/* Search forward */
+#define	IS_VMSQUOTE	0x16	/* VMS quote character */
+#define	IS_VMSFORW	0x18	/* Search forward for VMS */
+#define	IS_QUIT		0x1B	/* Exit the search */
+#define	IS_RUBOUT	0x7F	/* Delete previous character */
+
+/*
+ * Subroutine to do incremental reverse search.  It actually uses the
+ * same code as the normal incremental search, as both can go both ways.
+ */
+ 
+int risearch(f, n)
+{
+    LINE *curline;			/* Current line on entry	      */
+    int  curoff;			/* Current offset on entry	      */
+
+    /* remember the initial . on entry: */
+
+    curline = curwp->w_dotp;		/* Save the current line pointer      */
+    curoff  = curwp->w_doto;		/* Save the current offset	      */
+
+    /* Make sure the search doesn't match where we already are:		      */
+
+    backchar(TRUE, 1);			/* Back up a character		      */
+
+    if (!(isearch(f, -n)))		/* Call ISearch backwards	      */
+    {					/* If error in search:		      */
+	curwp->w_dotp = curline;	/* Reset the line pointer	      */
+	curwp->w_doto = curoff;		/*  and the offset to original value  */
+	curwp->w_flag |= WFMOVE;	/* Say we've moved		      */
+	update(FALSE);			/* And force an update		      */
+	mlwrite ("[search failed]");	/* Say we died			      */
+    } else mlerase ();			/* If happy, just erase the cmd line  */
+}
+
+/* Again, but for the forward direction */
+
+int fisearch(f, n)
+{
+    LINE *curline;			/* Current line on entry	      */
+    int  curoff;			/* Current offset on entry	      */
+
+    /* remember the initial . on entry: */
+
+    curline = curwp->w_dotp;		/* Save the current line pointer      */
+    curoff  = curwp->w_doto;		/* Save the current offset	      */
+
+    /* do the search */
+
+    if (!(isearch(f, n)))		/* Call ISearch forwards	      */
+    {					/* If error in search:		      */
+	curwp->w_dotp = curline;	/* Reset the line pointer	      */
+	curwp->w_doto = curoff;		/*  and the offset to original value  */
+	curwp->w_flag |= WFMOVE;	/* Say we've moved		      */
+	update(FALSE);			/* And force an update		      */
+	mlwrite ("[search failed]");	/* Say we died			      */
+    } else mlerase ();			/* If happy, just erase the cmd line  */
+}
+
+/*
+ * Subroutine to do an incremental search.  In general, this works similarly
+ * to the older micro-emacs search function, except that the search happens
+ * as each character is typed, with the screen and cursor updated with each
+ * new search character.
+ *
+ * While searching forward, each successive character will leave the cursor
+ * at the end of the entire matched string.  Typing a Control-S or Control-X
+ * will cause the next occurrence of the string to be searched for (where the
+ * next occurrence does NOT overlap the current occurrence).  A Control-R will
+ * change to a backwards search, ESC will terminate the search and Control-G
+ * will abort the search.  Rubout will back up to the previous match of the
+ * string, or if the starting point is reached first, it will delete the
+ * last character from the search string.
+ *
+ * While searching backward, each successive character will leave the cursor
+ * at the beginning of the matched string.  Typing a Control-R will search
+ * backward for the next occurrence of the string.  Control-S or Control-X
+ * will revert the search to the forward direction.  In general, the reverse
+ * incremental search is just like the forward incremental search inverted.
+ *
+ * In all cases, if the search fails, the user will be feeped, and the search
+ * will stall until the pattern string is edited back into something that
+ * exists (or until the search is aborted).
+ */
+ 
+isearch(f, n)
+{
+    int			status;		/* Search status */
+    int			col;		/* prompt column */
+    register int	cpos;		/* character number in search string  */
+    register int	c;		/* current input character */
+    char		pat_save[NPAT];	/* Saved copy of the old pattern str  */
+    LINE		*curline;	/* Current line on entry	      */
+    int			curoff;		/* Current offset on entry	      */
+    int			init_direction;	/* The initial search direction	      */
+
+    /* Initialize starting conditions */
+
+    cmd_reexecute = -1;		/* We're not re-executing (yet?)      */
+    cmd_offset = 0;			/* Start at the beginning of the buff */
+    cmd_buff[0] = '\0';		/* Init the command buffer	      */
+    strncpy (pat_save, pat, NPAT);	/* Save the old pattern string	      */
+    curline = curwp->w_dotp;		/* Save the current line pointer      */
+    curoff  = curwp->w_doto;		/* Save the current offset	      */
+    init_direction = n;			/* Save the initial search direction  */
+
+    /* This is a good place to start a re-execution: */
+
+start_over:
+
+    /* ask the user for the text of a pattern */
+    col = promptpattern("ISearch: ");		/* Prompt, remember the col   */
+
+    cpos = 0;					/* Start afresh		      */
+    status = TRUE;				/* Assume everything's cool   */
+
+    /*
+       Get the first character in the pattern.  If we get an initial Control-S
+       or Control-R, re-use the old search string and find the first occurrence
+     */
+
+    c = get_char();				/* Get the first character    */
+    if ((c == IS_FORWARD) ||
+        (c == IS_REVERSE) ||
+        (c == IS_VMSFORW))			/* Reuse old search string?   */
+    {
+    	for (cpos = 0; pat[cpos] != 0; cpos++)	/* Yup, find the length	      */
+    	    col = echochar(pat[cpos],col);	/*  and re-echo the string    */
+	if (c == IS_REVERSE) {			/* forward search?	      */
+	    n = -1;				/* No, search in reverse      */
+	    backchar (TRUE, 1);			/* Be defensive about EOB     */
+	} else
+	    n = 1;				/* Yes, search forward	      */
+	status = scanmore(pat,n,status);	/* Do the search	      */
+	c = get_char ();			/* Get another character      */
+    }
+
+    /* Top of the per character loop */
+        	
+    for (;;)					/* ISearch per character loop */
+    {
+	/* Check for magic characters first: */
+	/* Most cases here change the search */
+
+	switch (c)				/* dispatch on the input char */
+	{
+	  case IS_ABORT:			/* If abort search request    */
+	    return(FALSE);			/* Quit searching again	      */
+
+	  case IS_REVERSE:			/* If backward search	      */
+	  case IS_FORWARD:			/* If forward search	      */
+	  case IS_VMSFORW:			/*  of either flavor	      */
+	    if (c == IS_REVERSE)		/* If reverse search	      */
+		n = -1;				/* Set the reverse direction  */
+	    else				/* Otherwise, 		      */
+		n = 1;				/*  go forward		      */
+	    status = scanmore(pat,n,TRUE);	/* Start the search again     */
+	    c = get_char ();			/* Get the next char	      */
+	    continue;				/* Go continue with the search*/
+
+	  case IS_QUIT:				/* Want to quit searching?    */
+	    return (TRUE);			/* Quit searching now	      */
+
+	  case IS_NEWLINE:			/* Carriage return	      */
+	    c = '\n';				/* Make it a new line	      */
+	    break;				/* Make sure we use it	      */
+
+	  case IS_QUOTE:			/* Quote character	      */
+	  case IS_VMSQUOTE:			/*  of either variety	      */
+	    c = get_char ();			/* Get the next char	      */
+
+	  case IS_TAB:				/* Generically allowed	      */
+	  case '\n':				/*  controlled characters     */
+	    break;				/* Make sure we use it	      */
+
+	  case IS_BACKSP:			/* If a backspace:            */
+	  case IS_RUBOUT:			/*  or if a Rubout:	      */
+	    if (cmd_offset <= 1)		/* Anything to delete?	      */
+		return (TRUE);			/* No, just exit	      */
+	    --cmd_offset;			/* Back up over the Rubout    */
+	    cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char   */
+	    curwp->w_dotp = curline;		/* Reset the line pointer     */
+	    curwp->w_doto = curoff;		/*  and the offset	      */
+	    n = init_direction;			/* Reset the search direction */
+	    strncpy (pat, pat_save, NPAT);	/* Restore the old search str */
+	    cmd_reexecute = 0;		/* Start the whole mess over  */
+	    goto start_over;			/* Let it take care of itself */
+
+	  /* Presumably a quasi-normal character comes here */
+
+	  default:				/* All other chars    	      */
+	    if (c < ' ')			/* Is it printable?	      */
+	    {					/* Nope.		      */
+		reeat (c);			/* Re-eat the char	      */
+		return (TRUE);			/* And return the last status */
+	    }
+	}  /* Switch */
+
+	/* I guess we got something to search for, so search for it	      */
+
+	pat[cpos++] = c;			/* put the char in the buffer */
+	if (cpos >= NPAT)			/* too many chars in string?  */
+	{					/* Yup.  Complain about it    */
+	    mlwrite("? Search string too long");
+	    return(TRUE);			/* Return an error	      */
+	}
+	pat[cpos] = 0;				/* null terminate the buffer  */
+	col = echochar(c,col);			/* Echo the character	      */
+	if (!status) {				/* If we lost last time	      */
+	    (*term.t_putchar)(BELL);		/* Feep again		      */
+	    (*term.t_flush)();			/* see that the feep feeps    */
+	} else					/* Otherwise, we must have won*/
+	    if (!(status = checknext(c,pat,n,status))) /* See if match	      */
+		status = scanmore(pat,n,TRUE);	/*  or find the next match    */
+	c = get_char ();			/* Get the next char	      */
+    } /* for {;;} */
+}
+
+/*
+ * Trivial routine to insure that the next character in the search string is
+ * still true to whatever we're pointing to in the buffer.  This routine will
+ * not attempt to move the "point" if the match fails, although it will 
+ * implicitly move the "point" if we're forward searching, and find a match,
+ * since that's the way forward isearch works.
+ *
+ * If the compare fails, we return FALSE and assume the caller will call
+ * scanmore or something.
+ */
+
+int checknext (chr, patrn, dir, sts)/* Check next character in search string */
+char	chr;			/* Next char to look for		 */
+char	*patrn;			/* The entire search string (incl chr)   */
+int	dir;			/* Search direction			 */
+int	sts;			/* Search status			 */
+{
+    register LINE *curline;		/* current line during scan	      */
+    register int curoff;		/* position within current line	      */
+    register int buffchar;		/* character at current position      */
+    int status;				/* how well things go		      */
+
+    if (!sts) return(FALSE);		/* Don't try unless ok so far	      */
+
+    /* setup the local scan pointer to current "." */
+
+    curline = curwp->w_dotp;		/* Get the current line structure     */
+    curoff  = curwp->w_doto;		/* Get the offset within that line    */
+
+    if (dir > 0)			/* If searching forward		      */
+    {
+    	if (curoff == llength(curline)) /* If at end of line		      */
+    	{
+	    curline = lforw(curline);	/* Skip to the next line	      */
+	    if (curline == curbp->b_linep)
+		return (FALSE);		/* Abort if at end of buffer	      */
+	    curoff = 0;			/* Start at the beginning of the line */
+	    buffchar = '\n';		/* And say the next char is NL	      */
+	} else
+	    buffchar = lgetc(curline, curoff++); /* Get the next char	      */
+	if (status = eq(buffchar, chr))	/* Is it what we're looking for?      */
+	{
+	    curwp->w_dotp = curline;	/* Yes, set the buffer's point	      */
+	    curwp->w_doto = curoff;	/*  to the matched character	      */
+	    curwp->w_flag |= WFMOVE;	/* Say that we've moved		      */
+	}
+	return (status);		/* And return the status	      */
+    } else				/* Else, if reverse search:	      */
+	return (match_pat (patrn));	/* See if we're in the right place    */
+}
+
+/*
+ * This hack will search for the next occurrence of <pat> in the buffer, either
+ * forward or backward.  It is called with the status of the prior search
+ * attempt, so that it knows not to bother if it didn't work last time.  If
+ * we can't find any more matches, "point" is left where it was before.  If
+ * we do find a match, "point" will be at the end of the matched string for
+ * forward searches and at the beginning of the matched string for reverse
+ * searches.
+ */
+ 
+int scanmore(patrn,dir,sts)	/* search forward or back for a pattern	      */
+char	*patrn;			/* string to scan for			      */
+int	dir;			/* direction to search			      */
+int	sts;			/* previous search status		      */
+{
+    if (sts) 			/* don't try unless successful last time      */
+    {
+    	if (dir < 0)				/* reverse search?	      */
+	    sts = bakscan(patrn);		/* Yes, call our hacky routine*/
+	else
+	    sts = forscan(patrn,PTEND);		/* Nope. Go forward	      */
+    }
+    if (!sts) {
+    	(*term.t_putchar)(BELL);		/* Feep if search fails       */
+	(*term.t_flush)();			/* see that the feep feeps    */
+    }
+    return(sts);				/* else, don't even try	      */
+}
+
+/*
+ * The following is a minimal implementation of the reverse of "forscan".
+ * We aren't using the routine in SEARCH.C because it likes to type stuff,
+ * but the real solution is probably to fix that instead of duplicate the
+ * code here like we're doing.  On the other hand, we don't want to touch
+ * more modules than we have to for this first round ...
+ *
+ * This always leaves "." at the beginning of the matched pattern string
+ */
+
+int bakscan (patrn)		/* Scan backwards for a match		      */
+char	*patrn;			/* Search string to be matched		      */
+{
+    LINE *initline;			/* initial line pointer before scan   */
+    int initoff;			/* position within initial line	      */
+
+    /* Remember "point" on entry: */
+
+    initline = curwp->w_dotp;		/* Get the current line structure     */
+    initoff  = curwp->w_doto;		/* Get the offset within that line    */
+
+    /*
+     * Loop here, stepping the cursor until we match or until we reach the top
+     * of the buffer
+     */
+
+    while (backchar(TRUE, 1))			/* As long as there're chars  */
+	if (match_pat (patrn))			/* See if we match	      */
+	    return (TRUE);			/* Yep.  Stop'er right here   */
+    curwp->w_dotp = initline;			/* Top of buffer, just reset  */
+    curwp->w_doto = initoff;			/*   to original "point"      */
+    curwp->w_flag |= WFMOVE;			/* In case backchar moved us  */
+    return (FALSE);				/* And return failure	      */
+}
+
+/*
+ * The following is a worker subroutine used by the reverse search.  It
+ * compares the pattern string with the characters at "." for equality. If
+ * any characters mismatch, it will return FALSE.
+ *
+ * This isn't used for forward searches, because forward searches leave "."
+ * at the end of the search string (instead of in front), so all that needs to
+ * be done is match the last char input.
+ */
+
+int match_pat (patrn)	/* See if the pattern string matches string at "."   */
+char	*patrn;		/* String to match to buffer			     */
+{
+    register int  i;			/* Generic loop index/offset	      */
+    register int buffchar;		/* character at current position      */
+    register LINE *curline;		/* current line during scan	      */
+    register int curoff;		/* position within current line	      */
+
+    /* setup the local scan pointer to current "." */
+
+    curline = curwp->w_dotp;		/* Get the current line structure     */
+    curoff  = curwp->w_doto;		/* Get the offset within that line    */
+
+    /* top of per character compare loop: */
+
+    for (i = 0; i < strlen(patrn); i++)	/* Loop for all characters in patrn   */
+    {
+    	if (curoff == llength(curline)) /* If at end of line		      */
+    	{
+	    curline = lforw(curline);	/* Skip to the next line	      */
+	    curoff = 0;			/* Start at the beginning of the line */
+	    if (curline == curbp->b_linep)
+		return (FALSE);		/* Abort if at end of buffer	      */
+	    buffchar = '\n';		/* And say the next char is NL	      */
+	} else
+	    buffchar = lgetc(curline, curoff++); /* Get the next char	      */
+	if (!eq(buffchar, patrn[i]))	/* Is it what we're looking for?      */
+	    return (FALSE);		/* Nope, just punt it then	      */
+    }
+    return (TRUE);			/* Everything matched? Let's celebrate*/
+}
+
+/* Routine to prompt for I-Search string. */
+
+int promptpattern(prompt)
+char *prompt;
+{
+    char tpat[NPAT+20];
+
+    strcpy(tpat, prompt);		/* copy prompt to output string */
+    strcat(tpat, " [");			/* build new prompt string */
+    expandp(pat, &tpat[strlen(tpat)], NPAT/2);	/* add old pattern */
+    strcat(tpat, "]<ESC>: ");
+
+    /* check to see if we are executing a command line */
+    if (!clexec) {
+	mlwrite(tpat);
+    }
+    return(strlen(tpat));
+}
+
+/* routine to echo i-search characters */
+
+int echochar(c,col)
+int	c;	/* character to be echoed */
+int	col;	/* column to be echoed in */
+{
+    movecursor(term.t_nrow,col);		/* Position the cursor	      */
+    if ((c < ' ') || (c == 0x7F))		/* Control character?	      */
+    {
+	switch (c)				/* Yes, dispatch special cases*/
+	{
+	  case '\n':				/* Newline		      */
+	    (*term.t_putchar)('<');
+	    (*term.t_putchar)('N');
+	    (*term.t_putchar)('L');
+	    (*term.t_putchar)('>');
+	    col += 3;
+	    break;
+
+	  case '\t':				/* Tab			      */
+	    (*term.t_putchar)('<');
+	    (*term.t_putchar)('T');
+	    (*term.t_putchar)('A');
+	    (*term.t_putchar)('B');
+	    (*term.t_putchar)('>');
+	    col += 4;
+	    break;
+
+	  case 0x7F:				/* Rubout:		      */
+	    (*term.t_putchar)('^');		/* Output a funny looking     */
+	    (*term.t_putchar)('?');		/*  indication of Rubout      */
+	    col++;				/* Count the extra char       */
+	    break;
+
+	  default:				/* Vanilla control char       */
+	    (*term.t_putchar)('^');		/* Yes, output prefix	      */
+    	    (*term.t_putchar)(c+0x40);		/* Make it "^X"		      */
+	    col++;				/* Count this char	      */
+	}
+    } else
+	(*term.t_putchar)(c);			/* Otherwise, output raw char */
+    (*term.t_flush)();				/* Flush the output	      */
+    return(++col);				/* return the new column no   */
+}
+
+/*
+ * Routine to get the next character from the input stream.  If we're reading
+ * from the real terminal, force a screen update before we get the char. 
+ * Otherwise, we must be re-executing the command string, so just return the
+ * next character.
+ */
+
+int get_char ()
+{
+    int	c;				/* A place to get a character	      */
+
+    /* See if we're re-executing: */
+
+    if (cmd_reexecute >= 0)		/* Is there an offset?		      */
+	if ((c = cmd_buff[cmd_reexecute++]) != 0)
+	    return (c);			/* Yes, return any character	      */
+
+    /* We're not re-executing (or aren't any more).  Try for a real char      */
+
+    cmd_reexecute = -1;		/* Say we're in real mode again	      */
+    update(FALSE);			/* Pretty up the screen		      */
+    if (cmd_offset >= CMDBUFLEN-1)	/* If we're getting too big ...	      */
+    {
+	mlwrite ("? command too long");	/* Complain loudly and bitterly	      */
+	return (IS_QUIT);		/* And force a quit		      */
+    }
+    c = (*term.t_getchar)();		/* Get the next character	      */
+    cmd_buff[cmd_offset++] = c; /* Save the char for next time        */
+    cmd_buff[cmd_offset] = '\0';/* And terminate the buffer	      */
+    return (c);				/* Return the character		      */
+}
+
+/*
+ * Hacky routine to re-eat a character.  This will save the character to be
+ * re-eaten by redirecting the input call to a routine here.  Hack, etc.
+ */
+
+/* Come here on the next term.t_getchar call: */
+
+int uneat()
+{
+    int c;
+
+    term.t_getchar = saved_get_char;	/* restore the routine address	      */
+    c = eaten_char;			/* Get the re-eaten char	      */
+    eaten_char = -1;			/* Clear the old char		      */
+    return(c);				/* and return the last char	      */
+}
+
+int reeat(c)
+int	c;
+{
+    if (eaten_char != -1)		/* If we've already been here	      */
+	return (0);			/* Don't do it again		      */
+    eaten_char = c;			/* Else, save the char for later      */
+    saved_get_char = term.t_getchar;	/* Save the char get routine	      */
+    term.t_getchar = uneat;		/* Replace it with ours		      */
+}
+

Added: clients/emacs/line.c
===================================================================
--- clients/emacs/line.c	                        (rev 0)
+++ clients/emacs/line.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,526 @@
+/*
+ * The functions in this file are a general set of line management utilities.
+ * They are the only routines that touch the text. They also touch the buffer
+ * and window structures, to make sure that the necessary updating gets done.
+ * There are routines in this file that handle the kill buffer too. It isn't
+ * here for any good reason.
+ *
+ * Note that this code only updates the dot and mark values in the window list.
+ * Since all the code acts on the current window, the buffer that we are
+ * editing must be being displayed, which means that "b_nwnd" is non zero,
+ * which means that the dot and mark values in the buffer headers are nonsense.
+ */
+
+#include	"estruct.h"
+#include        "edef.h"
+
+KILL *ykbuf;	/* ptr to current kill buffer chunk being yanked */
+int ykboff;	/* offset into that chunk */
+
+/*
+ * This routine allocates a block of memory large enough to hold a LINE
+ * containing "used" characters. The block is always rounded up a bit. Return
+ * a pointer to the new block, or NULL if there isn't any memory left. Print a
+ * message in the message line if no space.
+ */
+LINE    *
+lalloc(used)
+register int    used;
+{
+        register LINE   *lp;
+        register int    size;
+
+        size = (used+NBLOCK-1) & ~(NBLOCK-1);
+        if (size == 0)                          /* Assume that an empty */
+                size = NBLOCK;                  /* line is for type-in. */
+        if ((lp = (LINE *) malloc((size_t)(sizeof(LINE)+size))) == NULL) {
+                mlwrite("Cannot allocate %d bytes", size);
+                return (NULL);
+        }
+        lp->l_size = size;
+        lp->l_used = used;
+        return (lp);
+}
+
+/*
+ * Delete line "lp". Fix all of the links that might point at it (they are
+ * moved to offset 0 of the next line. Unlink the line from whatever buffer it
+ * might be in. Release the memory. The buffers are updated too; the magic
+ * conditions described in the above comments don't hold here.
+ */
+lfree(lp)
+register LINE   *lp;
+{
+        register BUFFER *bp;
+        register WINDOW *wp;
+
+        wp = wheadp;
+        while (wp != NULL) {
+                if (wp->w_linep == lp)
+                        wp->w_linep = lp->l_fp;
+                if (wp->w_dotp  == lp) {
+                        wp->w_dotp  = lp->l_fp;
+                        wp->w_doto  = 0;
+                }
+                if (wp->w_markp == lp) {
+                        wp->w_markp = lp->l_fp;
+                        wp->w_marko = 0;
+                }
+                wp = wp->w_wndp;
+        }
+        bp = bheadp;
+        while (bp != NULL) {
+                if (bp->b_nwnd == 0) {
+                        if (bp->b_dotp  == lp) {
+                                bp->b_dotp = lp->l_fp;
+                                bp->b_doto = 0;
+                        }
+                        if (bp->b_markp == lp) {
+                                bp->b_markp = lp->l_fp;
+                                bp->b_marko = 0;
+                        }
+                }
+                bp = bp->b_bufp;
+        }
+        lp->l_bp->l_fp = lp->l_fp;
+        lp->l_fp->l_bp = lp->l_bp;
+        free((char *) lp);
+}
+
+/*
+ * This routine gets called when a character is changed in place in the current
+ * buffer. It updates all of the required flags in the buffer and window
+ * system. The flag used is passed as an argument; if the buffer is being
+ * displayed in more than 1 window we change EDIT t HARD. Set MODE if the
+ * mode line needs to be updated (the "*" has to be set).
+ */
+lchange(flag)
+register int    flag;
+{
+        register WINDOW *wp;
+
+        if (curbp->b_nwnd != 1)                 /* Ensure hard.         */
+                flag = WFHARD;
+        if ((curbp->b_flag&BFCHG) == 0) {       /* First change, so     */
+                flag |= WFMODE;                 /* update mode lines.   */
+                curbp->b_flag |= BFCHG;
+        }
+        wp = wheadp;
+        while (wp != NULL) {
+                if (wp->w_bufp == curbp)
+                        wp->w_flag |= flag;
+                wp = wp->w_wndp;
+        }
+}
+
+insspace(f, n)	/* insert spaces forward into text */
+
+int f, n;	/* default flag and numeric argument */
+
+{
+	linsert(n, ' ');
+	backchar(f, n);
+}
+
+/*
+ * Insert "n" copies of the character "c" at the current location of dot. In
+ * the easy case all that happens is the text is stored in the line. In the
+ * hard case, the line has to be reallocated. When the window list is updated,
+ * take special care; I screwed it up once. You always update dot in the
+ * current window. You update mark, and a dot in another window, if it is
+ * greater than the place where you did the insert. Return TRUE if all is
+ * well, and FALSE on errors.
+ */
+linsert(n, c)
+{
+        register char   *cp1;
+        register char   *cp2;
+        register LINE   *lp1;
+        register LINE   *lp2;
+        register LINE   *lp3;
+        register int    doto;
+        register int    i;
+        register WINDOW *wp;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        lchange(WFEDIT);
+        lp1 = curwp->w_dotp;                    /* Current line         */
+        if (lp1 == curbp->b_linep) {            /* At the end: special  */
+                if (curwp->w_doto != 0) {
+                        mlwrite("bug: linsert");
+                        return (FALSE);
+                }
+                if ((lp2=lalloc(n)) == NULL)    /* Allocate new line    */
+                        return (FALSE);
+                lp3 = lp1->l_bp;                /* Previous line        */
+                lp3->l_fp = lp2;                /* Link in              */
+                lp2->l_fp = lp1;
+                lp1->l_bp = lp2;
+                lp2->l_bp = lp3;
+                for (i=0; i<n; ++i)
+                        lp2->l_text[i] = c;
+                curwp->w_dotp = lp2;
+                curwp->w_doto = n;
+                return (TRUE);
+        }
+        doto = curwp->w_doto;                   /* Save for later.      */
+        if (lp1->l_used+n > lp1->l_size) {      /* Hard: reallocate     */
+                if ((lp2=lalloc(lp1->l_used+n)) == NULL)
+                        return (FALSE);
+                cp1 = &lp1->l_text[0];
+                cp2 = &lp2->l_text[0];
+                while (cp1 != &lp1->l_text[doto])
+                        *cp2++ = *cp1++;
+                cp2 += n;
+                while (cp1 != &lp1->l_text[lp1->l_used])
+                        *cp2++ = *cp1++;
+                lp1->l_bp->l_fp = lp2;
+                lp2->l_fp = lp1->l_fp;
+                lp1->l_fp->l_bp = lp2;
+                lp2->l_bp = lp1->l_bp;
+                free((char *) lp1);
+        } else {                                /* Easy: in place       */
+                lp2 = lp1;                      /* Pretend new line     */
+                lp2->l_used += n;
+                cp2 = &lp1->l_text[lp1->l_used];
+                cp1 = cp2-n;
+                while (cp1 != &lp1->l_text[doto])
+                        *--cp2 = *--cp1;
+        }
+        for (i=0; i<n; ++i)                     /* Add the characters   */
+                lp2->l_text[doto+i] = c;
+        wp = wheadp;                            /* Update windows       */
+        while (wp != NULL) {
+                if (wp->w_linep == lp1)
+                        wp->w_linep = lp2;
+                if (wp->w_dotp == lp1) {
+                        wp->w_dotp = lp2;
+                        if (wp==curwp || wp->w_doto>doto)
+                                wp->w_doto += n;
+                }
+                if (wp->w_markp == lp1) {
+                        wp->w_markp = lp2;
+                        if (wp->w_marko > doto)
+                                wp->w_marko += n;
+                }
+                wp = wp->w_wndp;
+        }
+        return (TRUE);
+}
+
+/*
+ * Insert a newline into the buffer at the current location of dot in the
+ * current window. The funny ass-backwards way it does things is not a botch;
+ * it just makes the last line in the file not a special case. Return TRUE if
+ * everything works out and FALSE on error (memory allocation failure). The
+ * update of dot and mark is a bit easier then in the above case, because the
+ * split forces more updating.
+ */
+lnewline()
+{
+        register char   *cp1;
+        register char   *cp2;
+        register LINE   *lp1;
+        register LINE   *lp2;
+        register int    doto;
+        register WINDOW *wp;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        lchange(WFHARD);
+        lp1  = curwp->w_dotp;                   /* Get the address and  */
+        doto = curwp->w_doto;                   /* offset of "."        */
+        if ((lp2=lalloc(doto)) == NULL)         /* New first half line  */
+                return (FALSE);
+        cp1 = &lp1->l_text[0];                  /* Shuffle text around  */
+        cp2 = &lp2->l_text[0];
+        while (cp1 != &lp1->l_text[doto])
+                *cp2++ = *cp1++;
+        cp2 = &lp1->l_text[0];
+        while (cp1 != &lp1->l_text[lp1->l_used])
+                *cp2++ = *cp1++;
+        lp1->l_used -= doto;
+        lp2->l_bp = lp1->l_bp;
+        lp1->l_bp = lp2;
+        lp2->l_bp->l_fp = lp2;
+        lp2->l_fp = lp1;
+        wp = wheadp;                            /* Windows              */
+        while (wp != NULL) {
+                if (wp->w_linep == lp1)
+                        wp->w_linep = lp2;
+                if (wp->w_dotp == lp1) {
+                        if (wp->w_doto < doto)
+                                wp->w_dotp = lp2;
+                        else
+                                wp->w_doto -= doto;
+                }
+                if (wp->w_markp == lp1) {
+                        if (wp->w_marko < doto)
+                                wp->w_markp = lp2;
+                        else
+                                wp->w_marko -= doto;
+                }
+                wp = wp->w_wndp;
+        }
+        return (TRUE);
+}
+
+/*
+ * This function deletes "n" bytes, starting at dot. It understands how do deal
+ * with end of lines, etc. It returns TRUE if all of the characters were
+ * deleted, and FALSE if they were not (because dot ran into the end of the
+ * buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
+ */
+ldelete(n, kflag)
+
+long n;		/* # of chars to delete */
+int kflag;	/* put killed text in kill buffer flag */
+
+{
+        register char   *cp1;
+        register char   *cp2;
+        register LINE   *dotp;
+        register int    doto;
+        register int    chunk;
+        register WINDOW *wp;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        while (n != 0) {
+                dotp = curwp->w_dotp;
+                doto = curwp->w_doto;
+                if (dotp == curbp->b_linep)     /* Hit end of buffer.   */
+                        return (FALSE);
+                chunk = dotp->l_used-doto;      /* Size of chunk.       */
+                if (chunk > n)
+                        chunk = n;
+                if (chunk == 0) {               /* End of line, merge.  */
+                        lchange(WFHARD);
+                        if (ldelnewline() == FALSE
+                        || (kflag!=FALSE && kinsert('\n')==FALSE))
+                                return (FALSE);
+                        --n;
+                        continue;
+                }
+                lchange(WFEDIT);
+                cp1 = &dotp->l_text[doto];      /* Scrunch text.        */
+                cp2 = cp1 + chunk;
+                if (kflag != FALSE) {           /* Kill?                */
+                        while (cp1 != cp2) {
+                                if (kinsert(*cp1) == FALSE)
+                                        return (FALSE);
+                                ++cp1;
+                        }
+                        cp1 = &dotp->l_text[doto];
+                }
+                while (cp2 != &dotp->l_text[dotp->l_used])
+                        *cp1++ = *cp2++;
+                dotp->l_used -= chunk;
+                wp = wheadp;                    /* Fix windows          */
+                while (wp != NULL) {
+                        if (wp->w_dotp==dotp && wp->w_doto>=doto) {
+                                wp->w_doto -= chunk;
+                                if (wp->w_doto < doto)
+                                        wp->w_doto = doto;
+                        }
+                        if (wp->w_markp==dotp && wp->w_marko>=doto) {
+                                wp->w_marko -= chunk;
+                                if (wp->w_marko < doto)
+                                        wp->w_marko = doto;
+                        }
+                        wp = wp->w_wndp;
+                }
+                n -= chunk;
+        }
+        return (TRUE);
+}
+
+/*
+ * Delete a newline. Join the current line with the next line. If the next line
+ * is the magic header line always return TRUE; merging the last line with the
+ * header line can be thought of as always being a successful operation, even
+ * if nothing is done, and this makes the kill buffer work "right". Easy cases
+ * can be done by shuffling data around. Hard cases require that lines be moved
+ * about in memory. Return FALSE on error and TRUE if all looks ok. Called by
+ * "ldelete" only.
+ */
+ldelnewline()
+{
+        register char   *cp1;
+        register char   *cp2;
+        register LINE   *lp1;
+        register LINE   *lp2;
+        register LINE   *lp3;
+        register WINDOW *wp;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        lp1 = curwp->w_dotp;
+        lp2 = lp1->l_fp;
+        if (lp2 == curbp->b_linep) {            /* At the buffer end.   */
+                if (lp1->l_used == 0)           /* Blank line.          */
+                        lfree(lp1);
+                return (TRUE);
+        }
+        if (lp2->l_used <= lp1->l_size-lp1->l_used) {
+                cp1 = &lp1->l_text[lp1->l_used];
+                cp2 = &lp2->l_text[0];
+                while (cp2 != &lp2->l_text[lp2->l_used])
+                        *cp1++ = *cp2++;
+                wp = wheadp;
+                while (wp != NULL) {
+                        if (wp->w_linep == lp2)
+                                wp->w_linep = lp1;
+                        if (wp->w_dotp == lp2) {
+                                wp->w_dotp  = lp1;
+                                wp->w_doto += lp1->l_used;
+                        }
+                        if (wp->w_markp == lp2) {
+                                wp->w_markp  = lp1;
+                                wp->w_marko += lp1->l_used;
+                        }
+                        wp = wp->w_wndp;
+                }
+                lp1->l_used += lp2->l_used;
+                lp1->l_fp = lp2->l_fp;
+                lp2->l_fp->l_bp = lp1;
+                free((char *) lp2);
+                return (TRUE);
+        }
+        if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL)
+                return (FALSE);
+        cp1 = &lp1->l_text[0];
+        cp2 = &lp3->l_text[0];
+        while (cp1 != &lp1->l_text[lp1->l_used])
+                *cp2++ = *cp1++;
+        cp1 = &lp2->l_text[0];
+        while (cp1 != &lp2->l_text[lp2->l_used])
+                *cp2++ = *cp1++;
+        lp1->l_bp->l_fp = lp3;
+        lp3->l_fp = lp2->l_fp;
+        lp2->l_fp->l_bp = lp3;
+        lp3->l_bp = lp1->l_bp;
+        wp = wheadp;
+        while (wp != NULL) {
+                if (wp->w_linep==lp1 || wp->w_linep==lp2)
+                        wp->w_linep = lp3;
+                if (wp->w_dotp == lp1)
+                        wp->w_dotp  = lp3;
+                else if (wp->w_dotp == lp2) {
+                        wp->w_dotp  = lp3;
+                        wp->w_doto += lp1->l_used;
+                }
+                if (wp->w_markp == lp1)
+                        wp->w_markp  = lp3;
+                else if (wp->w_markp == lp2) {
+                        wp->w_markp  = lp3;
+                        wp->w_marko += lp1->l_used;
+                }
+                wp = wp->w_wndp;
+        }
+        free((char *) lp1);
+        free((char *) lp2);
+        return (TRUE);
+}
+
+/*
+ * Delete all of the text saved in the kill buffer. Called by commands when a
+ * new kill context is being created. The kill buffer array is released, just
+ * in case the buffer has grown to immense size. No errors.
+ */
+kdelete()
+{
+	KILL *kp;	/* ptr to scan kill buffer chunk list */
+
+        if (kbufh != NULL) {
+
+		/* first, delete all the chunks */
+        	kbufp = kbufh;
+        	while (kbufp != NULL) {
+        		kp = kbufp->d_next;
+        		free(kbufp);
+        		kbufp = kp;
+        	}
+
+		/* and reset all the kill buffer pointers */
+		kbufh = kbufp = NULL;
+		kused = KBLOCK;        		
+        }
+}
+
+/*
+ * Insert a character to the kill buffer, allocating new chunks as needed.
+ * Return TRUE if all is well, and FALSE on errors.
+ */
+
+kinsert(c)
+
+int c;		/* character to insert in the kill buffer */
+
+{
+	KILL *nchunk;	/* ptr to newly malloced chunk */
+
+	/* check to see if we need a new chunk */
+	if (kused >= KBLOCK) {
+		if ((nchunk = (KILL *)malloc(sizeof(KILL))) == NULL)
+			return(FALSE);
+		if (kbufh == NULL)	/* set head ptr if first time */
+			kbufh = nchunk;
+		if (kbufp != NULL)	/* point the current to this new one */
+			kbufp->d_next = nchunk;
+		kbufp = nchunk;
+		kbufp->d_next = NULL;
+		kused = 0;
+	}
+
+	/* and now insert the character */
+	kbufp->d_chunk[kused++] = c;
+	return(TRUE);
+}
+
+/*
+ * Yank text back from the kill buffer. This is really easy. All of the work
+ * is done by the standard insert routines. All you do is run the loop, and
+ * check for errors. Bound to "C-Y".
+ */
+yank(f, n)
+{
+        register int    c;
+        register int    i;
+	register char	*sp;	/* pointer into string to insert */
+	KILL *kp;		/* pointer into kill buffer */
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (FALSE);
+	/* make sure there is something to yank */
+	if (kbufh == NULL)
+		return(TRUE);		/* not an error, just nothing */
+
+	/* for each time.... */
+        while (n--) {
+		kp = kbufh;
+		while (kp != NULL) {
+			if (kp->d_next == NULL)
+				i = kused;
+			else
+				i = KBLOCK;
+			sp = kp->d_chunk;
+			while (i--) {
+	                        if ((c = *sp++) == '\n') {
+        	                        if (lnewline(FALSE, 1) == FALSE)
+                	                        return (FALSE);
+	                        } else {
+        	                        if (linsert(1, c) == FALSE)
+                	                        return (FALSE);
+	                        }
+	                }
+	                kp = kp->d_next;
+                }
+        }
+        return (TRUE);
+}
+
+

Added: clients/emacs/lock.c
===================================================================
--- clients/emacs/lock.c	                        (rev 0)
+++ clients/emacs/lock.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,163 @@
+/*	LOCK:	File locking command routines for MicroEMACS
+		written by Daniel Lawrence
+								*/
+
+#include "estruct.h"
+#include "edef.h"
+
+#if	FILOCK
+#if	BSD
+#include <sys/errno.h>
+
+extern int sys_nerr;		/* number of system error messages defined */
+extern char *sys_errlist[];	/* list of message texts */
+extern int errno;		/* current error */
+
+char *lname[NLOCKS];	/* names of all locked files */
+int numlocks;		/* # of current locks active */
+
+/* lockchk:	check a file for locking and add it to the list */
+
+lockchk(fname)
+
+char *fname;	/* file to check for a lock */
+
+{
+	register int i;		/* loop indexes */
+	register int status;	/* return status */
+	char *undolock();
+
+	/* check to see if that file is already locked here */
+	if (numlocks > 0)
+		for (i=0; i < numlocks; ++i)
+			if (strcmp(fname, lname[i]) == 0)
+				return(TRUE);
+
+	/* if we have a full locking table, bitch and leave */
+	if (numlocks == NLOCKS) {
+		mlwrite("LOCK ERROR: Lock table full");
+		return(ABORT);
+	}
+
+	/* next, try to lock it */
+	status = lock(fname);
+	if (status == ABORT)	/* file is locked, no override */
+		return(ABORT);
+	if (status == FALSE)	/* locked, overriden, dont add to table */
+		return(TRUE);
+
+	/* we have now locked it, add it to our table */
+	lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1);
+	if (lname[numlocks - 1] == NULL) {	/* malloc failure */
+		undolock(fname);		/* free the lock */
+		mlwrite("Cannot lock, out of memory");
+		--numlocks;
+		return(ABORT);
+	}
+
+	/* everthing is cool, add it to the table */
+	strcpy(lname[numlocks-1], fname);
+	return(TRUE);
+}
+
+/*	lockrel:	release all the file locks so others may edit */
+
+lockrel()
+
+{
+	register int i;		/* loop index */
+	register int status;	/* status of locks */
+	register int s;		/* status of one unlock */
+
+	status = TRUE;
+	if (numlocks > 0)
+		for (i=0; i < numlocks; ++i) {
+			if ((s = unlock(lname[i])) != TRUE)
+				status = s;
+			free(lname[i]);
+		}
+	numlocks = 0;
+	return(status);
+}
+
+/* lock:	Check and lock a file from access by others
+		returns	TRUE = files was not locked and now is
+			FALSE = file was locked and overridden
+			ABORT = file was locked, abort command
+*/
+
+lock(fname)
+
+char *fname;	/* file name to lock */
+
+{
+	register char *locker;	/* lock error message */
+	register int status;	/* return status */
+	char msg[NSTRING];	/* message string */
+	char *dolock();
+
+	/* attempt to lock the file */
+	locker = dolock(fname);
+	if (locker == NULL)	/* we win */
+		return(TRUE);
+
+	/* file failed...abort */
+	if (strncmp(locker, "LOCK", 4) == 0) {
+		lckerror(locker);
+		return(ABORT);
+	}
+
+	/* someone else has it....override? */
+	strcpy(msg, "File in use by ");
+	strcat(msg, locker);
+	strcat(msg, ", overide?");
+	status = mlyesno(msg);		/* ask them */
+	if (status == TRUE)
+		return(FALSE);
+	else
+		return(ABORT);
+}
+
+/*	unlock:	Unlock a file
+		this only warns the user if it fails
+							*/
+
+unlock(fname)
+
+char *fname;	/* file to unlock */
+
+{
+	register char *locker;	/* undolock return string */
+	char *undolock();
+
+	/* unclock and return */
+	locker = undolock(fname);
+	if (locker == NULL)
+		return(TRUE);
+
+	/* report the error and come back */
+	lckerror(locker);
+	return(FALSE);
+}
+
+lckerror(errstr)	/* report a lock error */
+
+char *errstr;		/* lock error string to print out */
+
+{
+	char obuf[NSTRING];	/* output buffer for error message */
+
+	strcpy(obuf, errstr);
+	strcat(obuf, " - ");
+	if (errno < sys_nerr)
+		strcat(obuf, sys_errlist[errno]);
+	else
+		strcat(obuf, "[can not get system error message]");
+	mlwrite(obuf);
+}
+#endif
+#else
+lckhello()	/* dummy function */
+{
+}
+#endif

Added: clients/emacs/main.c
===================================================================
--- clients/emacs/main.c	                        (rev 0)
+++ clients/emacs/main.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,920 @@
+/*
+ * This program is in public domain; written by Dave G. Conroy.
+ * This file contains the main driving routine, and some keyboard processing
+ * code, for the MicroEMACS screen editor.
+ *
+ * REVISION HISTORY:
+ *
+ * 1.0  Steve Wilhite, 30-Nov-85
+ *      - Removed the old LK201 and VT100 logic. Added code to support the
+ *        DEC Rainbow keyboard (which is a LK201 layout) using the the Level
+ *        1 Console In ROM INT. See "rainbow.h" for the function key defs
+ *      Steve Wilhite, 1-Dec-85
+ *      - massive cleanup on code in display.c and search.c
+ *
+ * 2.0  George Jones, 12-Dec-85
+ *      - Ported to Amiga.
+ *
+ * 3.0  Daniel Lawrence, 29-Dec-85
+ *      - rebound keys/added new fast buffered I/O for AMIGA
+ *	- added META- repeat commands
+ *	- added reposition default to center screen (yeah!)
+ *	- changed exit with modified buffers message
+ *	- made filesave tell us what it is doing
+ *	- changed search string entry to terminate with <ESC>
+ *	  so we can use <NL> in search/replace strings
+ *	- updated version number in mode line to 3.0
+ *	12-Jan-86
+ *	- Added code to reconize the Search/replace functions
+ *	- Added code to perform search/replace & query functions
+ *	14-Jan-86
+ *	- moved search logic to separate function in search.c
+ *	- added replace and query replace functions
+ *	- separated out control key expansions to be used by others in search.c
+ *	15-Jan-86
+ *	- changed "visiting" to finding
+ *	- changed yes/no responces to not need return
+ *	- cleaned up various messages
+ *	16-jan-86
+ *	- fixed spurious spawn message in MSDOS
+ *	- added ^X-S synonime to save command
+ *	- moved escape to shell to ^X-C
+ *	21-jan-86
+ *	- added code to suspend shell under BSD
+ *	22-jan-86
+ *	- added function key support (SPEC) under MSDOS
+ *	- Abort now prints [Aborted] on message line
+ *	23-jan-86
+ *	- Added modes and commends to set/unset them
+ *	24-jan-86
+ *	- Added Goto Line command
+ *	- added Rename Buffer command
+ *	28-jan-86
+ *	- added goto begining and end of paragraph commands (META-P/META-N)
+ *	- re-wrote kdelete to use realloc. gained MUCH speed here when
+ *	  doing large wipes both on UNIX and MSDOS. Changed kill buffer
+ *	  allocation block size from 256 bytes to 1 k
+ *	29-jan-86
+ *	- moved extern function declarations to efunc.h
+ *	- made name[] name binding table
+ *	30-jan-86
+ *	- fixed Previous/Next paragraph command not to wrap around EOF
+ *	- added Fill Paragraph command (META-Q)
+ *	4-feb-86
+ *	- added code to properly display long lines, scrolling them right
+ *	  to left
+ *	5-feb-85
+ *	- rewrote code to right/left scroll...much better
+ *	- added shifted arror keys on IBMPC
+ *	6-feb-85
+ *	- add option to allow forword-word to jump to begining of
+ *	  next word instead of end of current one. This is different from
+ *	  other emacs' but can be configured off in estruct.h
+ *	- added VIEW mode to allow a buffer to be read only
+ *	   (-v switch on command line will activate this)
+ *	- changed quick exit to write out ALL changed buffers!!!
+ *	  MAKE SURE YOU KNOW THIS WHEN META-Zing
+ *	10-feb-86
+ *	- added handling of lines longer than allowed on file read in
+ *	  (they wrap on additional lines)
+ *	- made having space clear the message line and NOT insert itself
+ *	  a configuration option in ed.h
+ *	11-feb-86
+ *	- added Describe-command and Help commands.
+ *	13-feb-86
+ *	- added View file command (^X ^V) and finished HELP command
+ *	14-feb-86
+ *	- added option to let main loop skip update if type ahead commands
+ *	   are queued up
+ *	16-feb-86
+ *	- added Insert File command
+ *	17-feb-86
+ *	- added scroll next window up/down commands
+ *	18-feb-86
+ *	- added CMODE indentation
+ *	- re-arranged header files to standerdize extern and global
+ *	  definitions
+ *	- changed version number to 3.2
+ *	- added numeric arguments to search, reverse search and
+ *	  search and replace
+ *	24-feb-86
+ *	- added Bind To Key function (^C for now) to allow the user
+ *	  to change his command keys
+ *	- added Unbind key function (M-^C for now)
+ *	- added execute named command to execute unbound commands (M-X)
+ *	- added describe bindings command (not bound)
+ *	- changed version number to 3.3
+ *	25-feb-86
+ *	- scrapped CERROR mode (too many compilers)
+ *	- added EXACT mode for case sensitive searchers
+ *	26-feb-86
+ *	- added command completion on execute named command and
+ *	  all routined grabbing a command name
+ *	- adding execute-command-line command and its support functions
+ *	  (in preporation for sourcing files)
+ *	- added Execute Buffer command
+ *	27-feb-86
+ *	- added execute(source) file command and added code to automatically
+ *	  execute emacs.rc (or .emacsrc on UNIX) before initial read in
+ *	- changed version number to 3.4
+ *	4-mar-86
+ *	- changed word delete to be consistant with word move (it gets
+ *	  rid of the inter word space now) This is configurable with the
+ *	  NFWORD symbol in estruct.h
+ *	- added B_ACTIVE entry to the buffer table. Let emacs read multiple
+ *	  file names from the command line and only read them in as needed
+ *	5-mar-85
+ *	- rewrote command line parser to get rid of my patchy code
+ *	- changed version number to 3.5
+ *	1-apr-86
+ *	- added support for Aztec C 3.20e under MSDOS
+ *	- fixed bug in mlwrite on ADM3's and thier ilk under V7
+ *	- added insertion of pounds in column one under CMODE
+ *	- changed version number to 3.6
+ *	3-apr-86
+ *	- added next-buffer command (^X-X)
+ *	5-apr-86
+ *	- added kill paragraph command (M-^W)
+ *	- changed fill-paragraph to leave 2 spaces after a period at the
+ *	  end of a word.
+ *	- added OVERWRITE mode
+ *	7-apr-86
+ *	- fixed overwrite mode to handle tabs
+ *	8-apr-86
+ *	- added add/delete global mode (<ESC>M & <ESC> ^M) commands
+ *	9-apr-86
+ *	- added insert space command
+ *	- moved bindings around		^C	insert space
+ *					M-K	bind-to-key
+ *					INSERT	insert space
+ *					DELETE	forwdel
+ *	- added hunt forward and hunt reverse commands
+ *	10-apr-86
+ *	- fixed bug in DOBUF with non-terminated command string
+ *	15-apr-86
+ *	- fixed tab expansion bug in DISPLAY which hung the AMIGA
+ *	  (send in by Dawn Banks)
+ *	- fixed curcol problen if forwline/backline during keyboard
+ *	  macro execution (sent in by Ernst Christen)
+ *	- added AMIGA function/cursor key support
+ *	- fixed nonterminating <NL> replacement bug
+ *	- fixed word wrapping problems
+ *	16-apr-86
+ *	- updated documentation and froze development for 3.6 net release
+ *	23-apr-86	version 3.6a
+ *	- added forground and background colors. Setable with the
+ *	  add mode commands for the moment
+ *	24-apr-86
+ *	- added command to pipe CLI output to a buffer
+ *	25-apr-86
+ *	- added Dana Hoggat's code to replace lattice's sick system()
+ *	  function, now we no longer care what the switchar is.
+ *	- cleaned up the positioning on several of the spawing commands
+ *	26-apr-86
+ *	- added a output flush in vttidy(). Unix really appreciates this.
+ *	- added filter-buffer (^X#) command to send a buffer through
+ *	  a dos filter
+ *	- made automatic CMODE on .c and .h file compilation dependant
+ *	  in estruct.h
+ *	1-may-86
+ *	- optimized some code in update(). It certainly need a lot more.
+ *	- added AZTEC profiling capabilities. These are conditional on
+ *	  the APROF symbol in estruct.h
+ *	2-may-86
+ *	- added (u)ndo command in query-replace. undoes last repalce.
+ *	6-may-86
+ *	- re-orginized and wrote the update() function in display.c
+ *	  now my color hacks are in the right places and the code can be
+ *	  understood.
+ *	[Released version 3.6f for BETA test sites]
+ *	8-may-86
+ *	- fixed bug in new display routine to wrap cursor on extended
+ *	  lines at the right time
+ *	- modified the buffer-position command to give reasonable info
+ *	9-may-86
+ *	- improved the word wrap algorithm as not to discard non-space
+ *	  delimiters. The backscan now looks for white space rather than
+ *	  !inword().
+ *	[Released version 3.6g to Krannert]
+ *	10-may-86
+ *	- Added IBMPC.C an IBM-PC specific display driver. This makes paging
+ *	  4-6 times faster. Also made some conditional changes to DISPLAY.C
+ *	  to eliminate the pscreen[] if using the PC driver.
+ *	[changed version number to 3.6i]
+ *	12-may-86
+ *	- added delete-window (^X 0) command to dispose of a single window
+ *	- fixed problem with multiple prefixes from a command line which
+ *	  was reported by John Gamble
+ *	14-may-86
+ *	- Added AZTEC support for the IBMPC display driver. Had to
+ *	  readjust some includes and defines for this.
+ *	- fixed bug in delete-window.
+ *	- fixed some bizarre behavior with the cursor after coming back
+ *	  from spawn calls.
+ *	[changed version number to 3.7 Freezing development for net release]
+ *	15-may-86
+ *	- (that didn't last long...) Added execute-macro-(1 thru 20) commands
+ *	  to execute macro buffers (named "[Macro nn]")
+ *	- changed BFTEMP to BFINVS and cleaned up treatment of invisable
+ *	  buffers.
+ *	16-may-86
+ *	- added store-macro (unbound) to store any executed command lines to
+ *	  macro buffer.
+ *	- added clear-message-line (unbound) command to do just that
+ *	- added resize-window command to change a window's size to the
+ *	  specified argument
+ *	- improved help's logic not to re-read the file if it was already
+ *	  in a buffer
+ *	- added MAGIC mode to all structures and command tables, but the
+ *	  regular expression code that John Gamble is writting is not ready.
+ *	18-may-86
+ *	- added interactive prompt requests in command line execution. IE
+ *	  while executing a macro, a parameter starting with an at sign (@)
+ *	  causes emacs to prompt with the rest of the parameter and return
+ *	  the resulting input as the value of the parameter.
+ *	- added arguments to split-current-window to force the cursor into
+ *	  the upper or lower window.
+ *	20-may-86
+ *	- added support for the Microsoft C compiler as per the changes
+ *	  send in by Oliver Sharp
+ *	- made some upgrades and fixes for VMS sent in by Guy Streeter
+ *	21-may-86
+ *	- fixed an AZTEC bug in ttgetc by clearing the upper byte
+ *	- fixed buf in CMODE with #preprocesser input (bug fix submitted by
+ *	  Willis of unknown path)
+ *	- added support of alternative startup file ( @<filename> ) in
+ *	  the command line
+ *	- added ^Q quoting in interactive input (mlreplyt()).
+ *	- added re-binding of meta-prefix and ctlx-prefix
+ *	22-may-86
+ *	- reorginize getkey routines to make more sense and let prefix
+ *	  binding work properly.
+ *	23-may-86
+ *	- checked new code on BSD4.2 made a few fixes
+ *	- added optional fence matching while in CMODE
+ *	- added goto and search command line arguments by Mike Spitzer
+ *	26-may-86
+ *	- added parameter fetching from buffers
+ *	27-may-86
+ *	- fixed some HP150 bugs......
+ *	31-may-86
+ *	- Added Wang PC keyboard support from modifications by
+ *	  Sid Shapiro @ Wang Institute
+ *	- Fixed some reverse video bugs with code submitted by Peter Chubb
+ *	- Fixed bug in nextbuffer reported by Dave Forslund
+ *	- added system V support (USG) from Linwood Varney
+ *	2-jun-86
+ *	- changed defines to just define one unix define (for example,
+ *	  just define BSD for Unix BSD 4.2)
+ *	- Added Incremental search functions written by D. R. Banks
+ *	  in file ISEARCH.C
+ *	- added insert-string (unbound) command to help the macro
+ *	  language out.
+ *	- added unmark-buffer (M-~) command to turn off the current buffers
+ *	  change flag
+ *	- fixed nxtarg to truncate strings longer than asked for max length
+ *	4-jun-86
+ *	- added special characters in command line tokens. Tidle (~) is
+ *	  the special leadin character for "nrtb".
+ *	- Fixed bad ifdef in aztec code so it could look at HOME dir
+ *	  for startup, help, and emacs.rc files
+ *	6-jun-86
+ *	- make delete word commands clear the kill buffer if not after another
+ *	  kill command
+ *	11-jun-86
+ *	- made ~@ in string arguments pass as char(192) to nxtarg() so one can
+ *	  quote @ at the begining of string arguments
+ *	- changed buffer size vars in listbuffers() to long (for big files)
+ *	- re-wrote buffer-position command to be much faster
+ *	12-jun-86
+ *	- added count-words (M-^C) command to count the words/chars and
+ *	  lines in a region
+ *	- changed regions so they could be larger than 65535 (short ->
+ *	  long in the REGION structure)
+ *	- changed ldelete() and all callers to use a long size. The kill
+ *	  buffer will still have a problem >65535 that can not be solved
+ *	  until I restructure it.
+ *	- grouped paragraph commands and word count together under symbol
+ *	  WORDPRO to allow them to be conditionally made (or not)
+ *	13-jun-86
+ *	- re-wrote kill buffer routines again. Now they support an unlimited
+ *	  size kill buffer, and are (in theory) faster.
+ *	- changed delete-next-word (M-D) to not eat the newline after a word,
+ *	  instead it checks and eats a newline at the cursor.
+ *	17-jun-85
+ *	- added numeric argument to next/previous-window to access the nth
+ *	  window from the top/bottom
+ *	- added support for the data General 10 MSDOS machine
+ *	- added save-window (unbound) and restore-window (unbound) commands
+ *	  for the use of the menu script. Save-window remembers which window
+ *	  is current, and restore-window returns the cursor to that window.
+ *	20-jun-86
+ *	- fixed a bug with the fence matching locking up near the begining
+ *	of a buffer
+ *	- added argument to update to selectivaly force a complete update
+ *	- added update-screen (unbound) command so macros can force a
+ *	  screen update
+ *	21-jun-86
+ *	- rearranged token() and nxtarg() calls so that command names and
+ *	  repeat counts could also be prompted and fetched from buffers
+ *	- added write-message (unbound) command to write out a message
+ *	  on the message line (for macros)
+ *	- changed ifdef's so that color modes are reconized as legal in
+ *	  b/w version, and simply do nothing (allowing us to use the same
+ *	  script files)
+ */
+
+
+/* make global definitions not external */
+#define	maindef
+
+#include        "estruct.h"	/* global structures and defines */
+#include	"efunc.h"	/* function declarations and name table	*/
+#include	"edef.h"	/* global definitions */
+#include	"ebind.h"	/* default key bindings */
+
+#if     VMS
+#include        <ssdef.h>
+#define GOOD    (SS$_NORMAL)
+#endif
+
+#if	IBMPC
+#define MIN8BITCHAR	0x80
+#else
+#define MIN8BITCHAR	0xA0
+#endif
+
+#ifndef GOOD
+#define GOOD    0
+#endif
+
+#if	APROF	/* Declarations needed for AZTEC C profiling */
+int _Corg();	/* first address of program */
+int _Cend();	/* last address of program */
+
+short monbuf[NBUCK];	/* buffer for gather info */
+#endif
+
+#ifndef NOMAIN
+main(argc, argv)
+char    *argv[];
+{
+	emacs_main(argc, argv);
+}
+#endif
+
+int initialized;
+
+#ifdef NOMAIN
+#include <setjmp.h>
+jmp_buf done;
+#endif
+
+emacs_main(argc, argv)
+char    *argv[];
+{
+        register int    c;
+        register int    f;
+        register int    n;
+        register int    mflag;
+	register BUFFER *bp;
+	register int	ffile;		/* first file flag */
+	register int	carg;		/* current arg to scan */
+	static   int	startf;		/* startup executed flag */
+	int basec;			/* c stripped of meta character */
+	register int viewflag;		/* are we starting in view mode? */
+        int gotoflag;                   /* do we need to goto a line at start? */
+        int gline;                      /* if so, what line? */
+        int searchflag;                 /* Do we need to search at start? */
+        char bname[NBUFN];		/* buffer name of file to read */
+
+#if	APROF
+	/* if we are doing AZTEC C profiling, start it up */
+	/*_intr_sp(18);	 set clock interupt for 60/second */
+	monitor(_Corg, _Cend, monbuf, NBUCK, 0);
+#endif
+
+#ifdef NOMAIN
+	if (setjmp(done))
+		return;
+
+	if (initialized == TRUE)
+		goto skipinit;
+
+	initialized = TRUE;
+#endif
+
+	/* initialize the editor and process the command line arguments */
+        strcpy(bname, "main");	/* default buffer name */
+        vtinit();		/* Displays.            */
+        edinit(bname);		/* Buffers, windows.    */
+	startf = FALSE;		/* startup file not executed yet */
+
+#ifdef NOMAIN
+skipinit:
+#endif
+
+	viewflag = FALSE;	/* view mode defaults off in command line */
+	gotoflag = FALSE;	/* set to off to begin with */
+	searchflag = FALSE;	/* set to off to begin with */
+	ffile = TRUE;		/* no file to edit yet */
+
+#if	COLOR
+	curwp->w_fcolor = gfcolor;		/* and set colors	*/
+	curwp->w_bcolor = gbcolor;
+#endif
+	
+	/* scan through the command line and get the files to edit */
+	for (carg = 1; carg < argc; ++carg) {
+		/* if its a switch, process it */
+		if (argv[carg][0] == '-') {
+			switch (argv[carg][1]) {
+				case 'v':	/* -v for View File */
+				case 'V':
+					viewflag = TRUE;
+					break;
+				case 'e':	/* -e for Edit file */
+				case 'E':
+					viewflag = FALSE;
+					break;
+				case 's':	/* -s for initial search string */
+				case 'S':
+					searchflag = TRUE;
+					strcpy(pat,&argv[carg][2]);
+					break;
+				case 'g':	/* -g for initial goto */
+				case 'G':	
+					gotoflag = TRUE;
+					gline = atoi(&argv[carg][2]);
+					break;
+				default:	/* unknown switch */
+					/* ignore this for now */
+					break;
+			}
+		} else 	/* check for a macro file */
+			if (argv[carg][0]== '@') {
+
+			if (startup(&argv[carg][1]) == TRUE)
+				startf = TRUE;	/* don't execute emacs.rc */
+
+		} else {	/* process a file name */
+			/* if we haven't run emacs.rc, do it now */
+			if (startf == FALSE) {
+				startup("");
+				startf = TRUE;
+			}
+
+#ifdef NOMAIN
+			/* if this is the first file, read it in */
+			if (ffile) {
+				if (getfile(argv[carg], (viewflag==FALSE))
+								== ABORT) {
+					bp = curbp;
+					strcpy(bp->b_bname, "main");
+					strcpy(bp->b_fname, "");
+				}
+				bp = curbp;
+#else
+			/* set up a buffer for this file */
+	                makename(bname, argv[carg]);
+
+			/* if this is the first file, read it in */
+			if (ffile) {
+				bp = curbp;
+				makename(bname, argv[carg]);
+				strcpy(bp->b_bname, bname);
+				strcpy(bp->b_fname, argv[carg]);
+				if (readin(argv[carg], (viewflag==FALSE))
+								== ABORT) {
+					strcpy(bp->b_bname, "main");
+					strcpy(bp->b_fname, "");
+				}
+#endif
+
+				bp->b_dotp = bp->b_linep;
+				bp->b_doto = 0;
+				ffile = FALSE;
+			} else {
+				/* set this to inactive */
+				bp = bfind(bname, TRUE, 0);
+				strcpy(bp->b_fname, argv[carg]);
+				bp->b_active = FALSE;
+			}
+
+			/* set the view mode appropriatly */
+			if (viewflag)
+				bp->b_mode |= MDVIEW;
+		}
+	}
+
+	/* if invoked with nothing, run the startup file here */
+	if (startf == FALSE) {
+		startup("");
+		startf = TRUE;
+	}
+ 
+        /* Deal with startup gotos and searches */
+ 
+        if (gotoflag && searchflag) {
+        	update(FALSE);
+		mlwrite("[Can not search and goto at the same time!]");
+	}
+        else if (gotoflag) {
+                if (gotoline(TRUE,gline) == FALSE) {
+                	update(FALSE);
+			mlwrite("[Bogus goto argument]");
+		}
+        } else if (searchflag) {
+                if (forscan(&pat[0], 2) == FALSE) {
+                	update(FALSE);
+			mlwrite("Not found.");
+		}
+        }
+
+	/* setup to process commands */
+#ifdef NOMAIN
+	refresh(FALSE,1);
+#endif
+        lastflag = 0;                           /* Fake last flags.     */
+	curbp->b_mode |= gmode;			/* and set default modes*/
+	curwp->w_flag |= WFMODE;		/* and force an update	*/
+#if	COLOR
+	curwp->w_fcolor = gfcolor;		/* and set colors	*/
+	curwp->w_bcolor = gbcolor;
+#endif
+
+loop:
+        update(FALSE);                          /* Fix up the screen    */
+        c = getcmd();
+        if (mpresf != FALSE) {
+                mlerase();
+                update(FALSE);
+#if	CLRMSG
+                if (c == ' ')                   /* ITS EMACS does this  */
+                        goto loop;
+#endif
+        }
+        f = FALSE;
+        n = 1;
+
+	/* do META-# processing if needed */
+
+	basec = c & ~META;		/* strip meta char off if there */
+	if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) {
+		f = TRUE;		/* there is a # arg */
+		n = 0;			/* start with a zero default */
+		mflag = 1;		/* current minus flag */
+		c = basec;		/* strip the META */
+		while ((c >= '0' && c <= '9') || (c == '-')) {
+			if (c == '-') {
+				/* already hit a minus or digit? */
+				if ((mflag == -1) || (n != 0))
+					break;
+				mflag = -1;
+			} else {
+				n = n * 10 + (c - '0');
+			}
+			if ((n == 0) && (mflag == -1))	/* lonely - */
+				mlwrite("Arg:");
+			else
+				mlwrite("Arg: %d",n * mflag);
+
+			c = getcmd();	/* get the next key */
+		}
+		n = n * mflag;	/* figure in the sign */
+	}
+
+	/* do ^U repeat argument processing */
+
+        if (c == (CTRL|'U')) {                  /* ^U, start argument   */
+                f = TRUE;
+                n = 4;                          /* with argument of 4 */
+                mflag = 0;                      /* that can be discarded. */
+                mlwrite("Arg: 4");
+                while ((c=getcmd()) >='0' && c<='9' || c==(CTRL|'U') || c=='-'){
+                        if (c == (CTRL|'U'))
+                                n = n*4;
+                        /*
+                         * If dash, and start of argument string, set arg.
+                         * to -1.  Otherwise, insert it.
+                         */
+                        else if (c == '-') {
+                                if (mflag)
+                                        break;
+                                n = 0;
+                                mflag = -1;
+                        }
+                        /*
+                         * If first digit entered, replace previous argument
+                         * with digit and set sign.  Otherwise, append to arg.
+                         */
+                        else {
+                                if (!mflag) {
+                                        n = 0;
+                                        mflag = 1;
+                                }
+                                n = 10*n + c - '0';
+                        }
+                        mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
+                }
+                /*
+                 * Make arguments preceded by a minus sign negative and change
+                 * the special argument "^U -" to an effective "^U -1".
+                 */
+                if (mflag == -1) {
+                        if (n == 0)
+                                n++;
+                        n = -n;
+                }
+        }
+
+        if (kbdmip != NULL) {                   /* Save macro strokes.  */
+                if (c!=(CTLX|')') && kbdmip>&kbdm[NKBDM-6]) {
+                        ctrlg(FALSE, 0);
+                        goto loop;
+                }
+                if (f != FALSE) {
+                        *kbdmip++ = (CTRL|'U');
+                        *kbdmip++ = n;
+                }
+                *kbdmip++ = c;
+        }
+        execute(c, f, n);                       /* Do it.               */
+        goto loop;
+}
+
+/*
+ * Initialize all of the buffers and windows. The buffer name is passed down
+ * as an argument, because the main routine may have been told to read in a
+ * file by default, and we want the buffer name to be right.
+ */
+edinit(bname)
+char    bname[];
+{
+        register BUFFER *bp;
+        register WINDOW *wp;
+
+        bp = bfind(bname, TRUE, 0);             /* First buffer         */
+        blistp = bfind("[List]", TRUE, BFINVS); /* Buffer list buffer   */
+        wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window         */
+        if (bp==NULL || wp==NULL || blistp==NULL)
+                errexit();
+        curbp  = bp;                            /* Make this current    */
+        wheadp = wp;
+        curwp  = wp;
+        wp->w_wndp  = NULL;                     /* Initialize window    */
+        wp->w_bufp  = bp;
+        bp->b_nwnd  = 1;                        /* Displayed.           */
+        wp->w_linep = bp->b_linep;
+        wp->w_dotp  = bp->b_linep;
+        wp->w_doto  = 0;
+        wp->w_markp = NULL;
+        wp->w_marko = 0;
+        wp->w_toprow = 0;
+#if	COLOR
+	/* initalize colors to global defaults */
+	wp->w_fcolor = gfcolor;
+	wp->w_bcolor = gbcolor;
+#endif
+        wp->w_ntrows = term.t_nrow-1;           /* "-1" for mode line.  */
+        wp->w_force = 0;
+        wp->w_flag  = WFMODE|WFHARD;            /* Full.                */
+}
+
+/*
+ * This is the general command execution routine. It handles the fake binding
+ * of all the keys to "self-insert". It also clears out the "thisflag" word,
+ * and arranges to move it to the "lastflag", so that the next command can
+ * look at it. Return the status of command.
+ */
+execute(c, f, n)
+{
+        register KEYTAB *ktp;
+        register int    status;
+
+        ktp = &keytab[0];                       /* Look in key table.   */
+        while (ktp->k_fp != NULL) {
+                if (ktp->k_code == c) {
+                        thisflag = 0;
+                        status   = (*ktp->k_fp)(f, n);
+                        lastflag = thisflag;
+                        return (status);
+                }
+                ++ktp;
+        }
+
+        /*
+         * If a space was typed, fill column is defined, the argument is non-
+         * negative, wrap mode is enabled, and we are now past fill column,
+	 * and we are not read-only, perform word wrap.
+         */
+        if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
+	    n >= 0 && getccol(FALSE) > fillcol &&
+	    (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
+                wrapword();
+
+        if ((c>=0x20 && c<=0x7E)                /* Self inserting.      */
+        ||  (c>=MIN8BITCHAR && c<=0xFE)) {
+                if (n <= 0) {                   /* Fenceposts.          */
+                        lastflag = 0;
+                        return (n<0 ? FALSE : TRUE);
+                }
+                thisflag = 0;                   /* For the future.      */
+
+		/* if we are in overwrite mode, not at eol,
+		   and next char is not a tab or we are at a tab stop,
+		   delete a char forword			*/
+		if (curwp->w_bufp->b_mode & MDOVER &&
+		    curwp->w_doto < curwp->w_dotp->l_used &&
+			(lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
+			 (curwp->w_doto) % 8 == 7))
+				ldelete(1L, FALSE);
+
+		/* do the appropriate insertion */
+		if (c == '}' && (curbp->b_mode & MDCMOD) != 0)
+	        	status = insbrace(n, c);
+	        else if (c == '#' && (curbp->b_mode & MDCMOD) != 0)
+	        	status = inspound();
+	        else
+	                status = linsert(n, c);
+
+#if	CFENCE
+		/* check for CMODE fence matching */
+		if ((c == '}' || c == ')') && (curbp->b_mode & MDCMOD) != 0)
+			fmatch(c);
+#endif
+
+                lastflag = thisflag;
+                return (status);
+        }
+	(*term.t_beep)();
+	mlwrite("[Key not bound]");		/* complain		*/
+        lastflag = 0;                           /* Fake last flags.     */
+        return (FALSE);
+}
+
+/*
+ * Fancy quit command, as implemented by Norm. If the any buffer has
+ * changed do a write on that buffer and exit emacs, otherwise simply exit.
+ */
+quickexit(f, n)
+{
+	register BUFFER *bp;	/* scanning pointer to buffers */
+
+	bp = bheadp;
+	while (bp != NULL) {
+	        if ((bp->b_flag&BFCHG) != 0	/* Changed.             */
+        	&& (bp->b_flag&BFINVS) == 0) {	/* Real.                */
+			curbp = bp;		/* make that buffer cur	*/
+			mlwrite("[Saving %s]",bp->b_fname);
+                	filesave(f, n);
+		}
+	bp = bp->b_bufp;			/* on to the next buffer */
+	}
+        quit(f, n);                             /* conditionally quit   */
+}
+
+/*
+ * Quit command. If an argument, always quit. Otherwise confirm if a buffer
+ * has been changed and not written out. Normally bound to "C-X C-C".
+ */
+quit(f, n)
+{
+        register int    s;
+
+        if (f != FALSE                          /* Argument forces it.  */
+        || anycb() == FALSE                     /* All buffers clean.   */
+						/* User says it's OK.   */
+        || (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) {
+#if	FILOCK
+		if (lockrel() != TRUE) {
+			(*term.t_putchar)('\n');
+			(*term.t_putchar)('\r');
+			(*term.t_close)();
+			exit(1);
+		}
+#endif
+                vttidy();
+#if	APROF
+		/* if doing AZTEC C profiling, close up and write it out */
+		monitor(0,0,0,0,0);
+#endif
+#ifdef NOMAIN
+		    longjmp(done,0);
+#else
+		    exit(GOOD);
+#endif
+        }
+	mlwrite("");
+        return (s);
+}
+
+/*
+ * Begin a keyboard macro.
+ * Error if not at the top level in keyboard processing. Set up variables and
+ * return.
+ */
+ctlxlp(f, n)
+{
+        if (kbdmip!=NULL || kbdmop!=NULL) {
+                mlwrite("Not now");
+                return (FALSE);
+        }
+        mlwrite("[Start macro]");
+        kbdmip = &kbdm[0];
+        return (TRUE);
+}
+
+/*
+ * End keyboard macro. Check for the same limit conditions as the above
+ * routine. Set up the variables and return to the caller.
+ */
+ctlxrp(f, n)
+{
+        if (kbdmip == NULL) {
+                mlwrite("Not now");
+                return (FALSE);
+        }
+        mlwrite("[End macro]");
+        kbdmip = NULL;
+        return (TRUE);
+}
+
+/*
+ * Execute a macro.
+ * The command argument is the number of times to loop. Quit as soon as a
+ * command gets an error. Return TRUE if all ok, else FALSE.
+ */
+ctlxe(f, n)
+{
+        register int    c;
+        register int    af;
+        register int    an;
+        register int    s;
+
+        if (kbdmip!=NULL || kbdmop!=NULL) {
+                mlwrite("Not now");
+                return (FALSE);
+        }
+        if (n <= 0)
+                return (TRUE);
+        do {
+                kbdmop = &kbdm[0];
+                do {
+                        af = FALSE;
+                        an = 1;
+                        if ((c = *kbdmop++) == (CTRL|'U')) {
+                                af = TRUE;
+                                an = *kbdmop++;
+                                c  = *kbdmop++;
+                        }
+                        s = TRUE;
+                } while (c!=(CTLX|')') && (s=execute(c, af, an))==TRUE);
+                kbdmop = NULL;
+        } while (s==TRUE && --n);
+        return (s);
+}
+
+/*
+ * Abort.
+ * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
+ * Sometimes called as a routine, to do general aborting of stuff.
+ */
+ctrlg(f, n)
+{
+        (*term.t_beep)();
+        if (kbdmip != NULL) {
+                kbdm[0] = (CTLX|')');
+                kbdmip  = NULL;
+        }
+	mlwrite("[Aborted]");
+        return (ABORT);
+}
+
+/* tell the user that this command is illegal while we are in
+   VIEW (read-only) mode				*/
+
+rdonly()
+
+{
+	(*term.t_beep)();
+	mlwrite("[Key illegal in VIEW mode]");
+	return(FALSE);
+}
+
+meta()	/* dummy function for binding to meta prefix */
+{
+}
+
+cex()	/* dummy function for binding to control-x prefix */
+{
+}
+
+errexit()
+{
+#ifdef NOMAIN
+	longjmp(done, 1);
+#else
+	exit(1);
+#endif
+}

Added: clients/emacs/makefile
===================================================================
--- clients/emacs/makefile	                        (rev 0)
+++ clients/emacs/makefile	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,79 @@
+# Makefile for MicroEMACS 3.7 for use with Forthmacs/386.  To compile EMACS
+# for inclusion in the Zortech protected-mode loader (forth.exe), type:
+#
+#    make objects
+#
+# It is also possible to compile MicroEMACS by itself, without including it
+# in the Forth loader.  To do so, type:
+#
+#    make emacs.exe
+#
+# If you make emacs.exe, you must re-make "objects" before attempting to
+# recompile the Forth loader (in the dos/zortech directory), because the
+# main.obj file is different when compiled for self-contained emacs.exe
+# than when compiled for use with Forth (in particular, it does not have a
+# main() routine when compiled for Forth - the Forth loader supplies main())
+
+CFLAGS=		-mx -p
+CC=		ztc
+LFLAGS= 	-mx
+LD=		ztc
+
+HFILES=		estruct.h edef.h efunc.h epath.h ebind.h evar.h
+
+OFILES=     	ansi.obj basic.obj   bind.obj     buffer.obj  display.obj  \
+		exec.obj     file.obj    fileio.obj ibmpc.obj  \
+		input.obj   isearch.obj  line.obj    lock.obj   \
+		random.obj  region.obj   search.obj  spawn.obj  termio.obj  \
+		window.obj  word.obj
+
+config.h:	config.zth
+		cp config.zth config.h
+
+objects:	$(OFILES) config.h
+		$(CC) $(CFLAGS) -DNOMAIN -c main.c
+
+emacs.exe:	$(OFILES)
+		$(CC) $(CFLAGS) -c main.c
+		$(LD) $(LFLAGS) -o $@ *.obj
+
+basic.obj:	basic.c
+
+bind.obj:	bind.c
+
+buffer.obj:	buffer.c
+
+display.obj:	display.c
+
+exec.obj:	exec.c
+
+file.obj:	file.c
+
+fileio.obj:	fileio.c
+
+ibmpc.obj:	ibmpc.c
+
+input.obj:	input.c
+
+isearch.obj:	isearch.c
+
+line.obj:	line.c
+
+lock.obj:	lock.c
+
+random.obj:	random.c
+
+region.obj:	region.c
+
+search.obj:	search.c
+
+spawn.obj:	spawn.c
+
+termio.obj:	termio.c
+
+window.obj:	window.c
+
+word.obj:	word.c
+
+.C.OBJ:
+		$(CC) $(CFLAGS) -c $*

Added: clients/emacs/makefile.obp
===================================================================
--- clients/emacs/makefile.obp	                        (rev 0)
+++ clients/emacs/makefile.obp	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,76 @@
+# Makefile for MicroEMACS 3.7 for use with Forthmacs/386.  To compile EMACS
+# for inclusion in the Zortech protected-mode loader (forth.exe), type:
+#
+#    make objects
+#
+# It is also possible to compile MicroEMACS by itself, without including it
+# in the Forth loader.  To do so, type:
+#
+#    make emacs.exe
+#
+# If you make emacs.exe, you must re-make "objects" before attempting to
+# recompile the Forth loader (in the dos/zortech directory), because the
+# main.obj file is different when compiled for self-contained emacs.exe
+# than when compiled for use with Forth (in particular, it does not have a
+# main() routine when compiled for Forth - the Forth loader supplies main())
+
+CFLAGS=		-mx -p
+CC=		ztc
+LFLAGS= 	-mx
+LD=		ztc
+
+HFILES=		estruct.h edef.h efunc.h epath.h ebind.h evar.h
+
+OFILES=     	ansi.obj basic.obj   bind.obj     buffer.obj  display.obj  \
+		exec.obj     file.obj    fileio.obj ibmpc.obj  \
+		input.obj   isearch.obj  line.obj    lock.obj   \
+		random.obj  region.obj   search.obj  spawn.obj  termio.obj  \
+		window.obj  word.obj
+
+objects:	$(OFILES)
+		$(CC) $(CFLAGS) -DNOMAIN -c main.c
+
+emacs.exe:	$(OFILES)
+		$(CC) $(CFLAGS) -c main.c
+		$(LD) $(LFLAGS) -o $@ *.obj
+
+basic.obj:	basic.c
+
+bind.obj:	bind.c
+
+buffer.obj:	buffer.c
+
+display.obj:	display.c
+
+exec.obj:	exec.c
+
+file.obj:	file.c
+
+fileio.obj:	fileio.c
+
+ibmpc.obj:	ibmpc.c
+
+input.obj:	input.c
+
+isearch.obj:	isearch.c
+
+line.obj:	line.c
+
+lock.obj:	lock.c
+
+random.obj:	random.c
+
+region.obj:	region.c
+
+search.obj:	search.c
+
+spawn.obj:	spawn.c
+
+termio.obj:	termio.c
+
+window.obj:	window.c
+
+word.obj:	word.c
+
+.C.OBJ:
+		$(CC) $(CFLAGS) -c $*

Added: clients/emacs/me.man
===================================================================
--- clients/emacs/me.man	                        (rev 0)
+++ clients/emacs/me.man	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,810 @@
+From: sun!oliveb!hplabs!hp-pcd!craig 
+Article 2071 of net.emacs:
+Relay-Version: version B 2.10.2 9/18/84 SMI; site sun.uucp
+Posting-Version: notesfiles - hp 1.2 08/01/83; site hp-pcd.UUCP
+Path: sun!oliveb!hplabs!hp-pcd!craig
+>From: craig at hp-pcd.UUCP (craig)
+Newsgroups: net.emacs
+Subject: Re: MicroEmacs manual
+Message-ID: <9900002 at hpcvlo.UUCP>
+Date: 20 Jul 86 06:38:00 GMT
+Date-Received: 21 Jul 86 23:22:09 GMT
+References: <9900001 at hpcvlo.UUCP>
+Organization: Hewlett-Packard - Corvallis, OR
+Lines: 583
+Nf-ID: #R:hpcvlo:9900001:hpcvlo:9900002:000:25482
+Nf-From: hpcvlo!craig    Jul 19 22:38:00 1986
+
+
+	ME Documentation
+For the most part, read the Goslings or Unipress EMACS manuals.
+
+Soft keys and Function keys
+keyboard      ME key	Bound to
+   F1		~1
+   F2		~2
+   F3		~3
+   F4		~4
+   F5		~5
+   F6		~6
+   F7		~7
+   F8		~8
+   F9		~9
+   F10		~0
+  home		~A	(mark-and-home)
+  end		~B	(mark-and-end)
+  up arrow	~C	(previous-line)
+  down arrow    ~D	(next-line)
+  right arrow   ~E	(forward-character)
+  left arrow    ~F	(backward-character)
+  insert 	~G	(center-cursor)
+  delete	~H	(delete-char)
+  page up	~I	(previous-page)
+  page down	~J	(next-page)
+  clear line	~K	(kill-line)
+  delete line	~L	(delete-line)
+  insert line	~M	(insert-line)
+  select	~N	(set-mark)
+  roll up 	~O	(scroll-down)
+  roll down 	~P	(scroll-up)
+
+  ALT 0..9A..Z!	mapped to META 0..9A..Z!
+  Use the ALT key like the control key (ie hold it down while you press the
+    next key).
+
+Anytime you are being queried on the message line the softkeys return
+their internal value.  So if you want to bind F1, you can press F1
+when bind-to-key asks for a key.
+
+Case of letters:
+  Meta keys and Control X commands: next letter is ALWAYS uppercase.
+  Softkeys are case sensitive.
+
+TERMS
+args	Parameters or arguments that will be requested by the command.  If
+   [] surround the arg, then it will only be requested in certain cases.
+binding	See bound.
+bound	A key is attached or bound to a command or program.  If the key is
+   pressed, whatever it is bound to is invoked.
+buffer	A buffer is the internal workspace.  If a buffer is visible, it is
+   shown through one or more windows.  It is usually attached to a file (ie
+   contains the contents of the file).  If the buffer is created by reading
+   in a file, the buffer name is created by removing the path from it (and
+   leaving only the name and extension).
+command	A ME built in command such as (search-forward).  These can be bound
+   to a key to make executing them easier.
+dot	The place between two characters.  It is immediately to the left of
+   the cursor.  Also known as point.  One per window or buffer.
+file	
+   For MS-DOS, you can use forward slashes "/" as part of the path name.
+Kill buffer	An invisible buffer that holds things created by
+   (kill-region) and (copy-region).  Used to cut and paste or just paste.
+  If you want to move a block of text about: 1, set the mark at one end
+    and then move the dot to the other end.  2, kill the region. 3, move
+    the dot to the start of where you want the text to begin and 4, yank
+    the kill buffer.  Bingo.
+  Copy and kill append to the kill buffer if last command was also a
+    kill or copy, otherwise the kill buffer is cleared before the new text
+    is entered.
+macro	A sequence of keystrokes that can be replayed on command.  Used
+   when you don't want to spend the time writing a program.  Created by
+   going through the motions (which are actually done so you can verify
+   that what you want to happen is actually happening) (see (start-macro)
+   and (end-macro)).  When replayed, the exact sequence you typed in is
+   reentered.
+mark	A user settable dot.  One per window or buffer.
+message line or
+minibuffer	The bottom line of the screen.  This is the
+   place where all questions are asked, error messages sent, etc.
+MUT	The built in programming language.  Refer to the MUT documentation.
+n	Argument prefix (set by ^U).  This means repeat the key (or what
+   its bound to) or command n times.  If ^U is not used then n
+   defaults to 1.
+program	A program created by (defun).  Very few of these are builtin - most
+  of them are created by the user to make his editing easier.
+region	The area between dot and mark.
+window	A portion of the screen.  A window provides a view of a buffer.
+   There can be more than one window showing a buffer.  Windows are
+   separated from each by a mode line.  Mode lines look like:
+   -* MicroEMACS -- buffer_name -- file_name ---------------
+   The * is present only if the buffer has been modified.  The
+   file_name is present only if a file is associated with the buffer.
+word	A string of letters, digits, "$" or "_".
+
+COMMAND	 default binding, args and comments
+(abort)		^G
+  Back out of anything.
+  If remembering a macro, forget it.
+  If executing a program, stop it.
+(apropos)	$?	args: keyword
+  List all commands and programs that have a keyword in them.  For example,
+    if you apropos commands with "mark" in them you would get:
+	PROGRAMS:
+	mark-and-end               ~B
+	mark-and-home              ~A
+	COMMANDS:
+	exchange-dot-and-mark      ^X^X 
+	set-mark                   ^@ $SPACE ~N
+    On the left is the command name.  On the right is the key(s) it is
+    bound to.  So, in this case, (set-mark) is bound to control-@,
+    escape-space and softkey-N.
+  Command completion is on.
+  See also: (describe-bindings).
+
+(backward-character)	^B ~F (left arrow)
+  Move the dot backwards by a character.
+  See also: (forward-character).
+(backward-word)		$B
+  Move backwards until dot is at the beginning of a word or beginning of
+    buffer.
+  Word is a digit, letter, "$" or "_".
+  See also: (delete-previous-word), (delete-next-word), (forward-word).
+(beginning-of-buffer)	$<
+  Move the dot to the top of the buffer.
+  See also: (end-of-buffer), (mark-and-end), (mark-and-home).
+(beginning-of-line)	^A
+  Move the dot to the start of the line.
+  See also: (end-of-line).
+(bind-to-key)		Not bound.	args: command name, keystroke(s)
+  Attach a key to a command or program.  When ever the key is pressed, the
+    command or program will be executed (except when a question is being
+    asked).
+  Possible keys are single key strokes, soft keys and double keystrokes.
+    Double keystrokes are prefixed keys.  Prefix keys are: ^X
+    and escape (^[).  They can be prefixed to any key except soft keys.
+  When asked for the key you can press the key(s) or enter the keycode.
+    Keycodes are ascii (ie no control characters and such) representations
+    of a key.  For example, escape-D is represented by the 3 characters ^[D,
+    control-C by the 2 characters ^C and function key 1 (aka soft key 1) by
+    ~1.  Keycodes should be used when programming to avoid screwing up
+    things like printers (when you print out the file).
+    eg (bind-to-key "foo" "~1")
+    Note: Always use uppercase for control keys.
+  Command completion is on.
+  See also: (defun).
+
+(case-region-lower)	^X^L
+  Convert a region to lower case.
+(case-region-upper)	^X^U
+  Convert a region to upper case.
+(case-word-capitalize)	$C
+  Capitalize word after dot.
+  If dot is between words, searches forward to the start of the next word
+    and capitalizes that one.
+(case-word-lower)	$L
+  Convert word to lower case.
+  If dot is between words, searches forward to the start of the next word
+    and lower case that one.
+(case-word-upper)	$U
+  Convert word to upper case.
+  If dot is between words, searches forward to the start of the next word
+    and upper case that one.
+(center-cursor)		~G (insert)
+  Center the dot vertically in the current window.
+  Same as (arg-prefix 0) (reposition-window).
+  See also: (refresh-screen), (reposition-window).
+(completion)		Not bound	args: word to complete
+  Asks for a command, allows command completion and inserts the
+    command.  The arg prefix selects the list to be completed
+    Selector: or the lists you want (default is 3 (system & program)).
+	bit   value	list
+	 0	1	system keywords
+	 1	2	program names
+   	 2	4	MUT keywords
+   	 3	8	buffer names
+(copy-region)		$W
+  Copy a region to the kill buffer.  If the last command was
+    a kill command, append to the kill buffer.  The region is uneffected.
+  See also: (kill-region), (yank-from-killbuffer).
+
+(decompile)		Not bound	args: program name
+  Dump a program at the dot.  It is ready to be recompiled
+    (with (execute-buffer) or (load)) but will need to be formatted before
+    you save it to a file.
+  Command completion is on.
+  See also: (defun).
+(delete-blank-lines)	Not bound
+  Delete blank line above and below the dot.  If the dot is not on a blank
+    line, this command does nothing.  A blank line is one with nothing on
+    it (and that includes whitespace).  Does not put deleted lines
+    in kill buffer.
+(delete-char)		^D or ~H (delete)
+  Delete the character after the dot (visually under the cursor).  If at
+    the end of the line, the next line is joined to the current line.  If
+    given an argument, deleted characters are put into the kill buffer.
+(delete-line)		~L (delete line)
+  Make a line disappear.  Saved to the kill buffer.
+  Same as (beginning-of-line) (arg-prefix 1) (kill-line).
+(delete-next-word)	$D
+  Delete a word.  Save them in the kill buffer.
+(delete-other-windows)	^X1
+  Make the current window the only window on the screen.
+  See also: (split-window).
+(delete-previous-character)	^H or DEL
+  Delete the character before the dot (visually to the left of the cursor).
+    If at the beginning of the line, the current line is joined to the end
+    of the previous line.  If given an argument, deleted characters are put
+    into the kill buffer.
+(delete-previous-word)	$DEL or $^H
+  Delete the previous word.  Save them in the kill buffer.
+(describe-bindings)	Not bound
+  List all commands and programs along with their key bindings in the same
+    format as (apropos).
+  See also: (apropos).
+(describe-key)		Not bound	args: keystroke(s)
+  Tell what command a key is bound to.  If n, inserts the command name.
+  For example, (describe-key "^A") returns "^A is bound to
+  beginning-of-line".
+  For MUT programmer types, a handy program is:
+  (defun "deref-key"	; surround a command with braces
+  {
+    (set-mark) (let-user-respond) (arg-prefix 1)	; get a key
+    (if (describe-key)	; if it is bound put braces around it
+    {
+	(insert-text ")") (exchange-dot-and-mark) (insert-text "(")
+	(exchange-dot-and-mark)
+    } {})
+  })
+  This allows programming using keys rather than remembering command
+    names.
+  See also: (completion), (apropos).
+
+(end-macro)	^X)
+  Stop remembering keystrokes.  The keystrokes are stored in the macro
+    buffer ready to be replayed by (execute-macro).
+  See also: (execute-macro), (start-macro).
+(end-of-buffer)	$>
+  Move the dot to the bottom of the buffer.
+  See also: (beginning-of-buffer), (mark-and-end), (mark-and-home).
+(end-of-line)	^E
+  Move the dot to the end of the line.
+  See also: (beginning-of-line).
+(enlarge-window)	^XZ
+  Enlarge the current window by a line.
+  See also: (shrink-window).
+(exchange-dot-and-mark)	^X^X
+  Move the dot to the mark and set the mark to old dot value.  Visually,
+    move to where the mark was set.  Repeating this command will undo it.
+  See also: (set-mark).
+(execute-buffer)	Not bound	args: buffer name
+  Execute cmds or MUT programs in a buffer.  You can't execute the buffer you
+    are in (since if you changed the buffer you would change the program
+    which would probably tank ME).  The dot will track the pc (program
+    counter) so, if there is an error, the dot will (hopefully) be right 
+    after the error (when you switch to the buffer).  If you are single
+    stepping, ^L will cause the code that is executing to be on screen
+    (assuming the buffer is on screen).
+  Command completion is on.
+  See also: (execute-line), (load), document on MUT programming.
+(execute-extended-command)	$X	args: command or program name
+  Execute a command or program.  ie one of the things listed in this
+    document.  When asked what to Execute: use the name as listed here
+    (without the "()"'s).  eg Execute: execute-extended-command
+  Command completion is in effect.
+(execute-line)		$$	args: MUT code
+  Execute one line of MUT code.  eg (= HELP 0) or (bind-to-key "foo" "^F")
+  See also: (execute-buffer).
+(execute-macro)		^XE
+  Replay the keystrokes saved in the macro buffer.
+  See also: (start-macro), (end-macro).
+(execute-monitor-command)	^X!	args: op sys command
+  Call the operating system to perform a command or run a program and then
+    return to editing.
+  MS-DOS example:  To copy a file: (execute-monitor-command "copy foo bar")
+    To get a directory listing: (execute-monitor-command "ls").
+  See also: (spawn-cli).
+(exit)			^C or ^X^C	args: [yes or no]
+  Exit emacs.  If there is a modified buffer (one that has changed since it
+    was last saved), ask the user the user about it.
+  If n, quit no matter what and without making any noise.
+  See also: (quick-exit).
+
+(filter-region)		Not bound	args: filter name
+  Take a region and give to a filter as standard input.
+  Take the output of the filter and use it to replace the region.
+  For example:  If the region is a paragraph and adjust is a program that
+    formats text then (filter-region "adjust") will replace the paragraph
+    with a formatted copy.
+    If you don't want to remove anything, just make a null region (set the
+    mark at the dot).  eg (set-mark)(filter-region "ls") will insert a
+    directory listing at the dot.
+(forward-character)	^F or ~E (right arrow)
+  Move right a character.
+  See also: (backward-character).
+(forward-word)		$F
+  Move forwards until dot is after the end of a word or end of buffer.
+  Word is a digit, letter, "$" or "_".
+  See also: (backward-word), (delete-previous-word), (delete-next-word).
+
+(goto-line)		$G
+  Goto the nth line.
+
+(insert-file)		^X^I	args: file name
+  Insert a file at the dot.
+  See also: (read-file), (visit-file), (write-file).
+(insert-line)		~M (insert line)
+  Same as (beginning-of-line) (open-line)
+
+(kill-buffer)		^XK	args: buffer name, [yes or no]
+  Remove a buffer.  It disappears into ness-ness land.  Ask if the buffer
+    has been modified.  If the buffer is the only one on the screen,
+    replace it with the (next-buffer).  If it is the only buffer, replace
+    it with "main".
+  Defaults to the current buffer.
+  Command completion is on.
+  See also: (delete-other-windows).
+(kill-line)		^K or ~K (clear line)
+  Delete text from dot to the end of the line.
+    If an argument is given:
+	If n = 0: kill from beginning of line to dot.
+	If n > 0: kill forward over n newlines.
+	If n < 0: kill backword over n newlines.
+  The deleted text is put into the kill buffer or appended to the kill
+    buffer if the last command was also a kill command.
+  See also: (delete-next-word), (delete-previous-word),
+    (yank-from-killbuffer).
+(kill-region)		^W
+  Delete a region and save it in the kill buffer.  If the last command was
+    a kill command, append to the kill buffer.
+  See also: (copy-region), (yank-from-killbuffer).
+
+(list-buffers)		^X^B
+  List all the buffers currently loaded.  Magic buffers are not listed
+  (such as the list-buffers buffer).
+	C   Size Buffer           File
+	-   ---- ------           ----
+	     933 init.mut         ../init.mut
+	*  14287 me.doc           me.doc
+  C is * if the buffer is modified.  Size in bytes of the buffer or file.
+  File is the name of the file associated with a buffer.
+(load)		Not bound	args: file name
+  Load a file filled with MUT commands.
+  The file "init.mut" is loaded when ME is fired up (unless it does not
+  exist).
+  If the file is not in the current directory, it is looked
+    for in ME directory (pointed to by the ME environment variable).  Note
+    that the ME var must end with a slash (eg ME=A:\foo\).
+  See also: (execute-buffer), (execute-line), document on MUT programming.
+(mark-and-end)		~B (end)
+  Same as (set-mark) (end-of-buffer).
+  See also: (beginning-of-buffer), (end-of-buffer), (mark-and-home).
+(mark-and-home)		~A (end)
+  Same as (set-mark) (beginning-of-buffer).
+  See also: (beginning-of-buffer), (end-of-buffer), (mark-and-end).
+
+(newline)		^M
+  Insert a newline before the dot (visually before the cursor).
+  See also: (newline-and-indent), (open-line).
+(newline-and-indent)	^J
+  Insert a newline before the dot and duplicate the indentation of the
+    previous line (the one the dot just left).
+  See also: (newline), (open-line).
+(next-buffer)		Not bound
+  Replace the current buffer with the next buffer in the
+    buffer list.  The buffer list is in alphabetical order.
+  See also:  (list-buffers), (switch-to-buffer), (use-old-buffer).
+(next-line)		^N or ~D (down arrow)
+  Move the dot vertically down the screen.  Trys to stay in the same
+    column.
+  See also: (previous-line).
+(next-page)		^V or ~J (page down)
+  Scroll forwards a page (window size -2).
+  See also: (previous-page).
+(next-window)		^XN
+  Move to the next window down the screen and make it the current window.
+  See Also: (previous-window)
+(not-modified)		Not bound
+  Mark the current buffer as not modified.  When this has been done,
+    (save-buffer) will not write out the file until further changes are
+    made, (exit) won't complain about modified buffer, etc.
+
+(open-line)		^O (oh, not zero)
+  Insert a newline after the dot.  The dot does not move.
+  See also: (newline), (newline-and-indent).
+
+(previous-line)		^P or ~C (up arrow)
+  Move the dot vertically up the screen.  Trys to stay in the same
+    column.
+  See also: (next-line).
+(previous-page)		$V or ~I (page up)
+  Scroll backwards a page (window size -2).
+  See also: (next-page).
+(previous-window)	^XP
+  Move to the window immediately above the current window and make it the
+  current window.
+  See also: (next-window).
+
+(query-replace)		$Q	args: search string, replace string
+  Interactively search and replace strings.  The mark is set at the point
+    where the search started and returned there after a successful
+    (query-replace).
+  <ESC>,n,N : No, don't replace.  Go on to next match.
+  <SPACE>,y,Y : Yes, replace and go to next match.
+  ! : Replace all the rest without asking.
+  ^G : Abort.  The command stops and the cursor is left where it is.  To
+  	get to the start of the query-replace, use (exchange-dot-and-mark).
+  Patterns are saved across searches.  See (search-forward).
+  See also: (replace-string), (search-xxx).
+(quick-exit)		Not bound	args: [yes or no]
+  Write out the current buffer if it has changed, exit.  If any modified
+    buffers exist, ask about them.  If n, don't ask about modified buffers.
+  See also: (exit).
+(quote)			^Q or ^^ (control-^)
+  Insert the next character typed into the buffer.  This is how to get
+    control characters and the like into the buffer.
+  Note: This is not much use with ALT keys or softkeys.
+
+(read-file)		^X^R	args: file name, [yes or no]
+  Clear the current buffer (asking if the buffer has been modified) and read
+    in a file.
+  The file name defaults to the file name of the current buffer.
+  See also: (insert-file), (visit-file), (write-file).
+(refresh-screen)	^L
+  Repaint the screen.  If n, then center the dot vertically in the window.
+  See also: (center-cursor), (reposition-window).
+(rename-buffer)		Not bound	args: new file name
+  Change the file name associated with the current buffer.  If you want to
+    disassociate the buffer from a file, use a null response.
+  Command completion is on.
+(replace-string)	$R	args: search string, replace string
+  Search and replace string without asking.
+  Patterns are saved across searches.  See (search-forward).
+  See also: (query-replace), (search-xxx).
+(reposition-window)	$!
+  Move the current window so that the line the dot is on is n lines
+    from the top of the window.
+  If n<0, move the dot so that it is n lines from the bottom.
+  If n==0, the dot is centered vertically centered in the window.
+  See also: (center-cursor), (refresh-screen).
+
+(save-buffer)		^X^S
+  Write the current buffer to the file associated with it.  Does not
+    do anything if the buffer is unmodified.  If you want to force a write,
+    use (write-file).
+  See also:  (write-file).
+(scroll-down)		^X^N or ~O (oh) (roll up)
+  Move the current window down by a line.  Visually, the dot moves up the
+    screen.
+(scroll-up)		^X^P or ~P (roll down)
+  Move the current window up by a line.  Visually, the dot moves down the
+    screen.
+(search-forward)	^\ or ^S	args: search string
+(search-reverse)	^R		args: search string
+  Search for a string.
+  CR ends patterns, LF (^J) => start of line.
+	The pattern is saved across searches.  The pattern is also the
+	default search pattern for the replace commands.  Whenever the
+	search pattern changes, the replace pattern is cleared (this is so
+	you can replace something with nothing).
+  (search-forward) The dot is after the last character matched.
+  (search-reverse) The dot is before the last character matched, or put
+    another way, to the left of the first character of the search string.
+  See also: (query-replace), (replace-string).
+(set-fill-column)	^XF
+  Sets the column at which wordwrap is attempted.  Wordwrap is also turned
+    on.  If no n the fill-column is set to the current column.  If n==0,
+    turn off wordwrap.
+  See also: Note on wordwrap.
+(set-mark)		^@ or $SPACE or ~N (select)
+  Set the mark at the dot.  Visually, under the cursor.
+  See also: (exchange-dot-and-mark).
+(show-position)		^X=
+  Show stats in the form:
+	Row=rrr Col=c Y=y CH=h .=dddd (x% of z) Unused=a
+  where Row is the buffer row, Col is screen column, Y is screen row, CH is
+    the character after the dot, . is the position of the dot (the number of
+    characters between the beginning-of-buffer and dot), x% percent of the
+    buffer is before the dot, z is the size of the buffer and Unused is how
+    much wasted space there is in the buffer.
+(shrink-window)		^X^Z
+  Shrink the current window by a line.
+  See also: (enlarge-window).
+(spawn-cli)		^_
+  Jump to the operating system (shell) for a while.  ME is still loaded and
+    will sit in the background until you exit the shell (via exit in MS-DOS).
+  See also: (execute-monitor-command).
+(split-window)		^X2
+  Make 2 windows out of the current window.  A window with less than 3
+    lines  cannot be split.
+  See also: (delete-other-windows).
+(start-macro)		^X(
+  Start remembering keystrokes until (end-macro).
+  See also: (end-macro), (execute-macro).
+(switch-to-buffer)	^XB	args: buffer name
+  Replace the current window with another buffer.
+  Command completion is on.
+  See also: (list-buffers), (next-buffer), (use-old-buffer).
+
+(tab)			^I or the tab key
+  Set tab stops or insert a tab.
+  If given an argument then set the tab stops to every nth column.
+    If n==0 use the tab character.
+    If n>1 use spaces to simulate the tab character.
+  If no argument then move to the next tab stop.
+(transpose-characters)	^T
+  Swaps the 2 characters on either side of the dot.  If you want to change
+  "ab" to "ba" then put the cursor on the b and (transpose-characters).
+
+(use-old-buffer)	^X^O (oh)	args: name of existing buffer
+  Replace the current window with a buffer that already exists.
+  Command completion is on.
+  See also: (list-buffers), (switch-to-buffer).
+
+(version)		Not bound
+  Show the current version of ME.
+(visit-file)		^X^F or ^X^V	args: file name
+  Split the current buffer.  If the file (buffer) is already loaded, switch
+    to it.  Otherwise, read in the file.  The dot is set to the beginning of
+    the buffer and the mark is erased.
+  See also: (insert-file), (read-file), (write-file).
+
+(write-file)		^X^W	args: file name
+  Write the current buffer to a file.  If the file existed, it is
+    overwritten.  If the file does not already exist, it is created.
+  The file name defaults to the file name of the current buffer.
+  See also: (insert-file), (read-file), (save-buffer), (visit-file).
+
+(yank-from-killbuffer)	^Y
+  Insert the contents of the killbuffer before the dot (visually before the
+    cursor).  Does not affect the kill buffer.
+  The dot is left after the yanked text.  The mark does not move.
+  See also: (copy-region), (kill-region).
+
+VAR		COMMENTS
+HELP		Set the help level.  0 => no help.
+
+Notes:
+If you are being asked a question:
+  Key bindings are not in effect.  This means if have bound a normal key to
+	something by accident, you can unbind it without undo grief.
+  "Special" keys:
+    ^H or DEL	Backspace.
+    ^G	Abort out of the question.  Also causes command to be aborted.
+    ^I	Tab.
+    ^J	Returns the code for newline.  handy for searches.
+    ^M or return	End the question.
+    ^U	Erase everything and start over.
+    Control keys in general return the code for the key.
+    Function keys	return the function key itself NOT what its bound to.
+
+  If you answer the question by hitting <return or enter> and the line is
+    empty, you have entered the null line zone.  This can be interpreted as:
+	1.  An empty line.  It will then be ignored or complained about or
+	  stop the command.
+	2.  A ^M.  (bind-to-key) does this.
+	3.  A request to the default.  This is usually the current thing
+	  being manipulated (where thing is buffer, file, etc).
+	  eg (write-file) defaults to current file name and (kill-buffer)
+	  defaults to current buffer name.
+
+Command completion is triggered by the SPACE key.  Can be used if the
+	invoked command uses one of the lists that can be completed.
+  See also: (completion).
+
+Marks:  If the mark is at the dot (ie where it is when the mark is set) and
+  do something (insert text, yank text, etc), it is done between the dot
+  and mark, that is, the mark is before the change and the dot after.
+
+Word wrap:  Setting the (set-fill-column)>0 turns it on, 0 turns it off.
+	When you are typing at the end of a line and cross the fill column
+	the last "word" is wrapped to the next line.  If have some left
+	margin you wish to preserve, bind CR to newline-and-indent
+	(bind-to-key "newline-and-indent" "^M").
+
+What me does not have that emacs does (partial list):
+* file name completion
+* local key bindings
+* over write mode
+* recursive editing
+* regular expressions
+bunch more
+
+
+From: sun!oliveb!hplabs!hp-pcd!craig 
+Article 2072 of net.emacs:
+Relay-Version: version B 2.10.2 9/18/84 SMI; site sun.uucp
+Posting-Version: notesfiles - hp 1.2 08/01/83; site hp-pcd.UUCP
+Path: sun!oliveb!hplabs!hp-pcd!craig
+>From: craig at hp-pcd.UUCP (craig)
+Newsgroups: net.emacs
+Subject: Re: MicroEmacs manual
+Message-ID: <9900003 at hpcvlo.UUCP>
+Date: 20 Jul 86 06:38:00 GMT
+Date-Received: 21 Jul 86 23:22:53 GMT
+References: <9900001 at hpcvlo.UUCP>
+Organization: Hewlett-Packard - Corvallis, OR
+Lines: 189
+Nf-ID: #R:hpcvlo:9900001:hpcvlo:9900003:000:6422
+Nf-From: hpcvlo!craig    Jul 19 22:38:00 1986
+
+
+	MICROEMACS  COMMAND  SUMMARY
+	   Note: n means argument prefix (set by ^U).
+		dot is current cursor position.
+	^@	Set mark at current position (dot).
+	^A	Move cursor to beginning of line.
+	^B	Move cursor back one character.
+	^C	Exit without saving buffers (same as ^x^C).
+	^D	Delete current character.  If n then save to kill buffer.
+	^E	Move cursor to end of line.
+	^F	Move cursor forward one character.
+	^G	Abort any command. (shades of Teco).
+	^H	(backspace) Delete previous character.
+		  If n, save to kill buffer.
+	^I	Tab.  If n = 0 use tab.  If n>1, set tab stops & use blanks.
+	^J	Newline and match indent of previous line.
+	^K	Kill (delete) to end of line.
+		  If n = 0: kill from begining of line to dot.
+		  If n > 0: kill forward over n newlines.
+		  If n < 0: kill backword over n newlines.
+	^L	Redisplay screen.  If n, center cursor.
+	^M	Carriage return.
+	^N	Move cursor to next line.
+	^O	Open a new line.
+	^P	Move to previous line.
+	^Q	Quote the next character (insert the next character typed).
+	^R	Reverse search.
+	^S	Forward search.
+	^T	Transpose characters.
+	^U	Enter repeat count for next command (set n).
+	^V	View the next screen (scroll up one screen).
+	^W	Kill region (all text between cursor and last mark set).
+	^Y	Yank (undelete) last text killed (deleted).
+	^_	Push to a new interactive command shell.
+	^^	Quote the next character (same as ^Q).
+	^\	Forward search (same as ^S).
+	
+	^x!	Fork a command.
+	^x(	Begin keyboard macro.
+	^x)	End keyboard macro.
+	^x=	Show current position.
+	^x1	Display only current window.
+	^x2	Split the current window.
+	^xB	Prompt for new buffer.  If given n, buffer must exist.
+	^xE	Execute keyboard macro.
+	^xF	Set fill column (for word wrap).
+		  If n, set to n else set to current column.
+		  if n = 0, turn off word wrap.
+	^xK	Kill a buffer.
+	^xN	Move to next window.
+	^xP	Move to previous window.
+	^xZ	Enlarge current window by n lines.
+	
+	^x^B	Show active buffers.
+	^x^C	Exit without saving buffers.
+	^x^F	Visit file.
+	^x^G	Abort.
+	^x^I	Insert file at dot.
+	^x^L	Lower case region.
+	^x^N	Scroll current window up by n lines.
+	^x^O	Use old buffer.  Same as ^U^xB
+	^x^P	Scroll current window down by n lines.
+	^x^R	Read file into current buffer.  Defaults to current file name.
+	^x^S	Save (write) current buffer to its file.
+		  Only writes if changed.
+	^x^U	Uppercase region.
+	^x^V	Visit a file. Read file and display in current window.
+	^x^W	Write buffer to file.  Defaults to current file name.
+		  Always writes.
+	^x^X	Swap dot and mark.
+	^x^Z	Reduce current window by n lines.
+	
+	<del>	delete previous character.
+	
+	$!	Move current line to n lines from top of window.
+		if n = 0 center cursor.
+	$$	Execute-line.
+	$<space> Set mark.
+	$<	Move cursor to beginning of buffer.
+	$>	Move cursor to end of buffer.
+	$?	List all commands that have keyword in them.
+	$1, $2, $3, $4, $5, $6, $7, $8, $9
+		  Enter n for next command (like ^U).
+	$B	Move cursor back one word.
+	$C	Capitalize word.
+	$D	Delete next word.
+	$<del>	Delete previous word.
+	$F	Move cursor forward one word.
+	$G	Move cusor to line specified by n.
+ 	$^G	Abort.
+	$L	Lowercase next word.
+	$Q	Query replace.  Mark is set to begining of search.
+	$U	Uppercase next word.
+	$V	View the previous screen (scroll down one screen).
+	$W	Copy region to kill buffer.
+	$X	Execute meta command (such as goto-line).  Command
+		  completation when SPACE typed.
+
+      COMMAND			BINDING
+	PROGRAMS:
+	center-cursor              ~G 
+	delete-line                ~L 
+	insert-line                ~M 
+	mark-and-end               ~B 
+	mark-and-home              ~A 
+	COMMANDS:
+	abort                      ^G 
+	apropos                    $? 
+	backward-character         ^B ~F 
+	backward-word              $B 
+	beginning-of-buffer        $< 
+	beginning-of-line          ^A 
+	bind-to-key                Not bound
+	case-region-lower          ^X^L 
+	case-region-upper          ^X^U 
+	case-word-capitalize       $C 
+	case-word-lower            $L 
+	case-word-upper            $U 
+	completion                 Not bound
+	copy-region                $W 
+	decompile                  Not bound
+	delete-blank-lines         Not bound
+	delete-char                ^D ~H 
+	delete-next-word           $D 
+	delete-other-windows       ^X1 
+	delete-previous-character  ^H DEL 
+	delete-previous-word       $DEL $^H 
+	describe-bindings          Not bound
+	describe-key               Not bound
+	end-macro                  ^X) 
+	end-of-buffer              $> 
+	end-of-line                ^E 
+	enlarge-window             ^XZ 
+	exchange-dot-and-mark      ^X^X 
+	execute-buffer             Not bound
+	execute-extended-command   $X 
+	execute-line               $^[ 
+	execute-macro              ^XE 
+	execute-monitor-command    ^X! 
+	exit                       ^C ^X^C 
+	filter-region              Not bound
+	forward-character          ^F ~E 
+	forward-word               $F 
+	goto-line                  $G 
+	insert-file                ^X^I 
+	kill-buffer                ^XK 
+	kill-line                  ^K ~K 
+	kill-region                ^W 
+	list-buffers               ^X^B 
+	load                       Not bound
+	newline                    ^M 
+	newline-and-indent         ^J 
+	next-buffer                Not bound
+	next-line                  ^N ~D 
+	next-page                  ^V ~J 
+	next-window                ^XN 
+	not-modified               Not bound
+	open-line                  ^O 
+	previous-line              ^P ~C 
+	previous-page              $V ~I 
+	previous-window            ^XP 
+	query-replace              $Q 
+	quick-exit                 Not bound
+	quote                      ^^ ^Q 
+	read-file                  ^X^R 
+	refresh-screen             ^L 
+	rename-buffer              Not bound
+	replace-string             $R 
+	reposition-window          $! 
+	save-buffer                ^X^S 
+	scroll-down                ^X^N ~O 
+	scroll-up                  ^X^P ~P 
+	search-forward             ^\ ^S 
+	search-reverse             ^R 
+	set-fill-column            ^XF 
+	set-mark                   ^@ $SPACE ~N 
+	show-position              ^X= 
+	shrink-window              ^X^Z 
+	spawn-cli                  ^_ 
+	split-window               ^X2 
+	start-macro                ^X( 
+	switch-to-buffer           ^XB 
+	tab                        ^I 
+	transpose-characters       ^T 
+	use-old-buffer             ^X^O 
+	version                    Not bound
+	visit-file                 ^X^F ^X^V 
+	write-file                 ^X^W 
+	yank-from-killbuffer       ^Y 
+
+

Added: clients/emacs/menu.cmd
===================================================================
--- clients/emacs/menu.cmd	                        (rev 0)
+++ clients/emacs/menu.cmd	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,629 @@
+;	MENU.CMD:	Menu learning system for MicroEMACS 3.7
+;
+;			This file is executed to activate MicroEMACS's
+;			menu interface code
+
+;	setup windows for use
+
+	add-global-mode "blue"
+	1 split-current-window
+	5 resize-window
+	add-mode "red"
+	view-file "menu1"
+	name-buffer "menu window"
+	change-file-name ""
+	add-mode "view"
+	next-window
+
+;	Load menu routines as needed
+
+;	Activate Main Menu
+
+1	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<01"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key execute-macro-3	FN;
+	bind-to-key execute-macro-4	FN<
+	bind-to-key execute-macro-5	FN=
+	bind-to-key execute-macro-6	FN>
+	bind-to-key execute-macro-7	FN?
+	bind-to-key execute-macro-8	FN@
+	bind-to-key execute-macro-9	FNA
+	bind-to-key execute-macro-2	FNB
+	bind-to-key execute-macro-10	FNC
+	bind-to-key exit-emacs		FND
+	clear-message-line
+[end]
+
+;	and bring that menu up
+
+	execute-macro-1
+	write-message "         [loading MENU system]"
+
+;	set up the editor control menu
+
+2	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<02"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key execute-macro-11	FN;
+	bind-to-key execute-macro-12	FN<
+	bind-to-key execute-macro-13	FN=
+	bind-to-key execute-macro-14	FN>
+	bind-to-key execute-macro-15	FN?
+	bind-to-key execute-macro-16	FN@
+	bind-to-key execute-macro-17	FNA
+	bind-to-key execute-macro-18	FNB
+	bind-to-key execute-macro-19	FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+;	Activate word case/screen control Menu
+
+3	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<03"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key case-word-upper	FN;
+	bind-to-key case-region-upper	FN<
+	bind-to-key case-word-lower	FN=
+	bind-to-key case-region-lower	FN>
+	bind-to-key case-word-capitalize FN?
+	unbind-key FN@
+	bind-to-key clear-and-redraw	FNA
+	bind-to-key set-mark		FNB
+	bind-to-key redraw-display	FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+;	Activate paging/scrolling Menu
+
+4	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<08"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key previous-page	FN;
+	bind-to-key next-page		FN<
+	bind-to-key move-window-down	FN=
+	bind-to-key move-window-up	FN>
+	bind-to-key scroll-next-up	FN?
+	unbind-key 			FN@
+	bind-to-key scroll-next-down	FNA
+	unbind-key 			FNB
+	bind-to-key exchange-point-and-mark FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+;	Activate cut & paste Menu
+
+5	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<04"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key set-mark		FN;
+	unbind-key FN<
+	bind-to-key kill-region		FN=
+	unbind-key FN>
+	bind-to-key copy-region		FN?
+	unbind-key FN@
+	bind-to-key yank		FNA
+	unbind-key FNB
+	unbind-key FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+;	Activate Search & replace Menu
+
+6	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<09"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key search-forward	FN;
+	bind-to-key search-reverse	FN<
+	bind-to-key hunt-forward	FN=
+	bind-to-key hunt-backward	FN>
+	bind-to-key incremental-search	FN?
+	bind-to-key reverse-incremental-search FN@
+	bind-to-key replace-string	FNA
+	bind-to-key query-replace-string FNB
+	unbind-key FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+;	Activate Deletion Menu
+
+7	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<05"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key delete-previous-character FN;
+	unbind-key FN<
+	bind-to-key delete-next-character FN=
+	unbind-key FN>
+	bind-to-key kill-to-end-of-line	FN?
+	unbind-key FN@
+	bind-to-key delete-blank-lines	FNA
+	unbind-key FNB
+	unbind-key FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+;	Activate Word procesing Menu
+
+8	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<10"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key previous-word	FN;
+	bind-to-key next-word		FN<
+	bind-to-key previous-paragraph	FN=
+	bind-to-key next-paragraph	FN>
+	bind-to-key fill-paragraph	FN?
+	bind-to-key kill-paragraph	FN@
+	bind-to-key delete-previous-word FNA
+	bind-to-key delete-next-word	FNB
+	bind-to-key count-words		FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+;	Activate Insertion Menu
+
+9	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<06"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key open-line		FN;
+	bind-to-key insert-string	FN<
+	bind-to-key handle-tab		FN=
+	bind-to-key quote-character	FN>
+	bind-to-key insert-space	FN?
+	bind-to-key transpose-characters FN@
+	bind-to-key newline-and-indent	FNA
+	unbind-key FNB
+	bind-to-key newline		FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+;	Activate Cursor movement Menu
+
+10	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<07"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key begining-of-file	FN;
+	bind-to-key previous-line	FN<
+	bind-to-key backward-character	FN=
+	bind-to-key forward-character	FN>
+	bind-to-key end-of-file		FN?
+	bind-to-key next-line		FN@
+	bind-to-key begining-of-line	FNA
+	bind-to-key end-of-line		FNB
+	bind-to-key execute-macro-21	FNC
+	bind-to-key execute-macro-1	FND
+	clear-message-line
+[end]
+
+21	store-macro
+	"@Line number to go to: " goto-line
+[end]
+
+;	Activate Buffer Menu
+
+11	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<11"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key buffer-position	FN;
+	bind-to-key unmark-buffer	FN<
+	bind-to-key delete-buffer	FN=
+	bind-to-key next-buffer		FN>
+	bind-to-key list-buffers	FN?
+	bind-to-key execute-macro-22	FN@
+	bind-to-key name-buffer		FNA
+	unbind-key FNB
+	bind-to-key select-buffer	FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+22	store-macro
+	filter-buffer "@Name of DOS filter: "
+[end]
+;	Macro Menu
+
+12	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<11"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key begin-macro		FN;
+	unbind-key FN<
+	bind-to-key end-macro		FN=
+	unbind-key FN>
+	bind-to-key execute-macro	FN?
+	unbind-key FN@
+	unbind-key FNA
+	unbind-key FNB
+	unbind-key FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+;	Color change Menu
+
+13	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<12"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key execute-macro-23	FN;
+	unbind-key FN<
+	bind-to-key execute-macro-24	FN=
+	unbind-key FN>
+	bind-to-key execute-macro-25	FN?
+	unbind-key FN@
+	bind-to-key execute-macro-26	FNA
+	unbind-key FNB
+	unbind-key FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+;	Set forground color
+
+23	store-macro
+	save-window
+	1 next-window
+	select-buffer "[color]"
+	begining-of-file
+	insert-string "@Color to change to: "
+	newline
+	begining-of-file
+	case-word-upper
+	begining-of-file
+	unmark-buffer
+	select-buffer "menu window"
+	1 redraw-display
+	restore-window
+	add-mode "#[color]"
+	delete-buffer "[color]"
+[end]
+
+;	Set background color
+
+24	store-macro
+	save-window
+	1 next-window
+	select-buffer "[color]"
+	begining-of-file
+	insert-string "@Color to change to: "
+	newline
+	begining-of-file
+	case-word-lower
+	begining-of-file
+	unmark-buffer
+	select-buffer "menu window"
+	1 redraw-display
+	restore-window
+	add-mode "#[color]"
+	delete-buffer "[color]"
+[end]
+
+;	Set global forground color
+
+25	store-macro
+	save-window
+	1 next-window
+	select-buffer "[color]"
+	begining-of-file
+	insert-string "@Color to change to: "
+	newline
+	begining-of-file
+	case-word-upper
+	begining-of-file
+	unmark-buffer
+	select-buffer "menu window"
+	1 redraw-display
+	restore-window
+	add-global-mode "#[color]"
+	delete-buffer "[color]"
+[end]
+
+;	Set global background color
+
+26	store-macro
+	save-window
+	1 next-window
+	select-buffer "[color]"
+	begining-of-file
+	insert-string "@Color to change to: "
+	newline
+	begining-of-file
+	case-word-lower
+	begining-of-file
+	unmark-buffer
+	select-buffer "menu window"
+	1 redraw-display
+	restore-window
+	add-global-mode "#[color]"
+	delete-buffer "[color]"
+[end]
+
+;	set Mode Menu
+
+14	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<17"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key add-mode		FN;
+	bind-to-key add-global-mode	FN<
+	bind-to-key delete-mode		FN=
+	bind-to-key delete-global-mode	FN>
+	unbind-key FN?
+	bind-to-key execute-macro-27	FN@
+	unbind-key FNA
+	unbind-key FNB
+	bind-to-key select-buffer	FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+27	store-macro
+	"@Column to fill to: " set-fill-column
+[end]
+
+;	DOS command Menu
+
+15	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<13"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key shell-command	FN;
+	unbind-key FN<
+	bind-to-key pipe-command	FN=
+	unbind-key FN>
+	bind-to-key i-shell		FN?
+	unbind-key FN@
+	bind-to-key quick-exit		FNA
+	unbind-key FNB
+	bind-to-key exit-emacs		FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+;	Script Menu
+
+16	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<18"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key execute-file	FN;
+	bind-to-key execute-command-line FN<
+	bind-to-key execute-buffer	FN=
+	bind-to-key execute-named-command FN>
+	unbind-key FN?
+	unbind-key FN@
+	unbind-key FNA
+	unbind-key FNB
+	unbind-key FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+;	File access Menu
+
+17	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<14"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key find-file		FN;
+	bind-to-key save-file		FN<
+	bind-to-key view-file		FN=
+	bind-to-key write-file		FN>
+	bind-to-key read-file		FN?
+	bind-to-key change-file-name	FN@
+	bind-to-key insert-file		FNA
+	unbind-key FNB
+	unbind-key FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+;	Window Menu
+
+18	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<19"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key split-current-window FN;
+	bind-to-key delete-other-windows FN<
+	bind-to-key resize-window	FN=
+	bind-to-key delete-window	FN>
+	bind-to-key shrink-window	FN?
+	bind-to-key grow-window		FN@
+	bind-to-key next-window		FNA
+	bind-to-key previous-window	FNB
+	unbind-key FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+;	key binding Menu
+
+19	store-macro
+	save-window
+	1 next-window
+	begining-of-file
+	search-forward "<<15"
+	next-line
+	1 redraw-display
+	restore-window
+	update-screen
+
+;	***** Rebind the Function key group
+
+	bind-to-key bind-to-key		FN;
+	unbind-key FN<
+	bind-to-key unbind-key		FN=
+	unbind-key FN>
+	bind-to-key describe-key	FN?
+	unbind-key FN@
+	bind-to-key describe-bindings	FNA
+	unbind-key FNB
+	unbind-key FNC
+	bind-to-key execute-macro-2	FND
+	clear-message-line
+[end]
+
+	clear-message-line

Added: clients/emacs/menu1
===================================================================
--- clients/emacs/menu1	                        (rev 0)
+++ clients/emacs/menu1	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,115 @@
+--<<01>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 WORD CASE/SCREEN CONTROL   F2  PAGING/SCROLLING
+[Main Menu]         F3 CUT & PASTE                F4  SEARCH AND REPLACE
+                    F5 DELETION COMMANDS          F6  WORD PROCESSING
+                    F7 INSERTION COMMANDS         F8  EDITOR CONTROL
+ 06/18/86           F9 CURSOR MOVEMENT            F10 exit MicroEMACS
+--<<02>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 BUFFER CONTROL             F2  MACROS
+[Editor control]    F3 COLOR CHANGES              F4  MODES
+                    F5 DOS COMMANDS               F6  SCRIPTS
+                    F7 FILE ACCESS                F8  WINDOWS
+                    F9 KEY BINDINGS               F10 exit to MAIN MENU
+--<<03>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 upper case a word          F2  upper case a region
+ Word case &        F3 lower case a word          F4  lower case a region
+  Screen control    F5 capitilize a word
+                    F7 redraw the screen          F8  mark a region
+                    F9 center the current line    F10 exit to MAIN MENU
+--<<04>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1  mark a region
+  Cut & Paste       F3  delete the region
+                    F5  copy the region to the kill buffer
+                    F7  insert the kill buffer into the text here
+                                                  F10 exit to MAIN MENU
+--<<05>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 delete the last character
+  Deletions         F3 delete the next character
+                    F5 delete to the end of the current line
+                    F7 delete all the blank lines around the cursor
+                                                  F10 exit to MAIN MENU
+--<<06>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 open a blank line          F2  insert a prompted string
+  Insertion         F3 insert a tab               F4  quote the next character
+                    F5 insert a space             F6  transpose last 2 chars
+                    F7 insert a newline and indent like the last line
+                    F9 insert a newline           F10 exit to MAIN MENU
+--<<07>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 begining of the file       F2  up one line
+  Cursor Movement   F3 left                       F4  right
+        F^2         F5 end of the file            F6  down one line
+    F3 < + > F4     F7 begining of line           F8  end of line
+        FV6         F9 goto line                  F10 exit to MAIN MENU
+--<<08>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1  go up one page            F2  go down one page
+  Paging and        F3  scroll the screen up      F4  scroll the screen down
+     Scrolling      F5  make the next widow go up one page
+                    F7  make the next window go down one page
+                    F9  exchange cursor & mark    F10 exit to MAIN MENU
+--<<09>>-----------------------------------------------------------------------
+MicroEMACS 3.7      f1  search forward            f2  seach backwards
+  Search and        F3  hunt forward              f4  hunt backwards
+    Replace         F5  isearch forward           F6  isearch backward
+                    F7  replace string            F8  replace string w/query
+                                                  F10 exit to MAIN MENU
+--<<10>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 go back a word             F2  go forward a word
+  Word processing   F3 go back a paragraph        F4  go forward a paragraph
+                    F5 fill paragraph             F6  delete current paragraph
+                    F7 delete last word           F8  delete next word
+                    F9 count words in region      F10 exit to MAIN MENU
+--<<11>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 report position            F2  unmark buffer
+  Buffer Control    F3 delete buffer              F4  switch to next buffer
+                    F5 list all buffers           F6  filter buffer through
+                    F7 rename current buffer             DOS program
+                    F9 select buffer              F10 exit to CONTROL MENU
+--<<12>>-----------------------------------------------------------------------
+MicroEMACS 3.7      Colors:           |  F1 current window's forground color
+  Color changes       Black   Magenta |  F3 current window's background color
+                      Blue    Cyan    |  F5 global forground color
+                      Red     Yellow  |  F7 global background color
+                      Green   White   |           F10  exit to CONTROL MENU
+--<<13>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1  execute one DOS command
+  DOS commands      F3  pipe one DOS command to a buffer
+                    F5  shell up to a new command interpeter
+                    F7  QUICK exit (write out all changed buffers and exit)
+                    F9  exit MicroEMACS           F10 exit to CONTROL MENU
+--<<14>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 find file                  F2 save current file
+  File Access       F3 view file (in VIEW mode)   F4 write file w/ new name
+                    F5 read file into buffer      F6 change current file name
+                    F7 insert file into buffer
+                                                  F10  exit to CONTROL MENU
+--<<15>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 bind a function to a key
+  Key Bindings      F3 unbind a key
+                    F5 describe a key
+                    F7 describe all bindings
+                                                  F10  exit to CONTROL MENU
+--<<16>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 define macro         The keyboard macro only works
+  Keyboard Macro    F3 end macro            for standard commands, NOT for
+                    F5 execute macro        menu selections.
+
+                                                  F10  exit to CONTROL MENU
+--<<17>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 set mode                   F2  set global mode
+  Modes             F3 delete mode                F4  delete global mode
+            Standard modes are:                   F6  set fill column
+                WRAP  VIEW  CMODE  EXACT OVER MAGIC
+                                                  F10 exit to CONTROL MENU
+--<<18>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 execute script file        F2  execute script line
+  Script            F3 execute script in buffer   F4  execute command (by name)
+            Script line format:
+         {<repeat count>} <command name> {<argument(s)> | "<argument(s)>"}
+                                                  F10  exit to CONTROL MENU
+--<<19>>-----------------------------------------------------------------------
+MicroEMACS 3.7      F1 split current window       F2  delete all other windows
+  Windows           F3 resize window              F4  delete current window
+                    F5 shrink window              F6  enlarge window
+                    F7 next window                F8  previous window
+                                                  F10 exit to CONTROL MENU
+-------------------------------------------------------------------------------

Added: clients/emacs/ofwtermio.c
===================================================================
--- clients/emacs/ofwtermio.c	                        (rev 0)
+++ clients/emacs/ofwtermio.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,67 @@
+/*
+ * The functions in this file negotiate with the operating system for
+ * characters, and write characters in a barely buffered fashion on the display.
+ * All operating systems.
+ */
+
+#include	"estruct.h"
+#include        "edef.h"
+#include	"stdio.h"
+
+/*
+ * This function is called once to set up the terminal device streams.
+ */
+ttopen()
+{
+	/* on all screens we are not sure of the initial position
+	   of the cursor					*/
+	ttrow = 999;
+	ttcol = 999;
+}
+
+/*
+ * This function gets called just before we go back home to the command
+ * interpreter. It can be used to put the terminal back in a reasonable state.
+ */
+ttclose()
+{
+}
+
+/*
+ * Write a character to the display.
+ */
+ttputc(c)
+        char c;
+{
+        fputc(c, stdout);
+}
+
+/*
+ * Flush terminal buffer. Does real work where the terminal output is buffered
+ * up. A no-operation on systems where byte at a time terminal I/O is done.
+ */
+ttflush()
+{
+        fflush(stdout);
+}
+
+/*
+ * Read a character from the terminal, performing no editing and doing no echo
+ * at all.
+ */
+ttgetc()
+{
+        return(fgetc(stdin));
+}
+
+#if	TYPEAH
+/* typahead:	Check to see if any characters are already in the
+		keyboard buffer
+*/
+
+typahead()
+{
+	return(FALSE);
+}
+#endif
+

Added: clients/emacs/random.c
===================================================================
--- clients/emacs/random.c	                        (rev 0)
+++ clients/emacs/random.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,739 @@
+/*
+ * This file contains the command processing functions for a number of random
+ * commands. There is no functional grouping here, for sure.
+ */
+
+#include	"estruct.h"
+#include        "edef.h"
+
+int     tabsize;                        /* Tab size (0: use real tabs)  */
+
+/*
+ * Set fill column to n.
+ */
+setfillcol(f, n)
+{
+        fillcol = n;
+	mlwrite("[Fill column is %d]",n);
+        return(TRUE);
+}
+
+/*
+ * Display the current position of the cursor, in origin 1 X-Y coordinates,
+ * the character that is under the cursor (in hex), and the fraction of the
+ * text that is before the cursor. The displayed column is not the current
+ * column, but the column that would be used on an infinite width display.
+ * Normally this is bound to "C-X =".
+ */
+showcpos(f, n)
+{
+        register LINE   *lp;		/* current line */
+        register long   numchars;	/* # of chars in file */
+        register int	numlines;	/* # of lines in file */
+        register long   predchars;	/* # chars preceding point */
+        register int	predlines;	/* # lines preceding point */
+        register int    curchar;	/* character under cursor */
+        int ratio;
+        int col;
+	int savepos;			/* temp save for current offset */
+	int ecol;			/* column pos/end of current line */
+
+	/* starting at the begining of the buffer */
+        lp = lforw(curbp->b_linep);
+
+	/* start counting chars and lines */
+        numchars = 0;
+        numlines = 0;
+        while (lp != curbp->b_linep) {
+		/* if we are on the current line, record it */
+		if (lp == curwp->w_dotp) {
+			predlines = numlines;
+			predchars = numchars + curwp->w_doto;
+			if ((curwp->w_doto) == llength(lp))
+				curchar = '\n';
+			else
+				curchar = lgetc(lp, curwp->w_doto);
+		}
+		/* on to the next line */
+		++numlines;
+		numchars += llength(lp) + 1;
+		lp = lforw(lp);
+        }
+
+	/* if at end of file, record it */
+	if (curwp->w_dotp == curbp->b_linep) {
+		predlines = numlines;
+		predchars = numchars;
+	}
+
+	/* Get real column and end-of-line column. */
+	col = getccol(FALSE);
+	savepos = curwp->w_doto;
+	curwp->w_doto = llength(curwp->w_dotp);
+	ecol = getccol(FALSE);
+	curwp->w_doto = savepos;
+
+        ratio = 0;              /* Ratio before dot. */
+        if (numchars != 0)
+                ratio = (100L*predchars) / numchars;
+
+	/* summarize and report the info */
+	mlwrite("Line %d/%d Col %d/%d Char %D/%D (%d%%) char = 0x%x",
+		predlines+1, numlines+1, col, ecol,
+		predchars, numchars, ratio, curchar);
+        return (TRUE);
+}
+
+/*
+ * Return current column.  Stop at first non-blank given TRUE argument.
+ */
+getccol(bflg)
+int bflg;
+{
+        register int c, i, col;
+        col = 0;
+        for (i=0; i<curwp->w_doto; ++i) {
+                c = lgetc(curwp->w_dotp, i);
+                if (c!=' ' && c!='\t' && bflg)
+                        break;
+                if (c == '\t')
+                        col |= 0x07;
+                else if (c<0x20 || c==0x7F)
+                        ++col;
+                ++col;
+        }
+        return(col);
+}
+
+/*
+ * Twiddle the two characters on either side of dot. If dot is at the end of
+ * the line twiddle the two characters before it. Return with an error if dot
+ * is at the beginning of line; it seems to be a bit pointless to make this
+ * work. This fixes up a very common typo with a single stroke. Normally bound
+ * to "C-T". This always works within a line, so "WFEDIT" is good enough.
+ */
+twiddle(f, n)
+{
+        register LINE   *dotp;
+        register int    doto;
+        register int    cl;
+        register int    cr;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        dotp = curwp->w_dotp;
+        doto = curwp->w_doto;
+        if (doto==llength(dotp) && --doto<0)
+                return (FALSE);
+        cr = lgetc(dotp, doto);
+        if (--doto < 0)
+                return (FALSE);
+        cl = lgetc(dotp, doto);
+        lputc(dotp, doto+0, cr);
+        lputc(dotp, doto+1, cl);
+        lchange(WFEDIT);
+        return (TRUE);
+}
+
+/*
+ * Quote the next character, and insert it into the buffer. All the characters
+ * are taken literally, with the exception of the newline, which always has
+ * its line splitting meaning. The character is always read, even if it is
+ * inserted 0 times, for regularity. Bound to "C-Q"
+ */
+quote(f, n)
+{
+        register int    s;
+        register int    c;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        c = (*term.t_getchar)();
+        if (n < 0)
+                return (FALSE);
+        if (n == 0)
+                return (TRUE);
+        if (c == '\n') {
+                do {
+                        s = lnewline();
+                } while (s==TRUE && --n);
+                return (s);
+        }
+        return (linsert(n, c));
+}
+
+/*
+ * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
+ * tab into file.  If given argument, n, of zero, change to true tabs.
+ * If n > 1, simulate tab stop every n-characters using spaces. This has to be
+ * done in this slightly funny way because the tab (in ASCII) has been turned
+ * into "C-I" (in 10 bit code) already. Bound to "C-I".
+ */
+tab(f, n)
+{
+        if (n < 0)
+                return (FALSE);
+        if (n == 0 || n > 1) {
+                tabsize = n;
+                return(TRUE);
+        }
+        if (! tabsize)
+                return(linsert(1, '\t'));
+        return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
+}
+
+/*
+ * Open up some blank space. The basic plan is to insert a bunch of newlines,
+ * and then back up over them. Everything is done by the subcommand
+ * procerssors. They even handle the looping. Normally this is bound to "C-O".
+ */
+openline(f, n)
+{
+        register int    i;
+        register int    s;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (FALSE);
+        if (n == 0)
+                return (TRUE);
+        i = n;                                  /* Insert newlines.     */
+        do {
+                s = lnewline();
+        } while (s==TRUE && --i);
+        if (s == TRUE)                          /* Then back up overtop */
+                s = backchar(f, n);             /* of them all.         */
+        return (s);
+}
+
+/*
+ * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic
+ * indentation as specified.
+ */
+newline(f, n)
+{
+	register int    s;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+	if (n < 0)
+		return (FALSE);
+
+	/* if we are in C mode and this is a default <NL> */
+	if (n == 1 && (curbp->b_mode & MDCMOD) &&
+	    curwp->w_dotp != curbp->b_linep)
+		return(cinsert());
+
+	/* insert some lines */
+	while (n--) {
+		if ((s=lnewline()) != TRUE)
+			return (s);
+	}
+	return (TRUE);
+}
+
+cinsert()	/* insert a newline and indentation for C */
+
+{
+	register char *cptr;	/* string pointer into text to copy */
+	register int tptr;	/* index to scan into line */
+	register int bracef;	/* was there a brace at the end of line? */
+	register int i;
+	char ichar[NSTRING];	/* buffer to hold indent of last line */
+
+	/* grab a pointer to text to copy indentation from */
+	cptr = &curwp->w_dotp->l_text[0];
+
+	/* check for a brace */
+	tptr = curwp->w_doto - 1;
+	bracef = (cptr[tptr] == '{');
+
+	/* save the indent of the previous line */
+	i = 0;
+	while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t')
+		&& (i < NSTRING - 1)) {
+		ichar[i] = cptr[i];
+		++i;
+	}
+	ichar[i] = 0;		/* terminate it */
+
+	/* put in the newline */
+	if (lnewline() == FALSE)
+		return(FALSE);
+
+	/* and the saved indentation */
+	i = 0;
+	while (ichar[i])
+		linsert(1, ichar[i++]);
+
+	/* and one more tab for a brace */
+	if (bracef)
+		tab(FALSE, 1);
+
+	return(TRUE);
+}
+
+insbrace(n, c)	/* insert a brace into the text here...we are in CMODE */
+
+int n;	/* repeat count */
+int c;	/* brace to insert (always { for now) */
+
+{
+	register int ch;	/* last character before input */
+	register int i;
+	register int target;	/* column brace should go after */
+
+	/* if we are at the begining of the line, no go */
+	if (curwp->w_doto == 0)
+		return(linsert(n,c));
+		
+	/* scan to see if all space before this is white space */
+	for (i = curwp->w_doto - 1; i >= 0; --i) {
+		ch = lgetc(curwp->w_dotp, i);
+		if (ch != ' ' && ch != '\t')
+			return(linsert(n, c));
+	}
+
+	/* delete back first */
+	target = getccol(FALSE);	/* calc where we will delete to */
+	target -= 1;
+	target -= target % (tabsize == 0 ? 8 : tabsize);
+	while (getccol(FALSE) > target)
+		backdel(FALSE, 1);
+
+	/* and insert the required brace(s) */
+	return(linsert(n, c));
+}
+
+inspound()	/* insert a # into the text here...we are in CMODE */
+
+{
+	register int ch;	/* last character before input */
+	register int i;
+
+	/* if we are at the begining of the line, no go */
+	if (curwp->w_doto == 0)
+		return(linsert(1,'#'));
+		
+	/* scan to see if all space before this is white space */
+	for (i = curwp->w_doto - 1; i >= 0; --i) {
+		ch = lgetc(curwp->w_dotp, i);
+		if (ch != ' ' && ch != '\t')
+			return(linsert(1, '#'));
+	}
+
+	/* delete back first */
+	while (getccol(FALSE) >= 1)
+		backdel(FALSE, 1);
+
+	/* and insert the required pound */
+	return(linsert(1, '#'));
+}
+
+/*
+ * Delete blank lines around dot. What this command does depends if dot is
+ * sitting on a blank line. If dot is sitting on a blank line, this command
+ * deletes all the blank lines above and below the current line. If it is
+ * sitting on a non blank line then it deletes all of the blank lines after
+ * the line. Normally this command is bound to "C-X C-O". Any argument is
+ * ignored.
+ */
+deblank(f, n)
+{
+        register LINE   *lp1;
+        register LINE   *lp2;
+        long nld;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        lp1 = curwp->w_dotp;
+        while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
+                lp1 = lp2;
+        lp2 = lp1;
+        nld = 0;
+        while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
+                ++nld;
+        if (nld == 0)
+                return (TRUE);
+        curwp->w_dotp = lforw(lp1);
+        curwp->w_doto = 0;
+        return (ldelete(nld, FALSE));
+}
+
+/*
+ * Insert a newline, then enough tabs and spaces to duplicate the indentation
+ * of the previous line. Assumes tabs are every eight characters. Quite simple.
+ * Figure out the indentation of the current line. Insert a newline by calling
+ * the standard routine. Insert the indentation by inserting the right number
+ * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
+ * subcomands failed. Normally bound to "C-J".
+ */
+indent(f, n)
+{
+        register int    nicol;
+        register int    c;
+        register int    i;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (FALSE);
+        while (n--) {
+                nicol = 0;
+                for (i=0; i<llength(curwp->w_dotp); ++i) {
+                        c = lgetc(curwp->w_dotp, i);
+                        if (c!=' ' && c!='\t')
+                                break;
+                        if (c == '\t')
+                                nicol |= 0x07;
+                        ++nicol;
+                }
+                if (lnewline() == FALSE
+                || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
+                || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
+                        return (FALSE);
+        }
+        return (TRUE);
+}
+
+/*
+ * Delete forward. This is real easy, because the basic delete routine does
+ * all of the work. Watches for negative arguments, and does the right thing.
+ * If any argument is present, it kills rather than deletes, to prevent loss
+ * of text if typed with a big argument. Normally bound to "C-D".
+ */
+forwdel(f, n)
+{
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (backdel(f, -n));
+        if (f != FALSE) {                       /* Really a kill.       */
+                if ((lastflag&CFKILL) == 0)
+                        kdelete();
+                thisflag |= CFKILL;
+        }
+        return (ldelete((long)n, f));
+}
+
+/*
+ * Delete backwards. This is quite easy too, because it's all done with other
+ * functions. Just move the cursor back, and delete forwards. Like delete
+ * forward, this actually does a kill if presented with an argument. Bound to
+ * both "RUBOUT" and "C-H".
+ */
+backdel(f, n)
+{
+        register int    s;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (forwdel(f, -n));
+        if (f != FALSE) {                       /* Really a kill.       */
+                if ((lastflag&CFKILL) == 0)
+                        kdelete();
+                thisflag |= CFKILL;
+        }
+        if ((s=backchar(f, n)) == TRUE)
+                s = ldelete((long)n, f);
+        return (s);
+}
+
+/*
+ * Kill text. If called without an argument, it kills from dot to the end of
+ * the line, unless it is at the end of the line, when it kills the newline.
+ * If called with an argument of 0, it kills from the start of the line to dot.
+ * If called with a positive argument, it kills from dot forward over that
+ * number of newlines. If called with a negative argument it kills backwards
+ * that number of newlines. Normally bound to "C-K".
+ */
+killtext(f, n)
+{
+        register LINE   *nextp;
+        long chunk;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
+                kdelete();                      /* last wasn't a kill.  */
+        thisflag |= CFKILL;
+        if (f == FALSE) {
+                chunk = llength(curwp->w_dotp)-curwp->w_doto;
+                if (chunk == 0)
+                        chunk = 1;
+        } else if (n == 0) {
+                chunk = curwp->w_doto;
+                curwp->w_doto = 0;
+        } else if (n > 0) {
+                chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
+                nextp = lforw(curwp->w_dotp);
+                while (--n) {
+                        if (nextp == curbp->b_linep)
+                                return (FALSE);
+                        chunk += llength(nextp)+1;
+                        nextp = lforw(nextp);
+                }
+        } else {
+                mlwrite("neg kill");
+                return (FALSE);
+        }
+        return(ldelete(chunk, TRUE));
+}
+
+setmode(f, n)	/* prompt and set an editor mode */
+
+int f, n;	/* default and argument */
+
+{
+	adjustmode(TRUE, FALSE);
+}
+
+delmode(f, n)	/* prompt and delete an editor mode */
+
+int f, n;	/* default and argument */
+
+{
+	adjustmode(FALSE, FALSE);
+}
+
+setgmode(f, n)	/* prompt and set a global editor mode */
+
+int f, n;	/* default and argument */
+
+{
+	adjustmode(TRUE, TRUE);
+}
+
+delgmode(f, n)	/* prompt and delete a global editor mode */
+
+int f, n;	/* default and argument */
+
+{
+	adjustmode(FALSE, TRUE);
+}
+
+adjustmode(kind, global)	/* change the editor mode status */
+
+int kind;	/* true = set,		false = delete */
+int global;	/* true = global flag,	false = current buffer flag */
+{
+	register char *scan;		/* scanning pointer to convert prompt */
+	register int i;			/* loop index */
+#if	COLOR
+	register int uflag;		/* was modename uppercase?	*/
+#endif
+	char prompt[50];	/* string to prompt user with */
+	char cbuf[NPAT];		/* buffer to recieve mode name into */
+
+	/* build the proper prompt string */
+	if (global)
+		strcpy(prompt,"Global mode to ");
+	else
+		strcpy(prompt,"Mode to ");
+
+	if (kind == TRUE)
+		strcat(prompt, "add: ");
+	else
+		strcat(prompt, "delete: ");
+
+	/* prompt the user and get an answer */
+
+	mlreply(prompt, cbuf, NPAT - 1);
+
+	/* make it uppercase */
+
+	scan = cbuf;
+#if	COLOR
+	uflag = (*scan >= 'A' && *scan <= 'Z');
+#endif
+	while (*scan != 0) {
+		if (*scan >= 'a' && *scan <= 'z')
+			*scan = *scan - 32;
+		scan++;
+	}
+
+	/* test it first against the colors we know */
+	for (i=0; i<NCOLORS; i++) {
+		if (strcmp(cbuf, cname[i]) == 0) {
+			/* finding the match, we set the color */
+#if	COLOR
+			if (uflag)
+				if (global)
+					gfcolor = i;
+				else
+					curwp->w_fcolor = i;
+			else
+				if (global)
+					gbcolor = i;
+				else
+					curwp->w_bcolor = i;
+
+			curwp->w_flag |= WFCOLR;
+#endif
+			mlerase();
+			return(TRUE);
+		}
+	}
+
+	/* test it against the modes we know */
+
+	for (i=0; i < NUMMODES; i++) {
+		if (strcmp(cbuf, modename[i]) == 0) {
+			/* finding a match, we process it */
+			if (kind == TRUE)
+				if (global)
+					gmode |= (1 << i);
+				else
+					curwp->w_bufp->b_mode |= (1 << i);
+			else
+				if (global)
+					gmode &= ~(1 << i);
+				else
+					curwp->w_bufp->b_mode &= ~(1 << i);
+			/* display new mode line */
+			if (global == 0)
+				upmode();
+			mlerase();	/* erase the junk */
+			return(TRUE);
+		}
+	}
+
+	mlwrite("No such mode!");
+	return(FALSE);
+}
+
+/*	This function simply clears the message line,
+		mainly for macro usage			*/
+
+clrmes(f, n)
+
+int f, n;	/* arguments ignored */
+
+{
+	mlwrite("");
+	return(TRUE);
+}
+
+/*	This function writes a string on the message line
+		mainly for macro usage			*/
+
+writemsg(f, n)
+
+int f, n;	/* arguments ignored */
+
+{
+	register char *sp;	/* pointer into buf to expand %s */
+	register char *np;	/* ptr into nbuf */
+	register int status;
+	char buf[NPAT];		/* buffer to recieve mode name into */
+	char nbuf[NPAT*2];	/* buffer to expand string into */
+
+	if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE)
+		return(status);
+
+	/* expand all '%' to "%%" so mlwrite won't expect arguments */
+	sp = buf;
+	np = nbuf;
+	while (*sp) {
+		*np++ = *sp;
+		if (*sp++ == '%')
+			*np++ = '%';
+	}
+	*np = '\0';
+	mlwrite(nbuf);
+	return(TRUE);
+}
+
+/*	Close fences are matched against their partners, and if
+	on screen the cursor briefly lights there		*/
+
+fmatch(ch)
+
+char ch;	/* fence type to match against */
+
+{
+	register LINE *oldlp;	/* original line pointer */
+	register int oldoff;	/* and offset */
+	register LINE *toplp;	/* top line in current window */
+	register int count;	/* current fence level count */
+	register char opench;	/* open fence */
+	register char c;	/* current character in scan */
+	register int i;
+
+	/* first get the display update out there */
+	update(FALSE);
+
+	/* save the original cursor position */
+	oldlp = curwp->w_dotp;
+	oldoff = curwp->w_doto;
+
+	/* setup proper open fence for passed close fence */
+	if (ch == ')')
+		opench = '(';
+	else
+		opench = '{';
+
+	/* find the top line and set up for scan */
+	toplp = curwp->w_linep->l_bp;
+	count = 1;
+	backchar(FALSE, 2);
+
+	/* scan back until we find it, or reach past the top of the window */
+	while (count > 0 && curwp->w_dotp != toplp) {
+		c = lgetc(curwp->w_dotp, curwp->w_doto);
+		if (c == ch)
+			++count;
+		if (c == opench)
+			--count;
+		backchar(FALSE, 1);
+		if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp &&
+		    curwp->w_doto == 0)
+			break;
+	}
+
+	/* if count is zero, we have a match, display the sucker */
+	/* there is a real machine dependant timing problem here we have
+	   yet to solve......... */
+	if (count == 0) {
+		forwchar(FALSE, 1);
+		for (i = 0; i < term.t_pause; i++)
+			update(FALSE);
+	}
+
+	/* restore the current position */
+	curwp->w_dotp = oldlp;
+	curwp->w_doto = oldoff;
+	return(TRUE);
+}
+
+istring(f, n)	/* ask for and insert a string into the current
+		   buffer at the current point */
+
+int f, n;	/* ignored arguments */
+
+{
+	register char *tp;	/* pointer into string to add */
+	register int status;	/* status return code */
+	char tstring[NPAT+1];	/* string to add */
+
+	/* ask for string to insert */
+	status = mlreplyt("String to insert<ESC>: ", tstring, NPAT, 27);
+	if (status != TRUE)
+		return(status);
+
+	/* insert it */
+	tp = &tstring[0];
+	while (*tp) {
+		if (*tp == 0x0a)
+			status = lnewline();
+		else
+			status = linsert(1, *tp);
+		++tp;
+		if (status != TRUE)
+			return(status);
+	}
+	return(TRUE);
+}
+

Added: clients/emacs/readme
===================================================================
--- clients/emacs/readme	                        (rev 0)
+++ clients/emacs/readme	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,48 @@
+This directory contains the C source code for MicroEMACS 3.7 .
+
+MicroEMACS is an implementation of the EMACS text editor that was
+written and placed in the public domain by Dave Conroy, circa 1985.
+Daniel Lawrence subsequently extended it quite substantially,
+creating the 3.x series of versions.
+
+Version 3.7 is the last version that was released to the public domain.
+
+Version 3.8 and subsequent versions are copyrighted by Daniel Lawrence.
+3.11 is the latest version that I know of; it was relased in late 1991
+or early 1992.  The copyrighted versions have been made available to
+users under quite generous terms, but they cannot be incorporated into
+commercial products.  That is the one of the reasons why version 3.7,
+and not a more recent version, is included with Forthmacs.
+
+Another reason is "creeping featurism".  Many of the later features
+are, in my opinion, of marginal utility, and the size of the 3.11
+distribution is much larger than the 3.7 distribution.  Some of the
+new features (such as mouse support) are worthwhile, but the whole
+package is just too big to deal with (some people may think the same
+of Forthmacs!).
+
+This copy of MicroEMACS 3.7 has been modified slightly.  A few of the
+modifications are simple bug fixes.  The others are changes that were
+necessary in order to make MicroEMACS callable from Forth, so that
+you could go back and forth between Forth and MicroEMACS, without
+losing either environment's state.  Primarily, this involved changes
+in the initilization code and elimination of calls to "exit()" (they
+now essentially do subroutine returns rather than process exits).
+
+The other category of changes, limited to the ibmpc.c file, involved
+making the video driver work under 32-bit protected mode.  This was
+accomplished by using a far pointer to access the video memory.
+
+I also changed the binding of the F1 function key in the emacs.rc
+startup file, so it now executes the help function (DOS applications
+commonly use F1 for help).
+
+In this directory, MicroEMACS may be compiled either as a self-contained
+application (EMACS.EXE) or as a component of Forth (a set of subroutines
+linked into FORTH.EXE).  See the makefile in this directory for more
+information.  The makefile is set up to compile with Zortech C++.  It
+would be possible to compile the self-contained version of EMACS with
+another C compiler, such as Microsoft C or Borland C.  However, the
+"component of Forth" version must currently be compiled with Zortech C++,
+since Forth requires the 32-bit code generation and DOS Extender features
+of Zortech C++.

Added: clients/emacs/readme.dl
===================================================================
--- clients/emacs/readme.dl	                        (rev 0)
+++ clients/emacs/readme.dl	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,382 @@
+		MicroEMACS 3.7 release notes
+
+	First off, I would like to thank all the people that send in
+various comments, bug fixes and code segments.  I have included as many
+of these as possible in this current source.  All the new features which
+are larger than a couple of lines are IFDEF'ed by symbols in the
+ESTRUCT.H header file.  As long as everyone keeps sending these in, I
+will keep trying to incorporate them, at least in spirit. 
+
+	Installation is fairly straight forward.  Copy or compile the
+appropriate version of the editor into EMACS (EMACS.EXE on MS/PC DOS)
+somewhere on your executable path.  Then copy the emacs.hlp file to one
+of the directories names in the epath.h file for your system.  A startup
+file .emacsrc (EMACS.RC on PC/MS DOS) can be placed in the directory
+pointed to by your HOME environment variable. 
+	
+[	Note for AMIGA users: Lattice 3.02 was giving me some rather
+mysterious software task failure errors while compiling some of the
+modules. Not having the Amiga long enough to solve this, I upgraded to
+Lattice 3.03 and these problems disappeared. If enough people are stuck
+with 3.02 and someone comes up with a fix and sends it to me, I will
+incorporate it into the master sources. Remember to say "stack 16000"
+before compiling the larger files.]
+
+	A new reference manual with a listing of all the commands and
+descriptions is now included.  Commands are listed in logical groups.
+Also coming in the near future will be a beginner's document to replace
+"emacs.tut".
+
+	Also included are two files, "menu.cmd" and "menu1" that make up
+a simple menu driven interface to MicroEMACS 3.7.  For people who prefer
+menu driven interfaces, rename "menu.cmd" as "emacs.rc" and place it
+where a startup file would be expected.  Also find a place for the text
+file "menu1" and change your "emacs.rc" to view-file from that directory
+for "menu1".
+
+	MicroEMACS 3.7 is distributed on three 5 1/4" diskettes, or as one
+3 1/2" diskette, or as apx. ten shell archives.  The shell archives are
+posted to USENET mod.sources and do not include the executable files. 
+The executable PC and AMIGA versions will also be posted in the relevent
+USENET groups. 
+
+Disk ONE contains:
+
+	readme		this file
+
+	acemacs.exe	MSDOS ansi color executable
+	icemacs.exe	PCDOS color executable
+
+	ebind.h		default biding structures
+	edef.h		static global data declarations
+	efunc.h		function names binding table
+	epath.h		help/startup file path definitions
+	estruct.h	structure and configuration header file
+
+	emacs.hlp	online help file
+	emacs.key	command wall chart
+	emacs.rc	standard startup file
+	emacs2.mss	reference manual (in MicroSCRIBE format)
+	emacs.tut	beginers tutorial file
+	makefile	UNIX V7/BSD 4.2 compilation command file
+	azmap.cmd	an example MicroEMACS macro file
+	menu.cmd	Menu driven command driver script
+	menu1		data file for menu.cmd
+
+Disk TWO contains:
+
+	ansi.c		ANSI screen driver
+	basic.c		cursor movement
+	bind.c		bind/unbind and help commands
+	buffer.c	buffer management
+	display.c	display update functions
+	dg10.c		Data General System/10 screen driver
+	exec.c		macro line execution functions
+	file.c		use file commands
+	fileio.c	file I/O functions
+	hp150.c		HP150 screen/keyboard driver
+	ibmpc.c		IBM-PC screen driver
+	input.c		message line input routines
+	isearch.c	interactive search commands
+	line.c		line editing functions
+	lock.c		file locking front end
+	main.c		command line and keyboard command parsing
+	random.c	some random commands
+	region.c	wipe/copy/yank commands
+	search.c	normal search commands
+	spawn.c		DOS interface commands
+	tcap.c		UNIX screen drivers
+	termio.c	Keyboard I/O routines
+	vmsvt.c		VMS screen drivers
+	vt52.c		VT52 screen drivers
+	window.c	window management commands
+	word.c		word move/delete/reformat commands
+
+Disk THREE contains:
+
+	hpemacs.exe	HP150 executable
+	dgemacs.exe	Data General System/10 executable
+	wgemacs.exe	Wang PC executable
+	amemacs.exe	Commodore AMIGA executable
+
+	The next version of MicroEMACS (3.8) will probably not be until
+late fall 1986, but it will probably be accompanied by the first version
+of MicroSCRIBE, a text formater to go along with MicroEMACS.  As I will
+continue to support MicroEMACS, ideas, comments, bug fixes and new code
+should be send to:
+
+	Daniel Lawrence
+	617 New York St
+	Lafayette, IN 47091
+
+	or
+
+	ihnp4!pur-ee!pur-phy!duncan!lawrence on USENET
+
+	and, as before, copies of MicroEMACS 3.7 may be gotten by
+sending a self addressed, self stamped mailer with two 5 1/4" diskettes
+to the above address.
+
+-------------------------------------------------------------------------------
+		MicroEMACS 3.7	-	New Features
+
+***	COLOR!!!!
+
+	The forground and backgound color of buffers may be set
+with the add-mode and add-global-mode commands. Forgound colors
+are set with capitalized color names, and background colors with
+lower case color names. Availible colors are the ANSI color set:
+
+black, blue, red, green, yellow, cyan, magenta, and white
+
+	This feature is only availible on machines that support
+color properly in text mode. (IBM-PC w/color graphics adapter
+and its clones)
+
+***	Pipe command
+
+	The pipe-command (^X-@) command allows you to execute an
+operating system command and send the results into a buffer.
+MicroEMACS will make a buffer by the name of "command" for the
+results. This is only supported on systems that allow I/O redirection.
+
+***	Filter buffer
+
+	The filter-buffer (^X-#) command allows you to send an
+existing buffer's contents through a filter which runs under the
+current operating system. The result replaces the contents of
+the current buffer (beware of non-existant filters). Its a good
+idea to make a backup of the buffer to be filtered.
+
+***	Switchar is fixed
+
+	MicroEMACS under PC/MS DOS no longer cares about the
+setting of the switchar. It uses the DOS call to look it up and
+use it in its fork and system calls.
+
+***	CMODE is configurable
+
+	Automatic entering of CMODE for .c and .h extension
+files is now configurable with the ACMODE symbol in estruct.h
+
+***	Query-replace UNDO command
+
+	While making a query-replace (M-^R) run, the U key now
+undoes the last replace.
+
+***	New cursor position report
+
+	Re-wrote the buffer-position (^X-=) command to give more
+usefull information on # lines in file, current line and column,
+percentage of text before cursor and the hex value of the
+character the cursor is on.
+
+***	Word wrapping improved
+
+	Words are now only broken at spaces and tabs by the word
+wrapping algorithm. No more disapearing punctuation delimiters.
+
+***	IBM-PC Color board display driver
+
+	A new screen driver for the IBM-PC color board is in the
+file IBMPC.C and this vastly improves the paging speed and
+eliminates the retrace flicker. However, under the color
+version, the update while adding text is a little more slugish
+than I would hope. We will be working to improve this in the future.
+
+***	Destroying windows!!
+
+	A new command, delete-window (^X-0 [zero]) allows you to
+delete just the current window from the screen, leaving all the
+others intact, (and one of them bigger). This is very convient
+when you have a lot of windows on the screen.
+
+***	Execute Macro commands
+
+	Buffers holding commands can now be executed as a "macro". The
+names of these buffers is in the form "[Macro nn]" where nn is a number
+from 1 to 20.  Each buffer has a corrosponding execute-macro-nn command,
+the first ten of which are bound to the shifted function keys on the IBM
+versions.
+
+***	Macro loading
+
+	Macroes can be loaded from a command file (or startup file) with
+the use of the store-macro command. For example, to make macro 5 insert
+a blank line at the begining of the current line, one would put the
+following in their startup file:
+
+;	Open up a line before the current line
+
+5 store-macro
+	begining-of-line
+	open-line
+[end]
+
+	more details on this can be found in the standard startup file
+and the reference manual.
+
+***	Clear message line
+
+	Sometimes when executing macroes you want the last command not
+to leave a message on the message line at the bottom of the screen. The
+clear-message-line command does just that.
+
+***	Absolute window resizing
+
+	This new command, resize-window (^X-W) allows you to specify the
+number of lines you wish to have in the current window. For example,
+M 12 ^X W forces the current window to a size of 12 lines if possible.
+
+***	Interactive macro arguments
+
+	When executing a command line, if any of the arguments begin
+with an at sign (@) MicroEMACS will prompt the user for that argument on
+the message line, using whatever text follows. A quick macro
+demonstating this can be:
+
+;	consult file
+2 store-macro
+	2 split-current-window
+	previous-window
+	view-file "@File to Consult: "
+	8 resize-window
+	add-mode "green"
+	add-mode "Black"
+	next-window
+[end]
+
+***	Buffer Macro arguments
+
+	When executing a command line, any arguments begining with a
+pound sign (#) mean that the argument is to be fetched from the current
+line of the named buffer. The point in that buffer is then advanced one
+line if that buffer is not currently being displayed.
+
+***	Split window modified
+
+	The split window command normally leaves the cursor in the window
+where the cursor was originaly. Now a numeric argument of one forces the
+cursor into the upper window, and an argument of 2 forces the cursor
+into the lower window.
+
+***	MicroSoft C compiler support
+
+	The MicroSoft C compiler (version 3) now can be used
+successfully to compile MicroEMACS. Use the large data, small program
+model for best results. Thanks to Oliver Sharp for the needed
+modifications.
+
+***	VMS terminal support upgraded
+
+	VMS now uses the newer terminal modes when executing MicroEMACS.
+Also some bugs were fixed. Both of these are thanks to Guy Streeter.
+
+***	CMODE enhanced
+
+	Lines starting with # as the first non-blank character (ie
+pre-processer directives) force the # into column one.  Also, if
+matching open parenthises and braces are being displayed when the
+closing one is typed, the cursor will breifly flash to the open and
+back.
+
+***	Special character quoting
+
+	When typing in search/replace strings, ^Q quotes the following
+character, allowing keys like <ESC> to be searched for.
+
+***	Bindable prefix keys
+
+	The META and ^X prefixes may now be bound to other keys. Only
+one key may be a prefix key at a time, when one of these is rebound, the
+old key is automatically unbound.
+
+***	New command line options
+
+	@<file>		Specifies an alternative startup file(s) to
+			run instead of emacs.rc or .emacsrc
+
+	-g<n>		go to line <n> of the first file read in
+
+	-s<string>	search the first file for <string> and leave
+			the cursor there.
+
+***	Wang keyboard support
+
+	The Wang-PC keyboard and is function keys are now supported.
+(Define WANG in estruct.h as 1) Thanks to Sid Shapiro for this code.
+
+***	System V support
+
+	Unix system V should now compile and execute MicroEMACS
+properly. Code for this was submited by Linwood Varney.
+
+***	Unix definitions reorginized
+
+	Now only ONE of the unix symbols should be defined when
+compiling on unices.
+
+***	Incremental Search added
+
+	For those clamering for it.....Isearch commands. This code was
+submited by D. R. Banks and seems to work well. (Later we will merge it
+with parts of the normal searching code to conserve space) This is
+availible conditionally depending on the ISRCH symbol in estruct.h
+
+***	Insert string command
+
+	The insert-string command (unbound) allows you to insert text
+into a line from a macro.  This can be used to build special help and
+text screens.
+
+***	Unmark buffer command
+
+	The unmark-command (unbound) allows you to unmark a buffer. 
+This will keep the exit commands from complaining abount unchanged
+buffers.  This is most usefull when you have built up a text screen from
+a macro and have no intention of saving it.
+
+***	Special characters
+
+	Inside of string argument in macroes, the following special
+characters are active:
+
+	~n	newline
+	~t	tab
+	~b	backspace
+	~f	formfeed
+
+***	Fixed large file problems
+
+	Several problems caused by keeping character counts in integers
+have been fixed by making these counts be longs.  Also regions can now
+be larger than 65535 chars.
+
+***	Kill buffer re-coded
+
+	New kill buffer routines should (and do) work faster.  Also an
+unlimited (except by RAM) amount of text can be killed safely.
+
+***	Word counting
+
+	The count-words (M-^C) command counts the number of words,
+characters and lines in the current region.  It also gives an average
+words/character total. 
+
+***	Changed delete-word behavior
+
+	Delete-next-word no longer kills the newline as it deletes tha
+last word on the line.  It does however then delete the newline as it
+deletes the first word on the next line.
+
+***	Next/Previous buffer cammands augmented
+
+	Both now take a numeric argument to switch to the nth window
+from the top/bottom.
+
+***	Data General Support
+
+	MicroEMACS now supprts the Data General System/10 computer under
+MSDOS.
+
+

Added: clients/emacs/region.c
===================================================================
--- clients/emacs/region.c	                        (rev 0)
+++ clients/emacs/region.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,205 @@
+/*
+ * The routines in this file
+ * deal with the region, that magic space
+ * between "." and mark. Some functions are
+ * commands. Some functions are just for
+ * internal use.
+ */
+#include	"estruct.h"
+#include        "edef.h"
+
+/*
+ * Kill the region. Ask "getregion"
+ * to figure out the bounds of the region.
+ * Move "." to the start, and kill the characters.
+ * Bound to "C-W".
+ */
+killregion(f, n)
+{
+        register int    s;
+        REGION          region;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if ((s=getregion(&region)) != TRUE)
+                return (s);
+        if ((lastflag&CFKILL) == 0)             /* This is a kill type  */
+                kdelete();                      /* command, so do magic */
+        thisflag |= CFKILL;                     /* kill buffer stuff.   */
+        curwp->w_dotp = region.r_linep;
+        curwp->w_doto = region.r_offset;
+        return (ldelete(region.r_size, TRUE));
+}
+
+/*
+ * Copy all of the characters in the
+ * region to the kill buffer. Don't move dot
+ * at all. This is a bit like a kill region followed
+ * by a yank. Bound to "M-W".
+ */
+copyregion(f, n)
+{
+        register LINE   *linep;
+        register int    loffs;
+        register int    s;
+        REGION          region;
+
+        if ((s=getregion(&region)) != TRUE)
+                return (s);
+        if ((lastflag&CFKILL) == 0)             /* Kill type command.   */
+                kdelete();
+        thisflag |= CFKILL;
+        linep = region.r_linep;                 /* Current line.        */
+        loffs = region.r_offset;                /* Current offset.      */
+        while (region.r_size--) {
+                if (loffs == llength(linep)) {  /* End of line.         */
+                        if ((s=kinsert('\n')) != TRUE)
+                                return (s);
+                        linep = lforw(linep);
+                        loffs = 0;
+                } else {                        /* Middle of line.      */
+                        if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
+                                return (s);
+                        ++loffs;
+                }
+        }
+        return (TRUE);
+}
+
+/*
+ * Lower case region. Zap all of the upper
+ * case characters in the region to lower case. Use
+ * the region code to set the limits. Scan the buffer,
+ * doing the changes. Call "lchange" to ensure that
+ * redisplay is done in all buffers. Bound to
+ * "C-X C-L".
+ */
+lowerregion(f, n)
+{
+        register LINE   *linep;
+        register int    loffs;
+        register int    c;
+        register int    s;
+        REGION          region;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if ((s=getregion(&region)) != TRUE)
+                return (s);
+        lchange(WFHARD);
+        linep = region.r_linep;
+        loffs = region.r_offset;
+        while (region.r_size--) {
+                if (loffs == llength(linep)) {
+                        linep = lforw(linep);
+                        loffs = 0;
+                } else {
+                        c = lgetc(linep, loffs);
+                        if (c>='A' && c<='Z')
+                                lputc(linep, loffs, c+'a'-'A');
+                        ++loffs;
+                }
+        }
+        return (TRUE);
+}
+
+/*
+ * Upper case region. Zap all of the lower
+ * case characters in the region to upper case. Use
+ * the region code to set the limits. Scan the buffer,
+ * doing the changes. Call "lchange" to ensure that
+ * redisplay is done in all buffers. Bound to
+ * "C-X C-L".
+ */
+upperregion(f, n)
+{
+        register LINE   *linep;
+        register int    loffs;
+        register int    c;
+        register int    s;
+        REGION          region;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if ((s=getregion(&region)) != TRUE)
+                return (s);
+        lchange(WFHARD);
+        linep = region.r_linep;
+        loffs = region.r_offset;
+        while (region.r_size--) {
+                if (loffs == llength(linep)) {
+                        linep = lforw(linep);
+                        loffs = 0;
+                } else {
+                        c = lgetc(linep, loffs);
+                        if (c>='a' && c<='z')
+                                lputc(linep, loffs, c-'a'+'A');
+                        ++loffs;
+                }
+        }
+        return (TRUE);
+}
+
+/*
+ * This routine figures out the
+ * bounds of the region in the current window, and
+ * fills in the fields of the "REGION" structure pointed
+ * to by "rp". Because the dot and mark are usually very
+ * close together, we scan outward from dot looking for
+ * mark. This should save time. Return a standard code.
+ * Callers of this routine should be prepared to get
+ * an "ABORT" status; we might make this have the
+ * conform thing later.
+ */
+getregion(rp)
+register REGION *rp;
+{
+        register LINE   *flp;
+        register LINE   *blp;
+        long fsize;
+        long bsize;
+
+        if (curwp->w_markp == NULL) {
+                mlwrite("No mark set in this window");
+                return (FALSE);
+        }
+        if (curwp->w_dotp == curwp->w_markp) {
+                rp->r_linep = curwp->w_dotp;
+                if (curwp->w_doto < curwp->w_marko) {
+                        rp->r_offset = curwp->w_doto;
+                        rp->r_size = (long)(curwp->w_marko-curwp->w_doto);
+                } else {
+                        rp->r_offset = curwp->w_marko;
+                        rp->r_size = (long)(curwp->w_doto-curwp->w_marko);
+                }
+                return (TRUE);
+        }
+        blp = curwp->w_dotp;
+        bsize = (long)curwp->w_doto;
+        flp = curwp->w_dotp;
+        fsize = (long)(llength(flp)-curwp->w_doto+1);
+        while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
+                if (flp != curbp->b_linep) {
+                        flp = lforw(flp);
+                        if (flp == curwp->w_markp) {
+                                rp->r_linep = curwp->w_dotp;
+                                rp->r_offset = curwp->w_doto;
+                                rp->r_size = fsize+curwp->w_marko;
+                                return (TRUE);
+                        }
+                        fsize += llength(flp)+1;
+                }
+                if (lback(blp) != curbp->b_linep) {
+                        blp = lback(blp);
+                        bsize += llength(blp)+1;
+                        if (blp == curwp->w_markp) {
+                                rp->r_linep = blp;
+                                rp->r_offset = curwp->w_marko;
+                                rp->r_size = bsize - curwp->w_marko;
+                                return (TRUE);
+                        }
+                }
+        }
+        mlwrite("Bug: lost mark");
+        return (FALSE);
+}

Added: clients/emacs/search.c
===================================================================
--- clients/emacs/search.c	                        (rev 0)
+++ clients/emacs/search.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,607 @@
+/*
+ * The functions in this file implement commands that search in the forward
+ * and backward directions. There are no special characters in the search
+ * strings. Probably should have a regular expression search, or something
+ * like that.
+ *
+ */
+
+#include	"estruct.h"
+#include        "edef.h"
+
+/*
+ * Search forward. Get a search string from the user, and search, beginning at
+ * ".", for the string. If found, reset the "." to be just after the match
+ * string, and [perhaps] repaint the display. Bound to "C-S".
+ */
+
+/*	string search input parameters	*/
+
+#define	PTBEG	1	/* leave the point at the begining on search */
+#define	PTEND	2	/* leave the point at the end on search */
+
+forwsearch(f, n)
+
+{
+	register int status;
+
+	/* resolve the repeat count */
+	if (n == 0)
+		n = 1;
+	if (n < 1)	/* search backwards */
+		return(backsearch(f, -n));
+
+	/* ask the user for the text of a pattern */
+	if ((status = readpattern("Search")) != TRUE)
+		return(status);
+
+	/* search for the pattern */
+	while (n-- > 0) {
+		if ((status = forscan(&pat[0],PTEND)) == FALSE)
+			break;
+	}
+
+	/* and complain if not there */
+	if (status == FALSE)
+		mlwrite("Not found");
+	return(status);
+}
+
+forwhunt(f, n)
+
+{
+	register int status;
+
+	/* resolve the repeat count */
+	if (n == 0)
+		n = 1;
+	if (n < 1)	/* search backwards */
+		return(backhunt(f, -n));
+
+	/* Make sure a pattern exists */
+	if (pat[0] == 0) {
+		mlwrite("No pattern set");
+		return(FALSE);
+	}
+
+	/* search for the pattern */
+	while (n-- > 0) {
+		if ((status = forscan(&pat[0],PTEND)) == FALSE)
+			break;
+	}
+
+	/* and complain if not there */
+	if (status == FALSE)
+		mlwrite("Not found");
+	return(status);
+}
+
+/*
+ * Reverse search. Get a search string from the user, and search, starting at
+ * "." and proceeding toward the front of the buffer. If found "." is left
+ * pointing at the first character of the pattern [the last character that was
+ * matched]. Bound to "C-R".
+ */
+backsearch(f, n)
+
+{
+	register int s;
+
+	/* resolve null and negative arguments */
+	if (n == 0)
+		n = 1;
+	if (n < 1)
+		return(forwsearch(f, -n));
+
+	/* get a pattern to search */
+	if ((s = readpattern("Reverse search")) != TRUE)
+		return(s);
+
+	/* and go search for it */
+	bsearchcom(f,n);
+	return(TRUE);
+}
+
+backhunt(f, n)	/* hunt backward for the last search string entered */
+
+{
+	/* resolve null and negative arguments */
+	if (n == 0)
+		n = 1;
+	if (n < 1)
+		return(forwhunt(f, -n));
+
+	/* Make sure a pattern exists */
+	if (pat[0] == 0) {
+		mlwrite("No pattern set");
+		return(FALSE);
+	}
+
+	/* and go search for it */
+	bsearchcom(f,n);
+	return(TRUE);
+}
+
+bsearchcom(f, n)
+
+int f;		/* default flag */
+int n;		/* # of repetitions wanted */
+
+{
+	register LINE *clp;
+	register int cbo;
+	register LINE *tlp;
+	register int tbo;
+	register int c;
+	register char *epp;
+	register char *pp;
+
+	/* find a pointer to the end of the pattern */
+	for (epp = &pat[0]; epp[1] != 0; ++epp)
+		;
+
+	/* make local copies of the starting location */
+	clp = curwp->w_dotp;
+	cbo = curwp->w_doto;
+
+	while (n-- > 0) {
+		for (;;) {
+			/* if we are at the begining of the line, wrap back around */
+			if (cbo == 0) {
+				clp = lback(clp);
+
+				if (clp == curbp->b_linep) {
+					mlwrite("Not found");
+					return(FALSE);
+				}
+
+				cbo = llength(clp)+1;
+			}
+
+			/* fake the <NL> at the end of a line */
+			if (--cbo == llength(clp))
+				c = '\n';
+			else
+				c = lgetc(clp, cbo);
+
+			/* check for a match against the end of the pattern */
+			if (eq(c, *epp) != FALSE) {
+				tlp = clp;
+				tbo = cbo;
+				pp  = epp;
+
+				/* scanning backwards through the rest of the
+				   pattern looking for a match			*/
+				while (pp != &pat[0]) {
+					/* wrap across a line break */
+					if (tbo == 0) {
+						tlp = lback(tlp);
+						if (tlp == curbp->b_linep)
+							goto fail;
+
+						tbo = llength(tlp)+1;
+					}
+
+					/* fake the <NL> */
+					if (--tbo == llength(tlp))
+						c = '\n';
+					else
+						c = lgetc(tlp, tbo);
+
+					if (eq(c, *--pp) == FALSE)
+						goto fail;
+				}
+
+				/* A Match!  reset the current cursor */
+				curwp->w_dotp  = tlp;
+				curwp->w_doto  = tbo;
+				curwp->w_flag |= WFMOVE;
+				goto next;
+			}
+fail:;
+		}
+next:;
+	}
+	return(TRUE);
+}
+
+/*
+ * Compare two characters. The "bc" comes from the buffer. It has it's case
+ * folded out. The "pc" is from the pattern.
+ */
+eq(bc, pc)
+	int bc;
+	int pc;
+
+{
+	if ((curwp->w_bufp->b_mode & MDEXACT) == 0) {
+		if (bc>='a' && bc<='z')
+			bc -= 0x20;
+
+		if (pc>='a' && pc<='z')
+			pc -= 0x20;
+	}
+
+	if (bc == pc)
+		return(TRUE);
+
+	return(FALSE);
+}
+
+/*
+ * Read a pattern. Stash it in the external variable "pat". The "pat" is not
+ * updated if the user types in an empty line. If the user typed an empty line,
+ * and there is no old pattern, it is an error. Display the old pattern, in the
+ * style of Jeff Lomicka. There is some do-it-yourself control expansion.
+ * change to using <ESC> to delemit the end-of-pattern to allow <NL>s in
+ * the search string.
+ */
+readpattern(prompt)
+
+char *prompt;
+
+{
+	register int s;
+	char tpat[NPAT+20];
+
+	strcpy(tpat, prompt);	/* copy prompt to output string */
+	strcat(tpat, " [");	/* build new prompt string */
+	expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2);	/* add old pattern */
+	strcat(tpat, "]<ESC>: ");
+
+	s = mlreplyt(tpat, tpat, NPAT, 27);	/* Read pattern */
+
+	if (s == TRUE)				/* Specified */
+		strcpy(pat, tpat);
+	else if (s == FALSE && pat[0] != 0)	/* CR, but old one */
+		s = TRUE;
+
+	return(s);
+}
+
+sreplace(f, n)	/*	Search and replace (ESC-R)	*/
+
+int f;		/* default flag */
+int n;		/* # of repetitions wanted */
+
+{
+	return(replaces(FALSE, f, n));
+}
+
+qreplace(f, n)	/*	search and replace with query (ESC-CTRL-R)	*/
+
+int f;		/* default flag */
+int n;		/* # of repetitions wanted */
+
+{
+	return(replaces(TRUE, f, n));
+}
+
+/*	replaces:	search for a string and replace it with another
+			string. query might be enabled (according to
+			kind).						*/
+replaces(kind, f, n)
+
+int kind;	/* Query enabled flag */
+int f;		/* default flag */
+int n;		/* # of repetitions wanted */
+
+{
+	register int i;		/* loop index */
+	register int s;		/* success flag on pattern inputs */
+	register int slength,
+		     rlength;	/* length of search and replace strings */
+	register int numsub;	/* number of substitutions */
+	register int nummatch;	/* number of found matches */
+	int nlflag;		/* last char of search string a <NL>? */
+	int nlrepl;		/* was a replace done on the last line? */
+	char tmpc;		/* temporary character */
+	char c;			/* input char for query */
+	char tpat[NPAT];	/* temporary to hold search pattern */
+	LINE *origline;		/* original "." position */
+	int origoff;		/* and offset (for . query option) */
+	LINE *lastline;		/* position of last replace and */
+	int lastoff;		/* offset (for 'u' query option) */
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+
+	/* check for negative repititions */
+	if (f && n < 0)
+		return(FALSE);
+
+	/* ask the user for the text of a pattern */
+	if ((s = readpattern(
+		(kind == FALSE ? "Replace" : "Query replace"))) != TRUE)
+		return(s);
+	strcpy(&tpat[0], &pat[0]);	/* salt it away */
+
+	/* ask for the replacement string */
+	strcpy(&pat[0], &rpat[0]);	/* set up default string */
+	if ((s = readpattern("with")) == ABORT)
+		return(s);
+
+	/* move everything to the right place and length them */
+	strcpy(&rpat[0], &pat[0]);
+	strcpy(&pat[0], &tpat[0]);
+	slength = strlen(&pat[0]);
+	rlength = strlen(&rpat[0]);
+
+	/* set up flags so we can make sure not to do a recursive
+	   replace on the last line */
+	nlflag = (pat[slength - 1] == '\n');
+	nlrepl = FALSE;
+
+	if (kind) {
+		/* build query replace question string */
+		strcpy(tpat, "Replace '");
+		expandp(&pat[0], &tpat[strlen(tpat)], NPAT/3);
+		strcat(tpat, "' with '");
+		expandp(&rpat[0], &tpat[strlen(tpat)], NPAT/3);
+		strcat(tpat, "'? ");
+
+		/* initialize last replaced pointers */
+		lastline = NULL;
+		lastoff = 0;
+	}
+
+	/* save original . position */
+	origline = curwp->w_dotp;
+	origoff = curwp->w_doto;
+
+	/* scan through the file */
+	numsub = 0;
+	nummatch = 0;
+	while ((f == FALSE || n > nummatch) &&
+		(nlflag == FALSE || nlrepl == FALSE)) {
+
+		/* search for the pattern */
+		if (forscan(&pat[0],PTBEG) != TRUE)
+			break;		/* all done */
+		++nummatch;	/* increment # of matches */
+
+		/* check if we are on the last line */
+		nlrepl = (lforw(curwp->w_dotp) == curwp->w_bufp->b_linep);
+		
+		/* check for query */
+		if (kind) {
+			/* get the query */
+pprompt:		mlwrite(&tpat[0], &pat[0], &rpat[0]);
+qprompt:
+			update(FALSE);  /* show the proposed place to change */
+			c = (*term.t_getchar)();	/* and input */
+			mlwrite("");			/* and clear it */
+
+			/* and respond appropriately */
+			switch (c) {
+				case 'y':	/* yes, substitute */
+				case ' ':
+						break;
+
+				case 'n':	/* no, onword */
+						forwchar(FALSE, 1);
+						continue;
+
+				case '!':	/* yes/stop asking */
+						kind = FALSE;
+						break;
+
+				case 'u':	/* undo last and re-prompt */
+
+			/* restore old position */
+			if (lastline == NULL) {
+				/* there is nothing to undo */
+				(*term.t_beep)();
+				goto qprompt;
+			}
+			curwp->w_dotp = lastline;
+			curwp->w_doto = lastoff;
+			lastline = NULL;
+			lastoff = 0;
+
+			/* delete the new string */
+			backchar(FALSE, rlength);
+			if (ldelete((long)rlength, FALSE) != TRUE) {
+				mlwrite("ERROR while deleting");
+				return(FALSE);
+			}
+
+			/* and put in the old one */
+			for (i=0; i<slength; i++) {
+				tmpc = pat[i];
+				s = (tmpc == '\n' ? lnewline() :
+							linsert(1, tmpc));
+				if (s != TRUE) {
+					/* error while inserting */
+					mlwrite("Out of memory while inserting");
+					return(FALSE);
+				}
+			}
+
+			--numsub;	/* one less substitutions */
+
+			/* backup, and reprompt */
+			backchar(FALSE, slength);
+			goto pprompt;
+
+				case '.':	/* abort! and return */
+						/* restore old position */
+						curwp->w_dotp = origline;
+						curwp->w_doto = origoff;
+						curwp->w_flag |= WFMOVE;
+
+				case BELL:	/* abort! and stay */
+						mlwrite("Aborted!");
+						return(FALSE);
+
+				default:	/* bitch and beep */
+						(*term.t_beep)();
+
+				case '?':	/* help me */
+						mlwrite(
+"(Y)es, (N)o, (!)Do rest, (U)ndo last, (^G)Abort, (.)Abort back, (?)Help: ");
+						goto qprompt;
+
+			}
+		}
+
+		/* delete the sucker */
+		if (ldelete((long)slength, FALSE) != TRUE) {
+			/* error while deleting */
+			mlwrite("ERROR while deleteing");
+			return(FALSE);
+		}
+
+		/* and insert its replacement */
+		for (i=0; i<rlength; i++) {
+			tmpc = rpat[i];
+			s = (tmpc == '\n' ? lnewline() : linsert(1, tmpc));
+			if (s != TRUE) {
+				/* error while inserting */
+				mlwrite("Out of memory while inserting");
+				return(FALSE);
+			}
+		}
+
+		/* save where we are if we might undo this... */
+		if (kind) {
+			lastline = curwp->w_dotp;
+			lastoff = curwp->w_doto;
+		}
+
+		numsub++;	/* increment # of substitutions */
+	}
+
+	/* and report the results */
+	mlwrite("%d substitutions",numsub);
+	return(TRUE);
+}
+
+forscan(patrn,leavep)	/*	search forward for a <patrn>	*/
+
+char *patrn;		/* string to scan for */
+int leavep;		/* place to leave point
+				PTBEG = begining of match
+				PTEND = at end of match		*/
+
+{
+	register LINE *curline;		/* current line during scan */
+	register int curoff;		/* position within current line */
+	register LINE *lastline;	/* last line position during scan */
+	register int lastoff;		/* position within last line */
+	register int c;			/* character at current position */
+	register LINE *matchline;	/* current line during matching */
+	register int matchoff;		/* position in matching line */
+	register char *patptr;		/* pointer into pattern */
+
+	/* setup local scan pointers to global "." */
+
+	curline = curwp->w_dotp;
+	curoff = curwp->w_doto;
+
+	/* scan each character until we hit the head link record */
+
+	while (curline != curbp->b_linep) {
+
+		/* save the current position in case we need to
+		   restore it on a match			*/
+
+		lastline = curline;
+		lastoff = curoff;
+
+		/* get the current character resolving EOLs */
+
+		if (curoff == llength(curline)) {	/* if at EOL */
+			curline = lforw(curline);	/* skip to next line */
+			curoff = 0;
+			c = '\n';			/* and return a <NL> */
+		} else
+			c = lgetc(curline, curoff++);	/* get the char */
+
+		/* test it against first char in pattern */
+		if (eq(c, patrn[0]) != FALSE) {	/* if we find it..*/
+			/* setup match pointers */
+			matchline = curline;
+			matchoff = curoff;
+			patptr = &patrn[0];
+
+			/* scan through patrn for a match */
+			while (*++patptr != 0) {
+				/* advance all the pointers */
+				if (matchoff == llength(matchline)) {
+					/* advance past EOL */
+					matchline = lforw(matchline);
+					matchoff = 0;
+					c = '\n';
+				} else
+					c = lgetc(matchline, matchoff++);
+
+				/* and test it against the pattern */
+				if (eq(*patptr, c) == FALSE)
+					goto fail;
+			}
+
+			/* A SUCCESSFULL MATCH!!! */
+			/* reset the global "." pointers */
+			if (leavep == PTEND) {	/* at end of string */
+				curwp->w_dotp = matchline;
+				curwp->w_doto = matchoff;
+			} else {		/* at begining of string */
+				curwp->w_dotp = lastline;
+				curwp->w_doto = lastoff;
+			}
+			curwp->w_flag |= WFMOVE; /* flag that we have moved */
+			return(TRUE);
+
+		}
+fail:;			/* continue to search */
+	}
+
+	/* we could not find a match */
+
+	return(FALSE);
+}
+
+/* 	expandp:	expand control key sequences for output		*/
+
+expandp(srcstr, deststr, maxlength)
+
+char *srcstr;	/* string to expand */
+char *deststr;	/* destination of expanded string */
+int maxlength;	/* maximum chars in destination */
+
+{
+	char c;		/* current char to translate */
+
+	/* scan through the string */
+	while ((c = *srcstr++) != 0) {
+		if (c == '\n') {		/* its an EOL */
+			*deststr++ = '<';
+			*deststr++ = 'N';
+			*deststr++ = 'L';
+			*deststr++ = '>';
+			maxlength -= 4;
+		} else if (c < 0x20 || c == 0x7f) {	/* control character */
+			*deststr++ = '^';
+			*deststr++ = c ^ 0x40;
+			maxlength -= 2;
+		} else if (c == '%') {
+			*deststr++ = '%';
+			*deststr++ = '%';
+			maxlength -= 2;
+
+		} else {			/* any other character */
+			*deststr++ = c;
+			maxlength--;
+		}
+
+		/* check for maxlength */
+		if (maxlength < 4) {
+			*deststr++ = '$';
+			*deststr = '\0';
+			return(FALSE);
+		}
+	}
+	*deststr = '\0';
+	return(TRUE);
+}

Added: clients/emacs/spawn.c
===================================================================
--- clients/emacs/spawn.c	                        (rev 0)
+++ clients/emacs/spawn.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,533 @@
+/*	Spawn:	various DOS access commands
+		for MicroEMACS
+*/
+
+#include	"estruct.h"
+#include        "edef.h"
+
+#if     AMIGA
+#define  NEW   1006
+#endif
+
+#if     VMS
+#define EFN     0                               /* Event flag.          */
+
+#include        <ssdef.h>                       /* Random headers.      */
+#include        <stsdef.h>
+#include        <descrip.h>
+#include        <iodef.h>
+
+extern  int     oldmode[3];                     /* In "termio.c"        */
+extern  int     newmode[3];                     /* In "termio.c"        */
+extern  short   iochan;                         /* In "termio.c"        */
+#endif
+
+#if     V7 | USG | BSD
+#include        <signal.h>
+extern int vttidy();
+#endif
+
+#if	MSDOS & MSC
+#include	<process.h>
+#define	system(a)	spawnlp(P_WAIT, a, NULL)
+#endif
+
+/*
+ * Create a subjob with a copy of the command intrepreter in it. When the
+ * command interpreter exits, mark the screen as garbage so that you do a full
+ * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
+ * Under some (unknown) condition, you don't get one free when DCL starts up.
+ */
+spawncli(f, n)
+{
+#if     AMIGA
+        long newcli;
+
+        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
+        mlwrite("[Starting new CLI]");
+        sgarbf = TRUE;
+        Execute("", newcli, 0);
+        Close(newcli);
+        return(TRUE);
+#endif
+
+#if     V7 | USG | BSD
+        register char *cp;
+        char    *getenv();
+#endif
+#if     VMS
+        movecursor(term.t_nrow, 0);             /* In last line.        */
+        mlputs("[Starting DCL]\r\n");
+        (*term.t_flush)();                      /* Ignore "ttcol".      */
+        sgarbf = TRUE;
+        return (sys(NULL));                     /* NULL => DCL.         */
+#endif
+#if     CPM
+        mlwrite("Not in CP/M-86");
+#endif
+#if     MSDOS & AZTEC
+        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
+        (*term.t_flush)();
+	(*term.t_close)();
+	system("command.com");
+	(*term.t_open)();
+        sgarbf = TRUE;
+        return(TRUE);
+#endif
+#if     MSDOS & LATTICE
+        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
+        (*term.t_flush)();
+	(*term.t_close)();
+        sys("\\command.com", "");               /* Run CLI.             */
+	(*term.t_open)();
+        sgarbf = TRUE;
+        return(TRUE);
+#endif
+#if     OFW
+        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
+        (*term.t_flush)();
+	(*term.t_close)();
+        OFEnter();                              /* Run CLI.             */
+	(*term.t_open)();
+        sgarbf = TRUE;
+        return(TRUE);
+#endif
+#if     V7 | USG | BSD
+        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
+        (*term.t_flush)();
+        ttclose();                              /* stty to old settings */
+        if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
+                system(cp);
+        else
+#if	BSD
+                system("exec /bin/csh");
+#else
+                system("exec /bin/sh");
+#endif
+        sgarbf = TRUE;
+        sleep(2);
+        ttopen();
+        return(TRUE);
+#endif
+}
+
+#if	BSD
+
+bktoshell()		/* suspend MicroEMACS and wait to wake up */
+{
+	int pid;
+
+	vttidy();
+	pid = getpid();
+	kill(pid,SIGTSTP);
+}
+
+rtfrmshell()
+{
+	ttopen();
+	curwp->w_flag = WFHARD;
+	sgarbf = TRUE;
+}
+#endif
+
+/*
+ * Run a one-liner in a subjob. When the command returns, wait for a single
+ * character to be typed, then mark the screen as garbage so a full repaint is
+ * done. Bound to "C-X !".
+ */
+spawn(f, n)
+{
+        register int    s;
+        char            line[NLINE];
+#if     AMIGA
+        long newcli;
+
+        if ((s=mlreply("!", line, NLINE)) != TRUE)
+                return (s);
+        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
+        Execute(line,0,newcli);
+        Close(newcli);
+        (*term.t_getchar)();     /* Pause.               */
+        sgarbf = TRUE;
+        return(TRUE);
+#endif
+#if     VMS
+        if ((s=mlreply("!", line, NLINE)) != TRUE)
+                return (s);
+        (*term.t_putchar)('\n');                /* Already have '\r'    */
+        (*term.t_flush)();
+        s = sys(line);                          /* Run the command.     */
+        mlputs("\r\n\n[End]");                  /* Pause.               */
+        (*term.t_flush)();
+        (*term.t_getchar)();
+        sgarbf = TRUE;
+        return (s);
+#endif
+#if     CPM
+        mlwrite("Not in CP/M-86");
+        return (FALSE);
+#endif
+#if     MSDOS | OFW
+        if ((s=mlreply("!", line, NLINE)) != TRUE)
+                return(s);
+	movecursor(term.t_nrow - 1, 0);
+	(*term.t_close)();
+        system(line);
+	(*term.t_open)();
+        mlputs("\r\n\n[End]");                  /* Pause.               */
+        (*term.t_getchar)();     /* Pause.               */
+        sgarbf = TRUE;
+        return (TRUE);
+#endif
+#if     V7 | USG | BSD
+        if ((s=mlreply("!", line, NLINE)) != TRUE)
+                return (s);
+        (*term.t_putchar)('\n');                /* Already have '\r'    */
+        (*term.t_flush)();
+        ttclose();                              /* stty to old modes    */
+        system(line);
+        ttopen();
+        mlputs("[End]");                        /* Pause.               */
+        (*term.t_flush)();
+        while ((s = (*term.t_getchar)()) != '\r' && s != ' ')
+                ;
+        sgarbf = TRUE;
+        return (TRUE);
+#endif
+}
+
+/*
+ * Pipe a one line command into a window
+ * Bound to ^X @
+ */
+pipe(f, n)
+{
+        register int    s;	/* return status from CLI */
+	register WINDOW *wp;	/* pointer to new window */
+	register BUFFER *bp;	/* pointer to buffer to zot */
+        char	line[NLINE];	/* command line send to shell */
+	static char bname[] = "command";
+
+#if	AMIGA
+	static char filnam[] = "ram:command";
+        long newcli;
+#else
+	static char filnam[] = "command";
+#endif
+
+#if     VMS
+	mlwrite("Not availible under VMS");
+	return(FALSE);
+#endif
+#if     CPM
+        mlwrite("Not availible under CP/M-86");
+        return(FALSE);
+#endif
+#if     OFW
+	/* XXX we could do this by creating a special redirect I/O package */
+        mlwrite("Not availible under Open Firmware");
+        return(FALSE);
+#endif
+
+	/* get the command to pipe in */
+        if ((s=mlreply("@", line, NLINE)) != TRUE)
+                return(s);
+
+	/* get rid of the command output buffer if it exists */
+        if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
+		/* try to make sure we are off screen */
+		wp = wheadp;
+		while (wp != NULL) {
+			if (wp->w_bufp == bp) {
+				onlywind(FALSE, 1);
+				break;
+			}
+			wp = wp->w_wndp;
+		}
+		if (zotbuf(bp) != TRUE)
+			return(FALSE);
+	}
+
+#if     AMIGA
+        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
+	strcat(line, " >");
+	strcat(line, filnam);
+        Execute(line,0,newcli);
+	s = TRUE;
+        Close(newcli);
+        sgarbf = TRUE;
+#endif
+#if     MSDOS
+	strcat(line," >");
+	strcat(line,filnam);
+	movecursor(term.t_nrow - 1, 0);
+	(*term.t_close)();
+        system(line);
+	(*term.t_open)();
+        sgarbf = TRUE;
+	s = TRUE;
+#endif
+#if     V7 | USG | BSD
+        (*term.t_putchar)('\n');                /* Already have '\r'    */
+        (*term.t_flush)();
+        ttclose();                              /* stty to old modes    */
+	strcat(line,">");
+	strcat(line,filnam);
+        system(line);
+        ttopen();
+        (*term.t_flush)();
+        sgarbf = TRUE;
+        s = TRUE;
+#endif
+
+	if (s != TRUE)
+		return(s);
+
+	/* split the current window to make room for the command output */
+	if (splitwind(FALSE, 1) == FALSE)
+			return(FALSE);
+
+	/* and read the stuff in */
+	if (getfile(filnam, FALSE) == FALSE)
+		return(FALSE);
+
+	/* make this window in VIEW mode, update all mode lines */
+	curwp->w_bufp->b_mode |= MDVIEW;
+	wp = wheadp;
+	while (wp != NULL) {
+		wp->w_flag |= WFMODE;
+		wp = wp->w_wndp;
+	}
+#ifndef OBP
+	/* and get rid of the temporary file */
+	unlink(filnam);
+#endif
+	return(TRUE);
+}
+
+/*
+ * filter a buffer through an external DOS program
+ * Bound to ^X #
+ */
+filter(f, n)
+
+{
+        register int    s;	/* return status from CLI */
+	register BUFFER *bp;	/* pointer to buffer to zot */
+        char line[NLINE];	/* command line send to shell */
+	char tmpnam[NFILEN];	/* place to store real file name */
+	static char bname1[] = "fltinp";
+
+#if	AMIGA
+	static char filnam1[] = "ram:fltinp";
+	static char filnam2[] = "ram:fltout";
+        long newcli;
+#else
+	static char filnam1[] = "fltinp";
+	static char filnam2[] = "fltout";
+#endif
+
+#if     VMS
+	mlwrite("Not availible under VMS");
+	return(FALSE);
+#endif
+#if     CPM
+        mlwrite("Not availible under CP/M-86");
+        return(FALSE);
+#endif
+#if     OFW
+	/* XXX we could do this by creating a special redirect I/O package */
+        mlwrite("Not availible under Open Firmware");
+        return(FALSE);
+#endif
+
+	/* get the filter name and its args */
+        if ((s=mlreply("#", line, NLINE)) != TRUE)
+                return(s);
+
+	/* setup the proper file names */
+	bp = curbp;
+	strcpy(tmpnam, bp->b_fname);	/* save the original name */
+	strcpy(bp->b_fname, bname1);	/* set it to our new one */
+
+	/* write it out, checking for errors */
+	if (writeout(filnam1) != TRUE) {
+		mlwrite("[Cannot write filter file]");
+		strcpy(bp->b_fname, tmpnam);
+		return(FALSE);
+	}
+
+#if     AMIGA
+        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
+	strcat(line, " <ram:fltinp >ram:fltout");
+        Execute(line,0,newcli);
+	s = TRUE;
+        Close(newcli);
+        sgarbf = TRUE;
+#endif
+#if     MSDOS
+	strcat(line," <fltinp >fltout");
+	movecursor(term.t_nrow - 1, 0);
+	(*term.t_close)();
+        system(line);
+	(*term.t_open)();
+        sgarbf = TRUE;
+	s = TRUE;
+#endif
+#if     V7 | USG | BSD
+        (*term.t_putchar)('\n');                /* Already have '\r'    */
+        (*term.t_flush)();
+        ttclose();                              /* stty to old modes    */
+	strcat(line," <fltinp >fltout");
+        system(line);
+        ttopen();
+        (*term.t_flush)();
+        sgarbf = TRUE;
+        s = TRUE;
+#endif
+
+	/* on failure, escape gracefully */
+	if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
+		mlwrite("[Execution failed]");
+		strcpy(bp->b_fname, tmpnam);
+#ifndef OBP
+		unlink(filnam1);
+		unlink(filnam2);
+#endif
+		return(s);
+	}
+
+	/* reset file name */
+	strcpy(bp->b_fname, tmpnam);	/* restore name */
+	bp->b_flag |= BFCHG;		/* flag it as changed */
+
+	/* and get rid of the temporary file */
+#ifndef OBP
+	unlink(filnam1);
+	unlink(filnam2);
+#endif
+	return(TRUE);
+}
+
+#if     VMS
+/*
+ * Run a command. The "cmd" is a pointer to a command string, or NULL if you
+ * want to run a copy of DCL in the subjob (this is how the standard routine
+ * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
+ * and the way out, because DCL does not want the channel to be in raw mode.
+ */
+sys(cmd)
+register char   *cmd;
+{
+        struct  dsc$descriptor  cdsc;
+        struct  dsc$descriptor  *cdscp;
+        long    status;
+        long    substatus;
+        long    iosb[2];
+
+        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
+                          oldmode, sizeof(oldmode), 0, 0, 0, 0);
+        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+                return (FALSE);
+        cdscp = NULL;                           /* Assume DCL.          */
+        if (cmd != NULL) {                      /* Build descriptor.    */
+                cdsc.dsc$a_pointer = cmd;
+                cdsc.dsc$w_length  = strlen(cmd);
+                cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
+                cdsc.dsc$b_class   = DSC$K_CLASS_S;
+                cdscp = &cdsc;
+        }
+        status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
+        if (status != SS$_NORMAL)
+                substatus = status;
+        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
+                          newmode, sizeof(newmode), 0, 0, 0, 0);
+        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+                return (FALSE);
+        if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
+                return (FALSE);
+        return (TRUE);
+}
+#endif
+
+#if	~AZTEC & MSDOS
+
+/*
+ * This routine, once again by Bob McNamara, is a C translation of the "system"
+ * routine in the MWC-86 run time library. It differs from the "system" routine
+ * in that it does not unconditionally append the string ".exe" to the end of
+ * the command name. We needed to do this because we want to be able to spawn
+ * off "command.com". We really do not understand what it does, but if you don't
+ * do it exactly "malloc" starts doing very very strange things.
+ */
+sys(cmd, tail)
+char    *cmd;
+char    *tail;
+{
+#if MWC_86
+        register unsigned n;
+        extern   char     *__end;
+
+        n = __end + 15;
+        n >>= 4;
+        n = ((n + dsreg() + 16) & 0xFFF0) + 16;
+        return(execall(cmd, tail, n));
+#endif
+
+#if LATTICE
+        return(forklp(cmd, tail, (char *)NULL));
+#endif
+
+#if	MSC
+	return(spawnlp(P_WAIT, cmd, tail, NULL));
+#endif
+}
+#endif
+
+#if	MSDOS & LATTICE
+/*	System: a modified version of lattice's system() function
+		that detects the proper switchar and uses it
+		written by Dana Hogget				*/
+
+system(cmd)
+
+char *cmd;	/*  Incoming command line to execute  */
+
+{
+	char *getenv();
+	static char *swchar = "/C";	/*  Execution switch  */
+	union REGS inregs;	/*  parameters for dos call  */
+	union REGS outregs;	/*  Return results from dos call  */
+	char *shell;		/*  Name of system command processor  */
+	char *p;		/*  Temporary pointer  */
+	int ferr;		/*  Error condition if any  */
+
+	/*  get name of system shell  */
+	if ((shell = getenv("COMSPEC")) == NULL) {
+		return (-1);		/*  No shell located  */
+	}
+
+	p = cmd;
+	while (isspace(*p)) {		/*  find out if null command */
+		p++;
+	}
+
+	/**  If the command line is not empty, bring up the shell  **/
+	/**  and execute the command.  Otherwise, bring up the     **/
+	/**  shell in interactive mode.   **/
+
+	if (p && *p) {
+		/**  detect current switch character and us it  **/
+		inregs.h.ah = 0x37;	/*  get setting data  */
+		inregs.h.al = 0x00;	/*  get switch character  */
+		intdos(&inregs, &outregs);
+		*swchar = outregs.h.dl;
+		ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
+	} else {
+		ferr = forkl(shell, "command", (char *)NULL);
+	}
+
+	return (ferr ? ferr : wait());
+}
+#endif
+

Added: clients/emacs/tags
===================================================================
--- clients/emacs/tags	                        (rev 0)
+++ clients/emacs/tags	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,371 @@
+Mmain	main.c	/^main(argc, argv)$/
+addline	buffer.c	/^addline(text)$/
+adjustmode	random.c	/^adjustmode(kind, global)	\/* change the editor mode/
+agios	hp150.c	/^agios(buf, len)	\/* perform an AGIOS call *\/$/
+amg_flush	termio.c	/^amg_flush()$/
+ansibcol	ansi.c	/^ansibcol(color)		\/* set the current background col/
+ansibeep	ansi.c	/^ansibeep()$/
+ansiclose	ansi.c	/^ansiclose()$/
+ansieeol	ansi.c	/^ansieeol()$/
+ansieeop	ansi.c	/^ansieeop()$/
+ansifcol	ansi.c	/^ansifcol(color)		\/* set the current output color */
+ansihello	ansi.c	/^ansihello()$/
+ansimove	ansi.c	/^ansimove(row, col)$/
+ansiopen	ansi.c	/^ansiopen()$/
+ansiparm	ansi.c	/^ansiparm(n)$/
+ansirev	ansi.c	/^ansirev(state)		\/* change reverse video state *\/$/
+anycb	buffer.c	/^anycb()$/
+backchar	basic.c	/^backchar(f, n)$/
+backdel	random.c	/^backdel(f, n)$/
+backhunt	search.c	/^backhunt(f, n)	\/* hunt backward for the last searc/
+backline	basic.c	/^backline(f, n)$/
+backpage	basic.c	/^backpage(f, n)$/
+backsearch	search.c	/^backsearch(f, n)$/
+backword	word.c	/^backword(f, n)$/
+bakscan	isearch.c	/^int bakscan (patrn)		\/* Scan backwards for a match/
+bclear	buffer.c	/^bclear(bp)$/
+bfind	buffer.c	/^bfind(bname, cflag, bflag)$/
+bindtokey	bind.c	/^bindtokey(f, n)$/
+bktoshell	spawn.c	/^bktoshell()		\/* suspend MicroEMACS and wait to wak/
+bsearchcom	search.c	/^bsearchcom(f, n)$/
+capword	word.c	/^capword(f, n)$/
+cbuf	exec.c	/^cbuf(f, n, bufnum)$/
+cbuf1	exec.c	/^cbuf1(f, n)$/
+cbuf10	exec.c	/^cbuf10(f, n)$/
+cbuf11	exec.c	/^cbuf11(f, n)$/
+cbuf12	exec.c	/^cbuf12(f, n)$/
+cbuf13	exec.c	/^cbuf13(f, n)$/
+cbuf14	exec.c	/^cbuf14(f, n)$/
+cbuf15	exec.c	/^cbuf15(f, n)$/
+cbuf16	exec.c	/^cbuf16(f, n)$/
+cbuf17	exec.c	/^cbuf17(f, n)$/
+cbuf18	exec.c	/^cbuf18(f, n)$/
+cbuf19	exec.c	/^cbuf19(f, n)$/
+cbuf2	exec.c	/^cbuf2(f, n)$/
+cbuf20	exec.c	/^cbuf20(f, n)$/
+cbuf21	exec.c	/^cbuf21(f, n)$/
+cbuf22	exec.c	/^cbuf22(f, n)$/
+cbuf23	exec.c	/^cbuf23(f, n)$/
+cbuf24	exec.c	/^cbuf24(f, n)$/
+cbuf25	exec.c	/^cbuf25(f, n)$/
+cbuf26	exec.c	/^cbuf26(f, n)$/
+cbuf27	exec.c	/^cbuf27(f, n)$/
+cbuf28	exec.c	/^cbuf28(f, n)$/
+cbuf29	exec.c	/^cbuf29(f, n)$/
+cbuf3	exec.c	/^cbuf3(f, n)$/
+cbuf30	exec.c	/^cbuf30(f, n)$/
+cbuf31	exec.c	/^cbuf31(f, n)$/
+cbuf32	exec.c	/^cbuf32(f, n)$/
+cbuf33	exec.c	/^cbuf33(f, n)$/
+cbuf34	exec.c	/^cbuf34(f, n)$/
+cbuf35	exec.c	/^cbuf35(f, n)$/
+cbuf36	exec.c	/^cbuf36(f, n)$/
+cbuf37	exec.c	/^cbuf37(f, n)$/
+cbuf38	exec.c	/^cbuf38(f, n)$/
+cbuf39	exec.c	/^cbuf39(f, n)$/
+cbuf4	exec.c	/^cbuf4(f, n)$/
+cbuf40	exec.c	/^cbuf40(f, n)$/
+cbuf5	exec.c	/^cbuf5(f, n)$/
+cbuf6	exec.c	/^cbuf6(f, n)$/
+cbuf7	exec.c	/^cbuf7(f, n)$/
+cbuf8	exec.c	/^cbuf8(f, n)$/
+cbuf9	exec.c	/^cbuf9(f, n)$/
+cex	main.c	/^cex()	\/* dummy function for binding to control-x p/
+checknext	isearch.c	/^int checknext (chr, patrn, dir, sts)\/* Check next /
+cinsert	random.c	/^cinsert()	\/* insert a newline and indentation for /
+ckeyoff	hp150.c	/^ckeyoff()	\/* turn control-C trapping off *\/$/
+ckeyon	hp150.c	/^ckeyon()	\/* turn control-C trapping on *\/$/
+closehp	hp150.c	/^closehp()		\/* close the HP150 keyboard for input */
+clrmes	random.c	/^clrmes(f, n)$/
+cmdstr	bind.c	/^cmdstr(c, seq)	\/* change a key command to a string/
+copyregion	region.c	/^copyregion(f, n)$/
+ctlxe	main.c	/^ctlxe(f, n)$/
+ctlxlp	main.c	/^ctlxlp(f, n)$/
+ctlxrp	main.c	/^ctlxrp(f, n)$/
+ctrlg	main.c	/^ctrlg(f, n)$/
+deblank	random.c	/^deblank(f, n)$/
+defkey	hp150.c	/^defkey()	\/* change all special keys to intercept m/
+delbword	word.c	/^delbword(f, n)$/
+delfword	word.c	/^delfword(f, n)$/
+delgmode	random.c	/^delgmode(f, n)	\/* prompt and delete a global edito/
+delmode	random.c	/^delmode(f, n)	\/* prompt and delete an editor mode /
+delwind	window.c	/^delwind(f,n)$/
+desbind	bind.c	/^desbind(f, n)	\/* describe bindings$/
+deskey	bind.c	/^deskey(f, n)	\/* describe the command for a certain/
+dg10bcol	dg10.c	/^dg10bcol(color)		\/* set the current background col/
+dg10beep	dg10.c	/^dg10beep()$/
+dg10close	dg10.c	/^dg10close()$/
+dg10eeol	dg10.c	/^dg10eeol()$/
+dg10eeop	dg10.c	/^dg10eeop()$/
+dg10fcol	dg10.c	/^dg10fcol(color)		\/* set the current output color */
+dg10hello	dg10.c	/^dg10hello()$/
+dg10move	dg10.c	/^dg10move(row, col)$/
+dg10open	dg10.c	/^dg10open()$/
+dg10rev	dg10.c	/^dg10rev(state)		\/* change reverse video state *\/$/
+dobuf	exec.c	/^dobuf(bp)$/
+docmd	exec.c	/^docmd(cline)$/
+dofile	exec.c	/^dofile(fname)$/
+echochar	isearch.c	/^int echochar(c,col)$/
+edinit	main.c	/^edinit(bname)$/
+eltoa	buffer.c	/^eltoa(buf, width, num)$/
+emacs_main	main.c	/^emacs_main(argc, argv)$/
+enlargewind	window.c	/^enlargewind(f, n)$/
+eq	search.c	/^eq(bc, pc)$/
+errexit	main.c	/^errexit()$/
+execbuf	exec.c	/^execbuf(f, n)$/
+execcmd	exec.c	/^execcmd(f, n)$/
+execfile	exec.c	/^execfile(f, n)	\/* execute a series of commands in /
+execute	main.c	/^execute(c, f, n)$/
+expandp	search.c	/^expandp(srcstr, deststr, maxlength)$/
+far_out	ibmpc.c	/^far_out(source, dest, size)$/
+ffclose	fileio.c	/^ffclose()$/
+ffgetline	fileio.c	/^ffgetline(buf, nbuf)$/
+ffputline	fileio.c	/^ffputline(buf, nbuf)$/
+ffropen	fileio.c	/^ffropen(fn)$/
+ffwopen	fileio.c	/^ffwopen(fn)$/
+filefind	file.c	/^filefind(f, n)$/
+filename	file.c	/^filename(f, n)$/
+fileread	file.c	/^fileread(f, n)$/
+filesave	file.c	/^filesave(f, n)$/
+filewrite	file.c	/^filewrite(f, n)$/
+fillpara	word.c	/^fillpara(f, n)	\/* Fill the current paragraph accor/
+filter	spawn.c	/^filter(f, n)$/
+fisearch	isearch.c	/^int fisearch(f, n)$/
+fmatch	random.c	/^fmatch(ch)$/
+fncmatch	bind.c	/^int (*fncmatch(fname))() \/* match fname to a funct/
+forscan	search.c	/^forscan(patrn,leavep)	\/*	search forward for a <pat/
+forwchar	basic.c	/^forwchar(f, n)$/
+forwdel	random.c	/^forwdel(f, n)$/
+forwhunt	search.c	/^forwhunt(f, n)$/
+forwline	basic.c	/^forwline(f, n)$/
+forwpage	basic.c	/^forwpage(f, n)$/
+forwsearch	search.c	/^forwsearch(f, n)$/
+forwword	word.c	/^forwword(f, n)$/
+get1key	input.c	/^get1key()$/
+get_char	isearch.c	/^int get_char ()$/
+getccol	random.c	/^getccol(bflg)$/
+getckey	bind.c	/^getckey(mflag)	\/* get a command key sequence from /
+getcmd	input.c	/^getcmd()$/
+getfile	file.c	/^getfile(fname, lockfl)$/
+getgoal	basic.c	/^getgoal(dlp)$/
+gethpkey	hp150.c	/^gethpkey()	\/* get a key from the HP keyboard while/
+getname	input.c	/^int (*getname())()$/
+getregion	region.c	/^getregion(rp)$/
+gettok	exec.c	/^char *gettok(src, tok)$/
+gotobob	basic.c	/^gotobob(f, n)$/
+gotobol	basic.c	/^gotobol(f, n)$/
+gotobop	basic.c	/^gotobop(f, n)	\/* go back to the begining of the cu/
+gotoeob	basic.c	/^gotoeob(f, n)$/
+gotoeol	basic.c	/^gotoeol(f, n)$/
+gotoeop	basic.c	/^gotoeop(f, n)	\/* go forword to the end of the curr/
+gotoline	basic.c	/^gotoline(f, n)		\/* move to a particular line.$/
+h15hello	hp150.c	/^h15hello()$/
+hello	tcap.c	/^hello()$/
+hellovms	vmsvt.c	/^hellovms()$/
+help	bind.c	/^help(f, n)	\/* give me some help!!!!$/
+hp15bcol	hp150.c	/^hp15bcol()	\/* we really can't do colors here, so j/
+hp15beep	hp150.c	/^hp15beep()$/
+hp15eeol	hp150.c	/^hp15eeol()$/
+hp15eeop	hp150.c	/^hp15eeop()$/
+hp15fcol	hp150.c	/^hp15fcol()	\/* we really can't do colors here, so j/
+hp15move	hp150.c	/^hp15move(row, col)$/
+hp15parm	hp150.c	/^hp15parm(n)$/
+hp15rev	hp150.c	/^hp15rev(status)		\/* change the reverse video statu/
+hpflush	hp150.c	/^hpflush()$/
+ibmbcol	ibmpc.c	/^ibmbcol(color)		\/* set the current background colo/
+ibmbeep	ibmpc.c	/^ibmbeep()$/
+ibmclose	ibmpc.c	/^ibmclose()$/
+ibmeeol	ibmpc.c	/^ibmeeol()	\/* erase to the end of the line *\/$/
+ibmeeop	ibmpc.c	/^ibmeeop()$/
+ibmfcol	ibmpc.c	/^ibmfcol(color)		\/* set the current output color *\//
+ibmhello	ibmpc.c	/^ibmhello()$/
+ibmmove	ibmpc.c	/^ibmmove(row, col)$/
+ibmopen	ibmpc.c	/^ibmopen()$/
+ibmputc	ibmpc.c	/^ibmputc(ch)	\/* put a character at the current posi/
+ibmrev	ibmpc.c	/^ibmrev(state)		\/* change reverse video state *\/$/
+ifile	file.c	/^ifile(fname)$/
+indent	random.c	/^indent(f, n)$/
+insbrace	random.c	/^insbrace(n, c)	\/* insert a brace into the text her/
+insfile	file.c	/^insfile(f, n)$/
+inspound	random.c	/^inspound()	\/* insert a # into the text here...we a/
+insspace	line.c	/^insspace(f, n)	\/* insert spaces forward into text /
+inword	word.c	/^inword()$/
+isearch	isearch.c	/^isearch(f, n)$/
+istring	random.c	/^istring(f, n)	\/* ask for and insert a string into /
+kbdtext	input.c	/^kbdtext(buf)	\/* add this text string to the curren/
+kdelete	line.c	/^kdelete()$/
+keycoff	hp150.c	/^keycoff()	\/* turn keycode mode off *\/$/
+keycon	hp150.c	/^keycon()	\/* turn keycode mode on *\/$/
+killbuffer	buffer.c	/^killbuffer(f, n)$/
+killpara	word.c	/^killpara(f, n)	\/* delete n paragraphs starting wit/
+killregion	region.c	/^killregion(f, n)$/
+killtext	random.c	/^killtext(f, n)$/
+kinsert	line.c	/^kinsert(c)$/
+lalloc	line.c	/^lalloc(used)$/
+lback	estruct.h	/^#define lback(lp)       ((lp)->l_bp)$/
+lback	estructp.h	/^#define lback(lp)       ((lp)->l_bp)$/
+lchange	line.c	/^lchange(flag)$/
+lckerror	lock.c	/^lckerror(errstr)	\/* report a lock error *\/$/
+lckhello	lock.c	/^lckhello()	\/* dummy function *\/$/
+ldelete	line.c	/^ldelete(n, kflag)$/
+ldelnewline	line.c	/^ldelnewline()$/
+lforw	estruct.h	/^#define lforw(lp)       ((lp)->l_fp)$/
+lforw	estructp.h	/^#define lforw(lp)       ((lp)->l_fp)$/
+lfree	line.c	/^lfree(lp)$/
+lgetc	estruct.h	/^#define lgetc(lp, n)    ((lp)->l_text[(n)]&0xFF)$/
+lgetc	estructp.h	/^#define lgetc(lp, n)    ((lp)->l_text[(n)]&0xFF)$/
+linsert	line.c	/^linsert(n, c)$/
+listbuffers	buffer.c	/^listbuffers(f, n)$/
+llength	estruct.h	/^#define llength(lp)     ((lp)->l_used)$/
+llength	estructp.h	/^#define llength(lp)     ((lp)->l_used)$/
+lnewline	line.c	/^lnewline()$/
+lock	lock.c	/^lock(fname)$/
+lockchk	lock.c	/^lockchk(fname)$/
+lockrel	lock.c	/^lockrel()$/
+lowerregion	region.c	/^lowerregion(f, n)$/
+lowerword	word.c	/^lowerword(f, n)$/
+lputc	estruct.h	/^#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))$/
+lputc	estructp.h	/^#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))$/
+makelist	buffer.c	/^makelist()$/
+makename	file.c	/^makename(bname, fname)$/
+match_pat	isearch.c	/^int match_pat (patrn)	\/* See if the pattern string/
+meta	main.c	/^meta()	\/* dummy function for binding to meta prefi/
+mlerase	display.c	/^mlerase()$/
+mlputf	display.c	/^mlputf(s)$/
+mlputi	display.c	/^mlputi(i, r)$/
+mlputli	display.c	/^mlputli(l, r)$/
+mlputs	display.c	/^mlputs(s)$/
+mlreply	input.c	/^mlreply(prompt, buf, nbuf)$/
+mlreplyt	input.c	/^mlreplyt(prompt, buf, nbuf, eolchar)$/
+mlwrite	display.c	/^mlwrite(fmt, arg)$/
+mlyesno	input.c	/^mlyesno(prompt)$/
+modeline	display.c	/^modeline(wp)$/
+movecursor	display.c	/^movecursor(row, col)$/
+mvdnwind	window.c	/^mvdnwind(f, n)$/
+mvupwind	window.c	/^mvupwind(f, n)$/
+namebuffer	buffer.c	/^namebuffer(f,n)		\/*	Rename the current buffer	*\/$/
+namedcmd	exec.c	/^namedcmd(f, n)$/
+newline	random.c	/^newline(f, n)$/
+nextbuffer	buffer.c	/^nextbuffer(f, n)	\/* switch to the next buffer in t/
+nextwind	window.c	/^nextwind(f, n)$/
+nxtarg	exec.c	/^nxtarg(tok)$/
+onlywind	window.c	/^onlywind(f, n)$/
+openhp	hp150.c	/^openhp()		\/* open the HP150 keyboard for input *\/$/
+openline	random.c	/^openline(f, n)$/
+pipe	spawn.c	/^pipe(f, n)$/
+prevwind	window.c	/^prevwind(f, n)$/
+promptpattern	isearch.c	/^int promptpattern(prompt)$/
+putline	display.c	/^putline(row, col, buf)$/
+putnpad	tcap.c	/^putnpad(str, n)$/
+putpad	tcap.c	/^putpad(str)$/
+qreplace	search.c	/^qreplace(f, n)	\/*	search and replace with query (E/
+quickexit	main.c	/^quickexit(f, n)$/
+quit	main.c	/^quit(f, n)$/
+quote	random.c	/^quote(f, n)$/
+rawoff	hp150.c	/^rawoff()	\/* put the HP150 keyboard into COOKED mod/
+rawon	hp150.c	/^rawon()		\/* put the HP150 keyboard into RAW mode */
+rdonly	main.c	/^rdonly()$/
+readin	file.c	/^readin(fname, lockfl)$/
+readpattern	search.c	/^readpattern(prompt)$/
+reeat	isearch.c	/^int reeat(c)$/
+reframe	display.c	/^reframe(wp)$/
+refresh	window.c	/^refresh(f, n)$/
+replaces	search.c	/^replaces(kind, f, n)$/
+reposition	window.c	/^reposition(f, n)$/
+resize	window.c	/^resize(f, n)$/
+restwnd	window.c	/^restwnd(f, n)		\/* restore the saved screen *\/$/
+risearch	isearch.c	/^int risearch(f, n)$/
+rtfrmshell	spawn.c	/^rtfrmshell()$/
+savewnd	window.c	/^savewnd(f, n)		\/* save ptr to current window *\/$/
+scanmore	isearch.c	/^int scanmore(patrn,dir,sts)	\/* search forward or b/
+scinit	ibmpc.c	/^scinit()	\/* initialize the screen head pointers *\//
+scrnextdw	window.c	/^scrnextdw(f, n)		\/* scroll the next window down (f/
+scrnextup	window.c	/^scrnextup(f, n)		\/* scroll the next window up (bac/
+scwrite	ibmpc.c	/^scwrite(row, outstr, forg, bacg)	\/* write a line o/
+setfillcol	random.c	/^setfillcol(f, n)$/
+setgmode	random.c	/^setgmode(f, n)	\/* prompt and set a global editor m/
+setmark	basic.c	/^setmark(f, n)$/
+setmode	random.c	/^setmode(f, n)	\/* prompt and set an editor mode *\/$/
+showcpos	random.c	/^showcpos(f, n)$/
+shrinkwind	window.c	/^shrinkwind(f, n)$/
+spawn	spawn.c	/^spawn(f, n)$/
+spawncli	spawn.c	/^spawncli(f, n)$/
+splitwind	window.c	/^splitwind(f, n)$/
+sreplace	search.c	/^sreplace(f, n)	\/*	Search and replace (ESC-R)	*\/$/
+startup	bind.c	/^startup(sfname)$/
+storemac	exec.c	/^storemac(f, n)$/
+swapmark	basic.c	/^swapmark(f, n)$/
+swbuffer	buffer.c	/^swbuffer(bp)	\/* make buffer BP current *\/$/
+sys	spawn.c	/^sys(cmd)$/
+sys	spawn.c	/^sys(cmd, tail)$/
+system	spawn.c	/^#define	system(a)	spawnlp(P_WAIT, a, NULL)$/
+system	spawn.c	/^system(cmd)$/
+tab	random.c	/^tab(f, n)$/
+tcapbcol	tcap.c	/^tcapbcol()	\/* no colors here, ignore this *\/$/
+tcapbeep	tcap.c	/^tcapbeep()$/
+tcapeeol	tcap.c	/^tcapeeol()$/
+tcapeeop	tcap.c	/^tcapeeop()$/
+tcapfcol	tcap.c	/^tcapfcol()	\/* no colors here, ignore this *\/$/
+tcapmove	tcap.c	/^tcapmove(row, col)$/
+tcapopen	tcap.c	/^tcapopen()$/
+tcaprev	tcap.c	/^tcaprev(state)		\/* change reverse video status *\/$/
+ttclose	termio.c	/^ttclose()$/
+ttflush	termio.c	/^ttflush()$/
+ttgetc	termio.c	/^ttgetc()$/
+ttopen	termio.c	/^ttopen()$/
+ttputc	termio.c	/^ttputc(c)$/
+ttputs	vmsvt.c	/^ttputs(string)$/
+twiddle	random.c	/^twiddle(f, n)$/
+typahead	termio.c	/^typahead()$/
+unbindkey	bind.c	/^unbindkey(f, n)$/
+undefkey	hp150.c	/^undefkey()	\/* change all special keys to intercept/
+uneat	isearch.c	/^int uneat()$/
+unlock	lock.c	/^unlock(fname)$/
+unmark	buffer.c	/^unmark(f, n)	\/* unmark the current buffers change /
+updall	display.c	/^updall(wp)$/
+update	display.c	/^update(force)$/
+updateline	display.c	/^updateline(row, vp1)$/
+updateline	display.c	/^updateline(row, vp1, vp2)$/
+upddex	display.c	/^upddex()$/
+updext	display.c	/^updext()$/
+updgar	display.c	/^updgar()$/
+updone	display.c	/^updone(wp)$/
+updpos	display.c	/^updpos()$/
+updupd	display.c	/^updupd(force)$/
+upmode	display.c	/^upmode()	\/* update all the mode lines *\/$/
+upperregion	region.c	/^upperregion(f, n)$/
+upperword	word.c	/^upperword(f, n)$/
+upscreen	display.c	/^upscreen(f, n)$/
+usebuffer	buffer.c	/^usebuffer(f, n)$/
+viewfile	file.c	/^viewfile(f, n)	\/* visit a file in VIEW mode *\/$/
+vmsbcol	vmsvt.c	/^vmsbcol()$/
+vmsbeep	vmsvt.c	/^vmsbeep()$/
+vmseeol	vmsvt.c	/^vmseeol()$/
+vmseeop	vmsvt.c	/^vmseeop()$/
+vmsfcol	vmsvt.c	/^vmsfcol()$/
+vmsgtty	vmsvt.c	/^vmsgtty()$/
+vmsmove	vmsvt.c	/^vmsmove(row, col)$/
+vmsopen	vmsvt.c	/^vmsopen()$/
+vmspad	vmsvt.c	/^vmspad(count)$/
+vmsrev	vmsvt.c	/^vmsrev(status)$/
+vt52bcol	vt52.c	/^vt52bcol()	\/* set the background color [NOT IMPLIM/
+vt52beep	vt52.c	/^vt52beep()$/
+vt52eeol	vt52.c	/^vt52eeol()$/
+vt52eeop	vt52.c	/^vt52eeop()$/
+vt52fcol	vt52.c	/^vt52fcol()	\/* set the forground color [NOT IMPLIME/
+vt52move	vt52.c	/^vt52move(row, col)$/
+vt52open	vt52.c	/^vt52open()$/
+vt52rev	vt52.c	/^vt52rev(status)	\/* set the reverse video state *\/$/
+vteeol	display.c	/^vteeol()$/
+vtinit	display.c	/^vtinit()$/
+vtmove	display.c	/^vtmove(row, col)$/
+vtputc	display.c	/^vtputc(c)$/
+vtpute	display.c	/^vtpute(c)$/
+vttidy	display.c	/^vttidy()$/
+wordcount	word.c	/^wordcount(f, n)$/
+wpopup	window.c	/^wpopup()$/
+wrapword	word.c	/^wrapword(n)$/
+writemsg	random.c	/^writemsg(f, n)$/
+writeout	file.c	/^writeout(fn)$/
+yank	line.c	/^yank(f, n)$/
+zotbuf	buffer.c	/^zotbuf(bp)	\/* kill the buffer pointed to by bp *\/$/

Added: clients/emacs/tcap.c
===================================================================
--- clients/emacs/tcap.c	                        (rev 0)
+++ clients/emacs/tcap.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,202 @@
+/*	tcap:	Unix V5, V7 and BS4.2 Termcap video driver
+		for MicroEMACS
+*/
+
+#define	termdef	1			/* don't define "term" external */
+
+#include	"estruct.h"
+#include        "edef.h"
+
+#if TERMCAP
+
+#define	MARGIN	8
+#define	SCRSIZ	64
+#define	NPAUSE	10			/* # times thru update to pause */
+#define BEL     0x07
+#define ESC     0x1B
+
+extern int      ttopen();
+extern int      ttgetc();
+extern int      ttputc();
+extern int	tgetnum();
+extern int      ttflush();
+extern int      ttclose();
+extern int      tcapmove();
+extern int      tcapeeol();
+extern int      tcapeeop();
+extern int      tcapbeep();
+extern int	tcaprev();
+extern int      tcapopen();
+extern int      tput();
+extern char     *tgoto();
+#if	COLOR
+extern	int	tcapfcol();
+extern	int	tcapbcol();
+#endif
+
+#define TCAPSLEN 315
+char tcapbuf[TCAPSLEN];
+char *UP, PC, *CM, *CE, *CL, *SO, *SE;
+
+TERM term = {
+	NULL,		/* these two values are set dynamically at open time */
+	NULL,
+	MARGIN,
+	SCRSIZ,
+	NPAUSE,
+        tcapopen,
+        ttclose,
+        ttgetc,
+        ttputc,
+        ttflush,
+        tcapmove,
+        tcapeeol,
+        tcapeeop,
+        tcapbeep,
+        tcaprev
+#if	COLOR
+	, tcapfcol,
+	tcapbcol
+#endif
+};
+
+tcapopen()
+
+{
+        char *getenv();
+        char *t, *p, *tgetstr();
+        char tcbuf[1024];
+        char *tv_stype;
+        char err_str[72];
+
+        if ((tv_stype = getenv("TERM")) == NULL)
+        {
+                puts("Environment variable TERM not defined!");
+                exit(1);
+        }
+
+        if ((tgetent(tcbuf, tv_stype)) != 1)
+        {
+                sprintf(err_str, "Unknown terminal type %s!", tv_stype);
+                puts(err_str);
+                exit(1);
+        }
+
+ 
+       if ((term.t_nrow=(short)tgetnum("li")-1) == -1){
+               puts("termcap entry incomplete (lines)");
+               exit(1);
+       }
+ 
+       if ((term.t_ncol=(short)tgetnum("co")) == -1){
+               puts("Termcap entry incomplete (columns)");
+               exit(1);
+       }
+
+        p = tcapbuf;
+        t = tgetstr("pc", &p);
+        if(t)
+                PC = *t;
+
+        CL = tgetstr("cl", &p);
+        CM = tgetstr("cm", &p);
+        CE = tgetstr("ce", &p);
+        UP = tgetstr("up", &p);
+	SE = tgetstr("se", &p);
+	SO = tgetstr("so", &p);
+	if (SO != NULL)
+		revexist = TRUE;
+
+        if(CL == NULL || CM == NULL || UP == NULL)
+        {
+                puts("Incomplete termcap entry\n");
+                exit(1);
+        }
+
+	if (CE == NULL)		/* will we be able to use clear to EOL? */
+		eolexist = FALSE;
+		
+        if (p >= &tcapbuf[TCAPSLEN])
+        {
+                puts("Terminal description too big!\n");
+                exit(1);
+        }
+        ttopen();
+}
+
+tcapmove(row, col)
+register int row, col;
+{
+        putpad(tgoto(CM, col, row));
+}
+
+tcapeeol()
+{
+        putpad(CE);
+}
+
+tcapeeop()
+{
+        putpad(CL);
+}
+
+tcaprev(state)		/* change reverse video status */
+
+int state;		/* FALSE = normal video, TRUE = reverse video */
+
+{
+	static int revstate = FALSE;
+	/* mustn't send SE unless SO already sent, and vice versa */
+
+#if 0
+	if (state) {
+		if ((SO != NULL) && (revstate == FALSE))
+			putpad(SO);
+	} else
+		if ((SE != NULL) && (revstate == TRUE))
+			putpad(SE);
+
+	revstate = state;
+#endif
+	if (state) {
+		if (SO != NULL)
+			putpad(SO);
+	} else
+		if (SE != NULL)
+			putpad(SE);
+}
+
+#if	COLOR
+tcapfcol()	/* no colors here, ignore this */
+{
+}
+
+tcapbcol()	/* no colors here, ignore this */
+{
+}
+#endif
+
+tcapbeep()
+{
+	ttputc(BEL);
+}
+
+putpad(str)
+char    *str;
+{
+	tputs(str, 1, ttputc);
+}
+
+putnpad(str, n)
+char    *str;
+{
+	tputs(str, n, ttputc);
+}
+
+#else
+
+hello()
+{
+}
+
+#endif TERMCAP

Added: clients/emacs/termio.c
===================================================================
--- clients/emacs/termio.c	                        (rev 0)
+++ clients/emacs/termio.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,476 @@
+/*
+ * The functions in this file negotiate with the operating system for
+ * characters, and write characters in a barely buffered fashion on the display.
+ * All operating systems.
+ */
+
+#include	"estruct.h"
+#include        "edef.h"
+#ifdef __ZTC__
+#include	<dos.h>
+#endif
+#if     V7 | USG | BSD | OFW
+#include	"stdio.h"
+#endif
+
+#if     AMIGA
+#define NEW 1006
+#define AMG_MAXBUF      1024
+static long terminal;
+static char     scrn_tmp[AMG_MAXBUF+1];
+static int      scrn_tmp_p = 0;
+#endif
+
+#if     VMS
+#include        <stsdef.h>
+#include        <ssdef.h>
+#include        <descrip.h>
+#include        <iodef.h>
+#include        <ttdef.h>
+#include	<tt2def.h>
+
+#define NIBUF   128                     /* Input buffer size            */
+#define NOBUF   1024                    /* MM says bug buffers win!     */
+#define EFN     0                       /* Event flag                   */
+
+char    obuf[NOBUF];                    /* Output buffer                */
+int     nobuf;                  /* # of bytes in above    */
+char    ibuf[NIBUF];                    /* Input buffer          */
+int     nibuf;                  /* # of bytes in above  */
+int     ibufi;                  /* Read index                   */
+int     oldmode[3];                     /* Old TTY mode bits            */
+int     newmode[3];                     /* New TTY mode bits            */
+short   iochan;                  /* TTY I/O channel             */
+#endif
+
+#if     CPM
+#include        <bdos.h>
+#endif
+
+#if     MSDOS & (LATTICE | MSDOS)
+union REGS rg;		/* cpu register for use of DOS calls */
+int nxtchar = -1;	/* character held from type ahead    */
+#endif
+
+#if RAINBOW
+#include "rainbow.h"
+#endif
+
+#if	USG			/* System V */
+#include	<signal.h>
+#include	<termio.h>
+struct	termio	otermio;	/* original terminal characteristics */
+struct	termio	ntermio;	/* charactoristics to use inside */
+#endif
+
+#if V7 | BSD
+#undef	CTRL
+#include        <sgtty.h>        /* for stty/gtty functions */
+#include	<signal.h>
+struct  sgttyb  ostate;          /* saved tty state */
+struct  sgttyb  nstate;          /* values for editor mode */
+struct tchars	otchars;	/* Saved terminal special character set */
+struct tchars	ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+				/* A lot of nothing */
+#if BSD
+#include <sys/ioctl.h>		/* to get at the typeahead */
+extern	int rtfrmshell();	/* return from suspended shell */
+#define	TBUFSIZ	128
+char tobuf[TBUFSIZ];		/* terminal output buffer */
+#endif
+#endif
+
+/*
+ * This function is called once to set up the terminal device streams.
+ * On VMS, it translates TT until it finds the terminal, then assigns
+ * a channel to it and sets it raw. On CPM it is a no-op.
+ */
+ttopen()
+{
+	/* on all screens we are not sure of the initial position
+	   of the cursor					*/
+	ttrow = 999;
+	ttcol = 999;
+
+#if     AMIGA
+        terminal = Open("RAW:1/1/639/199/MicroEMACS 3.7/Amiga", NEW);
+#endif
+#if     VMS
+        struct  dsc$descriptor  idsc;
+        struct  dsc$descriptor  odsc;
+        char    oname[40];
+        int     iosb[2];
+        int     status;
+
+        odsc.dsc$a_pointer = "TT";
+        odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
+        odsc.dsc$b_dtype        = DSC$K_DTYPE_T;
+        odsc.dsc$b_class        = DSC$K_CLASS_S;
+        idsc.dsc$b_dtype        = DSC$K_DTYPE_T;
+        idsc.dsc$b_class        = DSC$K_CLASS_S;
+        do {
+                idsc.dsc$a_pointer = odsc.dsc$a_pointer;
+                idsc.dsc$w_length  = odsc.dsc$w_length;
+                odsc.dsc$a_pointer = &oname[0];
+                odsc.dsc$w_length  = sizeof(oname);
+                status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
+                if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
+                        exit(status);
+                if (oname[0] == 0x1B) {
+                        odsc.dsc$a_pointer += 4;
+                        odsc.dsc$w_length  -= 4;
+                }
+        } while (status == SS$_NORMAL);
+        status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
+        if (status != SS$_NORMAL)
+                exit(status);
+        status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
+                          oldmode, sizeof(oldmode), 0, 0, 0, 0);
+        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+                exit(status);
+        newmode[0] = oldmode[0];
+        newmode[1] = oldmode[1] | TT$M_NOECHO;
+        newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
+        newmode[2] = oldmode[2] | TT2$M_PASTHRU;
+        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
+                          newmode, sizeof(newmode), 0, 0, 0, 0);
+        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+                exit(status);
+        term.t_nrow = (newmode[1]>>24) - 1;
+        term.t_ncol = newmode[0]>>16;
+
+#endif
+#if     CPM
+#endif
+
+#if     MSDOS & (HP150 == 0) & LATTICE
+	/* kill the ctrl-break interupt */
+	rg.h.ah = 0x33;		/* control-break check dos call */
+	rg.h.al = 1;		/* set the current state */
+	rg.h.dl = 0;		/* set it OFF */
+	intdos(&rg, &rg);	/* go for it! */
+#endif
+
+#if	USG
+	ioctl(o, TCGETA, &otermio);	/* save old settings */
+	ntermio.c_iflag = 0;		/* setup new settings */
+	ntermio.c_oflag = 0;
+	ntermio.c_cflag = otermio.c_cflag;
+	ntermio.c_lflag = 0;
+	ntermio.c_line = otermio.c_line;
+	ntermio.c_cc[VMIN] = 1;
+	ntermio.c_cc[VTIME] = 0;
+	ioctl(0, TCSETA, &ntermio);	/* and activate them */
+#endif
+
+#if     V7 | BSD
+        gtty(0, &ostate);                       /* save old state */
+        gtty(0, &nstate);                       /* get base of new state */
+        nstate.sg_flags |= RAW;
+        nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
+        stty(0, &nstate);                       /* set mode */
+	ioctl(0, TIOCGETC, &otchars);		/* Save old characters */
+	ioctl(0, TIOCSETC, &ntchars);		/* Place new character into K */
+#if	BSD
+	/* provide a smaller terminal output buffer so that
+	   the type ahead detection works better (more often) */
+	setbuffer(stdout, &tobuf[0], TBUFSIZ);
+	signal(SIGTSTP,SIG_DFL);	/* set signals so that we can */
+	signal(SIGCONT,rtfrmshell);	/* suspend & restart emacs */
+#endif
+#endif
+}
+
+/*
+ * This function gets called just before we go back home to the command
+ * interpreter. On VMS it puts the terminal back in a reasonable state.
+ * Another no-operation on CPM.
+ */
+ttclose()
+{
+#if     AMIGA
+        amg_flush();
+        Close(terminal);
+#endif
+#if     VMS
+        int     status;
+        int     iosb[1];
+
+        ttflush();
+        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
+                 oldmode, sizeof(oldmode), 0, 0, 0, 0);
+        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+                exit(status);
+        status = SYS$DASSGN(iochan);
+        if (status != SS$_NORMAL)
+                exit(status);
+#endif
+#if     CPM
+#endif
+#if     MSDOS & (HP150 == 0) & LATTICE
+	/* restore the ctrl-break interupt */
+	rg.h.ah = 0x33;		/* control-break check dos call */
+	rg.h.al = 1;		/* set the current state */
+	rg.h.dl = 1;		/* set it ON */
+	intdos(&rg, &rg);	/* go for it! */
+#endif
+
+#if	USG
+	ioctl(0, TCSETA, &otermio);	/* restore terminal settings */
+#endif
+
+#if     V7 | BSD
+        stty(0, &ostate);
+	ioctl(0, TIOCSETC, &otchars);	/* Place old character into K */
+#endif
+#if	OFW
+	ansibcol(7);
+	ansifcol(0);
+	ansieeol();
+	ttflush();
+	OFInterpret0("false to already-go?");
+#endif
+}
+
+/*
+ * Write a character to the display. On VMS, terminal output is buffered, and
+ * we just put the characters in the big array, after checking for overflow.
+ * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
+ * MS-DOS (use the very very raw console output routine).
+ */
+ttputc(c)
+#if     AMIGA
+        char c;
+#endif
+{
+#if     AMIGA
+        scrn_tmp[scrn_tmp_p++] = c;
+        if(scrn_tmp_p>=AMG_MAXBUF)
+                amg_flush();
+#endif
+#if     VMS
+        if (nobuf >= NOBUF)
+                ttflush();
+        obuf[nobuf++] = c;
+#endif
+
+#if     CPM
+        bios(BCONOUT, c, 0);
+#endif
+
+#if     MSDOS & MWC86
+        dosb(CONDIO, c, 0);
+#endif
+
+#if	MSDOS & (LATTICE | AZTEC | MSC) & ~IBMPC
+	bdos(6, c, 0);
+#endif
+
+#if RAINBOW
+        Put_Char(c);                    /* fast video */
+#endif
+
+
+#if     V7 | USG | BSD | OFW
+        fputc(c, stdout);
+#endif
+}
+
+#if	AMIGA
+amg_flush()
+{
+        if(scrn_tmp_p)
+                Write(terminal,scrn_tmp,scrn_tmp_p);
+        scrn_tmp_p = 0;
+}
+#endif
+
+/*
+ * Flush terminal buffer. Does real work where the terminal output is buffered
+ * up. A no-operation on systems where byte at a time terminal I/O is done.
+ */
+ttflush()
+{
+#if     AMIGA
+        amg_flush();
+#endif
+#if     VMS
+        int     status;
+        int     iosb[2];
+
+        status = SS$_NORMAL;
+        if (nobuf != 0) {
+                status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
+                         iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
+                if (status == SS$_NORMAL)
+                        status = iosb[0] & 0xFFFF;
+                nobuf = 0;
+        }
+        return (status);
+#endif
+
+#if     CPM
+#endif
+
+#if     MSDOS
+#endif
+
+#if     V7 | USG | BSD | OFW
+        fflush(stdout);
+#endif
+}
+
+/*
+ * Read a character from the terminal, performing no editing and doing no echo
+ * at all. More complex in VMS that almost anyplace else, which figures. Very
+ * simple on CPM, because the system can do exactly what you want.
+ */
+ttgetc()
+{
+#if     AMIGA
+        char ch;
+        amg_flush();
+        Read(terminal, &ch, 1);
+        return(255 & (int)ch);
+#endif
+#if     VMS
+        int     status;
+        int     iosb[2];
+        int     term[2];
+
+        while (ibufi >= nibuf) {
+                ibufi = 0;
+                term[0] = 0;
+                term[1] = 0;
+                status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
+                         iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
+                if (status != SS$_NORMAL)
+                        exit(status);
+                status = iosb[0] & 0xFFFF;
+                if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
+                        exit(status);
+                nibuf = (iosb[0]>>16) + (iosb[1]>>16);
+                if (nibuf == 0) {
+                        status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
+                                 iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
+                        if (status != SS$_NORMAL
+                        || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
+                                exit(status);
+                        nibuf = (iosb[0]>>16) + (iosb[1]>>16);
+                }
+        }
+        return (ibuf[ibufi++] & 0xFF);    /* Allow multinational  */
+#endif
+
+#if     CPM
+        return (biosb(BCONIN, 0, 0));
+#endif
+
+#if RAINBOW
+        int Ch;
+
+        while ((Ch = Read_Keyboard()) < 0);
+
+        if ((Ch & Function_Key) == 0)
+                if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
+                        Ch &= 0xFF;
+
+        return Ch;
+#endif
+
+#if     MSDOS & MWC86
+        return (dosb(CONRAW, 0, 0));
+#endif
+
+#if	MSDOS & (LATTICE | MSC)
+	int c;		/* character read */
+
+	/* if a char already is ready, return it */
+	if (nxtchar >= 0) {
+		c = nxtchar;
+		nxtchar = -1;
+		return(c);
+	}
+
+	/* call the dos to get a char */
+	rg.h.ah = 7;		/* dos Direct Console Input call */
+	intdos(&rg, &rg);
+	c = rg.h.al;		/* grab the char */
+	return(c & 255);
+#endif
+
+#if	MSDOS & AZTEC
+	int c;		/* character read */
+
+	/* if a char already is ready, return it */
+	if (nxtchar >= 0) {
+		c = nxtchar;
+		nxtchar = -1;
+		return(c);
+	}
+
+	/* call the dos to get a char */
+	rg.h.ah = 7;		/* dos Direct Console I/O call */
+	sysint(33, &rg, &rg);
+	c = rg.h.al;		/* grab the char */
+	return(c & 255);
+#endif
+
+#if     V7 | USG | BSD
+        return(127 & fgetc(stdin));
+#endif
+
+#if     OFW
+        return(fgetc(stdin));
+#endif
+}
+
+#if	TYPEAH
+/* typahead:	Check to see if any characters are already in the
+		keyboard buffer
+*/
+
+typahead()
+
+{
+#if	MSDOS & (LATTICE | AZTEC)
+	int c;		/* character read */
+	int flags;	/* cpu flags from dos call */
+
+#if	MSC
+	if (kbhit() != 0)
+		return(TRUE);
+	else
+		return(FALSE);
+#endif
+
+	if (nxtchar >= 0)
+		return(TRUE);
+
+	rg.h.ah = 6;	/* Direct Console I/O call */
+	rg.h.dl = 255;	/*         does console input */
+#if	LATTICE
+	flags = intdos(&rg, &rg);
+#else
+	flags = sysint(33, &rg, &rg);
+#endif
+	c = rg.h.al;	/* grab the character */
+
+	/* no character pending */
+	if ((flags & 64) != 0)
+		return(FALSE);
+
+	/* save the character and return true */
+	nxtchar = c;
+	return(TRUE);
+#endif
+
+#if	BSD
+	int x;	/* holds # of pending chars */
+
+	return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
+#endif
+	return(FALSE);
+}
+#endif
+

Added: clients/emacs/vmsvt.c
===================================================================
--- clients/emacs/vmsvt.c	                        (rev 0)
+++ clients/emacs/vmsvt.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,310 @@
+/*
+ *  VMS terminal handling routines
+ *
+ *  Known types are:
+ *    VT52, VT100, and UNKNOWN (which is defined to be an ADM3a)
+ *    written by Curtis Smith
+ */
+
+#include        "estruct.h"
+#include	"edef.h"
+
+#if     VMSVT
+
+#define	termdef	1			/* don't define "term" external */
+
+#include <ssdef.h>		/* Status code definitions		*/
+#include <descrip.h>		/* Descriptor structures		*/
+#include <iodef.h>		/* IO commands				*/
+#include <ttdef.h>		/* tty commands				*/
+
+extern  int     ttopen();               /* Forward references.          */
+extern  int     ttgetc();
+extern  int     ttputc();
+extern  int     ttflush();
+extern  int     ttclose();
+extern  int	vmsopen();
+extern  int	vmseeol();
+extern  int	vmseeop();
+extern  int	vmsbeep();
+extern  int	vmsmove();
+extern	int	vmsrev();
+extern  int	eolexist;
+#if	COLOR
+extern	int	vmsfcol();
+extern	int	vmsbcol();
+#endif
+
+#define	NROWS	24			/* # of screen rolls		*/
+#define	NCOLS	80			/* # of screen columns		*/
+#define	MARGIN	8			/* size of minimim margin and	*/
+#define	SCRSIZ	64			/* scroll size for extended lines */
+#define	NPAUSE	100			/* # times thru update to pause */
+
+/*
+ * Dispatch table. All the
+ * hard fields just point into the
+ * terminal I/O code.
+ */
+TERM    term    = {
+	NROWS - 1,
+	NCOLS,
+	MARGIN,
+	SCRSIZ,
+	NPAUSE,
+        &vmsopen,
+        &ttclose,
+        &ttgetc,
+        &ttputc,
+        &ttflush,
+        &vmsmove,
+        &vmseeol,
+        &vmseeop,
+        &vmsbeep,
+        &vmsrev
+#if	COLOR
+	, &vmsfcol,
+	&vmsbcol
+#endif
+};
+
+char * termeop;			/* Erase to end of page string		*/
+int eoppad;			/* Number of pad characters after eop	*/
+char * termeol;			/* Erase to end of line string		*/
+int eolpad;			/* Number of pad characters after eol	*/
+char termtype;			/* Terminal type identifier		*/
+
+
+/*******
+ *  ttputs - Send a string to ttputc
+ *******/
+
+ttputs(string)
+char * string;
+{
+	while (*string != '\0')
+		ttputc(*string++);
+}
+
+
+/*******
+ *  vmspad - Pad the output after an escape sequence
+ *******/
+
+vmspad(count)
+int count;
+{
+	while (count-- > 0)
+		ttputc('\0');
+}
+
+
+/*******
+ *  vmsmove - Move the cursor
+ *******/
+
+vmsmove(row, col)
+{
+	switch (termtype) {
+		case TT$_UNKNOWN:
+			ttputc('\033');
+			ttputc('=');
+			ttputc(row+' ');
+			ttputc(col+' ');
+			break;
+		case TT$_VT52:
+			ttputc('\033');
+			ttputc('Y');
+			ttputc(row+' ');
+			ttputc(col+' ');
+			break;
+                case TT$_VT100:         /* I'm assuming that all these  */
+                case TT$_VT101:         /* are a super set of the VT100 */
+                case TT$_VT102:         /* If I'm wrong, just remove    */
+                case TT$_VT105:         /* those entries that aren't.   */
+                case TT$_VT125:
+                case TT$_VT131:
+                case TT$_VT132:
+                case TT$_VT200_SERIES:
+			{
+				char buffer[24];
+
+				sprintf(buffer, "\033[%d;%dH", row+1, col+1);
+				ttputs(buffer);
+				vmspad(50);
+			}
+	}
+}
+
+/*******
+ *  vmsrev - set the reverse video status
+ *******/
+
+vmsrev(status)
+
+int status;	/* TRUE = reverse video, FALSE = normal video */
+{
+	switch (termtype) {
+		case TT$_UNKNOWN:
+			break;
+		case TT$_VT52:
+			break;
+		case TT$_VT100:
+			if (status) {
+				ttputc('\033');
+				ttputc('[');
+				ttputc('7');
+				ttputc('m');
+			} else {
+				ttputc('\033');
+				ttputc('[');
+				ttputc('m');
+			}
+			break;
+	}
+}
+
+#if	COLOR
+/*******
+ *  vmsfcol - Set the forground color (not implimented)
+ *******/
+ 
+vmsfcol()
+{
+}
+
+/*******
+ *  vmsbcol - Set the background color (not implimented)
+ *******/
+ 
+vmsbcol()
+{
+}
+#endif
+
+/*******
+ *  vmseeol - Erase to end of line
+ *******/
+
+vmseeol()
+{
+	ttputs(termeol);
+	vmspad(eolpad);
+}
+
+
+/*******
+ *  vmseeop - Erase to end of page (clear screen)
+ *******/
+
+vmseeop()
+{
+	ttputs(termeop);
+	vmspad(eoppad);
+}
+
+
+/*******
+ *  vmsbeep - Ring the bell
+ *******/
+
+vmsbeep()
+{
+	ttputc('\007');
+}
+
+
+/*******
+ *  vmsopen - Get terminal type and open terminal
+ *******/
+
+vmsopen()
+{
+	termtype = vmsgtty();
+	switch (termtype) {
+		case TT$_UNKNOWN:	/* Assume ADM3a	*/
+			eolexist = FALSE;
+			termeop = "\032";
+			eoppad = 0;
+			break;
+		case TT$_VT52:
+			termeol = "\033K";
+			eolpad = 0;
+			termeop = "\033H\033J";
+			eoppad = 0;
+			break;
+		case TT$_VT100:
+			revexist = TRUE;
+			termeol = "\033[K";
+			eolpad = 3;
+			termeop = "\033[;H\033[2J";
+			eoppad = 50;
+			break;
+		default:
+			puts("Terminal type not supported");
+			exit (SS$_NORMAL);
+	}
+        ttopen();
+}
+
+
+struct iosb {			/* I/O status block			*/
+	short	i_cond;		/* Condition value			*/
+	short	i_xfer;		/* Transfer count			*/
+	long	i_info;		/* Device information			*/
+};
+
+struct termchar {		/* Terminal characteristics		*/
+	char	t_class;	/* Terminal class			*/
+	char	t_type;		/* Terminal type			*/
+	short	t_width;	/* Terminal width in characters		*/
+	long	t_mandl;	/* Terminal's mode and length		*/
+	long	t_extend;	/* Extended terminal characteristics	*/
+};
+
+/*******
+ *  vmsgtty - Get terminal type from system control block
+ *******/
+
+vmsgtty()
+{
+	short fd;
+	int status;
+	struct iosb iostatus;
+	struct termchar tc;
+	$DESCRIPTOR(devnam, "SYS$INPUT");
+
+	status = sys$assign(&devnam, &fd, 0, 0);
+	if (status != SS$_NORMAL)
+		exit (status);
+
+	status = sys$qiow(		/* Queue and wait		*/
+		0,			/* Wait on event flag zero	*/
+		fd,			/* Channel to input terminal	*/
+		IO$_SENSEMODE,		/* Get current characteristic	*/
+		&iostatus,		/* Status after operation	*/
+		0, 0,			/* No AST service		*/
+		&tc,			/* Terminal characteristics buf	*/
+		sizeof(tc),		/* Size of the buffer		*/
+		0, 0, 0, 0);		/* P3-P6 unused			*/
+
+					/* De-assign the input device	*/
+	if (sys$dassgn(fd) != SS$_NORMAL)
+		exit(status);
+
+	if (status != SS$_NORMAL)	/* Jump out if bad status	*/
+		exit(status);
+	if (iostatus.i_cond != SS$_NORMAL)
+		exit(iostatus.i_cond);
+
+	return tc.t_type;		/* Return terminal type		*/
+}
+
+#else
+
+hellovms()
+
+{
+}
+
+#endif	VMSVT

Added: clients/emacs/vt52.c
===================================================================
--- clients/emacs/vt52.c	                        (rev 0)
+++ clients/emacs/vt52.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,133 @@
+/*
+ * The routines in this file
+ * provide support for VT52 style terminals
+ * over a serial line. The serial I/O services are
+ * provided by routines in "termio.c". It compiles
+ * into nothing if not a VT52 style device. The
+ * bell on the VT52 is terrible, so the "beep"
+ * routine is conditionalized on defining BEL.
+ */
+#define	termdef	1			/* don't define "term" external */
+
+#include        "estruct.h"
+#include	"edef.h"
+
+#if     VT52
+
+#define NROW    24                      /* Screen size.                 */
+#define NCOL    80                      /* Edit if you want to.         */
+#define	MARGIN	8			/* size of minimim margin and	*/
+#define	SCRSIZ	64			/* scroll size for extended lines */
+#define	NPAUSE	100			/* # times thru update to pause */
+#define BIAS    0x20                    /* Origin 0 coordinate bias.    */
+#define ESC     0x1B                    /* ESC character.               */
+#define BEL     0x07                    /* ascii bell character         */
+
+extern  int     ttopen();               /* Forward references.          */
+extern  int     ttgetc();
+extern  int     ttputc();
+extern  int     ttflush();
+extern  int     ttclose();
+extern  int     vt52move();
+extern  int     vt52eeol();
+extern  int     vt52eeop();
+extern  int     vt52beep();
+extern  int     vt52open();
+extern	int	vt52rev();
+#if	COLOR
+extern	int	vt52fcol();
+extern	int	vt52bcol();
+#endif
+
+/*
+ * Dispatch table. All the
+ * hard fields just point into the
+ * terminal I/O code.
+ */
+TERM    term    = {
+        NROW-1,
+        NCOL,
+	MARGIN,
+	SCRSIZ,
+	NPAUSE,
+        &vt52open,
+        &ttclose,
+        &ttgetc,
+        &ttputc,
+        &ttflush,
+        &vt52move,
+        &vt52eeol,
+        &vt52eeop,
+        &vt52beep,
+        &vt52rev
+#if	COLOR
+	, &vt52fcol,
+	&vt52bcol
+#endif
+};
+
+vt52move(row, col)
+{
+        ttputc(ESC);
+        ttputc('Y');
+        ttputc(row+BIAS);
+        ttputc(col+BIAS);
+}
+
+vt52eeol()
+{
+        ttputc(ESC);
+        ttputc('K');
+}
+
+vt52eeop()
+{
+        ttputc(ESC);
+        ttputc('J');
+}
+
+vt52rev(status)	/* set the reverse video state */
+
+int status;	/* TRUE = reverse video, FALSE = normal video */
+
+{
+	/* can't do this here, so we won't */
+}
+
+#if	COLOR
+vt52fcol()	/* set the forground color [NOT IMPLIMENTED] */
+{
+}
+
+vt52bcol()	/* set the background color [NOT IMPLIMENTED] */
+{
+}
+#endif
+
+vt52beep()
+{
+#ifdef  BEL
+        ttputc(BEL);
+        ttflush();
+#endif
+}
+
+#endif
+
+vt52open()
+{
+#if     V7 | BSD
+        register char *cp;
+        char *getenv();
+
+        if ((cp = getenv("TERM")) == NULL) {
+                puts("Shell variable TERM not defined!");
+                exit(1);
+        }
+        if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) {
+                puts("Terminal type not 'vt52'or 'z19' !");
+                exit(1);
+        }
+#endif
+        ttopen();
+}

Added: clients/emacs/window.c
===================================================================
--- clients/emacs/window.c	                        (rev 0)
+++ clients/emacs/window.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,571 @@
+/*
+ * Window management. Some of the functions are internal, and some are
+ * attached to keys that the user actually types.
+ */
+
+#include        "estruct.h"
+#include	"edef.h"
+
+/*
+ * Reposition dot in the current window to line "n". If the argument is
+ * positive, it is that line. If it is negative it is that line from the
+ * bottom. If it is 0 the window is centered (this is what the standard
+ * redisplay code does). With no argument it defaults to 0. Bound to M-!.
+ */
+reposition(f, n)
+    {
+    if (f == FALSE)	/* default to 0 to center screen */
+	n = 0;
+    curwp->w_force = n;
+    curwp->w_flag |= WFFORCE;
+    return (TRUE);
+    }
+
+/*
+ * Refresh the screen. With no argument, it just does the refresh. With an
+ * argument it recenters "." in the current window. Bound to "C-L".
+ */
+refresh(f, n)
+    {
+    if (f == FALSE)
+        sgarbf = TRUE;
+    else
+        {
+        curwp->w_force = 0;             /* Center dot. */
+        curwp->w_flag |= WFFORCE;
+        }
+
+    return (TRUE);
+    }
+
+/*
+ * The command make the next window (next => down the screen) the current
+ * window. There are no real errors, although the command does nothing if
+ * there is only 1 window on the screen. Bound to "C-X C-N".
+ *
+ * with an argument this command finds the <n>th window from the top
+ *
+ */
+nextwind(f, n)
+
+int f, n;	/* default flag and numeric argument */
+
+{
+	register WINDOW *wp;
+	register int nwindows;		/* total number of windows */
+
+	if (f) {
+
+		/* first count the # of windows */
+		wp = wheadp;
+		nwindows = 1;
+		while (wp->w_wndp != NULL) {
+			nwindows++;
+			wp = wp->w_wndp;
+		}
+
+		/* if the argument is negative, it is the nth window
+		   from the bottom of the screen			*/
+		if (n < 0)
+			n = nwindows + n + 1;
+
+		/* if an argument, give them that window from the top */
+		if (n > 0 && n <= nwindows) {
+			wp = wheadp;
+			while (--n)
+				wp = wp->w_wndp;
+		} else {
+			mlwrite("Window number out of range");
+			return(FALSE);
+		}
+	} else
+		if ((wp = curwp->w_wndp) == NULL)
+			wp = wheadp;
+	curwp = wp;
+	curbp = wp->w_bufp;
+	upmode();
+	return (TRUE);
+}
+
+/*
+ * This command makes the previous window (previous => up the screen) the
+ * current window. There arn't any errors, although the command does not do a
+ * lot if there is 1 window.
+ */
+prevwind(f, n)
+{
+	register WINDOW *wp1;
+	register WINDOW *wp2;
+	register int nwindows;	/* total # of windows */
+
+	/* if we have an argument, we mean the nth window from the bottom */
+	if (f)
+		return(nextwind(f, -n));
+
+	wp1 = wheadp;
+	wp2 = curwp;
+
+	if (wp1 == wp2)
+		wp2 = NULL;
+
+	while (wp1->w_wndp != wp2)
+		wp1 = wp1->w_wndp;
+
+	curwp = wp1;
+	curbp = wp1->w_bufp;
+	upmode();
+	return (TRUE);
+}
+
+/*
+ * This command moves the current window down by "arg" lines. Recompute the
+ * top line in the window. The move up and move down code is almost completely
+ * the same; most of the work has to do with reframing the window, and picking
+ * a new dot. We share the code by having "move down" just be an interface to
+ * "move up". Magic. Bound to "C-X C-N".
+ */
+mvdnwind(f, n)
+    int n;
+    {
+    return (mvupwind(f, -n));
+    }
+
+/*
+ * Move the current window up by "arg" lines. Recompute the new top line of
+ * the window. Look to see if "." is still on the screen. If it is, you win.
+ * If it isn't, then move "." to center it in the new framing of the window
+ * (this command does not really move "."; it moves the frame). Bound to
+ * "C-X C-P".
+ */
+mvupwind(f, n)
+    int n;
+    {
+    register LINE *lp;
+    register int i;
+
+    lp = curwp->w_linep;
+
+    if (n < 0)
+        {
+        while (n++ && lp!=curbp->b_linep)
+            lp = lforw(lp);
+        }
+    else
+        {
+        while (n-- && lback(lp)!=curbp->b_linep)
+            lp = lback(lp);
+        }
+
+    curwp->w_linep = lp;
+    curwp->w_flag |= WFHARD;            /* Mode line is OK. */
+
+    for (i = 0; i < curwp->w_ntrows; ++i)
+        {
+        if (lp == curwp->w_dotp)
+            return (TRUE);
+        if (lp == curbp->b_linep)
+            break;
+        lp = lforw(lp);
+        }
+
+    lp = curwp->w_linep;
+    i  = curwp->w_ntrows/2;
+
+    while (i-- && lp != curbp->b_linep)
+        lp = lforw(lp);
+
+    curwp->w_dotp  = lp;
+    curwp->w_doto  = 0;
+    return (TRUE);
+    }
+
+/*
+ * This command makes the current window the only window on the screen. Bound
+ * to "C-X 1". Try to set the framing so that "." does not have to move on the
+ * display. Some care has to be taken to keep the values of dot and mark in
+ * the buffer structures right if the distruction of a window makes a buffer
+ * become undisplayed.
+ */
+onlywind(f, n)
+{
+        register WINDOW *wp;
+        register LINE   *lp;
+        register int    i;
+
+        while (wheadp != curwp) {
+                wp = wheadp;
+                wheadp = wp->w_wndp;
+                if (--wp->w_bufp->b_nwnd == 0) {
+                        wp->w_bufp->b_dotp  = wp->w_dotp;
+                        wp->w_bufp->b_doto  = wp->w_doto;
+                        wp->w_bufp->b_markp = wp->w_markp;
+                        wp->w_bufp->b_marko = wp->w_marko;
+                }
+                free((char *) wp);
+        }
+        while (curwp->w_wndp != NULL) {
+                wp = curwp->w_wndp;
+                curwp->w_wndp = wp->w_wndp;
+                if (--wp->w_bufp->b_nwnd == 0) {
+                        wp->w_bufp->b_dotp  = wp->w_dotp;
+                        wp->w_bufp->b_doto  = wp->w_doto;
+                        wp->w_bufp->b_markp = wp->w_markp;
+                        wp->w_bufp->b_marko = wp->w_marko;
+                }
+                free((char *) wp);
+        }
+        lp = curwp->w_linep;
+        i  = curwp->w_toprow;
+        while (i!=0 && lback(lp)!=curbp->b_linep) {
+                --i;
+                lp = lback(lp);
+        }
+        curwp->w_toprow = 0;
+        curwp->w_ntrows = term.t_nrow-1;
+        curwp->w_linep  = lp;
+        curwp->w_flag  |= WFMODE|WFHARD;
+        return (TRUE);
+}
+
+/*
+ * Delete the current window, placing its space in the window above,
+ * or, if it is the top window, the window below. Bound to C-X 0.
+ */
+
+delwind(f,n)
+
+int f, n;	/* arguments are ignored for this command */
+
+{
+	register WINDOW *wp;	/* window to recieve deleted space */
+	register WINDOW *lwp;	/* ptr window before curwp */
+	register int target;	/* target line to search for */
+
+	/* if there is only one window, don't delete it */
+	if (wheadp->w_wndp == NULL) {
+		mlwrite("Can not delete this window");
+		return(FALSE);
+	}
+
+	/* find window before curwp in linked list */
+	wp = wheadp;
+	lwp = NULL;
+	while (wp != NULL) {
+		if (wp == curwp)
+			break;
+		lwp = wp;
+		wp = wp->w_wndp;
+	}
+
+	/* find recieving window and give up our space */
+	wp = wheadp;
+	if (curwp->w_toprow == 0) {
+		/* find the next window down */
+		target = curwp->w_ntrows + 1;
+		while (wp != NULL) {
+			if (wp->w_toprow == target)
+				break;
+			wp = wp->w_wndp;
+		}
+		if (wp == NULL)
+			return(FALSE);
+		wp->w_toprow = 0;
+		wp->w_ntrows += target;
+	} else {
+		/* find the next window up */
+		target = curwp->w_toprow - 1;
+		while (wp != NULL) {
+			if ((wp->w_toprow + wp->w_ntrows) == target)
+				break;
+			wp = wp->w_wndp;
+		}
+		if (wp == NULL)
+			return(FALSE);
+		wp->w_ntrows += 1 + curwp->w_ntrows;
+	}
+
+	/* get rid of the current window */
+	if (--curwp->w_bufp->b_nwnd == 0) {
+		curwp->w_bufp->b_dotp = curwp->w_dotp;
+		curwp->w_bufp->b_doto = curwp->w_doto;
+		curwp->w_bufp->b_markp = curwp->w_markp;
+		curwp->w_bufp->b_marko = curwp->w_marko;
+	}
+	if (lwp == NULL)
+		wheadp = curwp->w_wndp;
+	else
+		lwp->w_wndp = curwp->w_wndp;
+	free((char *)curwp);
+	curwp = wp;
+	wp->w_flag |= WFHARD;
+	curbp = wp->w_bufp;
+	upmode();
+	return(TRUE);
+}
+
+/*
+
+Split the current window.  A window smaller than 3 lines cannot be
+split.  An argument of 1 forces the cursor into the upper window, an
+argument of two forces the cursor to the lower window.  The only other
+error that is possible is a "malloc" failure allocating the structure
+for the new window.  Bound to "C-X 2". 
+
+ */
+splitwind(f, n)
+
+int f, n;	/* default flag and numeric argument */
+
+{
+        register WINDOW *wp;
+        register LINE   *lp;
+        register int    ntru;
+        register int    ntrl;
+        register int    ntrd;
+        register WINDOW *wp1;
+        register WINDOW *wp2;
+
+        if (curwp->w_ntrows < 3) {
+                mlwrite("Cannot split a %d line window", curwp->w_ntrows);
+                return (FALSE);
+        }
+        if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
+                mlwrite("Cannot allocate WINDOW block");
+                return (FALSE);
+        }
+        ++curbp->b_nwnd;                        /* Displayed twice.     */
+        wp->w_bufp  = curbp;
+        wp->w_dotp  = curwp->w_dotp;
+        wp->w_doto  = curwp->w_doto;
+        wp->w_markp = curwp->w_markp;
+        wp->w_marko = curwp->w_marko;
+        wp->w_flag  = 0;
+        wp->w_force = 0;
+#if	COLOR
+	/* set the colors of the new window */
+	wp->w_fcolor = gfcolor;
+	wp->w_bcolor = gbcolor;
+#endif
+        ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
+        ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
+        lp = curwp->w_linep;
+        ntrd = 0;
+        while (lp != curwp->w_dotp) {
+                ++ntrd;
+                lp = lforw(lp);
+        }
+        lp = curwp->w_linep;
+        if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
+                /* Old is upper window. */
+                if (ntrd == ntru)               /* Hit mode line.       */
+                        lp = lforw(lp);
+                curwp->w_ntrows = ntru;
+                wp->w_wndp = curwp->w_wndp;
+                curwp->w_wndp = wp;
+                wp->w_toprow = curwp->w_toprow+ntru+1;
+                wp->w_ntrows = ntrl;
+        } else {                                /* Old is lower window  */
+                wp1 = NULL;
+                wp2 = wheadp;
+                while (wp2 != curwp) {
+                        wp1 = wp2;
+                        wp2 = wp2->w_wndp;
+                }
+                if (wp1 == NULL)
+                        wheadp = wp;
+                else
+                        wp1->w_wndp = wp;
+                wp->w_wndp   = curwp;
+                wp->w_toprow = curwp->w_toprow;
+                wp->w_ntrows = ntru;
+                ++ntru;                         /* Mode line.           */
+                curwp->w_toprow += ntru;
+                curwp->w_ntrows  = ntrl;
+                while (ntru--)
+                        lp = lforw(lp);
+        }
+        curwp->w_linep = lp;                    /* Adjust the top lines */
+        wp->w_linep = lp;                       /* if necessary.        */
+        curwp->w_flag |= WFMODE|WFHARD;
+        wp->w_flag |= WFMODE|WFHARD;
+        return (TRUE);
+}
+
+/*
+ * Enlarge the current window. Find the window that loses space. Make sure it
+ * is big enough. If so, hack the window descriptions, and ask redisplay to do
+ * all the hard work. You don't just set "force reframe" because dot would
+ * move. Bound to "C-X Z".
+ */
+enlargewind(f, n)
+{
+        register WINDOW *adjwp;
+        register LINE   *lp;
+        register int    i;
+
+        if (n < 0)
+                return (shrinkwind(f, -n));
+        if (wheadp->w_wndp == NULL) {
+                mlwrite("Only one window");
+                return (FALSE);
+        }
+        if ((adjwp=curwp->w_wndp) == NULL) {
+                adjwp = wheadp;
+                while (adjwp->w_wndp != curwp)
+                        adjwp = adjwp->w_wndp;
+        }
+        if (adjwp->w_ntrows <= n) {
+                mlwrite("Impossible change");
+                return (FALSE);
+        }
+        if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
+                lp = adjwp->w_linep;
+                for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
+                        lp = lforw(lp);
+                adjwp->w_linep  = lp;
+                adjwp->w_toprow += n;
+        } else {                                /* Shrink above.        */
+                lp = curwp->w_linep;
+                for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
+                        lp = lback(lp);
+                curwp->w_linep  = lp;
+                curwp->w_toprow -= n;
+        }
+        curwp->w_ntrows += n;
+        adjwp->w_ntrows -= n;
+        curwp->w_flag |= WFMODE|WFHARD;
+        adjwp->w_flag |= WFMODE|WFHARD;
+        return (TRUE);
+}
+
+/*
+ * Shrink the current window. Find the window that gains space. Hack at the
+ * window descriptions. Ask the redisplay to do all the hard work. Bound to
+ * "C-X C-Z".
+ */
+shrinkwind(f, n)
+{
+        register WINDOW *adjwp;
+        register LINE   *lp;
+        register int    i;
+
+        if (n < 0)
+                return (enlargewind(f, -n));
+        if (wheadp->w_wndp == NULL) {
+                mlwrite("Only one window");
+                return (FALSE);
+        }
+        if ((adjwp=curwp->w_wndp) == NULL) {
+                adjwp = wheadp;
+                while (adjwp->w_wndp != curwp)
+                        adjwp = adjwp->w_wndp;
+        }
+        if (curwp->w_ntrows <= n) {
+                mlwrite("Impossible change");
+                return (FALSE);
+        }
+        if (curwp->w_wndp == adjwp) {           /* Grow below.          */
+                lp = adjwp->w_linep;
+                for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
+                        lp = lback(lp);
+                adjwp->w_linep  = lp;
+                adjwp->w_toprow -= n;
+        } else {                                /* Grow above.          */
+                lp = curwp->w_linep;
+                for (i=0; i<n && lp!=curbp->b_linep; ++i)
+                        lp = lforw(lp);
+                curwp->w_linep  = lp;
+                curwp->w_toprow += n;
+        }
+        curwp->w_ntrows -= n;
+        adjwp->w_ntrows += n;
+        curwp->w_flag |= WFMODE|WFHARD;
+        adjwp->w_flag |= WFMODE|WFHARD;
+        return (TRUE);
+}
+
+/*	Resize the current window to the requested size	*/
+
+resize(f, n)
+
+int f, n;	/* default flag and numeric argument */
+
+{
+	int clines;	/* current # of lines in window */
+	
+	/* must have a non-default argument, else ignore call */
+	if (f == FALSE)
+		return(TRUE);
+
+	/* find out what to do */
+	clines = curwp->w_ntrows;
+
+	/* already the right size? */
+	if (clines == n)
+		return(TRUE);
+
+	return(enlargewind(TRUE, n - clines));
+}
+
+/*
+ * Pick a window for a pop-up. Split the screen if there is only one window.
+ * Pick the uppermost window that isn't the current window. An LRU algorithm
+ * might be better. Return a pointer, or NULL on error.
+ */
+WINDOW  *
+wpopup()
+{
+        register WINDOW *wp;
+
+        if (wheadp->w_wndp == NULL              /* Only 1 window        */
+        && splitwind(FALSE, 0) == FALSE)        /* and it won't split   */
+                return (NULL);
+        wp = wheadp;                            /* Find window to use   */
+        while (wp!=NULL && wp==curwp)
+                wp = wp->w_wndp;
+        return (wp);
+}
+
+scrnextup(f, n)		/* scroll the next window up (back) a page */
+
+{
+	nextwind(FALSE, 1);
+	backpage(f, n);
+	prevwind(FALSE, 1);
+}
+
+scrnextdw(f, n)		/* scroll the next window down (forward) a page */
+
+{
+	nextwind(FALSE, 1);
+	forwpage(f, n);
+	prevwind(FALSE, 1);
+}
+
+savewnd(f, n)		/* save ptr to current window */
+
+{
+	swindow = curwp;
+	return(TRUE);
+}
+
+restwnd(f, n)		/* restore the saved screen */
+
+{
+	register WINDOW *wp;
+
+	/* find the window */
+	wp = wheadp;
+	while (wp != NULL) {
+		if (wp == swindow) {
+			curwp = wp;
+			curbp = wp->w_bufp;
+			upmode();
+			return (TRUE);
+		}
+		wp = wp->w_wndp;
+	}
+
+	mlwrite("[No such window exists]");
+	return(FALSE);
+}

Added: clients/emacs/word.c
===================================================================
--- clients/emacs/word.c	                        (rev 0)
+++ clients/emacs/word.c	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,531 @@
+/*
+ * The routines in this file implement commands that work word or a
+ * paragraph at a time.  There are all sorts of word mode commands.  If I
+ * do any sentence mode commands, they are likely to be put in this file. 
+ */
+
+#include        "estruct.h"
+#include	"edef.h"
+
+/* Word wrap on n-spaces. Back-over whatever precedes the point on the current
+ * line and stop on the first word-break or the beginning of the line. If we
+ * reach the beginning of the line, jump back to the end of the word and start
+ * a new line.  Otherwise, break the line at the word-break, eat it, and jump
+ * back to the end of the word.
+ * Returns TRUE on success, FALSE on errors.
+ */
+wrapword(n)
+
+int n;
+
+{
+        register int cnt;	/* size of word wrapped to next line */
+	register int c;		/* charector temporary */
+
+	/* backup from the <NL> 1 char */
+        if (!backchar(0, 1))
+	        return(FALSE);
+
+	/* back up until we aren't in a word,
+	   make sure there is a break in the line */
+        cnt = 0;
+	while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
+				&& (c != '\t')) {
+                cnt++;
+                if (!backchar(0, 1))
+                        return(FALSE);
+		/* if we make it to the begining, start a new line */
+		if (curwp->w_doto == 0) {
+			gotoeol(FALSE, 0);
+			return(newline(0,1));
+		}
+        }
+
+	/* delete the forward white space */
+        if (!forwdel(0, 1))
+                return(FALSE);
+
+	/* put in a end of line */
+        if (!newline(0, 1))
+                return(FALSE);
+
+	/* and past the first word */
+	while (cnt-- > 0) {
+		if (forwchar(FALSE, 1) == FALSE)
+			return(FALSE);
+	}
+        return(TRUE);
+}
+
+/*
+ * Move the cursor backward by "n" words. All of the details of motion are
+ * performed by the "backchar" and "forwchar" routines. Error if you try to
+ * move beyond the buffers.
+ */
+backword(f, n)
+{
+        if (n < 0)
+                return (forwword(f, -n));
+        if (backchar(FALSE, 1) == FALSE)
+                return (FALSE);
+        while (n--) {
+                while (inword() == FALSE) {
+                        if (backchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+                while (inword() != FALSE) {
+                        if (backchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+        }
+        return (forwchar(FALSE, 1));
+}
+
+/*
+ * Move the cursor forward by the specified number of words. All of the motion
+ * is done by "forwchar". Error if you try and move beyond the buffer's end.
+ */
+forwword(f, n)
+{
+        if (n < 0)
+                return (backword(f, -n));
+        while (n--) {
+#if	NFWORD
+                while (inword() != FALSE) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+#endif
+                while (inword() == FALSE) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+#if	NFWORD == 0
+                while (inword() != FALSE) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+#endif
+        }
+	return(TRUE);
+}
+
+/*
+ * Move the cursor forward by the specified number of words. As you move,
+ * convert any characters to upper case. Error if you try and move beyond the
+ * end of the buffer. Bound to "M-U".
+ */
+upperword(f, n)
+{
+        register int    c;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (FALSE);
+        while (n--) {
+                while (inword() == FALSE) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+                while (inword() != FALSE) {
+                        c = lgetc(curwp->w_dotp, curwp->w_doto);
+                        if (c>='a' && c<='z') {
+                                c -= 'a'-'A';
+                                lputc(curwp->w_dotp, curwp->w_doto, c);
+                                lchange(WFHARD);
+                        }
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+        }
+        return (TRUE);
+}
+
+/*
+ * Move the cursor forward by the specified number of words. As you move
+ * convert characters to lower case. Error if you try and move over the end of
+ * the buffer. Bound to "M-L".
+ */
+lowerword(f, n)
+{
+        register int    c;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (FALSE);
+        while (n--) {
+                while (inword() == FALSE) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+                while (inword() != FALSE) {
+                        c = lgetc(curwp->w_dotp, curwp->w_doto);
+                        if (c>='A' && c<='Z') {
+                                c += 'a'-'A';
+                                lputc(curwp->w_dotp, curwp->w_doto, c);
+                                lchange(WFHARD);
+                        }
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+        }
+        return (TRUE);
+}
+
+/*
+ * Move the cursor forward by the specified number of words. As you move
+ * convert the first character of the word to upper case, and subsequent
+ * characters to lower case. Error if you try and move past the end of the
+ * buffer. Bound to "M-C".
+ */
+capword(f, n)
+{
+        register int    c;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (FALSE);
+        while (n--) {
+                while (inword() == FALSE) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                }
+                if (inword() != FALSE) {
+                        c = lgetc(curwp->w_dotp, curwp->w_doto);
+                        if (c>='a' && c<='z') {
+                                c -= 'a'-'A';
+                                lputc(curwp->w_dotp, curwp->w_doto, c);
+                                lchange(WFHARD);
+                        }
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                        while (inword() != FALSE) {
+                                c = lgetc(curwp->w_dotp, curwp->w_doto);
+                                if (c>='A' && c<='Z') {
+                                        c += 'a'-'A';
+                                        lputc(curwp->w_dotp, curwp->w_doto, c);
+                                        lchange(WFHARD);
+                                }
+                                if (forwchar(FALSE, 1) == FALSE)
+                                        return (FALSE);
+                        }
+                }
+        }
+        return (TRUE);
+}
+
+/*
+ * Kill forward by "n" words. Remember the location of dot. Move forward by
+ * the right number of words. Put dot back where it was and issue the kill
+ * command for the right number of characters. Bound to "M-D".
+ */
+delfword(f, n)
+{
+        register LINE   *dotp;
+        register int    doto;
+        long size;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (FALSE);
+        if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
+                kdelete();              /* last wasn't a kill.  */
+        thisflag |= CFKILL;
+        dotp = curwp->w_dotp;
+        doto = curwp->w_doto;
+        size = 0;
+        while (n--) {
+#if	NFWORD
+		if (curwp->w_doto == llength(curwp->w_dotp)) {
+			if (forwchar(FALSE,1) == FALSE)
+				return(FALSE);
+			++size;
+		}
+
+		while (inword() != FALSE) {
+			if (forwchar(FALSE,1) == FALSE)
+				return(FALSE);
+			++size;
+		}
+
+                while ((inword() == FALSE) &&
+				(curwp->w_doto != llength(curwp->w_dotp))) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                        ++size;
+                }
+#else
+                while (inword() == FALSE) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                        ++size;
+                }
+
+                while (inword() != FALSE) {
+                        if (forwchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                        ++size;
+                }
+#endif
+        }
+        curwp->w_dotp = dotp;
+        curwp->w_doto = doto;
+        return (ldelete(size, TRUE));
+}
+
+/*
+ * Kill backwards by "n" words. Move backwards by the desired number of words,
+ * counting the characters. When dot is finally moved to its resting place,
+ * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
+ */
+delbword(f, n)
+{
+        long size;
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+        if (n < 0)
+                return (FALSE);
+        if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
+                kdelete();              /* last wasn't a kill.  */
+        thisflag |= CFKILL;
+        if (backchar(FALSE, 1) == FALSE)
+                return (FALSE);
+        size = 0;
+        while (n--) {
+                while (inword() == FALSE) {
+                        if (backchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                        ++size;
+                }
+                while (inword() != FALSE) {
+                        if (backchar(FALSE, 1) == FALSE)
+                                return (FALSE);
+                        ++size;
+                }
+        }
+        if (forwchar(FALSE, 1) == FALSE)
+                return (FALSE);
+        return (ldelete(size, TRUE));
+}
+
+/*
+ * Return TRUE if the character at dot is a character that is considered to be
+ * part of a word. The word character list is hard coded. Should be setable.
+ */
+inword()
+{
+        register int    c;
+
+        if (curwp->w_doto == llength(curwp->w_dotp))
+                return (FALSE);
+        c = lgetc(curwp->w_dotp, curwp->w_doto);
+        if (c>='a' && c<='z')
+                return (TRUE);
+        if (c>='A' && c<='Z')
+                return (TRUE);
+        if (c>='0' && c<='9')
+                return (TRUE);
+        if (c=='$' || c=='_')                   /* For identifiers      */
+                return (TRUE);
+        return (FALSE);
+}
+
+#if	WORDPRO
+fillpara(f, n)	/* Fill the current paragraph according to the current
+		   fill column						*/
+
+int f, n;	/* deFault flag and Numeric argument */
+
+{
+	register int c;			/* current char durring scan	*/
+	register int wordlen;		/* length of current word	*/
+	register int clength;		/* position on line during fill	*/
+	register int i;			/* index during word copy	*/
+	register int newlength;		/* tentative new line length	*/
+	register int eopflag;		/* Are we at the End-Of-Paragraph? */
+	register int firstflag;		/* first word? (needs no space)	*/
+	register LINE *eopline;		/* pointer to line just past EOP */
+	register int dotflag;		/* was the last char a period?	*/
+	char wbuf[NSTRING];		/* buffer for current word	*/
+
+	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
+		return(rdonly());	/* we are in read only mode	*/
+	if (fillcol == 0) {	/* no fill column set */
+		mlwrite("No fill column set");
+		return(FALSE);
+	}
+
+	/* record the pointer to the line just past the EOP */
+	gotoeop(FALSE, 1);
+	eopline = lforw(curwp->w_dotp);
+
+	/* and back top the begining of the paragraph */
+	gotobop(FALSE, 1);
+
+	/* initialize various info */
+	clength = curwp->w_doto;
+	if (clength && curwp->w_dotp->l_text[0] == TAB)
+		clength = 8;
+	wordlen = 0;
+	dotflag = FALSE;
+
+	/* scan through lines, filling words */
+	firstflag = TRUE;
+	eopflag = FALSE;
+	while (!eopflag) {
+		/* get the next character in the paragraph */
+		if (curwp->w_doto == llength(curwp->w_dotp)) {
+			c = ' ';
+			if (lforw(curwp->w_dotp) == eopline)
+				eopflag = TRUE;
+		} else
+			c = lgetc(curwp->w_dotp, curwp->w_doto);
+
+		/* and then delete it */
+		ldelete(1L, FALSE);
+
+		/* if not a separator, just add it in */
+		if (c != ' ' && c != '	') {
+			dotflag = (c == '.');		/* was it a dot */
+			if (wordlen < NSTRING - 1)
+				wbuf[wordlen++] = c;
+		} else if (wordlen) {
+			/* at a word break with a word waiting */
+			/* calculate tantitive new length with word added */
+			newlength = clength + 1 + wordlen;
+			if (newlength <= fillcol) {
+				/* add word to current line */
+				if (!firstflag) {
+					linsert(1, ' '); /* the space */
+					++clength;
+				}
+				firstflag = FALSE;
+			} else {
+				/* start a new line */
+				lnewline();
+				clength = 0;
+			}
+
+			/* and add the word in in either case */
+			for (i=0; i<wordlen; i++) {
+				linsert(1, wbuf[i]);
+				++clength;
+			}
+			if (dotflag) {
+				linsert(1, ' ');
+				++clength;
+			}
+			wordlen = 0;
+		}
+	}
+	/* and add a last newline for the end of our new paragraph */
+	lnewline();
+	return(TRUE);
+}
+
+killpara(f, n)	/* delete n paragraphs starting with the current one */
+
+int f;	/* default flag */
+int n;	/* # of paras to delete */
+
+{
+	register int status;	/* returned status of functions */
+
+	while (n--) {		/* for each paragraph to delete */
+
+		/* mark out the end and begining of the para to delete */
+		gotoeop(FALSE, 1);
+
+		/* set the mark here */
+	        curwp->w_markp = curwp->w_dotp;
+	        curwp->w_marko = curwp->w_doto;
+
+		/* go to the begining of the paragraph */
+		gotobop(FALSE, 1);
+		curwp->w_doto = 0;	/* force us to the begining of line */
+	
+		/* and delete it */
+		if ((status = killregion(FALSE, 1)) != TRUE)
+			return(status);
+
+		/* and clean up the 2 extra lines */
+		ldelete(2L, TRUE);
+	}
+	return(TRUE);
+}
+
+
+/*	wordcount:	count the # of words in the marked region,
+			along with average word sizes, # of chars, etc,
+			and report on them.			*/
+
+wordcount(f, n)
+
+int f, n;	/* ignored numeric arguments */
+
+{
+	register LINE *lp;	/* current line to scan */
+	register int offset;	/* current char to scan */
+	long size;		/* size of region left to count */
+	register int ch;	/* current character to scan */
+	register int wordflag;	/* are we in a word now? */
+	register int lastflag;	/* were we just in a word? */
+	long nwords;		/* total # of words */
+	long nchars;		/* total number of chars */
+	int nlines;		/* total number of lines in region */
+	int avgch;		/* average number of chars/word */
+	int status;		/* status return code */
+	REGION region;		/* region to look at */
+
+	/* make sure we have a region to count */
+        if ((status = getregion(&region)) != TRUE)
+                return(status);
+	lp = region.r_linep;
+	offset = region.r_offset;
+	size = region.r_size;
+
+	/* count up things */
+	lastflag = FALSE;
+	nchars = 0L;
+	nwords = 0L;
+	nlines = 0;
+	while (size--) {
+
+		/* get the current character */
+		if (offset == llength(lp)) {	/* end of line */
+			ch = '\n';
+			lp = lforw(lp);
+			offset = 0;
+			++nlines;
+		} else {
+			ch = lgetc(lp, offset);
+			++offset;
+		}
+
+		/* and tabulate it */
+		wordflag = ((ch >= 'a' && ch <= 'z') ||
+			    (ch >= 'A' && ch <= 'Z') ||
+			    (ch >= '0' && ch <= '9') ||
+			    (ch == '$' || ch == '_'));
+		if (wordflag == TRUE && lastflag == FALSE)
+			++nwords;
+		lastflag = wordflag;
+		++nchars;
+	}
+
+	/* and report on the info */
+	if (nwords > 0L)
+		avgch = (int)((100L * nchars) / nwords);
+	else
+		avgch = 0;
+
+	mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
+		nwords, nchars, nlines + 1, avgch);
+	return(TRUE);
+}
+#endif

Added: clients/emacs/x86/Makefile
===================================================================
--- clients/emacs/x86/Makefile	                        (rev 0)
+++ clients/emacs/x86/Makefile	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,51 @@
+# Makefile for MicroEMACS 3.7 for use with Open Firmware.
+# 
+# To make emacs, type:	make emacs
+#	      or just: make	
+#
+
+BP=../../..
+SRCDIR=..
+HLIBDIR=$(BP)/clients/lib
+LIBDIR=$(HLIBDIR)/x86
+
+CFLAGS=   -I. -I$(SRCDIR) -I$(HLIBDIR)
+
+CC=		gcc
+LFLAGS= 	-T emacs.lds -N -e _start
+LD=		ld
+
+HFILES=		../estruct.h edef.h efunc.h epath.h ebind.h
+
+OFILES=     	ansi.o  basic.o  bind.o  buffer.o  display.o  \
+		exec.o  file.o  fileio.o  \
+		input.o  isearch.o  line.o  lock.o  main.o \
+		random.o  region.o   search.o  spawn.o  termio.o  \
+		window.o  word.o
+
+LIBS=		$(LIBDIR)/libobp.a
+
+# emacs.elf:	emacs.obp
+#	$(BP)/tools/xcftobin <emacs.obp >emacs.bin
+#	$(BP)/tools/bintoelf -e$(ORIGIN) <emacs.bin >emacs.elf
+
+emacs.obp:	$(LIBDIR)/start.o $(OFILES) $(LIBS) Makefile
+	$(LD) $(LFLAGS) -o $@ $(LIBDIR)/start.o $(OFILES) $(LIBS)
+	size $@
+	nm -n $@ >emacs.nm
+	strip $@
+
+$(LIBDIR)/start.o:	$(LIBDIR)/start.s
+	(cd $(LIBDIR); make start.o)
+
+$(LIBDIR)/libobp.a:	$(HLIBDIR)/lib.c
+	(cd $(LIBDIR); make libobp.a)
+
+%.o:$(SRCDIR)/%.c
+	$(CC) $(CFLAGS) -c $<
+
+main.o: $(SRCDIR)/ebind.h
+
+clean:
+	-rm -f *.o *.a
+

Added: clients/emacs/x86/config.h
===================================================================
--- clients/emacs/x86/config.h	                        (rev 0)
+++ clients/emacs/x86/config.h	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,55 @@
+/*	Machine/OS definitions			*/
+
+#define OFW     1                       /* Open Boot Prom               */
+#define AMIGA   0                       /* AmigaDOS			*/
+#define ST520   0                       /* ST520, TOS                   */
+#define MSDOS   0                       /* MS-DOS                       */
+#define V7      0                       /* V7 UN*X or Coherent or BSD4.2*/
+#define	BSD	0			/* UNIX BSD 4.2	and ULTRIX	*/
+#define	USG	0			/* UNIX system V		*/
+#define VMS     0                       /* VAX/VMS                      */
+#define CPM     0                       /* CP/M-86                      */
+
+/*	Compiler definitions			*/
+#define	GCC	1	/* Gnu C Compiler */
+#define MWC86   0	/* marc williams compiler */
+#define	LATTICE	0	/* either lattice compiler */
+#define	LAT2	0	/* Lattice 2.15 */
+#define	LAT3	0	/* Lattice 3.0 */
+#define	AZTEC	0	/* Aztec C 3.20e */
+#define	MSC	0	/* MicroSoft C compile version 3 */
+
+/*	Profiling options	*/
+#define	APROF	0	/* turn Aztec C profiling on? */
+#define	NBUCK	100	/* number of buckets to profile */
+
+/*   Special keyboard definitions            */
+ 
+#define WANGPC	0			/* WangPC - mostly escape sequences     */
+ 
+/*	Terminal Output definitions		*/
+
+#define ANSI    1			/* ansi escape sequences	*/
+#define	HP150	0			/* HP150 screen driver		*/
+#define	VMSVT	0			/* various VMS terminal entries	*/
+#define VT52    0                       /* VT52 terminal (Zenith).      */
+#define VT100   0                       /* Handle VT100 style keypad.   */
+#define LK201   0                       /* Handle LK201 style keypad.   */
+#define RAINBOW 0                       /* Use Rainbow fast video.      */
+#define TERMCAP 0                       /* Use TERMCAP                  */
+#define	IBMPC	0			/* IBM-PC specific driver	*/
+#define	DG10	0			/* Data General system/10	*/
+
+/*	Configuration options	*/
+
+#define CVMVAS  1	/* arguments to page forward/back in pages	*/
+#define	NFWORD	0	/* forward word jumps to begining of word	*/
+#define	CLRMSG	0	/* space clears the message line with no insert	*/
+#define	TYPEAH	1	/* type ahead causes update to be skipped	*/
+#define	FILOCK	0	/* file locking under unix BSD 4.2		*/
+#define	REVSTA	0	/* Status line appears in reverse video		*/
+#define	COLOR	1	/* color commands and windows			*/
+#define	ACMODE	1	/* auto CMODE on .C and .H files		*/
+#define	CFENCE	1	/* fench matching in CMODE			*/
+#define	ISRCH	1	/* Incremental searches like ITS EMACS		*/
+#define	WORDPRO	1	/* Advanced word processing features		*/

Added: clients/emacs/x86/emacs.lds
===================================================================
--- clients/emacs/x86/emacs.lds	                        (rev 0)
+++ clients/emacs/x86/emacs.lds	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,11 @@
+OUTPUT_FORMAT("elf32-i386");
+OUTPUT_ARCH(i386);
+
+ENTRY(_start); 
+SECTIONS {
+	. = 0x100000;
+	_start = . ;
+	.data : {
+		*(.data)
+	}
+}

Added: clients/emacs/x86/emacs.rc
===================================================================
--- clients/emacs/x86/emacs.rc	                        (rev 0)
+++ clients/emacs/x86/emacs.rc	2008-08-28 22:25:57 UTC (rev 897)
@@ -0,0 +1,94 @@
+;	EMACS.RC:	Startup file for MicroEMACS 3.4
+;
+;			This file is executed everytime the
+;			editor is entered
+
+;	***** Rebind the Function key group
+
+bind-to-key execute-macro-11		FNP
+bind-to-key execute-named-command	FNQ
+bind-to-key hunt-forward		FNW
+bind-to-key hunt-backward		FNx
+bind-to-key next-window			FNt
+bind-to-key find-file                   FNu
+bind-to-key save-file			FNq
+bind-to-key exit-emacs			FNr
+
+;	set screen colors
+add-global-mode "blue"
+
+;	Enter Help
+11 store-macro
+	help
+	8 resize-window
+	bind-to-key execute-macro-12 FN? ; page up
+	bind-to-key execute-macro-13 FN/ ; page down
+	bind-to-key execute-macro-14 FNP ; fixed
+	add-mode "red"
+	begining-of-file
+	2 forward-character
+	clear-message-line
+[end]
+
+;	bring up the function key window
+1 store-macro
+	2 split-current-window
+	select-buffer "Function Keys"
+	add-mode "red"
+	begining-of-file
+	2 resize-window
+	insert-string "      F1 Help on/off       F5 Open File       F6 Save File       F7 Exit"
+	newline
+	insert-string "            Move with arrow keys, PageUp, PageDown, Home, and End"
+	begining-of-file
+	unmark-buffer
+;	bind-to-key execute-macro-15 FNT
+	next-window
+[end]
+
+; reselect function key window
+15 store-macro
+	2 split-current-window
+	select-buffer "Function Keys"
+	begining-of-file
+	2 resize-window
+	add-mode "red"
+	next-window
+[end]
+
+;	consult file
+3 store-macro
+	2 split-current-window
+	previous-window
+	view-file "@File to Consult: "
+	8 resize-window
+	add-mode "green"
+	add-mode "Black"
+	next-window
+[end]
+
+;	Exit Help
+14 store-macro
+	bind-to-key previous-page FN?
+	bind-to-key next-page FN/
+	bind-to-key execute-macro-11 FNP ; fixed
+	delete-window
+	clear-message-line
+[end]
+
+;	last help page
+12 store-macro
+	begining-of-line
+	search-reverse "=>"
+	1 redraw-display
+[end]
+
+;	next help page
+13 store-macro
+	begining-of-line
+	2 forward-character
+	search-forward "=>"
+	1 redraw-display
+[end]
+
+execute-macro-1




More information about the openfirmware mailing list