[net.sources] Emacs mods: #5

chris@umcp-cs.UUCP (09/01/83)

: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting buffer.c.diff'
sed 's/^X//' <<'//go.sysin dd *' >buffer.c.diff
*** cmuemacs/buffer.c	Tue Jul 20 19:39:09 1982
--- emacs/buffer.c	Sat Aug 20 22:52:13 1983
***************
*** 4,9
  
  /* Modified 7-Dec-80 DJH	Maintain vector of buffer names for ^x^o */
  
  #include "buffer.h"
  #include "window.h"
  #include "syntax.h"

--- 4,10 -----
  
  /* Modified 7-Dec-80 DJH	Maintain vector of buffer names for ^x^o */
  
+ #include "config.h"
  #include "buffer.h"
  #include "window.h"
  #include "syntax.h"
***************
*** 21,26
  static int DefaultCommentColumn;
  int DefaultTabSize;		/* Also used as an extern in mlisp.c */
  
  /* insert character c at positon n in the current buffer */
  InsertAt (n, c)
  register    n; {

--- 22,29 -----
  static int DefaultCommentColumn;
  int DefaultTabSize;		/* Also used as an extern in mlisp.c */
  
+ extern char *malloc (), *realloc ();
+ 
  /* insert character c at positon n in the current buffer */
  InsertAt (n, c)
  register    n; {
***************
*** 45,51
      if (bf_gap < n)
  	if(GapRoom (n)) return;
      RecordInsert (dot, n);
!     while (*s && --n >= 0) {
  	if (bf_gap <= 0) {
  	    error ("InsCStr gap overrun!");
  	    break;

--- 48,54 -----
      if (bf_gap < n)
  	if(GapRoom (n)) return;
      RecordInsert (dot, n);
!     while (/* *s && */ --n >= 0) {
  	if (bf_gap <= 0) {
  	    error ("InsCStr gap overrun!");
  	    break;
***************
*** 259,264
      b -> b_mode.md_CommentColumn = DefaultCommentColumn;
      b -> b_mode.md_TabSize = DefaultTabSize;
      b -> b_mode.md_NeedsCheckpointing = 1;
      buffers = b;
  /* DJH -- Store buffer name in BufNames; realloc if necessary */
      BufNames[NBuffers++] = b -> b_name;

--- 262,268 -----
      b -> b_mode.md_CommentColumn = DefaultCommentColumn;
      b -> b_mode.md_TabSize = DefaultTabSize;
      b -> b_mode.md_NeedsCheckpointing = 1;
+     b -> b_mode.md_ReadOnly = 0;
      buffers = b;
  /* DJH -- Store buffer name in BufNames; realloc if necessary */
      BufNames[NBuffers++] = b -> b_name;
***************
*** 278,283
      register struct buffer *p;
      if (b == 0 || b -> b_kind == DeletedBuffer)
  	return;
      {
  	register struct process_blk *proc;
  	for (proc = process_list; proc; proc = proc -> next_process)

--- 282,288 -----
      register struct buffer *p;
      if (b == 0 || b -> b_kind == DeletedBuffer)
  	return;
+ #ifdef subprocesses
      {
  	register struct process_blk *proc;
  	for (proc = process_list; proc; proc = proc -> next_process)
***************
*** 281,288
      {
  	register struct process_blk *proc;
  	for (proc = process_list; proc; proc = proc -> next_process)
! 	    if (b == proc -> p_chan.ch_buffer) {
! 		error ("There is a process attached to buffer %s, so I can't delete it",
  			b -> b_name);
  		return;
  	    }

--- 286,296 -----
      {
  	register struct process_blk *proc;
  	for (proc = process_list; proc; proc = proc -> next_process)
! 	    if (b == proc -> p_chan.ch_buffer)
! 		if (proc -> p_flag & (EXITED | SIGNALED))
! 		    flush_process (proc);
! 		else {
! 		    error ("There is a process attached to buffer %s, so I can't delete it",
  			b -> b_name);
  		    return;
  		}
***************
*** 284,291
  	    if (b == proc -> p_chan.ch_buffer) {
  		error ("There is a process attached to buffer %s, so I can't delete it",
  			b -> b_name);
! 		return;
! 	    }
      }
      b -> b_kind = DeletedBuffer;
      {

--- 292,299 -----
  		else {
  		    error ("There is a process attached to buffer %s, so I can't delete it",
  			b -> b_name);
! 		    return;
! 		}
      }
  #endif
      DeleteBuffersCheckpointFile (b);
***************
*** 287,292
  		return;
  	    }
      }
      b -> b_kind = DeletedBuffer;
      {
  	register int    i;

--- 295,302 -----
  		    return;
  		}
      }
+ #endif
+     DeleteBuffersCheckpointFile (b);
      b -> b_kind = DeletedBuffer;
      {
  	register int    i;
***************
*** 317,323
  		break;
  	if (p == 0)
  	    p = buffers;
! 	if (p == 0)
  	    p = NewBf ("main");
  	TieWin (wn_cur, p);
      }

--- 327,333 -----
  		break;
  	if (p == 0)
  	    p = buffers;
! 	if (p == 0 || p == minibuf)
  	    p = NewBf ("main");
  	TieWin (wn_cur, p);
      }
***************
*** 328,334
  /* find a buffer with the given name -- returns nil if no such
     buffer exists */
  struct buffer *FindBf(name)
! char   *name; {
      register struct buffer *b = buffers;
      while (b && strcmp (name, b -> b_name) != 0)
  	b = b -> b_next;

--- 338,344 -----
  /* find a buffer with the given name -- returns nil if no such
     buffer exists */
  struct buffer *FindBf(name)
! register char *name; {
      register struct buffer *b = buffers;
      while (b && strcmp (name, b -> b_name) != 0)
  	b = b -> b_next;
***************
*** 390,395
      SetBfp (old);
  }
  
  /* initialize the buffer routines */
  Initbf () {			/* (DJH) allocate buffer list */
      DefaultTabSize = 8;

--- 400,429 -----
      SetBfp (old);
  }
  
+ /* Rename a buffer */
+ RenameBf (b, new)
+ register struct buffer *b;
+ register char *new;
+ {
+     register n = 0;
+     register char *old = b -> b_name;
+     if (!new || !*new) {
+ 	error ("Invalid buffer name");
+ 	return 1;
+     }
+     if (FindBf (new)) {
+ 	error ("Buffer name \"%s\" is in use", new);
+ 	return 1;
+     }
+     while (n < NBuffers && strcmp (BufNames[n], old))
+ 	++n;
+     if (n >= NBuffers)		/* "Can't happen" */
+ 	return -1;
+     free (old);
+     b -> b_name = BufNames[n] = savestr (new);
+     return 0;
+ }
+ 
  /* initialize the buffer routines */
  Initbf () {			/* (DJH) allocate buffer list */
  #ifdef DumpableEmacs
***************
*** 392,433
  
  /* initialize the buffer routines */
  Initbf () {			/* (DJH) allocate buffer list */
!     DefaultTabSize = 8;
!     BufNames = (char **) malloc( (BufNameFree = 10) * sizeof(char *) );
!     NBuffers = 0;
!     DefStrVar ("default-mode-line-format", DefaultModeFormat);
!     DefStrVar ("mode-line-format", bf_mode.md_ModeFormat);
!     SetSysDefault;
!     strcpy (DefaultModeFormat, " %[Buffer: %b%*  File: %f  %M (%m)  %p%]");
!     SetBfn ("  Minibuf");
!     minibuf = bf_cur;
!     SetBfn ("main");
!     minibuf -> b_mode.md_NeedsCheckpointing = 0;
!     bf_cur -> b_kind = FileBuffer;
!     DefIntVar ("default-case-fold-search", &DefaultFoldCase);
!     DefIntVar ("case-fold-search", &bf_mode.md_FoldCase);
!     SetSysDefault;
!     DefStrVar ("mode-string", bf_mode.md_ModeString);
!     DefIntVar ("buffer-is-modified", &bf_modified);
!     DefaultFoldCase = 0;
!     DefIntVar ("default-right-margin", &DefaultRightMargin);
!     DefIntVar ("right-margin", &bf_mode.md_RightMargin);
!     SetSysDefault;
!     DefaultRightMargin = 10000;
!     DefIntVar ("default-left-margin", &DefaultLeftMargin);
!     DefIntVar ("left-margin", &bf_mode.md_LeftMargin);
!     SetSysDefault;
!     DefaultLeftMargin = 1;
!     DefIntVar ("default-comment-column", &DefaultCommentColumn);
!     DefIntVar ("comment-column", &bf_mode.md_CommentColumn);
!     SetSysDefault;
!     DefaultCommentColumn = 33;
!     DefIntVar ("default-tab-size", &DefaultTabSize);
!     DefIntVar ("tab-size", &bf_mode.md_TabSize);
!     SetSysDefault;
!     DefIntVar ("needs-checkpointing", &bf_mode.md_NeedsCheckpointing);
!     DefIntVar ("abbrev-mode", &bf_mode.md_AbbrevOn);
!     DefStrVar ("prefix-string", bf_mode.md_PrefixString);
  }
  
  /* save a string in managed memory */

--- 426,473 -----
  
  /* initialize the buffer routines */
  Initbf () {			/* (DJH) allocate buffer list */
! #ifdef DumpableEmacs
!     if (!Once)
! #endif
!     {
! 	DefaultTabSize = 8;
! 	BufNames = (char **) malloc( (BufNameFree = 10) * sizeof(char *) );
! 	NBuffers = 0;
! 	DefStrVar ("default-mode-line-format", DefaultModeFormat);
! 	DefStrVar ("mode-line-format", bf_mode.md_ModeFormat);
! 	SetSysDefault;
! 	strcpy (DefaultModeFormat, " %[Buffer: %b%*  File: %f  %M (%m)  %p%]");
! 	SetBfn ("  Minibuf");
! 	minibuf = bf_cur;
! 	SetBfn ("main");
! 	minibuf -> b_mode.md_NeedsCheckpointing = 0;
! 	bf_cur -> b_kind = FileBuffer;
! 	DefIntVar ("default-case-fold-search", &DefaultFoldCase);
! 	DefIntVar ("case-fold-search", &bf_mode.md_FoldCase);
! 	SetSysDefault;
! 	DefStrVar ("mode-string", bf_mode.md_ModeString);
! 	DefIntVar ("buffer-is-modified", &bf_modified);
! 	DefaultFoldCase = 0;
! 	DefIntVar ("default-right-margin", &DefaultRightMargin);
! 	DefIntVar ("right-margin", &bf_mode.md_RightMargin);
! 	SetSysDefault;
! 	DefaultRightMargin = 10000;
! 	DefIntVar ("default-left-margin", &DefaultLeftMargin);
! 	DefIntVar ("left-margin", &bf_mode.md_LeftMargin);
! 	SetSysDefault;
! 	DefaultLeftMargin = 1;
! 	DefIntVar ("default-comment-column", &DefaultCommentColumn);
! 	DefIntVar ("comment-column", &bf_mode.md_CommentColumn);
! 	SetSysDefault;
! 	DefaultCommentColumn = 33;
! 	DefIntVar ("default-tab-size", &DefaultTabSize);
! 	DefIntVar ("tab-size", &bf_mode.md_TabSize);
! 	SetSysDefault;
! 	DefIntVar ("needs-checkpointing", &bf_mode.md_NeedsCheckpointing);
! 	DefIntVar ("abbrev-mode", &bf_mode.md_AbbrevOn);
! 	DefStrVar ("prefix-string", bf_mode.md_PrefixString);
! 	DefIntVar ("read-only", &bf_mode.md_ReadOnly);
!     }
  }
  
  /* save a string in managed memory */
***************
*** 528,531
      if (m -> m_pos <= bf_s1 + bf_gap)
  	return bf_s1 + 1;
      return m -> m_pos - bf_gap;
  }

--- 568,589 -----
      if (m -> m_pos <= bf_s1 + bf_gap)
  	return bf_s1 + 1;
      return m -> m_pos - bf_gap;
+ }
+ 
+ /* return the positional value of a marker in a buffer without changing
+    buffers.  Return 0 iff marker not set */
+ 
+ MarkerValue (m)
+ register struct marker *m; {
+     register struct buffer *old = bf_cur;
+     register rv;
+     if (m == 0 || m -> m_buf == 0)
+ 	return 0;
+     if (bf_cur != m -> m_buf)
+ 	SetBfp (m -> m_buf);
+     rv = m -> m_pos <= bf_s1		? m -> m_pos :
+ 	 m -> m_pos <= bf_s1 + bf_gap	? bf_s1 + 1  :
+ 					  m -> m_pos - bf_gap;
+     SetBfp (old);
+     return rv;
  }
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 buffer.c.diff
	/bin/echo -n '	'; /bin/ls -ld buffer.c.diff
fi
/bin/echo 'Extracting buffer.h.diff'
sed 's/^X//' <<'//go.sysin dd *' >buffer.h.diff
*** cmuemacs/buffer.h	Tue Jul 20 19:39:10 1982
--- emacs/buffer.h	Sun Oct 17 01:04:36 1982
***************
*** 42,47
  				   tail of the buffer by restrict-region */
      struct keymap *md_keys;	/* Keys that are bound local to this buffer
  				   (stuff like $J) */
  };
  
  /* structure that defines a buffer */

--- 42,48 -----
  				   tail of the buffer by restrict-region */
      struct keymap *md_keys;	/* Keys that are bound local to this buffer
  				   (stuff like $J) */
+     int  md_ReadOnly;		/* True iff file is considered read-only */
  };
  
  /* structure that defines a buffer */
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 buffer.h.diff
	/bin/echo -n '	'; /bin/ls -ld buffer.h.diff
fi
/bin/echo 'Extracting errlog.c'
sed 's/^X//' <<'//go.sysin dd *' >errlog.c
X/* Routines for parsing an error log */

X/*		Copyright (c) 1981,1980 James Gosling		*/

#include "buffer.h"
#include "window.h"
#include "keyboard.h"
#include "search.h"

struct err {			/* a single error message */
    struct marker  *e_mess;	/* points to the error message */
    struct marker  *e_text;	/* points to the position in the text
				   where the compiler thinks the error
				   is */
    struct err *e_next;		/* the next error in the chain */
};

static struct err
                   *errors,	/* the list of all error messages */
                   *ThisErr;	/* the current error */

X/* delete the error list */
DelErl () {
    register struct err *e;
    while (errors) {
	e = errors;
	DestMark (e -> e_mess);
	DestMark (e -> e_text);
	errors = e -> e_next;
    }
}

X/* Parse error messages from the current buffer from character pos to limit */
ParseErb (pos, limit)
register pos; {
    register struct buffer *erb = bf_cur;
    char old_fn[200];
    int old_ln = -1;
    struct search_globals lglobals;

    DelErl ();
    lglobals = search_globals;		/* Save the old search string */
    for (;;) {
	register    ln = 0;
	char    fn[200];
	register    fnend;
	register char  *p,
	                c;
	int     fnl = 0,
	        quoted = 0,
	        bol;
	SetBfp (erb);
	pos = search (", line ", 1, pos, 0);
	if (pos <= 0 || pos >= limit) {
	    search_globals = lglobals;	/* Restore old search string */
	    ThisErr = 0;
	    return errors != 0;
	}
	fnend = pos - 8;
	while (pos <= NumCharacters && (c = CharAt (pos)) >= '0' && c <= '9'){
	    pos++;
	    ln = ln * 10 + c - '0';
	}
	if (ln == 0)
	    continue;
	if (CharAt (fnend) == '"')
	    quoted++, fnend--;
	while (fnend >= 1) {
	    c = CharAt (fnend);
	    if (quoted) {
		if (c == '"') {
		    fnend++;
		    break;
		}
	    }
	    else
		if (c <= ' ') {
		    fnend++;
		    break;
		}
	    fnl++;
	    if(fnend<=1) break;
	    fnend--;
	}
	if (fnl == 0)
	    continue;
	for (p = fn; --fnl >= 0; fnend++)
	    *p++ = CharAt (fnend);
	*p++ = 0;
	if (old_ln == ln && strcmp (old_fn, fn)==0)
	    continue;
	old_ln = ln;
	strcpy (old_fn, fn);
	bol = ScanBf ('\n', fnend, -1);
	if (!VisitFile (fn, 0, 0))
	    continue;
	if (errors) {
	    ThisErr -> e_next
		= (struct err  *) malloc (sizeof (struct err));
	    ThisErr = ThisErr -> e_next;
	}
	else
	    errors = ThisErr
		= (struct err  *) malloc (sizeof (struct err));
	ThisErr -> e_next = 0;
	ThisErr -> e_mess = NewMark ();
	ThisErr -> e_text = NewMark ();
	SetMark (ThisErr -> e_mess, erb, bol);
	SetMark (ThisErr -> e_text, bf_cur, ScanBf ('\n', 1, ln - 1));
    }
}

X/* move to the next error message in the log */
NextErr () {
    register    n;
    if (!errors) {
	error ("No errors!");
	return 0;
    }
    if (ThisErr == 0)
	ThisErr = errors;
    else {
	ThisErr = ThisErr -> e_next;
	if (ThisErr == 0) {
	    error ("No more errors...");
	    return 0;
	}
    }
    n = ToMark (ThisErr -> e_mess);
    WindowOn (bf_cur);
    SetDot (n);
    SetMark (wn_cur -> w_start, bf_cur, dot);
    n = ToMark (ThisErr -> e_text);
    WindowOn (bf_cur);
    SetDot (n);
    return 1;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 errlog.c
	/bin/echo -n '	'; /bin/ls -ld errlog.c
fi
/bin/echo 'Extracting keyboard.c'
sed 's/^X//' <<'//go.sysin dd *' >keyboard.c
X/* keyboard manipulation primitives */

X/*		Copyright (c) 1981,1980 James Gosling		*/

#include "keyboard.h"
#include "window.h"
#include "buffer.h"
#include "config.h"
#include "mlisp.h"
#include <sgtty.h>

#ifdef subprocesses
#include <sys/mx.h>
#include "mchan.h"
#endif

#ifdef CatchSig
#include <signal.h>
#endif

X/* A keyboard called procedure returns:
	 0 normally
	-1 to quit */

static EndOfMac;		/* the place where the keyboard macro
				   currently being defined should end. */
static PushedBack;		/* The most recently pushed back character;
				   it will be returned by GetChar the next
				   time that GetChar is called */
static MetaPushBack;		/* The pushed-back meta key; it will be
				   returned by GetChar once PushedBack is
				   taken care of.  The idea is that if
				   the user hits Meta-Foo inside a
				   get-tty-character, get-tty-char will
				   return an ESC; this can be pushed back
				   and the meta key will still meta. */
static CheckpointFrequency;	/* The number of keystrokes between
				   checkpoints. */
static Keystrokes;		/* The number of keystrokes since the last
				   checkpoint. */
static CanCheckpoint;		/* True iff we're allowed to checkpoint
				   now. */
#ifdef ECHOKEYS
static char KeyBuf[10];		/* Buffer for keys from GetChar() */
static NextK;			/* Next index into KeyBuf */
static EchoKeys;		/* >= 0 iff we are to echo keystrokes */
static EchoArg;			/* >= 0 iff we are to echo arg */
static Echo1, Echo2;		/* Stuff for final echo */

#define	min(a,b)	((a)<(b)?(a):(b))

X/* Echo the current keystrokes */
X/* NOTE: DEPENDS ON POSITIVE ARGUMENT WHEN CALLED BY A SIGNAL */
EchoThem (notfinal)
register notfinal;
{
    char *dash = notfinal ? "-" : "";

    if (EchoArg >= 0 && ArgState != NoArg) {
	if (EchoKeys >= 0 && NextK)
	    message ("Arg: %d %s%s", arg, KeyToStr (KeyBuf, NextK), dash);
	else
	    message ("Arg: %d", arg);
    }
    else {
	if (EchoKeys >= 0 && NextK)
	    message ("%s%s", KeyToStr (KeyBuf, NextK), dash);
	else
	    return;
    }
    if (notfinal)
	Echo1++;		/* set echoed-flag */
    if (notfinal >= 0)
	DoDsp (0);
}
#endif ECHOKEYS

X/* ProcessKeys reads keystrokes and interprets them according to the
   given keymap and its inferior keymaps */
ProcessKeys () {
    register struct keymap *m;
    static struct keymap    NullMap;
    register    c;
    NextGlobalKeymap = 0;
    NextLocalKeymap = 0;

    while (1) {
	if (NextGlobalKeymap == 0) {
	    if (Remembering)
		EndOfMac = MemUsed;
	    if (ArgState != HaveArg && MemPtr == 0 && bf_cur != minibuf)
		UndoBoundary ();
	}
	CanCheckpoint++;
#ifdef ECHOKEYS
	if (!InputPending && (EchoKeys == 0 || EchoArg == 0))
	    EchoThem (-1);
#endif ECHOKEYS
	if ((c = GetChar ()) < 0) {
	    CanCheckpoint = 0;
	    return 0;
	}
	if (NextK >= sizeof KeyBuf)
	    NextK = 0;
	KeyBuf[NextK++] = c;
	CanCheckpoint = 0;
	if (wn_cur -> w_buf != bf_cur)
	    SetBfp (wn_cur -> w_buf);
	if (NextGlobalKeymap == 0)
	    NextGlobalKeymap = CurrentGlobalMap;
	if (NextLocalKeymap == 0)
	    NextLocalKeymap = bf_mode.md_keys;
	if (m = NextLocalKeymap) {
	    register struct BoundName  *p;
	    NextLocalKeymap = 0;
	    if (p = m -> k_binding[c]) {
		LastKeyStruck = c & 0177;
		if (p -> b_binding != KeyBound) {
#ifdef ECHOKEYS
		    /* If echoed immediate preceding key, echo this one */
		    if (!InputPending && Echo2)
			EchoThem (0);
		    NextK = 0;
#endif ECHOKEYS
		    ThisCommand = LastKeyStruck;
		}
		if (ExecuteBound (p) < 0)
		    return 0;
		if (ArgState != HaveArg)
		    PreviousCommand = ThisCommand;
		if (NextLocalKeymap == 0) {
		    NextGlobalKeymap = 0;
		    continue;
		}
	    }
	}
	if (m = NextGlobalKeymap) {
	    register struct BoundName  *p;
	    register struct keymap *local;
	    local = NextLocalKeymap;
	    NextGlobalKeymap = 0;
	    NextLocalKeymap = 0;
	    if (p = m -> k_binding[c]) {
		LastKeyStruck = c & 0177;
		if (p -> b_binding != KeyBound) {
#ifdef ECHOKEYS
		    if (!InputPending && Echo2)
			EchoThem (0);
		    NextK = 0;
#endif ECHOKEYS
		    ThisCommand = LastKeyStruck;
		}
		if (ExecuteBound (p) < 0)
		    return 0;
		if (ArgState != HaveArg)
		    PreviousCommand = ThisCommand;
		if (NextLocalKeymap) {
		    NextGlobalKeymap = NextLocalKeymap;
		    NextLocalKeymap = local ? local : &NullMap;
		}
		else {
		    NextGlobalKeymap = local ? &NullMap : 0;
		    NextLocalKeymap = local;
		}
		continue;
	    }
	    else {
		NextGlobalKeymap = local ? &NullMap : 0;
		NextLocalKeymap = local;
	    }
	}
	if (NextLocalKeymap == 0) {
	    NextK = 0;
	    IllegalOperation ();
	}
	else
	    NextGlobalKeymap = &NullMap;
    }
}

X/* read a character from the keyboard; call the redisplay if needed */
GetChar () {
    register c, alarmtime;

    if ((c = PushedBack) >= 0) {
	PushedBack = -1;
	goto HaveCharacter;
    }
    if ((c = MetaPushBack) >= 0) {
	MetaPushBack = -1;
	goto HaveCharacter;
    }
    if (MemPtr) {
	if (err) {
	    MemPtr = 0;
	    c = -1;
	    goto ReturnIt;
	}
	c = (unsigned char) *MemPtr++;
	if (c) {
	    c &= 0177;
	    goto HaveCharacter;
	}
	MemPtr = 0;
	c = -1;
	goto ReturnIt;
    }
    if (err && InputFD!=stdin) {
	c = -1;
	goto ReturnIt;
    }
#ifdef ECHOKEYS
    alarmtime = EchoKeys >= 0 ? (EchoArg >= 0 ? min (EchoKeys, EchoArg)
					      : EchoKeys)
			      : EchoArg;
#endif ECHOKEYS
#ifdef subprocesses
    if (InputFD==stdin && mpxin->ch_count==0 && !InputPending) {
#else
     if (InputFD==stdin && stdin->_cnt==0 && !InputPending) {
#endif
#ifdef FIONREAD
	ioctl (fileno(stdin), FIONREAD, &InputPending);
#endif
	if(!InputPending) {
	    DoDsp (0);
	    if(CheckpointFrequency>0 && CanCheckpoint
		    && Keystrokes>CheckpointFrequency) {
		CheckpointEverything ();
		Keystrokes = 0;
	    }
	}
    }
    Keystrokes++;
#ifdef subprocesses
    if(InputFD == stdin) {
#ifdef ECHOKEYS
	if (alarmtime > 0)
	    sigset (SIGALRM, EchoThem);
	c = mpx_getc(mpxin, alarmtime);
#else ECHOKEYS
	c = mpx_getc(mpxin);
#endif ECHOKEYS
	InputPending = mpxin->ch_count;
    }
    else {
	c = getc(InputFD);
	InputPending = stdin->_cnt>0;
    }
#else
    {
#ifdef ECHOKEYS
	if (alarmtime > 0) {
	    sigset (SIGALRM, EchoThem);
	    alarm ((unsigned) alarmtime);
	}
#endif ECHOKEYS
	c = getc(InputFD);
#ifdef ECHOKEYS
	alarm (0);
#endif ECHOKEYS
	InputPending = stdin->_cnt>0;
    }
#endif
    if (c < 0) {
	c = -1;
	goto ReturnIt;
    }
HaveCharacter:
    if (Remembering) {
	KeyMem[MemUsed++] = (MetaFlag && (c&0200)) ? 033 : c | 0200;
	if (MemUsed >= MemLen) {
	    error ("Keystroke memory overflow!");
	    Remembering = EndOfMac = MemUsed = KeyMem[0] = 0;
	}
    }
    if (MetaFlag && (c&0200)) {
	MetaPushBack = c & 0177;
	c = 033;
    }
    c &= 0177;
ReturnIt:
#ifdef ECHOKEYS
    Echo2 = Echo1;		/* Save last echoed-flag */
    Echo1 = 0;			/* Clear echoed-flag */
#endif ECHOKEYS
    return c;
}

X/* Given a keystroke sequence look up the BoundName that it is bound to */
struct BoundName **LookupKeys (map, keys, len)
register struct keymap *map;
register char *keys;
register len;
{
    register struct BoundName  *b;
    while (map && --len >= 0) {
	b = map -> k_binding[*keys];
	if (len == 0)
	    return &map -> k_binding[*keys];
	keys++;
	if (b == 0 || b -> b_binding != KeyBound)
	    break;
	map = b -> b_bound.b_keymap;
    }
    return 0;
}

static ExecutingKeyboardMacro;	/* true iff executing keyboard macro */

StartRemembering () {
    if (Remembering)
	error ("Already remembering!");
    else {
	Remembering++;
	ExecutingKeyboardMacro = 0;
	MemUsed = EndOfMac = 0;
	message("Remembering...");
    }
    return 0;
}

StopRemembering () {
    if (Remembering) {
	Remembering = 0;
	KeyMem[EndOfMac] = 0;
	message("Keyboard macro defined.");
    }
    return 0;
}

X/* Execute the given command string */
ExecStr (s)
char *s; {
    register char  *old = MemPtr;
    MemPtr = s;
    ProcessKeys ();
    MemPtr = old;
}

ExecuteKeyboardMacro () {
    if (Remembering)
	error ("Sorry, you can't call the keyboard macro while defining it.");
    else if (MemUsed == 0)
	    error ("No keyboard macro to execute.");
    else if (ExecutingKeyboardMacro)
	    return 0;
    else {
	register i = arg;
	ExecutingKeyboardMacro++;
	arg = 0;
	ArgState = NoArg;
	do ExecStr (KeyMem);
	while (!err && --i>0);
	ExecutingKeyboardMacro = 0;
    }
    return 0;
}

static
PushBackCharacter () {
    register    n = (int) *getkey (&GlobalMap, ": push-back-character ");
    if (!err)
	PushedBack = n;
    return 0;
}

RecursiveEdit () {
    struct ProgNode *oldp = CurExec;
    register FILE *oldf = InputFD;
    InputFD = stdin;
    CurExec = 0;
    RecurseDepth++;
    Cant1LineOpt++;
    RedoModes++;
    ProcessKeys ();
    RecurseDepth--;
    Cant1LineOpt++;
    RedoModes++;
    CurExec = oldp;
    InputFD = oldf;
    return 0;
}

X/* Return MLisp value nonzero if (a) input pending or (b) we can't tell */

static
KeysPending () {
    ReleaseExpr (MLvalue);
    MLvalue -> exp_type = IsInteger;
#ifdef FIONREAD
    if (!InputPending)
	ioctl (fileno(stdin), FIONREAD, &InputPending);
    MLvalue -> exp_int = InputPending;
#else
    MLvalue -> exp_int = -1;
#endif
    return 0;
}

InitKey () {
    PushedBack = -1;
    MetaPushBack = -1;
#ifdef CatchSig
    sigset (SIGINT, IllegalOperation);
    sigset (SIGTERM, IllegalOperation);
#endif
#ifdef DumpableEmacs
    if (!Once) {
	FluidStatic (&MetaFlag, sizeof MetaFlag);
	FluidStatic (&ExecutingKeyboardMacro, sizeof ExecutingKeyboardMacro);
#else
    {
#endif
	setkey (CtlXmap, ('e'), ExecuteKeyboardMacro, "execute-keyboard-macro");
	setkey (CtlXmap, ('('), StartRemembering, "start-remembering");
	setkey (CtlXmap, (')'), StopRemembering, "stop-remembering");
	DefIntVar ("checkpoint-frequency", &CheckpointFrequency);
	CheckpointFrequency = 300;
	DefIntVar ("echo-keystrokes", &EchoKeys);
	EchoKeys = -1;
	DefIntVar ("echo-argument", &EchoArg);
	EchoArg = -1;
	defproc (PushBackCharacter, "push-back-character");
	defproc (RecursiveEdit, "recursive-edit");
	defproc (KeysPending, "pending-input");
	DefIntVar ("this-command", &ThisCommand);
    }
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 keyboard.c
	/bin/echo -n '	'; /bin/ls -ld keyboard.c
fi
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris.umcp-cs@UDel-Relay