*** empty log message ***
[gnus] / lisp / gnus.el
index 543cc17..787e19c 100644 (file)
 (require 'mail-utils)
 (require 'timezone)
 (require 'nnheader)
-(require 'message)
 (require 'nnmail)
-(require 'backquote)
+(require 'nnoo)
 
 (eval-when-compile (require 'cl))
 
-;;;###autoload
 (defvar gnus-directory (or (getenv "SAVEDIR") "~/News/")
   "*Directory variable from which all other Gnus file variables are derived.")
 
@@ -144,7 +142,32 @@ see the manual for details.")
     (nnfolder-get-new-mail nil)
     (nnfolder-inhibit-expiry t))
   "*Method used for archiving messages you've sent.
-This should be a mail method.")
+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.")
+
+(defvar 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
+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.
+
+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 
+        '((if (message-news-p)
+              \"misc-news\" 
+            \"misc-mail\")))
+
+Normally the group names returned by this variable should be
+unprefixed -- which implictly 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.")
 
 (defvar gnus-refer-article-method nil
   "*Preferred method for fetching an article by Message-ID.
@@ -187,6 +210,7 @@ instead.")
 (defvar gnus-group-faq-directory
   '("/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
     "/ftp@sunsite.auc.dk:/pub/usenet/"
+    "/ftp@sunsite.doc.ic.ac.uk:/pub/usenet/news-faqs/"
     "/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
     "/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
     "/ftp@rtfm.mit.edu:/pub/usenet/"
@@ -200,8 +224,8 @@ This will most commonly be on a remote machine, and the file will be
 fetched by ange-ftp.
 
 This variable can also be a list of directories.  In that case, the
-first element in the list will be used by default, and the others will
-be used as backup sites.
+first element in the list will be used by default.  The others can
+be used when being prompted for a site.
 
 Note that Gnus uses an aol machine as the default directory.  If this
 feels fundamentally unclean, just think of it as a way to finally get
@@ -279,7 +303,11 @@ If this variable is a list, and the list contains the element
 `not-score', long file names will not be used for score files; if it
 contains the element `not-save', long file names will not be used for
 saving; and if it contains the element `not-kill', long file names
-will not be used for kill files.")
+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.")
 
 (defvar gnus-article-save-directory gnus-directory
   "*Name of the directory articles will be saved in (default \"~/News\").")
@@ -478,7 +506,7 @@ If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
 comparing subjects.")
 
 (defvar gnus-simplify-ignored-prefixes nil
-  "*Regexp, matches for which are removed from subject lines when simplifying.")
+  "*Regexp, matches for which are removed from subject lines when simplifying fuzzily.")
 
 (defvar gnus-build-sparse-threads nil
   "*If non-nil, fill in the gaps in threads.
@@ -511,15 +539,26 @@ whether it is read or not.")
   "*If non-nil, the \\<gnus-group-mode-map>\\[gnus-group-get-new-news-this-group] command will advance point to the next group.")
 
 (defvar gnus-check-new-newsgroups t
-  "*Non-nil means that Gnus will add new newsgroups at startup.
-If this variable is `ask-server', Gnus will ask the server for new
-groups since the last time it checked. This means that the killed list
-is no longer necessary, so you could set `gnus-save-killed-list' to
-nil.
-
-A variant is to have this variable be a list of select methods.         Gnus
-will then use the `ask-server' method on all these select methods to
-query for new groups from all those servers.
+  "*Non-nil means that Gnus will run gnus-find-new-newsgroups at startup.
+This normally finds new newsgroups by comparing the active groups the
+servers have already reported with those Gnus already knows, either alive
+or killed.
+
+When any of the following are true, gnus-find-new-newsgroups will instead
+ask the servers (primary, secondary, and archive servers) to list new
+groups since the last time it checked:
+  1. This variable is `ask-server'.
+  2. This variable is a list of select methods (see below).
+  3. `gnus-read-active-file' is nil or `some'.
+  4. A prefix argument is given to gnus-find-new-newsgroups interactively.
+
+Thus, if this variable is `ask-server' or a list of select methods or
+`gnus-read-active-file' is nil or `some', then the killed list is no
+longer necessary, so you could safely set `gnus-save-killed-list' to nil.
+
+This variable can be a list of select methods which Gnus will query with
+the `ask-server' method in addition to the primary, secondary, and archive
+servers.
 
 Eg.
   (setq gnus-check-new-newsgroups
@@ -856,7 +895,6 @@ beginning of a line.")
        '(vertical 1.0
                 (summary 0.25 point)
                 (if gnus-carpal '(summary-carpal 4))
-                (if gnus-use-trees '(tree 0.25))
                 (article 1.0)))))
     (server
      (vertical 1.0
@@ -1075,7 +1113,7 @@ list of parameters to that command.")
 (defvar gnus-insert-pseudo-articles t
   "*If non-nil, insert pseudo-articles when decoding articles.")
 
-(defvar gnus-group-line-format "%M%S%p%P%5y: %(%g%)%l\n"
+(defvar gnus-group-line-format "%M\%S\%p\%P\%5y: %(%g%)%l\n"
   "*Format of group lines.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
@@ -1123,7 +1161,7 @@ Also note that if you change the format specification to include any
 of these specs, you must probably re-start Gnus to see them go into
 effect.")
 
-(defvar gnus-summary-line-format "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"
+(defvar 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,
@@ -1212,7 +1250,7 @@ with some simple extensions:
   "*The format specification for the article mode line.
 See `gnus-summary-mode-line-format' for a closer description.")
 
-(defvar gnus-group-mode-line-format "Gnus: %%b {%M%:%S}"
+(defvar gnus-group-mode-line-format "Gnus: %%b {%M\%:%S}"
   "*The format specification for the group mode line.
 It works along the same lines as a normal formatting string,
 with some simple extensions:
@@ -1232,13 +1270,13 @@ with some simple extensions:
     ("nneething" none address prompt-address)
     ("nndoc" none address prompt-address)
     ("nnbabyl" mail address respool)
-    ("nnkiboze" post address virtual)
+    ("nnkiboze" post virtual)
     ("nnsoup" post-mail address)
     ("nndraft" post-mail)
     ("nnfolder" mail respool address))
   "An alist of valid select methods.
 The first element of each list lists should be a string with the name
-of the select method.  The other elements may be be the category of
+of the select method.  The other elements may be the category of
 this method (ie. `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
@@ -1306,12 +1344,20 @@ See `gnus-thread-score-function' for en explanation of what a
   "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
   "*All new groups that match this regexp will be subscribed automatically.
 Note that this variable only deals with new groups.  It has no effect
-whatsoever on old groups.")
+whatsoever on old groups.
+
+New groups that match this regexp will not be handled by
+`gnus-subscribe-newsgroup-method'.  Instead, they will
+be subscribed using `gnus-subscribe-options-newsgroup-method'.")
 
 (defvar gnus-options-subscribe nil
   "*All new groups matching this regexp will be subscribed unconditionally.
 Note that this variable deals only with new newsgroups.         This variable
-does not affect old newsgroups.")
+does not affect old newsgroups.
+
+New groups that match this regexp will not be handled by
+`gnus-subscribe-newsgroup-method'.  Instead, they will
+be subscribed using `gnus-subscribe-options-newsgroup-method'.")
 
 (defvar gnus-options-not-subscribe nil
   "*All new groups matching this regexp will be ignored.
@@ -1361,6 +1407,9 @@ It calls `gnus-summary-expire-articles' by default.")
 (defvar gnus-summary-exit-hook nil
   "*A hook called on exit from the summary buffer.")
 
+(defvar gnus-check-bogus-groups-hook nil
+  "A hook run after removing bogus groups.")
+
 (defvar gnus-group-catchup-group-hook nil
   "*A hook run when catching up a group from the group buffer.")
 
@@ -1422,12 +1471,6 @@ If you want to run a special decoding program like nkf, use this hook.")
 ;(add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
 ;(add-hook 'gnus-article-display-hook 'gnus-article-maybe-highlight)
 
-(defvar gnus-article-x-face-command
-  "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -"
-  "String or function to be executed to display an X-Face header.
-If it is a string, the command will be executed in a sub-shell
-asynchronously.         The compressed face will be piped to this command.")
-
 (defvar gnus-article-x-face-too-ugly nil
   "Regexp matching posters whose face shouldn't be shown automatically.")
 
@@ -1703,7 +1746,7 @@ variable (string, integer, character, etc).")
     (?A gnus-tmp-article-number ?d)
     (?Z gnus-tmp-unread-and-unselected ?s)
     (?V gnus-version ?s)
-    (?U gnus-tmp-unread ?d)
+    (?U gnus-tmp-unread-and-unticked ?d)
     (?S gnus-tmp-subject ?s)
     (?e gnus-tmp-unselected ?d)
     (?u gnus-tmp-user-defined ?s)
@@ -1728,7 +1771,7 @@ variable (string, integer, character, etc).")
   "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
   "The mail address of the Gnus maintainers.")
 
-(defconst gnus-version-number "5.2.8"
+(defconst gnus-version-number "5.2.35"
   "Version number for this version of Gnus.")
 
 (defconst gnus-version (format "Gnus v%s" gnus-version-number)
@@ -1737,7 +1780,11 @@ variable (string, integer, character, etc).")
 (defvar gnus-info-nodes
   '((gnus-group-mode "(gnus)The Group Buffer")
     (gnus-summary-mode "(gnus)The Summary Buffer")
-    (gnus-article-mode "(gnus)The Article Buffer"))
+    (gnus-article-mode "(gnus)The Article Buffer")
+    (gnus-server-mode "(gnus)The Server Buffer")
+    (gnus-browse-mode "(gnus)Browse Foreign Server")
+    (gnus-tree-mode "(gnus)Tree Display")
+    )
   "Alist of major modes and related Info nodes.")
 
 (defvar gnus-group-buffer "*Group*")
@@ -1944,7 +1991,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
     gnus-newsgroup-history gnus-newsgroup-ancient
     gnus-newsgroup-sparse
     (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
-    gnus-newsgroup-adaptive-score-file
+    gnus-newsgroup-adaptive-score-file (gnus-reffed-article-number . -1)
     (gnus-newsgroup-expunged-tally . 0)
     gnus-cache-removable-articles gnus-newsgroup-cached
     gnus-newsgroup-data gnus-newsgroup-data-reverse
@@ -2007,7 +2054,7 @@ Thank you for your help in stamping out bugs.
       gnus-group-brew-soup gnus-brew-soup gnus-soup-add-article
       gnus-soup-send-replies gnus-soup-save-areas gnus-soup-pack-packet)
      ("nnsoup" nnsoup-pack-replies)
-     ("gnus-scomo" :interactive t gnus-score-mode)
+     ("score-mode" :interactive t gnus-score-mode)
      ("gnus-mh" gnus-mh-mail-setup gnus-summary-save-article-folder
       gnus-Folder-save-name gnus-folder-save-name)
      ("gnus-mh" :interactive t gnus-summary-save-in-folder)
@@ -2080,20 +2127,22 @@ Thank you for your help in stamping out bugs.
       gnus-uu-decode-binhex-view)
      ("gnus-msg" (gnus-summary-send-map keymap)
       gnus-mail-yank-original gnus-mail-send-and-exit
-      gnus-sendmail-setup-mail gnus-article-mail
-      gnus-inews-message-id gnus-new-mail gnus-mail-reply)
+      gnus-article-mail gnus-new-mail gnus-mail-reply
+      gnus-copy-article-buffer)
      ("gnus-msg" :interactive t
       gnus-group-post-news gnus-group-mail gnus-summary-post-news
       gnus-summary-followup gnus-summary-followup-with-original
       gnus-summary-cancel-article gnus-summary-supersede-article
-      gnus-post-news gnus-inews-news gnus-cancel-news
+      gnus-post-news gnus-inews-news 
       gnus-summary-reply gnus-summary-reply-with-original
       gnus-summary-mail-forward gnus-summary-mail-other-window
       gnus-bug)
      ("gnus-picon" :interactive t gnus-article-display-picons
-      gnus-group-display-picons gnus-picons-article-display-x-face)
+      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-grouplens-mode)
+     ("smiley" :interactive t gnus-smiley-display)
      ("gnus-vm" gnus-vm-mail-setup)
      ("gnus-vm" :interactive t gnus-summary-save-in-vm
       gnus-summary-save-article-vm))))
@@ -2127,6 +2176,10 @@ Thank you for your help in stamping out bugs.
             ,@forms)
         (select-window ,tempvar)))))
 
+(put 'gnus-eval-in-buffer-window 'lisp-indent-function 1)
+(put 'gnus-eval-in-buffer-window 'lisp-indent-hook 1)
+(put 'gnus-eval-in-buffer-window 'edebug-form-spec '(form body))
+
 (defmacro gnus-gethash (string hashtable)
   "Get hash value of STRING in HASHTABLE."
   `(symbol-value (intern-soft ,string ,hashtable)))
@@ -3003,7 +3056,8 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        (setq groupkey
              (if (string-match "^\\(.*\\)\\.[^.]+$" groupkey)
                  (substring groupkey (match-beginning 1) (match-end 1)))))
-      (gnus-subscribe-newsgroup newgroup before))))
+      (gnus-subscribe-newsgroup newgroup before))
+    (kill-buffer (current-buffer))))
 
 (defun gnus-subscribe-interactively (group)
   "Subscribe the new GROUP interactively.
@@ -3108,49 +3162,50 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
 ;; all whitespace.
 ;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
 (defun gnus-simplify-buffer-fuzzy ()
-  (goto-char (point-min))
-  (while (search-forward "\t" nil t)
-    (replace-match " " t t))
-  (goto-char (point-min))
-  (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *" nil t)
-  (goto-char (match-beginning 0))
-  (while (or
-         (looking-at "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
-         (looking-at "^[[].*: .*[]]$"))
+  (let ((case-fold-search t))
+    (goto-char (point-min))
+    (while (search-forward "\t" nil t)
+      (replace-match " " t t))
+    (goto-char (point-min))
+    (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *" nil t)
+    (goto-char (match-beginning 0))
+    (while (or
+           (looking-at "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
+           (looking-at "^[[].*: .*[]]$"))
+      (goto-char (point-min))
+      (while (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
+                               nil t)
+       (replace-match "" t t))
+      (goto-char (point-min))
+      (while (re-search-forward "^[[].*: .*[]]$" nil t)
+       (goto-char (match-end 0))
+       (delete-char -1)
+       (delete-region
+        (progn (goto-char (match-beginning 0)))
+        (re-search-forward ":"))))
     (goto-char (point-min))
-    (while (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
-                             nil t)
+    (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
       (replace-match "" t t))
     (goto-char (point-min))
-    (while (re-search-forward "^[[].*: .*[]]$" nil t)
-      (goto-char (match-end 0))
-      (delete-char -1)
-      (delete-region
-       (progn (goto-char (match-beginning 0)))
-       (re-search-forward ":"))))
-  (goto-char (point-min))
-  (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
-    (replace-match "" t t))
-  (goto-char (point-min))
-  (while (re-search-forward "  +" nil t)
-    (replace-match " " t t))
-  (goto-char (point-min))
-  (while (re-search-forward " $" nil t)
-    (replace-match "" t t))
-  (goto-char (point-min))
-  (while (re-search-forward "^ +" nil t)
-    (replace-match "" t t))
-  (goto-char (point-min))
-  (when gnus-simplify-subject-fuzzy-regexp
-    (if (listp gnus-simplify-subject-fuzzy-regexp)
-       (let ((list gnus-simplify-subject-fuzzy-regexp))
-         (while list
-           (goto-char (point-min))
-           (while (re-search-forward (car list) nil t)
-             (replace-match "" t t))
-           (setq list (cdr list))))
-      (while (re-search-forward gnus-simplify-subject-fuzzy-regexp nil t)
-       (replace-match "" t t)))))
+    (while (re-search-forward "  +" nil t)
+      (replace-match " " t t))
+    (goto-char (point-min))
+    (while (re-search-forward " $" nil t)
+      (replace-match "" t t))
+    (goto-char (point-min))
+    (while (re-search-forward "^ +" nil t)
+      (replace-match "" t t))
+    (goto-char (point-min))
+    (when gnus-simplify-subject-fuzzy-regexp
+      (if (listp gnus-simplify-subject-fuzzy-regexp)
+         (let ((list gnus-simplify-subject-fuzzy-regexp))
+           (while list
+             (goto-char (point-min))
+             (while (re-search-forward (car list) nil t)
+               (replace-match "" t t))
+             (setq list (cdr list))))
+       (while (re-search-forward gnus-simplify-subject-fuzzy-regexp nil t)
+         (replace-match "" t t))))))
 
 (defun gnus-simplify-subject-fuzzy (subject)
   "Siplify a subject string fuzzily."
@@ -3201,6 +3256,10 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
        gnus-server-alist nil
        gnus-group-list-mode nil
        gnus-opened-servers nil
+       gnus-group-mark-positions nil
+       gnus-newsgroup-data nil
+       gnus-newsgroup-unreads nil
+       nnoo-state-alist nil
        gnus-current-select-method nil)
   (gnus-shutdown 'gnus)
   ;; Kill the startup file.
@@ -3217,10 +3276,14 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
   (while gnus-buffer-list
     (gnus-kill-buffer (pop gnus-buffer-list)))
   ;; Remove Gnus frames.
+  (gnus-kill-gnus-frames))
+
+(defun gnus-kill-gnus-frames ()
+  "Kill all frames Gnus has created."
   (while gnus-created-frames
     (when (frame-live-p (car gnus-created-frames))
       ;; We slap a condition-case around this `delete-frame' to ensure 
-      ;; agains errors if we try do delete the single frame that's left.
+      ;; against errors if we try do delete the single frame that's left.
       (condition-case ()
          (delete-frame (car gnus-created-frames))
        (error nil)))
@@ -3254,13 +3317,15 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
        (or (not (numberp (nth i elem)))
            (zerop (nth i elem))
            (progn
-             (setq perc  (/ (float (nth 0 elem)) total))
+             (setq perc (if (= i 2)
+                            1.0
+                          (/ (float (nth 0 elem)) total)))
              (setq out (cons (if (eq pbuf (nth i types))
-                                 (vector (nth i types) perc 'point)
-                               (vector (nth i types) perc))
+                                 (list (nth i types) perc 'point)
+                               (list (nth i types) perc))
                              out))))
        (setq i (1+ i)))
-      (list (nreverse out)))))
+      `(vertical 1.0 ,@(nreverse out)))))
 
 ;;;###autoload
 (defun gnus-add-configuration (conf)
@@ -3784,7 +3849,7 @@ simple-first is t, first argument is already simplified."
     (apply 'format args)))
 
 (defun gnus-error (level &rest args)
-  "Beep an error if `gnus-verbose' is on LEVEL or less."
+  "Beep an error if LEVEL is equal to or less than `gnus-verbose'."
   (when (<= (floor level) gnus-verbose)
     (apply 'message args)
     (ding)
@@ -3814,7 +3879,7 @@ simple-first is t, first argument is already simplified."
   (remove-text-properties b e gnus-hidden-properties)
   (when (memq 'intangible gnus-hidden-properties)
     (gnus-put-text-property (max (1- b) (point-min))
-                      b 'intangible nil)))
+                           b 'intangible nil)))
 
 (defun gnus-hide-text-type (b e type)
   "Hide text of TYPE between B and E."
@@ -4170,7 +4235,7 @@ Note: LIST has to be sorted over `<'."
     "V" gnus-version
     "s" gnus-group-save-newsrc
     "z" gnus-group-suspend
-    "Z" gnus-group-clear-dribble
+;    "Z" gnus-group-clear-dribble
     "q" gnus-group-exit
     "Q" gnus-group-quit
     "?" gnus-group-describe-briefly
@@ -4448,7 +4513,8 @@ prompt the user for the name of an NNTP server to use."
            (setcar (cddr entry) (gnus-byte-code 'gnus-tmp-func)))))
 
       (push (cons 'version emacs-version) gnus-format-specs)
-
+      ;; Mark the .newsrc.eld file as "dirty".
+      (gnus-dribble-enter " ")
       (gnus-message 7 "Compiling user specs...done"))))
 
 (defun gnus-indent-rigidly (start end arg)
@@ -4734,6 +4800,20 @@ If REGEXP, only list groups matching REGEXP."
       (pop opened))
     out))
 
+(defun gnus-archive-server-wanted-p ()
+  "Say whether the user wants to use the archive server."
+  (cond 
+   ((or (not gnus-message-archive-method)
+       (not gnus-message-archive-group))
+    nil)
+   ((and gnus-message-archive-method gnus-message-archive-group)
+    t)
+   (t
+    (let ((active (cadr (assq 'nnfolder-active-file
+                             gnus-message-archive-method))))
+      (and active
+          (file-exists-p active))))))
+
 (defun gnus-group-prefixed-name (group method)
   "Return the whole name from GROUP and METHOD."
   (and (stringp method) (setq method (gnus-server-to-method method)))
@@ -4916,16 +4996,17 @@ increase the score of each group you read."
         (group (gnus-group-group-name))
         (entry (and group (gnus-gethash group gnus-newsrc-hashtb)))
         gnus-group-indentation)
-    (and entry
-        (not (gnus-ephemeral-group-p group))
-        (gnus-dribble-enter
-         (concat "(gnus-group-set-info '"
-                 (prin1-to-string (nth 2 entry)) ")")))
-    (setq gnus-group-indentation (gnus-group-group-indentation))
-    (gnus-delete-line)
-    (gnus-group-insert-group-line-info group)
-    (forward-line -1)
-    (gnus-group-position-point)))
+    (when group
+      (and entry
+          (not (gnus-ephemeral-group-p group))
+          (gnus-dribble-enter
+           (concat "(gnus-group-set-info '"
+                   (prin1-to-string (nth 2 entry)) ")")))
+      (setq gnus-group-indentation (gnus-group-group-indentation))
+      (gnus-delete-line)
+      (gnus-group-insert-group-line-info group)
+      (forward-line -1)
+      (gnus-group-position-point))))
 
 (defun gnus-group-insert-group-line-info (group)
   "Insert GROUP on the current line."
@@ -5090,23 +5171,25 @@ already."
             (max-len 60)
             gnus-tmp-header            ;Dummy binding for user-defined formats
             ;; Get the resulting string.
+            (modified 
+             (and gnus-dribble-buffer
+                  (buffer-name gnus-dribble-buffer)
+                  (buffer-modified-p gnus-dribble-buffer)
+                  (save-excursion
+                    (set-buffer gnus-dribble-buffer)
+                    (not (zerop (buffer-size))))))
             (mode-string (eval gformat)))
        ;; Say whether the dribble buffer has been modified.
        (setq mode-line-modified
-             (if (and gnus-dribble-buffer
-                      (buffer-name gnus-dribble-buffer)
-                      (buffer-modified-p gnus-dribble-buffer)
-                      (save-excursion
-                        (set-buffer gnus-dribble-buffer)
-                        (not (zerop (buffer-size)))))
-                 "---*- " "----- "))
+             (if modified "---*- " "----- "))
        ;; If the line is too long, we chop it off.
        (when (> (length mode-string) max-len)
          (setq mode-string (substring mode-string 0 (- max-len 4))))
        (prog1
            (setq mode-line-buffer-identification 
-                 (list mode-string))
-         (set-buffer-modified-p t))))))
+                 (gnus-mode-line-buffer-identification
+                  (list mode-string)))
+         (set-buffer-modified-p modified))))))
 
 (defun gnus-group-group-name ()
   "Get the name of the newsgroup on the current line."
@@ -5442,15 +5525,15 @@ Returns whether the fetching was successful or not."
                                             group gnus-active-hashtb))))
       (and b (goto-char b)))))
 
-(defun gnus-group-next-group (n)
+(defun gnus-group-next-group (n &optional silent)
   "Go to next N'th newsgroup.
 If N is negative, search backward instead.
 Returns the difference between N and the number of skips actually
 done."
   (interactive "p")
-  (gnus-group-next-unread-group n t))
+  (gnus-group-next-unread-group n t nil silent))
 
-(defun gnus-group-next-unread-group (n &optional all level)
+(defun gnus-group-next-unread-group (n &optional all level silent)
   "Go to next N'th unread newsgroup.
 If N is negative, search backward instead.
 If ALL is non-nil, choose any newsgroup, unread or not.
@@ -5466,8 +5549,10 @@ made."
                (gnus-group-search-forward
                 backward (or (not gnus-group-goto-unread) all) level))
       (setq n (1- n)))
-    (if (/= 0 n) (gnus-message 7 "No more%s newsgroups%s" (if all "" " unread")
-                              (if level " on this level or higher" "")))
+    (when (and (/= 0 n)
+              (not silent))
+      (gnus-message 7 "No more%s newsgroups%s" (if all "" " unread")
+                   (if level " on this level or higher" "")))
     n))
 
 (defun gnus-group-prev-group (n)
@@ -5603,10 +5688,11 @@ ADDRESS."
     t))
 
 (defun gnus-group-delete-group (group &optional force)
-  "Delete the current group.
+  "Delete the current group.  Only meaningful with mail groups.
 If FORCE (the prefix) is non-nil, all the articles in the group will
 be deleted.  This is \"deleted\" as in \"removed forever from the face
-of the Earth\".         There is no undo."
+of the Earth\".         There is no undo.  The user will be prompted before
+doing the deletion."
   (interactive
    (list (gnus-group-group-name)
         current-prefix-arg))
@@ -6148,7 +6234,8 @@ or nil if no action could be taken."
                     (gnus-uncompress-sequence (cdr expirable)) group))
                ;; Just expire using the normal expiry values.
                (gnus-request-expire-articles
-                (gnus-uncompress-sequence (cdr expirable)) group)))))
+                (gnus-uncompress-sequence (cdr expirable)) group))))
+           (gnus-close-group group))
          (gnus-message 6 "Expiring articles in %s...done" group)))
       (gnus-group-position-point))))
 
@@ -6319,6 +6406,12 @@ of groups killed."
        (while groups
          (gnus-group-remove-mark (setq group (pop groups)))
          (gnus-delete-line)
+         (push group gnus-killed-list)
+         (setq gnus-newsrc-alist
+               (delq (assoc group gnus-newsrc-alist)
+                     gnus-newsrc-alist))
+         (when gnus-group-change-level-function
+           (funcall gnus-group-change-level-function group 9 3))
          (cond
           ((setq entry (gnus-gethash group gnus-newsrc-hashtb))
            (push (cons (car entry) (nth 2 entry))
@@ -6376,8 +6469,10 @@ is returned."
     (let* ((prev gnus-newsrc-alist)
           (alist (cdr prev)))
       (while alist
-       (if (= (gnus-info-level level) level)
-           (setcdr prev (cdr alist))
+       (if (= (gnus-info-level (car alist)) level)
+           (progn
+             (push (gnus-info-group (car alist)) gnus-killed-list)
+             (setcdr prev (cdr alist)))
          (setq prev alist))
        (setq alist (cdr alist)))
       (gnus-make-hashtable-from-newsrc-alist)
@@ -6498,7 +6593,10 @@ If N is negative, this group and the N-1 previous groups will be checked."
            (unless (gnus-virtual-group-p group)
              (gnus-close-group group))
            (gnus-group-update-group group))
-       (gnus-error 3 "%s error: %s" group (gnus-status-message group))))
+       (if (eq (gnus-server-status (gnus-find-method-for-group group))
+               'denied)
+           (gnus-error "Server denied access")
+         (gnus-error 3 "%s error: %s" group (gnus-status-message group)))))
     (when beg (goto-char beg))
     (when gnus-goto-next-group-when-activating
       (gnus-group-next-unread-group 1 t))
@@ -6509,11 +6607,13 @@ If N is negative, this group and the N-1 previous groups will be checked."
   "Fetch the FAQ for the current group."
   (interactive
    (list
-    (gnus-group-real-name (gnus-group-group-name))
+    (and (gnus-group-group-name)
+        (gnus-group-real-name (gnus-group-group-name)))
     (cond (current-prefix-arg
           (completing-read
            "Faq dir: " (and (listp gnus-group-faq-directory)
-                            gnus-group-faq-directory))))))
+                            (mapcar (lambda (file) (list file))
+                                    gnus-group-faq-directory)))))))
   (or faq-dir
       (setq faq-dir (if (listp gnus-group-faq-directory)
                        (car gnus-group-faq-directory)
@@ -6528,16 +6628,17 @@ If N is negative, this group and the N-1 previous groups will be checked."
 (defun gnus-group-describe-group (force &optional group)
   "Display a description of the current newsgroup."
   (interactive (list current-prefix-arg (gnus-group-group-name)))
-  (and force (setq gnus-description-hashtb nil))
-  (let ((method (gnus-find-method-for-group group))
-       desc)
+  (let* ((method (gnus-find-method-for-group group))
+        (mname (gnus-group-prefixed-name "" method))
+        desc)
+    (when (and force
+              gnus-description-hashtb)
+      (gnus-sethash mname nil gnus-description-hashtb))
     (or group (error "No group name given"))
     (and (or (and gnus-description-hashtb
                  ;; We check whether this group's method has been
                  ;; queried for a description file.
-                 (gnus-gethash
-                  (gnus-group-prefixed-name "" method)
-                  gnus-description-hashtb))
+                 (gnus-gethash mname gnus-description-hashtb))
             (setq desc (gnus-group-get-description group))
             (gnus-read-descriptions-file method))
         (gnus-message 1
@@ -6568,7 +6669,7 @@ If N is negative, this group and the N-1 previous groups will be checked."
     (goto-char (point-min))
     (gnus-group-position-point)))
 
-;; Suggested by by Daniel Quinlan <quinlan@best.com>.
+;; Suggested by Daniel Quinlan <quinlan@best.com>.
 (defun gnus-group-apropos (regexp &optional search-description)
   "List all newsgroups that have names that match a regexp."
   (interactive "sGnus apropos (regexp): ")
@@ -6705,19 +6806,18 @@ The hook gnus-suspend-gnus-hook is called before actually suspending."
   (interactive)
   (run-hooks 'gnus-suspend-gnus-hook)
   ;; Kill Gnus buffers except for group mode buffer.
-  (let ((group-buf (get-buffer gnus-group-buffer)))
-    ;; Do this on a separate list in case the user does a ^G before we finish
-    (let ((gnus-buffer-list
-          (delq group-buf (delq gnus-dribble-buffer
-                                (append gnus-buffer-list nil)))))
-      (while gnus-buffer-list
-       (gnus-kill-buffer (car gnus-buffer-list))
-       (setq gnus-buffer-list (cdr gnus-buffer-list))))
-    (if group-buf
-       (progn
-         (setq gnus-buffer-list (list group-buf))
-         (bury-buffer group-buf)
-         (delete-windows-on group-buf t)))))
+  (let* ((group-buf (get-buffer gnus-group-buffer))
+        ;; Do this on a separate list in case the user does a ^G before we finish
+        (gnus-buffer-list
+         (delete group-buf (delete gnus-dribble-buffer
+                                   (append gnus-buffer-list nil)))))
+    (while gnus-buffer-list
+      (gnus-kill-buffer (pop gnus-buffer-list)))
+    (gnus-kill-gnus-frames)
+    (when group-buf
+      (setq gnus-buffer-list (list group-buf))
+      (bury-buffer group-buf)
+      (delete-windows-on group-buf t))))
 
 (defun gnus-group-clear-dribble ()
   "Clear all information from the dribble buffer."
@@ -7077,6 +7177,7 @@ and the second element is the address."
     "s" gnus-article-hide-signature
     "c" gnus-article-hide-citation
     "p" gnus-article-hide-pgp
+    "P" gnus-article-hide-pem
     "\C-c" gnus-article-hide-citation-maybe)
 
   (gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
@@ -7168,6 +7269,8 @@ The following commands are available:
   (make-local-variable 'gnus-summary-line-format)
   (make-local-variable 'gnus-summary-line-format-spec)
   (make-local-variable 'gnus-summary-mark-positions)
+  (gnus-make-local-hook 'post-command-hook)
+  (gnus-add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
   (run-hooks 'gnus-summary-mode-hook))
 
 (defun gnus-summary-make-local-variables ()
@@ -7521,6 +7624,7 @@ This is all marks except unread, ticked, dormant, and expirable."
          (article-buffer gnus-article-buffer)
          (original gnus-original-article-buffer)
          (gac gnus-article-current)
+         (reffed gnus-reffed-article-number)
          (score-file gnus-current-score-file))
       (save-excursion
        (set-buffer gnus-group-buffer)
@@ -7533,6 +7637,7 @@ This is all marks except unread, ticked, dormant, and expirable."
        (setq gnus-summary-buffer summary)
        (setq gnus-article-buffer article-buffer)
        (setq gnus-original-article-buffer original)
+       (setq gnus-reffed-article-number reffed)
        (setq gnus-current-score-file score-file)))))
 
 (defun gnus-summary-last-article-p (&optional article)
@@ -7784,7 +7889,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        (cond (gnus-newsgroup-dormant
               (gnus-summary-limit-include-dormant))
              ((and gnus-newsgroup-scored show-all)
-              (gnus-summary-limit-include-expunged))))
+              (gnus-summary-limit-include-expunged t))))
       ;; Function `gnus-apply-kill-file' must be called in this hook.
       (run-hooks 'gnus-apply-kill-hook)
       (if (and (zerop (buffer-size))
@@ -8150,6 +8255,15 @@ If NO-DISPLAY, don't generate a summary buffer."
       (gnus-data-compute-positions)
       (setq gnus-newsgroup-threads (nconc threads gnus-newsgroup-threads)))))
 
+(defun gnus-number-to-header (number)
+  "Return the header for article NUMBER."
+  (let ((headers gnus-newsgroup-headers))
+    (while (and headers
+               (not (= number (mail-header-number (car headers)))))
+      (pop headers))
+    (when headers
+      (car headers))))
+
 (defun gnus-id-to-thread (id)
   "Return the (sub-)thread where ID appears."
   (gnus-gethash id gnus-newsgroup-dependencies))
@@ -8205,8 +8319,8 @@ If NO-DISPLAY, don't generate a summary buffer."
       (while threads
        (setq sub (car threads))
        (if (stringp (car sub))
-           ;; This is a gathered threads, so we look at the roots
-           ;; below it to find whether this article in in this
+           ;; This is a gathered thread, so we look at the roots
+           ;; below it to find whether this article is in this
            ;; gathered root.
            (progn
              (setq sub (cdr sub))
@@ -8386,11 +8500,16 @@ Unscored articles will be counted as having a score of zero."
   ;; This function find the total score of the thread below ROOT.
   (setq root (car root))
   (apply gnus-thread-score-function
-        (or (cdr (assq (mail-header-number root) gnus-newsgroup-scored))
-            gnus-summary-default-score 0)
-        (mapcar 'gnus-thread-total-score
-                (cdr (gnus-gethash (mail-header-id root)
-                                   gnus-newsgroup-dependencies)))))
+        (or (append
+             (mapcar 'gnus-thread-total-score
+                     (cdr (gnus-gethash (mail-header-id root)
+                                        gnus-newsgroup-dependencies)))
+                (if (> (mail-header-number root) 0)
+                    (list (or (cdr (assq (mail-header-number root) 
+                                         gnus-newsgroup-scored))
+                              gnus-summary-default-score 0))))
+            (list gnus-summary-default-score)
+            '(0))))
 
 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defvar gnus-tmp-prev-subject nil)
@@ -8611,6 +8730,8 @@ or a straight list of headers."
                    gnus-cached-mark)
                   ((memq number gnus-newsgroup-replied)
                    gnus-replied-mark)
+                  ((memq number gnus-newsgroup-saved)
+                   gnus-saved-mark)
                   (t gnus-unread-mark))
             gnus-tmp-from (mail-header-from gnus-tmp-header)
             gnus-tmp-name
@@ -8799,7 +8920,6 @@ If READ-ALL is non-nil, all articles in the group are selected."
              gnus-newsgroup-end
              (mail-header-number
               (gnus-last-element gnus-newsgroup-headers))))
-      (setq gnus-reffed-article-number -1)
       ;; GROUP is successfully selected.
       (or gnus-newsgroup-headers t)))))
 
@@ -8836,7 +8956,8 @@ If READ-ALL is non-nil, all articles in the group are selected."
                           "How many articles from %s (default %d): "
                           gnus-newsgroup-name number))))
                    (if (string-match "^[ \t]*$" input) number input)))
