Synch to No Gnus 200509052359.
[elisp/gnus.git-] / lisp / gnus-spec.el
index 9424123..187e3e5 100644 (file)
@@ -1,6 +1,7 @@
 ;;; gnus-spec.el --- format spec functions for Gnus
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
-;;        Free Software Foundation, Inc.
+
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Katsumi Yamaoka <yamaoka@jpl.org>
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(defvar gnus-newsrc-file-version)
 
 (require 'alist)
 (require 'gnus)
 
 (defcustom gnus-use-correct-string-widths t
   "*If non-nil, use correct functions for dealing with wide characters."
+  :version "22.1"
   :group 'gnus-format
   :type 'boolean)
 
 (defcustom gnus-make-format-preserve-properties (featurep 'xemacs)
   "*If non-nil, use a replacement `format' function which preserves
 text properties. This is only needed on XEmacs, as FSF Emacs does this anyway."
+  :version "22.1"
   :group 'gnus-format
   :type 'boolean)
 
@@ -191,26 +195,33 @@ text properties. This is only needed on XEmacs, as FSF Emacs does this anyway."
     (lisp-interaction-mode)
     (insert (gnus-pp-to-string spec))))
 
-(put 'gnus-search-or-regist-spec 'lisp-indent-function 1)
-(defmacro gnus-search-or-regist-spec (mspec &rest body)
-  (let ((specs (nth 0 mspec)) (type (nth 1 mspec)) (format (nth 2 mspec))
-       (spec (nth 3 mspec)) (entry (nth 4 mspec)) (elem (nth 5 mspec)))
-    `(let* ((,entry (assq ,type ,specs))
-           (,elem (assoc ,format (cdr ,entry))))
-       (or (cdr ,elem)
-          (when (progn ,@body)
-            (if ,entry
-                (if ,elem
-                    (setcdr ,elem ,spec)
-                  (setcdr ,entry (cons (cons ,format ,spec) (cdr ,entry))))
-              (push (list ,type (cons ,format ,spec)) ,specs))
-            (gnus-product-variable-touch (quote ,specs)))
-          ,spec))))
+(eval-when-compile (defvar unchanged))
+
+(put 'gnus-search-or-regist-spec 'lisp-indent-function 4)
+(defmacro gnus-search-or-regist-spec (specs type format val &rest body)
+  `(let* ((entry (assq ,type ,specs))
+         (elem (assoc ,format (cdr entry))))
+     ;; That `(cdr elem)' returns non-nil means the spec for `type'
+     ;; doesn't need to be updated.
+     (or (cdr elem)
+        ;; This variable is set beforehand.
+        (setq unchanged nil)
+        ;; Update the spec.  Where `body' will modify `val'.  This
+        ;; section will be skipped if compiling the spec is disabled.
+        (when (progn ,@body)
+          (if entry
+              (if elem
+                  (setcdr elem ,val)
+                (setcdr entry (cons (cons ,format ,val) (cdr entry))))
+            (push (list ,type (cons ,format ,val)) ,specs))
+          (gnus-product-variable-touch (quote ,specs)))
+        ;; Return the new spec without compiling.
+        ,val)))
 
 (defun gnus-update-format-specification-1 (type format val)
   (set (intern (format "gnus-%s-line-format-spec" type))
-       (gnus-search-or-regist-spec (gnus-format-specs-compiled
-                                   type format val entry elem)
+       (gnus-search-or-regist-spec
+          gnus-format-specs-compiled type format val
         (when (and gnus-compile-user-specs val)
           (setq val (prog1
                         (progn
@@ -235,49 +246,51 @@ Return a list of updated types."
          gnus-format-specs-compiled nil)
     (gnus-product-variable-touch 'gnus-format-specs
                                 'gnus-format-specs-compiled))
-  ;; Flush the group format spec cache if there's the grouplens stuff.
-  (let ((spec (assq 'group gnus-format-specs)))
-    (when (and (memq 'group types)
-              (string-match " gnus-tmp-grouplens[ )]"
-                            (gnus-prin1-to-string (cdr spec))))
-      (setq gnus-format-specs (delq spec gnus-format-specs)
-           spec (assq 'group gnus-format-specs-compiled)
-           gnus-format-specs-compiled (delq spec gnus-format-specs-compiled))))
+  ;; Flush the group format spec cache if there's the grouplens stuff
+  ;; or it doesn't support decoded group names.
+  (when (memq 'group types)
+    (let* ((spec (assq 'group gnus-format-specs))
+          (sspec (gnus-prin1-to-string (nth 2 spec))))
+      (when (or (string-match " gnus-tmp-grouplens[ )]" sspec)
+               (not (string-match " gnus-tmp-decoded-group[ )]" sspec)))
+       (setq gnus-format-specs (delq spec gnus-format-specs)
+             spec (assq 'group gnus-format-specs-compiled)
+             gnus-format-specs-compiled (delq spec
+                                              gnus-format-specs-compiled)))))
 
   ;; Go through all the formats and see whether they need updating.
-  (let (type val updated)
+  (let (new-format type val unchanged updated)
     (save-excursion
       (while (setq type (pop types))
        ;; Jump to the proper buffer to find out the value of the
        ;; variable, if possible.  (It may be buffer-local.)
-       (let ((new-format
-              (let ((buffer (intern (format "gnus-%s-buffer" type))))
-                (when (and (boundp buffer)
-                           (setq val (symbol-value buffer))
-                           (gnus-buffer-exists-p val))
-                  (set-buffer val))
-                (symbol-value
-                 (intern (format "gnus-%s-line-format" type))))))
-         (when
-             (or (gnus-update-format-specification-1 type new-format nil)
-                 ;; This is a new format.
-                 (gnus-update-format-specification-1
-                  type new-format
-                  (gnus-search-or-regist-spec (gnus-format-specs
-                                               type new-format val entry elem)
-                    (setq val
-                          (if (stringp new-format)
-                              ;; This is a "real" format.
-                              (gnus-parse-format
-                               new-format
-                               (symbol-value
-                                (intern (format "gnus-%s-line-format-alist"
-                                                type)))
-                               (not (string-match "mode$"
-                                                  (symbol-name type))))
-                            ;; This is a function call or something.
-                            new-format)))))
-           (push type updated)))))
+       (let ((buffer (intern (format "gnus-%s-buffer" type))))
+         (when (and (boundp buffer)
+                    (setq val (symbol-value buffer))
+                    (gnus-buffer-exists-p val))
+           (set-buffer val))
+         (setq new-format (symbol-value
+                           (intern (format "gnus-%s-line-format" type)))))
+       (setq unchanged t)
+       (or (gnus-update-format-specification-1 type new-format nil)
+           ;; This is a new format.
+           (gnus-update-format-specification-1
+            type new-format
+            (gnus-search-or-regist-spec
+                gnus-format-specs type new-format val
+              (setq val (if (stringp new-format)
+                            ;; This is a "real" format.
+                            (gnus-parse-format
+                             new-format
+                             (symbol-value
+                              (intern (format "gnus-%s-line-format-alist"
+                                              type)))
+                             (not (string-match "mode$"
+                                                (symbol-name type))))
+                          ;; This is a function call or something.
+                          new-format)))))
+       (unless unchanged
+         (push type updated))))
     updated))
 
 (defvar gnus-mouse-face-0 'highlight)
@@ -315,21 +328,15 @@ Return a list of updated types."
 
 (defun gnus-spec-tab (column)
   (if (> column 0)
-      `(insert (make-string (max (- ,column (current-column)) 0) ? ))
+      `(insert-char ?  (max (- ,column (current-column)) 0))
     (let ((column (abs column)))
-      (if gnus-use-correct-string-widths
-         `(progn
-            (if (> (current-column) ,column)
-                (while (progn
-                         (delete-backward-char 1)
-                         (> (current-column) ,column))))
-            (insert (make-string (max (- ,column (current-column)) 0) ? )))
-       `(progn
-          (if (> (current-column) ,column)
-              (delete-region (point)
-                             (- (point) (- (current-column) ,column)))
-            (insert (make-string (max (- ,column (current-column)) 0)
-                                 ? ))))))))
+      `(if (> (current-column) ,column)
+          (let ((end (point)))
+            (if (= (move-to-column ,column) ,column)
+                (delete-region (point) end)
+              (delete-region (1- (point)) end)
+              (insert " ")))
+        (insert-char ?  (max (- ,column (current-column)) 0))))))
 
 (defun gnus-correct-length (string)
   "Return the correct width of STRING."
@@ -548,7 +555,7 @@ are supported for %s."
         (t
          (if (null args)
              (error 'wrong-number-of-arguments #'my-format n fstring))
-         (let* ((minlen (string-to-int (or (match-string 2) "")))
+         (let* ((minlen (string-to-number (or (match-string 2) "")))
                 (arg (car args))
                 (str (if (stringp arg) arg (format "%s" arg)))
                 (lpad (null (match-string 1)))