* spam.el (spam-list-of-processors): use nil for nonexistent processors
[gnus] / lisp / gnus.el
index 42f839e..2377eab 100644 (file)
@@ -1,7 +1,7 @@
 ;;; gnus.el --- a newsreader for GNU Emacs
 
 ;; Copyright (C) 1987, 1988, 1989, 1990, 1993, 1994, 1995, 1996, 1997,
-;; 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+;; 1998, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -70,7 +70,7 @@
 ;; These belong to gnus-group.el.
 (defgroup gnus-group nil
   "Group buffers."
-  :link '(custom-manual "(gnus)The Group Buffer")
+  :link '(custom-manual "(gnus)Group Buffer")
   :group 'gnus)
 
 (defgroup gnus-group-foreign nil
 ;; These belong to gnus-sum.el.
 (defgroup gnus-summary nil
   "Summary buffers."
-  :link '(custom-manual "(gnus)The Summary Buffer")
+  :link '(custom-manual "(gnus)Summary Buffer")
   :group 'gnus)
 
 (defgroup gnus-summary-exit nil
 
 (defgroup gnus-summary-sort nil
   "Sorting the summary buffer."
-  :link '(custom-manual "(gnus)Sorting")
+  :link '(custom-manual "(gnus)Summary Sorting")
   :group 'gnus-summary)
 
 (defgroup gnus-summary-visual nil
@@ -282,10 +282,10 @@ is restarted, and sometimes reloaded."
   :link '(custom-manual "(gnus)Exiting Gnus")
   :group 'gnus)
 
-(defconst gnus-version-number "5.10.3"
+(defconst gnus-version-number "0.3"
   "Version number for this version of Gnus.")
 
-(defconst gnus-version (format "Gnus v%s" gnus-version-number)
+(defconst gnus-version (format "No Gnus v%s" gnus-version-number)
   "Version string for this version of Gnus.")
 
 (defcustom gnus-inhibit-startup-message nil
@@ -303,9 +303,6 @@ be set in `.emacs' instead."
 (unless (fboundp 'gnus-group-remove-excess-properties)
   (defalias 'gnus-group-remove-excess-properties 'ignore))
 
-(unless (fboundp 'gnus-set-text-properties)
-  (defalias 'gnus-set-text-properties 'set-text-properties))
-
 (unless (featurep 'gnus-xmas)
   (defalias 'gnus-make-overlay 'make-overlay)
   (defalias 'gnus-delete-overlay 'delete-overlay)
@@ -316,7 +313,6 @@ be set in `.emacs' instead."
   (defalias 'gnus-overlay-end 'overlay-end)
   (defalias 'gnus-extent-detached-p 'ignore)
   (defalias 'gnus-extent-start-open 'ignore)
-  (defalias 'gnus-appt-select-lowest-window 'appt-select-lowest-window)
   (defalias 'gnus-mail-strip-quoted-names 'mail-strip-quoted-names)
   (defalias 'gnus-character-to-event 'identity)
   (defalias 'gnus-assq-delete-all 'assq-delete-all)
@@ -339,7 +335,9 @@ be set in `.emacs' instead."
                                         (:type xbm :file "gnus-pointer.xbm"
                                                :ascent center))))
                              gnus-mode-line-image-cache)
-                           'help-echo "This is Gnus")
+                           'help-echo (format
+                                       "This is %s, %s."
+                                       gnus-version (gnus-emacs-version)))
                      str)
                     (list str))
            line)))
@@ -849,12 +847,12 @@ be set in `.emacs' instead."
     (storm "#666699" "#99ccff")
     (pdino "#9999cc" "#99ccff")
     (purp "#9999cc" "#666699")
-    (no "#000000" "#ff0000")
+    (no "#ff0000" "#ffff00")
     (neutral "#b4b4b4" "#878787")
     (september "#bf9900" "#ffcc00"))
   "Color alist used for the Gnus logo.")
 
-(defcustom gnus-logo-color-style 'oort
+(defcustom gnus-logo-color-style 'no
   "*Color styles used for the Gnus logo."
   :type `(choice ,@(mapcar (lambda (elem) (list 'const (car elem)))
                           gnus-logo-color-alist))
@@ -938,10 +936,10 @@ be set in `.emacs' instead."
 
 (eval-when (load)
   (let ((command (format "%s" this-command)))
-    (if (and (string-match "gnus" command)
-            (not (string-match "gnus-other-frame" command)))
-       (gnus-splash)
-      (gnus-get-buffer-create gnus-group-buffer))))
+    (when (string-match "gnus" command)
+      (if (string-match "gnus-other-frame" command)
+         (gnus-get-buffer-create gnus-group-buffer)
+       (gnus-splash)))))
 
 ;;; Do the rest.
 
@@ -1093,21 +1091,16 @@ used to 899, you would say something along these lines:
   :group 'gnus-server
   :type 'file)
 
-;; This function is used to check both the environment variable
-;; NNTPSERVER and the /etc/nntpserver file to see whether one can find
-;; an nntp server name default.
 (defun gnus-getenv-nntpserver ()
+  "Find default nntp server.
+Check the NNTPSERVER environment variable and the
+`gnus-nntpserver-file' file."
   (or (getenv "NNTPSERVER")
       (and (file-readable-p gnus-nntpserver-file)
-          (save-excursion
-            (set-buffer (gnus-get-buffer-create " *gnus nntp*"))
+          (with-temp-buffer
             (insert-file-contents gnus-nntpserver-file)
-            (let ((name (buffer-string)))
-              (prog1
-                  (if (string-match "\\'[ \t\n]*$" name)
-                      nil
-                    name)
-                (kill-buffer (current-buffer))))))))
+            (when (re-search-forward "[^ \t\n\r]+" nil t)
+              (match-string 0))))))
 
 (defcustom gnus-select-method
   (condition-case nil
@@ -1416,11 +1409,6 @@ cache to the full extent of the law."
   :group 'gnus-meta
   :type 'boolean)
 
-(defcustom gnus-use-grouplens nil
-  "*If non-nil, use GroupLens ratings."
-  :group 'gnus-meta
-  :type 'boolean)
-
 (defcustom gnus-keep-backlog 20
   "*If non-nil, Gnus will keep read articles for later re-retrieval.
 If it is a number N, then Gnus will only keep the last N articles
@@ -1835,51 +1823,69 @@ This only makes sense for mail groups."
    "The spam classification (spam, ham, or neither) of this group.
 When a spam group is entered, all unread articles are marked as spam.")
 
+  (gnus-define-group-parameter
+   spam-resend-to
+   :type list
+   :function-document
+   "The address to get spam resent (through spam-report-resend)."
+   :variable gnus-spam-resend-to
+   :variable-default nil
+   :variable-document
+   "The address to get spam resent (through spam-report-resend)."
+   :variable-group spam
+   :variable-type '(repeat
+                   (list :tag "Group address for resending spam"
+                         (regexp :tag "Group")
+                         (string :tag "E-mail address for resending spam (requires the spam-use-resend exit processor)")))
+   :parameter-type 'string :tag "E-mail address for resending spam (requires the spam-use-resend exit processor)"
+   :parameter-document
+   "The address to get spam resent (through spam-report-resend).")
+
   (defvar gnus-group-spam-exit-processor-ifile "ifile"
-    "The ifile summary exit spam processor.")
+    "OBSOLETE: The ifile summary exit spam processor.")
 
   (defvar gnus-group-spam-exit-processor-stat "stat"
-    "The spam-stat summary exit spam processor.")
+    "OBSOLETE: The spam-stat summary exit spam processor.")
 
   (defvar gnus-group-spam-exit-processor-bogofilter "bogofilter"
-    "The Bogofilter summary exit spam processor.")
+    "OBSOLETE: The Bogofilter summary exit spam processor.")
 
   (defvar gnus-group-spam-exit-processor-blacklist "blacklist"
-    "The Blacklist summary exit spam processor.")
+    "OBSOLETE: The Blacklist summary exit spam processor.")
 
   (defvar gnus-group-spam-exit-processor-report-gmane "report-gmane"
-    "The Gmane reporting summary exit spam processor.
+    "OBSOLETE: The Gmane reporting summary exit spam processor.
 Only applicable to NNTP groups with articles from Gmane.  See spam-report.el")
 
   (defvar gnus-group-spam-exit-processor-spamoracle "spamoracle-spam"
-    "The spamoracle summary exit spam processor.")
+    "OBSOLETE: The spamoracle summary exit spam processor.")
 
   (defvar gnus-group-ham-exit-processor-ifile "ifile-ham"
-    "The ifile summary exit ham processor.
+    "OBSOLETE: The ifile summary exit ham processor.
 Only applicable to non-spam (unclassified and ham) groups.")
 
   (defvar gnus-group-ham-exit-processor-bogofilter "bogofilter-ham"
-    "The Bogofilter summary exit ham processor.
+    "OBSOLETE: The Bogofilter summary exit ham processor.
 Only applicable to non-spam (unclassified and ham) groups.")
 
   (defvar gnus-group-ham-exit-processor-stat "stat-ham"
-    "The spam-stat summary exit ham processor.
+    "OBSOLETE: The spam-stat summary exit ham processor.
 Only applicable to non-spam (unclassified and ham) groups.")
 
   (defvar gnus-group-ham-exit-processor-whitelist "whitelist"
-    "The whitelist summary exit ham processor.
+    "OBSOLETE: The whitelist summary exit ham processor.
 Only applicable to non-spam (unclassified and ham) groups.")
 
   (defvar gnus-group-ham-exit-processor-BBDB "bbdb"
-    "The BBDB summary exit ham processor.
+    "OBSOLETE: The BBDB summary exit ham processor.
 Only applicable to non-spam (unclassified and ham) groups.")
 
   (defvar gnus-group-ham-exit-processor-copy "copy"
-    "The ham copy exit ham processor.
+    "OBSOLETE: The ham copy exit ham processor.
 Only applicable to non-spam (unclassified and ham) groups.")
 
   (defvar gnus-group-ham-exit-processor-spamoracle "spamoracle-ham"
-    "The spamoracle summary exit ham processor.
+    "OBSOLETE: The spamoracle summary exit ham processor.
 Only applicable to non-spam (unclassified and ham) groups.")
 
   (gnus-define-group-parameter
@@ -1891,19 +1897,39 @@ Only applicable to non-spam (unclassified and ham) groups.")
      :value nil
      (list :tag "Spam Summary Exit Processor Choices"
           (set
+           (const :tag "Spam: Bogofilter"    (spam spam-use-bogofilter))
+           (const :tag "Spam: Blacklist"     (spam spam-use-blacklist))
+           (const :tag "Spam: Bsfilter"      (spam spam-use-bsfilter))
+           (const :tag "Spam: Gmane Report"  (spam spam-use-gmane))
+           (const :tag "Spam: Resend Message"(spam spam-use-resend))
+           (const :tag "Spam: ifile"         (spam spam-use-ifile))
+           (const :tag "Spam: Spam Oracle"   (spam spam-use-spamoracle))
+           (const :tag "Spam: Spam-stat"     (spam spam-use-stat))
+           (const :tag "Spam: SpamAssassin"  (spam spam-use-spamassassin))
+           (const :tag "Spam: CRM114"        (spam spam-use-crm114))
+           (const :tag "Ham: BBDB"           (ham spam-use-BBDB))
+           (const :tag "Ham: Bogofilter"     (ham spam-use-bogofilter))
+           (const :tag "Ham: Bsfilter"       (ham spam-use-bsfilter))
+           (const :tag "Ham: Copy"           (ham spam-use-ham-copy))
+           (const :tag "Ham: ifile"          (ham spam-use-ifile))
+           (const :tag "Ham: Spam Oracle"    (ham spam-use-spamoracle))
+           (const :tag "Ham: Spam-stat"      (ham spam-use-stat))
+           (const :tag "Ham: SpamAssassin"   (ham spam-use-spamassassin))
+           (const :tag "Ham: CRM114"         (ham spam-use-crm114))
+           (const :tag "Ham: Whitelist"      (ham spam-use-whitelist))
            (variable-item gnus-group-spam-exit-processor-ifile)
            (variable-item gnus-group-spam-exit-processor-stat)
            (variable-item gnus-group-spam-exit-processor-bogofilter)
            (variable-item gnus-group-spam-exit-processor-blacklist)
-           (variable-item gnus-group-spam-exit-processor-report-gmane)
            (variable-item gnus-group-spam-exit-processor-spamoracle)
+           (variable-item gnus-group-spam-exit-processor-report-gmane)
            (variable-item gnus-group-ham-exit-processor-bogofilter)
            (variable-item gnus-group-ham-exit-processor-ifile)
            (variable-item gnus-group-ham-exit-processor-stat)
            (variable-item gnus-group-ham-exit-processor-whitelist)
            (variable-item gnus-group-ham-exit-processor-BBDB)
-           (variable-item gnus-group-ham-exit-processor-copy)
-           (variable-item gnus-group-ham-exit-processor-spamoracle))))
+           (variable-item gnus-group-ham-exit-processor-spamoracle)
+           (variable-item gnus-group-ham-exit-processor-copy))))
    :function-document
    "Which spam or ham processors will be applied when the summary is exited."
    :variable gnus-spam-process-newsgroups
@@ -1920,6 +1946,25 @@ spam processing, associated with the appropriate processor."
                  (regexp :tag "Group Regexp")
                  (set 
                   :tag "Spam/Ham Summary Exit Processor"
+                  (const :tag "Spam: Bogofilter"    (spam spam-use-bogofilter))
+                  (const :tag "Spam: Blacklist"     (spam spam-use-blacklist))
+                  (const :tag "Spam: Bsfilter"      (spam spam-use-bsfilter))
+                  (const :tag "Spam: ifile"         (spam spam-use-ifile))
+                  (const :tag "Spam: Gmane Report"  (spam spam-use-gmane))
+                  (const :tag "Spam: Spam-stat"     (spam spam-use-stat))
+                  (const :tag "Spam: Spam Oracle"   (spam spam-use-spamoracle))
+                  (const :tag "Spam: SpamAssassin"  (spam spam-use-spamassassin))
+                  (const :tag "Spam: CRM114"        (spam spam-use-crm114))
+                  (const :tag "Ham: BBDB"           (ham spam-use-BBDB))
+                  (const :tag "Ham: Bogofilter"     (ham spam-use-bogofilter))
+                  (const :tag "Ham: Bsfilter"       (ham spam-use-bsfilter))
+                  (const :tag "Ham: Copy"           (ham spam-use-ham-copy))
+                  (const :tag "Ham: ifile"          (ham spam-use-ifile))
+                  (const :tag "Ham: Spam-stat"      (ham spam-use-stat))
+                  (const :tag "Ham: Spam Oracle"    (ham spam-use-spamoracle))
+                  (const :tag "Ham: SpamAssassin"   (ham spam-use-spamassassin))
+                  (const :tag "Ham: CRM114"         (ham spam-use-crm114))
+                  (const :tag "Ham: Whitelist"      (ham spam-use-whitelist))
                   (variable-item gnus-group-spam-exit-processor-ifile)
                   (variable-item gnus-group-spam-exit-processor-stat)
                   (variable-item gnus-group-spam-exit-processor-bogofilter)
@@ -1933,9 +1978,104 @@ spam processing, associated with the appropriate processor."
                   (variable-item gnus-group-ham-exit-processor-BBDB)
                   (variable-item gnus-group-ham-exit-processor-spamoracle)
                   (variable-item gnus-group-ham-exit-processor-copy))))
+
    :parameter-document
    "Which spam or ham processors will be applied when the summary is exited.")
 
+  (gnus-define-group-parameter
+   spam-autodetect
+   :type list
+   :parameter-type 
+   '(boolean :tag "Spam autodetection")
+   :function-document
+   "Should spam be autodetected (with spam-split) in this group?"
+   :variable gnus-spam-autodetect
+   :variable-default nil
+   :variable-document
+   "*Groups in which spam should be autodetected when they are entered.
+   Only unseen articles will be examined, unless
+   spam-autodetect-recheck-messages is set."
+   :variable-group spam
+   :variable-type 
+   '(repeat
+     :tag "Autodetection setting"
+     (list
+      (regexp :tag "Group Regexp")
+      boolean))
+   :parameter-document
+   "Spam autodetection.
+Only unseen articles will be examined, unless
+spam-autodetect-recheck-messages is set.")
+
+  (gnus-define-group-parameter
+   spam-autodetect-methods
+   :type list
+   :parameter-type 
+   '(choice :tag "Spam autodetection-specific methods"
+     (const none)
+     (const default)
+     (set :tag "Use specific methods"
+         (variable-item spam-use-blacklist)
+         (variable-item spam-use-gmane-xref)
+         (variable-item spam-use-regex-headers)
+         (variable-item spam-use-regex-body)
+         (variable-item spam-use-whitelist)
+         (variable-item spam-use-BBDB)
+         (variable-item spam-use-ifile)
+         (variable-item spam-use-spamoracle)
+         (variable-item spam-use-crm114)
+         (variable-item spam-use-spamassassin)
+         (variable-item spam-use-spamassassin-headers)
+         (variable-item spam-use-bsfilter)
+         (variable-item spam-use-bsfilter-headers)
+         (variable-item spam-use-stat)
+         (variable-item spam-use-blackholes)
+         (variable-item spam-use-hashcash)
+         (variable-item spam-use-bogofilter-headers)
+         (variable-item spam-use-bogofilter)))
+   :function-document
+   "Methods to be used for autodetection in each group"
+   :variable gnus-spam-autodetect-methods
+   :variable-default nil
+   :variable-document
+   "*Methods for autodetecting spam per group.
+Requires the spam-autodetect parameter.  Only unseen articles
+will be examined, unless spam-autodetect-recheck-messages is
+set."
+   :variable-group spam
+   :variable-type 
+   '(repeat
+     :tag "Autodetection methods"
+     (list
+      (regexp :tag "Group Regexp")
+      (choice
+       (const none)
+       (const default)
+       (set :tag "Use specific methods"
+       (variable-item spam-use-blacklist)
+       (variable-item spam-use-gmane-xref)
+       (variable-item spam-use-regex-headers)
+       (variable-item spam-use-regex-body)
+       (variable-item spam-use-whitelist)
+       (variable-item spam-use-BBDB)
+       (variable-item spam-use-ifile)
+       (variable-item spam-use-spamoracle)
+       (variable-item spam-use-crm114)
+       (variable-item spam-use-stat)
+       (variable-item spam-use-blackholes)
+       (variable-item spam-use-hashcash)
+       (variable-item spam-use-spamassassin)
+       (variable-item spam-use-spamassassin-headers)
+       (variable-item spam-use-bsfilter)
+       (variable-item spam-use-bsfilter-headers)
+       (variable-item spam-use-bogofilter-headers)
+       (variable-item spam-use-bogofilter)))))
+     :parameter-document
+   "Spam autodetection methods.  
+Requires the spam-autodetect parameter.  Only unseen articles
+will be examined, unless spam-autodetect-recheck-messages is
+set.")
+
   (gnus-define-group-parameter
    spam-process-destination
    :type list
@@ -1980,6 +2120,7 @@ mail groups."
      (string :tag "Move to a group")
      (repeat :tag "Move to multiple groups"
             (string :tag "Destination group"))
+     (const :tag "Respool" respool)
      (const :tag "Do nothing" nil))
    :function-document
    "Where ham articles will go at summary exit from a spam group."
@@ -2002,7 +2143,8 @@ mail groups, and only works in spam groups."
        :tag "Destination for ham articles at summary exit from spam group"
        (string :tag "Move to a group")
        (repeat :tag "Move to multiple groups"
-              (string :tag "Destination group"))
+               (string :tag "Destination group"))
+       (const :tag "Respool" respool)
        (const :tag "Expire" nil))))
    :parameter-document
    "Where ham articles will go at summary exit from a spam group.")
@@ -2103,8 +2245,7 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL."
                      summary-menu group-menu article-menu
                      tree-highlight menu highlight
                      browse-menu server-menu
-                     page-marker tree-menu binary-menu pick-menu
-                     grouplens-menu)
+                     page-marker tree-menu binary-menu pick-menu)
   "*Enable visual features.
 If `visual' is disabled, there will be no menus and few faces.  Most of
 the visual customization options below will be ignored.  Gnus will use
@@ -2118,8 +2259,7 @@ instance, to switch off all visual things except menus, you can say:
 Valid elements include `summary-highlight', `group-highlight',
 `article-highlight', `mouse-face', `summary-menu', `group-menu',
 `article-menu', `tree-highlight', `menu', `highlight', `browse-menu',
-`server-menu', `page-marker', `tree-menu', `binary-menu', `pick-menu',
-and `grouplens-menu'."
+`server-menu', `page-marker', `tree-menu', `binary-menu', and`pick-menu'."
   :group 'gnus-meta
   :group 'gnus-visual
   :type '(set (const summary-highlight)
@@ -2137,8 +2277,7 @@ and `grouplens-menu'."
              (const page-marker)
              (const tree-menu)
              (const binary-menu)
-             (const pick-menu)
-             (const grouplens-menu)))
+             (const pick-menu)))
 
 ;; Byte-compiler warning.
 (defvar gnus-visual)
@@ -2222,11 +2361,33 @@ This should be an alist for Emacs, or a plist for XEmacs."
                         (symbol :tag "Parameter")
                         (sexp :tag "Value")))))
 
+(defcustom gnus-user-agent 'emacs-gnus-type
+  "Which information should be exposed in the User-Agent header.
+
+It can be one of the symbols `gnus' \(show only Gnus version\), `emacs-gnus'
+\(show only Emacs and Gnus versions\), `emacs-gnus-config' \(same as
+`emacs-gnus' plus system configuration\), `emacs-gnus-type' \(same as
+`emacs-gnus' plus system type\) or a custom string.  If you set it to a
+string, be sure to use a valid format, see RFC 2616."
+  :group 'gnus-message
+  :type '(choice
+         (item :tag "Show Gnus and Emacs versions and system type"
+               emacs-gnus-type)
+         (item :tag "Show Gnus and Emacs versions and system configuration"
+               emacs-gnus-config)
+         (item :tag "Show Gnus and Emacs versions" emacs-gnus)
+         (item :tag "Show only Gnus version" gnus)
+         (string :tag "Other")))
+
 \f
 ;;; Internal variables
 
 (defvar gnus-agent-gcc-header "X-Gnus-Agent-Gcc")
 (defvar gnus-agent-meta-information-header "X-Gnus-Agent-Meta-Information")
+(defvar gnus-agent-method-p-cache nil
+  ; Reset each time gnus-agent-covered-methods is changed else
+  ; gnus-agent-method-p may mis-report a methods status.
+  )
 (defvar gnus-agent-target-move-group-header "X-Gnus-Agent-Move-To")
 (defvar gnus-draft-meta-information-header "X-Draft-From")
 (defvar gnus-group-get-parameter-function 'gnus-group-get-parameter)
@@ -2238,7 +2399,8 @@ This should be an alist for Emacs, or a plist for XEmacs."
 (defvar gnus-agent-fetching nil
   "Whether Gnus agent is in fetching mode.")
 
-(defvar gnus-agent-covered-methods nil)
+(defvar gnus-agent-covered-methods nil
+  "A list of servers, NOT methods, showing which servers are covered by the agent.")
 
 (defvar gnus-command-method nil
   "Dynamically bound variable that says what the current back end is.")
@@ -2350,7 +2512,7 @@ such as a mark that says whether an article is stored in the cache
                        gnus-newsrc-alist gnus-server-alist
                        gnus-killed-list gnus-zombie-list
                        gnus-topic-topology gnus-topic-alist
-                       gnus-agent-covered-methods gnus-format-specs)
+                       gnus-format-specs)
   "Gnus variables saved in the quick startup file.")
 
 (defvar gnus-newsrc-alist nil
@@ -2525,8 +2687,6 @@ gnus-registry.el will populate this if it's loaded.")
       gnus-summary-post-forward gnus-summary-wide-reply-with-original
       gnus-summary-post-forward)
      ("gnus-picon" :interactive t gnus-treat-from-picon)
-     ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p
-      gnus-grouplens-mode)
      ("smiley" :interactive t smiley-region)
      ("gnus-win" gnus-configure-windows gnus-add-configuration)
      ("gnus-sum" gnus-summary-insert-line gnus-summary-read-group
@@ -2638,7 +2798,6 @@ with some simple extensions.
 %z   Article zcore (character)
 %t   Number of articles under the current thread (number).
 %e   Whether the thread is empty or not (character).
-%l   GroupLens score (string).
 %V   Total thread score (number).
 %P   The line number (number).
 %O   Download mark (character).
@@ -3087,7 +3246,7 @@ that that variable is buffer-local to the summary buffers."
 (defun gnus-generate-new-group-name (leaf)
   (let ((name leaf)
        (num 0))
-    (while (gnus-gethash name gnus-newsrc-hashtb)
+    (while (gnus-group-entry name)
       (setq name (concat leaf "<" (int-to-string (setq num (1+ num))) ">")))
     name))
 
@@ -3124,6 +3283,38 @@ that that variable is buffer-local to the summary buffers."
                                   (nth 1 method))))
       method)))
 
+(defsubst gnus-method-to-server (method)
+  (catch 'server-name
+    (setq method (or method gnus-select-method))
+
+    ;; Perhaps it is already in the cache.
+    (mapc (lambda (name-method)
+            (if (equal (cdr name-method) method)
+                (throw 'server-name (car name-method))))
+          gnus-server-method-cache)
+
+    (mapc
+     (lambda (server-alist)
+       (mapc (lambda (name-method)
+               (when (gnus-methods-equal-p (cdr name-method) method)
+                 (unless (member name-method gnus-server-method-cache)
+                   (push name-method gnus-server-method-cache))
+                 (throw 'server-name (car name-method))))
+             server-alist))
+     (let ((alists (list gnus-server-alist
+                         gnus-predefined-server-alist)))
+       (if gnus-select-method
+           (push (list (cons "native" gnus-select-method)) alists))
+       alists))
+
+    (let* ((name (if (member (cadr method) '(nil ""))
+                     (format "%s" (car method))
+                   (format "%s:%s" (car method) (cadr method))))
+           (name-method (cons name method)))
+      (unless (member name-method gnus-server-method-cache)
+        (push name-method gnus-server-method-cache))
+      name)))
+
 (defsubst gnus-server-to-method (server)
   "Map virtual server names to select methods."
   (or (and server (listp server) server)
@@ -3150,8 +3341,25 @@ that that variable is buffer-local to the summary buffers."
                            (not (equal server (format "%s:%s" (caar servers)
                                                       (cadar servers)))))
                  (pop servers))
-               (car servers)))))
-       (push (cons server result) gnus-server-method-cache)
+               (car servers))
+              ;; This could be some sort of foreign server that I
+              ;; simply haven't opened (yet).  Do a brute-force scan
+              ;; of the entire gnus-newsrc-alist for the server name
+              ;; of every method.  As a side-effect, loads the
+              ;; gnus-server-method-cache so this only happens once,
+              ;; if at all.
+              (let (match)
+                (mapcar 
+                 (lambda (info)
+                   (let ((info-method (gnus-info-method info)))
+                     (unless (stringp info-method)
+                       (let ((info-server (gnus-method-to-server info-method)))
+                         (when (equal server info-server)
+                           (setq match info-method))))))
+                 (cdr gnus-newsrc-alist))
+                match))))
+        (when result
+          (push (cons server result) gnus-server-method-cache))
        result)))
 
 (defsubst gnus-server-get-method (group method)
@@ -3329,10 +3537,10 @@ You should probably use `gnus-find-method-for-group' instead."
 (defsubst gnus-secondary-method-p (method)
   "Return whether METHOD is a secondary select method."
   (let ((methods gnus-secondary-select-methods)
-       (gmethod (gnus-server-get-method nil method)))
+       (gmethod (inline (gnus-server-get-method nil method))))
     (while (and methods
                (not (gnus-method-equal
-                     (gnus-server-get-method nil (car methods))
+                     (inline (gnus-server-get-method nil (car methods)))
                      gmethod)))
       (setq methods (cdr methods)))
     methods))
@@ -3731,6 +3939,9 @@ If NEWSGROUP is nil, return the global kill file name instead."
       (setq valids (cdr valids)))
     outs))
 
+(eval-when-compile
+  (autoload 'message-y-or-n-p "message" nil nil 'macro))
+
 (defun gnus-read-group (prompt &optional default)
   "Prompt the user for a group name.
 Disallow invalid group names."
@@ -3743,21 +3954,19 @@ Disallow invalid group names."
                                      (cons (or default "") 0)
                                      'gnus-group-history)))
        (let ((match (match-string 0 group)))
-         ;; `/' may be okay (e.g. for nnimap), so ask the user:
-         (unless (and (string-match "/" match)
+         ;; Might be okay (e.g. for nnimap), so ask the user:
+         (unless (and (not (string-match "^$\\|:" match))
                       (message-y-or-n-p
                        "Proceed and create group anyway? " t
 "The group name \"" group "\" contains a forbidden character: \"" match "\".
 
 Usually, it's dangerous to create a group with this name, because it's not
-supported by all back ends and servers.  On some IMAP servers, it's valid to
-use the character \"/\".
-
-If you are really sure, you can proceed anyway and create the group.
+supported by all back ends and servers.  On IMAP servers it should work,
+though.  If you are really sure, you can proceed anyway and create the group.
 
 You may customize the variable `gnus-invalid-group-regexp', which currently is
 set to \"" gnus-invalid-group-regexp
-"\", if you want to get rid of this query."))
+"\", if you want to get rid of this query permanently."))
            (setq prefix (format "Invalid group name: \"%s\".  " group)
                  group nil)))))
     group))
