home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / packages / fix-my-terminal / vt200-esc-fix.el < prev    next >
Encoding:
Text File  |  1993-03-26  |  11.3 KB  |  291 lines

  1. ;;; File:  vt200-esc-fix.el, v 4.0 (emacs 18[.58] version)
  2. ;;;
  3. ;;;               -----------   -----   -----
  4. ;;;               E s c a p e   K e y   F i x
  5. ;;;               -----------   -----   -----
  6. ;;;
  7. ;;;
  8. ;;; Copyright (C) 1990 Free Software Foundation, Inc.
  9. ;;; Copyright (C) 1993 Jeff Morgenthaler
  10. ;;; Thanks to Joe Wells for encouragement to code everything right.  
  11.  
  12.  
  13. ;; LCD Archive Entry:
  14. ;; fix-my-terminal|Jeff Morgenthaler|jpmorgen@wisp4.physics.wisc.edu|
  15. ;; Fixes:  flow control, arrow keys, and vt200 function keys|
  16. ;; 93-03-23|1.0|~/packages/fix-my-terminal.tar.Z
  17.  
  18. ;; Archived at archive.cis.ohio-state.edu
  19.  
  20. ;;;
  21. ;;; GNU Emacs is distributed in the hope that it will be useful, but
  22. ;;; WITHOUT ANY WARRANTY.  No author or distributor accepts
  23. ;;; RESPONSIBILITY TO anyone for the consequences of using it or for
  24. ;;; whether it serves any particular purpose or works at all, unless 
  25. ;;; he says so in writing.  Refer to the GNU Emacs General Public
  26. ;;; License for full details.
  27. ;;;
  28. ;;;  Send bug reports and suggestions for improvement to Jeff Morgenthaler
  29. ;;;  (jpmorgen@wisp4.physics.wisc.edu).
  30. ;;;
  31. ;;; Everyone is granted permission to copy, modify and redistribute
  32. ;;; GNU Emacs, but only under the conditions described in the GNU
  33. ;;; Emacs General Public License.  A copy of this license is supposed
  34. ;;; to have been given to you along with GNU Emacs so you can know
  35. ;;; your rights and responsibilities.  It should be in a file named
  36. ;;; COPYING.  Among other things, the Copyright notice and this notice
  37. ;;; must be preserved on all copies.
  38. ;;;
  39.  
  40. ;;;; VT200 type terminals have no escape key. This causes great
  41. ;;;; trouble for emacs and another well known UNIX editor.  The most
  42. ;;;; popular solution to this problem is to run the terminal in vt100
  43. ;;;; mode (if possible).  This unfortunately makes the function keys
  44. ;;;; inaccessible (including "do," "find," etc) and puts the ESC key
  45. ;;;; in a rather inconvenient place (F11).  Another solution is to run
  46. ;;;; the terminal in vt200 mode and use M-x enable-arrow-keys.  This
  47. ;;;; maps F11 (which is really ESC[23~) to ESC-prefix.  Unfortunately,
  48. ;;;; ESC-prefix is not really ESC and some parts of emacs (like
  49. ;;;; isearch) have troubles with it (try to terminate an isearch with
  50. ;;;; F11 and you will get a [23~ in your buffer).
  51.  
  52. ;;;; The best solution is to get the terminal to remap some keys
  53. ;;;; (vt300s and xterms do this).  The usual remapping is to put the
  54. ;;;; ~/` key down on the </> key and put the < and > above the , and .
  55. ;;;; where they belong.  Also, F11 can sometimes be made to send a
  56. ;;;; real ESC, not an ESC[23~.
  57.  
  58. ;;;; This code simulates the above remappings as best as emacs allows.
  59. ;;;; First of all, there is no way software can tell the difference
  60. ;;;; between , and shift-, if the terminal sends the same character
  61. ;;;; for both.  This means that something is going to get lost.  Since
  62. ;;;; only one key is being remapped to ESC (` by default), I have
  63. ;;;; chosen to lose it.  
  64.  
  65. ;;;; You can probably see what's going to happen when you run this
  66. ;;;; code: everything is the same on the keyboard, except that when
  67. ;;;; you press ` you get ESC instead.  How will you get `?  This is
  68. ;;;; where the fun begins.  
  69.  
  70. ;;;; Earlier versions of this code assumed that you would just turn
  71. ;;;; escape-key-fix off whenever you wanted `.  You can still do this,
  72. ;;;; and in many respects this is the least confusing thing to do.
  73.  
  74. ;;;; In order to achieve easier access to the ` key, I have mapped
  75. ;;;; C-c-ESC to ` (this will actually look like C-c ` on your
  76. ;;;; keyboard).  You can also make the F11 key send ` with the code:
  77.  
  78. ;;;; (setq term-setup-hook
  79. ;;;;     (function
  80. ;;;;       (lambda ()
  81. ;;;;      (and (fboundp 'enable-arrow-keys)
  82. ;;;;           (progn
  83. ;;;;         (enable-arrow-keys)
  84. ;;;;         (define-key CSI-map "23~" 'type-escape-key-replacement)   ; F11
  85. ;;;;           ))
  86. ;;;;      ))
  87. ;;;; )
  88.  
  89. ;;;; Unfortunately, this is not good enough.  When processing C-x and
  90. ;;;; C-c events, emacs looks for literal keystrokes.  So, you cannot
  91. ;;;; use "C-x F11" for "C-x `."  Nor can you use C-x C-c ` (you will
  92. ;;;; be popped out of emacs).  Therefore, more keys have to be
  93. ;;;; remapped!  
  94.  
  95. ;;;; Again, since the ` key is the only messed up key, I have remapped
  96. ;;;; only the key bindings that use it (and that I know about).  So
  97. ;;;; far, I've remapped C-x ` (next-error) to C-x ~.  The binding of
  98. ;;;; C-x ~ (nil) is saved so that it can be restored when
  99. ;;;; escape-key-fix is turned off.  Tell me if there are any other
  100. ;;;; bindings that are effected and I will add them to
  101. ;;;; escape-key-fix-rebind-list.
  102.  
  103. ;;;; Unfortunately, there will be a fundamental problem if any local
  104. ;;;; modes remap these keys.  Code will have to be added to each of
  105. ;;;; these modes to remap things out of the way of `.  
  106.  
  107.  
  108. ;;;; Installation:
  109.  
  110. ;;;; To make this facility available for all users, place this file,
  111. ;;;; vt200-esc-fix.el, into your site's public emacs/lisp directory
  112. ;;;; and add the following command to your site's default.el file:
  113.  
  114. ;;;;        (require 'vt200-esc-fix)
  115. ;;;;            (auto-escape-key-fix)
  116.  
  117.  
  118. ;;;; NOTE.  You must also have flow-ctrl.el on your load path.
  119.  
  120. ;;;; This code can either be called interactively with "M-x escape-key-fix"
  121. ;;;; or started automatically with the code:
  122.  
  123. ;;;;  (setq terminal-needs-escape-key
  124. ;;;;        '("vt200" "vt201" "vt220" "vt240"))
  125.  
  126. ;;;; in the user's .emacs file.  To turn it off, just use "M-x
  127. ;;;; escape-key-fix" again.  
  128.  
  129. ;;;; The ESC key can be remapped to another key on the keyboard that
  130. ;;;; sends a single character (not the function keys, sorry) with the
  131. ;;;; code:
  132.  
  133. ;;;; (setq escape-key-replacement ?<)
  134. ;;;; (setq escape-key-fix-rebind-alist '(("\C-c\e" . "\C-c\e") 
  135. ;;;;                          ("\C-x<" . "\C-xl")))
  136.  
  137. ;;;; You can bind type-escape-key-replacement to any key.  For
  138. ;;;; instance, if you wanted C-t to send ` (or your customized
  139. ;;;; escape-key-replacement), you would use the code:
  140.  
  141. ;;;; (global-set-key "\C-t" 'type-escape-key-replacement)
  142.  
  143. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  144.  
  145. (provide 'vt200-esc-fix)
  146. (require 'flow-ctrl)
  147.  
  148. ;; Define default ESC replacement and associated work arounds.  Tell me if 
  149. ;; there are any more conflicts.
  150.  
  151. (defvar escape-key-replacement ?`
  152.   "*Ascii code of escape key replacement.  Example of setting this variable: 
  153. (setq escape-key-replacement ?<).")
  154.  
  155. (defvar escape-key-fix-rebind-alist '(("\C-c\e" . "\C-c\e") 
  156.                      ("\C-x`" . "\C-x~"))
  157.   "*List containing pairs of key sequences.  The first element of each pair 
  158. is the key sequence messed up by escape-key-fix, the second is the key 
  159. sequence which replaces it.  If the key sequence is repeated, that key
  160. sequence is bound to type-escape-key-replacement.  Example of setting
  161. this variable: 
  162. \(setq escape-key-fix-rebind-alist '((""\\C-c\\e"" . ""\\C-c\\e"") 
  163.                      (""\\C-x<"" . ""\\C-xl""))).")
  164.  
  165. (defvar escape-key-fix-overmapped-complex-keys nil
  166.   "*List of cons cells.  The first element of each cell is a key sequence,
  167. the second is its binding when escape-key-fix is not active.")
  168.  
  169. (defvar escape-key-fix-remap-message nil
  170.   "*Message informing users of control sequence remappings.")
  171.  
  172. (defun escape-key-fix-remap-complex-keys (rebind-alist)
  173.   "Remaps complex key sequences (like C-x `) for escape-key-fix.
  174. Creates escape-key-fix-overmapped-complex-keys and
  175. escape-key-fix-remap-message."
  176.   (while rebind-alist 
  177.     ;; Unpack rebind-alist.
  178.     (let ((old-key (car (car rebind-alist)))
  179.       (new-key (cdr (car rebind-alist))))
  180.       ;; Make a list of overmapped keys so they can be restored later
  181.       (setq escape-key-fix-overmapped-complex-keys 
  182.         (cons (cons new-key (key-binding new-key))
  183.           escape-key-fix-overmapped-complex-keys))
  184.       (if (string-equal new-key old-key)
  185.       ;; Signal to bind this key sequence to type-escape-key-replacemant
  186.       (progn
  187.         (global-set-key new-key 'type-escape-key-replacement)
  188.         (setq escape-key-fix-remap-message 
  189.           (concat escape-key-fix-remap-message 
  190.               (key-description new-key)
  191.               " is now " 
  192.               (single-key-description escape-key-replacement)
  193.               ".  ")))
  194.     (progn
  195.       (global-set-key new-key (key-binding old-key))
  196.       (setq escape-key-fix-remap-message 
  197.         (concat escape-key-fix-remap-message "Use "
  198.             (key-description new-key)
  199.             " for " 
  200.             (key-description old-key)
  201.             ".  "))))
  202.       (setq rebind-alist (cdr rebind-alist)))))
  203.  
  204.  
  205. (defun escape-key-fix-restore-complex-keys (overmapped-list)
  206.     (while overmapped-list 
  207.       (let ((restore-key (car (car overmapped-list)))
  208.         (displaced-function (cdr (car overmapped-list))))
  209.     (global-set-key restore-key displaced-function)
  210.     (setq overmapped-list (cdr overmapped-list))
  211.     )))
  212.  
  213.  
  214. (defun type-escape-key-replacement (arg)
  215.   "Inserts the character escape-key-replacement, since it is overwritten
  216. by escape-key-fix."
  217.   (interactive "p")
  218.   (insert-char escape-key-replacement arg))
  219.  
  220. (defvar escape-key-fix-flag nil
  221.   "*Flag to indicate if escape is remapped.")
  222.  
  223.  
  224. (defun escape-key-fix (arg)
  225.   "A quick fix for vt200 type keyboards which have no escape key.
  226. This function remaps escape-key-replacement \(` by default\) to ESC
  227. and provides hooks for remapping all other effected keys and key
  228. sequences \(escape-key-fix-rebind-alist\) for remaping effected complex
  229. control character sequences \(like C-x `\).  ALL remappings are
  230. restored when escape-key-fix is called again \(it toggles\).
  231.  
  232. This function is not intended for permanent use.  The best solution to
  233. the problem of the vt200 escape key is to fix your hardware.  In X
  234. windows, you can use xmodmap, on vt300s, you can remap keys in the
  235. setup menu."
  236.  
  237.   (interactive
  238.    (list
  239.     (if current-prefix-arg
  240.     ;; If an argument is specified, then turn on if non-negative else
  241.     ;; turn off if negative.
  242.     (>= (prefix-numeric-value current-prefix-arg) 0)
  243.       ;; If no argument is specified, then toggle.
  244.       'toggle)))
  245.  
  246.   (setq escape-key-fix-flag
  247.     (if (eq arg 'toggle)
  248.         (not escape-key-fix-flag)
  249.      arg))
  250.   ;; Thanks to the elisp prowess of jbw for the above sequence!
  251.  
  252.   (if escape-key-fix-flag
  253.       (progn
  254.     ;; Make the "escape-key-replacement" key send ESC.
  255.     ;; Can't swap them directly, since that messes up arrow/function keys.
  256.     (init-keyboard-translate-table)
  257.     (aset keyboard-translate-table  escape-key-replacement ?\e)
  258.     (setq escape-key-fix-remap-message nil)
  259.     (escape-key-fix-remap-complex-keys escape-key-fix-rebind-alist)
  260.     (message (concat "The "(single-key-description escape-key-replacement)
  261.              " key now sends ESC.  "
  262.              escape-key-fix-remap-message))
  263.     (sleep-for 1) ; Give user a chance to see message.
  264.       )
  265.     ;; reset ESC, escape-key-replacement, and the list of keys in 
  266.     ;; escape-key-fix-overmapped-complex-keys
  267.     (progn
  268.       (init-keyboard-translate-table)
  269.       (aset keyboard-translate-table ?\e ?\e)
  270.       (aset keyboard-translate-table 
  271.         escape-key-replacement escape-key-replacement)
  272.       (escape-key-fix-restore-complex-keys 
  273.        escape-key-fix-overmapped-complex-keys)
  274.       (setq escape-key-fix-overmapped-complex-keys nil)
  275.       (message 
  276.        (concat "The " (single-key-description escape-key-replacement)
  277.            " key is no longer ESC.  All associated bindings are reset."))
  278.       )
  279.     )
  280.   )
  281.  
  282. (defun auto-escape-key-fix ()
  283.   "Assigns the ESC key to the key named in escape-key-replacement using 
  284. escape-key-fix if the current terminal is is the list terminal-needs-escape.  
  285. Drops everthing in TERM past the first hyphen."
  286.   (if (boundp 'terminal-needs-escape-key)
  287.       (if (TERM-in-list terminal-needs-escape-key)
  288.       (escape-key-fix t))
  289.     )
  290.   )
  291.