-;; Terminal emulator for GNU Emacs.
-;; Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
-;; Written by Richard Mlynarik, November 1986.
+;;; terminal.el --- terminal emulator for GNU Emacs.
+
+;; Copyright (C) 1986,87,88,89,93,94 Free Software Foundation, Inc.
+
+;; Author: Richard Mlynarik <mly@eddie.mit.edu>
+;; Maintainer: FSF
+;; Keywords: comm, terminals
;; 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 1, or (at your option)
+;; 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,
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;; Code:
+
;;>>TODO
;;>> terminfo?
;;>> ** Nothing can be done about emacs' meta-lossage **
(defvar terminal-more-break-insertion
"*** More break -- Press space to continue ***")
-(defvar terminal-escape-map nil)
+(defvar terminal-meta-map nil)
+(if terminal-meta-map
+ nil
+ (let ((map (make-sparse-keymap)))
+ (define-key map [t] 'te-pass-through)
+ (setq terminal-meta-map map)))
+
(defvar terminal-map nil)
-(defvar terminal-more-break-map nil)
(if terminal-map
nil
- (let ((map (make-keymap)))
- (fillarray map 'te-pass-through)
+ (let ((map (make-sparse-keymap)))
+ (define-key map [t] 'te-pass-through)
+ (define-key map [switch-frame] 'handle-switch-frame)
+ (define-key map "\e" terminal-meta-map)
;(define-key map "\C-l"
; '(lambda () (interactive) (te-pass-through) (redraw-display)))
(setq terminal-map map)))
-;(setq terminal-escape-map nil)
+(defvar terminal-escape-map nil)
(if terminal-escape-map
nil
- (let ((map (make-keymap)))
- ;(fillarray map 'te-escape-extended-command-unread)
- (fillarray map 'undefined)
+ (let ((map (make-sparse-keymap)))
+ (define-key map [t] 'undefined)
(let ((s "0"))
(while (<= (aref s 0) ?9)
(define-key map s 'digit-argument)
(define-key map (char-to-string help-char) 'te-escape-help)
(setq terminal-escape-map map)))
-(defvar te-escape-command-alist ())
-;(setq te-escape-command-alist ())
+(defvar te-escape-command-alist nil)
(if te-escape-command-alist
nil
(setq te-escape-command-alist
("Set Redisplay Interval" . te-set-redisplay-interval)
)))
-;(setq terminal-more-break-map nil)
+(defvar terminal-more-break-map nil)
(if terminal-more-break-map
nil
- (let ((map (make-keymap)))
- (fillarray map 'te-more-break-unread)
+ (let ((map (make-sparse-keymap)))
+ (define-key map [t] 'te-more-break-unread)
(define-key map (char-to-string help-char) 'te-more-break-help)
(define-key map " " 'te-more-break-resume)
(define-key map "\C-l" 'redraw-display)
(setq terminal-more-break-map map)))
+\f
+;;; Pacify the byte compiler
+(defvar te-process nil)
+(defvar te-log-buffer nil)
+(defvar te-height nil)
+(defvar te-width nil)
+(defvar te-more-count nil)
+(defvar te-redisplay-count nil)
+(defvar te-pending-output nil)
+(defvar te-saved-point)
+(defvar te-more-old-point nil)
+(defvar te-more-old-local-map nil)
+(defvar te-more-old-filter nil)
+(defvar te-more-old-mode-line-format nil)
+(defvar te-pending-output-info nil)
+
\f
;;;; escape map
(princ (substitute-command-keys "\\{terminal-escape-map}\n"))
(princ (format "\nSubcommands of \"%s\" (%s)\n"
(where-is-internal 'te-escape-extended-command
- terminal-escape-map nil t)
+ terminal-escape-map t)
'te-escape-extended-command))
(let ((l (if (fboundp 'sortcar)
(sortcar (copy-sequence te-escape-command-alist)
;; not used.
(defun te-escape-extended-command-unread ()
(interactive)
- (setq unread-command-char last-input-char)
+ (setq unread-command-events (listify-key-sequence (this-command-keys)))
(te-escape-extended-command))
(defun te-set-escape-char (c)
(interactive "cSet escape character to: ")
(let ((o terminal-escape-char))
(message (if (= o c)
- "\"%s\" is escape char"
- "\"%s\" is now escape; \"%s\" passes though")
+ "\"%s\" is the escape char"
+ "\"%s\" is now the escape; \"%s\" passes through")
(single-key-description c)
(single-key-description o))
(setq terminal-escape-char c)))
(put 'te-more-break-unread 'suppress-keymap t)
(defun te-more-break-unread ()
(interactive)
- (if (= last-input-char terminal-escape-char)
+ (if (eq last-input-char terminal-escape-char)
(call-interactively 'te-escape)
(message "Continuing from more break (\"%s\" typed, %d chars output pending...)"
(single-key-description last-input-char)
(princ "Terminal-emulator more break.\n\n")
(princ (format "Type \"%s\" (te-more-break-resume)\n%s\n"
(where-is-internal 'te-more-break-resume
- terminal-more-break-map nil t)
+ terminal-more-break-map t)
(documentation 'te-more-break-resume)))
(princ (substitute-command-keys "\\{terminal-more-break-map}\n"))
(princ "Any other key is passed through to the program
(defun te-more-break-flush-pending-output ()
"Discard any output which has been received by the terminal emulator but
-not yet proceesed and then proceed from the more break."
+not yet processed and then proceed from the more break."
(interactive)
(te-more-break-unwind)
(te-flush-pending-output))
the terminal escape character (normally C-^)
lets you type a terminal emulator command."
(interactive)
- (cond ((= last-input-char terminal-escape-char)
+ (cond ((eq last-input-char terminal-escape-char)
(call-interactively 'te-escape))
(t
- (and terminal-more-processing (null (cdr te-pending-output))
- (te-set-more-count nil))
- (send-string te-process (make-string 1 last-input-char))
- (te-process-output t))))
+ ;; 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)))
+ ;; Convert meta characters to 8-bit form for transmission.
+ (if (and (integerp last-input-char)
+ (not (zerop (logand last-input-char (lsh 1 23)))))
+ (setq last-input-char (+ 128 (logand last-input-char 127))))
+ ;; Now ignore all but actual characters.
+ ;; (It ought to be possible to send through function
+ ;; keys as character sequences if we add a description
+ ;; to our termcap entry of what they should look like.)
+ (if (integerp last-input-char)
+ (progn
+ (and terminal-more-processing (null (cdr te-pending-output))
+ (te-set-more-count nil))
+ (send-string te-process (make-string 1 last-input-char))
+ (te-process-output t))
+ (message "Function key `%s' ignored"
+ (single-key-description last-input-char))))))
(defun te-set-window-start ()
(defun terminal-edit-mode ()
"Major mode for editing the contents of a terminal-emulator buffer.
The editing commands are the same as in Fundamental mode,
-together with a command \\<terminal-edit-mode-map>to return to terminal emulation: \\[terminal-cease-edit]."
+together with a command \\<terminal-edit-map>to return to terminal emulation: \\[terminal-cease-edit]."
(use-local-map terminal-edit-map)
(setq major-mode 'terminal-edit-mode)
(setq mode-name "Terminal Edit")
(setq te-more-count -1)))
(setq mode-line-modified (default-value 'mode-line-modified))
+ (use-local-map terminal-map)
(setq major-mode 'terminal-mode)
(setq mode-name "terminal")
- (setq mode-line-process '(": %s")))
+ (setq mode-line-process '(":%s")))
\f
;;;; more break hair
\f
(defun te-filter (process string)
- (let* ((obuf (current-buffer))
- (m meta-flag))
+ (let* ((obuf (current-buffer)))
;; can't use save-excursion, as that preserves point, which we don't want
(unwind-protect
(progn
(set-buffer (process-buffer process))))
(setq te-pending-output (nconc te-pending-output (list string)))
(te-update-pending-output-display)
- ;; this binding is needed because emacs looks at meta-flag when
- ;; the keystroke is read from the keyboard, not when it is about
- ;; to be fed into a keymap (or returned by read-char)
- ;; There still could be some screws, though.
- (let ((meta-flag m))
- (te-process-output (eq (current-buffer)
- (window-buffer (selected-window)))))
+ (te-process-output (eq (current-buffer)
+ (window-buffer (selected-window))))
(set-buffer (process-buffer process))
(setq te-saved-point (point)))
(set-buffer obuf))))
(progn (goto-char (point-max))
(recenter -1)))))))
\f
-(defvar te-stty-string "stty -nl dec echo"
+(defvar te-stty-string "stty -nl erase '^?' kill '^u' intr '^c' echo pass8"
"Shell command to set terminal modes for terminal emulator.")
;; This used to have `new' in it, but that loses outside BSD
;; and it's apparently not needed in BSD.
;;-- For disgusting programs.
;; (VI? What losers need these, I wonder?)
"im=:ei=:dm=:ed=:mi:do=^p^j:nl=^p^j:bs:")))
- (if (fboundp 'start-subprocess)
- ;; this winning function would do everything, except that
- ;; rms doesn't want it.
- (setq te-process (start-subprocess "terminal-emulator"
- program args
- 'channel-type 'terminal
- 'filter 'te-filter
- 'buffer (current-buffer)
- 'sentinel 'te-sentinel
- 'modify-environment
- (list (cons "TERM" "emacs-virtual")
- (cons "TERMCAP" termcap))))
- ;; so instead we resort to this...
- (setq te-process (start-process "terminal-emulator" (current-buffer)
- "/bin/sh" "-c"
- ;; Yuck!!! Start a shell to set some terminal
- ;; control characteristics. Then start the
- ;; "env" program to setup the terminal type
- ;; Then finally start the program we wanted.
- (format "%s; exec %s TERM=emacs-virtual %s %s"
- te-stty-string
- (te-quote-arg-for-sh
- (concat exec-directory "env"))
- (te-quote-arg-for-sh
- (concat "TERMCAP=" termcap))
- (mapconcat 'te-quote-arg-for-sh
- (cons program args) " "))))
- (set-process-filter te-process 'te-filter)
- (set-process-sentinel te-process 'te-sentinel)))
+ (let ((process-environment
+ (cons "TERM=emacs-virtual"
+ (cons (concat "TERMCAP=" termcap)
+ process-environment))))
+ (setq te-process
+ (start-process "terminal-emulator" (current-buffer)
+ "/bin/sh" "-c"
+ (format "%s; exec %s"
+ te-stty-string
+ (mapconcat 'te-quote-arg-for-sh
+ (cons program args) " ")))))
+ (set-process-filter te-process 'te-filter)
+ (set-process-sentinel te-process 'te-sentinel))
(error (fundamental-mode)
(signal (car err) (cdr err))))
- ;; sigh
- (if (default-value 'meta-flag)
- (progn (message
- "Note: Meta key disabled due to maybe-eventually-reparable braindamage")
- (sit-for 1)))
(setq inhibit-quit t) ;sport death
(use-local-map terminal-map)
(run-hooks 'terminal-mode-hook)
(message "Entering emacs terminal-emulator... Type %s %s for help"
(single-key-description terminal-escape-char)
(mapconcat 'single-key-description
- (where-is-internal 'te-escape-help
- terminal-escape-map
- nil t)
+ (where-is-internal 'te-escape-help terminal-escape-map t)
" ")))
(defun te-parse-program-and-args (s)
- (cond ((string-match "\\`\\([a-zA-Z0-9-+=_.@/:]+[ \t]*\\)+\\'" s)
+ (cond ((string-match "\\`\\([-a-zA-Z0-9+=_.@/:]+[ \t]*\\)+\\'" s)
(let ((l ()) (p 0))
(while p
(setq l (cons (if (string-match
- "\\([a-zA-Z0-9-+=_.@/:]+\\)\\([ \t]+\\)*"
+ "\\([-a-zA-Z0-9+=_.@/:]+\\)\\([ \t]+\\)*"
s p)
(prog1 (substring s p (match-end 1))
(setq p (match-end 0))
(put 'terminal-mode 'mode-class 'special)
;; This is only separated out from function terminal-emulator
-;; to keep the latter a little more managable.
+;; to keep the latter a little more manageable.
(defun terminal-mode ()
- "Set up variables for use f the terminal-emualtor.
+ "Set up variables for use with the terminal-emulator.
One should not call this -- it is an internal function
of the terminal-emulator"
(kill-all-local-variables)
(setq mode-name "terminal")
; (make-local-variable 'Helper-return-blurb)
; (setq Helper-return-blurb "return to terminal simulator")
- (setq mode-line-process '(": %s"))
+ (setq mode-line-process '(":%s"))
(setq buffer-read-only t)
(setq truncate-lines t)
(make-local-variable 'terminal-escape-char)
(setq te-more-count -1)
(make-local-variable 'te-redisplay-count)
(setq te-redisplay-count terminal-redisplay-interval)
- ;;>> Nothing can be done about this without decruftifying
- ;;>> emacs keymaps.
- (make-local-variable 'meta-flag) ;sigh
- (setq meta-flag nil)
;(use-local-map terminal-mode-map)
;; terminal-mode-hook is called above in function terminal-emulator
)
;;;; what a complete loss
(defun te-quote-arg-for-sh (string)
- (cond ((string-match "\\`[a-zA-Z0-9-+=_.@/:]+\\'"
+ (cond ((string-match "\\`[-a-zA-Z0-9+=_.@/:]+\\'"
string)
string)
((not (string-match "[$]" string))
(concat "\"" harder "\"")))))
(provide 'terminal)
+
+;;; terminal.el ends here