home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / terms / vt200-esc-fix.el < prev    next >
Encoding:
Text File  |  1993-03-27  |  12.6 KB  |  336 lines

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