* subr.el (map-keymap-sorted): Rename from map-keymap-internal.
[bpt/emacs.git] / lisp / subr.el
index 16cb891..b23ca35 100644 (file)
@@ -1,7 +1,7 @@
 ;;; subr.el --- basic lisp subroutines for Emacs
 
 ;; Copyright (C) 1985, 1986, 1992, 1994, 1995, 1999, 2000, 2001, 2002, 2003,
-;;   2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;;   2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: internal
@@ -36,6 +36,42 @@ Each element of this list holds the arguments to one call to `defcustom'.")
   (setq custom-declare-variable-list
        (cons arguments custom-declare-variable-list)))
 
+(defmacro declare-function (fn file &optional arglist fileonly)
+  "Tell the byte-compiler that function FN is defined, in FILE.
+Optional ARGLIST is the argument list used by the function.  The
+FILE argument is not used by the byte-compiler, but by the
+`check-declare' package, which checks that FILE contains a
+definition for FN.  ARGLIST is used by both the byte-compiler and
+`check-declare' to check for consistency.
+
+FILE can be either a Lisp file (in which case the \".el\"
+extension is optional), or a C file.  C files are expanded
+relative to the Emacs \"src/\" directory.  Lisp files are
+searched for using `locate-library', and if that fails they are
+expanded relative to the location of the file containing the
+declaration.  A FILE with an \"ext:\" prefix is an external file.
+`check-declare' will check such files if they are found, and skip
+them without error if they are not.
+
+FILEONLY non-nil means that `check-declare' will only check that
+FILE exists, not that it defines FN.  This is intended for
+function-definitions that `check-declare' does not recognize, e.g.
+`defstruct'.
+
+To specify a value for FILEONLY without passing an argument list,
+set ARGLIST to `t'.  This is necessary because `nil' means an
+empty argument list, rather than an unspecified one.
+
+Note that for the purposes of `check-declare', this statement
+must be the first non-whitespace on a line, and everything up to
+the end of FILE must be all on the same line.  For example:
+
+\(declare-function c-end-of-defun \"progmodes/cc-cmds.el\"
+                  \(&optional arg))
+
+For more information, see Info node `elisp(Declaring Functions)'."
+  ;; Does nothing - byte-compile-declare-function does the work.
+  nil)
 \f
 ;;;; Basic Lisp macros.
 
@@ -496,25 +532,23 @@ The order of bindings in a keymap matters when it is used as a menu."
            (setq inserted t)))
       (setq tail (cdr tail)))))
 
-(defun map-keymap-internal (function keymap &optional sort-first)
+(defun map-keymap-sorted (function keymap)
   "Implement `map-keymap' with sorting.
 Don't call this function; it is for internal use only."
-  (if sort-first
-      (let (list)
-       (map-keymap (lambda (a b) (push (cons a b) list))
-                   keymap)
-       (setq list (sort list
-                        (lambda (a b)
-                          (setq a (car a) b (car b))
-                          (if (integerp a)
-                              (if (integerp b) (< a b)
-                                t)
-                            (if (integerp b) t
-                               ;; string< also accepts symbols.
-                              (string< a b))))))
-       (dolist (p list)
-         (funcall function (car p) (cdr p))))
-    (map-keymap function keymap)))
+  (let (list)
+    (map-keymap (lambda (a b) (push (cons a b) list))
+                keymap)
+    (setq list (sort list
+                     (lambda (a b)
+                       (setq a (car a) b (car b))
+                       (if (integerp a)
+                           (if (integerp b) (< a b)
+                             t)
+                         (if (integerp b) t
+                           ;; string< also accepts symbols.
+                           (string< a b))))))
+    (dolist (p list)
+      (funcall function (car p) (cdr p)))))
 
 (put 'keyboard-translate-table 'char-table-extra-slots 0)
 
@@ -723,7 +757,9 @@ even when EVENT actually has modifiers."
     (if (listp type)
        (setq type (car type)))
     (if (symbolp type)
-       (cdr (get type 'event-symbol-elements))
+        ;; Don't read event-symbol-elements directly since we're not
+        ;; sure the symbol has already been parsed.
+       (cdr (internal-event-symbol-parse-modifiers type))
       (let ((list nil)
            (char (logand type (lognot (logior ?\M-\^@ ?\C-\^@ ?\S-\^@
                                               ?\H-\^@ ?\s-\^@ ?\A-\^@)))))
@@ -858,7 +894,8 @@ and `event-end' functions."
             (x (/ (car pair) (frame-char-width frame)))
             (y (/ (cdr pair) (+ (frame-char-height frame)
                                 (or (frame-parameter frame 'line-spacing)
-                                    default-line-spacing
+                                     ;; FIXME: Why the `default'?
+                                    (default-value 'line-spacing)
                                     0)))))
        (cons x y))))))
 
