+If optional fourth argument OLDMAP is specified, we redefine
+in KEYMAP as NEWDEF those chars which are defined as OLDDEF in OLDMAP."
+ (or prefix (setq prefix ""))
+ (let* ((scan (or oldmap keymap))
+ (vec1 (vector nil))
+ (prefix1 (vconcat prefix vec1)))
+ ;; Scan OLDMAP, finding each char or event-symbol that
+ ;; has any definition, and act on it with hack-key.
+ (while (consp scan)
+ (if (consp (car scan))
+ (let ((char (car (car scan)))
+ (defn (cdr (car scan))))
+ ;; The inside of this let duplicates exactly
+ ;; the inside of the following let that handles array elements.
+ (aset vec1 0 char)
+ (aset prefix1 (length prefix) char)
+ (let (inner-def)
+ ;; Skip past menu-prompt.
+ (while (stringp (car-safe defn))
+ (setq defn (cdr defn)))
+ (setq inner-def defn)
+ (while (and (symbolp inner-def)
+ (fboundp inner-def))
+ (setq inner-def (symbol-function inner-def)))
+ (if (eq defn olddef)
+ (define-key keymap prefix1 newdef)
+ (if (keymapp defn)
+ (substitute-key-definition olddef newdef keymap
+ inner-def
+ prefix1)))))
+ (if (arrayp (car scan))
+ (let* ((array (car scan))
+ (len (length array))
+ (i 0))
+ (while (< i len)
+ (let ((char i) (defn (aref array i)))
+ ;; The inside of this let duplicates exactly
+ ;; the inside of the previous let.
+ (aset vec1 0 char)
+ (aset prefix1 (length prefix) char)
+ (let (inner-def)
+ ;; Skip past menu-prompt.
+ (while (stringp (car-safe defn))
+ (setq defn (cdr defn)))
+ (setq inner-def defn)
+ (while (and (symbolp inner-def)
+ (fboundp inner-def))
+ (setq inner-def (symbol-function inner-def)))
+ (if (eq defn olddef)
+ (define-key keymap prefix1 newdef)
+ (if (keymapp defn)
+ (substitute-key-definition olddef newdef keymap
+ inner-def
+ prefix1)))))
+ (setq i (1+ i))))))
+ (setq scan (cdr scan)))))
+\f
+(defun listify-key-sequence (key)
+ "Convert a key sequence to a list of events."
+ (if (vectorp key)
+ (append key nil)
+ (mapcar (function (lambda (c)
+ (if (> c 127)
+ (logxor c 8388736)
+ c)))
+ (append key nil))))
+
+(defsubst eventp (obj)
+ "True if the argument is an event object."
+ (or (integerp obj)
+ (and (symbolp obj)
+ (get obj 'event-symbol-elements))
+ (and (consp obj)
+ (symbolp (car obj))
+ (get (car obj) 'event-symbol-elements))))
+
+(defun event-modifiers (event)
+ "Returns a list of symbols representing the modifier keys in event EVENT.
+The elements of the list may include `meta', `control',
+`shift', `hyper', `super', `alt'.
+See also the function `event-modifier-bits'."
+ (let ((type event))
+ (if (listp type)
+ (setq type (car type)))
+ (if (symbolp type)
+ (cdr (get type 'event-symbol-elements))
+ (let ((list nil))
+ (or (zerop (logand type (lsh 1 23)))
+ (setq list (cons 'meta list)))
+ (or (and (zerop (logand type (lsh 1 22)))
+ (>= (logand type 127) 32))
+ (setq list (cons 'control list)))
+ (or (and (zerop (logand type (lsh 1 21)))
+ (= (logand type 255) (downcase (logand type 255))))
+ (setq list (cons 'shift list)))
+ (or (zerop (logand type (lsh 1 20)))
+ (setq list (cons 'hyper list)))
+ (or (zerop (logand type (lsh 1 19)))
+ (setq list (cons 'super list)))
+ (or (zerop (logand type (lsh 1 18)))
+ (setq list (cons 'alt list)))
+ list))))
+
+(defun event-basic-type (event)
+ "Returns the basic type of the given event (all modifiers removed).
+The value is an ASCII printing character (not upper case) or a symbol."
+ (if (symbolp event)
+ (car (get event 'event-symbol-elements))
+ (let ((base (logand event (1- (lsh 1 18)))))
+ (downcase (if (< base 32) (logior base 64) base)))))
+
+(defsubst mouse-movement-p (object)
+ "Return non-nil if OBJECT is a mouse movement event."
+ (and (consp object)
+ (eq (car object) 'mouse-movement)))
+
+(defsubst event-start (event)
+ "Return the starting position of EVENT.
+If EVENT is a mouse press or a mouse click, this returns the location
+of the event.
+If EVENT is a drag, this returns the drag's starting position.
+The return value is of the form
+ (WINDOW BUFFER-POSITION (COL . ROW) TIMESTAMP)
+The `posn-' functions access elements of such lists."
+ (nth 1 event))