*** empty log message ***
[gnus] / lisp / gnus.el
index b353b77..10cf215 100644 (file)
@@ -1,9 +1,9 @@
 ;;; gnus.el --- a newsreader for GNU Emacs
-;; Copyright (C) 1987,88,89,90,93,94,95,96 Free Software Foundation, Inc.
+;; Copyright (C) 1987,88,89,90,93,94,95,96,97 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
+;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 (eval '(run-hooks 'gnus-load-hook))
 
 (require 'custom)
+(require 'gnus-load)
+(require 'message)
 
 (defgroup gnus nil
   "The coffee-brewing, all singing, all dancing, kitchen sink newsreader."
-  :group 'emacs)
+  :group 'news
+  :group 'mail)
 
 (defgroup gnus-start nil
   "Starting your favorite newsreader."
   :group 'gnus)
 
+(defgroup gnus-start-server nil
+  "Server options at startup."
+  :group 'gnus-start)
+
+;; These belong to gnus-group.el.
+(defgroup gnus-group nil
+  "Group buffers."
+  :link '(custom-manual "(gnus)The Group Buffer")
+  :group 'gnus)
+
+(defgroup gnus-group-foreign nil
+  "Foreign groups."
+  :link '(custom-manual "(gnus)Foreign Groups")
+  :group 'gnus-group)
+
+(defgroup gnus-group-new nil
+  "Automatic subscription of new groups."
+  :group 'gnus-group)
+
+(defgroup gnus-group-levels nil
+  "Group levels."
+  :link '(custom-manual "(gnus)Group Levels")
+  :group 'gnus-group)
+
+(defgroup gnus-group-select nil
+  "Selecting a Group."
+  :link '(custom-manual "(gnus)Selecting a Group")
+  :group 'gnus-group)
+
+(defgroup gnus-group-listing nil
+  "Showing slices of the group list."
+  :link '(custom-manual "(gnus)Listing Groups")
+  :group 'gnus-group)
+
+(defgroup gnus-group-visual nil
+  "Sorting the group buffer."
+  :link '(custom-manual "(gnus)Group Buffer Format")
+  :group 'gnus-group
+  :group 'gnus-visual)
+
+(defgroup gnus-group-various nil
+  "Various group options."
+  :link '(custom-manual "(gnus)Scanning New Messages")
+  :group 'gnus-group)
+
+;; These belong to gnus-sum.el.
+(defgroup gnus-summary nil
+  "Summary buffers."
+  :link '(custom-manual "(gnus)The Summary Buffer")
+  :group 'gnus)
+
+(defgroup gnus-summary-exit nil
+  "Leaving summary buffers."
+  :link '(custom-manual "(gnus)Exiting the Summary Buffer")
+  :group 'gnus-summary)
+
+(defgroup gnus-summary-marks nil
+  "Marks used in summary buffers."
+  :link '(custom-manual "(gnus)Marking Articles")
+  :group 'gnus-summary)
+
+(defgroup gnus-thread nil
+  "Ordering articles according to replies."
+  :link '(custom-manual "(gnus)Threading")
+  :group 'gnus-summary)
+
+(defgroup gnus-summary-format nil
+  "Formatting of the summary buffer."
+  :link '(custom-manual "(gnus)Summary Buffer Format")
+  :group 'gnus-summary)
+
+(defgroup gnus-summary-choose nil
+  "Choosing Articles."
+  :link '(custom-manual "(gnus)Choosing Articles")
+  :group 'gnus-summary)
+
+(defgroup gnus-summary-maneuvering nil
+  "Summary movement commands."
+  :link '(custom-manual "(gnus)Summary Maneuvering")
+  :group 'gnus-summary)
+
+(defgroup gnus-summary-mail nil
+  "Mail group commands."
+  :link '(custom-manual "(gnus)Mail Group Commands")
+  :group 'gnus-summary)
+
+(defgroup gnus-summary-sort nil
+  "Sorting the summary buffer."
+  :link '(custom-manual "(gnus)Sorting")
+  :group 'gnus-summary)
+
+(defgroup gnus-summary-visual nil
+  "Highlighting and menus in the summary buffer."
+  :link '(custom-manual "(gnus)Summary Highlighting")
+  :group 'gnus-visual
+  :group 'gnus-summary)
+
+(defgroup gnus-summary-various nil
+  "Various summary buffer options."
+  :link '(custom-manual "(gnus)Various Summary Stuff")
+  :group 'gnus-summary)
+
+;; Belongs to gnus-uu.el
+(defgroup gnus-extract-view nil
+  "Viewing extracted files."
+  :link '(custom-manual "(gnus)Viewing Files")
+  :group 'gnus-extract)
+
+;; Belongs to gnus-score.el
 (defgroup gnus-score nil
   "Score and kill file handling."
-  :group 'gnus )
+  :group 'gnus)
+
+(defgroup gnus-score-kill nil
+  "Kill files."
+  :group 'gnus-score)
+
+(defgroup gnus-score-adapt nil
+  "Adaptive score files."
+  :group 'gnus-score)
+
+(defgroup gnus-score-default nil
+  "Default values for score files."
+  :group 'gnus-score)
+
+(defgroup gnus-score-expire nil
+  "Expiring score rules."
+  :group 'gnus-score)
+
+(defgroup gnus-score-decay nil
+  "Decaying score rules."
+  :group 'gnus-score)
+
+(defgroup gnus-score-files nil
+  "Score and kill file names."
+  :group 'gnus-score
+  :group 'gnus-files)
+
+(defgroup gnus-score-various nil
+  "Various scoring and killing options."
+  :group 'gnus-score)
+
+;; Other
+(defgroup gnus-visual nil
+  "Options controling the visual fluff."
+  :group 'gnus
+  :group 'faces)
+
+(defgroup gnus-files nil
+  "Files used by Gnus."
+  :group 'gnus)
+
+(defgroup gnus-dribble-file nil
+  "Auto save file."
+  :link '(custom-manual "(gnus)Auto Save")
+  :group 'gnus-files)
+
+(defgroup gnus-newsrc nil
+  "Storing Gnus state."
+  :group 'gnus-files)
+
+(defgroup gnus-server nil
+  "Options related to newsservers and other servers used by Gnus."
+  :group 'gnus)
+
+(defgroup gnus-message '((message custom-group))
+  "Composing replies and followups in Gnus."
+  :group 'gnus)
+
+(defgroup gnus-meta nil
+  "Meta variables controling major portions of Gnus.
+In general, modifying these variables does not take affect until Gnus
+is restarted, and sometimes reloaded."
+  :group 'gnus)
+
+(defgroup gnus-various nil
+  "Other Gnus options."
+  :link '(custom-manual "(gnus)Various Various")
+  :group 'gnus)
+
+(defgroup gnus-exit nil
+  "Exiting gnus."
+  :link '(custom-manual "(gnus)Exiting Gnus")
+  :group 'gnus)
 
-(defconst gnus-version-number "0.53"
+(defconst gnus-version-number "5.4.29"
   "Version number for this version of Gnus.")
 
-(defconst gnus-version (format "Red Gnus v%s" gnus-version-number)
+(defconst gnus-version (format "Gnus v%s" gnus-version-number)
   "Version string for this version of Gnus.")
 
 (defcustom gnus-inhibit-startup-message nil
-  "*If non-nil, the startup message will not be displayed.
+  "If non-nil, the startup message will not be displayed.
 This variable is used before `.gnus.el' is loaded, so it should
 be set in `.emacs' instead."
   :group 'gnus-start
@@ -62,32 +246,25 @@ be set in `.emacs' instead."
 
 ;;; Kludges to help the transition from the old `custom.el'.
 
-;; XEmacs and Emacs 19.29 facep does different things.
-(defalias 'custom-facep
-  (cond ((fboundp 'find-face)
-        'find-face)
-       ((fboundp 'facep)
-        'facep)
-       (t
-        'ignore)))
-
-(defalias 'gnus-make-overlay 'make-overlay)
-(defalias 'gnus-overlay-put 'overlay-put)
-(defalias 'gnus-move-overlay 'move-overlay)
-(defalias 'gnus-overlay-end 'overlay-end)
-(defalias 'gnus-extent-detached-p 'ignore)
-(defalias 'gnus-extent-start-open 'ignore)
-(defalias 'gnus-set-text-properties 'set-text-properties)
-(defalias 'gnus-group-remove-excess-properties 'ignore)
-(defalias 'gnus-topic-remove-excess-properties 'ignore)
-(defalias 'gnus-appt-select-lowest-window 'appt-select-lowest-window)
-(defalias 'gnus-mail-strip-quoted-names 'mail-strip-quoted-names)
-(defalias 'gnus-make-local-hook 'make-local-hook)
-(defalias 'gnus-add-hook 'add-hook)
-(defalias 'gnus-character-to-event 'identity)
-(defalias 'gnus-add-text-properties 'add-text-properties)
-(defalias 'gnus-put-text-property 'put-text-property)
-(defalias 'gnus-mode-line-buffer-identification 'identity)
+(unless (featurep 'gnus-xmas)
+  (defalias 'gnus-make-overlay 'make-overlay)
+  (defalias 'gnus-overlay-put 'overlay-put)
+  (defalias 'gnus-move-overlay 'move-overlay)
+  (defalias 'gnus-overlay-end 'overlay-end)
+  (defalias 'gnus-extent-detached-p 'ignore)
+  (defalias 'gnus-extent-start-open 'ignore)
+  (defalias 'gnus-set-text-properties 'set-text-properties)
+  (defalias 'gnus-group-remove-excess-properties 'ignore)
+  (defalias 'gnus-topic-remove-excess-properties 'ignore)
+  (defalias 'gnus-appt-select-lowest-window 'appt-select-lowest-window)
+  (defalias 'gnus-mail-strip-quoted-names 'mail-strip-quoted-names)
+  (defalias 'gnus-add-hook 'add-hook)
+  (defalias 'gnus-character-to-event 'identity)
+  (defalias 'gnus-add-text-properties 'add-text-properties)
+  (defalias 'gnus-put-text-property 'put-text-property)
+  (defalias 'gnus-mode-line-buffer-identification 'identity)
+  (defalias 'gnus-characterp 'numberp)
+  (defalias 'gnus-key-press-event-p 'numberp))
 
 ;; The XEmacs people think this is evil, so it must go.
 (defun custom-face-lookup (&optional fg bg stipple bold italic underline)
@@ -103,14 +280,12 @@ be set in `.emacs' instead."
       (copy-face 'default name)
       (when (and fg
                 (not (string-equal fg "default")))
-       (condition-case ()
-           (set-face-foreground name fg)
-         (error nil)))
+       (ignore-errors
+         (set-face-foreground name fg)))
       (when (and bg
                 (not (string-equal bg "default")))
-       (condition-case ()
-           (set-face-background name bg)
-         (error nil)))
+       (ignore-errors
+         (set-face-background name bg)))
       (when (and stipple
                 (not (string-equal stipple "default"))
                 (not (eq stipple 'custom:asis))
@@ -118,31 +293,335 @@ be set in `.emacs' instead."
        (set-face-stipple name stipple))
       (when (and bold
                 (not (eq bold 'custom:asis)))
-       (condition-case ()
-           (make-face-bold name)
-         (error nil)))
+       (ignore-errors
+         (make-face-bold name)))
       (when (and italic
                 (not (eq italic 'custom:asis)))
-       (condition-case ()
-           (make-face-italic name)
-         (error nil)))
+       (ignore-errors
+         (make-face-italic name)))
       (when (and underline
                 (not (eq underline 'custom:asis)))
-       (condition-case ()
-           (set-face-underline-p name t)
-         (error nil))))
+       (ignore-errors
+         (set-face-underline-p name t))))
     name))
 
-;;; Internal variables
+;; We define these group faces here to avoid the display
+;; update forced when creating new faces.
+
+(defface gnus-group-news-1-face
+  '((((class color)
+      (background dark))
+     (:foreground "PaleTurquoise" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "ForestGreen" :bold t))
+    (t
+     ()))
+  "Level 1 newsgroup face.")
+
+(defface gnus-group-news-1-empty-face
+  '((((class color)
+      (background dark))
+     (:foreground "PaleTurquoise"))
+    (((class color)
+      (background light))
+     (:foreground "ForestGreen"))
+    (t
+     ()))
+  "Level 1 empty newsgroup face.")
+
+(defface gnus-group-news-2-face
+  '((((class color)
+      (background dark))
+     (:foreground "turquoise" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "CadetBlue4" :bold t))
+    (t
+     ()))
+  "Level 2 newsgroup face.")
+
+(defface gnus-group-news-2-empty-face
+  '((((class color)
+      (background dark))
+     (:foreground "turquoise"))
+    (((class color)
+      (background light))
+     (:foreground "CadetBlue4"))
+    (t
+     ()))
+  "Level 2 empty newsgroup face.")
+
+(defface gnus-group-news-3-face
+  '((((class color)
+      (background dark))
+     (:bold t))
+    (((class color)
+      (background light))
+     (:bold t))
+    (t
+     ()))
+  "Level 3 newsgroup face.")
+
+(defface gnus-group-news-3-empty-face
+  '((((class color)
+      (background dark))
+     ())
+    (((class color)
+      (background light))
+     ())
+    (t
+     ()))
+  "Level 3 empty newsgroup face.")
+
+(defface gnus-group-news-low-face
+  '((((class color)
+      (background dark))
+     (:foreground "DarkTurquoise" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "DarkGreen" :bold t))
+    (t
+     ()))
+  "Low level newsgroup face.")
+
+(defface gnus-group-news-low-empty-face
+  '((((class color)
+      (background dark))
+     (:foreground "DarkTurquoise"))
+    (((class color)
+      (background light))
+     (:foreground "DarkGreen"))
+    (t
+     ()))
+  "Low level empty newsgroup face.")
+
+(defface gnus-group-mail-1-face
+  '((((class color)
+      (background dark))
+     (:foreground "aquamarine1" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "DeepPink3" :bold t))
+    (t
+     (:bold t)))
+  "Level 1 mailgroup face.")
+
+(defface gnus-group-mail-1-empty-face
+  '((((class color)
+      (background dark))
+     (:foreground "aquamarine1"))
+    (((class color)
+      (background light))
+     (:foreground "DeepPink3"))
+    (t
+     (:italic t :bold t)))
+  "Level 1 empty mailgroup face.")
+
+(defface gnus-group-mail-2-face
+  '((((class color)
+      (background dark))
+     (:foreground "aquamarine2" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "HotPink3" :bold t))
+    (t
+     (:bold t)))
+  "Level 2 mailgroup face.")
+
+(defface gnus-group-mail-2-empty-face
+  '((((class color)
+      (background dark))
+     (:foreground "aquamarine2"))
+    (((class color)
+      (background light))
+     (:foreground "HotPink3"))
+    (t
+     (:bold t)))
+  "Level 2 empty mailgroup face.")
+
+(defface gnus-group-mail-3-face
+  '((((class color)
+      (background dark))
+     (:foreground "aquamarine3" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "magenta4" :bold t))
+    (t
+     (:bold t)))
+  "Level 3 mailgroup face.")
+
+(defface gnus-group-mail-3-empty-face
+  '((((class color)
+      (background dark))
+     (:foreground "aquamarine3"))
+    (((class color)
+      (background light))
+     (:foreground "magenta4"))
+    (t
+     ()))
+  "Level 3 empty mailgroup face.")
+
+(defface gnus-group-mail-low-face
+  '((((class color)
+      (background dark))
+     (:foreground "aquamarine4" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "DeepPink4" :bold t))
+    (t
+     (:bold t)))
+  "Low level mailgroup face.")
+
+(defface gnus-group-mail-low-empty-face
+  '((((class color)
+      (background dark))
+     (:foreground "aquamarine4"))
+    (((class color)
+      (background light))
+     (:foreground "DeepPink4"))
+    (t
+     (:bold t)))
+  "Low level empty mailgroup face.")
+
+;; Summary mode faces.
+
+(defface gnus-summary-selected-face '((t
+                                      (:underline t)))
+  "Face used for selected articles.")
+
+(defface gnus-summary-cancelled-face
+  '((((class color))
+     (:foreground "yellow" :background "black")))
+  "Face used for cancelled articles.")
+
+(defface gnus-summary-high-ticked-face
+  '((((class color)
+      (background dark))
+     (:foreground "pink" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "firebrick" :bold t))
+    (t
+     (:bold t)))
+  "Face used for high interest ticked articles.")
+
+(defface gnus-summary-low-ticked-face
+  '((((class color)
+      (background dark))
+     (:foreground "pink" :italic t))
+    (((class color)
+      (background light))
+     (:foreground "firebrick" :italic t))
+    (t
+     (:italic t)))
+  "Face used for low interest ticked articles.")
+
+(defface gnus-summary-normal-ticked-face
+  '((((class color)
+      (background dark))
+     (:foreground "pink"))
+    (((class color)
+      (background light))
+     (:foreground "firebrick"))
+    (t
+     ()))
+  "Face used for normal interest ticked articles.")
+
+(defface gnus-summary-high-ancient-face
+  '((((class color)
+      (background dark))
+     (:foreground "SkyBlue" :bold t))
+    (((class color)
+      (background light))
+     (:foreground "RoyalBlue" :bold t))
+    (t
+     (:bold t)))
+  "Face used for high interest ancient articles.")
+
+(defface gnus-summary-low-ancient-face
+  '((((class color)
+      (background dark))
+     (:foreground "SkyBlue" :italic t))
+    (((class color)
+      (background light))
+     (:foreground "RoyalBlue" :italic t))
+    (t
+     (:italic t)))
+  "Face used for low interest ancient articles.")
+
+(defface gnus-summary-normal-ancient-face
+  '((((class color)
+      (background dark))
+     (:foreground "SkyBlue"))
+    (((class color)
+      (background light))
+     (:foreground "RoyalBlue"))
+    (t
+     ()))
+  "Face used for normal interest ancient articles.")
+
+(defface gnus-summary-high-unread-face
+  '((t
+     (:bold t)))
+  "Face used for high interest unread articles.")
+
+(defface gnus-summary-low-unread-face
+  '((t
+     (:italic t)))
+  "Face used for low interest unread articles.")
+
+(defface gnus-summary-normal-unread-face
+  '((t
+     ()))
+  "Face used for normal interest unread articles.")
+
+(defface gnus-summary-high-read-face
+  '((((class color)
+      (background dark))
+     (:foreground "PaleGreen"
+                 :bold t))
+    (((class color)
+      (background light))
+     (:foreground "DarkGreen"
+                 :bold t))
+    (t
+     (:bold t)))
+  "Face used for high interest read articles.")
+
+(defface gnus-summary-low-read-face
+  '((((class color)
+      (background dark))
+     (:foreground "PaleGreen"
+                 :italic t))
+    (((class color)
+      (background light))
+     (:foreground "DarkGreen"
+                 :italic t))
+    (t
+     (:italic t)))
+  "Face used for low interest read articles.")
+
+(defface gnus-summary-normal-read-face
+  '((((class color)
+      (background dark))
+     (:foreground "PaleGreen"))
+    (((class color)
+      (background light))
+     (:foreground "DarkGreen"))
+    (t
+     ()))
+  "Face used for normal interest read articles.")
+
+
+;;; Splash screen.
 
 (defvar gnus-group-buffer "*Group*")
 
 (eval-and-compile
   (autoload 'gnus-play-jingle "gnus-audio"))
 
-;;; Splash screen.
-
-(defface gnus-splash-face 
+(defface gnus-splash-face
   '((((class color)
       (background dark))
      (:foreground "red"))
@@ -176,6 +655,8 @@ be set in `.emacs' instead."
       (while (search-forward "\t" nil t)
        (replace-match "        " t t)))))
 
+(defvar gnus-simple-splash nil)
+
 (defun gnus-group-startup-message (&optional x y)
   "Insert startup message in current buffer."
   ;; Insert the message.
@@ -214,7 +695,8 @@ be set in `.emacs' instead."
   ;; Fontify some.
   (put-text-property (point-min) (point-max) 'face 'gnus-splash-face)
   (goto-char (point-min))
-  (setq mode-line-buffer-identification gnus-version)
+  (setq mode-line-buffer-identification (concat " " gnus-version))
+  (setq gnus-simple-splash t)
   (set-buffer-modified-p t))
 
 (eval-when (load)
@@ -229,15 +711,23 @@ be set in `.emacs' instead."
 (require 'gnus-util)
 (require 'nnheader)
 
-(defcustom gnus-directory (or (getenv "SAVEDIR") "~/News/")
-  "*Directory variable from which all other Gnus file variables are derived."
-  :group 'gnus-start
+(defcustom gnus-home-directory "~/"
+  "Directory variable that specifies the \"home\" directory.
+All other Gnus path variables are initialized from this variable."
+  :group 'gnus-files
+  :type 'directory)
+
+(defcustom gnus-directory (or (getenv "SAVEDIR")
+                             (nnheader-concat gnus-home-directory "News/"))
+  "Directory variable from which all other Gnus file variables are derived."
+  :group 'gnus-files
   :type 'directory)
 
 (defcustom gnus-default-directory nil
   "*Default directory for all Gnus buffers."
-  :group 'gnus-start
-  :type 'directory)
+  :group 'gnus-files
+  :type '(choice (const :tag "current" nil)
+                directory))
 
 ;; Site dependent variables.  These variables should be defined in
 ;; paths.el.
@@ -251,15 +741,18 @@ See the documentation to that variable.")
 
 ;; Don't touch this variable.
 (defvar gnus-nntp-service "nntp"
-  "*NNTP service name (\"nntp\" or 119).
+  "NNTP service name (\"nntp\" or 119).
 This is an obsolete variable, which is scarcely used.  If you use an
 nntp server for your newsgroup and want to change the port number
 used to 899, you would say something along these lines:
 
  (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))")
 
-(defvar gnus-nntpserver-file "/etc/nntpserver"
-  "*A file with only the name of the nntp server in it.")
+(defcustom gnus-nntpserver-file "/etc/nntpserver"
+  "A file with only the name of the nntp server in it."
+  :group 'gnus-files
+  :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
@@ -279,54 +772,59 @@ used to 899, you would say something along these lines:
                 (kill-buffer (current-buffer))))))))
 
 (defcustom gnus-select-method
-  (nconc
-   (list 'nntp (or (condition-case ()
-                      (gnus-getenv-nntpserver)
-                    (error nil))
-                  (when (and gnus-default-nntp-server
-                             (not (string= gnus-default-nntp-server "")))
-                    gnus-default-nntp-server)
-                  (system-name)))
-   (if (or (null gnus-nntp-service)
-          (equal gnus-nntp-service "nntp"))
-       nil
-     (list gnus-nntp-service)))
-  "*Default method for selecting a newsgroup.
+  (ignore-errors
+    (nconc
+     (list 'nntp (or (ignore-errors
+                      (gnus-getenv-nntpserver))
+                    (when (and gnus-default-nntp-server
+                               (not (string= gnus-default-nntp-server "")))
+                      gnus-default-nntp-server)
+                    (system-name)))
+     (if (or (null gnus-nntp-service)
+            (equal gnus-nntp-service "nntp"))
+        nil
+       (list gnus-nntp-service))))
+  "Default method for selecting a newsgroup.
 This variable should be a list, where the first element is how the
 news is to be fetched, the second is the address.
 
 For instance, if you want to get your news via NNTP from
 \"flab.flab.edu\", you could say:
 
-(setq gnus-select-method '(nntp \"flab.flab.edu\"))
+\(setq gnus-select-method '(nntp \"flab.flab.edu\"))
 
 If you want to use your local spool, say:
 
-(setq gnus-select-method (list 'nnspool (system-name)))
+\(setq gnus-select-method (list 'nnspool (system-name)))
 
 If you use this variable, you must set `gnus-nntp-server' to nil.
 
 There is a lot more to know about select methods and virtual servers -
-see the manual for details.")
+see the manual for details."
+  :group 'gnus-server
+  :type 'gnus-select-method)
 
-(defvar gnus-message-archive-method 
+(defcustom gnus-message-archive-method
   `(nnfolder
     "archive"
     (nnfolder-directory ,(nnheader-concat message-directory "archive"))
-    (nnfolder-active-file 
+    (nnfolder-active-file
      ,(nnheader-concat message-directory "archive/active"))
     (nnfolder-get-new-mail nil)
     (nnfolder-inhibit-expiry t))
-  "*Method used for archiving messages you've sent.
+  "Method used for archiving messages you've sent.
 This should be a mail method.
 
 It's probably not a very effective to change this variable once you've
 run Gnus once.  After doing that, you must edit this server from the
-server buffer.")
+server buffer."
+  :group 'gnus-server
+  :group 'gnus-message
+  :type 'gnus-select-method)
 
-(defvar gnus-message-archive-group nil
+(defcustom gnus-message-archive-group nil
   "*Name of the group in which to save the messages you've written.
-This can either be a string, a list of strings; or an alist
+This can either be a string; a list of strings; or an alist
 of regexps/functions/forms to be evaluated to return a string (or a list
 of strings).  The functions are called with the name of the current
 group (or nil) as a parameter.
@@ -334,71 +832,80 @@ group (or nil) as a parameter.
 If you want to save your mail in one group and the news articles you
 write in another group, you could say something like:
 
- \(setq gnus-message-archive-group 
+ \(setq gnus-message-archive-group
         '((if (message-news-p)
-              \"misc-news\" 
+              \"misc-news\"
             \"misc-mail\")))
 
 Normally the group names returned by this variable should be
 unprefixed -- which implicitly means \"store on the archive server\".
 However, you may wish to store the message on some other server.  In
 that case, just return a fully prefixed name of the group --
-\"nnml+private:mail.misc\", for instance.")
+\"nnml+private:mail.misc\", for instance."
+  :group 'gnus-message
+  :type '(choice (const :tag "none" nil)
+                string))
 
-(defvar gnus-secondary-servers nil
-  "*List of NNTP servers that the user can choose between interactively.
+(defcustom gnus-secondary-servers nil
+  "List of NNTP servers that the user can choose between interactively.
 To make Gnus query you for a server, you have to give `gnus' a
-non-numeric prefix - `C-u M-x gnus', in short.")
+non-numeric prefix - `C-u M-x gnus', in short."
+  :group 'gnus-server
+  :type '(repeat string))
 
-(defvar gnus-nntp-server nil
+(defcustom gnus-nntp-server nil
   "*The name of the host running the NNTP server.
 This variable is semi-obsolete.         Use the `gnus-select-method'
-variable instead.")
+variable instead."
+  :group 'gnus-server
+  :type '(choice (const :tag "disable" nil)
+                string))
 
-(defvar gnus-secondary-select-methods nil
-  "*A list of secondary methods that will be used for reading news.
+(defcustom gnus-secondary-select-methods nil
+  "A list of secondary methods that will be used for reading news.
 This is a list where each element is a complete select method (see
 `gnus-select-method').
 
 If, for instance, you want to read your mail with the nnml backend,
 you could set this variable:
 
-(setq gnus-secondary-select-methods '((nnml \"\")))")
+\(setq gnus-secondary-select-methods '((nnml \"\")))"
+:group 'gnus-server
+:type '(repeat gnus-select-method))
 
 (defvar gnus-backup-default-subscribed-newsgroups
   '("news.announce.newusers" "news.groups.questions" "gnu.emacs.gnus")
   "Default default new newsgroups the first time Gnus is run.
 Should be set in paths.el, and shouldn't be touched by the user.")
 
-(defvar gnus-local-domain nil
+(defcustom gnus-local-domain nil
   "Local domain name without a host name.
 The DOMAINNAME environment variable is used instead if it is defined.
 If the `system-name' function returns the full Internet name, there is
-no need to set this variable.")
+no need to set this variable."
+  :group 'gnus-message
+  :type '(choice (const :tag "default" nil)
+                string))
 
 (defvar gnus-local-organization nil
   "String with a description of what organization (if any) the user belongs to.
-The ORGANIZATION environment variable is used instead if it is defined.
-If this variable contains a function, this function will be called
-with the current newsgroup name as the argument.  The function should
-return a string.
-
-In any case, if the string (either in the variable, in the environment
-variable, or returned by the function) is a file name, the contents of
-this file will be used as the organization.")
+Obsolete variable; use `message-user-organization' instead.")
 
 ;; Customization variables
 
-(defvar gnus-refer-article-method nil
-  "*Preferred method for fetching an article by Message-ID.
+(defcustom gnus-refer-article-method nil
+  "Preferred method for fetching an article by Message-ID.
 If you are reading news from the local spool (with nnspool), fetching
 articles by Message-ID is painfully slow.  By setting this method to an
 nntp method, you might get acceptable results.
 
 The value of this variable must be a valid select method as discussed
-in the documentation of `gnus-select-method'.")
+in the documentation of `gnus-select-method'."
+  :group 'gnus-server
+  :type '(choice (const :tag "default" nil)
+                gnus-select-method))
 
-(defvar gnus-group-faq-directory
+(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/"
@@ -410,7 +917,7 @@ in the documentation of `gnus-select-method'.")
     "/ftp@nctuccca.edu.tw:/USENET/FAQ/"
     "/ftp@hwarang.postech.ac.kr:/pub/usenet/"
     "/ftp@ftp.hk.super.net:/mirror/faqs/")
-  "*Directory where the group FAQs are stored.
+  "Directory where the group FAQs are stored.
 This will most commonly be on a remote machine, and the file will be
 fetched by ange-ftp.
 
@@ -433,26 +940,41 @@ If the default site is too slow, try one of these:
                  sunsite.auc.dk                 /pub/usenet
    Asia:         nctuccca.edu.tw                /USENET/FAQ
                  hwarang.postech.ac.kr          /pub/usenet
-                 ftp.hk.super.net               /mirror/faqs")
+                 ftp.hk.super.net               /mirror/faqs"
+  :group 'gnus-group-various
+  :type '(choice directory
+                (repeat directory)))
 
-(defvar gnus-use-cross-reference t
+(defcustom gnus-use-cross-reference t
   "*Non-nil means that cross referenced articles will be marked as read.
 If nil, ignore cross references.  If t, mark articles as read in
 subscribed newsgroups. If neither t nor nil, mark as read in all
-newsgroups.")
-
-(defvar gnus-process-mark ?#
-  "*Process mark.")
-
-(defvar gnus-asynchronous nil
-  "*If non-nil, Gnus will supply backends with data needed for async article fetching.")
+newsgroups."
+  :group 'gnus-server
+  :type '(choice (const :tag "off" nil)
+                (const :tag "subscribed" t)
+                (sexp :format "all"
+                      :value always)))
+
+(defcustom gnus-process-mark ?#
+  "*Process mark."
+  :group 'gnus-group-visual
+  :group 'gnus-summary-marks
+  :type 'character)
+
+(defcustom gnus-asynchronous nil
+  "*If non-nil, Gnus will supply backends with data needed for async article fetching."
+  :group 'gnus-asynchronous
+  :type 'boolean)
 
-(defvar gnus-large-newsgroup 200
+(defcustom gnus-large-newsgroup 200
   "*The number of articles which indicates a large newsgroup.
 If the number of articles in a newsgroup is greater than this value,
-confirmation is required for selecting the newsgroup.")
+confirmation is required for selecting the newsgroup."
+  :group 'gnus-group-select
+  :type 'integer)
 
-(defvar gnus-use-long-file-name (not (memq system-type '(usg-unix-v xenix)))
+(defcustom gnus-use-long-file-name (not (memq system-type '(usg-unix-v xenix)))
   "*Non-nil means that the default name of a file to save articles in is the group name.
 If it's nil, the directory form of the group name is used instead.
 
@@ -464,105 +986,160 @@ will not be used for kill files.
 
 Note that the default for this variable varies according to what system
 type you're using.  On `usg-unix-v' and `xenix' this variable defaults
-to nil while on all other systems it defaults to t.")
+to nil while on all other systems it defaults to t."
+  :group 'gnus-start
+  :type 'boolean)
 
-(defvar gnus-kill-files-directory gnus-directory
-  "*Name of the directory where kill files will be stored (default \"~/News\").")
+(defcustom gnus-kill-files-directory gnus-directory
+  "*Name of the directory where kill files will be stored (default \"~/News\")."
+  :group 'gnus-score-files
+  :group 'gnus-score-kill
+  :type 'directory)
 
-(defvar gnus-save-score nil
-  "*If non-nil, save group scoring info.")
+(defcustom gnus-save-score nil
+  "*If non-nil, save group scoring info."
+  :group 'gnus-score-various
+  :group 'gnus-start
+  :type 'boolean)
 
-(defvar gnus-use-undo t
-  "*If non-nil, allow undoing in Gnus group mode buffers.")
+(defcustom gnus-use-undo t
+  "*If non-nil, allow undoing in Gnus group mode buffers."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-use-adaptive-scoring nil
+(defcustom gnus-use-adaptive-scoring nil
   "*If non-nil, use some adaptive scoring scheme.
 If a list, then the values `word' and `line' are meaningful.  The
 former will perform adaption on individual words in the subject
-header while `line' will perform adaption on several headers.")
+header while `line' will perform adaption on several headers."
+  :group 'gnus-meta
+  :group 'gnus-score-adapt
+  :type '(set (const word) (const line)))
 
-(defvar gnus-use-cache 'passive
+(defcustom gnus-use-cache 'passive
   "*If nil, Gnus will ignore the article cache.
 If `passive', it will allow entering (and reading) articles
 explicitly entered into the cache.  If anything else, use the
-cache to the full extent of the law.")
-
-(defvar gnus-use-trees nil
-  "*If non-nil, display a thread tree buffer.")
+cache to the full extent of the law."
+  :group 'gnus-meta
+  :group 'gnus-cache
+  :type '(choice (const :tag "off" nil)
+                (const :tag "passive" passive)
+                (const :tag "active" t)))
+
+(defcustom gnus-use-trees nil
+  "*If non-nil, display a thread tree buffer."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-use-grouplens nil
-  "*If non-nil, use GroupLens ratings.")
+(defcustom gnus-use-grouplens nil
+  "*If non-nil, use GroupLens ratings."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-keep-backlog nil
+(defcustom gnus-keep-backlog nil
   "*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
 read.  If it is neither nil nor a number, Gnus will keep all read
-articles.  This is not a good idea.")
-
-(defvar gnus-use-nocem nil
-  "*If non-nil, Gnus will read NoCeM cancel messages.")
+articles.  This is not a good idea."
+  :group 'gnus-meta
+  :type '(choice (const :tag "off" nil)
+                integer
+                (sexp :format "all"
+                      :value t)))
+
+(defcustom gnus-use-nocem nil
+  "*If non-nil, Gnus will read NoCeM cancel messages."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-suppress-duplicates nil
-  "*If non-nil, Gnus will mark duplicate copies of the same article as read.")
+(defcustom gnus-suppress-duplicates nil
+  "*If non-nil, Gnus will mark duplicate copies of the same article as read."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-use-demon nil
-  "If non-nil, Gnus might use some demons.")
+(defcustom gnus-use-demon nil
+  "If non-nil, Gnus might use some demons."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-use-scoring t
-  "*If non-nil, enable scoring.")
+(defcustom gnus-use-scoring t
+  "*If non-nil, enable scoring."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-use-picons nil
-  "*If non-nil, display picons.")
+(defcustom gnus-use-picons nil
+  "*If non-nil, display picons."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-summary-prepare-exit-hook nil
-  "*A hook called when preparing to exit from the summary buffer.
-It calls `gnus-summary-expire-articles' by default.")
-(add-hook 'gnus-summary-prepare-exit-hook 'gnus-summary-expire-articles)
+(defcustom gnus-summary-prepare-exit-hook
+  '(gnus-summary-expire-articles)
+  "A hook called when preparing to exit from the summary buffer.
+It calls `gnus-summary-expire-articles' by default."
+  :group 'gnus-summary-exit
+  :type 'hook)
 
-(defvar gnus-novice-user t
+(defcustom gnus-novice-user t
   "*Non-nil means that you are a usenet novice.
 If non-nil, verbose messages may be displayed and confirmations may be
-required.")
+required."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-expert-user nil
+(defcustom gnus-expert-user nil
   "*Non-nil means that you will never be asked for confirmation about anything.
-And that means *anything*.")
+And that means *anything*."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-interactive-catchup t
-  "*If non-nil, require your confirmation when catching up a group.")
+(defcustom gnus-interactive-catchup t
+  "*If non-nil, require your confirmation when catching up a group."
+  :group 'gnus-group-select
+  :type 'boolean)
 
-(defvar gnus-interactive-exit t
-  "*If non-nil, require your confirmation when exiting Gnus.")
+(defcustom gnus-interactive-exit t
+  "*If non-nil, require your confirmation when exiting Gnus."
+  :group 'gnus-exit
+  :type 'boolean)
 
-(defvar gnus-extract-address-components 'gnus-extract-address-components
+(defcustom gnus-extract-address-components 'gnus-extract-address-components
   "*Function for extracting address components from a From header.
 Two pre-defined function exist: `gnus-extract-address-components',
 which is the default, quite fast, and too simplistic solution, and
 `mail-extract-address-components', which works much better, but is
-slower.")
-
-(defvar gnus-carpal nil
-  "*If non-nil, display clickable icons.")
+slower."
+  :group 'gnus-summary-format
+  :type '(radio (function-item gnus-extract-address-components)
+               (function-item mail-extract-address-components)
+               (function :tag "Other")))
+
+(defcustom gnus-carpal nil
+  "*If non-nil, display clickable icons."
+  :group 'gnus-meta
+  :type 'boolean)
 
-(defvar gnus-shell-command-separator ";"
-  "String used to separate to shell commands.")
+(defcustom gnus-shell-command-separator ";"
+  "String used to separate to shell commands."
+  :group 'gnus-files
+  :type 'string)
 
-(defvar gnus-valid-select-methods
-  '(("nntp" post address prompt-address)
+(defcustom gnus-valid-select-methods
+  '(("nntp" post address prompt-address physical-address)
     ("nnspool" post address)
     ("nnvirtual" post-mail virtual prompt-address)
     ("nnmbox" mail respool address)
     ("nnml" mail respool address)
     ("nnmh" mail respool address)
-    ("nndir" post-mail prompt-address)
-    ("nneething" none address prompt-address)
+    ("nndir" post-mail prompt-address physical-address)
+    ("nneething" none address prompt-address physical-address)
     ("nndoc" none address prompt-address)
     ("nnbabyl" mail address respool)
     ("nnkiboze" post virtual)
     ("nnsoup" post-mail address)
     ("nndraft" post-mail)
     ("nnfolder" mail respool address)
-    ("nngateway" none address prompt-address)
+    ("nngateway" none address prompt-address physical-address)
     ("nnweb" none))
   "An alist of valid select methods.
 The first element of each list lists should be a string with the name
@@ -570,46 +1147,91 @@ of the select method.  The other elements may be the category of
 this method (i. e., `post', `mail', `none' or whatever) or other
 properties that this method has (like being respoolable).
 If you implement a new select method, all you should have to change is
-this variable. I think.")
-
-(defvar gnus-updated-mode-lines '(group article summary tree)
-  "*List of buffers that should update their mode lines.
-The list may contain the symbols `group', `article' and `summary'.  If
-the corresponding symbol is present, Gnus will keep that mode line
-updated with information that may be pertinent.
-If this variable is nil, screen refresh may be quicker.")
+this variable. I think."
+  :group 'gnus-server
+  :type '(repeat (group (string :tag "Name")
+                       (radio-button-choice (const :format "%v " post)
+                                            (const :format "%v " mail)
+                                            (const :format "%v " none)
+                                            (const post-mail))
+                       (checklist :inline t
+                                  (const :format "%v " address)
+                                  (const :format "%v " prompt-address)
+                                  (const :format "%v " virtual)
+                                  (const respool)))))
+
+(define-widget 'gnus-select-method 'list
+  "Widget for entering a select method."
+  :args `((choice :tag "Method"
+                 ,@(mapcar (lambda (entry)
+                             (list 'const :format "%v\n"
+                                   (intern (car entry))))
+                           gnus-valid-select-methods))
+         (string :tag "Address")
+         (editable-list  :inline t
+                         (list :format "%v"
+                               variable
+                               (sexp :tag "Value")))))
+
+(defcustom gnus-updated-mode-lines '(group article summary tree)
+  "List of buffers that should update their mode lines.
+The list may contain the symbols `group', `article', `tree' and
+`summary'.  If the corresponding symbol is present, Gnus will keep
+that mode line updated with information that may be pertinent.
+If this variable is nil, screen refresh may be quicker."
+  :group 'gnus-various
+  :type '(set (const group)
+             (const article)
+             (const summary)
+             (const tree)))
 
 ;; Added by Keinonen Kari <kk85613@cs.tut.fi>.
-(defvar gnus-mode-non-string-length nil
+(defcustom gnus-mode-non-string-length nil
   "*Max length of mode-line non-string contents.
 If this is nil, Gnus will take space as is needed, leaving the rest
-of the modeline intact.")
+of the modeline intact.  Note that the default of nil is unlikely
+to be desirable; see the manual for further details."
+  :group 'gnus-various
+  :type '(choice (const nil)
+                integer))
 
-(defvar gnus-auto-expirable-newsgroups nil
+(defcustom gnus-auto-expirable-newsgroups nil
   "*Groups in which to automatically mark read articles as expirable.
 If non-nil, this should be a regexp that should match all groups in
-which to perform auto-expiry.  This only makes sense for mail groups.")
+which to perform auto-expiry.  This only makes sense for mail groups."
+  :group 'nnmail-expire
+  :type '(choice (const nil)
+                regexp))
 
-(defvar gnus-total-expirable-newsgroups nil
+(defcustom gnus-total-expirable-newsgroups nil
   "*Groups in which to perform expiry of all read articles.
 Use with extreme caution.  All groups that match this regexp will be
 expiring - which means that all read articles will be deleted after
-(say) one week.         (This only goes for mail groups and the like, of
-course.)")
-
-(defvar gnus-group-uncollapsed-levels 1
-  "Number of group name elements to leave alone when making a short group name.")
-
-(defvar gnus-group-use-permanent-levels nil
-  "*If non-nil, once you set a level, Gnus will use this level.")
+\(say) one week.        (This only goes for mail groups and the like, of
+course.)"
+  :group 'nnmail-expire
+  :type '(choice (const nil)
+                regexp))
+
+(defcustom gnus-group-uncollapsed-levels 1
+  "Number of group name elements to leave alone when making a short group name."
+  :group 'gnus-group-visual
+  :type 'integer)
+
+(defcustom gnus-group-use-permanent-levels nil
+  "*If non-nil, once you set a level, Gnus will use this level."
+  :group 'gnus-group-levels
+  :type 'boolean)
 
 ;; Hooks.
 
-(defvar gnus-load-hook nil
-  "*A hook run while Gnus is loaded.")
+(defcustom gnus-load-hook nil
+  "A hook run while Gnus is loaded."
+  :group 'gnus-start
+  :type 'hook)
 
-(defvar gnus-apply-kill-hook '(gnus-apply-kill-file)
-  "*A hook called to apply kill files to a group.
+(defcustom gnus-apply-kill-hook '(gnus-apply-kill-file)
+  "A hook called to apply kill files to a group.
 This hook is intended to apply a kill file to the selected newsgroup.
 The function `gnus-apply-kill-file' is called by default.
 
@@ -624,16 +1246,21 @@ following hook:
        (lambda ()
          (cond ((string-match \"control\" gnus-newsgroup-name)
                 (gnus-kill \"Subject\" \"rmgroup\")
-                (gnus-expunge \"X\"))))))")
+                (gnus-expunge \"X\"))))))"
+  :group 'gnus-score-kill
+  :options '(gnus-apply-kill-file)
+  :type 'hook)
 
-(defvar gnus-group-change-level-function nil
+(defcustom gnus-group-change-level-function nil
   "Function run when a group level is changed.
-It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
+It is called with three parameters -- GROUP, LEVEL and OLDLEVEL."
+  :group 'gnus-group-level
+  :type 'function)
 
 ;;; Face thingies.
 
-(defvar gnus-visual 
-  '(summary-highlight group-highlight article-highlight 
+(defcustom gnus-visual
+  '(summary-highlight group-highlight article-highlight
                      mouse-face
                      summary-menu group-menu article-menu
                      tree-highlight menu highlight
@@ -643,9 +1270,39 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
   "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
-less space and be faster as a result.")
-
-(defvar gnus-mouse-face
+less space and be faster as a result.
+
+This variable can also be a list of visual elements to switch on.  For
+instance, to switch off all visual things except menus, you can say:
+
+   (setq gnus-visual '(menu))
+
+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'."
+  :group 'gnus-meta
+  :group 'gnus-visual
+  :type '(set (const summary-highlight)
+             (const group-highlight)
+             (const article-highlight)
+             (const mouse-face)
+             (const summary-menu)
+             (const group-menu)
+             (const article-menu)
+             (const tree-highlight)
+             (const menu)
+             (const highlight)
+             (const browse-menu)
+             (const server-menu)
+             (const page-marker)
+             (const tree-menu)
+             (const binary-menu)
+             (const pick-menu)
+             (const grouplens-menu)))
+
+(defcustom gnus-mouse-face
   (condition-case ()
       (if (gnus-visual-p 'mouse-face 'highlight)
          (if (boundp 'gnus-mouse-face)
@@ -655,9 +1312,11 @@ less space and be faster as a result.")
     (error 'highlight))
   "Face used for group or summary buffer mouse highlighting.
 The line beneath the mouse pointer will be highlighted with this
-face.")
+face."
+  :group 'gnus-visual
+  :type 'face)
 
-(defvar gnus-article-display-hook
+(defcustom gnus-article-display-hook
   (if (and (string-match "XEmacs" emacs-version)
           (featurep 'xface))
       '(gnus-article-hide-headers-if-wanted
@@ -674,9 +1333,46 @@ face.")
 If you leave the list empty, the article will appear exactly as it is
 stored on the disk.  The list entries will hide or highlight various
 parts of the article, making it easier to find the information you
-want.")
-
-
+want."
+  :group 'gnus-article-highlight
+  :group 'gnus-visual
+  :type 'hook
+  :options '(gnus-article-add-buttons
+            gnus-article-add-buttons-to-head
+            gnus-article-emphasize
+            gnus-article-fill-cited-article
+            gnus-article-remove-cr
+            gnus-article-de-quoted-unreadable
+            gnus-article-display-x-face
+            gnus-summary-stop-page-breaking
+            ;; gnus-summary-caesar-message
+            ;; gnus-summary-verbose-headers
+            gnus-summary-toggle-mime
+            gnus-article-hide
+            gnus-article-hide-headers
+            gnus-article-hide-boring-headers
+            gnus-article-hide-signature
+            gnus-article-hide-citation
+            gnus-article-hide-pgp
+            gnus-article-hide-pem
+            gnus-article-highlight
+            gnus-article-highlight-headers
+            gnus-article-highlight-citation
+            gnus-article-highlight-signature
+            gnus-article-date-ut
+            gnus-article-date-local
+            gnus-article-date-lapsed
+            gnus-article-date-original
+            gnus-article-remove-trailing-blank-lines
+            gnus-article-strip-leading-blank-lines
+            gnus-article-strip-multiple-blank-lines
+            gnus-article-strip-blank-lines
+            gnus-article-treat-overstrike))
+
+(defcustom gnus-article-save-directory gnus-directory
+  "*Name of the directory articles will be saved in (default \"~/News\")."
+  :group 'gnus-article-saving
+  :type 'directory)
 
 \f
 ;;; Internal variables
@@ -696,6 +1392,7 @@ want.")
 
 ;; Variable holding the user answers to all method prompts.
 (defvar gnus-method-history nil)
+(defvar gnus-group-history nil)
 
 ;; Variable holding the user answers to all mail method prompts.
 (defvar gnus-mail-method-history nil)
@@ -758,6 +1455,9 @@ want.")
 (defvar gnus-slave nil
   "Whether this Gnus is a slave or not.")
 
+(defvar gnus-batch-mode nil
+  "Whether this Gnus is running in batch mode or not.")
+
 (defvar gnus-variable-list
   '(gnus-newsrc-options gnus-newsrc-options-n
     gnus-newsrc-last-checked-date
@@ -792,8 +1492,8 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (defvar gnus-active-hashtb nil
   "Hashtable of active articles.")
 
-(defvar gnus-moderated-list nil
-  "List of moderated newsgroups.")
+(defvar gnus-moderated-hashtb nil
+  "Hashtable of moderated newsgroups.")
 
 ;; Save window configuration.
 (defvar gnus-prev-winconf nil)
@@ -829,6 +1529,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("info" Info-goto-node)
      ("hexl" hexl-hex-string-to-integer)
      ("pp" pp pp-to-string pp-eval-expression)
+     ("ps-print" ps-print-preprint)
      ("mail-extr" mail-extract-address-components)
      ("message" :interactive t
       message-send-and-exit message-yank-original)
@@ -839,6 +1540,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("rmailout" rmail-output)
      ("rmail" rmail-insert-rmail-file-header rmail-count-new-messages
       rmail-show-message)
+     ("gnus-audio" :interactive t gnus-audio-play)
      ("gnus-xmas" gnus-xmas-splash)
      ("gnus-soup" :interactive t
       gnus-group-brew-soup gnus-brew-soup gnus-soup-add-article
@@ -849,6 +1551,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-Folder-save-name gnus-folder-save-name)
      ("gnus-mh" :interactive t gnus-summary-save-in-folder)
      ("gnus-demon" gnus-demon-add-nocem gnus-demon-add-scanmail
+      gnus-demon-add-rescan gnus-demon-add-scan-timestamps
       gnus-demon-add-disconnection gnus-demon-add-handler
       gnus-demon-remove-handler)
      ("gnus-demon" :interactive t
@@ -889,7 +1592,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-score-find-trace gnus-score-file-name)
      ("gnus-cus" :interactive t gnus-group-customize gnus-score-customize)
      ("gnus-topic" :interactive t gnus-topic-mode)
-     ("gnus-topic" gnus-topic-remove-group)
+     ("gnus-topic" gnus-topic-remove-group gnus-topic-set-parameters)
      ("gnus-salt" :interactive t gnus-pick-mode gnus-binary-mode)
      ("gnus-uu" (gnus-uu-extract-map keymap) (gnus-uu-mark-map keymap))
      ("gnus-uu" :interactive t
@@ -903,6 +1606,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-uu-decode-uu-and-save-view gnus-uu-decode-unshar-view
       gnus-uu-decode-unshar-and-save-view gnus-uu-decode-save-view
       gnus-uu-decode-binhex-view)
+     ("gnus-uu" gnus-uu-delete-work-dir gnus-quote-arg-for-sh-or-csh)
      ("gnus-msg" (gnus-summary-send-map keymap)
       gnus-article-mail gnus-copy-article-buffer gnus-extended-version)
      ("gnus-msg" :interactive t
@@ -916,10 +1620,10 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("gnus-picon" :interactive t gnus-article-display-picons
       gnus-group-display-picons gnus-picons-article-display-x-face
       gnus-picons-display-x-face)
-     ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p 
+     ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p
       gnus-grouplens-mode)
      ("smiley" :interactive t gnus-smiley-display)
-     ("gnus-win" gnus-configure-windows)
+     ("gnus-win" gnus-configure-windows gnus-add-configuration)
      ("gnus-sum" gnus-summary-insert-line gnus-summary-read-group
       gnus-list-of-unread-articles gnus-list-of-read-articles
       gnus-offer-save-summaries gnus-make-thread-indent-array
@@ -935,7 +1639,8 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-article-prepare gnus-article-set-window-start
       gnus-article-next-page gnus-article-prev-page
       gnus-request-article-this-buffer gnus-article-mode
-      gnus-article-setup-buffer gnus-narrow-to-page)
+      gnus-article-setup-buffer gnus-narrow-to-page
+      gnus-article-delete-invisible-text)
      ("gnus-art" :interactive t
       gnus-article-hide-headers gnus-article-hide-boring-headers
       gnus-article-treat-overstrike gnus-article-word-wrap
@@ -945,9 +1650,9 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-article-hide-pem gnus-article-hide-signature
       gnus-article-strip-leading-blank-lines gnus-article-date-local
       gnus-article-date-original gnus-article-date-lapsed
-      gnus-decode-rfc1522 gnus-article-show-all-headers
+      gnus-article-show-all-headers
       gnus-article-edit-mode gnus-article-edit-article
-      gnus-article-edit-done)
+      gnus-article-edit-done gnus-decode-rfc1522 article-decode-rfc1522)
      ("gnus-int" gnus-request-type)
      ("gnus-start" gnus-newsrc-parse-options gnus-1 gnus-no-server-1
       gnus-dribble-enter)
@@ -960,15 +1665,15 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("gnus-logic" gnus-score-advanced)
      ("gnus-undo" gnus-undo-mode gnus-undo-register)
      ("gnus-async" gnus-async-request-fetched-article gnus-async-prefetch-next
-      gnus-async-prefetch-article gnus-async-prefetch-remove-group)
-     ("article" article-decode-rfc1522)
+      gnus-async-prefetch-article gnus-async-prefetch-remove-group
+      gnus-async-halt-prefetch)
      ("gnus-vm" :interactive t gnus-summary-save-in-vm
       gnus-summary-save-article-vm))))
 
 ;;; gnus-sum.el thingies
 
 
-(defvar gnus-summary-line-format "%U\%R\%z\%I\%(%[%4L: %-20,20n%]%) %s\n"
+(defcustom gnus-summary-line-format "%U\%R\%z\%I\%(%[%4L: %-20,20n%]%) %s\n"
   "*The format specification of the lines in the summary buffer.
 
 It works along the same lines as a normal formatting string,
@@ -1002,6 +1707,7 @@ with some simple extensions.
 %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).
 %u   User defined specifier.  The next character in the format string should
      be a letter.  Gnus will call the function gnus-user-format-function-X,
@@ -1024,7 +1730,9 @@ which is bad enough.
 The smart choice is to have these specs as for to the left as
 possible.
 
-This restriction may disappear in later versions of Gnus.")
+This restriction may disappear in later versions of Gnus."
+  :type 'string
+  :group 'gnus-summary-format)
 
 ;;;
 ;;; Skeleton keymaps
@@ -1032,16 +1740,22 @@ This restriction may disappear in later versions of Gnus.")
 
 (defun gnus-suppress-keymap (keymap)
   (suppress-keymap keymap)
-  (let ((keys `([delete] "\177" "\M-u"))) ;gnus-mouse-2 
+  (let ((keys `([delete] "\177" "\M-u"))) ;gnus-mouse-2
     (while keys
       (define-key keymap (pop keys) 'undefined))))
 
-(defvar gnus-article-mode-map (make-keymap))
-(gnus-suppress-keymap gnus-article-mode-map)
-(defvar gnus-summary-mode-map (make-keymap))
-(gnus-suppress-keymap gnus-summary-mode-map)
-(defvar gnus-group-mode-map (make-keymap))
-(gnus-suppress-keymap gnus-group-mode-map)
+(defvar gnus-article-mode-map
+  (let ((keymap (make-keymap)))
+    (gnus-suppress-keymap keymap)
+    keymap))
+(defvar gnus-summary-mode-map
+  (let ((keymap (make-keymap)))
+    (gnus-suppress-keymap keymap)
+    keymap))
+(defvar gnus-group-mode-map
+  (let ((keymap (make-keymap)))
+    (gnus-suppress-keymap keymap)
+    keymap))
 
 \f
 
@@ -1134,7 +1848,7 @@ This restriction may disappear in later versions of Gnus.")
 
 (defun gnus-info-set-entry (info entry number)
   ;; Extend the info until we have enough elements.
-  (while (< (length info) number)
+  (while (<= (length info) number)
     (nconc info (list nil)))
   ;; Set the entry.
   (setcar (nthcdr number info) entry))
@@ -1235,7 +1949,7 @@ If ARG, insert string at point."
       (string-to-number
        (if (zerop major)
           (format "%s00%02d%02d"
-                  (cond 
+                  (cond
                    ((member alpha '("(ding)" "d")) "4.99")
                    ((member alpha '("September" "s")) "5.01")
                    ((member alpha '("Red" "r")) "5.03"))
@@ -1348,7 +2062,9 @@ that that variable is buffer-local to the summary buffers."
 (defsubst gnus-server-add-address (method)
   (let ((method-name (symbol-name (car method))))
     (if (and (memq 'address (assoc method-name gnus-valid-select-methods))
-            (not (assq (intern (concat method-name "-address")) method)))
+            (not (assq (intern (concat method-name "-address")) method))
+            (memq 'physical-address (assq (car method)
+                                          gnus-valid-select-methods)))
        (append method (list (list (intern (concat method-name "-address"))
                                   (nth 1 method))))
       method)))
@@ -1370,7 +2086,7 @@ that that variable is buffer-local to the summary buffers."
 
 (defun gnus-server-to-method (server)
   "Map virtual server names to select methods."
-  (or 
+  (or
    ;; Is this a method, perhaps?
    (and server (listp server) server)
    ;; Perhaps this is the native server?
@@ -1421,7 +2137,7 @@ that that variable is buffer-local to the summary buffers."
 
 (defun gnus-archive-server-wanted-p ()
   "Say whether the user wants to use the archive server."
-  (cond 
+  (cond
    ((or (not gnus-message-archive-method)
        (not gnus-message-archive-group))
     nil)
@@ -1455,7 +2171,8 @@ that that variable is buffer-local to the summary buffers."
     ""))
 
 (defun gnus-group-method (group)
-  "Return the server or method used for selecting GROUP."
+  "Return the server or method used for selecting GROUP.
+You should probably use `gnus-find-method-for-group' instead."
   (let ((prefix (gnus-group-real-prefix group)))
     (if (equal prefix "")
        gnus-select-method
@@ -1596,6 +2313,15 @@ just the host name."
              group nil)))
     name))
 
+(defun gnus-narrow-to-body ()
+  "Narrow to the body of an article."
+  (narrow-to-region
+   (progn
+     (goto-char (point-min))
+     (or (search-forward "\n\n" nil t)
+        (point-max)))
+   (point-max)))
+
 \f
 ;;;
 ;;; Kill file handling.
@@ -1620,13 +2346,14 @@ Returns the number of articles marked as read."
 
 (defcustom gnus-kill-file-name "KILL"
   "Suffix of the kill files."
-  :group 'gnus-score
+  :group 'gnus-score-kill
+  :group 'gnus-score-files
   :type 'string)
 
 (defun gnus-newsgroup-kill-file (newsgroup)
   "Return the name of a kill file name for NEWSGROUP.
 If NEWSGROUP is nil, return the global kill file name instead."
-  (cond 
+  (cond
    ;; The global KILL file is placed at top of the directory.
    ((or (null newsgroup)
        (string-equal newsgroup ""))
@@ -1658,26 +2385,33 @@ If NEWSGROUP is nil, return the global kill file name instead."
   (memq option (assoc (format "%s" (car method))
                      gnus-valid-select-methods)))
 
+(defun gnus-similar-server-opened (method)
+  (let ((opened gnus-opened-servers))
+    (while (and method opened)
+      (when (and (equal (cadr method) (cadaar opened))
+                (not (equal method (caar opened))))
+       (setq method nil))
+      (pop opened))
+    (not method)))
+
 (defun gnus-server-extend-method (group method)
   ;; This function "extends" a virtual server. If the server is
   ;; "hello", and the select method is ("hello" (my-var "something"))
   ;; in the group "alt.alt", this will result in a new virtual server
   ;; called "hello+alt.alt".
-  (let ((entry
-        (gnus-copy-sequence
-         (if (gnus-server-equal method gnus-select-method) gnus-select-method
-           (cdr (assoc (car method) gnus-server-alist))))))
-    (if (not entry)
-       method
-      (setcar (cdr entry) (concat (nth 1 entry) "+" group))
-      (nconc entry (cdr method)))))
+  (if (or (not (inline (gnus-similar-server-opened method)))
+         (not (cddr method)))
+      method
+    `(,(car method) ,(concat (cadr method) "+" group)
+      (,(intern (format "%s-address" (car method))) ,(cadr method))
+      ,@(cddr method))))
 
 (defun gnus-server-status (method)
   "Return the status of METHOD."
   (nth 1 (assoc method gnus-opened-servers)))
 
 (defun gnus-group-name-to-method (group)
-  "Return a select method suitable for GROUP."
+  "Guess a select method based on GROUP."
   (if (string-match ":" group)
       (let ((server (substring group 0 (match-beginning 0))))
        (if (string-match "\\+" server)
@@ -1699,9 +2433,9 @@ If NEWSGROUP is nil, return the global kill file name instead."
            gnus-select-method
          (setq method
                (cond ((stringp method)
-                      (gnus-server-to-method method))
-                     ((stringp (car method))
-                      (gnus-server-extend-method group method))
+                      (inline (gnus-server-to-method method)))
+                     ((stringp (cadr method))
+                      (inline (gnus-server-extend-method group method)))
                      (t
                       method)))
          (cond ((equal (cadr method) "")
@@ -1711,13 +2445,16 @@ If NEWSGROUP is nil, return the global kill file name instead."
                (t
                 (gnus-server-add-address method)))))))
 
-(defun gnus-check-backend-function (func group)
-  "Check whether GROUP supports function FUNC."
-  (let ((method (if (stringp group) (car (gnus-find-method-for-group group))
-                 group)))
-    (unless (featurep method)
-      (require method))
-    (fboundp (intern (format "%s-%s" method func)))))
+(defsubst gnus-check-backend-function (func group)
+  "Check whether GROUP supports function FUNC.
+GROUP can either be a string (a group name) or a select method."
+  (ignore-errors
+    (let ((method (if (stringp group)
+                     (car (gnus-find-method-for-group group))
+                   group)))
+      (unless (featurep method)
+       (require method))
+      (fboundp (intern (format "%s-%s" method func))))))
 
 (defun gnus-methods-using (feature)
   "Find all methods that have FEATURE."
@@ -1729,6 +2466,21 @@ If NEWSGROUP is nil, return the global kill file name instead."
       (setq valids (cdr valids)))
     outs))
 
+(defun gnus-read-group (prompt &optional default)
+  "Prompt the user for a group name.
+Disallow illegal group names."
+  (let ((prefix "")
+       group)
+    (while (not group)
+      (when (string-match
+            "[: `'\"/]\\|^$"
+            (setq group (read-string (concat prefix prompt)
+                                     (cons (or default "") 0)
+                                     'gnus-group-history)))
+       (setq prefix (format "Illegal group name: \"%s\".  " group)
+             group nil)))
+    group))
+
 (defun gnus-read-method (prompt)
   "Prompt the user for a method.
 Allow completion over sensible values."
@@ -1737,7 +2489,7 @@ Allow completion over sensible values."
          prompt (append gnus-valid-select-methods gnus-predefined-server-alist
                         gnus-server-alist)
          nil t nil 'gnus-method-history)))
-    (cond 
+    (cond
      ((equal method "")
       (setq method gnus-select-method))
      ((assoc method gnus-valid-select-methods)
@@ -1780,11 +2532,14 @@ As opposed to `gnus', this command will not connect to the local server."
 (defun gnus-other-frame (&optional arg)
   "Pop up a frame to read news."
   (interactive "P")
-  (if (gnus-alive-p)
-      (let ((pop-up-frames t))
-       (gnus arg))
-    (select-frame (make-frame))
-    (gnus arg)))
+  (let ((window (get-buffer-window gnus-group-buffer)))
+    (cond (window
+          (select-frame (window-frame window)))
+         ((= (length (frame-list)) 1)
+          (select-frame (make-frame)))
+         (t
+          (other-frame 1))))
+  (gnus arg))
 
 ;;;###autoload
 (defun gnus (&optional arg dont-connect slave)