(read-quoted-char): Convert function keys like Return
[bpt/emacs.git] / lisp / subr.el
index 83cc198..14ae2ba 100644 (file)
 ;; Boston, MA 02111-1307, USA.
 
 ;;; Code:
-
+(defvar custom-declare-variable-list nil
+  "Record `defcustom' calls made before `custom.el' is loaded to handle them.
+Each element of this list holds the arguments to one call to `defcustom'.")
+
+;; Use this rather that defcustom, in subr.el and other files loaded
+;; before custom.el.
+(defun custom-declare-variable-early (&rest arguments)
+  (setq custom-declare-variable-list
+       (cons arguments custom-declare-variable-list)))
 \f
 ;;;; Lisp language features.
 
@@ -43,17 +51,17 @@ BODY should be a list of lisp expressions."
   ;; depend on backquote.el.
   (list 'function (cons 'lambda cdr)))
 
-;;(defmacro defun-inline (name args &rest body)
-;;  "Create an \"inline defun\" (actually a macro).
-;;Use just like `defun'."
-;;  (nconc (list 'defmacro name '(&rest args))
-;;      (if (stringp (car body))
-;;          (prog1 (list (car body))
-;;            (setq body (or (cdr body) body))))
-;;      (list (list 'cons (list 'quote
-;;                              (cons 'lambda (cons args body)))
-;;                  'args))))
-
+(defmacro when (cond &rest body)
+  "(when COND BODY...): if COND yields non-nil, do BODY, else return nil."
+  (list 'if cond (cons 'progn body)))
+(put 'when 'lisp-indent-function 1)
+(put 'when 'edebug-form-spec '(&rest form))
+
+(defmacro unless (cond &rest body)
+  "(unless COND BODY...): if COND yields nil, do BODY, else return nil."
+  (cons 'if (cons cond (cons nil body))))
+(put 'unless 'lisp-indent-function 1)
+(put 'unless 'edebug-form-spec '(&rest form))
 \f
 ;;;; Keymap support.
 
@@ -125,7 +133,11 @@ in KEYMAP as NEWDEF those chars which are defined as OLDDEF in OLDMAP."
              (while (and (symbolp inner-def)
                          (fboundp inner-def))
                (setq inner-def (symbol-function inner-def)))
-             (if (eq defn olddef)
+             (if (or (eq defn olddef)
+                     ;; Compare with equal if definition is a key sequence.
+                     ;; That is useful for operating on function-key-map.
+                     (and (or (stringp defn) (vectorp defn))
+                          (equal defn olddef)))
                  (define-key keymap prefix1 (nconc (nreverse skipped) newdef))
                (if (and (keymapp defn)
                         ;; Avoid recursively scanning
@@ -141,7 +153,7 @@ in KEYMAP as NEWDEF those chars which are defined as OLDDEF in OLDMAP."
                    (substitute-key-definition olddef newdef keymap
                                               inner-def
                                               prefix1)))))
-       (if (arrayp (car scan))
+       (if (vectorp (car scan))
            (let* ((array (car scan))
                   (len (length array))
                   (i 0))
@@ -162,7 +174,9 @@ in KEYMAP as NEWDEF those chars which are defined as OLDDEF in OLDMAP."
                    (while (and (symbolp inner-def)
                                (fboundp inner-def))
                      (setq inner-def (symbol-function inner-def)))
-                   (if (eq defn olddef)
+                   (if (or (eq defn olddef)
+                           (and (or (stringp defn) (vectorp defn))
+                                (equal defn olddef)))
                        (define-key keymap prefix1
                          (nconc (nreverse skipped) newdef))
                      (if (and (keymapp defn)
@@ -174,17 +188,59 @@ in KEYMAP as NEWDEF those chars which are defined as OLDDEF in OLDMAP."
                          (substitute-key-definition olddef newdef keymap
                                                     inner-def
                                                     prefix1)))))
-               (setq i (1+ i))))))
+               (setq i (1+ i))))
+         (if (char-table-p (car scan))
+             (map-char-table
+              (function (lambda (char defn)
+                          (let ()
+                            ;; The inside of this let duplicates exactly
+                            ;; the inside of the previous let,
+                            ;; except that it uses set-char-table-range
+                            ;; instead of define-key.
+                            (aset vec1 0 char)
+                            (aset prefix1 (length prefix) char)
+                            (let (inner-def skipped)
+                              ;; Skip past menu-prompt.
+                              (while (stringp (car-safe defn))
+                                (setq skipped (cons (car defn) skipped))
+                                (setq defn (cdr defn)))
+                              (and (consp defn) (consp (car 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 (or (eq defn olddef)
+                                      (and (or (stringp defn) (vectorp defn))
+                                           (equal defn olddef)))
+                                  (define-key keymap prefix1
+                                    (nconc (nreverse skipped) newdef))
+                                (if (and (keymapp defn)
+                                         (let ((elt (lookup-key keymap prefix1)))
+                                           (or (null elt)
+                                               (keymapp elt)))
+                                         (not (memq inner-def
+                                                    key-substitution-in-progress)))
+                                    (substitute-key-definition olddef newdef keymap
+                                                               inner-def
+                                                               prefix1)))))))
+              (car scan)))))
       (setq scan (cdr scan)))))
 
 (defun define-key-after (keymap key definition after)
   "Add binding in KEYMAP for KEY => DEFINITION, right after AFTER's binding.
 This is like `define-key' except that the binding for KEY is placed
 just after the binding for the event AFTER, instead of at the beginning
-of the map.
-The order matters when the keymap is used as a menu.
+of the map.  Note that AFTER must be an event type (like KEY), NOT a command
+\(like DEFINITION).
+
+If AFTER is t, the new binding goes at the end of the keymap.
+
 KEY must contain just one event type--that is to say, it must be
-a string or vector of length 1."
+a string or vector of length 1.
+
+The order of bindings in a keymap matters when it is used as a menu."
+
   (or (keymapp keymap)
       (signal 'wrong-type-argument (list 'keymapp keymap)))
   (if (> (length key) 1)
@@ -198,7 +254,8 @@ a string or vector of length 1."
       ;; When we reach AFTER's binding, insert the new binding after.
       ;; If we reach an inherited keymap, insert just before that.
       ;; If we reach the end of this keymap, insert at the end.
-      (if (or (eq (car-safe (car tail)) after)
+      (if (or (and (eq (car-safe (car tail)) after)
+                  (not (eq after t)))
              (eq (car (cdr tail)) 'keymap)
              (null (cdr tail)))
          (progn
@@ -213,6 +270,12 @@ a string or vector of length 1."
            (setq inserted t)))
       (setq tail (cdr tail)))))
 
+(defmacro kbd (keys)
+  "Convert KEYS to the internal Emacs key representation.
+KEYS should be a string constant in the format used for
+saving keyboard macros (see `insert-kbd-macro')."
+  (read-kbd-macro keys))
+
 (put 'keyboard-translate-table 'char-table-extra-slots 0)
 
 (defun keyboard-translate (from to)
@@ -594,33 +657,66 @@ FILE should be the name of a library, with no directory name."
 \f
 ;;;; Input and display facilities.
 
+(defvar read-quoted-char-radix 8
+  "*Radix for \\[quoted-insert] and other uses of `read-quoted-char'.
+Legitimate radix values are 8, 10 and 16.")
+
+(custom-declare-variable-early
+ 'read-quoted-char-radix 8 
+ "*Radix for \\[quoted-insert] and other uses of `read-quoted-char'.
+Legitimate radix values are 8, 10 and 16."
+  :type '(choice (const 8) (const 10) (const 16))
+  :group 'editing-basics)
+
 (defun read-quoted-char (&optional prompt)
-  "Like `read-char', except that if the first character read is an octal
-digit, we read up to two more octal digits and return the character
-represented by the octal number consisting of those digits.
-Optional argument PROMPT specifies a string to use to prompt the user."
-  (let ((message-log-max nil) (count 0) (code 0) char)
-    (while (< count 3)
-      (let ((inhibit-quit (zerop count))
+  "Like `read-char', but do not allow quitting.
+Also, if the first character read is an octal digit,
+we read any number of octal digits and return the
+soecified character code.  Any nondigit terminates the sequence.
+If the terminator is RET, it is discarded;
+any other terminator is used itself as input.
+
+The optional argument PROMPT specifies a string to use to prompt the user."
+  (let ((message-log-max nil) done (first t) (code 0) char)
+    (while (not done)
+      (let ((inhibit-quit first)
            ;; Don't let C-h get the help message--only help function keys.
            (help-char nil)
            (help-form
             "Type the special character you want to use,
-or three octal digits representing its character code."))
+or the octal character code.
+RET terminates the character code and is discarded;
+any other non-digit terminates the character code and is then used as input."))
        (and prompt (message "%s-" prompt))
-       (setq char (read-char))
+       (setq char (read-event))
        (if inhibit-quit (setq quit-flag nil)))
+      ;; Translate TAB key into control-I ASCII character, and so on.
+      (and char
+          (let ((translated (lookup-key function-key-map (vector char))))
+            (if translated
+                (setq char (aref translated 0)))))
       (cond ((null char))
-           ((and (<= ?0 char) (<= char ?7))
-            (setq code (+ (* code 8) (- char ?0))
-                  count (1+ count))
+           ((not (integerp char))
+            (setq unread-command-events (list char)
+                  done t))
+           ((and (<= ?0 char) (< char (+ ?0 (min 10 read-quoted-char-radix))))
+            (setq code (+ (* code read-quoted-char-radix) (- char ?0)))
+            (and prompt (setq prompt (message "%s %c" prompt char))))
+           ((and (<= ?a (downcase char))
+                 (< (downcase char) (+ ?a -10 (min 26 read-quoted-char-radix))))
+            (setq code (+ (* code read-quoted-char-radix) (+ 10 (- char ?a))))
             (and prompt (setq prompt (message "%s %c" prompt char))))
-           ((> count 0)
-            (setq unread-command-events (list char) count 259))
-           (t (setq code char count 259))))
+           ((and (not first) (eq char ?\C-m))
+            (setq done t))
+           ((not first)
+            (setq unread-command-events (list char)
+                  done t))
+           (t (setq code char
+                    done t)))
+      (setq first nil))
     ;; Turn a meta-character into a character with the 0200 bit set.
     (logior (if (/= (logand code ?\M-\^@) 0) 128 0)
-           (logand 255 code))))
+           code)))
 
 (defun force-mode-line-update (&optional all)
   "Force the mode-line of the current buffer to be redisplayed.
@@ -783,6 +879,24 @@ See also `with-temp-file' and `with-output-to-string'."
        (prog1
           (buffer-string)
         (kill-buffer nil)))))
+
+(defmacro combine-after-change-calls (&rest body)
+  "Execute BODY, but don't call the after-change functions till the end.
+If BODY makes changes in the buffer, they are recorded
+and the functions on `after-change-functions' are called several times
+when BODY is finished.
+The return value is the value of the last form in BODY.
+
+If `before-change-functions' is non-nil, then calls to the after-change
+functions can't be deferred, so in that case this macro has no effect.
+
+Do not alter `after-change-functions' or `before-change-functions'
+in BODY."
+  `(unwind-protect
+       (let ((combine-after-change-calls t))
+        . ,body)
+     (combine-after-change-execute)))
+
 \f
 (defvar save-match-data-internal)
 
@@ -836,20 +950,24 @@ If SEPARATORS is absent, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
       argument
     (if (eq system-type 'windows-nt)
        (concat "\"" argument "\"")
-      ;; Quote everything except POSIX filename characters.
-      ;; This should be safe enough even for really weird shells.
-      (let ((result "") (start 0) end)
-       (while (string-match "[^-0-9a-zA-Z_./]" argument start)
-         (setq end (match-beginning 0)
-               result (concat result (substring argument start end)
-                              "\\" (substring argument end (1+ end)))
-               start (1+ end)))
-       (concat result (substring argument start))))))
+      (if (equal argument "")
+         "''"
+       ;; Quote everything except POSIX filename characters.
+       ;; This should be safe enough even for really weird shells.
+       (let ((result "") (start 0) end)
+         (while (string-match "[^-0-9a-zA-Z_./]" argument start)
+           (setq end (match-beginning 0)
+                 result (concat result (substring argument start end)
+                                "\\" (substring argument end (1+ end)))
+                 start (1+ end)))
+         (concat result (substring argument start)))))))
 
 (defun make-syntax-table (&optional oldtable)
   "Return a new syntax table.
-It inherits all letters and control characters from the standard
-syntax table; other characters are copied from the standard syntax table."
+If OLDTABLE is non-nil, copy OLDTABLE.
+Otherwise, create a syntax table which inherits
+all letters and control characters from the standard syntax table;
+other characters are copied from the standard syntax table."
   (if oldtable
       (copy-syntax-table oldtable)
     (let ((table (copy-syntax-table))
@@ -871,6 +989,22 @@ syntax table; other characters are copied from the standard syntax table."
        (aset table i nil)
        (setq i (1+ i)))
       table)))
+
+(defun add-to-invisibility-spec (arg)
+  "Add elements to `buffer-invisibility-spec'.
+See documentation for `buffer-invisibility-spec' for the kind of elements
+that can be added."
+  (cond
+   ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
+       (setq buffer-invisibility-spec (list arg)))
+   (t
+    (setq buffer-invisibility-spec
+         (cons arg buffer-invisibility-spec)))))
+
+(defun remove-from-invisibility-spec (arg)
+  "Remove elements from `buffer-invisibility-spec'."
+  (if buffer-invisibility-spec
+    (setq buffer-invisibility-spec (delete arg buffer-invisibility-spec))))
 \f
 (defun global-set-key (key command)
   "Give KEY a global binding as COMMAND.
@@ -926,6 +1060,12 @@ configuration."
   (and (consp object)
        (eq (car object) 'frame-configuration)))
 
+(defun functionp (object)
+  "Non-nil if OBJECT is a type of object that can be called as a function."
+  (or (subrp object) (compiled-function-p object)
+      (eq (car-safe object) 'lambda)
+      (and (symbolp object) (fboundp object))))
+
 ;; now in fns.c
 ;(defun nth (n list)
 ;  "Returns the Nth element of LIST.
@@ -947,4 +1087,3 @@ configuration."
 ;  alist)
 
 ;;; subr.el ends here
-