Commits

steve  committed aafbeb7

Created

  • Participants
  • Tags xemacs

Comments (0)

Files changed (14)

+1998-01-11  SL Baur  <steve@altair.xemacs.org>
+
+	* Makefile: Update to newer package interface.
+
+1997-11-02  SL Baur  <steve@altair.xemacs.org>
+
+	* term.el (term-is-xemacs): Match against XEmacs instead of Lucid.
+	(term-exec-1): Use `locate-data-directory' instead of data-directory.
+
+1997-09-30  SL Baur  <steve@altair.xemacs.org>
+
+	* term.el (term-mode): Use window-displayed-height instead of
+	window-height.
+	(term-check-size): Ditto.
+	From Glynn Clements <glynn@sensei.co.uk>
+
+1997-06-04  Steven L Baur  <steve@altair.xemacs.org>
+
+	* term.el (make-term): Fix docstring.
+
+Sun Dec 22 00:38:46 1996  Sudish Joseph  <sudish@mindspring.com>
+
+	* tgud.el (tgud-gdb-complete-filter): Match carriage returns as
+	well as line feeds.
+
+Tue Jun 13 16:38:40 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+	* term.el:  Various optimizations.  The main one is to optimize for
+	simple output at the end of the buffer, with no paging, and in that
+	case to defer scrolling while we can.
+	(term-emulate-terminal):  Don't call term-handle-scroll in
+	simple cases unless we are either paging or term-scroll-with-delete.
+	(term-down):  Likewise.
+	(term-handle-scroll):  Modify accordingly.
+	(term-emulate-terminal):  Avoid deleting old text in common case.
+	Optimize the simple case of CRLF when we're at buffer end.
+	Handle deferred scroll when done processing output.
+	(term-handle-deferred-scroll):  New function.
+	(term-down):  Simplify - no longer take RIGHT argument.  Tune.
+	(term-goto):  Use term-move-columns to compensate for the above.
+
+Sat Jun 10 23:10:52 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+	* term.el (term-escape-char, term-set-escape-char):  Add doc-string.
+	(term-mouse-paste):  Add xemacs support.
+
+	* term.el:  Various speed enhencements:
+	(term-handle-scroll):  Don't clear term-current-row; maybe adjust it.
+	(term-down):  Don't call term-adjust-current-row-cache if we've
+	done term-handle-scroll.
+	(term-emulate-terminal):  Don't call term-adjust-current-row-cache.
+	(term-emulate-terminal):  For TAB, don't nil term-start-line-column.
+	(term-goto):  Possible optimization.
+
+Wed Mar 15 17:20:26 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+	* term.el (term-mouse-paste):  Make work for xemacs-19.11.
+	For GNU emacs, don't mouse-set-point, but do
+	run-hooks on mouse-leave-buffer-hook,
+
+	* term.el (term-char-mode):  Fix paren error that caused
+	the arrow keys to not be recognized under xemacs.
+	Also, simplify/fix [(button2)] to [button2] for paste under xemacs.
+
+Tue Mar  7 16:43:51 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+	* term.el (term-eol-on-send):  New variable.
+	(term-send-input):  Move point to eol before sending only if
+	term-eol-on-send is true.
+
+	* term.el (term-send-input):  Don't move process-mark until
+	after possible 'history processing.
+
+Tue Feb  7 02:59:59 1995  Richard Stallman  <rms@pogo.gnu.ai.mit.edu>
+
+	* term.el (term-protocol-version): Renamed from term-version.
+
+Sat Feb  4 16:23:18 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+	* term.el (term-version):  Increased to 0.95.
+	(term-pager-enabled):  New macro.  Use it a bunch of places.
+	(term-terminal-menu):  Clean up initialization so we don't get
+	complaints when re-loading term.el.
+	(term-send-raw-meta):  Redo to handle meta-symbols (e.g. meta-delete).
+	More robust checking of parameter to make-string.
+	(term-update-mode-line):  New function.  Call it whenever we change
+	char/line/paging mode.  Now includes "page" in mode-line-process
+	if paging is abled.
+
+	* term.el:  Remove causes for byte-compilation to complain:
+	(term-terminal-pos):  Declare x and y in let-binding.
+	(term-send-invisible):  Remove bogus second "iteractive" call.
+	(term-*): Provide defvars for lots of buffer-local variables.
+	(term-mode):  Make comments and initial value setting from
+	here to the corresponding defvar.
+	(term-line-start-column):  Remove unused variable.
+	(term-erase-in-line):  Fix syntax (incorrect parenthesis) error.
+	(term-erase-in-display):  Fix typo "\?n" -> "?\n".
+
+	* term.el:  Make Unix "resize" command work:
+	(term-handle-ansi-escape):  On "\e[row;colH", limit row
+	and col to size of window.  (Resize sends "999;999".)
+	(term-handle-ansi-escape):   Implement "\e[6n" "Report cursor
+	position".  This requires that we pass proc as an extra parameter.
+	(term-scroll-region):  An empty region means extend to window bottom.
+
+Fri Jan 20 14:07:31 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+	* term.el (term-version):  Increased to 0.94.
+	(term-if-emacs19, term-if-xemacs, term-ifnot-xemacs):  New macros
+	to conditionalize at compile-time for different emacs versions.
+	(various places):  Use them (instead of term-is-XXXX).
+	(term-is-emacs19):  Removed, no longer needed.
+
+	* term.el:  Change keybindings to not use C-c LETTER, for
+	term-char-mode, term-line-mode.  Keybindings for term-pager-enable
+	and term-pager-disable replaced by one for term-pager-toggle.
+	(term-pager-toggle):  New function.
+
+	* term.el (term-fake-pager-enable, term-fake-pager-disable):
+	Define as aliases, so that menubar code will find proper keybindings.
+	(term-char-mode):  Make no-op if already in char mode.
+	(term-line-mode):  Make no-op if already in line mode.
+	(term-mode-map):  Add keybinding for no-op term-line-mode, so
+	code to display menubar keybindings doesn't lose it.  (Needed
+	as long as char-mode and line-mode share term-terminal-menu.)
+	(term-raw-escape-map):  Likewise for term-char-mode.
+	(term-char-mode, term-line-mode):  Better documentation strings.
+
+	* term.el:  Added menubar for pager sub-mode.
+
+Wed Jan 11 17:06:37 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+	* term.el (term-command-hook):  Disabled the feature that allowed
+	inferior to send a lisp command to emacs - too big a security hole.
+
+Mon Nov 21 12:38:05 1994  Per Bothner  <bothner@kalessin.cygnus.com>
+
+	* term.el (term-termcap-format):  Add cd capability.  Fix ei.
+	(term-exec-1):  Pass $TERMINFO instead of $TERMCAP if appropriate.
+	(term-exec-1):  Pass emacs-version and term-version in $TERM.
+	(term-exec-1):  Re-write to set process-environment.
+
+Sun Jun 26 20:31:52 1994  Per Bothner  (bothner@kalessin.cygnus.com)
+
+	* term.el:  Set version number to 0.92.
+	* term.el (term):  New top-level function.
+
+Tue May 17 11:45:21 1994  Per Bothner  (bothner@kalessin.cygnus.com)
+
+	* term.el (term-emulate-terminal):  Move most of the scrolling
+	and other final actions inside the body of the unwind-protect.
+	But make sure to select the original selected window in the
+	cleanup actions.  Bug reported by David Hampton <hampton@cisco.com>.
+
+	* term.el (term-emulate-terminal):  Ignore ?\016 (Shift Out)
+	and ?\017 (Shift In).  (These are produced by the Lynx WWW-viewer.)
+
+# Makefile for eterm Terminal Emulator lisp code
+
+# This file is part of XEmacs.
+
+# XEmacs is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2, or (at your option) any
+# later version.
+
+# XEmacs is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with XEmacs; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+VERSION = 1.02
+PACKAGE = eterm
+PKG_TYPE = regular
+REQUIRES = xemacs-base
+CATEGORY = os
+
+ELCS = term.elc tgud.elc tshell.elc
+
+include ../../XEmacs.rules
+
+all:: $(ELCS) auto-autoloads.elc custom-load.elc
+
+srckit: srckit-std
+
+binkit: binkit-sourcedata
+- What should be the default escape key for char mode?
+  Currently; I'm using ^C.
+
+- What other keybindings should we have for char mode?
+
+- What terminal type should we use?
+  The old shell.el defined TERM=emacs.
+  To avoid confusion, we should use something different.  (E.g. if TERM
+  is "emacs", bash turns off editing, which is not what we want.)
+  I'm currently using TERM=emacs-terminal.
+  This is somewhat verbose.
+  Other ideas:  TERM=eterm TERM=emacsterm TERM=emacst.
+
+- How should buffer-local variables be defined and documented?
+
+; Features in comint.el not supported:
+; comint-scroll-to-bottom-on-input
+; comint-process-echoes (would be always true)
+; comint-password-prompt-regexp (not useful)
+; comint-watch-for-password-prompt (not useful)
+; comint-eol-on-send
+; comint-run
+; comint-preinput-scroll-to-bottom
+; comint-postoutput-scroll-to-bottom (inlined into term-emulate-terminal).
+
+; Should set EMACS env var to emacs-version?
+; Should set TERM to vt100 if using terminfo?
+; Should we set COLUMNS if using terminfo?
+; New C-c kodes?
+This new term-mode is a merge of the comint shell mode with a
+ANSI-compatible terminal-emulator.
+
+If you're using emacs-19.23 (or newer) or xemacs-19.11 (or newer),
+and only want the terminal-emulator itself, just load the file
+term.el.  (You probably want to byte-compile it first, especially
+if you have a slow machine.)
+
+To start term do M-x term RETURN.
+
+Compared to terminal.el:
+* Uses standard ANSI (vt102) escape sequences.
+* High-lighting (inverse video, underline, bold) are supported.
+* Fully integrated into shell mode.
+* Can switch back and forth between character mode (acts like xterm)
+  and line mode (acts like old shell mode).
+* Tab and line breaks are stored in buffer (so cut and paste will get
+  the correct tabs and line breaks), but terminal motion uses the
+  "visible" layout of the screen (and display programs can assume
+  tab, cr and lf work as on plain terminal).
+
+In character ("raw") sub-mode:
+Each character type is sent to the inferior process, except for C-c.
+C-c C-c	Send a C-c to the inferior.
+C-c C-j	Enter line sub-mode
+C-c OTHER Same as cooked C-x map
+Can use bash line editing, filename completion, and history.
+Can run emacs in an emacs window! (bash users first do: export -n DISPLAY)
+
+In line ("cooked") mode:
+Like traditional shell mode
+C-c C-k	Enter character sub-mode
+
+Either character or line sub-mode:
+C-c C-q Toggle pager sub-mode (enable or disable)
+The "pager" provides functionality similar to the "more" program:
+Whenever a screenful has been received, emacs stops reading from
+the process until you type the appropriate key.  (The key 'h' provides help.)
+The pager is smart enough that you can leave it on,  even while
+running full-screen interactive programs inside a shell window.
+(The pager does not work under xemacs 19.11.)
+
+The file tshell.el is a preliminary replacement for shell mode.
+After loading it, you invoke it with M-x tshell RET.
+This needs a little work, and is not recommended.  It differs from
+term-mode in that it starts in line mode, and it performs directory
+tracking.  Such directory tracking cannot be made reliable.
+It you're running bash, it is better to just use term-mode and have
+bash tell term the current directory.  You can do that by adding
+the following to your ~/.bashrc:
+
+	if [ "$TERM" = "eterm" ]; then
+	  PROMPT_COMMAND='echo "/${PWD}"'
+	fi
+
+The file tgud.el is a preliminary replacement for gud.el, including
+gdb-mode.  After loading it, invoke "tgdb-mode" with M-x tgdb RET.
+
+An alternative is to run gdb from term (or tshell) mode.
+Just start gdb with the --fullname flag.  This will cause gdb to
+ask emacs to display proper source frame on break-points -
+even over a telnet/rlogin link!  You would not be able to use the
+gud-specific commands, but you can use gdb/readline line editing.
+
+If you're using terminfo, copy the e directory (itself, not just
+the files in it) into the emacs 'etc' directory (as given by
+ESC ESC data-directory RET), so you have ..../etc/e/eterm.
+(Your system uses terminfo if ESC ESC (boundp 'system-uses-terminfo) RET
+return t.)  If you can't do that, replace the word "data-directory"
+in term.el by a string naming this directory.
+
+The file TODO.term notes ideas for improvements.
+
+The file term.texi contain some notes that one day may become part
+of a manual.
+
+Term.el will be in the next emacs release from the FSF.
+It will also probably be in the next xemacs release.
+The comint-based shell.el and gud.el will be replaced later.
+Telnet.el can then be junked.
+Long-term, term.el will replace comint.el, but can co-exist with it.
+
+Comments and bug fixes should be sent to Per Bothner (bothner@cygnus.com).
+Note that I'm new to emacs hacking, so improvements are very welcome.
+* Define a sentinel function, so that the display doesn't get
+screwed up the default sentinel when the process finishes.
+
+* Performance improvements?  (It is zippy enough on reasonably
+fast machines, though.)
+
+* Should more terminal escape sequences be supported?
+Yes:  At least the ANSI color escapes (as in colour_xterm).
+
+* The caching variables (e.g. term-current-row) assume that there
+is be no random editing of the buffer that we don't know about.  In that
+respect, they are somewhat fragile.
+
+* Document the internals better, and make it easier to write
+emulators for other kinds of terminals.
+
+* The scrolling behavior is still not quite right.
+
+* Stallman has expressed dislike for the xterm style of switching to the
+alternate buffer on the "ti" capability.  An alternative would be to
+defer this until the screen is cleared.  That assumes there are programs
+that emit ti without following that by a command to erase the window.
+I'm not sure there are any such programs (that we care about) ...
+
+*** CHANGES THAT REQUIRE NEW EMACS PRIMITIVES ***
+
+* If ioctl is made accessible to elisp, it may be possible
+to support some kind of automatic switching between char mode
+and line mode.  It also becomes possible to privide term
+primitives to turn off echoing in the inferior.
+
+*** CHANGES TO DO IN OTHER PROGRAMS ***
+
+* In gdb-mode, a keysequence like \C-c\C-s works by sending the command
+"step" in gdb-mode.  Emacs goes to a fair bit of trouble to delete the
+prompt preceding the command, as well as the echo from the inferior.
+In addition to being hairy, it is somewhat fragile (because of possible
+type-ahead, and because the inferior might be mixing other output with
+the echo).
+More robust would be for emacs to send the command "noecho step" (or
+"step #noecho") where the "noecho" is an instruction to gdb (readline)
+to erase the prompt for this command, and suppress its echo.
+
+* Bash (and perhaps other shells) should be modified so that before
+the prompt (and PROMPT_COMMAND) are printed, they emit:
+	printf("\032/%s\n", PWD);
+This will tell the shell window which directory it should assume,
+and obviates the need for all that hairy directory tracking.

File etc/e/README

+Rebuild terminfo files with
+TERMINFO=<Full-Path-To-XEmacs-tree>/etc tic *.ti

File etc/e/emancs

Binary file added.

File etc/e/emancs.ti

+emancs,
+	cols#80,
+	sgr0=\003,
+	smso=\001,
+	smul=\002,
+	rmul=\003,
+	it#1,

File etc/e/eterm

Binary file added.

File etc/e/eterm.ti

+# These are ordered as in the O'Reilly "termcap and terminfo" book.
+eterm,
+	lines#24,cols#80,
+	cuu1=\E[A,cud1=\n,cub1=\b,cuf1=\E[C,home=\E[H,cr=\r,
+	cuu=\E[%p1%dA,cud=\E[%p1%dB,cub=\E[%p1%dD,cuf=\E[%p1%dC,
+	cup=\E[%i%p1%d;%p2%dH,
+	ind=\n,csr=\E[%i%p1%d;%p2%dr,
+	il1=\E[L,il=\E[%p1%dL,
+	clear=\E[H\E[J,ed=\\E[J,el=\E[K,
+	dl1=\E[M,dl=\E[%p1%dM,dch1=\E[P,dch=\E[%p1%dP,
+	kcub1=\E[D,kcuf1=\E[C,kcuu1=\E[A,kcud1=\E[B,
+	smir=\E[4h,rmir=\E[4l,ich=\E[%p1%d@,mir,
+	smcup=\E7\E[?47h,rmcup=\E[2J\E[?47l\E8,
+	ht=\t,
+	smso=\E[7m,rmso=\E[m,
+	smul=\E[4m,rmul=\E[m,
+	rev=\E[7m,bold=\E[1m,sgr0=\E[m,
+	bel=^G,xenl,am,

File package-info.in

+(eterm
+  (version VERSION
+   description "Terminal emulation."
+   filename FILENAME
+   md5sum MD5SUM
+   size SIZE
+   provides (eterm)
+   requires (REQUIRES)
+   type regular
+))
+;;; term.el --- general command interpreter in a window stuff
+
+;; Copyright (C) 1988-1995, 1997 Free Software Foundation, Inc.
+
+;; Author: Per Bothner <bothner@cygnus.com>
+;; Based on comint mode written by: Olin Shivers <shivers@cs.cmu.edu>
+;; Keyword: processes
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; The changelog is at the end of this file.
+
+;; Please send me bug reports, bug fixes, and extensions, so that I can
+;; merge them into the master source.
+;;     - Per Bothner (bothner@cygnus.com)
+
+;; This file defines a general command-interpreter-in-a-buffer package
+;; (term mode). The idea is that you can build specific process-in-a-buffer
+;; modes on top of term mode -- e.g., lisp, shell, scheme, T, soar, ....
+;; This way, all these specific packages share a common base functionality, 
+;; and a common set of bindings, which makes them easier to use (and
+;; saves code, implementation time, etc., etc.).
+
+;; For hints on converting existing process modes (e.g., tex-mode,
+;; background, dbx, gdb, kermit, prolog, telnet) to use term-mode
+;; instead of shell-mode, see the notes at the end of this file.
+
+
+;; Brief Command Documentation:
+;;============================================================================
+;; Term Mode Commands: (common to all derived modes, like cmushell & cmulisp
+;; mode)
+;;
+;; m-p	    term-previous-input    	  Cycle backwards in input history
+;; m-n	    term-next-input  	    	  Cycle forwards
+;; m-r     term-previous-matching-input  Previous input matching a regexp
+;; m-s     comint-next-matching-input      Next input that matches
+;; return  term-send-input
+;; c-c c-a term-bol                      Beginning of line; skip prompt.
+;; c-d	    term-delchar-or-maybe-eof     Delete char unless at end of buff.
+;; c-c c-u term-kill-input	    	    ^u
+;; c-c c-w backward-kill-word    	    ^w
+;; c-c c-c term-interrupt-subjob 	    ^c
+;; c-c c-z term-stop-subjob	    	    ^z
+;; c-c c-\ term-quit-subjob	    	    ^\
+;; c-c c-o term-kill-output		    Delete last batch of process output
+;; c-c c-r term-show-output		    Show last batch of process output
+;; c-c c-h term-dynamic-list-input-ring  List input history
+;;
+;; Not bound by default in term-mode
+;; term-send-invisible			Read a line w/o echo, and send to proc
+;; (These are bound in shell-mode)
+;; term-dynamic-complete		Complete filename at point.
+;; term-dynamic-list-completions	List completions in help buffer.
+;; term-replace-by-expanded-filename	Expand and complete filename at point;
+;;					replace with expanded/completed name.
+;; term-kill-subjob			No mercy.
+;; term-show-maximum-output            Show as much output as possible.
+;; term-continue-subjob		Send CONT signal to buffer's process
+;;					group. Useful if you accidentally
+;;					suspend your process (with C-c C-z).
+
+;; term-mode-hook is the term mode hook. Basically for your keybindings.
+;; term-load-hook is run after loading in this package.
+
+;; Code:
+
+;; This is passed to the inferior in the EMACS environment variable,
+;; so it is important to increase it if there are protocol-relevant changes.
+(defconst term-protocol-version "0.95")
+
+(require 'ring)
+(require 'ehelp)
+
+(if (fboundp 'defgroup) nil
+  (defmacro defgroup (&rest forms) nil)
+  (defmacro defcustom (name init doc &rest forms)
+    (list 'defvar name init doc)))
+
+(defgroup term nil
+  "General command interpreter in a window"
+  :group 'processes
+  :group 'unix)
+
+
+;;; Buffer Local Variables:
+;;;============================================================================
+;;; Term mode buffer local variables:
+;;;     term-prompt-regexp    - string       term-bol uses to match prompt.
+;;;     term-delimiter-argument-list - list  For delimiters and arguments
+;;;     term-last-input-start - marker       Handy if inferior always echoes
+;;;     term-last-input-end   - marker       For term-kill-output command
+;; For the input history mechanism:
+(defvar term-input-ring-size 32 "Size of input history ring.")
+;;;     term-input-ring-size  - integer
+;;;     term-input-ring       - ring
+;;;     term-input-ring-index - number           ...
+;;;     term-input-autoexpand - symbol           ...
+;;;     term-input-ignoredups - boolean          ...
+;;;     term-last-input-match - string           ...
+;;;     term-dynamic-complete-functions - hook   For the completion mechanism
+;;;     term-completion-fignore - list           ...
+;;;     term-get-old-input    - function     Hooks for specific 
+;;;     term-input-filter-functions - hook     process-in-a-buffer
+;;;     term-input-filter     - function         modes.
+;;;     term-input-send	- function
+;;;     term-scroll-to-bottom-on-output - symbol ...
+;;;     term-scroll-show-maximum-output - boolean...
+(defvar term-height) ;; Number of lines in window.
+(defvar term-width) ;; Number of columns in window.
+(defvar term-home-marker) ;; Marks the "home" position for cursor addressing.
+(defvar term-saved-home-marker nil) ;; When using alternate sub-buffer,
+;;		contains saved term-home-marker from original sub-buffer .
+(defvar term-start-line-column 0) ;; (current-column) at start of screen line,
+;;		or nil if unknown.
+(defvar term-current-column 0) ;; If non-nil, is cache for (current-column).
+(defvar term-current-row 0) ;; Current vertical row (relative to home-marker)
+;;		or nil if unknown.
+(defvar term-insert-mode nil)
+(defvar term-vertical-motion)
+(defvar term-terminal-state 0) ;; State of the terminal emulator:
+;;		state 0: Normal state
+;;		state 1: Last character was a graphic in the last column.
+;;		If next char is graphic, first move one column right
+;;		(and line warp) before displaying it.
+;;		This emulates (more or less) the behavior of xterm.
+;;		state 2: seen ESC
+;;		state 3: seen ESC [ (or ESC [ ?)
+;;		state 4: term-terminal-parameter contains pending output.
+(defvar term-kill-echo-list nil) ;; A queue of strings whose echo
+;;		we want suppressed.
+(defvar term-terminal-parameter)
+(defvar term-terminal-previous-parameter)
+(defvar term-current-face 'default)
+(defvar term-scroll-start 0) ;; Top-most line (inclusive) of scrolling region.
+(defvar term-scroll-end) ;; Number of line (zero-based) after scrolling region.
+(defvar term-pager-count nil) ;; If nil, paging is disabled.
+;;		Otherwise, number of lines before we need to page.
+(defvar term-saved-cursor nil)
+(defvar term-command-hook)
+(defvar term-log-buffer nil)
+(defvar term-scroll-with-delete nil) ;; term-scroll-with-delete is t if
+;;		forward scrolling should be implemented by delete to
+;;		top-most line(s); and nil if scrolling should be implemented
+;;		by moving term-home-marker.  It is set to t iff there is a
+;;		(non-default) scroll-region OR the alternate buffer is used.
+(defvar term-pending-delete-marker) ;; New user input in line mode needs to
+;;		be deleted, because it gets echoed by the inferior.
+;;		To reduce flicker, we defer the delete until the next output.
+(defvar term-old-mode-map nil) ;; Saves the old keymap when in char mode.
+(defvar term-old-mode-line-format) ;; Saves old mode-line-format while paging.
+(defvar term-pager-old-local-map nil) ;; Saves old keymap while paging.
+(defvar term-pager-old-filter) ;; Saved process-filter while paging.
+
+(defcustom explicit-shell-file-name nil
+  "*If non-nil, is file name to use for explicitly requested inferior shell."
+  :type '(choice (const nil) file)
+  :group 'term)
+
+(defvar term-prompt-regexp "^"
+  "Regexp to recognise prompts in the inferior process.
+Defaults to \"^\", the null string at BOL.
+
+Good choices:
+  Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
+  Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
+  franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
+  kcl: \"^>+ *\"
+  shell: \"^[^#$%>\\n]*[#$%>] *\"
+  T: \"^>+ *\"
+
+This is a good thing to set in mode hooks.")
+
+(defvar term-delimiter-argument-list ()
+  "List of characters to recognise as separate arguments in input.
+Strings comprising a character in this list will separate the arguments
+surrounding them, and also be regarded as arguments in their own right (unlike
+whitespace).  See `term-arguments'.
+Defaults to the empty list.
+
+For shells, a good value is (?\\| ?& ?< ?> ?\\( ?\\) ?;).
+
+This is a good thing to set in mode hooks.")
+
+(defcustom term-input-autoexpand nil
+  "*If non-nil, expand input command history references on completion.
+This mirrors the optional behavior of tcsh (its autoexpand and histlit).
+
+If the value is `input', then the expansion is seen on input.
+If the value is `history', then the expansion is only when inserting
+into the buffer's input ring.  See also `term-magic-space' and
+`term-dynamic-complete'.
+
+This variable is buffer-local."
+  :type '(choice (const nil) (const t) (const input) (const history))
+  :group 'term)
+
+(defcustom term-input-ignoredups nil
+  "*If non-nil, don't add input matching the last on the input ring.
+This mirrors the optional behavior of bash.
+
+This variable is buffer-local."
+  :type 'boolean
+  :group 'term)
+
+(defcustom term-input-ring-file-name nil
+  "*If non-nil, name of the file to read/write input history.
+See also `term-read-input-ring' and `term-write-input-ring'.
+
+This variable is buffer-local, and is a good thing to set in mode hooks."
+  :type 'boolean
+  :group 'term)
+
+(defcustom term-scroll-to-bottom-on-output nil
+  "*Controls whether interpreter output causes window to scroll.
+If nil, then do not scroll.  If t or `all', scroll all windows showing buffer.
+If `this', scroll only the selected window.
+If `others', scroll only those that are not the selected window.
+
+The default is nil.
+
+See variable `term-scroll-show-maximum-output'. This variable is buffer-local."
+  :type '(choice (const :tag "off" nil)
+                 (const t)
+                 (const all)
+                 (const this)
+                 (const others))
+  :group 'term)
+
+(defcustom term-scroll-show-maximum-output nil
+  "*Controls how interpreter output causes window to scroll.
+If non-nil, then show the maximum output when the window is scrolled.
+
+See variable `term-scroll-to-bottom-on-output'.
+This variable is buffer-local."
+  :type 'boolean
+  :group 'term)
+
+;; Where gud-display-frame should put the debugging arrow.  This is
+;; set by the marker-filter, which scans the debugger's output for
+;; indications of the current pc.
+(defvar term-pending-frame nil)
+
+;;; Here are the per-interpreter hooks.
+(defvar term-get-old-input (function term-get-old-input-default)
+  "Function that submits old text in term mode.
+This function is called when return is typed while the point is in old text.
+It returns the text to be submitted as process input.  The default is
+term-get-old-input-default, which grabs the current line, and strips off
+leading text matching term-prompt-regexp")
+
+(defvar term-dynamic-complete-functions
+  '(term-replace-by-expanded-history term-dynamic-complete-filename)
+  "List of functions called to perform completion.
+Functions should return non-nil if completion was performed.
+See also `term-dynamic-complete'.
+
+This is a good thing to set in mode hooks.")
+
+(defvar term-input-filter
+  (function (lambda (str) (not (string-match "\\`\\s *\\'" str))))
+  "Predicate for filtering additions to input history.
+Only inputs answering true to this function are saved on the input
+history list. Default is to save anything that isn't all whitespace")
+
+(defvar term-input-filter-functions '()
+  "Functions to call before input is sent to the process.
+These functions get one argument, a string containing the text to send.
+
+This variable is buffer-local.")
+
+(defvar term-input-sender (function term-simple-send)
+  "Function to actually send to PROCESS the STRING submitted by user.
+Usually this is just 'term-simple-send, but if your mode needs to 
+massage the input string, this is your hook. This is called from
+the user command term-send-input. term-simple-send just sends
+the string plus a newline.")
+
+(defcustom term-eol-on-send t
+  "*Non-nil means go to the end of the line before sending input.
+See `term-send-input'."
+  :type 'boolean
+  :group 'term)
+
+(defcustom term-mode-hook '()
+  "Called upon entry into term-mode
+This is run before the process is cranked up."
+  :type 'hook
+  :group 'term)
+
+(defcustom term-exec-hook '()
+  "Called each time a process is exec'd by term-exec.
+This is called after the process is cranked up.  It is useful for things that
+must be done each time a process is executed in a term-mode buffer (e.g.,
+\(process-kill-without-query)).  In contrast, the term-mode-hook is only
+executed once when the buffer is created."
+  :type 'hook
+  :group 'term)
+
+(defvar term-mode-map nil)
+(defvar term-raw-map nil
+  "Keyboard map for sending characters directly to the inferior process.")
+(defvar term-escape-char nil
+  "Escape character for char-sub-mode of term mode.
+Do not change it directly;  use term-set-escape-char instead.")
+(defvar term-raw-escape-map nil)
+
+(defvar term-pager-break-map nil)
+
+(defvar term-ptyp t
+  "True if communications via pty; false if by pipe.  Buffer local.
+This is to work around a bug in emacs process signaling.")
+
+(defvar term-last-input-match ""
+  "Last string searched for by term input history search, for defaulting.
+Buffer local variable.") 
+
+(defvar term-input-ring nil)
+(defvar term-last-input-start)
+(defvar term-last-input-end)
+(defvar term-input-ring-index nil
+  "Index of last matched history element.")
+(defvar term-matching-input-from-input-string ""
+  "Input previously used to match input history.")
+; This argument to set-process-filter disables reading from the process,
+; assuming this is emacs-19.20 or newer.
+(defvar term-pager-filter t)
+
+(put 'term-replace-by-expanded-history 'menu-enable 'term-input-autoexpand)
+(put 'term-input-ring 'permanent-local t)
+(put 'term-input-ring-index 'permanent-local t)
+(put 'term-input-autoexpand 'permanent-local t)
+(put 'term-input-filter-functions 'permanent-local t)
+(put 'term-scroll-to-bottom-on-output 'permanent-local t)
+(put 'term-scroll-show-maximum-output 'permanent-local t)
+(put 'term-ptyp 'permanent-local t)
+
+;; Do FORMS if running under Emacs-19.
+(defmacro term-if-emacs19 (&rest forms)
+  (if (string-match "^19" emacs-version) (cons 'progn forms)))
+;; True if running under XEmacs (previously Lucid emacs).
+(defmacro term-is-xemacs ()  '(string-match "XEmacs" emacs-version))
+;; Do FORM if running under XEmacs (previously Lucid emacs).
+(defmacro term-if-xemacs (&rest forms)
+  (if (term-is-xemacs) (cons 'progn forms)))
+;; Do FORM if NOT running under XEmacs (previously Lucid emacs).
+(defmacro term-ifnot-xemacs (&rest forms)
+  (if (not (term-is-xemacs)) (cons 'progn forms)))
+
+(defmacro term-in-char-mode () '(eq (current-local-map) term-raw-map))
+(defmacro term-in-line-mode () '(not (term-in-char-mode)))
+;; True if currently doing PAGER handling.
+(defmacro term-pager-enabled () 'term-pager-count)
+(defmacro term-handling-pager () 'term-pager-old-local-map)
+(defmacro term-using-alternate-sub-buffer () 'term-saved-home-marker)
+
+(defvar term-signals-menu)
+(defvar term-terminal-menu)
+
+(term-if-xemacs
+ (defvar term-terminal-menu
+   '("Terminal"
+     [ "Character mode" term-char-mode (term-in-line-mode)]
+     [ "Line mode" term-line-mode (term-in-char-mode)]
+     [ "Enable paging" term-pager-toggle (not term-pager-count)]
+     [ "Disable paging" term-pager-toggle term-pager-count])))
+
+(defun term-mode ()
+  "Major mode for interacting with an inferior interpreter.
+Interpreter name is same as buffer name, sans the asterisks.
+In line sub-mode, return at end of buffer sends line as input,
+while return not at end copies rest of line to end and sends it.
+In char sub-mode, each character (except `term-escape-char`) is
+set immediately.
+
+This mode is typically customised to create inferior-lisp-mode,
+shell-mode, etc.. This can be done by setting the hooks
+term-input-filter-functions, term-input-filter, term-input-sender and
+term-get-old-input to appropriate functions, and the variable
+term-prompt-regexp to the appropriate regular expression.
+
+An input history is maintained of size `term-input-ring-size', and
+can be accessed with the commands \\[term-next-input], \\[term-previous-input], and \\[term-dynamic-list-input-ring].
+Input ring history expansion can be achieved with the commands
+\\[term-replace-by-expanded-history] or \\[term-magic-space].
+Input ring expansion is controlled by the variable `term-input-autoexpand',
+and addition is controlled by the variable `term-input-ignoredups'.
+
+Input to, and output from, the subprocess can cause the window to scroll to
+the end of the buffer.  See variables `term-scroll-to-bottom-on-input',
+and `term-scroll-to-bottom-on-output'.
+
+If you accidentally suspend your process, use \\[term-continue-subjob]
+to continue it.
+
+\\{term-mode-map}
+
+Entry to this mode runs the hooks on term-mode-hook"
+  (interactive)
+    ;; Do not remove this.  All major modes must do this.
+    (kill-all-local-variables)
+    (setq major-mode 'term-mode)
+    (setq mode-name "Term")
+    (use-local-map term-mode-map)
+    (make-local-variable 'term-home-marker)
+    (setq term-home-marker (copy-marker 0))
+    (make-local-variable 'term-saved-home-marker)
+    (make-local-variable 'term-height)
+    (make-local-variable 'term-width)
+    (setq term-width (1- (window-width)))
+    (setq term-height (1- (window-displayed-height)))
+    (make-local-variable 'term-terminal-parameter)
+    (make-local-variable 'term-saved-cursor)
+    (make-local-variable 'term-last-input-start)
+    (setq term-last-input-start (make-marker))
+    (make-local-variable 'term-last-input-end)
+    (setq term-last-input-end (make-marker))
+    (make-local-variable 'term-last-input-match)
+    (setq term-last-input-match "")
+    (make-local-variable 'term-prompt-regexp)        ; Don't set; default
+    (make-local-variable 'term-input-ring-size)      ; ...to global val.
+    (make-local-variable 'term-input-ring)
+    (make-local-variable 'term-input-ring-file-name)
+    (or (and (boundp 'term-input-ring) term-input-ring)
+	(setq term-input-ring (make-ring term-input-ring-size)))
+    (make-local-variable 'term-input-ring-index)
+    (or (and (boundp 'term-input-ring-index) term-input-ring-index)
+	(setq term-input-ring-index nil))
+
+    (make-local-variable 'term-command-hook)
+    (setq term-command-hook (symbol-function 'term-command-hook))
+
+    (make-local-variable 'term-terminal-state)
+    (make-local-variable 'term-kill-echo-list)
+    (make-local-variable 'term-start-line-column)
+    (make-local-variable 'term-current-column)
+    (make-local-variable 'term-current-row)
+    (make-local-variable 'term-log-buffer)
+    (make-local-variable 'term-scroll-start)
+    (make-local-variable 'term-scroll-end)
+    (setq term-scroll-end term-height)
+    (make-local-variable 'term-scroll-with-delete)
+    (make-local-variable 'term-pager-count)
+    (make-local-variable 'term-pager-old-local-map)
+    (make-local-variable 'term-old-mode-map)
+    (make-local-variable 'term-insert-mode)
+    (make-local-variable 'term-dynamic-complete-functions)
+    (make-local-variable 'term-completion-fignore)
+    (make-local-variable 'term-get-old-input)
+    (make-local-variable 'term-matching-input-from-input-string)
+    (make-local-variable 'term-input-autoexpand)
+    (make-local-variable 'term-input-ignoredups)
+    (make-local-variable 'term-delimiter-argument-list)
+    (make-local-variable 'term-input-filter-functions)
+    (make-local-variable 'term-input-filter)  
+    (make-local-variable 'term-input-sender)
+    (make-local-variable 'term-eol-on-send)
+    (make-local-variable 'term-scroll-to-bottom-on-output)
+    (make-local-variable 'term-scroll-show-maximum-output)
+    (make-local-variable 'term-ptyp)
+    (make-local-variable 'term-exec-hook)
+    (make-local-variable 'term-vertical-motion)
+    (make-local-variable 'term-pending-delete-marker)
+    (setq term-pending-delete-marker (make-marker))
+    (make-local-variable 'term-current-face)
+    (make-local-variable 'term-pending-frame)
+    (setq term-pending-frame nil)
+    (run-hooks 'term-mode-hook)
+    (term-if-xemacs
+     (if (fboundp 'add-submenu)
+	 (progn
+	   (set (make-local-variable 'current-menubar)
+		(copy-sequence current-menubar))
+	   (add-submenu nil term-terminal-menu))))
+    (or term-input-ring
+	(setq term-input-ring (make-ring term-input-ring-size)))
+    (term-update-mode-line))
+
+(if term-mode-map
+    nil
+  (setq term-mode-map (make-sparse-keymap))
+  (define-key term-mode-map "\ep" 'term-previous-input)
+  (define-key term-mode-map "\en" 'term-next-input)
+  (define-key term-mode-map "\er" 'term-previous-matching-input)
+  (define-key term-mode-map "\es" 'term-next-matching-input)
+  (term-ifnot-xemacs
+   (define-key term-mode-map [?\A-\M-r] 'term-previous-matching-input-from-input)
+   (define-key term-mode-map [?\A-\M-s] 'term-next-matching-input-from-input))
+  (define-key term-mode-map "\e\C-l" 'term-show-output)
+  (define-key term-mode-map "\C-m" 'term-send-input)
+  (define-key term-mode-map "\C-d" 'term-delchar-or-maybe-eof)
+  (define-key term-mode-map "\C-c\C-a" 'term-bol)
+  (define-key term-mode-map "\C-c\C-u" 'term-kill-input)
+  (define-key term-mode-map "\C-c\C-w" 'backward-kill-word)
+  (define-key term-mode-map "\C-c\C-c" 'term-interrupt-subjob)
+  (define-key term-mode-map "\C-c\C-z" 'term-stop-subjob)
+  (define-key term-mode-map "\C-c\C-\\" 'term-quit-subjob)
+  (define-key term-mode-map "\C-c\C-m" 'term-copy-old-input)
+  (define-key term-mode-map "\C-c\C-o" 'term-kill-output)
+  (define-key term-mode-map "\C-c\C-r" 'term-show-output)
+  (define-key term-mode-map "\C-c\C-e" 'term-show-maximum-output)
+  (define-key term-mode-map "\C-c\C-l" 'term-dynamic-list-input-ring)
+  (define-key term-mode-map "\C-c\C-n" 'term-next-prompt)
+  (define-key term-mode-map "\C-c\C-p" 'term-previous-prompt)
+  (define-key term-mode-map "\C-c\C-d" 'term-send-eof)
+  (define-key term-mode-map "\C-c\C-k" 'term-char-mode)
+  (define-key term-mode-map "\C-c\C-j" 'term-line-mode)
+  (define-key term-mode-map "\C-c\C-q" 'term-pager-toggle)
+
+  (copy-face 'default 'term-underline-face)
+  (set-face-underline-p 'term-underline-face t)
+
+;  ;; completion:
+;  (define-key term-mode-map [menu-bar completion] 
+;    (cons "Complete" (make-sparse-keymap "Complete")))
+;  (define-key term-mode-map [menu-bar completion complete-expand]
+;    '("Expand File Name" . term-replace-by-expanded-filename))
+;  (define-key term-mode-map [menu-bar completion complete-listing]
+;    '("File Completion Listing" . term-dynamic-list-filename-completions))
+;  (define-key term-mode-map [menu-bar completion complete-file]
+;    '("Complete File Name" . term-dynamic-complete-filename))
+;  (define-key term-mode-map [menu-bar completion complete]
+;    '("Complete Before Point" . term-dynamic-complete))
+;  ;; Put them in the menu bar:
+;  (setq menu-bar-final-items (append '(terminal completion inout signals)
+;				     menu-bar-final-items))
+  )
+
+;; Menu bars:
+(term-ifnot-xemacs
+ (term-if-emacs19
+
+  ;; terminal:
+  (let (newmap)
+    (setq newmap (make-sparse-keymap "Terminal"))
+    (define-key newmap [terminal-pager-enable]
+      '("Enable paging" . term-fake-pager-enable))
+    (define-key newmap [terminal-pager-disable]
+      '("Disable paging" . term-fake-pager-disable))
+    (define-key newmap [terminal-char-mode]
+      '("Character mode" . term-char-mode))
+    (define-key newmap [terminal-line-mode]
+      '("Line mode" . term-line-mode))
+    (define-key newmap [menu-bar terminal] 
+      (setq term-terminal-menu (cons "Terminal" newmap)))
+
+    ;; completion:  (line mode only)
+    (defvar term-completion-menu (make-sparse-keymap "Complete"))
+    (define-key term-mode-map [menu-bar completion] 
+      (cons "Complete" term-completion-menu))
+    (define-key term-completion-menu [complete-expand]
+      '("Expand File Name" . term-replace-by-expanded-filename))
+    (define-key term-completion-menu [complete-listing]
+      '("File Completion Listing" . term-dynamic-list-filename-completions))
+    (define-key term-completion-menu [menu-bar completion complete-file]
+      '("Complete File Name" . term-dynamic-complete-filename))
+    (define-key term-completion-menu [menu-bar completion complete]
+      '("Complete Before Point" . term-dynamic-complete))
+
+    ;; Input history: (line mode only)
+    (defvar term-inout-menu (make-sparse-keymap "In/Out"))
+    (define-key term-mode-map [menu-bar inout] 
+      (cons "In/Out" term-inout-menu))
+    (define-key term-inout-menu [kill-output]
+      '("Kill Current Output Group" . term-kill-output))
+    (define-key term-inout-menu [next-prompt]
+      '("Forward Output Group" . term-next-prompt))
+    (define-key term-inout-menu [previous-prompt]
+      '("Backward Output Group" . term-previous-prompt))
+    (define-key term-inout-menu [show-maximum-output]
+      '("Show Maximum Output" . term-show-maximum-output))
+    (define-key term-inout-menu [show-output]
+      '("Show Current Output Group" . term-show-output))
+    (define-key term-inout-menu [kill-input]
+      '("Kill Current Input" . term-kill-input))
+    (define-key term-inout-menu [copy-input]
+      '("Copy Old Input" . term-copy-old-input))
+    (define-key term-inout-menu [forward-matching-history]
+      '("Forward Matching Input..." . term-forward-matching-input))
+    (define-key term-inout-menu [backward-matching-history]
+      '("Backward Matching Input..." . term-backward-matching-input))
+    (define-key term-inout-menu [next-matching-history]
+      '("Next Matching Input..." . term-next-matching-input))
+    (define-key term-inout-menu [previous-matching-history]
+      '("Previous Matching Input..." . term-previous-matching-input))
+    (define-key term-inout-menu [next-matching-history-from-input]
+      '("Next Matching Current Input" . term-next-matching-input-from-input))
+    (define-key term-inout-menu [previous-matching-history-from-input]
+      '("Previous Matching Current Input" . term-previous-matching-input-from-input))
+    (define-key term-inout-menu [next-history]
+      '("Next Input" . term-next-input))
+    (define-key term-inout-menu [previous-history]
+      '("Previous Input" . term-previous-input))
+    (define-key term-inout-menu [list-history]
+      '("List Input History" . term-dynamic-list-input-ring))
+    (define-key term-inout-menu [expand-history]
+      '("Expand History Before Point" . term-replace-by-expanded-history))
+
+    ;; Signals
+    (setq newmap (make-sparse-keymap "Signals"))
+    (define-key newmap [eof] '("EOF" . term-send-eof))
+    (define-key newmap [kill] '("KILL" . term-kill-subjob))
+    (define-key newmap [quit] '("QUIT" . term-quit-subjob))
+    (define-key newmap [cont] '("CONT" . term-continue-subjob))
+    (define-key newmap [stop] '("STOP" . term-stop-subjob))
+    (define-key newmap [] '("BREAK" . term-interrupt-subjob))
+    (define-key term-mode-map [menu-bar signals]
+      (setq term-signals-menu (cons "Signals" newmap)))
+    )))
+
+(defun term-reset-size (height width)
+  (setq term-height height)
+  (setq term-width width)
+  (setq term-start-line-column nil)
+  (setq term-current-row nil)
+  (setq term-current-column nil)
+  (term-scroll-region 0 height))
+
+;; Recursive routine used to check if any string in term-kill-echo-list
+;; matches part of the buffer before point.
+;; If so, delete that matched part of the buffer - this suppresses echo.
+;; Also, remove that string from the term-kill-echo-list.
+;; We *also* remove any older string on the list, as a sanity measure,
+;; in case something gets out of sync.  (Except for type-ahead, there
+;; should only be one element in the list.)
+
+(defun term-check-kill-echo-list ()
+  (let ((cur term-kill-echo-list) (found nil) (save-point (point)))
+    (unwind-protect
+	(progn
+	  (end-of-line)
+	  (while cur
+	    (let* ((str (car cur)) (len (length str)) (start (- (point) len)))
+	      (if (and (>= start (point-min))
+		       (string= str (buffer-substring start (point))))
+		  (progn (delete-backward-char len)
+			 (setq term-kill-echo-list (cdr cur))
+			 (setq term-current-column nil)
+			 (setq term-current-row nil)
+			 (setq term-start-line-column nil)
+			 (setq cur nil found t))
+		(setq cur (cdr cur))))))
+      (if (not found)
+	  (goto-char save-point)))
+    found))
+
+(defun term-check-size (process)
+  (if (or (/= term-height (1- (window-displayed-height)))
+	  (/= term-width (1- (window-width))))
+      (progn
+	(term-reset-size (1- (window-displayed-height)) (1- (window-width)))
+	(set-process-window-size process term-height term-width))))
+
+(defun term-send-raw-string (chars)
+  (let ((proc (get-buffer-process (current-buffer))))
+    (if (not proc)
+	(error "Current buffer has no process")
+      ;; Note that (term-current-row) must be called *after*
+      ;; (point) has been updated to (process-mark proc).
+      (goto-char (process-mark proc))
+      (if (term-pager-enabled)
+	  (setq term-pager-count (term-current-row)))
+      (process-send-string proc chars))))
+
+(defun term-send-raw ()
+  "Send the last character typed through the terminal-emulator
+without any interpretation." 
+  (interactive)
+
+  (term-if-xemacs
+   (if (key-press-event-p last-input-event)
+       (let ((mods (event-modifiers last-input-event))
+ 	     (key (event-key last-input-event))
+ 	     meta)
+ 	 (if (memq 'meta mods)
+	     (progn
+	       (setq meta t)
+	       (setq mods (delq 'meta mods))))
+	 (let ((ascii (event-to-character (character-to-event
+					   (append mods (list key)))
+					  t ;; lenient
+					  nil ;; no meta mucking
+					  t ;; allow non-ASCII
+					  )))
+	   (cond (ascii
+		  (if meta
+		      (term-send-raw-string (format "\e%c" ascii))
+		    (term-send-raw-string (make-string 1 ascii))))
+		 (t (command-execute (key-binding last-input-event))))))
+     (let ((cmd (lookup-key (current-global-map) (this-command-keys))))
+       (and cmd (call-interactively cmd)))))
+
+  (term-ifnot-xemacs
+   ;; Convert `return' to C-m, etc.
+   (if (and (symbolp last-input-char)
+	    (get last-input-char 'ascii-character))
+       (setq last-input-char (get last-input-char 'ascii-character)))
+   (term-send-raw-string (make-string 1 last-input-char))))
+
+(defun term-mouse-paste (click arg)
+  "Insert the last stretch of killed text at the position clicked on."
+  (interactive "e\nP")
+  (term-if-xemacs
+   (term-send-raw-string (or (condition-case () (x-get-selection) (error ()))
+			     (x-get-cutbuffer)
+			     (error "No selection or cut buffer available"))))
+  (term-ifnot-xemacs
+   ;; Give temporary modes such as isearch a chance to turn off.
+   (run-hooks 'mouse-leave-buffer-hook)
+   (setq this-command 'yank)
+   (term-send-raw-string (current-kill (cond
+					((listp arg) 0)
+					((eq arg '-) -1)
+					(t (1- arg)))))))
+
+;; Which would be better:  "\e[A" or "\eOA"? readline accepts either.
+;; Both xterm and dtterm (CDE) send "\e[A", which argues for that choice.
+;; The xterm termcap claims ku=\EOA; the dtterm terminfo entry says ku=\E[A.
+(defun term-send-up    () (interactive) (term-send-raw-string "\e[A"))
+(defun term-send-down  () (interactive) (term-send-raw-string "\e[B"))
+(defun term-send-right () (interactive) (term-send-raw-string "\e[C"))
+(defun term-send-left  () (interactive) (term-send-raw-string "\e[D"))
+(defun term-send-home  () (interactive) (term-send-raw-string "\e[H"))
+(defun term-send-end   () (interactive) (term-send-raw-string "\eOw"))
+(defun term-send-prior () (interactive) (term-send-raw-string "\e[5~"))
+(defun term-send-next  () (interactive) (term-send-raw-string "\e[6~"))
+(defun term-send-del   () (interactive) (term-send-raw-string "\C-?"))
+(defun term-send-backspace  () (interactive) (term-send-raw-string "\C-H"))
+
+(defun term-set-escape-char (c)
+  "Change term-escape-char and keymaps that depend on it."
+  (if term-escape-char
+      (define-key term-raw-map term-escape-char 'term-send-raw))
+  (setq c (make-string 1 c))
+  (define-key term-raw-map c term-raw-escape-map)
+  ;; Define standard bindings in term-raw-escape-map
+  (define-key term-raw-escape-map "\C-x"
+    (lookup-key (current-global-map) "\C-x"))
+  (define-key term-raw-escape-map "\C-v"
+    (lookup-key (current-global-map) "\C-v"))
+  (define-key term-raw-escape-map "\C-u"
+    (lookup-key (current-global-map) "\C-u"))
+  (define-key term-raw-escape-map c 'term-send-raw)
+  (define-key term-raw-escape-map "\C-q" 'term-pager-toggle)
+  ;; The keybinding for term-char-mode is needed by the menubar code.
+  (define-key term-raw-escape-map "\C-k" 'term-char-mode)
+  (define-key term-raw-escape-map "\C-j" 'term-line-mode))
+    
+(defun term-char-mode ()
+  "Switch to char (\"raw\") sub-mode of term mode.
+Each character you type is sent directly to the inferior without
+intervention from emacs, except for the escape character (usually C-c)."
+  (interactive)
+  (if (not term-raw-map)
+      ;; Initialize term-raw-map.
+      (let* ((map (make-keymap))
+	     (save-meta-prefix-char meta-prefix-char)
+	     (i 0))
+	;; Temporarily disable meta-prefix-char while building keymaps.
+	(setq meta-prefix-char -1)
+	(term-if-xemacs
+	 (set-keymap-default-binding map 'term-send-raw))
+	(term-ifnot-xemacs
+	 (while (< i 128)
+	   (define-key map (make-string 1 i) 'term-send-raw)
+	   (setq i (1+ i))))
+	(setq term-raw-map map)
+	(setq term-raw-escape-map
+	      (copy-keymap (lookup-key (current-global-map) "\C-x")))
+	(define-key term-raw-map [up] 'term-send-up)
+	(define-key term-raw-map [down] 'term-send-down)
+	(define-key term-raw-map [right] 'term-send-right)
+	(define-key term-raw-map [left] 'term-send-left)
+	(define-key term-raw-map [home] 'term-send-home)
+	(define-key term-raw-map [end] 'term-send-end)
+	(define-key term-raw-map [prior] 'term-send-prior)
+	(define-key term-raw-map [next] 'term-send-next)
+	(term-if-xemacs
+	 (define-key term-raw-map [button2] 'term-mouse-paste))
+	(term-ifnot-xemacs
+	 (define-key term-raw-map [mouse-2] 'term-mouse-paste)
+	 (define-key term-raw-map [menu-bar terminal] term-terminal-menu)
+	 (define-key term-raw-map [menu-bar signals] term-signals-menu)
+	 (define-key term-raw-map [delete] 'term-send-del)
+	 (define-key term-raw-map [backspace] 'term-send-backspace))
+	(setq meta-prefix-char save-meta-prefix-char)
+	(term-set-escape-char ?\C-c)))
+  ;; FIXME: Emit message? Cfr ilisp-raw-message
+  (if (term-in-line-mode)
+      (progn
+	(setq term-old-mode-map (current-local-map))
+	(use-local-map term-raw-map)
+
+	;; Send existing partial line to inferior (without newline).
+	(let ((pmark (process-mark (get-buffer-process (current-buffer))))
+	      (save-input-sender term-input-sender))
+	  (if (> (point) pmark)
+	      (unwind-protect
+		  (progn
+		    (setq term-input-sender
+			  (symbol-function 'term-send-string))
+		    (end-of-line)
+		    (term-send-input))
+		(setq term-input-sender save-input-sender))))
+	(term-update-mode-line))))
+
+(defun term-line-mode  ()
+  "Switch to line (\"cooked\") sub-mode of term mode.
+This means that emacs editing commands work as normally, until
+you type \\[term-send-input] which sends the current line to the inferior."
+  (interactive)
+  (if (term-in-char-mode)
+      (progn
+	(use-local-map term-old-mode-map)
+	(term-update-mode-line))))
+
+(defun term-update-mode-line ()
+  (setq mode-line-process
+	(if (term-in-char-mode)
+	    (if (term-pager-enabled) '(": char page %s") '(": char %s"))
+	  (if (term-pager-enabled) '(": line page %s") '(": line %s"))))
+  (force-mode-line-update))
+
+(defun term-check-proc (buffer)
+  "True if there is a process associated w/buffer BUFFER, and
+it is alive (status RUN or STOP). BUFFER can be either a buffer or the
+name of one"
+  (let ((proc (get-buffer-process buffer)))
+    (and proc (memq (process-status proc) '(run stop)))))
+
+;;; Note that this guy, unlike shell.el's make-shell, barfs if you pass it ()
+;;; for the second argument (program).
+;;;###autoload
+(defun make-term (name program &optional startfile &rest switches)
+  "Make a term process NAME in a buffer, running PROGRAM.
+The name of the buffer is made by surrounding NAME with `*'s.
+If there is already a running process in that buffer, it is not restarted.
+Optional third arg STARTFILE is the name of a file to send the contents of to 
+the process.  Any more args are arguments to PROGRAM."
+  (let ((buffer (get-buffer-create (concat "*" name "*"))))
+    ;; If no process, or nuked process, crank up a new one and put buffer in
+    ;; term mode. Otherwise, leave buffer and existing process alone.
+    (cond ((not (term-check-proc buffer))
+	   (save-excursion
+	     (set-buffer buffer)
+	     (term-mode)) ; Install local vars, mode, keymap, ...
+	   (term-exec buffer name program startfile switches)))
+    buffer))
+
+;;;###autoload
+(defun term (program)
+  "Start a terminal-emulator in a new buffer."
+  (interactive (list (read-from-minibuffer "Run program: "
+					   (or explicit-shell-file-name
+					       (getenv "ESHELL")
+					       (getenv "SHELL")
+					       "/bin/sh"))))
+  (set-buffer (make-term "terminal" program))
+  (term-mode)
+  (term-char-mode)
+  (switch-to-buffer "*terminal*"))
+
+(defun term-exec (buffer name command startfile switches)
+  "Start up a process in buffer for term modes.
+Blasts any old process running in the buffer. Doesn't set the buffer mode.
+You can use this to cheaply run a series of processes in the same term
+buffer. The hook term-exec-hook is run after each exec."
+  (save-excursion
+    (set-buffer buffer)
+    (let ((proc (get-buffer-process buffer)))	; Blast any old process.
+      (if proc (delete-process proc)))
+    ;; Crank up a new process
+    (let ((proc (term-exec-1 name buffer command switches)))
+      (make-local-variable 'term-ptyp)
+      (setq term-ptyp process-connection-type) ; T if pty, NIL if pipe.
+      ;; Jump to the end, and set the process mark.
+      (goto-char (point-max))
+      (set-marker (process-mark proc) (point))
+      (set-process-filter proc 'term-emulate-terminal)
+      ;; Feed it the startfile.
+      (cond (startfile
+	     ;;This is guaranteed to wait long enough
+	     ;;but has bad results if the term does not prompt at all
+	     ;;	     (while (= size (buffer-size))
+	     ;;	       (sleep-for 1))
+	     ;;I hope 1 second is enough!
+	     (sleep-for 1)
+	     (goto-char (point-max))
+	     (insert-file-contents startfile)
+	     (setq startfile (buffer-substring (point) (point-max)))
+	     (delete-region (point) (point-max))
+	     (term-send-string proc startfile)))
+    (run-hooks 'term-exec-hook)
+    buffer)))
+
+;;; Name to use for TERM.
+;;; Using "emacs" loses, because bash disables editing if TERM == emacs.
+(defvar term-term-name "eterm")
+; Format string, usage: (format term-termcap-string emacs-term-name "TERMCAP=" 24 80)
+(defvar term-termcap-format
+  "%s%s:li#%d:co#%d:cl=\\E[H\\E[J:cd=\\E[J:bs:am:xn:cm=\\E[%%i%%d;%%dH\
+:nd=\\E[C:up=\\E[A:ce=\\E[K:ho=\\E[H:pt\
+:al=\\E[L:dl=\\E[M:DL=\\E[%%dM:AL=\\E[%%dL:cs=\\E[%%i%%d;%%dr:sf=\\n\
+:te=\\E[2J\\E[?47l\\E8:ti=\\E7\\E[?47h\
+:dc=\\E[P:DC=\\E[%%dP:IC=\\E[%%d@:im=\\E[4h:ei=\\E[4l:mi\
+:kd=\\E[B:kl=\\E[D:kr=\\E[C:ku=\\E[A\
+:so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:md=\\E[1m:mr=\\E[7m:me=\\E[m\
+:UP=\\E[%%dA:DO=\\E[%%dB:LE=\\E[%%dD:RI=\\E[%%dC"
+;;; : -undefine ic
+  "termcap capabilities supported")
+
+;;; This auxiliary function cranks up the process for term-exec in
+;;; the appropriate environment.
+
+(defun term-exec-1 (name buffer command switches)
+  ;; We need to do an extra (fork-less) exec to run stty.
+  ;; (This would not be needed if we had suitable emacs primitives.)
+  ;; The 'if ...; then shift; fi' hack is because Bourne shell
+  ;; loses one arg when called with -c, and newer shells (bash,  ksh) don't.
+  ;; Thus we add an extra dummy argument "..", and then remove it.
+  (let ((process-environment
+	 (nconc
+	  (list
+	   (format "TERM=%s" term-term-name)
+	   (if (and (boundp 'system-uses-terminfo) system-uses-terminfo)
+	       (format "TERMINFO=%s" (locate-data-directory "eterm"))
+	    (format term-termcap-format "TERMCAP="
+		    term-term-name term-height term-width))
+	   (format "EMACS=%s (term:%s)" emacs-version term-protocol-version)
+	   (format "LINES=%d" term-height)
+	   (format "COLUMNS=%d" term-width))
+	  process-environment)))
+    (apply 'start-process name buffer
+	   "/bin/sh" "-c"
+	   (format "stty -nl echo rows %d columns %d sane 2>/dev/null;\
+if [ $1 = .. ]; then shift; fi; exec \"$@\""
+		   term-height term-width)
+	   ".."
+	   command switches)))
+
+;;; This should be in emacs, but it isn't.
+(defun term-mem (item list &optional elt=)
+  "Test to see if ITEM is equal to an item in LIST.
+Option comparison function ELT= defaults to equal."
+  (let ((elt= (or elt= (function equal)))
+	(done nil))
+    (while (and list (not done))
+      (if (funcall elt= item (car list))
+	  (setq done list)
+	  (setq list (cdr list))))
+    done))
+
+
+;;; Input history processing in a buffer
+;;; ===========================================================================
+;;; Useful input history functions, courtesy of the Ergo group.
+
+;;; Eleven commands:
+;;; term-dynamic-list-input-ring	List history in help buffer.
+;;; term-previous-input		Previous input...
+;;; term-previous-matching-input	...matching a string.
+;;; term-previous-matching-input-from-input ... matching the current input.
+;;; term-next-input			Next input...
+;;; term-next-matching-input		...matching a string.
+;;; term-next-matching-input-from-input     ... matching the current input.
+;;; term-backward-matching-input      Backwards input...
+;;; term-forward-matching-input       ...matching a string.
+;;; term-replace-by-expanded-history	Expand history at point;
+;;;					replace with expanded history.
+;;; term-magic-space			Expand history and insert space.
+;;;
+;;; Three functions:
+;;; term-read-input-ring              Read into term-input-ring...
+;;; term-write-input-ring             Write to term-input-ring-file-name.
+;;; term-replace-by-expanded-history-before-point Workhorse function.
+
+(defun term-read-input-ring (&optional silent)
+  "Sets the buffer's `term-input-ring' from a history file.
+The name of the file is given by the variable `term-input-ring-file-name'.
+The history ring is of size `term-input-ring-size', regardless of file size.
+If `term-input-ring-file-name' is nil this function does nothing.
+
+If the optional argument SILENT is non-nil, we say nothing about a
+failure to read the history file.
+
+This function is useful for major mode commands and mode hooks.
+
+The structure of the history file should be one input command per line,
+with the most recent command last.
+See also `term-input-ignoredups' and `term-write-input-ring'."
+  (cond ((or (null term-input-ring-file-name)
+	     (equal term-input-ring-file-name ""))
+	 nil)
+	((not (file-readable-p term-input-ring-file-name))
+	 (or silent
+	     (message "Cannot read history file %s"
+		      term-input-ring-file-name)))
+	(t
+	 (let ((history-buf (get-buffer-create " *temp*"))
+	       (file term-input-ring-file-name)
+	       (count 0)
+	       (ring (make-ring term-input-ring-size)))
+	   (unwind-protect
+	       (save-excursion
+		 (set-buffer history-buf)
+		 (widen)
+		 (erase-buffer)
+		 (insert-file-contents file)
+		 ;; Save restriction in case file is already visited...
+		 ;; Watch for those date stamps in history files!
+		 (goto-char (point-max))
+		 (while (and (< count term-input-ring-size)
+			     (re-search-backward "^[ \t]*\\([^#\n].*\\)[ \t]*$"
+						 nil t))
+		   (let ((history (buffer-substring (match-beginning 1)
+						    (match-end 1))))
+		     (if (or (null term-input-ignoredups)
+			     (ring-empty-p ring)
+			     (not (string-equal (ring-ref ring 0) history)))
+			 (ring-insert-at-beginning ring history)))
+		   (setq count (1+ count))))
+	     (kill-buffer history-buf))
+	   (setq term-input-ring ring
+		 term-input-ring-index nil)))))
+
+(defun term-write-input-ring ()
+  "Writes the buffer's `term-input-ring' to a history file.
+The name of the file is given by the variable `term-input-ring-file-name'.
+The original contents of the file are lost if `term-input-ring' is not empty.
+If `term-input-ring-file-name' is nil this function does nothing.
+
+Useful within process sentinels.
+
+See also `term-read-input-ring'."
+  (cond ((or (null term-input-ring-file-name)
+	     (equal term-input-ring-file-name "")
+	     (null term-input-ring) (ring-empty-p term-input-ring))
+	 nil)
+	((not (file-writable-p term-input-ring-file-name))
+	 (message "Cannot write history file %s" term-input-ring-file-name))
+	(t
+	 (let* ((history-buf (get-buffer-create " *Temp Input History*"))
+		(ring term-input-ring)
+		(file term-input-ring-file-name)
+		(index (ring-length ring)))
+	   ;; Write it all out into a buffer first.  Much faster, but messier,
+	   ;; than writing it one line at a time.
+	   (save-excursion
+	     (set-buffer history-buf)
+	     (erase-buffer)
+	     (while (> index 0)
+	       (setq index (1- index))
+	       (insert (ring-ref ring index) ?\n))
+	     (write-region (buffer-string) nil file nil 'no-message)
+	     (kill-buffer nil))))))
+
+
+(defun term-dynamic-list-input-ring ()
+  "List in help buffer the buffer's input history."
+  (interactive)
+  (if (or (not (ring-p term-input-ring))
+	  (ring-empty-p term-input-ring))
+      (message "No history")
+    (let ((history nil)
+	  (history-buffer " *Input History*")
+	  (index (1- (ring-length term-input-ring)))
+	  (conf (current-window-configuration)))
+      ;; We have to build up a list ourselves from the ring vector.
+      (while (>= index 0)
+	(setq history (cons (ring-ref term-input-ring index) history)
+	      index (1- index)))
+      ;; Change "completion" to "history reference"
+      ;; to make the display accurate.
+      (with-output-to-temp-buffer history-buffer
+	(display-completion-list history)
+	(set-buffer history-buffer)
+	(forward-line 3)
+	(while (search-backward "completion" nil 'move)
+	  (replace-match "history reference")))
+      (sit-for 0)
+      (message "Hit space to flush")
+      (let ((ch (read-event)))
+	(if (eq ch ?\ )
+	    (set-window-configuration conf)
+	  (setq unread-command-events (list ch)))))))
+
+
+(defun term-regexp-arg (prompt)
+  ;; Return list of regexp and prefix arg using PROMPT.
+  (let* ((minibuffer-history-sexp-flag nil)
+	 ;; Don't clobber this.
+	 (last-command last-command)
+	 (regexp (read-from-minibuffer prompt nil nil nil
+				       'minibuffer-history-search-history)))
+    (list (if (string-equal regexp "")
+	      (setcar minibuffer-history-search-history
+		      (nth 1 minibuffer-history-search-history))
+	    regexp)
+	  (prefix-numeric-value current-prefix-arg))))
+
+(defun term-search-arg (arg)
+  ;; First make sure there is a ring and that we are after the process mark
+  (cond ((not (term-after-pmark-p))
+	 (error "Not at command line"))
+	((or (null term-input-ring)
+	     (ring-empty-p term-input-ring))
+	 (error "Empty input ring"))
+	((zerop arg)
+	 ;; arg of zero resets search from beginning, and uses arg of 1
+	 (setq term-input-ring-index nil)
+	 1)
+	(t
+	 arg)))
+
+(defun term-search-start (arg)
+  ;; Index to start a directional search, starting at term-input-ring-index
+  (if term-input-ring-index
+      ;; If a search is running, offset by 1 in direction of arg
+      (mod (+ term-input-ring-index (if (> arg 0) 1 -1))
+	   (ring-length term-input-ring))
+    ;; For a new search, start from beginning or end, as appropriate
+    (if (>= arg 0)
+	0				       ; First elt for forward search
+      (1- (ring-length term-input-ring)))))  ; Last elt for backward search
+
+(defun term-previous-input-string (arg)
+  "Return the string ARG places along the input ring.
+Moves relative to `term-input-ring-index'."
+  (ring-ref term-input-ring (if term-input-ring-index
+				  (mod (+ arg term-input-ring-index) 
+				       (ring-length term-input-ring))
+				arg)))
+
+(defun term-previous-input (arg)
+  "Cycle backwards through input history."
+  (interactive "*p")
+  (term-previous-matching-input "." arg))
+
+(defun term-next-input (arg)
+  "Cycle forwards through input history."
+  (interactive "*p")
+  (term-previous-input (- arg)))
+
+(defun term-previous-matching-input-string (regexp arg)
+  "Return the string matching REGEXP ARG places along the input ring.
+Moves relative to `term-input-ring-index'."
+  (let* ((pos (term-previous-matching-input-string-position regexp arg)))
+    (if pos (ring-ref term-input-ring pos))))
+
+(defun term-previous-matching-input-string-position (regexp arg &optional start)
+  "Return the index matching REGEXP ARG places along the input ring.
+Moves relative to START, or `term-input-ring-index'."
+  (if (or (not (ring-p term-input-ring))
+	  (ring-empty-p term-input-ring))
+      (error "No history"))
+  (let* ((len (ring-length term-input-ring))
+	 (motion (if (> arg 0) 1 -1))
+	 (n (mod (- (or start (term-search-start arg)) motion) len))
+	 (tried-each-ring-item nil)
+	 (prev nil))
+    ;; Do the whole search as many times as the argument says.
+    (while (and (/= arg 0) (not tried-each-ring-item))
+      ;; Step once.
+      (setq prev n
+	    n (mod (+ n motion) len))
+      ;; If we haven't reached a match, step some more.
+      (while (and (< n len) (not tried-each-ring-item)
+		  (not (string-match regexp (ring-ref term-input-ring n))))
+	(setq n (mod (+ n motion) len)
+	      ;; If we have gone all the way around in this search.
+	      tried-each-ring-item (= n prev)))
+      (setq arg (if (> arg 0) (1- arg) (1+ arg))))
+    ;; Now that we know which ring element to use, if we found it, return that.
+    (if (string-match regexp (ring-ref term-input-ring n))
+	n)))
+
+(defun term-previous-matching-input (regexp arg)
+  "Search backwards through input history for match for REGEXP.
+\(Previous history elements are earlier commands.)
+With prefix argument N, search for Nth previous match.
+If N is negative, find the next or Nth next match."
+  (interactive (term-regexp-arg "Previous input matching (regexp): "))
+  (setq arg (term-search-arg arg))
+  (let ((pos (term-previous-matching-input-string-position regexp arg)))
+    ;; Has a match been found?
+    (if (null pos)
+	(error "Not found")
+      (setq term-input-ring-index pos)
+      (message "History item: %d" (1+ pos))
+      (delete-region 
+       ;; Can't use kill-region as it sets this-command
+       (process-mark (get-buffer-process (current-buffer))) (point))
+      (insert (ring-ref term-input-ring pos)))))
+
+(defun term-next-matching-input (regexp arg)
+  "Search forwards through input history for match for REGEXP.
+\(Later history elements are more recent commands.)
+With prefix argument N, search for Nth following match.
+If N is negative, find the previous or Nth previous match."
+  (interactive (term-regexp-arg "Next input matching (regexp): "))
+  (term-previous-matching-input regexp (- arg)))
+
+(defun term-previous-matching-input-from-input (arg)
+  "Search backwards through input history for match for current input.
+\(Previous history elements are earlier commands.)
+With prefix argument N, search for Nth previous match.
+If N is negative, search forwards for the -Nth following match."
+  (interactive "p")
+  (if (not (memq last-command '(term-previous-matching-input-from-input
+				term-next-matching-input-from-input)))
+      ;; Starting a new search
+      (setq term-matching-input-from-input-string
+	    (buffer-substring 
+	     (process-mark (get-buffer-process (current-buffer))) 
+	     (point))
+	    term-input-ring-index nil))
+  (term-previous-matching-input
+   (concat "^" (regexp-quote term-matching-input-from-input-string))
+   arg))
+
+(defun term-next-matching-input-from-input (arg)
+  "Search forwards through input history for match for current input.
+\(Following history elements are more recent commands.)
+With prefix argument N, search for Nth following match.
+If N is negative, search backwards for the -Nth previous match."
+  (interactive "p")
+  (term-previous-matching-input-from-input (- arg)))
+
+
+(defun term-replace-by-expanded-history (&optional silent)
+  "Expand input command history references before point.
+Expansion is dependent on the value of `term-input-autoexpand'.
+
+This function depends on the buffer's idea of the input history, which may not
+match the command interpreter's idea, assuming it has one.
+
+Assumes history syntax is like typical Un*x shells'.  However, since emacs
+cannot know the interpreter's idea of input line numbers, assuming it has one,
+it cannot expand absolute input line number references.
+
+If the optional argument SILENT is non-nil, never complain
+even if history reference seems erroneous.
+
+See `term-magic-space' and `term-replace-by-expanded-history-before-point'.
+
+Returns t if successful."
+  (interactive)
+  (if (and term-input-autoexpand
+	   (string-match "[!^]" (funcall term-get-old-input))
+	   (save-excursion (beginning-of-line)
+			   (looking-at term-prompt-regexp)))
+      ;; Looks like there might be history references in the command.
+      (let ((previous-modified-tick (buffer-modified-tick)))
+	(message "Expanding history references...")
+	(term-replace-by-expanded-history-before-point silent)
+	(/= previous-modified-tick (buffer-modified-tick)))))
+
+
+(defun term-replace-by-expanded-history-before-point (silent)
+  "Expand directory stack reference before point.
+See `term-replace-by-expanded-history'.  Returns t if successful."
+  (save-excursion
+    (let ((toend (- (save-excursion (end-of-line nil) (point)) (point)))
+	  (start (progn (term-bol nil) (point))))
+      (while (progn
+	       (skip-chars-forward "^!^"
+				   (save-excursion
+				     (end-of-line nil) (- (point) toend)))
+	       (< (point)
+		  (save-excursion
+		    (end-of-line nil) (- (point) toend))))
+	;; This seems a bit complex.  We look for references such as !!, !-num,
+	;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^.
+	;; If that wasn't enough, the plings can be suffixed with argument
+	;; range specifiers.
+	;; Argument ranges are complex too, so we hive off the input line,
+	;; referenced with plings, with the range string to `term-args'.
+	(setq term-input-ring-index nil)
+	(cond ((or (= (preceding-char) ?\\)
+		   (term-within-quotes start (point)))
+	       ;; The history is quoted, or we're in quotes.
+	       (goto-char (1+ (point))))
+	      ((looking-at "![0-9]+\\($\\|[^-]\\)")
+	       ;; We cannot know the interpreter's idea of input line numbers.
+	       (goto-char (match-end 0))
+	       (message "Absolute reference cannot be expanded"))
+	      ((looking-at "!-\\([0-9]+\\)\\(:?[0-9^$*-]+\\)?")
+	       ;; Just a number of args from `number' lines backward.
+	       (let ((number (1- (string-to-number
+				  (buffer-substring (match-beginning 1)
+						    (match-end 1))))))
+		 (if (<= number (ring-length term-input-ring))
+		     (progn
+		       (replace-match
+			(term-args (term-previous-input-string number)
+				     (match-beginning 2) (match-end 2))
+			t t)
+		       (setq term-input-ring-index number)
+		       (message "History item: %d" (1+ number)))
+		   (goto-char (match-end 0))
+		   (message "Relative reference exceeds input history size"))))
+	      ((or (looking-at "!!?:?\\([0-9^$*-]+\\)") (looking-at "!!"))
+	       ;; Just a number of args from the previous input line.
+	       (replace-match
+		(term-args (term-previous-input-string 0)
+			     (match-beginning 1) (match-end 1))
+		t t)
+	       (message "History item: previous"))
+	      ((looking-at
+		"!\\??\\({\\(.+\\)}\\|\\(\\sw+\\)\\)\\(:?[0-9^$*-]+\\)?")
+	       ;; Most recent input starting with or containing (possibly
+	       ;; protected) string, maybe just a number of args.  Phew.
+	       (let* ((mb1 (match-beginning 1)) (me1 (match-end 1))
+		      (mb2 (match-beginning 2)) (me2 (match-end 2))
+		      (exp (buffer-substring (or mb2 mb1) (or me2 me1)))
+		      (pref (if (save-match-data (looking-at "!\\?")) "" "^"))
+		      (pos (save-match-data
+			     (term-previous-matching-input-string-position
+			      (concat pref (regexp-quote exp)) 1))))
+		 (if (null pos)
+		     (progn
+		       (goto-char (match-end 0))
+		       (or silent
+			   (progn (message "Not found")
+				  (ding))))
+		   (setq term-input-ring-index pos)
+		   (replace-match
+		    (term-args (ring-ref term-input-ring pos)
+				 (match-beginning 4) (match-end 4))
+		    t t)
+		   (message "History item: %d" (1+ pos)))))
+	      ((looking-at "\\^\\([^^]+\\)\\^?\\([^^]*\\)\\^?")
+	       ;; Quick substitution on the previous input line.
+	       (let ((old (buffer-substring (match-beginning 1) (match-end 1)))
+		     (new (buffer-substring (match-beginning 2) (match-end 2)))
+		     (pos nil))
+		 (replace-match (term-previous-input-string 0) t t)
+		 (setq pos (point))
+		 (goto-char (match-beginning 0))
+		 (if (not (search-forward old pos t))
+		     (or silent
+			 (error "Not found"))
+		   (replace-match new t t)
+		   (message "History item: substituted"))))
+	      (t
+	       (goto-char (match-end 0))))))))
+
+
+(defun term-magic-space (arg)
+  "Expand input history references before point and insert ARG spaces.
+A useful command to bind to SPC.  See `term-replace-by-expanded-history'."
+  (interactive "p")
+  (term-replace-by-expanded-history)
+  (self-insert-command arg))
+
+(defun term-within-quotes (beg end)
+  "Return t if the number of quotes between BEG and END is odd.
+Quotes are single and double."
+  (let ((countsq (term-how-many-region "\\(^\\|[^\\\\]\\)\'" beg end))
+	(countdq (term-how-many-region "\\(^\\|[^\\\\]\\)\"" beg end)))
+    (or (= (mod countsq 2) 1) (= (mod countdq 2) 1))))
+
+(defun term-how-many-region (regexp beg end)
+  "Return number of matches for REGEXP from BEG to END."
+  (let ((count 0))
+    (save-excursion
+      (save-match-data
+	(goto-char beg)
+	(while (re-search-forward regexp end t)
+	  (setq count (1+ count)))))
+    count))
+
+(defun term-args (string begin end)
+  ;; From STRING, return the args depending on the range specified in the text
+  ;; from BEGIN to END.  If BEGIN is nil, assume all args.  Ignore leading `:'.
+  ;; Range can be x-y, x-, -y, where x/y can be [0-9], *, ^, $.
+  (save-match-data
+    (if (null begin)
+	(term-arguments string 0 nil)
+      (let* ((range (buffer-substring
+		     (if (eq (char-after begin) ?:) (1+ begin) begin) end))
+	     (nth (cond ((string-match "^[*^]" range) 1)
+			((string-match "^-" range) 0)
+			((string-equal range "$") nil)
+			(t (string-to-number range))))
+	     (mth (cond ((string-match "[-*$]$" range) nil)
+			((string-match "-" range)
+			 (string-to-number (substring range (match-end 0))))
+			(t nth))))
+	(term-arguments string nth mth)))))
+
+;; Return a list of arguments from ARG.  Break it up at the
+;; delimiters in term-delimiter-argument-list.  Returned list is backwards.
+(defun term-delim-arg (arg)
+  (if (null term-delimiter-argument-list)
+      (list arg)
+    (let ((args nil)
+	  (pos 0)
+	  (len (length arg)))
+      (while (< pos len)
+	(let ((char (aref arg pos))
+	      (start pos))
+	  (if (memq char term-delimiter-argument-list)
+	      (while (and (< pos len) (eq (aref arg pos) char))
+		(setq pos (1+ pos)))
+	    (while (and (< pos len)
+			(not (memq (aref arg pos)
+				   term-delimiter-argument-list)))
+	      (setq pos (1+ pos))))
+	  (setq args (cons (substring arg start pos) args))))
+      args)))
+
+(defun term-arguments (string nth mth)
+  "Return from STRING the NTH to MTH arguments.
+NTH and/or MTH can be nil, which means the last argument.
+Returned arguments are separated by single spaces.
+We assume whitespace separates arguments, except within quotes.
+Also, a run of one or more of a single character
+in `term-delimiter-argument-list' is a separate argument.
+Argument 0 is the command name."
+  (let ((argpart "[^ \n\t\"'`]+\\|\\(\"[^\"]*\"\\|'[^']*'\\|`[^`]*`\\)")
+	(args ()) (pos 0)
+	(count 0)
+	beg str quotes)
+    ;; Build a list of all the args until we have as many as we want.
+    (while (and (or (null mth) (<= count mth))
+		(string-match argpart string pos))
+      (if (and beg (= pos (match-beginning 0)))
+	  ;; It's contiguous, part of the same arg.
+	  (setq pos (match-end 0)
+		quotes (or quotes (match-beginning 1)))
+	;; It's a new separate arg.
+	(if beg
+	    ;; Put the previous arg, if there was one, onto ARGS.
+	    (setq str (substring string beg pos)
+		  args (if quotes (cons str args)
+			 (nconc (term-delim-arg str) args))
+		  count (1+ count)))
+	(setq quotes (match-beginning 1))
+	(setq beg (match-beginning 0))
+	(setq pos (match-end 0))))
+    (if beg
+	(setq str (substring string beg pos)
+	      args (if quotes (cons str args)
+		     (nconc (term-delim-arg str) args))
+	      count (1+ count)))
+    (let ((n (or nth (1- count)))
+	  (m (if mth (1- (- count mth)) 0)))
+      (mapconcat
+       (function (lambda (a) a)) (nthcdr n (nreverse (nthcdr m args))) " "))))
+
+;;;
+;;; Input processing stuff [line mode]
+;;;
+
+(defun term-send-input () 
+  "Send input to process.
+After the process output mark, sends all text from the process mark to
+point as input to the process.  Before the process output mark, calls value
+of variable term-get-old-input to retrieve old input, copies it to the
+process mark, and sends it.  A terminal newline is also inserted into the
+buffer and sent to the process.  The list of function names contained in the
+value of `term-input-filter-functions' is called on the input before sending
+it.  The input is entered into the input history ring, if the value of variable
+term-input-filter returns non-nil when called on the input.
+
+Any history reference may be expanded depending on the value of the variable
+`term-input-autoexpand'.  The list of function names contained in the value
+of `term-input-filter-functions' is called on the input before sending it.
+The input is entered into the input history ring, if the value of variable
+`term-input-filter' returns non-nil when called on the input.
+
+If variable `term-eol-on-send' is non-nil, then point is moved to the
+end of line before sending the input.
+
+The values of `term-get-old-input', `term-input-filter-functions', and
+`term-input-filter' are chosen according to the command interpreter running
+in the buffer.  E.g.,
+
+If the interpreter is the csh,
+    term-get-old-input is the default: take the current line, discard any
+        initial string matching regexp term-prompt-regexp.
+    term-input-filter-functions monitors input for \"cd\", \"pushd\", and
+	\"popd\" commands. When it sees one, it cd's the buffer.
+    term-input-filter is the default: returns T if the input isn't all white
+	space.
+
+If the term is Lucid Common Lisp, 
+    term-get-old-input snarfs the sexp ending at point.
+    term-input-filter-functions does nothing.
+    term-input-filter returns NIL if the input matches input-filter-regexp,
+        which matches (1) all whitespace (2) :a, :c, etc.
+
+Similarly for Soar, Scheme, etc."
+  (interactive)
+  ;; Note that the input string does not include its terminal newline.
+  (let ((proc (get-buffer-process (current-buffer))))
+    (if (not proc) (error "Current buffer has no process")
+      (let* ((pmark (process-mark proc))
+	     (pmark-val (marker-position pmark))
+	     (input-is-new (>= (point) pmark-val))
+	     (intxt (if input-is-new
+			(progn (if term-eol-on-send (end-of-line))
+			       (buffer-substring pmark (point)))
+		      (funcall term-get-old-input)))
+	     (input (if (not (eq term-input-autoexpand 'input))
+			;; Just whatever's already there
+			intxt
+		      ;; Expand and leave it visible in buffer
+		      (term-replace-by-expanded-history t)
+		      (buffer-substring pmark (point))))
+	     (history (if (not (eq term-input-autoexpand 'history))
+			  input
+			;; This is messy 'cos ultimately the original
+			;; functions used do insertion, rather than return
+			;; strings.  We have to expand, then insert back.
+			(term-replace-by-expanded-history t)
+			(let ((copy (buffer-substring pmark (point))))
+			  (delete-region pmark (point))
+			  (insert input)
+			  copy))))
+	(if (term-pager-enabled)
+	    (save-excursion
+	      (goto-char (process-mark proc))
+	      (setq term-pager-count (term-current-row))))
+	(if (and (funcall term-input-filter history)
+		 (or (null term-input-ignoredups)
+		     (not (ring-p term-input-ring))
+		     (ring-empty-p term-input-ring)
+		     (not (string-equal (ring-ref term-input-ring 0)
+					history))))
+	    (ring-insert term-input-ring history))
+	(let ((functions term-input-filter-functions))
+	  (while functions
+	    (funcall (car functions) (concat input "\n"))
+	    (setq functions (cdr functions))))
+	(setq term-input-ring-index nil)
+
+	;; Update the markers before we send the input
+	;; in case we get output amidst sending the input.
+	(set-marker term-last-input-start pmark)
+	(set-marker term-last-input-end (point))
+	(if input-is-new
+	    (progn
+	      ;; Set up to delete, because inferior should echo.
+	      (if (marker-buffer term-pending-delete-marker)
+		  (delete-region term-pending-delete-marker pmark))
+	      (set-marker term-pending-delete-marker pmark-val)
+	      (set-marker (process-mark proc) (point))))
+	(goto-char pmark)
+	(funcall term-input-sender proc input)))))
+
+(defun term-get-old-input-default ()
+  "Default for term-get-old-input.
+Take the current line, and discard any initial text matching
+term-prompt-regexp."
+  (save-excursion
+    (beginning-of-line)
+    (term-skip-prompt)
+    (let ((beg (point)))
+      (end-of-line)
+      (buffer-substring beg (point)))))
+
+(defun term-copy-old-input ()
+  "Insert after prompt old input at point as new input to be edited.
+Calls `term-get-old-input' to get old input."
+  (interactive)
+  (let ((input (funcall term-get-old-input))
+ 	(process (get-buffer-process (current-buffer))))
+    (if (not process)
+	(error "Current buffer has no process")
+      (goto-char (process-mark process))
+      (insert input))))
+
+(defun term-skip-prompt ()
+  "Skip past the text matching regexp term-prompt-regexp. 
+If this takes us past the end of the current line, don't skip at all."
+  (let ((eol (save-excursion (end-of-line) (point))))
+    (if (and (looking-at term-prompt-regexp)
+	     (<= (match-end 0) eol))
+	(goto-char (match-end 0)))))
+
+
+(defun term-after-pmark-p ()
+  "Is point after the process output marker?"
+  ;; Since output could come into the buffer after we looked at the point
+  ;; but before we looked at the process marker's value, we explicitly 
+  ;; serialise. This is just because I don't know whether or not emacs
+  ;; services input during execution of lisp commands.
+  (let ((proc-pos (marker-position
+		   (process-mark (get-buffer-process (current-buffer))))))
+    (<= proc-pos (point))))
+
+(defun term-simple-send (proc string)
+  "Default function for sending to PROC input STRING.
+This just sends STRING plus a newline. To override this,
+set the hook TERM-INPUT-SENDER."
+  (term-send-string proc string)
+  (term-send-string proc "\n"))
+
+(defun term-bol (arg)
+  "Goes to the beginning of line, then skips past the prompt, if any.
+If a prefix argument is given (\\[universal-argument]), then no prompt skip 
+-- go straight to column 0.
+
+The prompt skip is done by skipping text matching the regular expression
+term-prompt-regexp, a buffer local variable."
+  (interactive "P")
+  (beginning-of-line)
+  (if (null arg) (term-skip-prompt)))
+
+;;; These two functions are for entering text you don't want echoed or
+;;; saved -- typically passwords to ftp, telnet, or somesuch.
+;;; Just enter m-x term-send-invisible and type in your line.
+
+(defun term-read-noecho (prompt &optional stars)
+  "Read a single line of text from user without echoing, and return it. 
+Prompt with argument PROMPT, a string.  Optional argument STARS causes
+input to be echoed with '*' characters on the prompt line.  Input ends with
+RET, LFD, or ESC.  DEL or C-h rubs out.  C-u kills line.  C-g aborts (if
+`inhibit-quit' is set because e.g. this function was called from a process
+filter and C-g is pressed, this function returns nil rather than a string).
+
+Note that the keystrokes comprising the text can still be recovered
+\(temporarily) with \\[view-lossage].  This may be a security bug for some
+applications."
+  (let ((ans "")
+	(c 0)
+	(echo-keystrokes 0)
+	(cursor-in-echo-area t)
+        (done nil))
+    (while (not done)
+      (if stars
+          (message "%s%s" prompt (make-string (length ans) ?*))
+        (message "%s" prompt))
+      (setq c (read-char))
+      (cond ((= c ?\C-g)
+             ;; This function may get called from a process filter, where
+             ;; inhibit-quit is set.  In later versions of emacs read-char
+             ;; may clear quit-flag itself and return C-g.  That would make
+             ;; it impossible to quit this loop in a simple way, so
+             ;; re-enable it here (for backward-compatibility the check for
+             ;; quit-flag below would still be necessary, so this seems
+             ;; like the simplest way to do things).
+             (setq quit-flag t
+                   done t))
+            ((or (= c ?\r) (= c ?\n) (= c ?\e))
+             (setq done t))
+            ((= c ?\C-u)
+             (setq ans ""))
+            ((and (/= c ?\b) (/= c ?\177))
+             (setq ans (concat ans (char-to-string c))))
+            ((> (length ans) 0)
+             (setq ans (substring ans 0 -1)))))
+    (if quit-flag
+        ;; Emulate a true quit, except that we have to return a value.
+        (prog1
+            (setq quit-flag nil)
+          (message "Quit")
+          (beep t))
+      (message "")
+      ans)))
+
+(defun term-send-invisible (str &optional proc)
+  "Read a string without echoing.
+Then send it to the process running in the current buffer. A new-line
+is additionally sent. String is not saved on term input history list.
+Security bug: your string can still be temporarily recovered with
+\\[view-lossage]."
+  (interactive "P") ; Defeat snooping via C-x esc
+  (if (not (stringp str))
+      (setq str (term-read-noecho "Non-echoed text: " t)))
+  (if (not proc)
+      (setq proc (get-buffer-process (current-buffer))))
+  (if (not proc) (error "Current buffer has no process")
+    (setq term-kill-echo-list (nconc term-kill-echo-list
+				     (cons str nil)))
+    (term-send-string proc str)
+    (term-send-string proc "\n")))
+
+
+;;; Low-level process communication
+
+(defvar term-input-chunk-size 512
+  "*Long inputs send to term processes are broken up into chunks of this size.
+If your process is choking on big inputs, try lowering the value.")
+
+(defun term-send-string (proc str)
+  "Send PROCESS the contents of STRING as input.
+This is equivalent to process-send-string, except that long input strings
+are broken up into chunks of size term-input-chunk-size. Processes
+are given a chance to output between chunks. This can help prevent processes
+from hanging when you send them long inputs on some OS's."
+  (let* ((len (length str))
+	 (i (min len term-input-chunk-size)))
+    (process-send-string proc (substring str 0 i))
+    (while (< i len)
+      (let ((next-i (+ i term-input-chunk-size)))
+	(accept-process-output)
+	(process-send-string proc (substring str i (min len next-i)))
+	(setq i next-i)))))
+
+(defun term-send-region (proc start end)
+  "Sends to PROC the region delimited by START and END.
+This is a replacement for process-send-region that tries to keep
+your process from hanging on long inputs. See term-send-string."
+  (term-send-string proc (buffer-substring start end)))
+
+
+;;; Random input hackage
+
+(defun term-kill-output ()
+  "Kill all output from interpreter since last input."
+  (interactive)
+  (let ((pmark (process-mark (get-buffer-process (current-buffer)))))
+    (kill-region term-last-input-end pmark)
+    (goto-char pmark)    
+    (insert "*** output flushed ***\n")
+    (set-marker pmark (point))))
+
+(defun term-show-output ()
+  "Display start of this batch of interpreter output at top of window.
+Sets mark to the value of point when this command is run."
+  (interactive)
+  (goto-char term-last-input-end)
+  (backward-char)
+  (beginning-of-line)
+  (set-window-start (selected-window) (point))
+  (end-of-line))
+
+(defun term-interrupt-subjob ()
+  "Interrupt the current subjob."
+  (interactive)
+  (interrupt-process nil term-ptyp))
+
+(defun term-kill-subjob ()
+  "Send kill signal to the current subjob."
+  (interactive)
+  (kill-process nil term-ptyp))
+
+(defun term-quit-subjob ()
+  "Send quit signal to the current subjob."
+  (interactive)
+  (quit-process nil term-ptyp))
+
+(defun term-stop-subjob ()
+  "Stop the current subjob.
+WARNING: if there is no current subjob, you can end up suspending
+the top-level process running in the buffer. If you accidentally do
+this, use \\[term-continue-subjob] to resume the process. (This
+is not a problem with most shells, since they ignore this signal.)"
+  (interactive)
+  (stop-process nil term-ptyp))
+
+(defun term-continue-subjob ()
+  "Send CONT signal to process buffer's process group.
+Useful if you accidentally suspend the top-level process."
+  (interactive)
+  (continue-process nil term-ptyp))
+
+(defun term-kill-input ()
+  "Kill all text from last stuff output by interpreter to point."
+  (interactive)
+  (let* ((pmark (process-mark (get-buffer-process (current-buffer))))
+	 (p-pos (marker-position pmark)))
+    (if (> (point) p-pos)
+	(kill-region pmark (point)))))
+
+(defun term-delchar-or-maybe-eof (arg)
+  "Delete ARG characters forward, or send an EOF to process if at end of buffer."
+  (interactive "p")
+  (if (eobp)
+      (process-send-eof)
+      (delete-char arg)))
+
+(defun term-send-eof ()
+  "Send an EOF to the current buffer's process."
+  (interactive)
+  (process-send-eof))
+