Synch with Oort Gnus.
[elisp/gnus.git-] / lisp / gnus.el
index 5f7f346..c8e3e24 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus.el --- a newsreader for GNU Emacs
-;; Copyright (C) 1987, 1988, 1989, 1990, 1993, 1994, 1995, 1996,
+;; Copyright (C) 1987, 1988, 1989, 1990, 1993, 1994, 1995, 1996, 2001,
 ;;        1997, 1998, 2000, 2001 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
@@ -923,11 +923,11 @@ defaults to a proper value only if this file is byte-compiled by make.")
 REST is a plist of following:
 :type               One of `bool', `list' or `nil'.
 :function           The name of the function.
-:function-document  The document of the function.
+:function-document  The documentation of the function.
 :parameter-type     The type for customizing the parameter.
-:parameter-document The document for the parameter.
+:parameter-document The documentation for the parameter.
 :variable           The name of the variable.
-:variable-document  The document for the variable.
+:variable-document  The documentation for the variable.
 :variable-group     The group for customizing the variable.
 :variable-type      The type for customizing the variable.
 :variable-default   The default value of the variable."
@@ -1202,10 +1202,10 @@ list, Gnus will try all the methods in the list until it finds a match."
 
 (defcustom gnus-group-faq-directory
   '("/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
-    "/ftp@sunsite.auc.dk:/pub/usenet/"
     "/ftp@sunsite.doc.ic.ac.uk:/pub/usenet/news-faqs/"
     "/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
     "/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
+    "/ftp@ftp.pasteur.fr:/pub/FAQ/"
     "/ftp@rtfm.mit.edu:/pub/usenet/"
     "/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
     "/ftp@ftp.sunet.se:/pub/usenet/"
@@ -1232,7 +1232,7 @@ If the default site is too slow, try one of these:
    Europe:       ftp.uni-paderborn.de           /pub/FAQ
                  src.doc.ic.ac.uk               /usenet/news-FAQS
                  ftp.sunet.se                   /pub/usenet
-                 sunsite.auc.dk                 /pub/usenet
+                 ftp.pasteur.fr                 /pub/FAQ
    Asia:         nctuccca.edu.tw                /USENET/FAQ
                  hwarang.postech.ac.kr          /pub/usenet
                  ftp.hk.super.net               /mirror/faqs"
@@ -1631,9 +1631,8 @@ posting an article."
  :variable-group gnus-group-foreign
  :parameter-type
  '(choice :tag "Posting Method"
-         (const nil)
-         (const current)
-         (const native)
+         (const :tag "Use native server" native)
+         (const :tag "Use current server" current)
          (list :convert-widget
                (lambda (widget)
                  (list 'sexp :tag "Methods"
@@ -2418,6 +2417,21 @@ This restriction may disappear in later versions of Gnus."
 ;;; Gnus Utility Functions
 ;;;
 
+(defun gnus-find-subscribed-addresses ()
+  "Return a regexp matching the addresses of all subscribed mail groups.
+It consists of the `to-address' or `to-list' parameter of all groups
+with a `subscribed' parameter."
+  (let ((addresses))
+    (mapc (lambda (entry)
+           (let ((group (car entry)))
+             (when (gnus-group-find-parameter group 'subscribed)
+               (let ((address (or
+                               (gnus-group-fast-parameter group 'to-address)
+                               (gnus-group-fast-parameter group 'to-list))))
+                 (when address
+                   (setq addresses (cons address addresses)))))))
+         (cdr gnus-newsrc-alist))
+    (list (mapconcat 'regexp-quote addresses "\\|"))))
 
 (defmacro gnus-string-or (&rest strings)
   "Return the first element of STRINGS that is a non-blank string.
@@ -2595,16 +2609,18 @@ that that variable is buffer-local to the summary buffers."
 
 (defun gnus-news-group-p (group &optional article)
   "Return non-nil if GROUP (and ARTICLE) come from a news server."
-  (or (gnus-member-of-valid 'post group) ; Ordinary news group.
-      (and (gnus-member-of-valid 'post-mail group) ; Combined group.
-          (if (or (null article)
-                  (not (< article 0)))
-              (eq (gnus-request-type group article) 'news)
-            (if (not (vectorp article))
-                nil
-              ;; It's a real article.
-              (eq (gnus-request-type group (mail-header-id article))
-                  'news))))))
+  (cond ((gnus-member-of-valid 'post group) ;Ordinary news group
+        t)                             ;is news of course.
+       ((not (gnus-member-of-valid 'post-mail group)) ;Non-combined.
+        nil)                           ;must be mail then.
+       ((vectorp article)              ;Has header info.
+        (eq (gnus-request-type group (mail-header-id article)) 'news))
+       ((null article)                 ;Hasn't header info
+        (eq (gnus-request-type group) 'news)) ;(unknown ==> mail)
+       ((< article 0)                  ;Virtual message
+        nil)                           ;we don't know, guess mail.
+       (t                              ;Has positive number
+        (eq (gnus-request-type group article) 'news)))) ;use it.
 
 ;; Returns a list of writable groups.
 (defun gnus-writable-groups ()
@@ -2876,6 +2892,15 @@ You should probably use `gnus-find-method-for-group' instead."
                     params-list))))
     params-list))
 