-                ((and (> scored marked) (< scored number))
+                ((and (> scored marked) (< scored number)
+                      (> (- scored number) 20))
                  (let ((input
                         (read-string
                          (format "%s %s (%d scored, %d total): "
@@ -8893,7 +9014,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
         (min (car active))
         (max (cdr active))
         (types gnus-article-mark-lists)
-        (uncompressed '(score bookmark))
+        (uncompressed '(score bookmark killed))
         marks var articles article mark)
 
     (while marked-lists
@@ -8909,14 +9030,15 @@ If READ-ALL is non-nil, all articles in the group are selected."
       ;; All articles have to be subsets of the active articles.
       (cond
        ;; Adjust "simple" lists.
-       ((memq mark '(tick dormant expirable reply killed save))
+       ((memq mark '(tick dormant expirable reply save))
        (while articles
          (when (or (< (setq article (pop articles)) min) (> article max))
            (set var (delq article (symbol-value var))))))
        ;; Adjust assocs.
-       ((memq mark '(score bookmark))
+       ((memq mark uncompressed)
        (while articles
-         (when (or (< (car (setq article (pop articles))) min)
+         (when (or (not (consp (setq article (pop articles))))
+                   (< (car article) min)
                    (> (car article) max))
            (set var (delq article (symbol-value var))))))))))
 
@@ -8951,7 +9073,8 @@ If READ-ALL is non-nil, all articles in the group are selected."
                                                (car type))))))
          (push (cons (cdr type)
                      (if (memq (cdr type) uncompressed) list
-                       (gnus-compress-sequence (set symbol (sort list '<)) t)))
+                       (gnus-compress-sequence 
+                        (set symbol (sort list '<)) t)))
                newmarked)))
 
       ;; Enter these new marks into the info of the group.
@@ -9043,7 +9166,9 @@ If WHERE is `summary', the summary mode line format will be used."
          ;; Pad the mode string a bit.
          (setq mode-string (format (format "%%-%ds" max-len) mode-string))))
       ;; Update the mode line.
-      (setq mode-line-buffer-identification (list mode-string))
+      (setq mode-line-buffer-identification 
+           (gnus-mode-line-buffer-identification
+            (list mode-string)))
       (set-buffer-modified-p t))))
 
 (defun gnus-create-xref-hashtb (from-newsgroup headers unreads)
@@ -9250,10 +9375,10 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (if (search-forward "\nreferences: " nil t)
-                 (prog1
-                     (gnus-header-value)
-                   (setq end (match-end 0))
-                   (save-excursion
+                 (progn
+                   (setq end (point))
+                   (prog1
+                       (gnus-header-value)
                      (setq ref
                            (buffer-substring
                             (progn
@@ -9508,10 +9633,10 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
 the list of process marked articles, and the current article will be
 taken into consideration."
   (cond
-   ((and n (numberp n))
+   (n
     ;; A numerical prefix has been given.
     (let ((backward (< n 0))
-         (n (abs n))
+         (n (abs (prefix-numeric-value n)))
          articles article)
       (save-excursion
        (while
@@ -9837,6 +9962,8 @@ With arg, turn line truncation on iff arg is positive."
 The prefix argument ALL means to select all articles."
   (interactive "P")
   (gnus-set-global-variables)
+  (when (gnus-ephemeral-group-p gnus-newsgroup-name)
+    (error "Ephemeral groups can't be reselected"))
   (let ((current-subject (gnus-summary-article-number))
        (group gnus-newsgroup-name))
     (setq gnus-newsgroup-begin nil)
@@ -9849,7 +9976,7 @@ The prefix argument ALL means to select all articles."
       (save-excursion
        (gnus-group-get-new-news-this-group 1)))
     (gnus-group-read-group all t)
-    (gnus-summary-goto-subject current-subject)))
+    (gnus-summary-goto-subject current-subject nil t)))
 
 (defun gnus-summary-rescan-group (&optional all)
   "Exit the newsgroup, ask for new articles, and select the newsgroup."
@@ -10351,8 +10478,7 @@ If BACKWARD, the previous article is selected instead of the next."
    ;; If not, we try the first unread, if that is wanted.
    ((and subject
         gnus-auto-select-same
-        (or (gnus-summary-first-unread-article)
-            (eq (gnus-summary-article-mark) gnus-canceled-mark)))
+        (gnus-summary-first-unread-article))
     (gnus-summary-position-point)
     (gnus-message 6 "Wrapped"))
    ;; Try to get next/previous article not displayed in this group.
@@ -10375,7 +10501,8 @@ If BACKWARD, the previous article is selected instead of the next."
       (select-window (get-buffer-window (current-buffer)))
       ;; Select next unread newsgroup automagically.
       (cond
-       ((not gnus-auto-select-next)
+       ((or (not gnus-auto-select-next)
+           (not cmd))
        (gnus-message 7 "No more%s articles" (if unread " unread" "")))
        ((or (eq gnus-auto-select-next 'quietly)
            (and (eq gnus-auto-select-next 'slightly-quietly)
@@ -10485,9 +10612,8 @@ article."
              (not (equal (car gnus-article-current) gnus-newsgroup-name)))
          ;; Selected subject is different from current article's.
          (gnus-summary-display-article article)
-       (gnus-eval-in-buffer-window
-        gnus-article-buffer
-        (setq endp (gnus-article-next-page lines)))
+       (gnus-eval-in-buffer-window gnus-article-buffer
+         (setq endp (gnus-article-next-page lines)))
        (if endp
            (cond (circular
                   (gnus-summary-beginning-of-article))
@@ -10516,7 +10642,7 @@ Argument LINES specifies lines to be scrolled down."
        (gnus-summary-display-article article)
       (gnus-summary-recenter)
       (gnus-eval-in-buffer-window gnus-article-buffer
-                                 (gnus-article-prev-page lines))))
+       (gnus-article-prev-page lines))))
   (gnus-summary-position-point))
 
 (defun gnus-summary-scroll-up (lines)
@@ -10527,13 +10653,12 @@ Argument LINES specifies lines to be scrolled up (or down if negative)."
   (gnus-configure-windows 'article)
   (gnus-summary-show-thread)
   (when (eq (gnus-summary-select-article nil nil 'pseudo) 'old)
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (cond ((> lines 0)
-           (if (gnus-article-next-page lines)
-               (gnus-message 3 "End of message")))
-          ((< lines 0)
-           (gnus-article-prev-page (- lines))))))
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (cond ((> lines 0)
+            (if (gnus-article-next-page lines)
+                (gnus-message 3 "End of message")))
+           ((< lines 0)
+            (gnus-article-prev-page (- lines))))))
   (gnus-summary-recenter)
   (gnus-summary-position-point))
 
@@ -10824,6 +10949,7 @@ If ALL, mark even excluded ticked and dormants as read."
   (setq gnus-newsgroup-limit articles)
   (let ((total (length gnus-newsgroup-data))
        (data (gnus-data-find-list (gnus-summary-article-number)))
+       (gnus-summary-mark-below nil)   ; Inhibit this.
        found)
     ;; This will do all the work of generating the new summary buffer
     ;; according to the new limit.
@@ -11068,10 +11194,17 @@ Return how many articles were fetched."
       (setq message-id (concat "<" message-id)))
     (unless (string-match ">$" message-id)
       (setq message-id (concat message-id ">")))
-    (let ((header (gnus-id-to-header message-id)))
+    (let* ((header (gnus-id-to-header message-id))
+          (sparse (and header
+                       (memq (mail-header-number header)
+                             gnus-newsgroup-sparse))))
       (if header
-         ;; The article is present in the buffer, to we just go to it.
-         (gnus-summary-goto-article (mail-header-number header) nil header)
+         (prog1
+             ;; The article is present in the buffer, to we just go to it.
+             (gnus-summary-goto-article 
+              (mail-header-number header) nil header)
+           (when sparse
+             (gnus-summary-update-article (mail-header-number header))))
        ;; We fetch the article
        (let ((gnus-override-method 
               (and (gnus-news-group-p gnus-newsgroup-name)
@@ -11130,10 +11263,9 @@ If REGEXP-P (the prefix) is non-nil, do regexp isearch."
   (gnus-set-global-variables)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
-  (gnus-eval-in-buffer-window
-   gnus-article-buffer
-   (goto-char (point-min))
-   (isearch-forward regexp-p)))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    ;;(goto-char (point-min))
+    (isearch-forward regexp-p)))
 
 (defun gnus-summary-search-article-forward (regexp &optional backward)
   "Search for an article containing REGEXP forward.
@@ -11178,6 +11310,8 @@ Optional argument BACKWARD means do search for backward.
     (gnus-save-hidden-threads
       (gnus-summary-select-article)
       (set-buffer gnus-article-buffer)
+      (when backward
+       (forward-line -1))
       (while (not found)
        (gnus-message 7 "Searching article: %d..." (cdr gnus-article-current))
        (if (if backward
@@ -11273,11 +11407,10 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
   (gnus-set-global-variables)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
-  (gnus-eval-in-buffer-window
-   gnus-article-buffer
-   (widen)
-   (goto-char (point-min))
-   (and gnus-break-pages (gnus-narrow-to-page))))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (widen)
+    (goto-char (point-min))
+    (and gnus-break-pages (gnus-narrow-to-page))))
 
 (defun gnus-summary-end-of-article ()
   "Scroll to the end of the article."
@@ -11285,12 +11418,11 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
   (gnus-set-global-variables)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
-  (gnus-eval-in-buffer-window
-   gnus-article-buffer
-   (widen)
-   (goto-char (point-max))
-   (recenter -3)
-   (and gnus-break-pages (gnus-narrow-to-page))))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (widen)
+    (goto-char (point-max))
+    (recenter -3)
+    (and gnus-break-pages (gnus-narrow-to-page))))
 
 (defun gnus-summary-show-article (&optional arg)
   "Force re-fetching of the current article.
@@ -11378,21 +11510,21 @@ forward."
   (gnus-set-global-variables)
   (gnus-summary-select-article)
   (let ((mail-header-separator ""))
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (save-restriction
-       (widen)
-       (let ((start (window-start))
-            buffer-read-only)
-        (message-caesar-buffer-body arg)
-        (set-window-start (get-buffer-window (current-buffer)) start))))))
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (save-restriction
+       (widen)
+       (let ((start (window-start))
+             buffer-read-only)
+         (message-caesar-buffer-body arg)
+         (set-window-start (get-buffer-window (current-buffer)) start))))))
 
 (defun gnus-summary-stop-page-breaking ()
   "Stop page breaking in the current article."
   (interactive)
   (gnus-set-global-variables)
   (gnus-summary-select-article)
-  (gnus-eval-in-buffer-window gnus-article-buffer (widen)))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (widen)))
 
 (defun gnus-summary-move-article (&optional n to-newsgroup select-method action)
   "Move the current article to a different newsgroup.
@@ -11439,7 +11571,7 @@ and `request-accept' functions."
             articles prefix))
       (set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
     (setq to-method (or select-method 
-                       (gnus-find-method-for-group to-newsgroup)))
+                       (gnus-group-name-to-method to-newsgroup)))
     ;; Check the method we are to move this article to...
     (or (gnus-check-backend-function 'request-accept-article (car to-method))
        (error "%s does not support article copying" (car to-method)))
@@ -11610,7 +11742,7 @@ latter case, they will be copied into the relevant groups."
                                        gnus-newsgroup-name)))))
                (method
                 (gnus-completing-read 
-                 methname "What backend do you want to use when"
+                 methname "What backend do you want to use when respooling?"
                  methods nil t nil 'gnus-method-history))
                ms)
           (cond
@@ -11659,7 +11791,7 @@ latter case, they will be copied into the relevant groups."
                          (current-time-string (nth 5 atts))
                          (current-time-zone now)
                          (current-time-zone now)) "\n"
-               "Message-ID: " (gnus-inews-message-id) "\n"
+               "Message-ID: " (message-make-message-id) "\n"
                "Lines: " (int-to-string lines) "\n"
                "Chars: " (int-to-string (nth 7 atts)) "\n\n"))
       (gnus-request-accept-article group nil t)
@@ -11786,9 +11918,11 @@ groups."
   (interactive)
   (if (gnus-group-read-only-p)
       (progn
-       (gnus-summary-edit-article-postpone)
-       (gnus-error
-        1 "The current newsgroup does not support article editing."))
+       (let ((beep (not (eq major-mode 'text-mode))))
+         (gnus-summary-edit-article-postpone)
+         (when beep
+           (gnus-error
+            3 "The current newsgroup does not support article editing."))))
     (let ((buf (format "%s" (buffer-string))))
       (erase-buffer)
       (insert buf)
@@ -11803,8 +11937,8 @@ groups."
        (gnus-configure-windows 'summary)
        (gnus-summary-update-article (cdr gnus-article-current))
        (when gnus-use-cache
-         (gnus-cache-update-article 
-          (cdr gnus-article-current) (car gnus-article-current)))
+         (gnus-cache-update-article    
+          (car gnus-article-current) (cdr gnus-article-current)))
        (when gnus-keep-backlog
          (gnus-backlog-remove-article 
           (car gnus-article-current) (cdr gnus-article-current))))
@@ -12044,9 +12178,7 @@ the actual number of articles marked is returned."
 
 (defun gnus-summary-mark-forward (n &optional mark no-expire)
   "Mark N articles as read forwards.
-If N is negative, mark backwards instead.
-Mark with MARK.         If MARK is ? , ?! or ??, articles will be
-marked as unread.
+If N is negative, mark backwards instead.  Mark with MARK, ?r by default.
 The difference between N and the actual number of articles marked is
 returned."
   (interactive "p")
@@ -12100,32 +12232,34 @@ returned."
 (defun gnus-summary-mark-article-as-unread (mark)
   "Mark the current article quickly as unread with MARK."
   (let ((article (gnus-summary-article-number)))
-    (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
-    (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
-    (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
-    (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
-    (cond ((= mark gnus-ticked-mark)
-          (push article gnus-newsgroup-marked))
-         ((= mark gnus-dormant-mark)
-          (push article gnus-newsgroup-dormant))
-         (t
-          (push article gnus-newsgroup-unreads)))
-    (setq gnus-newsgroup-reads
-         (delq (assq article gnus-newsgroup-reads)
-               gnus-newsgroup-reads))
-
-    ;; See whether the article is to be put in the cache.
-    (and gnus-use-cache
-        (vectorp (gnus-summary-article-header article))
-        (save-excursion
-          (gnus-cache-possibly-enter-article
-           gnus-newsgroup-name article
-           (gnus-summary-article-header article)
-           (= mark gnus-ticked-mark)
-           (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
-
-    ;; Fix the mark.
-    (gnus-summary-update-mark mark 'unread)
+    (if (< article 0)
+       (gnus-error 1 "Unmarkable article")
+      (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+      (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
+      (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
+      (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
+      (cond ((= mark gnus-ticked-mark)
+            (push article gnus-newsgroup-marked))
+           ((= mark gnus-dormant-mark)
+            (push article gnus-newsgroup-dormant))
+           (t
+            (push article gnus-newsgroup-unreads)))
+      (setq gnus-newsgroup-reads
+           (delq (assq article gnus-newsgroup-reads)
+                 gnus-newsgroup-reads))
+
+      ;; See whether the article is to be put in the cache.
+      (and gnus-use-cache
+          (vectorp (gnus-summary-article-header article))
+          (save-excursion
+            (gnus-cache-possibly-enter-article
+             gnus-newsgroup-name article
+             (gnus-summary-article-header article)
+             (= mark gnus-ticked-mark)
+             (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
+
+      ;; Fix the mark.
+      (gnus-summary-update-mark mark 'unread))
     t))
 
 (defun gnus-summary-mark-article (&optional article mark no-expire)
@@ -12388,7 +12522,7 @@ even ticked and dormant ones."
 
 ;; Suggested by Daniel Quinlan <quinlan@best.com>.
 (defalias 'gnus-summary-show-all-expunged 'gnus-summary-limit-include-expunged)
-(defun gnus-summary-limit-include-expunged ()
+(defun gnus-summary-limit-include-expunged (&optional no-error)
   "Display all the hidden articles that were expunged for low scores."
   (interactive)
   (gnus-set-global-variables)
@@ -12401,11 +12535,14 @@ even ticked and dormant ones."
                 (< (cdar scored) gnus-summary-expunge-below)
                 (setq headers (cons h headers))))
        (setq scored (cdr scored)))
-      (or headers (error "No expunged articles hidden."))
-      (goto-char (point-min))
-      (gnus-summary-prepare-unthreaded (nreverse headers)))
-    (goto-char (point-min))
-    (gnus-summary-position-point)))
+      (if (not headers)
+         (when (not no-error)
+           (error "No expunged articles hidden."))
+       (goto-char (point-min))
+       (gnus-summary-prepare-unthreaded (nreverse headers))
+       (goto-char (point-min))
+       (gnus-summary-position-point)
+       t))))
 
 (defun gnus-summary-catchup (&optional all quietly to-here not-mark)
   "Mark all articles not marked as unread in this newsgroup as read.
@@ -12605,6 +12742,7 @@ If ARG is positive number, turn showing conversation threads on."
            (> (prefix-numeric-value arg) 0)))
     (gnus-summary-prepare)
     (gnus-summary-goto-subject current)
+    (gnus-message 6 "Threading is now %s" (if gnus-show-threads "on" "off"))
     (gnus-summary-position-point)))
 
 (defun gnus-summary-show-all-threads ()
@@ -12797,8 +12935,8 @@ If the prefix argument is positive, remove any kinds of marks.
 If the prefix argument is negative, tick articles instead."
   (interactive "P")
   (gnus-set-global-variables)
-  (if unmark
-      (setq unmark (prefix-numeric-value unmark)))
+  (when unmark
+    (setq unmark (prefix-numeric-value unmark)))
   (let ((articles (gnus-summary-articles-in-thread)))
     (save-excursion
       ;; Expand the thread.
@@ -12914,6 +13052,8 @@ The variable `gnus-default-article-saver' specifies the saver function."
   (interactive "P")
   (gnus-set-global-variables)
   (let ((articles (gnus-summary-work-articles n))
+       (save-buffer (save-excursion 
+                      (nnheader-set-temp-buffer " *Gnus Save*")))
        file header article)
     (while articles
       (setq header (gnus-summary-article-header
@@ -12926,33 +13066,37 @@ The variable `gnus-default-article-saver' specifies the saver function."
        ;; This is a real article.
        (save-window-excursion
          (gnus-summary-select-article t nil nil article))
+       (save-excursion
+         (set-buffer save-buffer)
+         (erase-buffer)
+         (insert-buffer-substring gnus-original-article-buffer))
        (unless gnus-save-all-headers
          ;; Remove headers accoring to `gnus-saved-headers'.
          (let ((gnus-visible-headers
-                (or gnus-saved-headers gnus-visible-headers)))
+                (or gnus-saved-headers gnus-visible-headers))
+               (gnus-article-buffer save-buffer))
            (gnus-article-hide-headers 1 t)))
-       ;; Remove any X-Gnus lines.
-       (save-excursion
-         (set-buffer gnus-article-buffer)
-         (save-restriction
-           (let ((buffer-read-only nil))
-             (nnheader-narrow-to-headers)
-             (while (re-search-forward "^X-Gnus" nil t)
-               (gnus-delete-line)))))
        (save-window-excursion
          (if (not gnus-default-article-saver)
              (error "No default saver is defined.")
-           (setq file (funcall
-                       gnus-default-article-saver
-                       (cond
-                        ((not gnus-prompt-before-saving)
-                         'default)
-                        ((eq gnus-prompt-before-saving 'always)
-                         nil)
-                        (t file))))))
+           ;; !!! Magic!  The saving functions all save
+           ;; `gnus-original-article-buffer' (or so they think),
+           ;; but we bind that variable to our save-buffer.
+           (set-buffer gnus-article-buffer)
+           (let ((gnus-original-article-buffer save-buffer))
+             (set-buffer gnus-summary-buffer)
+             (setq file (funcall
+                         gnus-default-article-saver
+                         (cond
+                          ((not gnus-prompt-before-saving)
+                           'default)
+                          ((eq gnus-prompt-before-saving 'always)
+                           nil)
+                          (t file)))))))
        (gnus-summary-remove-process-mark article)
        (unless not-saved
          (gnus-summary-set-saved-mark article))))
+    (gnus-kill-buffer save-buffer)
     (gnus-summary-position-point)
     n))
 
@@ -13091,6 +13235,14 @@ save those articles instead."
          (setq to-newsgroup (or default "")))
       (or (gnus-active to-newsgroup)
          (gnus-activate-group to-newsgroup)
+         (if (gnus-y-or-n-p (format "No such group: %s.  Create it? "
+                                    to-newsgroup))
+             (or (and (gnus-request-create-group 
+                       to-newsgroup (gnus-group-name-to-method to-newsgroup))
+                      (gnus-activate-group to-newsgroup nil nil
+                                           (gnus-group-name-to-method
+                                            to-newsgroup)))
+                 (error "Couldn't create group %s" to-newsgroup)))
          (error "No such group: %s" to-newsgroup)))
     to-newsgroup))
 
@@ -13108,10 +13260,14 @@ save those articles instead."
             default-name))
           ;; A single split name was found
           ((= 1 (length split-name))
-           (read-file-name
-            (concat prompt " (default " (car split-name) ") ")
-            gnus-article-save-directory
-            (concat gnus-article-save-directory (car split-name))))
+           (let* ((name (car split-name))
+                  (dir (cond ((file-directory-p name)
+                              (file-name-as-directory name))
+                             ((file-exists-p name) name)
+                             (t gnus-article-save-directory))))
+             (read-file-name
+              (concat prompt " (default " name ") ")
+              dir name)))
           ;; A list of splits was found.
           (t
            (setq split-name (nreverse split-name))
@@ -13152,12 +13308,11 @@ Directory to save to is default to `gnus-article-save-directory'."
                (t (gnus-read-save-file-name
                    "Save in rmail file:" default-name))))
     (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window
-     gnus-original-article-buffer
-     (save-excursion
-       (save-restriction
-        (widen)
-        (gnus-output-to-rmail filename))))
+    (gnus-eval-in-buffer-window gnus-original-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (gnus-output-to-rmail filename))))
     ;; Remember the directory name to save articles
     (setq gnus-newsgroup-last-rmail filename)))
 
@@ -13181,15 +13336,14 @@ Directory to save to is default to `gnus-article-save-directory'."
                            (and default-name
                                 (file-name-directory default-name))))
     (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window
-     gnus-original-article-buffer
-     (save-excursion
-       (save-restriction
-        (widen)
-        (if (and (file-readable-p filename) (mail-file-babyl-p filename))
-            (gnus-output-to-rmail filename)
-          (let ((mail-use-rfc822 t))
-            (rmail-output filename 1 t t))))))
+    (gnus-eval-in-buffer-window gnus-original-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (if (and (file-readable-p filename) (mail-file-babyl-p filename))
+             (gnus-output-to-rmail filename)
+           (let ((mail-use-rfc822 t))
+             (rmail-output filename 1 t t))))))
     ;; Remember the directory name to save articles.
     (setq gnus-newsgroup-last-mail filename)))
 
@@ -13209,12 +13363,11 @@ Directory to save to is default to `gnus-article-save-directory'."
                (t (gnus-read-save-file-name
                    "Save in file:" default-name))))
     (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window
-     gnus-original-article-buffer
-     (save-excursion
-       (save-restriction
-        (widen)
-        (gnus-output-to-file filename))))
+    (gnus-eval-in-buffer-window gnus-original-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (gnus-output-to-file filename))))
     ;; Remember the directory name to save articles.
     (setq gnus-newsgroup-last-file filename)))
 
@@ -13234,15 +13387,14 @@ The directory to save in defaults to `gnus-article-save-directory'."
                (t (gnus-read-save-file-name
                    "Save body in file:" default-name))))
     (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (save-excursion
-       (save-restriction
-        (widen)
-        (goto-char (point-min))
-        (and (search-forward "\n\n" nil t)
-             (narrow-to-region (point) (point-max)))
-        (gnus-output-to-file filename))))
+    (gnus-eval-in-buffer-window gnus-original-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (goto-char (point-min))
+         (and (search-forward "\n\n" nil t)
+              (narrow-to-region (point) (point-max)))
+         (gnus-output-to-file filename))))
     ;; Remember the directory name to save articles.
     (setq gnus-newsgroup-last-file filename)))
 
@@ -13258,11 +13410,10 @@ The directory to save in defaults to `gnus-article-save-directory'."
                              gnus-last-shell-command))))
   (if (string-equal command "")
       (setq command gnus-last-shell-command))
-  (gnus-eval-in-buffer-window
-   gnus-article-buffer
-   (save-restriction
-     (widen)
-     (shell-command-on-region (point-min) (point-max) command nil)))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (save-restriction
+      (widen)
+      (shell-command-on-region (point-min) (point-max) command nil)))
   (setq gnus-last-shell-command command))
 
 ;; Summary extract commands
@@ -13353,8 +13504,10 @@ The directory to save in defaults to `gnus-article-save-directory'."
       (erase-buffer)
       (insert "$ " command "\n\n")
       (if gnus-view-pseudo-asynchronously
-         (start-process "gnus-execute" nil "sh" "-c" command)
-       (call-process "sh" nil t nil "-c" command)))))
+         (start-process "gnus-execute" nil shell-file-name
+                        shell-command-switch command)
+       (call-process shell-file-name nil t nil
+                     shell-command-switch command)))))
 
 (defun gnus-copy-file (file &optional to)
   "Copy FILE to TO."
@@ -13410,6 +13563,9 @@ The directory to save in defaults to `gnus-article-save-directory'."
     "\r" gnus-article-press-button
     "\t" gnus-article-next-button
     "\M-\t" gnus-article-prev-button
+    "<" beginning-of-buffer
+    ">" end-of-buffer
+    "\C-c\C-i" gnus-info-find-node
     "\C-c\C-b" gnus-bug)
 
   (substitute-key-definition
@@ -13472,6 +13628,7 @@ The following commands are available:
       (set-buffer (get-buffer-create gnus-original-article-buffer))
       (buffer-disable-undo (current-buffer))
       (setq major-mode 'gnus-original-article-mode)
+      (gnus-add-current-to-buffer-list)
       (make-local-variable 'gnus-original-article))
     (if (get-buffer name)
        (save-excursion
@@ -13669,14 +13826,9 @@ The following commands are available:
        ;; We have found the header.
        header
       ;; We have to really fetch the header to this article.
-      (when (setq where
-                 (if (gnus-check-backend-function 'request-head group)
-                     (gnus-request-head id group)
-                   (gnus-request-article id group)))
+      (when (setq where (gnus-request-head id group))
        (save-excursion
          (set-buffer nntp-server-buffer)
-         (and (search-forward "\n\n" nil t)
-              (delete-region (1- (point)) (point-max)))
          (goto-char (point-max))
          (insert ".\n")
          (goto-char (point-min))
@@ -13868,7 +14020,7 @@ Provided for backwards compatibility."
   "Toggle whether to hide unwanted headers and possibly sort them as well.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive "P")
+  (interactive (gnus-hidden-arg))
   (if (gnus-article-check-hidden-text 'headers arg)
       ;; Show boring headers as well.
       (gnus-article-show-hidden-text 'boring-headers)
@@ -13893,6 +14045,7 @@ always hide."
                       ((and gnus-visible-headers
                             (listp gnus-visible-headers))
                        (mapconcat 'identity gnus-visible-headers "\\|"))))
+               (inhibit-point-motion-hooks t)
                want-list beg)
            ;; First we narrow to just the headers.
            (widen)
@@ -13901,7 +14054,9 @@ always hide."
            (while (looking-at "From ")
              (forward-line 1))
            (unless (bobp)
-             (gnus-hide-text (point-min) (point) props))
+             (if delete
+                 (delete-region (point-min) (point))
+               (gnus-hide-text (point-min) (point) props)))
            ;; Then treat the rest of the header lines.
            (narrow-to-region
             (point)
@@ -13938,7 +14093,7 @@ always hide."
   "Toggle hiding of headers that aren't very interesting.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive "P")
+  (interactive (gnus-hidden-arg))
   (unless (gnus-article-check-hidden-text 'boring-headers arg)
     (save-excursion
       (set-buffer gnus-article-buffer)
@@ -14108,7 +14263,8 @@ always hide."
              (let ((process-connection-type nil))
                (process-kill-without-query
                 (start-process
-                 "gnus-x-face" nil "sh" "-c" gnus-article-x-face-command))
+                 "gnus-x-face" nil shell-file-name shell-command-switch
+                 gnus-article-x-face-command))
                (process-send-region "gnus-x-face" beg end)
                (process-send-eof "gnus-x-face")))))))))
 
@@ -14124,6 +14280,7 @@ always hide."
        (goto-char (point-min))
        (or (search-forward "\n\n" nil t) (point-max)))
 
+      (goto-char (point-min))
       (while (re-search-forward 
              "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
        (setq string (match-string 1))
@@ -14177,7 +14334,7 @@ or not."
   "Toggle hiding of any PGP headers and signatures in the current article.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive "P")
+  (interactive (gnus-hidden-arg))
   (unless (gnus-article-check-hidden-text 'pgp arg)
     (save-excursion
       (set-buffer gnus-article-buffer)
@@ -14208,11 +14365,40 @@ always hide."
            (gnus-hide-text (match-beginning 0) (match-end 0) props))
          (widen))))))
 
+(defun gnus-article-hide-pem (&optional arg)
+  "Toggle hiding of any PEM headers and signatures in the current article.
+If given a negative prefix, always show; if given a positive prefix,
+always hide."
+  (interactive (gnus-hidden-arg))
+  (unless (gnus-article-check-hidden-text 'pem arg)
+    (save-excursion
+      (set-buffer gnus-article-buffer)
+      (let ((props (nconc (list 'gnus-type 'pem) gnus-hidden-properties))
+           buffer-read-only end)
+       (widen)
+       (goto-char (point-min))
+       ;; hide the horrendously ugly "header".
+       (and (search-forward "\n-----BEGIN PRIVACY-ENHANCED MESSAGE-----\n"
+                            nil
+                            t)
+            (setq end (1+ (match-beginning 0)))
+            (gnus-hide-text
+             end
+             (if (search-forward "\n\n" nil t)
+                 (match-end 0)
+               (point-max))
+             props))
+       ;; hide the trailer as well
+       (and (search-forward "\n-----END PRIVACY-ENHANCED MESSAGE-----\n"
+                            nil
+                            t)
+            (gnus-hide-text (match-beginning 0) (match-end 0) props))))))
+
 (defun gnus-article-hide-signature (&optional arg)
   "Hide the signature in the current article.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive "P")
+  (interactive (gnus-hidden-arg))
   (unless (gnus-article-check-hidden-text 'signature arg)
     (save-excursion
       (set-buffer gnus-article-buffer)
@@ -14240,10 +14426,11 @@ always hide."
   (if (and (boundp 'mime::preview/content-list)
           mime::preview/content-list)
       (let ((pcinfo (car (last mime::preview/content-list))))
-       (narrow-to-region
-        (funcall (intern "mime::preview-content-info/point-min") pcinfo)
-        (point-max))
-       t))
+       (condition-case ()
+           (narrow-to-region
+            (funcall (intern "mime::preview-content-info/point-min") pcinfo)
+            (point-max))
+         (error nil))))
   (goto-char (point-max))
   (when (re-search-backward gnus-signature-separator nil t)
     (forward-line 1)
@@ -14257,17 +14444,29 @@ always hide."
       (narrow-to-region (point) (point-max))
       t)))
 
+(defun gnus-hidden-arg ()
+  "Return the current prefix arg as a number, or 0 if no prefix."
+  (list (if current-prefix-arg
+           (prefix-numeric-value current-prefix-arg)
+         0)))
+
 (defun gnus-article-check-hidden-text (type arg)
-  "Return nil if hiding is necessary."
+  "Return nil if hiding is necessary.
+Arg can be nil or a number.  Nil and positive means hide, negative
+means show, 0 means toggle."
   (save-excursion
     (set-buffer gnus-article-buffer)
     (let ((hide (gnus-article-hidden-text-p type)))
-      (cond ((or (and (null arg) (eq hide 'hidden))
-                (and arg (< 0 (prefix-numeric-value arg))))
-            (gnus-article-show-hidden-text type))
-           ((eq hide 'shown)
-            (gnus-article-show-hidden-text type t))
-           (t nil)))))
+      (cond
+       ((or (null arg)
+           (> arg 0))
+       nil)
+       ((< arg 0)
+       (gnus-article-show-hidden-text type))
+       (t
+       (if (eq hide 'hidden)
+           (gnus-article-show-hidden-text type)
+         nil))))))
 
 (defun gnus-article-hidden-text-p (type)
   "Say whether the current buffer contains hidden text of type TYPE."
@@ -14507,20 +14706,14 @@ function and want to see what the date was before converting."
 
 (defun gnus-output-to-file (file-name)
   "Append the current article to a file named FILE-NAME."
-  (setq file-name (expand-file-name file-name))
-  (let ((artbuf (current-buffer))
-       (tmpbuf (get-buffer-create " *Gnus-output*")))
-    (save-excursion
-      (set-buffer tmpbuf)
-      (buffer-disable-undo (current-buffer))
-      (erase-buffer)
+  (let ((artbuf (current-buffer)))
+    (nnheader-temp-write nil
       (insert-buffer-substring artbuf)
       ;; Append newline at end of the buffer as separator, and then
       ;; save it to file.
       (goto-char (point-max))
       (insert "\n")
-      (append-to-file (point-min) (point-max) file-name))
-    (kill-buffer tmpbuf)))
+      (append-to-file (point-min) (point-max) file-name))))
 
 (defun gnus-convert-article-to-rmail ()
   "Convert article in current buffer to Rmail message format."
@@ -14652,7 +14845,7 @@ Argument LINES specifies lines to be scrolled down."
   "Describe article mode commands briefly."
   (interactive)
   (gnus-message 6
-               (substitute-command-keys "\\<gnus-article-mode-map>\\[gnus-article-next-page]:Next page  \\[gnus-article-prev-page]:Prev page  \\[gnus-article-show-summary]:Show summary  \\[gnus-info-find-node]:Run Info  \\[gnus-article-describe-briefly]:This help")))
+               (substitute-command-keys "\\<gnus-article-mode-map>\\[gnus-article-goto-next-page]:Next page     \\[gnus-article-goto-prev-page]:Prev page  \\[gnus-article-show-summary]:Show summary  \\[gnus-info-find-node]:Run Info  \\[gnus-article-describe-briefly]:This help")))
 
 (defun gnus-article-summary-command ()
   "Execute the last keystroke in the summary buffer."
@@ -14681,7 +14874,9 @@ Argument LINES specifies lines to be scrolled down."
   (let ((nosaves
         '("q" "Q"  "c" "r" "R" "\C-c\C-f" "m"  "a" "f" "F"
           "Zc" "ZC" "ZE" "ZQ" "ZZ" "Zn" "ZR" "ZG" "ZN" "ZP"
-          "=" "^" "\M-^"))
+          "=" "^" "\M-^" "|"))
+       (nosave-but-article
+        '("A\r"))
        keys)
     (save-excursion
       (set-buffer gnus-summary-buffer)
@@ -14689,12 +14884,18 @@ Argument LINES specifies lines to be scrolled down."
       (setq keys (read-key-sequence nil)))
     (message "")
 
-    (if (member keys nosaves)
+    (if (or (member keys nosaves)
+           (member keys nosave-but-article))
        (let (func)
-         (pop-to-buffer gnus-summary-buffer 'norecord)
-         (if (setq func (lookup-key (current-local-map) keys))
-             (call-interactively func)
-           (ding)))
+         (save-window-excursion
+           (pop-to-buffer gnus-summary-buffer 'norecord)
+           (setq func (lookup-key (current-local-map) keys)))
+         (if (not func)
+             (ding)
+           (set-buffer gnus-summary-buffer)
+           (call-interactively func))
+         (when (member keys nosave-but-article)
+           (pop-to-buffer gnus-article-buffer 'norecord)))
       (let ((obuf (current-buffer))
            (owin (current-window-configuration))
            (opoint (point))
@@ -14829,6 +15030,7 @@ If NEWSGROUP is nil, return the global kill file name instead."
        (set-buffer gnus-dribble-buffer)
        (insert string "\n")
        (set-window-point (get-buffer-window (current-buffer)) (point-max))
+       (bury-buffer gnus-dribble-buffer)
        (set-buffer obuf))))
 
 (defun gnus-dribble-read-file ()
@@ -14994,7 +15196,7 @@ If it is down, start it up (again)."
        (unless silent
          (message ""))))))
 
-(defun gnus-get-function (method function)
+(defun gnus-get-function (method function &optional noerror)
   "Return a function symbol based on METHOD and FUNCTION."
   ;; Translate server names into methods.
   (unless method
@@ -15006,7 +15208,8 @@ If it is down, start it up (again)."
     ;; question.
     (unless (fboundp func)
       (require (car method))
-      (unless (fboundp func)
+      (when (and (not (fboundp func))
+                (not noerror))
        ;; This backend doesn't implement this function.
        (error "No such function: %s" func)))
     func))
@@ -15157,9 +15360,19 @@ If BUFFER, insert the article in that group."
 
 (defun gnus-request-head (article group)
   "Request the head of ARTICLE in GROUP."
-  (let ((method (gnus-find-method-for-group group)))
-    (funcall (gnus-get-function method 'request-head)
-            article (gnus-group-real-name group) (nth 1 method))))
+  (let* ((method (gnus-find-method-for-group group))
+        (head (gnus-get-function method 'request-head t)))
+    (if (fboundp head)
+       (funcall head article (gnus-group-real-name group) (nth 1 method))
+      (let ((res (gnus-request-article article group)))
+       (when res
+         (save-excursion
+           (set-buffer nntp-server-buffer)
+           (goto-char (point-min))
+           (when (search-forward "\n\n" nil t)
+             (delete-region (1- (point)) (point-max)))
+           (nnheader-fold-continuation-lines)))
+       res))))
 
 (defun gnus-request-body (article group)
   "Request the body of ARTICLE in GROUP."
@@ -15208,7 +15421,7 @@ If GROUP is nil, all groups on METHOD are scanned."
     (setq method (gnus-server-to-method method)))
   (when (and (not method)
             (stringp group))
-    (setq method (gnus-find-method-for-group group)))
+    (setq method (gnus-group-name-to-method group)))
   (goto-char (point-max))
   (unless (bolp)
     (insert "\n"))
@@ -15277,6 +15490,20 @@ If GROUP is nil, all groups on METHOD are scanned."
     (setcar (cdr entry) (concat (nth 1 entry) "+" group))
     (nconc entry (cdr 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."
+  (if (string-match ":" group)
+      (let ((server (substring group 0 (match-beginning 0))))
+       (if (string-match "\\+" server)
+           (list (intern (substring server 0 (match-beginning 0)))
+                 (substring server (match-end 0)))
+         (list (intern server) "")))
+    gnus-select-method))
+
 (defun gnus-find-method-for-group (group &optional info)
   "Find the select method that GROUP uses."
   (or gnus-override-method
@@ -15337,7 +15564,7 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
       (gnus-read-newsrc-file rawfile))
 
     (when (and (not (assoc "archive" gnus-server-alist))
-              gnus-message-archive-method)
+              (gnus-archive-server-wanted-p))
       (push (cons "archive" gnus-message-archive-method)
            gnus-server-alist))
 
@@ -15487,7 +15714,7 @@ the server for new groups."
   (let* ((date (or gnus-newsrc-last-checked-date (current-time-string)))
         (methods (cons gnus-select-method
                        (nconc
-                        (when gnus-message-archive-method
+                        (when (gnus-archive-server-wanted-p)
                           (list "archive"))
                         (append
                          (and (consp gnus-check-new-newsgroups)
@@ -15750,7 +15977,7 @@ newsgroup."
          (gnus-group-change-level entry gnus-level-killed)
          (setq gnus-killed-list (delete group gnus-killed-list))))
       ;; Then we remove all bogus groups from the list of killed and
-      ;; zombie groups.  They are are removed without confirmation.
+      ;; zombie groups.  They are removed without confirmation.
       (let ((dead-lists '(gnus-killed-list gnus-zombie-list))
            killed)
        (while dead-lists
@@ -15762,6 +15989,7 @@ newsgroup."
              (set (car dead-lists)
                   (delete group (symbol-value (car dead-lists))))))
          (setq dead-lists (cdr dead-lists))))
+      (run-hooks 'gnus-check-bogus-groups-hook)
       (gnus-message 5 "Checking bogus newsgroups...done"))))
 
 (defun gnus-check-duplicate-killed-groups ()
@@ -15776,6 +16004,7 @@ newsgroup."
 ;; We want to inline a function from gnus-cache, so we cheat here:
 (eval-when-compile
   (provide 'gnus)
+  (setq gnus-directory (or (getenv "SAVEDIR") "~/News/"))
   (require 'gnus-cache))
 
 (defun gnus-get-unread-articles-in-group (info active &optional update)
@@ -15949,10 +16178,10 @@ newsgroup."
       (while list
        (gnus-sethash (car list) (pop list) gnus-killed-hashtb)))))
 
-(defun gnus-activate-group (group &optional scan dont-check)
+(defun gnus-activate-group (group &optional scan dont-check method)
   ;; Check whether a group has been activated or not.
   ;; If SCAN, request a scan of that group as well.
-  (let ((method (gnus-find-method-for-group group))
+  (let ((method (or method (gnus-find-method-for-group group)))
        active)
     (and (gnus-check-server method)
         ;; We escape all bugs and quit here to make it possible to
@@ -15964,7 +16193,7 @@ newsgroup."
                (gnus-request-scan group method))
           t)
         (condition-case ()
-            (gnus-request-group group dont-check)
+            (gnus-request-group group dont-check method)
        ;   (error nil)
           (quit nil))
         (save-excursion
@@ -16050,7 +16279,7 @@ Returns whether the updating was successful."
       (setq lists (cdr lists)))))
 
 (defun gnus-get-killed-groups ()
-  "Go through the active hashtb and all all unknown groups as killed."
+  "Go through the active hashtb and mark all unknown groups as killed."
   ;; First make sure active file has been read.
   (unless (gnus-read-active-file-p)
     (let ((gnus-read-active-file t))
@@ -16086,7 +16315,7 @@ Returns whether the updating was successful."
            ;; secondary ones.
            gnus-secondary-select-methods)
          ;; Also read from the archive server.
-         (when gnus-message-archive-method
+         (when (gnus-archive-server-wanted-p)
            (list "archive"))))
        list-type)
     (setq gnus-have-read-active-file nil)
@@ -16898,7 +17127,7 @@ If FORCE is non-nil, the .newsrc file is read."
 (defun gnus-read-all-descriptions-files ()
   (let ((methods (cons gnus-select-method 
                       (nconc
-                       (when gnus-message-archive-method
+                       (when (gnus-archive-server-wanted-p)
                          (list "archive"))
                        gnus-secondary-select-methods))))
     (while methods
@@ -16907,7 +17136,8 @@ If FORCE is non-nil, the .newsrc file is read."
     t))
 
 (defun gnus-read-descriptions-file (&optional method)
-  (let ((method (or method gnus-select-method)))
+  (let ((method (or method gnus-select-method))
+       group)
     (when (stringp method)
       (setq method (gnus-server-to-method method)))
     ;; We create the hashtable whether we manage to read the desc file
@@ -16928,35 +17158,43 @@ If FORCE is non-nil, the .newsrc file is read."
       (gnus-message 1 "Couldn't read newsgroups descriptions")
       nil)
      (t
-      (let (group)
-       (save-excursion
-         (save-restriction
-           (set-buffer nntp-server-buffer)
-           (goto-char (point-min))
-           (if (or (search-forward "\n.\n" nil t)
+      (save-excursion
+       (save-restriction
+         (set-buffer nntp-server-buffer)
+         (goto-char (point-min))
+         (when (or (search-forward "\n.\n" nil t)
                    (goto-char (point-max)))
-               (progn
-                 (beginning-of-line)
-                 (narrow-to-region (point-min) (point))))
-           (goto-char (point-min))
-           (while (not (eobp))
-             ;; If we get an error, we set group to 0, which is not a
-             ;; symbol...
-             (setq group
-                   (condition-case ()
-                       (let ((obarray gnus-description-hashtb))
-                         ;; Group is set to a symbol interned in this
-                         ;; hash table.
-                         (read nntp-server-buffer))
-                     (error 0)))
-             (skip-chars-forward " \t")
-             ;; ...  which leads to this line being effectively ignored.
-             (and (symbolp group)
-                  (set group (buffer-substring
-                              (point) (progn (end-of-line) (point)))))
-             (forward-line 1))))
-       (gnus-message 5 "Reading descriptions file...done")
-       t)))))
+           (beginning-of-line)
+           (narrow-to-region (point-min) (point)))
+         ;; If these are groups from a foreign select method, we insert the
+         ;; group prefix in front of the group names.
+         (and method (not (gnus-server-equal
+                           (gnus-server-get-method nil method)
+                           (gnus-server-get-method nil gnus-select-method)))
+              (let ((prefix (gnus-group-prefixed-name "" method)))
+                (goto-char (point-min))
+                (while (and (not (eobp))
+                            (progn (insert prefix)
+                                   (zerop (forward-line 1)))))))
+         (goto-char (point-min))
+         (while (not (eobp))
+           ;; If we get an error, we set group to 0, which is not a
+           ;; symbol...
+           (setq group
+                 (condition-case ()
+                     (let ((obarray gnus-description-hashtb))
+                       ;; Group is set to a symbol interned in this
+                       ;; hash table.
+                       (read nntp-server-buffer))
+                   (error 0)))
+           (skip-chars-forward " \t")
+           ;; ...  which leads to this line being effectively ignored.
+           (and (symbolp group)
+                (set group (buffer-substring
+                            (point) (progn (end-of-line) (point)))))
+           (forward-line 1))))
+      (gnus-message 5 "Reading descriptions file...done")
+      t))))
 
 (defun gnus-group-get-description (group)
   "Get the description of a group by sending XGTITLE to the server."