@@ -945,10 +982,17 @@ is converted into a string by expressing it in decimal."
 (make-obsolete 'focus-frame "it does nothing." "22.1")
 (defalias 'unfocus-frame 'ignore "")
 (make-obsolete 'unfocus-frame "it does nothing." "22.1")
-(make-obsolete 'make-variable-frame-local "use a frame-parameter instead" "22.2")
+(make-obsolete 'make-variable-frame-local "use a frame-parameter instead." "22.2")
 \f
 ;;;; Obsolescence declarations for variables, and aliases.
 
+(make-obsolete-variable 'redisplay-end-trigger-functions 'jit-lock-register "23.1")
+(make-obsolete 'window-redisplay-end-trigger nil "23.1")
+(make-obsolete 'set-window-redisplay-end-trigger nil "23.1")
+
+(make-obsolete 'process-filter-multibyte-p nil "23.1")
+(make-obsolete 'set-process-filter-multibyte nil "23.1")
+
 (make-obsolete-variable 'directory-sep-char "do not use it." "21.1")
 (make-obsolete-variable
  'mode-line-inverse-video
@@ -1064,7 +1108,17 @@ function, it is changed to a list of functions."
                (append hook-value (list function))
              (cons function hook-value))))
     ;; Set the actual variable
-    (if local (set hook hook-value) (set-default hook hook-value))))
+    (if local
+       (progn
+         ;; If HOOK isn't a permanent local,
+         ;; but FUNCTION wants to survive a change of modes,
+         ;; mark HOOK as partially permanent.
+         (and (symbolp function)
+              (get function 'permanent-local-hook)
+              (not (get hook 'permanent-local))
+              (put hook 'permanent-local 'permanent-local-hook))
+         (set hook hook-value))
+      (set-default hook hook-value))))
 
 (defun remove-hook (hook function &optional local)
   "Remove from the value of HOOK the function FUNCTION.
@@ -1392,7 +1446,6 @@ definition only or variable definition only.
        (setq files (cdr files)))
       file)))
 
-;;;###autoload
 (defun locate-library (library &optional nosuffix path interactive-call)
   "Show the precise file name of Emacs library LIBRARY.
 This command searches the directories in `load-path' like `\\[load-library]'
@@ -1537,6 +1590,23 @@ FILE should be the name of a library, with no directory name."
 \f
 ;;;; Process stuff.
 
+(defun process-lines (program &rest args)
+  "Execute PROGRAM with ARGS, returning its output as a list of lines.
+Signal an error if the program returns with a non-zero exit status."
+  (with-temp-buffer
+    (let ((status (apply 'call-process program nil (current-buffer) nil args)))
+      (unless (eq status 0)
+       (error "%s exited with status %s" program status))
+      (goto-char (point-min))
+      (let (lines)
+       (while (not (eobp))
+         (setq lines (cons (buffer-substring-no-properties
+                            (line-beginning-position)
+                            (line-end-position))
+                           lines))
+         (forward-line 1))
+       (nreverse lines)))))
+
 ;; open-network-stream is a wrapper around make-network-process.
 
 (when (featurep 'make-network-process)
@@ -1627,7 +1697,10 @@ any other non-digit terminates the character code and is then used as input."))
       ;; We could try and use read-key-sequence instead, but then C-q ESC
       ;; or C-q C-x might not return immediately since ESC or C-x might be
       ;; bound to some prefix in function-key-map or key-translation-map.
-      (setq translated char)
+      (setq translated
+           (if (integerp char)
+               (char-resolve-modifers char)
+             char))
       (let ((translation (lookup-key local-function-key-map (vector char))))
        (if (arrayp translation)
            (setq translated (aref translation 0))))
@@ -1765,9 +1838,10 @@ in milliseconds; this was useful when Emacs was built without
 floating point support.
 
 \(fn SECONDS &optional NODISP)"
-  (when (or obsolete (numberp nodisp))
-    (setq seconds (+ seconds (* 1e-3 nodisp)))
-    (setq nodisp obsolete))
+  (if (numberp nodisp)
+      (setq seconds (+ seconds (* 1e-3 nodisp))
+            nodisp obsolete)
+    (if obsolete (setq nodisp obsolete)))
   (cond
    (noninteractive
     (sleep-for seconds)
@@ -1804,6 +1878,10 @@ user can undo the change normally."
   (let ((handle (make-symbol "--change-group-handle--"))
        (success (make-symbol "--change-group-success--")))
     `(let ((,handle (prepare-change-group))
+          ;; Don't truncate any undo data in the middle of this.
+          (undo-outer-limit nil)
+          (undo-limit most-positive-fixnum)
+          (undo-strong-limit most-positive-fixnum)
           (,success nil))
        (unwind-protect
           (progn
@@ -1873,24 +1951,25 @@ This finishes the change group by reverting all of its changes."
     (with-current-buffer (car elt)
       (setq elt (cdr elt))
       (let ((old-car
-            (if (consp elt) (car elt)))
-           (old-cdr
-            (if (consp elt) (cdr elt))))
-       ;; Temporarily truncate the undo log at ELT.
-       (when (consp elt)
-         (setcar elt nil) (setcdr elt nil))
-       (unless (eq last-command 'undo) (undo-start))
-       ;; Make sure there's no confusion.
-       (when (and (consp elt) (not (eq elt (last pending-undo-list))))
-         (error "Undoing to some unrelated state"))
-       ;; Undo it all.
-       (while (listp pending-undo-list) (undo-more 1))
-       ;; Reset the modified cons cell ELT to its original content.
-       (when (consp elt)
-         (setcar elt old-car)
-         (setcdr elt old-cdr))
-       ;; Revert the undo info to what it was when we grabbed the state.
-       (setq buffer-undo-list elt)))))
+             (if (consp elt) (car elt)))
+            (old-cdr
+             (if (consp elt) (cdr elt))))
+        ;; Temporarily truncate the undo log at ELT.
+        (when (consp elt)
+          (setcar elt nil) (setcdr elt nil))
+        (unless (eq last-command 'undo) (undo-start))
+        ;; Make sure there's no confusion.
+        (when (and (consp elt) (not (eq elt (last pending-undo-list))))
+          (error "Undoing to some unrelated state"))
+        ;; Undo it all.
+        (save-excursion
+          (while (listp pending-undo-list) (undo-more 1)))
+        ;; Reset the modified cons cell ELT to its original content.
+        (when (consp elt)
+          (setcar elt old-car)
+          (setcdr elt old-cdr))
+        ;; Revert the undo info to what it was when we grabbed the state.
+        (setq buffer-undo-list elt)))))
 \f
 ;;;; Display-related functions.
 
@@ -2057,26 +2136,29 @@ Note that this should end with a directory separator.")
 (defun find-tag-default ()
   "Determine default tag to search for, based on text at point.
 If there is no plausible default, return nil."
-  (save-excursion
-    (while (looking-at "\\sw\\|\\s_")
-      (forward-char 1))
-    (if (or (re-search-backward "\\sw\\|\\s_"
-                               (save-excursion (beginning-of-line) (point))
-                               t)
-           (re-search-forward "\\(\\sw\\|\\s_\\)+"
-                              (save-excursion (end-of-line) (point))
-                              t))
-       (progn
-         (goto-char (match-end 0))
-         (condition-case nil
-             (buffer-substring-no-properties
-              (point)
-              (progn (forward-sexp -1)
-                     (while (looking-at "\\s'")
-                       (forward-char 1))
-                     (point)))
-           (error nil)))
-      nil)))
+  (let (from to bound)
+    (when (or (progn
+               ;; Look at text around `point'.
+               (save-excursion
+                 (skip-syntax-backward "w_") (setq from (point)))
+               (save-excursion
+                 (skip-syntax-forward "w_") (setq to (point)))
+               (> to from))
+             ;; Look between `line-beginning-position' and `point'.
+             (save-excursion
+               (and (setq bound (line-beginning-position))
+                    (skip-syntax-backward "^w_" bound)
+                    (> (setq to (point)) bound)
+                    (skip-syntax-backward "w_")
+                    (setq from (point))))
+             ;; Look between `point' and `line-end-position'.
+             (save-excursion
+               (and (setq bound (line-end-position))
+                    (skip-syntax-forward "^w_" bound)
+                    (< (setq from (point)) bound)
+                    (skip-syntax-forward "w_")
+                    (setq to (point)))))
+      (buffer-substring-no-properties from to))))
 
 (defun play-sound (sound)
   "SOUND is a list of the form `(sound KEYWORD VALUE...)'.
@@ -2099,6 +2181,8 @@ a system-dependent default device name is used."
       (play-sound-internal sound)
     (error "This Emacs binary lacks sound support")))
 
+(declare-function w32-shell-dos-semantics "w32-fns" nil)
+
 (defun shell-quote-argument (argument)
   "Quote an argument for passing as argument to an inferior shell."
   (if (or (eq system-type 'ms-dos)
@@ -2519,7 +2603,7 @@ If BODY finishes, `while-no-input' returns whatever value BODY produced."
        (catch ',catch-sym
         (let ((throw-on-input ',catch-sym))
           (or (input-pending-p)
-              ,@body))))))
+              (progn ,@body)))))))
 
 (defmacro condition-case-no-debug (var bodyform &rest handlers)
   "Like `condition-case' except that it does not catch anything when debugging.