diff lisp/prim/keymap.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/prim/keymap.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,412 @@
+;; Keymap functions.
+;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
+
+;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; Synched up with: FSF 19.28.
+;;; Note: FSF does not have a file keymap.el.  This stuff is
+;;; in keymap.c.
+
+;Prevent the \{...} documentation construct
+;from mentioning keys that run this command.
+(put 'undefined 'suppress-keymap t)
+
+(defun undefined ()
+  (interactive)
+  (ding))
+
+(defun suppress-keymap (map &optional nodigits)
+  "Make MAP override all normally self-inserting keys to be undefined.
+Normally, as an exception, digits and minus-sign are set to make prefix args,
+but optional second arg NODIGITS non-nil treats them like other chars."
+  (substitute-key-definition 'self-insert-command 'undefined map global-map)
+  (or nodigits
+      (let ((string (make-string 1 ?0)))
+	(define-key map "-" 'negative-argument)
+	;; Make plain numbers do numeric args.
+	(while (<= (aref string 0) ?9)
+	  (define-key map string 'digit-argument)
+	  (aset string 0 (1+ (aref string 0)))))))
+
+(defun substitute-key-definition (olddef newdef keymap &optional oldmap prefix)
+  "Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as OLDDEF.
+In other words, OLDDEF is replaced with NEWDEF wherever it appears.
+Prefix keymaps are checked recursively.  If optional fourth argument OLDMAP
+is specified, we redefine in KEYMAP as NEWDEF those chars which are defined
+as OLDDEF in OLDMAP, unless that keybinding is already present in keymap.
+If optional fifth argument PREFIX is defined, then only those occurrences of
+OLDDEF found in keymaps accessible through the keymap bound to PREFIX in
+KEYMAP are redefined.  See also `accessible-keymaps'."
+  (let ((maps (accessible-keymaps (or oldmap keymap) prefix))
+	(shadowing (not (null oldmap)))
+	prefix map)
+    (while maps
+      (setq prefix (car (car maps))
+	    map (cdr (car maps))
+	    maps (cdr maps))
+      ;; Substitute in this keymap
+      (map-keymap #'(lambda (key binding)
+		      (if (eq binding olddef)
+			  ;; The new bindings always go in KEYMAP even if we
+			  ;; found them in OLDMAP or one of it's children.
+			  ;; If KEYMAP will be shadowing OLDMAP, then do not
+			  ;; redefine the key if there is another binding
+			  ;; in KEYMAP that will shadow OLDDEF.
+			  (or (and shadowing
+				   (lookup-key keymap key))
+			      ;; define-key will give an error if a prefix
+			      ;; of the key is already defined.  Otherwise
+			      ;; it will define the key in the map. 
+			      ;; #### - Perhaps this should be protected?
+			      (define-key
+				keymap
+				(vconcat prefix (list key))
+				newdef))))
+		  map)
+      )))
+
+;; from Bill Dubuque <wgd@martigny.ai.mit.edu>
+(defun insert-key-binding (key)         ; modeled after describe-key
+  (interactive "kInsert command bound to key: ")
+  (let (defn)
+    ;; If the key typed was really a menu selection, grab the form out
+    ;; of the event object and intuit the function that would be called,
+    ;; and describe that instead.
+    (if (and (vectorp key) (= 1 (length key))
+             (or (misc-user-event-p (aref key 0))
+                 (eq (car-safe (aref key 0)) 'menu-selection)))
+        (let ((event (aref key 0)))
+          (setq defn (if (eventp event)
+                         (list (event-function event) (event-object event))
+                       (cdr event)))
+          (if (eq (car defn) 'eval)
+              (setq defn (` (lambda ()
+                              (interactive)
+                              (, (car (cdr defn)))))))
+          (if (eq (car-safe defn) 'call-interactively)
+              (setq defn (car (cdr defn))))
+          (if (and (consp defn) (null (cdr defn)))
+              (setq defn (car defn))))
+      (setq defn (key-binding key)))
+    (if (or (null defn) (integerp defn))
+        (error "%s is undefined" (key-description key))
+      (if (or (stringp defn) (vectorp defn))
+          (setq defn (key-binding defn))) ;; a keyboard macro
+      (insert (format "%s" defn)))))
+
+;; from Bill Dubuque <wgd@martigny.ai.mit.edu>
+(defun read-command-or-command-sexp (prompt)
+  "Read a command symbol or command sexp.
+A command sexp is wrapped in an interactive lambda if needed.
+Prompts with PROMPT."
+  ;; Todo: it would be better if we could reject symbols that are not
+  ;; commandp (as does 'read-command') but that is not easy to do
+  ;; because we must supply arg4 = require-match = nil for sexp case.
+  (let ((result (car (read-from-string
+                      (completing-read prompt obarray 'commandp)))))
+    (if (and (consp result)
+             (not (eq (car result) 'lambda)))
+        (` (lambda ()
+             (interactive)
+             (, result)))
+      result)))
+
+(defun local-key-binding (keys)
+  "Return the binding for command KEYS in current local keymap only.
+KEYS is a string, a vector of events, or a vector of key-description lists
+as described in the documentation for the `define-key' function.
+The binding is probably a symbol with a function definition; see
+the documentation for `lookup-key' for more information."
+  (let ((map (current-local-map)))
+    (if map
+        (lookup-key map keys)
+        nil)))
+
+(defun global-key-binding (keys)
+  "Return the binding for command KEYS in current global keymap only.
+KEYS is a string or vector of events, a sequence of keystrokes.
+The binding is probably a symbol with a function definition; see
+the documentation for `lookup-key' for more information."
+  (lookup-key (current-global-map) keys))
+
+;; from Bill Dubuque <wgd@martigny.ai.mit.edu>
+(defun global-set-key (key command)
+  "Give KEY a global binding as COMMAND.
+COMMAND is a symbol naming an interactively-callable function.
+KEY is a string, a vector of events, or a vector of key-description lists
+as described in the documentation for the `define-key' function.
+Note that if KEY has a local binding in the current buffer
+that local binding will continue to shadow any global binding."
+  ;;(interactive "KSet key globally: \nCSet key %s to command: ")
+  (interactive (list (setq key (read-key-sequence "Set key globally: "))
+                     ;; Command sexps are allowed here so that this arg
+                     ;; may be supplied interactively via insert-key-binding.
+                     (read-command-or-command-sexp
+                       (format "Set key %s to command: "
+                               (key-description key)))))
+  (define-key (current-global-map) key command)
+  nil)
+
+;; from Bill Dubuque <wgd@martigny.ai.mit.edu>
+(defun local-set-key (key command)
+  "Give KEY a local binding as COMMAND.
+COMMAND is a symbol naming an interactively-callable function.
+KEY is a string, a vector of events, or a vector of key-description lists
+as described in the documentation for the `define-key' function.
+The binding goes in the current buffer's local map,
+which is shared with other buffers in the same major mode."
+  ;;(interactive "KSet key locally: \nCSet key %s locally to command: ")
+  (interactive (list (setq key (read-key-sequence "Set key locally: "))
+                     ;; Command sexps are allowed here so that this arg
+                     ;; may be supplied interactively via insert-key-binding.
+                     (read-command-or-command-sexp
+                       (format "Set key %s locally to command: "
+                               (key-description key)))))
+  (if (null (current-local-map))
+      (use-local-map (make-sparse-keymap)))
+  (define-key (current-local-map) key command)
+  nil)
+
+(defun global-unset-key (key)
+  "Remove global binding of KEY.
+KEY is a string, a vector of events, or a vector of key-description lists
+as described in the documentation for the `define-key' function."
+  (interactive "kUnset key globally: ")
+  (global-set-key key nil))
+
+(defun local-unset-key (key)
+  "Remove local binding of KEY.
+KEY is a string, a vector of events, or a vector of key-description lists
+as described in the documentation for the `define-key' function."
+  (interactive "kUnset key locally: ")
+  (if (current-local-map)
+      (define-key (current-local-map) key nil)))
+
+
+;; Yet more RMS brain-death.
+(defun minor-mode-key-binding (key &optional accept-default)
+  "Find the visible minor mode bindings of KEY.
+Return an alist of pairs (MODENAME . BINDING), where MODENAME is the
+the symbol which names the minor mode binding KEY, and BINDING is
+KEY's definition in that mode.  In particular, if KEY has no
+minor-mode bindings, return nil.  If the first binding is a
+non-prefix, all subsequent bindings will be omitted, since they would
+be ignored.  Similarly, the list doesn't include non-prefix bindings
+that come after prefix bindings.
+
+If optional argument ACCEPT-DEFAULT is non-nil, recognize default
+bindings; see the description of `lookup-key' for more details about this."
+  (let ((tail minor-mode-map-alist)
+        a s v)
+    (while tail
+      (setq a (car tail)
+            tail (cdr tail))
+      (and (consp a)
+           (symbolp (setq s (car a)))
+           (boundp s)
+           (symbol-value s)
+           ;; indirect-function deals with autoloadable keymaps
+           (setq v (indirect-function (cdr a)))
+           (setq v (lookup-key v key accept-default))
+           ;; Terminate loop, with v set to non-nil value
+           (setq tail nil)))
+    v))
+    
+
+(defun current-minor-mode-maps ()
+  "Return a list of keymaps for the minor modes of the current buffer."
+  (let ((l '())
+        (tail minor-mode-map-alist)
+        a s v)
+    (while tail
+      (setq a (car tail)
+            tail (cdr tail))
+      (and (consp a)
+           (symbolp (setq s (car a)))
+           (boundp s)
+           (symbol-value s)
+           ;; indirect-function deals with autoloadable keymaps
+           (setq v (indirect-function (cdr a)))
+           (setq l (cons v l))))
+    (nreverse l)))
+
+
+;;#### What a crock
+(defun define-prefix-command (name &optional mapvar)
+  "Define COMMAND as a prefix command.
+A new sparse keymap is stored as COMMAND's function definition.
+If second optional argument MAPVAR is not specified,
+ COMMAND's value (as well as its function definition) is set to the keymap.
+If a second optional argument MAPVAR is given and is not `t',
+  the map is stored as its value.
+Regardless of MAPVAR, COMMAND's function-value is always set to the keymap."
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-name map name)
+    (fset name map)
+    (cond ((not mapvar)
+           (set name map))
+          ((eq mapvar 't)
+           )
+          (t
+           (set mapvar map)))
+    name))
+
+
+;;; Converting vectors of events to a read-equivalent form.
+;;; This is used both by call-interactively (for the command history)
+;;; and by macros.el (for saving keyboard macros to a file).
+
+(defun events-to-keys (events &optional no-mice)
+ "Given a vector of event objects, returns a vector of key descriptors,
+or a string (if they all fit in the ASCII range).
+Optional arg NO-MICE means that button events are not allowed."
+ (if (and events (symbolp events)) (setq events (vector events)))
+ (cond ((stringp events)
+        events)
+       ((not (vectorp events))
+        (signal 'wrong-type-argument (list 'vectorp events)))
+       ((let* ((length (length events))
+               (string (make-string length 0))
+               c ce
+               (i 0))
+          (while (< i length)
+            (setq ce (aref events i))
+            (or (eventp ce) (setq ce (character-to-event ce)))
+            ;; Normalize `c' to `?c' and `(control k)' to `?\C-k'
+            ;; By passing t for the `allow-meta' arg we could get kbd macros
+            ;; with meta in them to translate to the string form instead of
+            ;; the list/symbol form; but I expect that would cause confusion,
+            ;; so let's use the list/symbol form whenever there's 
+            ;; any ambiguity.
+            (setq c (event-to-character ce))
+            (if (and c
+                     character-set-property
+                     (key-press-event-p ce))
+                (cond ((symbolp (event-key ce))
+                       (if (get (event-key ce) character-set-property)
+                           ;; Don't use a string for `backspace' and `tab' to
+                           ;;  avoid that unpleasant little ambiguity.
+                           (setq c nil)))
+                      ((and (= (event-modifier-bits ce) 1) ;control
+                            (integerp (event-key ce)))
+                       (let* ((te (character-to-event c)))
+                         (if (and (symbolp (event-key te))
+                                  (get (event-key te) character-set-property))
+                             ;; Don't "normalize" (control i) to tab
+                             ;;  to avoid the ambiguity in the other direction
+                             (setq c nil))
+                         (deallocate-event te)))))
+            (if c
+                (aset string i c)
+                (setq i length string nil))
+            (setq i (1+ i)))
+          string))
+       (t
+        (let* ((length (length events))
+               (new (copy-sequence events))
+               event mods key
+               (i 0))
+          (while (< i length)
+            (setq event (aref events i))
+            (cond ((key-press-event-p event)
+                   (setq mods (event-modifiers event)
+                         key (event-key event))
+                   (if (numberp key)
+                       (setq key (intern (make-string 1 key))))
+                   (aset new i (if mods
+                                   (nconc mods (cons key nil))
+                                   key)))
+                  ((misc-user-event-p event)
+                   (aset new i (list 'menu-selection
+                                     (event-function event)
+                                     (event-object event))))
+                  ((or (button-press-event-p event)
+                       (button-release-event-p event))
+                   (if no-mice
+                       (error 
+                         "Mouse events can't be saved in keyboard macros."))
+                   (setq mods (event-modifiers event)
+                         key (intern (concat "button"
+                                             (event-button event)
+                                             (if (button-release-event-p event)
+                                                 "up" ""))))
+                   (aset new i (if mods
+                                   (nconc mods (cons key nil))
+                                   key)))
+                  ((or (and event (symbolp event))
+                       (and (consp event) (symbolp (car event))))
+                   (aset new i event))
+                  (t
+                   (signal 'wrong-type-argument (list 'eventp event))))
+            (setq i (1+ i)))
+          new))))
+
+;FSFmacs ####
+;;; Support keyboard commands to turn on various modifiers.
+;
+;;; These functions -- which are not commands -- each add one modifier
+;;; to the following event.
+;
+;(defun event-apply-alt-modifier (ignore-prompt)
+;  (vector (event-apply-modifier (read-event) 'alt 22 "A-")))
+;(defun event-apply-super-modifier (ignore-prompt)
+;  (vector (event-apply-modifier (read-event) 'super 23 "s-")))
+;(defun event-apply-hyper-modifier (ignore-prompt)
+;  (vector (event-apply-modifier (read-event) 'hyper 24 "H-")))
+;(defun event-apply-shift-modifier (ignore-prompt)
+;  (vector (event-apply-modifier (read-event) 'shift 25 "S-")))
+;(defun event-apply-control-modifier (ignore-prompt)
+;  (vector (event-apply-modifier (read-event) 'control 26 "C-")))
+;(defun event-apply-meta-modifier (ignore-prompt)
+;  (vector (event-apply-modifier (read-event) 'meta 27 "M-")))
+;
+;(defun event-apply-modifier (event symbol lshiftby prefix)
+;  "Apply a modifier flag to event EVENT.
+;SYMBOL is the name of this modifier, as a symbol.
+;LSHIFTBY is the numeric value of this modifier, in keyboard events.
+;PREFIX is the string that represents this modifier in an event type symbol."
+;  (if (numberp event)
+;      (cond ((eq symbol 'control)
+;	      (if (and (<= (downcase event) ?z)
+;		       (>= (downcase event) ?a))
+;		  (- (downcase event) ?a -1)
+;		(if (and (<= (downcase event) ?Z)
+;			 (>= (downcase event) ?A))
+;		    (- (downcase event) ?A -1)
+;		  (logior (lsh 1 lshiftby) event))))
+;	     ((eq symbol 'shift)
+;	      (if (and (<= (downcase event) ?z)
+;		       (>= (downcase event) ?a))
+;		  (upcase event)
+;		(logior (lsh 1 lshiftby) event)))
+;	     (t
+;	      (logior (lsh 1 lshiftby) event)))
+;    (if (memq symbol (event-modifiers event))
+;	 event
+;      (let ((event-type (if (symbolp event) event (car event))))
+;	 (setq event-type (intern (concat prefix (symbol-name event-type))))
+;	 (if (symbolp event)
+;	     event-type
+;	   (cons event-type (cdr event)))))))
+;
+;(define-key function-key-map [?\C-x ?@ ?h] 'event-apply-hyper-modifier)
+;(define-key function-key-map [?\C-x ?@ ?s] 'event-apply-super-modifier)
+;(define-key function-key-map [?\C-x ?@ ?m] 'event-apply-meta-modifier)
+;(define-key function-key-map [?\C-x ?@ ?a] 'event-apply-alt-modifier)
+;(define-key function-key-map [?\C-x ?@ ?S] 'event-apply-shift-modifier)
+;(define-key function-key-map [?\C-x ?@ ?c] 'event-apply-control-modifier)