+(defun gnus-expand-group-parameter (match value group)
+  "Use MATCH to expand VALUE in GROUP."
+  (with-temp-buffer
+    (insert group)
+    (goto-char (point-min))
+    (while (re-search-forward match nil t)
+      (replace-match value))
+    (buffer-string)))
+
 (defun gnus-expand-group-parameters (match parameters group)
   "Go through PARAMETERS and expand them according to the match data."
   (let (new)
@@ -2883,28 +2908,58 @@ You should probably use `gnus-find-method-for-group' instead."
       (if (and (stringp (cdr elem))
               (string-match "\\\\" (cdr elem)))
          (push (cons (car elem)
-                     (with-temp-buffer
-                       (insert group)
-                       (goto-char (point-min))
-                       (while (re-search-forward match nil t)
-                         (replace-match (cdr elem)))
-                       (buffer-string)))
+                     (gnus-expand-group-parameter match (cdr elem) group))
                new)
        (push elem new)))
     new))
 
+(defun gnus-group-fast-parameter (group symbol &optional allow-list)
+  "For GROUP, return the value of SYMBOL.
+
+You should call this in the `gnus-group-buffer' buffer.  
+The function `gnus-group-find-parameter' will do that for you."
+  ;; The speed trick:  No cons'ing and quit early.
+  (or (let ((params (funcall gnus-group-get-parameter-function group)))
+       ;; Start easy, check the "real" group parameters.
+       (gnus-group-parameter-value params symbol allow-list))
+      ;; We didn't found it there, try `gnus-parameters'.
+      (let ((result nil)
+           (head nil)
+           (tail gnus-parameters))
+       ;; A good old-fashioned non-cl loop.
+       (while tail
+         (setq head (car tail)
+               tail (cdr tail))
+         ;; The car is regexp matching for matching the group name.
+         (when (string-match (car head) group)
+           ;; The cdr is the parameters.
+           (setq result (gnus-group-parameter-value (cdr head) 
+                                                    symbol allow-list))
+           (when result
+             ;; Expand if necessary.
+             (if (and (stringp result) (string-match "\\\\" result))
+                 (setq result (gnus-expand-group-parameter (car head)
+                                                           result group)))
+             ;; Exit the loop early.
+             (setq tail nil))))
+       ;; Done.
+       result)))
+
 (defun gnus-group-find-parameter (group &optional symbol allow-list)
   "Return the group parameters for GROUP.
-If SYMBOL, return the value of that symbol in the group parameters."
+If SYMBOL, return the value of that symbol in the group parameters.
+
+If you call this function inside a loop, consider using the faster
+`gnus-group-fast-parameter' instead."
   (save-excursion
     (set-buffer gnus-group-buffer)
-    (let ((parameters
-          (nconc
-           (copy-sequence
-            (funcall gnus-group-get-parameter-function group))
-           (gnus-parameters-get-parameter group))))
-      (if symbol
-         (gnus-group-parameter-value parameters symbol allow-list)
+    (if symbol
+       (gnus-group-fast-parameter group symbol allow-list)
+      (let ((parameters
+            (nconc
+             (copy-sequence
+              (funcall gnus-group-get-parameter-function group))
+             (gnus-parameters-get-parameter group))))
        parameters))))
 
 (defun gnus-group-get-parameter (group &optional symbol allow-list)