@@ -3803,7 +4012,13 @@ Allow completion over sensible values."
 
 (defun gnus-agent-method-p (method)
   "Say whether METHOD is covered by the agent."
-  (member method gnus-agent-covered-methods))
+  (or (eq (car gnus-agent-method-p-cache) method)
+      (setq gnus-agent-method-p-cache 
+            (cons method
+                  (member (if (stringp method) 
+                              method 
+                            (gnus-method-to-server method)) gnus-agent-covered-methods))))
+  (cdr gnus-agent-method-p-cache))
 
 (defun gnus-online (method)
   (not
@@ -3891,7 +4106,7 @@ current display is used."
 (defun gnus (&optional arg dont-connect slave)
   "Read network news.
 If ARG is non-nil and a positive number, Gnus will use that as the
-startup level. If ARG is non-nil and not a positive number, Gnus will
+startup level.  If ARG is non-nil and not a positive number, Gnus will
 prompt the user for the name of an NNTP server to use."
   (interactive "P")
   (unless (byte-code-function-p (symbol-function 'gnus))
@@ -3905,4 +4120,5 @@ prompt the user for the name of an NNTP server to use."
 
 (provide 'gnus)
 
+;;; arch-tag: acebeeab-f331-4f8f-a7ea-89c58c84f636
 ;;; gnus.el ends here