*** empty log message ***
[gnus] / lisp / gnus.el
index 8fe5446..31c5e1c 100644 (file)
 (require 'mail-utils)
 (require 'timezone)
 (require 'nnheader)
+(require 'message)
+(require 'nnmail)
+(require 'backquote)
 
 (eval-when-compile (require 'cl))
 
+(defvar gnus-directory (or (getenv "SAVEDIR") "~/News/")
+  "*Directory variable from which all other Gnus file variables are derived.")
+
 ;; Site dependent variables.  These variables should be defined in
 ;; paths.el.
 
@@ -129,12 +135,19 @@ There is a lot more to know about select methods and virtual servers -
 see the manual for details.")
 
 (defvar gnus-message-archive-method 
-  '(nnfolder "archive" (nnfolder-directory "~/Mail/archive/")
-            (nnfolder-active-file "~/Mail/archive/active")
-            (nnfolder-get-new-mail nil)
-            (nnfolder-inhibit-expiry t))
+  `(nnfolder
+    "archive"
+    (nnfolder-directory ,(nnheader-concat message-directory "archive"))
+    (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.
-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-refer-article-method nil
   "*Preferred method for fetching an article by Message-ID.
@@ -176,13 +189,15 @@ 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/news.answers/"
+    "/ftp@rtfm.mit.edu:/pub/usenet/"
     "/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
     "/ftp@ftp.sunet.se:/pub/usenet/"
     "/ftp@nctuccca.edu.tw:/USENET/FAQ/"
-    "/ftp@hwarang.postech.ac.kr:/pub/usenet/news.answers/"
+    "/ftp@hwarang.postech.ac.kr:/pub/usenet/"
     "/ftp@ftp.hk.super.net:/mirror/faqs/")
   "*Directory where the group FAQs are stored.
 This will most commonly be on a remote machine, and the file will be
@@ -200,12 +215,13 @@ If the default site is too slow, try one of these:
 
    North America: mirrors.aol.com               /pub/rtfm/usenet
                  ftp.seas.gwu.edu               /pub/rtfm
-                 rtfm.mit.edu                   /pub/usenet/news.answers
+                 rtfm.mit.edu                   /pub/usenet
    Europe:       ftp.uni-paderborn.de           /pub/FAQ
                   src.doc.ic.ac.uk               /usenet/news-FAQS
                  ftp.sunet.se                   /pub/usenet
+                 sunsite.auc.dk                 /pub/usenet
    Asia:         nctuccca.edu.tw                /USENET/FAQ
-                 hwarang.postech.ac.kr          /pub/usenet/news.answers
+                 hwarang.postech.ac.kr          /pub/usenet
                  ftp.hk.super.net               /mirror/faqs")
 
 (defvar gnus-group-archive-directory
@@ -267,15 +283,17 @@ 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.
 
-(defvar gnus-article-save-directory (or (getenv "SAVEDIR") "~/News/")
-  "*Name of the directory articles will be saved in (default \"~/News\").
-Initialized from the SAVEDIR environment variable.")
+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-kill-files-directory (or (getenv "SAVEDIR") "~/News/")
-  "*Name of the directory where kill files will be stored (default \"~/News\").
-Initialized from the SAVEDIR environment variable.")
+(defvar gnus-article-save-directory gnus-directory
+  "*Name of the directory articles will be saved in (default \"~/News\").")
+
+(defvar gnus-kill-files-directory gnus-directory
+  "*Name of the directory where kill files will be stored (default \"~/News\").")
 
 (defvar gnus-default-article-saver 'gnus-summary-save-in-rmail
   "*A function to save articles in your favorite format.
@@ -348,7 +366,7 @@ It uses the same syntax as the `gnus-split-methods' variable.")
 (defvar gnus-use-adaptive-scoring nil
   "*If non-nil, use some adaptive scoring scheme.")
 
-(defvar gnus-use-cache nil
+(defvar 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
@@ -597,9 +615,6 @@ nil if you set this variable to nil.")
 (defvar gnus-interactive-catchup t
   "*If non-nil, require your confirmation when catching up a group.")
 
-(defvar gnus-interactive-post t
-  "*If non-nil, group name will be asked for when posting.")
-
 (defvar gnus-interactive-exit t
   "*If non-nil, require your confirmation when exiting Gnus.")
 
@@ -909,6 +924,10 @@ beginning of a line.")
               (summary 0.25 point)
               (if gnus-carpal '(summary-carpal 4))
               ("*Shell Command Output*" 1.0)))
+    (bug
+     (vertical 1.0
+              ("*Gnus Help Bug*" 0.5)
+              ("*Gnus Bug*" 1.0 point)))
     (compose-bounce
      (vertical 1.0
               (article 0.5)
@@ -942,6 +961,8 @@ buffer configuration.")
     (browse-carpal . gnus-carpal-browse-buffer)
     (edit-score . gnus-score-edit-buffer)
     (message . gnus-message-buffer)
+    (mail . gnus-message-buffer)
+    (post-news . gnus-message-buffer)
     (faq . gnus-faq-buffer)
     (picons . "*Picons*")
     (tree . gnus-tree-buffer)
@@ -960,7 +981,8 @@ inserts new groups at the beginning of the list of groups;
 `gnus-subscribe-alphabetically' inserts new groups in strict
 alphabetic order; `gnus-subscribe-hierarchically' inserts new groups
 in hierarchical newsgroup order; `gnus-subscribe-interactively' asks
-for your decision; `gnus-subscribe-killed' kills all new groups.")
+for your decision; `gnus-subscribe-killed' kills all new groups;
+`gnus-subscribe-zombies' will make all new groups into zombies.")
 
 ;; Suggested by a bug report by Hallvard B Furuseth.
 ;; <h.b.furuseth@usit.uio.no>.
@@ -1142,7 +1164,7 @@ with some simple extensions.
 %z   Article zcore (character)
 %t   Number of articles under the current thread (number).
 %e   Whether the thread is empty or not (character).
-%l   GroupLens score (number)
+%l   GroupLens score (string).
 %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,
      where X is the letter following %u.  The function will be passed the
@@ -1198,13 +1220,14 @@ 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:
 
 %S   The native news server.
-%M   The native select method.")
+%M   The native select method.
+%:   \":\" if %S isn't \"\".")
 
 (defvar gnus-valid-select-methods
   '(("nntp" post address prompt-address)
@@ -1217,7 +1240,7 @@ 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))
@@ -1247,7 +1270,7 @@ of the modeline intact.")
 ;  "*Face used for mouse highlighting in Gnus.
 ;No mouse highlights will be done if `gnus-visual' is nil.")
 
-(defvar gnus-summary-mark-below nil
+(defvar gnus-summary-mark-below 0
   "*Mark all articles with a score below this variable as read.
 This variable is local to each summary buffer and usually set by the
 score file.")
@@ -1349,6 +1372,9 @@ It calls `gnus-summary-expire-articles' by default.")
 (defvar gnus-group-catchup-group-hook nil
   "*A hook run when catching up a group from the group buffer.")
 
+(defvar gnus-group-update-group-hook nil
+  "*A hook called when updating group lines.")
+
 (defvar gnus-open-server-hook nil
   "*A hook called just before opening connection to the news server.")
 
@@ -1404,12 +1430,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.")
 
@@ -1459,6 +1479,7 @@ is not run if `gnus-visual' is nil.")
 
 (defvar gnus-parse-headers-hook nil
   "*A hook called before parsing the headers.")
+(add-hook 'gnus-parse-headers-hook 'gnus-decode-rfc1522)
 
 (defvar gnus-exit-group-hook nil
   "*A hook called when exiting (not quitting) summary mode.")
@@ -1515,13 +1536,31 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
            (remove-hook 'gnus-summary-prepare-hook
                         'hilit-rehighlight-buffer-quietly)
            (remove-hook 'gnus-summary-prepare-hook 'hilit-install-line-hooks)
-           (setq gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read))
+           (setq gnus-mark-article-hook
+                 '(gnus-summary-mark-read-and-unread-as-read))
            (remove-hook 'gnus-article-prepare-hook
                         'hilit-rehighlight-buffer-quietly)))
 
 \f
 ;; Internal variables
 
+(defvar gnus-tree-buffer "*Tree*"
+  "Buffer where Gnus thread trees are displayed.")
+
+;; Dummy variable.
+(defvar gnus-use-generic-from nil)
+
+(defvar gnus-thread-indent-array nil)
+(defvar gnus-thread-indent-array-level gnus-thread-indent-level)
+
+(defvar gnus-newsrc-file-version nil)
+
+(defvar gnus-method-history nil)
+;; Variable holding the user answers to all method prompts.
+
+(defvar gnus-group-history nil)
+;; Variable holding the user answers to all group prompts.
+
 (defvar gnus-server-alist nil
   "List of available servers.")
 
@@ -1567,6 +1606,8 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
 (defvar gnus-opened-servers nil)
 
 (defvar gnus-current-move-group nil)
+(defvar gnus-current-copy-group nil)
+(defvar gnus-current-crosspost-group nil)
 
 (defvar gnus-newsgroup-dependencies nil)
 (defvar gnus-newsgroup-async nil)
@@ -1664,7 +1705,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)
@@ -1680,7 +1721,8 @@ variable (string, integer, character, etc).")
 (defvar gnus-group-mode-line-format-alist
   `((?S gnus-tmp-news-server ?s)
     (?M gnus-tmp-news-method ?s)
-    (?u gnus-tmp-user-defined ?s)))
+    (?u gnus-tmp-user-defined ?s)
+    (?: gnus-tmp-colon ?s)))
 
 (defvar gnus-have-read-active-file nil)
 
@@ -1688,14 +1730,21 @@ 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 "September Gnus v0.60"
+(defconst gnus-version-number "5.2.24"
   "Version number for this version of Gnus.")
 
+(defconst gnus-version (format "Gnus v%s" gnus-version-number)
+  "Version string for this version of Gnus.")
+
 (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"))
-  "Assoc list of major modes and related Info nodes.")
+  '((gnus-group-mode "(gnus)The Group Buffer")
+    (gnus-summary-mode "(gnus)The Summary 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*")
 (defvar gnus-summary-buffer "*Summary*")
@@ -1894,9 +1943,10 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
     gnus-last-article gnus-article-internal-prepare-hook
     gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
     gnus-newsgroup-scored gnus-newsgroup-kill-headers
-    gnus-newsgroup-async 
+    gnus-newsgroup-async gnus-thread-expunge-below
     gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
-    gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files
+    (gnus-summary-mark-below . global)
+    gnus-newsgroup-active gnus-scores-exclude-files
     gnus-newsgroup-history gnus-newsgroup-ancient
     gnus-newsgroup-sparse
     (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
@@ -1956,16 +2006,14 @@ Thank you for your help in stamping out bugs.
      ("nnvirtual" nnvirtual-catchup-group)
      ("timezone" timezone-make-date-arpa-standard timezone-fix-time
       timezone-make-sortable-date timezone-make-time-string)
-     ("sendmail" mail-position-on-field mail-setup)
      ("rmailout" rmail-output)
-     ("rnewspost" news-mail-other-window news-reply-yank-original
-      news-caesar-buffer-body)
      ("rmail" rmail-insert-rmail-file-header rmail-count-new-messages
       rmail-show-message)
      ("gnus-soup" :interactive t
       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)
      ("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)
@@ -1995,7 +2043,8 @@ Thank you for your help in stamping out bugs.
      ("gnus-srvr" gnus-browse-foreign-server)
      ("gnus-cite" :interactive t
       gnus-article-highlight-citation gnus-article-hide-citation-maybe
-      gnus-article-hide-citation gnus-article-fill-cited-article)
+      gnus-article-hide-citation gnus-article-fill-cited-article
+      gnus-article-hide-citation-in-followups)
      ("gnus-kill" gnus-kill gnus-apply-kill-file-internal
       gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author
       gnus-execute gnus-expunge)
@@ -2013,7 +2062,8 @@ Thank you for your help in stamping out bugs.
       gnus-score-raise-same-subject gnus-score-default
       gnus-score-raise-thread gnus-score-lower-same-subject-and-select
       gnus-score-lower-same-subject gnus-score-lower-thread
-      gnus-possibly-score-headers)
+      gnus-possibly-score-headers gnus-summary-raise-score 
+      gnus-summary-set-score gnus-summary-current-score)
      ("gnus-score"
       (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
       gnus-current-score-file-nondirectory gnus-score-adaptive
@@ -2036,15 +2086,12 @@ 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-msg" :interactive t
       gnus-group-post-news gnus-group-mail gnus-summary-post-news
       gnus-summary-followup gnus-summary-followup-with-original
-      gnus-summary-followup-and-reply
-      gnus-summary-followup-and-reply-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)
@@ -2052,9 +2099,10 @@ Thank you for your help in stamping out bugs.
       gnus-group-display-picons gnus-picons-article-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 gnus-yank-article))))
+      gnus-summary-save-article-vm))))
 
 \f
 
@@ -2071,14 +2119,24 @@ Thank you for your help in stamping out bugs.
 
 (defmacro gnus-eval-in-buffer-window (buffer &rest forms)
   "Pop to BUFFER, evaluate FORMS, and then return to the original window."
-  (let ((tempvar (make-symbol "GnusStartBufferWindow")))
-    `(let ((,tempvar (selected-window)))
+  (let ((tempvar (make-symbol "GnusStartBufferWindow"))
+       (w (make-symbol "w"))
+       (buf (make-symbol "buf")))
+    `(let* ((,tempvar (selected-window))
+           (,buf ,buffer)
+           (,w (get-buffer-window ,buf 'visible)))
        (unwind-protect
           (progn
-            (pop-to-buffer ,buffer)
+            (if ,w
+                (select-window ,w)
+              (pop-to-buffer ,buf))
             ,@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)))
@@ -2170,6 +2228,18 @@ Thank you for your help in stamping out bugs.
   (and gnus-group-buffer
        (get-buffer gnus-group-buffer)))
 
+(defun gnus-delete-first (elt list)
+  "Delete by side effect the first occurrence of ELT as a member of LIST."
+  (if (equal (car list) elt)
+      (cdr list)
+    (let ((total list))
+      (while (and (cdr list)
+                 (not (equal (cadr list) elt)))
+       (setq list (cdr list)))
+      (when (cdr list)
+       (setcdr list (cddr list)))
+      total)))
+
 ;; Delete the current line (and the next N lines.);
 (defmacro gnus-delete-line (&optional n)
   `(delete-region (progn (beginning-of-line) (point))
@@ -2252,6 +2322,16 @@ Thank you for your help in stamping out bugs.
          flist)
       (cons 'progn (cddr fval)))))
 
+;; Find out whether the gnus-visual TYPE is wanted.
+(defun gnus-visual-p (&optional type class)
+  (and gnus-visual                     ; Has to be non-nil, at least.
+       (if (not type)                  ; We don't care about type.
+          gnus-visual
+        (if (listp gnus-visual)        ; It's a list, so we check it.
+            (or (memq type gnus-visual)
+                (memq class gnus-visual))
+          t))))
+
 ;;; Load the compatability functions.
 
 (require 'gnus-cus)
@@ -2315,7 +2395,7 @@ Thank you for your help in stamping out bugs.
 (defun gnus-summary-line-format-spec ()
   (insert gnus-tmp-unread gnus-tmp-replied
          gnus-tmp-score-char gnus-tmp-indentation)
-  (put-text-property
+  (gnus-put-text-property
    (point)
    (progn
      (insert
@@ -2335,7 +2415,7 @@ Thank you for your help in stamping out bugs.
 
 (defun gnus-summary-dummy-line-format-spec ()
   (insert "*  ")
-  (put-text-property
+  (gnus-put-text-property
    (point)
    (progn
      (insert ":                                 :")
@@ -2351,7 +2431,7 @@ Thank you for your help in stamping out bugs.
          gnus-tmp-process-marked
          gnus-group-indentation
          (format "%5s: " gnus-tmp-number-of-unread))
-  (put-text-property
+  (gnus-put-text-property
    (point)
    (progn
      (insert gnus-tmp-group "\n")
@@ -2413,9 +2493,10 @@ Thank you for your help in stamping out bugs.
   "Return the value of the header FIELD of current article."
   (save-excursion
     (save-restriction
-      (let ((case-fold-search t))
+      (let ((case-fold-search t)
+           (inhibit-point-motion-hooks t))
        (nnheader-narrow-to-headers)
-       (mail-fetch-field field)))))
+       (message-fetch-field field)))))
 
 (defun gnus-goto-colon ()
   (beginning-of-line)
@@ -2516,30 +2597,39 @@ Thank you for your help in stamping out bugs.
 (defun gnus-update-summary-mark-positions ()
   "Compute where the summary marks are to go."
   (save-excursion
+    (when (and gnus-summary-buffer
+              (get-buffer gnus-summary-buffer)
+              (buffer-name (get-buffer gnus-summary-buffer)))
+      (set-buffer gnus-summary-buffer))
     (let ((gnus-replied-mark 129)
          (gnus-score-below-mark 130)
          (gnus-score-over-mark 130)
          (thread nil)
          (gnus-visual nil)
+         (spec gnus-summary-line-format-spec)
          pos)
-      (gnus-set-work-buffer)
-      (gnus-summary-insert-line
-       [0 "" "" "" "" "" 0 0 ""]  0 nil 128 t nil "" nil 1)
-      (goto-char (point-min))
-      (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
-                                        (- (point) 2)))))
-      (goto-char (point-min))
-      (push (cons 'replied (and (search-forward "\201" nil t) (- (point) 2)))
-           pos)
-      (goto-char (point-min))
-      (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
-           pos)
+      (save-excursion
+       (gnus-set-work-buffer)
+       (let ((gnus-summary-line-format-spec spec))
+         (gnus-summary-insert-line
+          [0 "" "" "" "" "" 0 0 ""]  0 nil 128 t nil "" nil 1)
+         (goto-char (point-min))
+         (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
+                                            (- (point) 2)))))
+         (goto-char (point-min))
+         (push (cons 'replied (and (search-forward "\201" nil t) 
+                                   (- (point) 2)))
+               pos)
+         (goto-char (point-min))
+         (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
+               pos)))
       (setq gnus-summary-mark-positions pos))))
 
 (defun gnus-update-group-mark-positions ()
   (save-excursion
     (let ((gnus-process-mark 128)
-         (gnus-group-marked '("dummy.group")))
+         (gnus-group-marked '("dummy.group"))
+         (gnus-active-hashtb (make-vector 10 0)))
       (gnus-set-active "dummy.group" '(0 . 0))
       (gnus-set-work-buffer)
       (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
@@ -2555,7 +2645,7 @@ Thank you for your help in stamping out bugs.
 (defvar gnus-mouse-face-4 'highlight)
 
 (defun gnus-mouse-face-function (form type)
-  `(put-text-property
+  `(gnus-put-text-property
     (point) (progn ,@form (point))
     gnus-mouse-face-prop
     ,(if (equal type 0)
@@ -2569,7 +2659,7 @@ Thank you for your help in stamping out bugs.
 (defvar gnus-face-4 'bold)
 
 (defun gnus-face-face-function (form type)
-  `(put-text-property
+  `(gnus-put-text-property
     (point) (progn ,@form (point))
     'face ',(symbol-value (intern (format "gnus-face-%d" type)))))
 
@@ -2740,7 +2830,7 @@ Thank you for your help in stamping out bugs.
 If PROPS, insert the result."
   (let ((form (gnus-parse-format format alist props)))
     (if props
-       (add-text-properties (point) (progn (eval form) (point)) props)
+       (gnus-add-text-properties (point) (progn (eval form) (point)) props)
       (eval form))))
 
 (defun gnus-remove-text-with-property (prop)
@@ -2774,7 +2864,7 @@ Otherwise, it is like ~/News/news/group/num."
                       (gnus-capitalize-newsgroup newsgroup)
                     (gnus-newsgroup-directory-form newsgroup))
                   "/" (int-to-string (mail-header-number headers)))
-          (or gnus-article-save-directory "~/News"))))
+          gnus-article-save-directory)))
     (if (and last-file
             (string-equal (file-name-directory default)
                           (file-name-directory last-file))
@@ -2792,7 +2882,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                       newsgroup
                     (gnus-newsgroup-directory-form newsgroup))
                   "/" (int-to-string (mail-header-number headers)))
-          (or gnus-article-save-directory "~/News"))))
+          gnus-article-save-directory)))
     (if (and last-file
             (string-equal (file-name-directory default)
                           (file-name-directory last-file))
@@ -2809,7 +2899,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        (if (gnus-use-long-file-name 'not-save)
           (gnus-capitalize-newsgroup newsgroup)
         (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
-       (or gnus-article-save-directory "~/News"))))
+       gnus-article-save-directory)))
 
 (defun gnus-plain-save-name (newsgroup headers &optional last-file)
   "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
@@ -2820,7 +2910,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        (if (gnus-use-long-file-name 'not-save)
           newsgroup
         (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
-       (or gnus-article-save-directory "~/News"))))
+       gnus-article-save-directory)))
 
 ;; For subscribing new newsgroup
 
@@ -2843,7 +2933,10 @@ If variable `gnus-use-long-file-name' is non-nil, it is
              (setq prefixes (cons prefix prefixes))
              (message "Descend hierarchy %s? ([y]nsq): "
                       (substring prefix 1 (1- (length prefix))))
-             (setq ans (read-char))
+             (while (not (memq (setq ans (read-char)) '(?y ?\n ?n ?s ?q)))
+               (ding)
+               (message "Descend hierarchy %s? ([y]nsq): "
+                        (substring prefix 1 (1- (length prefix)))))
              (cond ((= ans ?n)
                     (while (and groups
                                 (string-match prefix
@@ -2869,7 +2962,9 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                       (setq groups (cdr groups))))
                    (t nil)))
          (message "Subscribe %s? ([n]yq)" (car groups))
-         (setq ans (read-char))
+         (while (not (memq (setq ans (read-char)) '(?y ?\n ?q ?n)))
+           (ding)
+           (message "Subscribe %s? ([n]yq)" (car groups)))
          (setq group (car groups))
          (cond ((= ans ?y)
                 (gnus-subscribe-alphabetically (car groups))
@@ -3023,49 +3118,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 (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
-                             nil t)
+    (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 " *[[{(][^()\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."
@@ -3085,6 +3181,10 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
   (not (or (string< s1 s2)
           (string= s1 s2))))
 
+(defun gnus-read-active-file-p ()
+  "Say whether the active file has been read from `gnus-select-method'."
+  (memq gnus-select-method gnus-have-read-active-file))
+
 ;;; General various misc type functions.
 
 (defun gnus-clear-system ()
@@ -3128,10 +3228,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)))
@@ -3165,13 +3269,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)
@@ -3445,9 +3551,10 @@ should have point."
             (delete-windows-on (car bufs)))
        (setq bufs (cdr bufs))))))
 
-(defun gnus-version ()
-  "Version numbers of this version of Gnus."
-  (interactive)
+(defun gnus-version (&optional arg)
+  "Version number of this version of Gnus.
+If ARG, insert string at point."
+  (interactive "P")
   (let ((methods gnus-valid-select-methods)
        (mess gnus-version)
        meth)
@@ -3461,7 +3568,9 @@ should have point."
           (stringp (symbol-value meth))
           (setq mess (concat mess "; " (symbol-value meth))))
       (setq methods (cdr methods)))
-    (gnus-message 2 mess)))
+    (if arg
+       (insert (message mess))
+      (message mess))))
 
 (defun gnus-info-find-node ()
   "Find Info documentation of Gnus."
@@ -3565,6 +3674,12 @@ that that variable is buffer-local to the summary buffers."
   (memq 'virtual (assoc (symbol-name (car (gnus-find-method-for-group group)))
                        gnus-valid-select-methods)))
 
+(defun gnus-news-group-p (group &optional article)
+  "Return non-nil if GROUP (and ARTICLE) come from a news server."
+  (or (gnus-member-of-valid 'post group) ; Ordinary news group.
+      (and (gnus-member-of-valid 'post-mail group) ; Combined group.
+          (eq (gnus-request-type group article) 'news))))
+
 (defsubst gnus-simplify-subject-fully (subject)
   "Simplify a subject string according to the user's wishes."
   (cond
@@ -3598,6 +3713,16 @@ simple-first is t, first argument is already simplified."
        (push group groups)))
     (nreverse groups)))
 
+(defun gnus-completing-read (default prompt &rest args)
+  ;; Like `completing-read', except that DEFAULT is the default argument.
+  (let* ((prompt (if default 
+                    (concat prompt " (default " default ") ")
+                  (concat prompt " ")))
+        (answer (apply 'completing-read prompt args)))
+    (if (or (null answer) (zerop (length answer)))
+       default
+      answer)))
+
 ;; Two silly functions to ensure that all `y-or-n-p' questions clear
 ;; the echo area.
 (defun gnus-y-or-n-p (prompt)
@@ -3624,17 +3749,30 @@ simple-first is t, first argument is already simplified."
 ;; it yet. -erik selberg@cs.washington.edu
 (defun gnus-dd-mmm (messy-date)
   "Return a string like DD-MMM from a big messy string"
-  (let ((datevec (timezone-parse-date messy-date)))
-    (format "%2s-%s"
-           (condition-case ()
-               ;; Make sure leading zeroes are stripped.
-               (number-to-string (string-to-number (aref datevec 2)))
-             (error "??"))
-           (capitalize
-            (or (car
-                 (nth (1- (string-to-number (aref datevec 1)))
-                      timezone-months-assoc))
-                "???")))))
+  (let ((datevec (condition-case () (timezone-parse-date messy-date) 
+                  (error nil))))
+    (if (not datevec)
+       "??-???"
+      (format "%2s-%s"
+             (condition-case ()
+                 ;; Make sure leading zeroes are stripped.
+                 (number-to-string (string-to-number (aref datevec 2)))
+               (error "??"))
+             (capitalize
+              (or (car
+                   (nth (1- (string-to-number (aref datevec 1)))
+                        timezone-months-assoc))
+                  "???"))))))
+
+(defun gnus-mode-string-quote (string)
+  "Quote all \"%\" in STRING."
+  (save-excursion
+    (gnus-set-work-buffer)
+    (insert string)
+    (goto-char (point-min))
+    (while (search-forward "%" nil t)
+      (insert "%"))
+    (buffer-string)))
 
 ;; Make a hash table (default and minimum size is 255).
 ;; Optional argument HASHSIZE specifies the table size.
@@ -3662,6 +3800,17 @@ simple-first is t, first argument is already simplified."
     ;; from `message'.
     (apply 'format args)))
 
+(defun gnus-error (level &rest args)
+  "Beep an error if `gnus-verbose' is on LEVEL or less."
+  (when (<= (floor level) gnus-verbose)
+    (apply 'message args)
+    (ding)
+    (let (duration)
+      (when (and (floatp level)
+                (not (zerop (setq duration (* 10 (- level (floor level)))))))
+       (sit-for duration))))
+  nil)
+
 ;; Generate a unique new group name.
 (defun gnus-generate-new-group-name (leaf)
   (let ((name leaf)
@@ -3671,37 +3820,40 @@ simple-first is t, first argument is already simplified."
     name))
 
 (defsubst gnus-hide-text (b e props)
-  "Set text PROPS on the B to E region, extending `intangble' 1 past B."
-  (add-text-properties b e props)
+  "Set text PROPS on the B to E region, extending `intangible' 1 past B."
+  (gnus-add-text-properties b e props)
   (when (memq 'intangible props)
-    (put-text-property (max (1- b) (point-min))
+    (gnus-put-text-property (max (1- b) (point-min))
                       b 'intangible (cddr (memq 'intangible props)))))
 
 (defsubst gnus-unhide-text (b e)
   "Remove hidden text properties from region between B and E."
   (remove-text-properties b e gnus-hidden-properties)
   (when (memq 'intangible gnus-hidden-properties)
-    (put-text-property (max (1- b) (point-min))
-                      b 'intangible nil)))
+    (gnus-put-text-property (max (1- b) (point-min))
+                           b 'intangible nil)))
 
 (defun gnus-hide-text-type (b e type)
   "Hide text of TYPE between B and E."
   (gnus-hide-text b e (cons 'gnus-type (cons type gnus-hidden-properties))))
 
-;; Find out whether the gnus-visual TYPE is wanted.
-(defun gnus-visual-p (&optional type class)
-  (and gnus-visual                     ; Has to be non-nil, at least.
-       (if (not type)                  ; We don't care about type.
-          gnus-visual
-        (if (listp gnus-visual)        ; It's a list, so we check it.
-            (or (memq type gnus-visual)
-                (memq class gnus-visual))
-          t))))
+(defun gnus-parent-headers (headers &optional generation)
+  "Return the headers of the GENERATIONeth parent of HEADERS."
+  (unless generation 
+    (setq generation 1))
+  (let (references parent)
+    (while (and headers (not (zerop generation)))
+      (setq references (mail-header-references headers))
+      (when (and references
+                (setq parent (gnus-parent-id references))
+                (setq headers (car (gnus-id-to-thread parent))))
+       (decf generation)))
+    headers))
 
 (defun gnus-parent-id (references)
   "Return the last Message-ID in REFERENCES."
   (when (and references
-            (string-match "\\(<[^<>]+>\\)[ \t\n]*\\'" references))
+            (string-match "\\(<[^\n<>]+>\\)[ \t\n]*\\'" references))
     (substring references (match-beginning 1) (match-end 1))))
 
 (defun gnus-split-references (references)
@@ -4153,8 +4305,13 @@ The following commands are available:
   (buffer-disable-undo (current-buffer))
   (setq truncate-lines t)
   (setq buffer-read-only t)
+  (gnus-make-local-hook 'post-command-hook)
+  (gnus-add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
   (run-hooks 'gnus-group-mode-hook))
 
+(defun gnus-clear-inboxes-moved ()
+  (setq nnmail-moved-inboxes nil))
+
 (defun gnus-mouse-pick-group (e)
   "Enter the group under the mouse pointer."
   (interactive "e")
@@ -4167,9 +4324,12 @@ The following commands are available:
 (defun gnus-group-default-level (&optional level number-or-nil)
   (cond
    (gnus-group-use-permanent-levels
-    (setq gnus-group-default-list-level
-         (or level gnus-group-default-list-level))
-    (or gnus-group-default-list-level gnus-level-subscribed))
+    (or (setq gnus-group-use-permanent-levels
+             (or level (if (numberp gnus-group-use-permanent-levels)
+                           gnus-group-use-permanent-levels
+                         (or gnus-group-default-list-level
+                             gnus-level-subscribed))))
+       gnus-group-default-list-level gnus-level-subscribed))
    (number-or-nil
     level)
    (t
@@ -4190,10 +4350,10 @@ If ARG is non-nil and not a positive number, Gnus will
 prompt the user for the name of an NNTP server to use.
 As opposed to `gnus', this command will not connect to the local server."
   (interactive "P")
-  (let ((gnus-group-use-permanent-levels t))
-    (gnus (or arg (1- gnus-level-default-subscribed)) t slave))
-  (make-local-variable 'gnus-group-use-permanent-levels)
-  (setq gnus-group-use-permanent-levels t))
+  (let ((val (or arg (1- gnus-level-default-subscribed))))
+    (gnus val t slave)
+    (make-local-variable 'gnus-group-use-permanent-levels)
+    (setq gnus-group-use-permanent-levels val)))
 
 ;;;###autoload
 (defun gnus-slave (&optional arg)
@@ -4255,7 +4415,8 @@ prompt the user for the name of an NNTP server to use."
                (gnus-make-newsrc-file gnus-startup-file))
 
          ;; Read the dribble file.
-         (and (or gnus-slave gnus-use-dribble-file) (gnus-dribble-read-file))
+         (when (or gnus-slave gnus-use-dribble-file)
+           (gnus-dribble-read-file))
 
          ;; Allow using GroupLens predictions.
          (when gnus-use-grouplens
@@ -4355,7 +4516,7 @@ prompt the user for the name of an NNTP server to use."
   ;; Fontify some.
   (goto-char (point-min))
   (and (search-forward "Praxis" nil t)
-       (put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
+       (gnus-put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
   (goto-char (point-min))
   (let* ((mode-string (gnus-group-set-mode-line)))
     (setq mode-line-buffer-identification
@@ -4495,7 +4656,7 @@ If REGEXP, only list groups matching REGEXP."
        (while groups
          (setq group (pop groups))
          (when (string-match regexp group)
-           (add-text-properties
+           (gnus-add-text-properties
             (point) (prog1 (1+ (point))
                       (insert " " mark "     *: " group "\n"))
             (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
@@ -4503,7 +4664,7 @@ If REGEXP, only list groups matching REGEXP."
                   'gnus-level level))))
       ;; This loop is used when listing all groups.
       (while groups
-       (add-text-properties
+       (gnus-add-text-properties
         (point) (prog1 (1+ (point))
                   (insert " " mark "     *: "
                           (setq group (pop groups)) "\n"))
@@ -4531,14 +4692,21 @@ If REGEXP, only list groups matching REGEXP."
   ;; select method, and return a select method.
   (cond ((stringp method)
         (gnus-server-to-method method))
+       ((equal method gnus-select-method)
+        gnus-select-method)
        ((and (stringp (car method)) group)
         (gnus-server-extend-method group method))
+       ((and method (not group)
+             (equal (cadr method) ""))
+        method)
        (t
         (gnus-server-add-address method))))
 
 (defun gnus-server-to-method (server)
   "Map virtual server names to select methods."
   (or 
+   ;; Is this a method, perhaps?
+   (and server (listp server) server)
    ;; Perhaps this is the native server?
    (and (equal server "native") gnus-select-method)
    ;; It should be in the server alist.
@@ -4573,6 +4741,16 @@ If REGEXP, only list groups matching REGEXP."
                  (t m2))))
     (gnus-method-equal m1 m2)))
 
+(defun gnus-servers-using-backend (backend)
+  "Return a list of known servers using BACKEND."
+  (let ((opened gnus-opened-servers)
+       out)
+    (while opened
+      (when (eq backend (caaar opened))
+       (push (caar opened) out))
+      (pop opened))
+    out))
+
 (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)))
@@ -4715,16 +4893,18 @@ increase the score of each group you read."
        (setq method (gnus-info-method info))
        (when (gnus-server-equal method "native")
          (setq method nil))
-       (if method
-           ;; It's a foreign group...
-           (gnus-group-make-group
-            (gnus-group-real-name (gnus-info-group info))
-            (if (stringp method) method
-              (prin1-to-string (car method)))
-            (and (consp method)
-                 (nth 1 (gnus-info-method info))))
-         ;; It's a native group.
-         (gnus-group-make-group (gnus-info-group info)))
+       (save-excursion
+         (set-buffer gnus-group-buffer)
+         (if method
+             ;; It's a foreign group...
+             (gnus-group-make-group
+              (gnus-group-real-name (gnus-info-group info))
+              (if (stringp method) method
+                (prin1-to-string (car method)))
+              (and (consp method)
+                   (nth 1 (gnus-info-method info))))
+           ;; It's a native group.
+           (gnus-group-make-group (gnus-info-group info))))
        (gnus-message 6 "Note: New group created")
        (setq entry
              (gnus-gethash (gnus-group-prefixed-name
@@ -4751,17 +4931,19 @@ increase the score of each group you read."
   "Update the current line in the group buffer."
   (let* ((buffer-read-only nil)
         (group (gnus-group-group-name))
-        (gnus-group-indentation (gnus-group-group-indentation))
-        (entry (and group (gnus-gethash group gnus-newsrc-hashtb))))
-    (and entry
-        (not (gnus-ephemeral-group-p group))
-        (gnus-dribble-enter
-         (concat "(gnus-group-set-info '"
-                 (prin1-to-string (nth 2 entry)) ")")))
-    (gnus-delete-line)
-    (gnus-group-insert-group-line-info group)
-    (forward-line -1)
-    (gnus-group-position-point)))
+        (entry (and group (gnus-gethash group gnus-newsrc-hashtb)))
+        gnus-group-indentation)
+    (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."
@@ -4836,7 +5018,7 @@ increase the score of each group you read."
         (buffer-read-only nil)
         header gnus-tmp-header)        ; passed as parameter to user-funcs.
     (beginning-of-line)
-    (add-text-properties
+    (gnus-add-text-properties
      (point)
      (prog1 (1+ (point))
        ;; Insert the text.
@@ -4881,7 +5063,10 @@ already."
          (goto-char loc)
          (let ((gnus-group-indentation (gnus-group-group-indentation)))
            (gnus-delete-line)
-           (gnus-group-insert-group-line-info group))
+           (gnus-group-insert-group-line-info group)
+           (save-excursion
+             (forward-line -1)
+             (run-hooks 'gnus-group-update-group-hook)))
          (setq loc (1+ loc)))
        (unless (or found visible-only)
          ;; No such line in the buffer, find out where it's supposed to
@@ -4900,28 +5085,48 @@ already."
              (or entry (goto-char (point-max)))))
          ;; Finally insert the line.
          (let ((gnus-group-indentation (gnus-group-group-indentation)))
-           (gnus-group-insert-group-line-info group)))
+           (gnus-group-insert-group-line-info group)
+           (save-excursion
+             (forward-line -1)
+             (run-hooks 'gnus-group-update-group-hook))))
        (gnus-group-set-mode-line)))))
 
 (defun gnus-group-set-mode-line ()
+  "Update the mode line in the group buffer."
   (when (memq 'group gnus-updated-mode-lines)
-    (let* ((gformat (or gnus-group-mode-line-format-spec
-                       (setq gnus-group-mode-line-format-spec
-                             (gnus-parse-format
-                              gnus-group-mode-line-format
-                              gnus-group-mode-line-format-alist))))
-          (gnus-tmp-news-server (cadr gnus-select-method))
-          (gnus-tmp-news-method (car gnus-select-method))
-          (max-len 60)
-          gnus-tmp-header                      ;Dummy binding for user-defined formats
-          ;; Get the resulting string.
-          (mode-string (eval gformat)))
-      ;; 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)))))
+    ;; Yes, we want to keep this mode line updated.
+    (save-excursion
+      (set-buffer gnus-group-buffer)
+      (let* ((gformat (or gnus-group-mode-line-format-spec
+                         (setq gnus-group-mode-line-format-spec
+                               (gnus-parse-format
+                                gnus-group-mode-line-format
+                                gnus-group-mode-line-format-alist))))
+            (gnus-tmp-news-server (cadr gnus-select-method))
+            (gnus-tmp-news-method (car gnus-select-method))
+            (gnus-tmp-colon (if (equal gnus-tmp-news-server "") "" ":"))
+            (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 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 
+                 (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."
@@ -4994,24 +5199,23 @@ If FIRST-TOO, the current line is also eligible as a target."
   (interactive "p")
   (let ((buffer-read-only nil)
        group)
-    (while
-       (and (> n 0)
-            (setq group (gnus-group-group-name))
-            (progn
-              (beginning-of-line)
-              (forward-char
-               (or (cdr (assq 'process gnus-group-mark-positions)) 2))
-              (delete-char 1)
-              (if unmark
-                  (progn
-                    (insert " ")
-                    (setq gnus-group-marked (delete group gnus-group-marked)))
-                (insert "#")
-                (setq gnus-group-marked
-                      (cons group (delete group gnus-group-marked))))
-              t)
-            (or no-advance (zerop (gnus-group-next-group 1))))
-      (setq n (1- n)))
+    (while (and (> n 0)
+               (not (eobp)))
+      (when (setq group (gnus-group-group-name))
+       ;; Update the mark.
+       (beginning-of-line)
+       (forward-char
+        (or (cdr (assq 'process gnus-group-mark-positions)) 2))
+       (delete-char 1)
+       (if unmark
+           (progn
+             (insert " ")
+             (setq gnus-group-marked (delete group gnus-group-marked)))
+         (insert "#")
+         (setq gnus-group-marked
+               (cons group (delete group gnus-group-marked)))))
+      (or no-advance (gnus-group-next-group 1))
+      (decf n))
     (gnus-summary-position-point)
     n))
 
@@ -5084,9 +5288,7 @@ Return nil if the group isn't displayed."
                             (substitute-command-keys
                              "\\<gnus-group-mode-map>\\[gnus-group-universal-argument]")))))
            'undefined)
-       (progn
-         (message "Undefined key")
-         (ding))
+       (gnus-error 1 "Undefined key")
       (while groups
        (gnus-group-remove-mark (setq group (pop groups)))
        (command-execute func))))
@@ -5112,6 +5314,7 @@ Take into consideration N (the prefix) and the list of marked groups."
       (nreverse groups)))
    ((and (boundp 'transient-mark-mode)
         transient-mark-mode
+        (boundp 'mark-active)
         mark-active)
     ;; Work on the region between point and mark.
     (let ((max (max (point) (mark)))
@@ -5221,10 +5424,15 @@ Returns whether the fetching was successful or not."
   (interactive
    (list (completing-read
          "Group: " gnus-active-hashtb nil
-         (memq gnus-select-method gnus-have-read-active-file))))
+         (gnus-read-active-file-p)
+         nil
+         'gnus-group-history)))
 
-  (if (equal group "")
-      (error "Empty group name"))
+  (when (equal group "")
+    (error "Empty group name"))
+
+  (when (string-match "[\000-\032]" group)
+    (error "Control characters in group: %s" group))
 
   (let ((b (text-property-any
            (point-min) (point-max)
@@ -5320,7 +5528,8 @@ If EXCLUDE-GROUP, do not go to that group."
   (goto-char (point-min))
   (let ((best 100000)
        unread best-point)
-    (while (setq unread (get-text-property (point) 'gnus-unread))
+    (while (not (eobp))
+      (setq unread (get-text-property (point) 'gnus-unread))
       (if (and (numberp unread) (> unread 0))
          (progn
            (if (and (get-text-property (point) 'gnus-level)
@@ -5366,7 +5575,7 @@ ADDRESS."
     (let ((method
           (completing-read
            "Method: " (append gnus-valid-select-methods gnus-server-alist)
-           nil t)))
+           nil t nil 'gnus-method-history)))
       (cond ((assoc method gnus-valid-select-methods)
             (list method
                   (if (memq 'prompt-address
@@ -5378,41 +5587,47 @@ ADDRESS."
            (t
             (list method ""))))))
 
-  (save-excursion
-    (set-buffer gnus-group-buffer)
-    (let* ((meth (and method (if address (list (intern method) address)
-                              method)))
-          (nname (if method (gnus-group-prefixed-name name meth) name))
-          backend info)
-      (and (gnus-gethash nname gnus-newsrc-hashtb)
-          (error "Group %s already exists" nname))
-      (gnus-group-change-level
-       (setq info (list t nname gnus-level-default-subscribed nil nil meth))
-       gnus-level-default-subscribed gnus-level-killed
-       (and (gnus-group-group-name)
-           (gnus-gethash (gnus-group-group-name)
-                         gnus-newsrc-hashtb))
-       t)
-      (gnus-set-active nname (cons 1 0))
-      (or (gnus-ephemeral-group-p name)
-         (gnus-dribble-enter
-          (concat "(gnus-group-set-info '" (prin1-to-string (cdr info)) ")")))
-      (gnus-group-insert-group-line-info nname)
-
-      (when (assoc (symbol-name (setq backend (car (gnus-server-get-method
-                                                   nil meth))))
-                  gnus-valid-select-methods)
-       (require backend))
-      (gnus-check-server meth)
-      (and (gnus-check-backend-function 'request-create-group nname)
-          (gnus-request-create-group nname))
-      t)))
+  (let* ((meth (and method (if address (list (intern method) address)
+                            method)))
+        (nname (if method (gnus-group-prefixed-name name meth) name))
+        backend info)
+    (when (gnus-gethash nname gnus-newsrc-hashtb)
+      (error "Group %s already exists" nname))
+    ;; Subscribe to the new group.
+    (gnus-group-change-level
+     (setq info (list t nname gnus-level-default-subscribed nil nil meth))
+     gnus-level-default-subscribed gnus-level-killed
+     (and (gnus-group-group-name)
+         (gnus-gethash (gnus-group-group-name)
+                       gnus-newsrc-hashtb))
+     t)
+    ;; Make it active.
+    (gnus-set-active nname (cons 1 0))
+    (or (gnus-ephemeral-group-p name)
+       (gnus-dribble-enter
+        (concat "(gnus-group-set-info '" (prin1-to-string (cdr info)) ")")))
+    ;; Insert the line.
+    (gnus-group-insert-group-line-info nname)
+    (forward-line -1)
+    (gnus-group-position-point)
+
+    ;; Load the backend and try to make the backend create
+    ;; the group as well.
+    (when (assoc (symbol-name (setq backend (car (gnus-server-get-method
+                                                 nil meth))))
+                gnus-valid-select-methods)
+      (require backend))
+    (gnus-check-server meth)
+    (and (gnus-check-backend-function 'request-create-group nname)
+        (gnus-request-create-group nname))
+    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))
@@ -5427,9 +5642,7 @@ of the Earth\".    There is no undo."
          () ; Whew!
        (gnus-message 6 "Deleting group %s..." group)
        (if (not (gnus-request-delete-group group force))
-           (progn
-             (gnus-message 3 "Couldn't delete group %s" group)
-             (ding))
+           (gnus-error 3 "Couldn't delete group %s" group)
          (gnus-message 6 "Deleting group %s...done" group)
          (gnus-group-goto-group group)
          (gnus-group-kill-group 1 t)
@@ -5463,9 +5676,7 @@ of the Earth\".    There is no undo."
   (gnus-message 6 "Renaming group %s to %s..." group new-name)
   (prog1
       (if (not (gnus-request-rename-group group new-name))
-         (progn
-           (gnus-message 3 "Couldn't rename group %s to %s" group new-name)
-           (ding))
+         (gnus-error 3 "Couldn't rename group %s to %s" group new-name)
        ;; We rename the group internally by killing it...
        (gnus-group-goto-group group)
        (gnus-group-kill-group)
@@ -5590,7 +5801,7 @@ of the Earth\".    There is no undo."
                                    "etc/gnus-tut.txt"))))
        (setq path nil)))
     (if (not file)
-       (message "Couldn't find doc group")
+       (gnus-message 1 "Couldn't find doc group")
       (gnus-group-make-group
        (gnus-group-real-name name)
        (list 'nndoc "gnus-help"
@@ -5626,9 +5837,7 @@ of the Earth\".    There is no undo."
      (gnus-group-real-name name)
      (list 'nndoc (file-name-nondirectory file)
           (list 'nndoc-address file)
-          (list 'nndoc-article-type (or type 'guess))))
-    (forward-line -1)
-    (gnus-group-position-point)))
+          (list 'nndoc-article-type (or type 'guess))))))
 
 (defun gnus-group-make-archive-group (&optional all)
   "Create the (ding) Gnus archive group of the most recent articles.
@@ -5643,9 +5852,7 @@ Given a prefix, create a full group."
      (list 'nndir (if all "hpc" "edu")
           (list 'nndir-directory
                 (if all gnus-group-archive-directory
-                  gnus-group-recent-archive-directory)))))
-  (forward-line -1)
-  (gnus-group-position-point))
+                  gnus-group-recent-archive-directory))))))
 
 (defun gnus-group-make-directory-group (dir)
   "Create an nndir group.
@@ -5668,9 +5875,7 @@ mail messages or news articles in files that have numeric names."
       (setq ext (format "<%d>" (setq i (1+ i)))))
     (gnus-group-make-group
      (gnus-group-real-name group)
-     (list 'nndir group (list 'nndir-directory dir))))
-  (forward-line -1)
-  (gnus-group-position-point))
+     (list 'nndir group (list 'nndir-directory dir)))))
 
 (defun gnus-group-make-kiboze-group (group address scores)
   "Create an nnkiboze group.
@@ -5695,14 +5900,9 @@ score file entries for articles to include in the group."
        (setq scores (cons (cons header regexps) scores)))
       scores)))
   (gnus-group-make-group group "nnkiboze" address)
-  (save-excursion
-    (gnus-set-work-buffer)
+  (nnheader-temp-write (gnus-score-file-name (concat "nnkiboze:" group))
     (let (emacs-lisp-mode-hook)
-      (pp scores (current-buffer)))
-    (write-region (point-min) (point-max)
-                 (gnus-score-file-name (concat "nnkiboze:" group))))
-  (forward-line -1)
-  (gnus-group-position-point))
+      (pp scores (current-buffer)))))
 
 (defun gnus-group-add-to-virtual (n vgroup)
   "Add the current group to a virtual group."
@@ -5849,7 +6049,7 @@ If REVERSE, sort in reverse order."
        (level2 (gnus-info-level info2)))
     (or (< level1 level2)
        (and (= level1 level2)
-            (< (gnus-info-score info1) (gnus-info-score info2))))))
+            (> (gnus-info-score info1) (gnus-info-score info2))))))
 
 ;; Group catching up.
 
@@ -5876,6 +6076,8 @@ read.  Cross references (Xref: header) of articles are ignored.
 The difference between N and actual number of newsgroups that were
 caught up is returned."
   (interactive "P")
+  (unless (gnus-group-group-name)
+    (error "No group on the current line"))
   (if (not (or (not gnus-interactive-catchup) ;Without confirmation?
               gnus-expert-user
               (gnus-y-or-n-p
@@ -5892,11 +6094,13 @@ caught up is returned."
              (nnvirtual-catchup-group
               (gnus-group-real-name (car groups)) (nth 1 method) all)))
        (gnus-group-remove-mark (car groups))
-       (if (prog1
-               (gnus-group-goto-group (car groups))
-             (gnus-group-catchup (car groups) all))
-           (gnus-group-update-group-line)
-         (setq ret (1+ ret)))
+       (if (>= (gnus-group-group-level) gnus-level-zombie)
+           (gnus-message 2 "Dead groups can't be caught up")
+         (if (prog1
+                 (gnus-group-goto-group (car groups))
+               (gnus-group-catchup (car groups) all))
+             (gnus-group-update-group-line)
+           (setq ret (1+ ret))))
        (setq groups (cdr groups)))
       (gnus-group-next-unread-group 1)
       ret)))
@@ -5965,7 +6169,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))))
 
@@ -6032,7 +6237,9 @@ group line."
   (interactive
    (list (completing-read
          "Group: " gnus-active-hashtb nil
-         (memq gnus-select-method gnus-have-read-active-file))))
+         (gnus-read-active-file-p)
+         nil 
+         'gnus-group-history)))
   (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb)))
     (cond
      ((string-match "^[ \t]$" group)
@@ -6047,7 +6254,7 @@ group line."
       (unless silent
        (gnus-group-update-group group)))
      ((and (stringp group)
-          (or (not (memq gnus-select-method gnus-have-read-active-file))
+          (or (not (gnus-read-active-file-p))
               (gnus-active group)))
       ;; Add new newsgroup.
       (gnus-group-change-level
@@ -6134,6 +6341,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))
@@ -6216,28 +6429,7 @@ entail asking the server for the groups."
   (interactive "P")
   ;; Find all possible killed newsgroups if arg.
   (when arg
-    ;; First make sure active file has been read.
-    (unless gnus-have-read-active-file
-      (let ((gnus-read-active-file t))
-       (gnus-read-active-file)))
-    (or gnus-killed-hashtb (gnus-make-hashtable-from-killed))
-    ;; Go through all newsgroups that are known to Gnus - enlarge kill list
-    (mapatoms
-     (lambda (sym)
-       (let ((groups 0)
-            (group (symbol-name sym)))
-        (if (or (null group)
-                (gnus-gethash group gnus-killed-hashtb)
-                (gnus-gethash group gnus-newsrc-hashtb))
-            ()
-          (let ((do-sub (gnus-matches-options-n group)))
-            (if (or (eq do-sub 'subscribe) (eq do-sub 'ignore))
-                ()
-              (setq groups (1+ groups))
-              (setq gnus-killed-list
-                    (cons group gnus-killed-list))
-              (gnus-sethash group group gnus-killed-hashtb))))))
-     gnus-active-hashtb))
+    (gnus-get-killed-groups))
   (if (not gnus-killed-list)
       (gnus-message 6 "No killed groups")
     (let (gnus-group-list-mode)
@@ -6261,7 +6453,7 @@ entail asking the server for the groups."
   "List all groups that are available from the server(s)."
   (interactive)
   ;; First we make sure that we have really read the active file.
-  (unless gnus-have-read-active-file
+  (unless (gnus-read-active-file-p)
     (let ((gnus-read-active-file t))
       (gnus-read-active-file)))
   ;; Find all groups and sort them.
@@ -6270,7 +6462,8 @@ entail asking the server for the groups."
          (let (list)
            (mapatoms
             (lambda (sym)
-              (and (symbol-value sym)
+              (and (boundp sym)
+                   (symbol-value sym)
                    (setq list (cons (symbol-name sym) list))))
             gnus-active-hashtb)
            list)
@@ -6322,37 +6515,35 @@ If N is negative, this group and the N-1 previous groups will be checked."
   (interactive "P")
   (let* ((groups (gnus-group-process-prefix n))
         (ret (if (numberp n) (- n (length groups)) 0))
+        (beg (unless n (point)))
         group)
-    (while groups
-      (setq group (car groups)
-           groups (cdr groups))
+    (while (setq group (pop groups))
       (gnus-group-remove-mark group)
-      (unless (gnus-get-new-news-in-group group)
-       (ding)
-       (gnus-message 3 "%s error: %s" group (gnus-status-message group))))
+      (if (gnus-activate-group group 'scan)
+         (progn
+           (gnus-get-unread-articles-in-group
+            (gnus-get-info group) (gnus-active group) t)
+           (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))))
+    (when beg (goto-char beg))
     (when gnus-goto-next-group-when-activating
       (gnus-group-next-unread-group 1 t))
     (gnus-summary-position-point)
     ret))
 
-(defun gnus-get-new-news-in-group (group)
-  (when (and group (gnus-activate-group group 'scan))
-    (gnus-get-unread-articles-in-group
-     (gnus-get-info group) (gnus-active group) t)
-    (gnus-close-group group)
-    (when (gnus-group-goto-group group)
-      (gnus-group-update-group-line))
-    t))
-
 (defun gnus-group-fetch-faq (group &optional faq-dir)
   "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)
@@ -6367,7 +6558,9 @@ 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))
+  (when (and force
+            gnus-description-hashtb)
+    (gnus-sethash group nil gnus-description-hashtb))
   (let ((method (gnus-find-method-for-group group))
        desc)
     (or group (error "No group name given"))
@@ -6379,7 +6572,7 @@ If N is negative, this group and the N-1 previous groups will be checked."
                   gnus-description-hashtb))
             (setq desc (gnus-group-get-description group))
             (gnus-read-descriptions-file method))
-        (message
+        (gnus-message 1
          (or desc (gnus-gethash group gnus-description-hashtb)
              "No description available")))))
 
@@ -6399,7 +6592,7 @@ If N is negative, this group and the N-1 previous groups will be checked."
        (setq b (point))
        (insert (format "      *: %-20s %s\n" (symbol-name group)
                       (symbol-value group)))
-       (add-text-properties
+       (gnus-add-text-properties
        b (1+ b) (list 'gnus-group group
                       'gnus-unread t 'gnus-marked nil
                       'gnus-level (1+ gnus-level-subscribed))))
@@ -6464,8 +6657,14 @@ If N is negative, this group and the N-1 previous groups will be checked."
 If the prefix LEVEL is non-nil, it should be a number that says which
 level to cut off listing groups.
 If ALL, also list groups with no unread articles.
-If LOWEST, don't list groups with level lower than LOWEST."
+If LOWEST, don't list groups with level lower than LOWEST.
+
+This command may read the active file."
   (interactive "P\nsList newsgroups matching: ")
+  ;; First make sure active file has been read.
+  (when (and level
+            (> (prefix-numeric-value level) gnus-level-killed))
+    (gnus-get-killed-groups))
   (gnus-group-prepare-flat (or level gnus-level-subscribed)
                           all (or lowest 1) regexp)
   (goto-char (point-min))
@@ -6538,19 +6737,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."
@@ -6564,7 +6762,6 @@ The hook `gnus-exit-gnus-hook' is called before actually exiting."
   (interactive)
   (when 
       (or noninteractive               ;For gnus-batch-kill
-         (not (gnus-server-opened gnus-select-method)) ;NNTP connection closed
          (not gnus-interactive-exit)   ;Without confirmation
          gnus-expert-user
          (gnus-y-or-n-p "Are you sure you want to quit reading news? "))
@@ -6651,7 +6848,7 @@ and the second element is the address."
    (list (let ((how (completing-read
                     "Which backend: "
                     (append gnus-valid-select-methods gnus-server-alist)
-                    nil t (cons "nntp" 0))))
+                    nil t (cons "nntp" 0) 'gnus-method-history)))
           ;; We either got a backend name or a virtual server name.
           ;; If the first, we also need an address.
           (if (assoc how gnus-valid-select-methods)
@@ -6985,15 +7182,7 @@ The following commands are available:
             (gnus-visual-p 'summary-menu 'menu))
     (gnus-summary-make-menu-bar))
   (kill-all-local-variables)
-  (let ((locals gnus-summary-local-variables))
-    (while locals
-      (if (consp (car locals))
-         (progn
-           (make-local-variable (caar locals))
-           (set (caar locals) (eval (cdar locals))))
-       (make-local-variable (car locals))
-       (set (car locals) nil))
-      (setq locals (cdr locals))))
+  (gnus-summary-make-local-variables)
   (gnus-make-thread-indent-array)
   (gnus-simplify-mode-line)
   (setq major-mode 'gnus-summary-mode)
@@ -7007,8 +7196,29 @@ The following commands are available:
   (setq selective-display-ellipses t)  ;Display `...'
   (setq buffer-display-table gnus-summary-display-table)
   (setq gnus-newsgroup-name group)
+  (make-local-variable 'gnus-summary-line-format)
+  (make-local-variable 'gnus-summary-line-format-spec)
+  (make-local-variable 'gnus-summary-mark-positions)
   (run-hooks 'gnus-summary-mode-hook))
 
+(defun gnus-summary-make-local-variables ()
+  "Make all the local summary buffer variables."
+  (let ((locals gnus-summary-local-variables)
+       global local)
+    (while (setq local (pop locals))
+      (if (consp local)
+         (progn
+           (if (eq (cdr local) 'global)
+               ;; Copy the global value of the variable.
+               (setq global (symbol-value (car local)))
+             ;; Use the value from the list.
+             (setq global (eval (cdr local))))
+           (make-local-variable (car local))
+           (set (car local) global))
+       ;; Simple nil-valued local variable.
+       (make-local-variable local)
+       (set local nil)))))
+
 (defun gnus-summary-make-display-table ()
   ;; Change the display table. Odd characters have a tendency to mess
   ;; up nicely formatted displays - we make all possible glyphs
@@ -7266,6 +7476,39 @@ This is all marks except unread, ticked, dormant, and expirable."
           (= mark gnus-dormant-mark)
           (= mark gnus-expirable-mark))))
 
+;; Saving hidden threads.
+
+(put 'gnus-save-hidden-threads 'lisp-indent-function 0)
+(put 'gnus-save-hidden-threads 'lisp-indent-hook 0)
+(put 'gnus-save-hidden-threads 'edebug-form-spec '(body))
+
+(defmacro gnus-save-hidden-threads (&rest forms)
+  "Save hidden threads, eval FORMS, and restore the hidden threads."
+  (let ((config (make-symbol "config")))
+    `(let ((,config (gnus-hidden-threads-configuration)))
+       (unwind-protect
+          (progn
+            ,@forms)
+        (gnus-restore-hidden-threads-configuration ,config)))))
+
+(defun gnus-hidden-threads-configuration ()
+  "Return the current hidden threads configuration."
+  (save-excursion
+    (let (config)
+      (goto-char (point-min))
+      (while (search-forward "\r" nil t)
+       (push (1- (point)) config))
+      config)))
+
+(defun gnus-restore-hidden-threads-configuration (config)
+  "Restore hidden threads configuration from CONFIG."
+  (let (point buffer-read-only)
+    (while (setq point (pop config))
+      (when (and (< point (point-max))
+                (goto-char point)
+                (= (following-char) ?\n))
+       (subst-char-in-region point (1+ point) ?\n ?\r)))))
+
 ;; Various summary mode internalish functions.
 
 (defun gnus-mouse-pick-article (e)
@@ -7327,17 +7570,15 @@ This is all marks except unread, ticked, dormant, and expirable."
   "Return whether ARTICLE is the last article in the buffer."
   (if (not (setq article (or article (gnus-summary-article-number))))
       t ; All non-existant numbers are the last article. :-)
-    (cdr (gnus-data-find-list article))))
+    (not (cdr (gnus-data-find-list article)))))
 
 (defun gnus-summary-insert-dummy-line (gnus-tmp-subject gnus-tmp-number)
   "Insert a dummy root in the summary buffer."
   (beginning-of-line)
-  (add-text-properties
+  (gnus-add-text-properties
    (point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
    (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
 
-(defvar gnus-thread-indent-array nil)
-(defvar gnus-thread-indent-array-level gnus-thread-indent-level)
 (defun gnus-make-thread-indent-array ()
   (let ((n 200))
     (unless (and gnus-thread-indent-array
@@ -7390,7 +7631,7 @@ This is all marks except unread, ticked, dormant, and expirable."
     (when (string= gnus-tmp-name "")
       (setq gnus-tmp-name gnus-tmp-from))
     (or (numberp gnus-tmp-lines) (setq gnus-tmp-lines 0))
-    (put-text-property
+    (gnus-put-text-property
      (point)
      (progn (eval gnus-summary-line-format-spec) (point))
      'gnus-number gnus-tmp-number)
@@ -7443,7 +7684,7 @@ This is all marks except unread, ticked, dormant, and expirable."
            1)
           ((memq (mail-header-number (car thread)) gnus-newsgroup-limit)
            1)
-          (t 1))))
+          (t 0))))
     (when (and level (zerop level) gnus-tmp-new-adopts)
       (incf number
            (apply '+ (mapcar
@@ -7550,10 +7791,15 @@ If NO-DISPLAY, don't generate a summary buffer."
       (when gnus-build-sparse-threads
        (gnus-build-sparse-threads))
       ;; Find the initial limit.
-      (if show-all
-         (let ((gnus-newsgroup-dormant nil))
+      (if gnus-show-threads
+         (if show-all
+             (let ((gnus-newsgroup-dormant nil))
+               (gnus-summary-initial-limit show-all))
            (gnus-summary-initial-limit show-all))
-       (gnus-summary-initial-limit show-all))
+       (setq gnus-newsgroup-limit 
+             (mapcar 
+              (lambda (header) (mail-header-number header))
+              gnus-newsgroup-headers)))
       ;; Generate the summary buffer.
       (unless no-display
        (gnus-summary-prepare))
@@ -7593,9 +7839,10 @@ If NO-DISPLAY, don't generate a summary buffer."
                 (not no-display)
                 gnus-newsgroup-unreads
                 gnus-auto-select-first)
-           (if (eq gnus-auto-select-first 'best)
-               (gnus-summary-best-unread-article)
-             (gnus-summary-first-unread-article))
+           (unless (if (eq gnus-auto-select-first 'best)
+                       (gnus-summary-best-unread-article)
+                     (gnus-summary-first-unread-article))
+             (gnus-configure-windows 'summary))
          ;; Don't select any articles, just move point to the first
          ;; article in the group.
          (goto-char (point-min))
@@ -7864,26 +8111,32 @@ If NO-DISPLAY, don't generate a summary buffer."
                      (delq number gnus-newsgroup-unselected)))
            (push number gnus-newsgroup-ancient)))))))
 
-(defun gnus-summary-update-article (article &optional header)
+(defun gnus-summary-update-article (article &optional iheader)
   "Update ARTICLE in the summary buffer."
   (set-buffer gnus-summary-buffer)
-  (let* ((header (or header (gnus-summary-article-header article)))
+  (let* ((header (or iheader (gnus-summary-article-header article)))
         (id (mail-header-id header))
         (data (gnus-data-find article))
         (thread (gnus-id-to-thread id))
+        (references (mail-header-references header))
         (parent
-         (gnus-id-to-thread (or (gnus-parent-id 
-                                 (mail-header-references header))
-                                "tull")))
+         (gnus-id-to-thread
+          (or (gnus-parent-id 
+               (if (and references
+                        (not (equal "" references)))
+                   references))
+              "none")))
         (buffer-read-only nil)
         (old (car thread))
         (number (mail-header-number header))
         pos)
     (when thread
-      (setcar thread nil)
+      ;; !!! Should this be in or not?
+      (unless iheader
+       (setcar thread nil))
       (when parent
        (delq thread parent))
-      (if (gnus-summary-insert-subject id header)
+      (if (gnus-summary-insert-subject id header iheader)
          ;; Set the (possibly) new article number in the data structure.
          (gnus-data-set-number data (gnus-id-to-article id))
        (setcar thread old)
@@ -7920,7 +8173,7 @@ If NO-DISPLAY, don't generate a summary buffer."
     (let (threads)
       ;; We then insert this thread into the summary buffer.
       (let (gnus-newsgroup-data gnus-newsgroup-threads)
-       (gnus-summary-prepare-threads (list thread))
+       (gnus-summary-prepare-threads (gnus-cut-threads (list thread)))
        (setq data (nreverse gnus-newsgroup-data))
        (setq threads gnus-newsgroup-threads))
       ;; We splice the new data into the data structure.
@@ -7928,6 +8181,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))
@@ -7935,7 +8197,8 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defun gnus-id-to-article (id)
   "Return the article number of ID."
   (let ((thread (gnus-id-to-thread id)))
-    (when thread
+    (when (and thread
+              (car thread))
       (mail-header-number (car thread)))))
 
 (defun gnus-id-to-header (id)
@@ -7945,15 +8208,16 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defun gnus-article-displayed-root-p (article)
   "Say whether ARTICLE is a root(ish) article."
   (let ((level (gnus-summary-thread-level article))
+       (refs (mail-header-references  (gnus-summary-article-header article)))
        particle)
     (cond 
      ((null level) nil)
      ((zerop level) t)
+     ((null refs) t)
+     ((null (gnus-parent-id refs)) t)
      ((and (= 1 level)
           (null (setq particle (gnus-id-to-article
-                                (gnus-parent-id 
-                                 (mail-header-references 
-                                  (gnus-summary-article-header article))))))
+                                (gnus-parent-id refs))))
           (null (gnus-summary-thread-level particle)))))))
 
 (defun gnus-root-id (id)
@@ -8118,8 +8382,8 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defsubst gnus-article-sort-by-date (h1 h2)
   "Sort articles by root article date."
   (string-lessp
-   (gnus-sortable-date (mail-header-date h1))
-   (gnus-sortable-date (mail-header-date h2))))
+   (inline (gnus-sortable-date (mail-header-date h1)))
+   (inline (gnus-sortable-date (mail-header-date h2)))))
 
 (defun gnus-thread-sort-by-date (h1 h2)
   "Sort threads by root article date."
@@ -8148,22 +8412,34 @@ Unscored articles will be counted as having a score of zero."
 
 (defun gnus-thread-total-score (thread)
   ;;  This function find the total score of THREAD.
-  (if (consp thread)
-      (if (stringp (car thread))
-         (apply gnus-thread-score-function 0
-                (mapcar 'gnus-thread-total-score-1 (cdr thread)))
-       (gnus-thread-total-score-1 thread))
-    (gnus-thread-total-score-1 (list thread))))
+  (cond ((null thread)
+        0)
+       ((consp thread)
+        (if (stringp (car thread))
+            (apply gnus-thread-score-function 0
+                   (mapcar 'gnus-thread-total-score-1 (cdr thread)))
+          (gnus-thread-total-score-1 thread)))
+       (t
+        (gnus-thread-total-score-1 (list thread)))))
 
 (defun gnus-thread-total-score-1 (root)
-  ;; This function find the total score of the thread below ROOT.
+  ;; This function finds 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)))))
+  (let ((number (mail-header-number root)))
+    (if (and (not (memq number gnus-newsgroup-limit))
+            (not (memq number gnus-newsgroup-sparse)))
+       ;; This article shouldn't be counted.
+       (apply gnus-thread-score-function
+              (mapcar 'gnus-thread-total-score
+                      (cdr (gnus-gethash (mail-header-id root)
+                                         gnus-newsgroup-dependencies))))
+      ;; This article should be counted.
+      (apply gnus-thread-score-function
+            (or (cdr (assq number gnus-newsgroup-scored))
+                gnus-summary-default-score 0)
+            (mapcar 'gnus-thread-total-score
+                    (cdr (gnus-gethash (mail-header-id root)
+                                       gnus-newsgroup-dependencies)))))))
 
 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defvar gnus-tmp-prev-subject nil)
@@ -8308,7 +8584,8 @@ or a straight list of headers."
                        default-score)
                    gnus-summary-mark-below)
                 ;; Don't touch sparse articles.
-                (not (memq number gnus-newsgroup-sparse)))
+                (not (memq number gnus-newsgroup-sparse))
+                (not (memq number gnus-newsgroup-ancient)))
            (setq gnus-newsgroup-unreads
                  (delq number gnus-newsgroup-unreads))
            (if gnus-newsgroup-auto-expire
@@ -8383,6 +8660,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
@@ -8400,7 +8679,7 @@ or a straight list of headers."
            (when (string= gnus-tmp-name "")
              (setq gnus-tmp-name gnus-tmp-from))
            (or (numberp gnus-tmp-lines) (setq gnus-tmp-lines 0))
-           (put-text-property
+           (gnus-put-text-property
             (point)
             (progn (eval gnus-summary-line-format-spec) (point))
             'gnus-number number)
@@ -8424,16 +8703,16 @@ or a straight list of headers."
   (let (header number mark)
 
     (while headers
-      (setq header (car headers)
-           headers (cdr headers)
-           number (mail-header-number header))
-
       ;; We may have to root out some bad articles...
-      (when (memq number gnus-newsgroup-limit)
+      (when (memq (setq number (mail-header-number
+                               (setq header (pop headers))))
+                 gnus-newsgroup-limit)
+       ;; Mark article as read when it has a low score.
        (when (and gnus-summary-mark-below
                   (< (or (cdr (assq number gnus-newsgroup-scored))
                          gnus-summary-default-score 0)
-                     gnus-summary-mark-below))
+                     gnus-summary-mark-below)
+                  (not (memq number gnus-newsgroup-ancient)))
          (setq gnus-newsgroup-unreads
                (delq number gnus-newsgroup-unreads))
          (if gnus-newsgroup-auto-expire
@@ -8471,13 +8750,19 @@ If READ-ALL is non-nil, all articles in the group are selected."
        (error "Couldn't open server"))
 
     (or (and entry (not (eq (car entry) t))) ; Either it's active...
-       (gnus-activate-group group) ; Or we can activate it...
-       (progn ; Or we bug out.
+       (gnus-activate-group group)     ; Or we can activate it...
+       (progn                          ; Or we bug out.
          (when (equal major-mode 'gnus-summary-mode)
            (kill-buffer (current-buffer)))
          (error "Couldn't request group %s: %s"
                 group (gnus-status-message group))))
 
+    (unless (gnus-request-group group t)
+      (when (equal major-mode 'gnus-summary-mode)
+       (kill-buffer (current-buffer)))
+      (error "Couldn't request group %s: %s"
+            group (gnus-status-message group)))      
+
     (setq gnus-newsgroup-name group)
     (setq gnus-newsgroup-unselected nil)
     (setq gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
@@ -8559,12 +8844,12 @@ If READ-ALL is non-nil, all articles in the group are selected."
       (unless gnus-single-article-buffer
        (gnus-article-setup-buffer))
       ;; First and last article in this newsgroup.
-      (and gnus-newsgroup-headers
-          (setq gnus-newsgroup-begin
-                (mail-header-number (car gnus-newsgroup-headers)))
-          (setq gnus-newsgroup-end
-                (mail-header-number
-                 (gnus-last-element gnus-newsgroup-headers))))
+      (when gnus-newsgroup-headers
+       (setq gnus-newsgroup-begin
+             (mail-header-number (car gnus-newsgroup-headers))
+             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)))))
@@ -8602,7 +8887,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): "
@@ -8717,7 +9003,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.
@@ -8792,12 +9079,13 @@ If WHERE is `summary', the summary mode line format will be used."
               (gnus-tmp-subject
                (if (and gnus-current-headers
                         (vectorp gnus-current-headers))
-                   (mail-header-subject gnus-current-headers) ""))
+                   (gnus-mode-string-quote
+                    (mail-header-subject gnus-current-headers)) ""))
               max-len
               gnus-tmp-header);; passed as argument to any user-format-funcs
          (setq mode-string (eval mformat))
          (setq max-len (max 4 (if gnus-mode-non-string-length
-                                  (- (frame-width)
+                                  (- (window-width)
                                      gnus-mode-non-string-length)
                                 (length mode-string))))
          ;; We might have to chop a bit of the string off...
@@ -8808,7 +9096,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)
@@ -8958,6 +9248,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
        headers id id-dep ref-dep end ref)
     (save-excursion
       (set-buffer nntp-server-buffer)
+      (run-hooks 'gnus-parse-headers-hook)
       (let ((case-fold-search t)
            in-reply-to header p lines)
        (goto-char (point-min))
@@ -9014,10 +9305,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
@@ -9100,21 +9391,20 @@ The resulting hash table is returned, or nil if no Xrefs were found."
   '(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
 
 ;; Goes through the xover lines and returns a list of vectors
-(defun gnus-get-newsgroup-headers-xover (sequence &optional force-new)
+(defun gnus-get-newsgroup-headers-xover (sequence &optional 
+                                                 force-new dependencies)
   "Parse the news overview data in the server buffer, and return a
 list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
   ;; Get the Xref when the users reads the articles since most/some
   ;; NNTP servers do not include Xrefs when using XOVER.
   (setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
   (let ((cur nntp-server-buffer)
-       (dependencies gnus-newsgroup-dependencies)
+       (dependencies (or dependencies gnus-newsgroup-dependencies))
        number headers header)
     (save-excursion
       (set-buffer nntp-server-buffer)
       ;; Allow the user to mangle the headers before parsing them.
       (run-hooks 'gnus-parse-headers-hook)
-      ;; Allow the user to mangle the headers before parsing them.
-      (run-hooks 'gnus-parse-headers-hook)
       (goto-char (point-min))
       (while (and sequence (not (eobp)))
        (setq number (read cur))
@@ -9173,8 +9463,7 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
                 (gnus-nov-field))      ; misc
               ))
       (error (progn
-              (ding)
-              (gnus-message 4 "Strange nov line")
+              (gnus-error 4 "Strange nov line")
               (setq header nil)
               (goto-char eol))))
 
@@ -9198,13 +9487,12 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
                (setq header nil))
            (setcar (symbol-value id-dep) header))
        (set id-dep (list header))))
-    (if header
-       (progn
-         (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
-             (setcdr (symbol-value ref-dep)
-                     (nconc (cdr (symbol-value ref-dep))
-                            (list (symbol-value id-dep))))
-           (set ref-dep (list nil (symbol-value id-dep))))))
+    (when header
+      (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
+         (setcdr (symbol-value ref-dep)
+                 (nconc (cdr (symbol-value ref-dep))
+                        (list (symbol-value id-dep))))
+       (set ref-dep (list nil (symbol-value id-dep)))))
     header))
 
 (defun gnus-article-get-xrefs ()
@@ -9230,23 +9518,31 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
                                               (progn (end-of-line) (point))))
                  (mail-header-set-xref headers xref))))))))
 
-(defun gnus-summary-insert-subject (id &optional old-header)
+(defun gnus-summary-insert-subject (id &optional old-header use-old-header)
   "Find article ID and insert the summary line for that article."
-  (let ((header (gnus-read-header id))
+  (let ((header (if (and old-header use-old-header)
+                   old-header (gnus-read-header id)))
        (number (and (numberp id) id))
        pos)
     (when header
       ;; Rebuild the thread that this article is part of and go to the
       ;; article we have fetched.
-      (when old-header
+      (when (and (not gnus-show-threads)
+                old-header)
        (when (setq pos (text-property-any
                         (point-min) (point-max) 'gnus-number 
                         (mail-header-number old-header)))
          (goto-char pos)
          (gnus-delete-line)
          (gnus-data-remove (mail-header-number old-header))))
+      (when old-header
+       (mail-header-set-number header (mail-header-number old-header)))
+      (setq gnus-newsgroup-sparse
+           (delq (setq number (mail-header-number header)) 
+                 gnus-newsgroup-sparse))
+      (setq gnus-newsgroup-ancient (delq number gnus-newsgroup-ancient))
       (gnus-rebuild-thread (mail-header-id header))
-      (gnus-summary-goto-subject (setq number (mail-header-number header))))
+      (gnus-summary-goto-subject number nil t))
     (when (and (numberp number)
               (> number 0))
       ;; We have to update the boundaries even if we can't fetch the
@@ -9267,10 +9563,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
@@ -9322,12 +9618,14 @@ If EXCLUDE-GROUP, do not go to this group."
 
 (defun gnus-summary-find-next (&optional unread article backward)
   (if backward (gnus-summary-find-prev)
-    (let* ((article (or article (gnus-summary-article-number)))
+    (let* ((dummy (gnus-summary-article-intangible-p))
+          (article (or article (gnus-summary-article-number)))
           (arts (gnus-data-find-list article))
           result)
-      (when (or (not gnus-summary-check-current)
-               (not unread)
-               (not (gnus-data-unread-p (car arts))))
+      (when (and (not dummy)
+                (or (not gnus-summary-check-current)
+                    (not unread)
+                    (not (gnus-data-unread-p (car arts)))))
        (setq arts (cdr arts)))
       (when (setq result
                  (if unread
@@ -9343,12 +9641,14 @@ If EXCLUDE-GROUP, do not go to this group."
        (gnus-data-number result)))))
 
 (defun gnus-summary-find-prev (&optional unread article)
-  (let* ((article (or article (gnus-summary-article-number)))
+  (let* ((eobp (eobp))
+        (article (or article (gnus-summary-article-number)))
         (arts (gnus-data-find-list article (gnus-data-list 'rev)))
         result)
-    (when (or (not gnus-summary-check-current)
-             (not unread)
-             (not (gnus-data-unread-p (car arts))))
+    (when (and (not eobp)
+              (or (not gnus-summary-check-current)
+                  (not unread)
+                  (not (gnus-data-unread-p (car arts)))))
       (setq arts (cdr arts)))
     (if (setq result
              (if unread
@@ -9570,9 +9870,7 @@ displayed, no centering will be performed."
             "\\<gnus-summary-mode-map>\\[gnus-summary-universal-argument]"
             ))))
         'undefined)
-       (progn
-         (message "Undefined key")
-         (ding))
+       (gnus-error 1 "Undefined key")
       (save-excursion
        (while articles
          (gnus-summary-goto-subject (setq article (pop articles)))
@@ -9594,6 +9892,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)
@@ -9606,7 +9906,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."
@@ -9659,11 +9959,9 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
         (quit-config (gnus-group-quit-config gnus-newsgroup-name))
         (mode major-mode)
         (buf (current-buffer)))
-    (unless temporary
-      (run-hooks 'gnus-summary-prepare-exit-hook))
+    (run-hooks 'gnus-summary-prepare-exit-hook)
     ;; If we have several article buffers, we kill them at exit.
     (unless gnus-single-article-buffer
-      (gnus-kill-buffer gnus-article-buffer)
       (gnus-kill-buffer gnus-original-article-buffer)
       (setq gnus-article-current nil))
     (when gnus-use-cache
@@ -9678,11 +9976,10 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
     ;; Make sure where I was, and go to next newsgroup.
     (set-buffer gnus-group-buffer)
     (unless quit-config
-      (gnus-group-jump-to-group group)
-      (gnus-group-next-unread-group 1))
+      (gnus-group-jump-to-group group))
     (run-hooks 'gnus-summary-exit-hook)
-    (unless gnus-single-article-buffer
-      (setq gnus-article-current nil))
+    (unless quit-config
+      (gnus-group-next-unread-group 1))
     (if temporary
        nil                             ;Nothing to do.
       ;; If we have several article buffers, we kill them at exit.
@@ -9820,6 +10117,12 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
 
 (defun gnus-kill-or-deaden-summary (buffer)
   "Kill or deaden the summary BUFFER."
+  (when (and (buffer-name buffer)
+            (not gnus-single-article-buffer))
+    (save-excursion
+      (set-buffer buffer)
+      (gnus-kill-buffer gnus-article-buffer)
+      (gnus-kill-buffer gnus-original-article-buffer)))
   (cond (gnus-kill-summary-on-exit
         (when (and gnus-use-trees
                    (and (get-buffer buffer)
@@ -10002,7 +10305,7 @@ If FORCE, also allow jumping to articles not currently shown."
     ;; We read in the article if we have to.
     (and (not data)
         force
-        (gnus-summary-insert-subject article)
+        (gnus-summary-insert-subject article (and (vectorp force) force) t)
         (setq data (gnus-data-find article)))
     (goto-char b)
     (if (not data)
@@ -10034,15 +10337,15 @@ Given a prefix, will force an `article' buffer configuration."
            (funcall gnus-summary-display-article-function article all-header)
          (gnus-article-prepare article all-header))
       (run-hooks 'gnus-select-article-hook)
+      (unless (zerop gnus-current-article)
+       (gnus-summary-goto-subject gnus-current-article))
       (gnus-summary-recenter)
-      (gnus-summary-goto-subject article)
       (when gnus-use-trees
        (gnus-possibly-generate-tree article)
        (gnus-highlight-selected-tree article))
       ;; Successfully display article.
       (gnus-article-set-window-start
-       (cdr (assq article gnus-newsgroup-bookmarks)))
-      t)))
+       (cdr (assq article gnus-newsgroup-bookmarks))))))
 
 (defun gnus-summary-select-article (&optional all-headers force pseudo article)
   "Select the current article.
@@ -10050,6 +10353,9 @@ If ALL-HEADERS is non-nil, show all header fields.  If FORCE is
 non-nil, the article will be re-fetched even if it already present in
 the article buffer.  If PSEUDO is non-nil, pseudo-articles will also
 be displayed."
+  ;; Make sure we are in the summary buffer to work around bbdb bug.
+  (unless (eq major-mode 'gnus-summary-mode)
+    (set-buffer gnus-summary-buffer))
   (let ((article (or article (gnus-summary-article-number)))
        (all-headers (not (not all-headers))) ;Must be T or NIL.
        gnus-summary-display-article-function
@@ -10126,7 +10432,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)
@@ -10225,25 +10532,29 @@ article."
   (let ((article (gnus-summary-article-number))
        (endp nil))
     (gnus-configure-windows 'article)
-    (if (or (null gnus-current-article)
-           (null gnus-article-current)
-           (/= article (cdr gnus-article-current))
-           (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)))
-      (if endp
-         (cond (circular
-                (gnus-summary-beginning-of-article))
-               (lines
-                (gnus-message 3 "End of message"))
-               ((null lines)
-                (if (and (eq gnus-summary-goto-unread 'never)
-                         (not (gnus-summary-last-article-p article)))
-                    (gnus-summary-next-article)
-                  (gnus-summary-next-unread-article))))))
+    (if (eq (cdr (assq article gnus-newsgroup-reads)) gnus-canceled-mark)
+       (if (and (eq gnus-summary-goto-unread 'never)
+                (not (gnus-summary-last-article-p article)))
+           (gnus-summary-next-article)
+         (gnus-summary-next-unread-article))
+      (if (or (null gnus-current-article)
+             (null gnus-article-current)
+             (/= article (cdr gnus-article-current))
+             (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)))
+       (if endp
+           (cond (circular
+                  (gnus-summary-beginning-of-article))
+                 (lines
+                  (gnus-message 3 "End of message"))
+                 ((null lines)
+                  (if (and (eq gnus-summary-goto-unread 'never)
+                           (not (gnus-summary-last-article-p article)))
+                      (gnus-summary-next-article)
+                    (gnus-summary-next-unread-article)))))))
     (gnus-summary-recenter)
     (gnus-summary-position-point)))
 
@@ -10262,7 +10573,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)
@@ -10273,13 +10584,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))
 
@@ -10335,10 +10645,11 @@ Return nil if there are no unread articles."
           (setq best score
                 article (gnus-data-number (car data))))
       (setq data (cdr data)))
-    (if article
-       (gnus-summary-goto-article article)
-      (error "No unread articles"))
-    (gnus-summary-position-point)))
+    (prog1
+       (if article
+           (gnus-summary-goto-article article)
+         (error "No unread articles"))
+      (gnus-summary-position-point))))
 
 (defun gnus-summary-last-subject ()
   "Go to the last displayed subject line in the group."
@@ -10598,21 +10909,27 @@ If ALL, mark even excluded ticked and dormants as read."
     ;; buffer as a result of the new limit.
     (- total (length gnus-newsgroup-data))))
 
+(defsubst gnus-invisible-cut-children (threads)
+  (let ((num 0))
+    (while threads
+      (when (memq (mail-header-number (caar threads)) gnus-newsgroup-limit)
+       (incf num))
+      (pop threads))
+    (< num 2)))
+
 (defsubst gnus-cut-thread (thread)
   "Go forwards in the thread until we find an article that we want to display."
-  (when (eq gnus-fetch-old-headers 'some)
-    ;; Deal with old-fetched headers.
-    (while (and thread
-               (memq (mail-header-number (car thread)) 
-                     gnus-newsgroup-ancient)
-               (<= (length (cdr thread)) 1))
-      (setq thread (cadr thread))))
-  ;; Deal with sparse threads.
-  (when (or (eq gnus-build-sparse-threads 'some)
+  (when (or (eq gnus-fetch-old-headers 'some)
+           (eq gnus-build-sparse-threads 'some)
            (eq gnus-build-sparse-threads 'more))
-    (while (and thread
-               (memq (mail-header-number (car thread)) gnus-newsgroup-sparse)
-               (= (length (cdr thread)) 1))
+    ;; Deal with old-fetched headers and sparse threads.
+    (while (and
+           thread
+           (or
+            (memq (mail-header-number (car thread)) gnus-newsgroup-sparse)
+            (memq (mail-header-number (car thread)) gnus-newsgroup-ancient))
+           (or (<= (length (cdr thread)) 1)
+               (gnus-invisible-cut-children (cdr thread))))
       (setq thread (cadr thread))))
   thread)
 
@@ -10684,7 +11001,7 @@ fetch-old-headers verbiage, and so on."
           ;; children, then this article isn't visible.
           (and (memq number gnus-newsgroup-dormant)
                (= children 0))
-          ;; If this is "fetch-old-headered" and there is only one
+          ;; If this is "fetch-old-headered" and there is only one
           ;; visible child (or less), then we don't want this article.
           (and (eq gnus-fetch-old-headers 'some)
                (memq number gnus-newsgroup-ancient)
@@ -10762,7 +11079,7 @@ The difference between N and the number of articles fetched is returned."
                     (set-buffer gnus-original-article-buffer)
                     (nnheader-narrow-to-headers)
                     (prog1
-                        (mail-fetch-field "references")
+                        (message-fetch-field "references")
                       (widen)))
                 ;; It's not the current article, so we take a bet on
                 ;; the value we got from the server.
@@ -10807,16 +11124,25 @@ 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 (car (gnus-gethash message-id
-                                    gnus-newsgroup-dependencies))))
+    (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 t)
+         (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 gnus-refer-article-method)
+       (let ((gnus-override-method 
+              (and (gnus-news-group-p gnus-newsgroup-name)
+                   gnus-refer-article-method))
              number)
          ;; Start the special refer-article method, if necessary.
-         (when gnus-refer-article-method
+         (when (and gnus-refer-article-method
+                    (gnus-news-group-p gnus-newsgroup-name))
            (gnus-check-server gnus-refer-article-method))
          ;; Fetch the header, and display the article.
          (if (setq number (gnus-summary-insert-subject message-id))
@@ -10867,10 +11193,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.
@@ -10887,9 +11212,7 @@ If BACKWARD, search backward instead."
   (if (string-equal regexp "")
       (setq regexp (or gnus-last-search-regexp ""))
     (setq gnus-last-search-regexp regexp))
-  (if (gnus-summary-search-article regexp backward)
-      (gnus-article-set-window-start
-       (cdr (assq (gnus-summary-article-number) gnus-newsgroup-bookmarks)))
+  (unless (gnus-summary-search-article regexp backward)
     (error "Search failed: \"%s\"" regexp)))
 
 (defun gnus-summary-search-article-backward (regexp)
@@ -10905,46 +11228,52 @@ If BACKWARD, search backward instead."
 (defun gnus-summary-search-article (regexp &optional backward)
   "Search for an article containing REGEXP.
 Optional argument BACKWARD means do search for backward.
-gnus-select-article-hook is not called during the search."
+`gnus-select-article-hook' is not called during the search."
   (let ((gnus-select-article-hook nil) ;Disable hook.
+       (gnus-article-display-hook nil)
        (gnus-mark-article-hook nil)    ;Inhibit marking as read.
        (re-search
         (if backward
-            (function re-search-backward) (function re-search-forward)))
-       (found nil)
-       (last nil))
-    ;; Hidden thread subtrees must be searched for ,too.
-    (gnus-summary-show-all-threads)
-    ;; First of all, search current article.
-    ;; We don't want to read article again from NNTP server nor reset
-    ;; current point.
-    (gnus-summary-select-article)
-    (gnus-message 9 "Searching article: %d..." gnus-current-article)
-    (setq last gnus-current-article)
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (save-restriction
-       (widen)
-       ;; Begin search from current point.
-       (setq found (funcall re-search regexp nil t))))
-    ;; Then search next articles.
-    (while (and (not found)
-               (gnus-summary-display-article
-                (if backward (gnus-summary-find-prev)
-                  (gnus-summary-find-next))))
-      (gnus-message 9 "Searching article: %d..." gnus-current-article)
-      (gnus-eval-in-buffer-window
-       gnus-article-buffer
-       (save-restriction
-        (widen)
-        (goto-char (if backward (point-max) (point-min)))
-        (setq found (funcall re-search regexp nil t)))))
-    (message "")
-    ;; Adjust article pointer.
-    (or (eq last gnus-current-article)
-       (setq gnus-last-article last))
-    ;; Return T if found such article.
-    found))
+            're-search-backward 're-search-forward))
+       (sum (current-buffer))
+       (found nil))
+    (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
+               (re-search-backward regexp nil t)
+             (re-search-forward regexp nil t))
+           ;; We found the regexp.
+           (progn
+             (setq found 'found)
+             (beginning-of-line)
+             (set-window-start
+              (get-buffer-window (current-buffer))
+              (point))
+             (forward-line 1)
+             (set-buffer sum))
+         ;; We didn't find it, so we go to the next article.
+         (set-buffer sum)
+         (if (not (if backward (gnus-summary-find-prev)
+                    (gnus-summary-find-next)))
+             ;; No more articles.
+             (setq found t)
+           ;; Select the next article and adjust point.
+           (gnus-summary-select-article)
+           (set-buffer gnus-article-buffer)
+           (widen)
+           (goto-char (if backward (point-max) (point-min))))))
+      (gnus-message 7 ""))
+    ;; Return whether we found the regexp.
+    (when (eq found 'found)
+      (gnus-summary-show-thread)
+      (gnus-summary-goto-subject gnus-current-article)
+      (gnus-summary-position-point)
+      t)))
 
 (defun gnus-summary-find-matching (header regexp &optional backward unread
                                          not-case-fold)
@@ -11008,11 +11337,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."
@@ -11020,12 +11348,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.
@@ -11040,8 +11367,10 @@ article massaging functions being run."
     (let ((gnus-have-all-headers t)
          gnus-article-display-hook
          gnus-article-prepare-hook
+         gnus-break-pages
          gnus-visual)
       (gnus-summary-select-article nil 'force)))
+  (gnus-summary-goto-subject gnus-current-article)
 ;  (gnus-configure-windows 'article)
   (gnus-summary-position-point))
 
@@ -11111,20 +11440,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)))
-        (news-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.
@@ -11133,7 +11463,7 @@ If N is a negative number, move the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 move those articles instead.
 If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
-If SELECT-METHOD is symbol, do not move to a specific newsgroup, but
+If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
 re-spool using this method.
 
 For this function to work, both the current newsgroup and the
@@ -11153,9 +11483,9 @@ and `request-accept' functions."
         (error "The current group does not support article editing")))
   (let ((articles (gnus-summary-work-articles n))
        (prefix (gnus-group-real-prefix gnus-newsgroup-name))
-       (names '((move "move" "Moving")
-                (copy "copy" "Copying")
-                (crosspost "crosspost" "Crossposting")))
+       (names '((move "Move" "Moving")
+                (copy "Copy" "Copying")
+                (crosspost "Crosspost" "Crossposting")))
        (copy-buf (save-excursion
                    (nnheader-set-temp-buffer " *copy article*")))
        art-group to-method new-xref article to-groups)
@@ -11167,12 +11497,11 @@ and `request-accept' functions."
       (setq to-newsgroup
            (gnus-read-move-group-name
             (cadr (assq action names))
-            gnus-current-move-group articles prefix))
+            (symbol-value (intern (format "gnus-current-%s-group" action)))
+            articles prefix))
       (set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
-    (setq to-method (if select-method (list select-method "")
-                     (gnus-find-method-for-group to-newsgroup)))
-    ;;(when (equal to-newsgroup gnus-newsgroup-name)
-    ;;(error "Can't %s to the same group you're already in" action))
+    (setq to-method (or select-method 
+                       (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)))
@@ -11180,7 +11509,7 @@ and `request-accept' functions."
        (error "Can't open server %s" (car to-method)))
     (gnus-message 6 "%s to %s: %s..."
                  (caddr (assq action names))
-                 (or select-method to-newsgroup) articles)
+                 (or (car select-method) to-newsgroup) articles)
     (while articles
       (setq article (pop articles))
       (setq
@@ -11194,9 +11523,7 @@ and `request-accept' functions."
          (nth 1 (gnus-find-method-for-group
                  gnus-newsgroup-name)) ; Server
          (list 'gnus-request-accept-article
-               (if select-method
-                   (list 'quote select-method)
-                 to-newsgroup)
+               to-newsgroup (list 'quote select-method)
                (not articles))         ; Accept form
          (not articles)))              ; Only save nov last time
        ;; Copy the article.
@@ -11205,8 +11532,7 @@ and `request-accept' functions."
           (set-buffer copy-buf)
           (gnus-request-article-this-buffer article gnus-newsgroup-name)
           (gnus-request-accept-article
-           (if select-method select-method to-newsgroup)
-           (not articles))))
+           to-newsgroup select-method (not articles))))
        ;; Crosspost the article.
        ((eq action 'crosspost)
         (let ((xref (mail-header-xref (gnus-summary-article-header article))))
@@ -11222,8 +11548,7 @@ and `request-accept' functions."
             (gnus-request-article-this-buffer article gnus-newsgroup-name)
             (nnheader-replace-header "xref" new-xref)
             (gnus-request-accept-article
-             (if select-method select-method to-newsgroup)
-             (not articles)))))))
+             to-newsgroup select-method (not articles)))))))
       (if (not art-group)
          (gnus-message 1 "Couldn't %s article %s"
                        (cadr (assq action names)) article)
@@ -11233,8 +11558,8 @@ and `request-accept' functions."
                 (gnus-gethash
                  (gnus-group-prefixed-name
                   (car art-group)
-                  (if select-method (list select-method "")
-                    (gnus-find-method-for-group to-newsgroup)))
+                  (or select-method 
+                      (gnus-find-method-for-group to-newsgroup)))
                  gnus-newsrc-hashtb)))
               (info (nth 2 entry))
               (to-group (gnus-info-group info)))
@@ -11310,7 +11635,7 @@ and `request-accept' functions."
 (defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
   "Move the current article to a different newsgroup.
 If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
-If SELECT-METHOD is symbol, do not move to a specific newsgroup, but
+If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
 re-spool using this method."
   (interactive "P")
   (gnus-summary-move-article n nil select-method 'copy))
@@ -11320,7 +11645,11 @@ re-spool using this method."
   (interactive "P")
   (gnus-summary-move-article n nil nil 'crosspost))
 
-(defun gnus-summary-respool-article (&optional n respool-method)
+(defvar gnus-summary-respool-default-method nil
+  "Default method for respooling an article.  
+If nil, use to the current newsgroup method.")
+
+(defun gnus-summary-respool-article (&optional n method)
   "Respool the current article.
 The article will be squeezed through the mail spooling process again,
 which means that it will be put in some mail newsgroup or other
@@ -11334,22 +11663,35 @@ Respooling can be done both from mail groups and \"real\" newsgroups.
 In the former case, the articles in question will be moved from the
 current group into whatever groups they are destined to.  In the
 latter case, they will be copied into the relevant groups."
-  (interactive "P")
+  (interactive 
+   (list current-prefix-arg
+        (let* ((methods (gnus-methods-using 'respool))
+               (methname
+                (symbol-name (or gnus-summary-respool-default-method
+                                 (car (gnus-find-method-for-group
+                                       gnus-newsgroup-name)))))
+               (method
+                (gnus-completing-read 
+                 methname "What backend do you want to use when respooling?"
+                 methods nil t nil 'gnus-method-history))
+               ms)
+          (cond
+           ((zerop (length (setq ms (gnus-servers-using-backend method))))
+            (list (intern method) ""))
+           ((= 1 (length ms))
+            (car ms))
+           (t
+            (cdr (completing-read 
+                  "Server name: "
+                  (mapcar (lambda (m) (cons (cadr m) m)) ms) nil t)))))))
   (gnus-set-global-variables)
-  (let ((respool-methods (gnus-methods-using 'respool))
-       (methname
-        (symbol-name (car (gnus-find-method-for-group gnus-newsgroup-name)))))
-    (unless respool-method
-      (setq respool-method
-           (completing-read
-            "What method do you want to use when respooling? "
-            respool-methods nil t (cons methname 0))))
-    (unless (string= respool-method "")
-      (if (assoc (symbol-name
-                 (car (gnus-find-method-for-group gnus-newsgroup-name)))
-                respool-methods)
-         (gnus-summary-move-article n nil (intern respool-method))
-       (gnus-summary-copy-article n nil (intern respool-method))))))
+  (unless method
+    (error "No method given for respooling"))
+  (if (assoc (symbol-name
+             (car (gnus-find-method-for-group gnus-newsgroup-name)))
+            (gnus-methods-using 'respool))
+      (gnus-summary-move-article n nil method)
+    (gnus-summary-copy-article n nil method)))
 
 (defun gnus-summary-import-article (file)
   "Import a random file into a mail newsgroup."
@@ -11379,13 +11721,13 @@ 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 t)
+      (gnus-request-accept-article group nil t)
       (kill-buffer (current-buffer)))))
 
-(defun gnus-summary-expire-articles ()
+(defun gnus-summary-expire-articles (&optional now)
   "Expire all articles that are marked as expirable in the current group."
   (interactive)
   (gnus-set-global-variables)
@@ -11397,8 +11739,9 @@ latter case, they will be copied into the relevant groups."
                          (gnus-list-of-read-articles gnus-newsgroup-name)
                        (setq gnus-newsgroup-expirable
                              (sort gnus-newsgroup-expirable '<))))
-          (expiry-wait (gnus-group-get-parameter
-                        gnus-newsgroup-name 'expiry-wait))
+          (expiry-wait (if now 'immediate
+                         (gnus-group-get-parameter
+                          gnus-newsgroup-name 'expiry-wait)))
           es)
       (when expirable
        ;; There are expirable articles in this group, so we run them
@@ -11433,11 +11776,9 @@ deleted forever, right now."
   (gnus-set-global-variables)
   (or gnus-expert-user
       (gnus-y-or-n-p
-       "Are you really, really, really sure you want to expunge? ")
+       "Are you really, really, really sure you want to delete all these messages? ")
       (error "Phew!"))
-  (let ((nnmail-expiry-wait 'immediate)
-       (nnmail-expiry-wait-function nil))
-    (gnus-summary-expire-articles)))
+  (gnus-summary-expire-articles t))
 
 ;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
 (defun gnus-summary-delete-article (&optional n)
@@ -11459,7 +11800,8 @@ delete these instead."
     (if (and gnus-novice-user
             (not (gnus-y-or-n-p
                   (format "Do you really want to delete %s forever? "
-                          (if (> (length articles) 1) "these articles"
+                          (if (> (length articles) 1) 
+                              (format "these %s articles" (length articles))
                             "this article")))))
        ()
       ;; Delete the articles.
@@ -11507,9 +11849,8 @@ groups."
   (if (gnus-group-read-only-p)
       (progn
        (gnus-summary-edit-article-postpone)
-       (gnus-message
-        1 "The current newsgroup does not support article editing.")
-       (ding))
+       (gnus-error
+        1 "The current newsgroup does not support article editing."))
     (let ((buf (format "%s" (buffer-string))))
       (erase-buffer)
       (insert buf)
@@ -11524,8 +11865,17 @@ 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))))
+      (save-excursion
+       (when (get-buffer gnus-original-article-buffer)
+         (set-buffer gnus-original-article-buffer)
+         (setq gnus-original-article nil)))
+      (setq gnus-article-current nil
+           gnus-current-article nil)
       (run-hooks 'gnus-article-display-hook)
       (and (gnus-visual-p 'summary-highlight 'highlight)
           (run-hooks 'gnus-visual-mark-article-hook)))))
@@ -11555,41 +11905,6 @@ groups."
       (pp-eval-expression
        (list 'quote (mapcar 'car (nnmail-article-group 'identity)))))))
 
-;; Summary score commands.
-
-;; Suggested by boubaker@cenatls.cena.dgac.fr.
-
-(defun gnus-summary-raise-score (n)
-  "Raise the score of the current article by N."
-  (interactive "p")
-  (gnus-set-global-variables)
-  (gnus-summary-set-score (+ (gnus-summary-article-score) n)))
-
-(defun gnus-summary-set-score (n)
-  "Set the score of the current article to N."
-  (interactive "p")
-  (gnus-set-global-variables)
-  (save-excursion
-    (gnus-summary-show-thread)
-    (let ((buffer-read-only nil))
-      ;; Set score.
-      (gnus-summary-update-mark
-       (if (= n (or gnus-summary-default-score 0)) ? 
-        (if (< n (or gnus-summary-default-score 0))
-            gnus-score-below-mark gnus-score-over-mark)) 'score))
-    (let* ((article (gnus-summary-article-number))
-          (score (assq article gnus-newsgroup-scored)))
-      (if score (setcdr score n)
-       (setq gnus-newsgroup-scored
-             (cons (cons article n) gnus-newsgroup-scored))))
-    (gnus-summary-update-line)))
-
-(defun gnus-summary-current-score ()
-  "Return the score of the current article."
-  (interactive)
-  (gnus-set-global-variables)
-  (message "%s" (gnus-summary-article-score)))
-
 ;; Summary marking commands.
 
 (defun gnus-summary-kill-same-subject-and-select (&optional unmark)
@@ -11791,9 +12106,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")
@@ -11847,32 +12160,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)
@@ -11942,9 +12257,10 @@ marked."
   (beginning-of-line)
   (let ((forward (cdr (assq type gnus-summary-mark-positions)))
        (buffer-read-only nil))
-    (when forward
+    (when (and forward
+              (<= (+ forward (point)) (point-max)))
       ;; Go to the right position on the line.
-      (forward-char forward)
+      (goto-char (+ forward (point)))
       ;; Replace the old mark with the new mark.
       (subst-char-in-region (point) (1+ (point)) (following-char) mark)
       ;; Optionally update the marks by some user rule.
@@ -12201,10 +12517,11 @@ If ALL is non-nil, also mark ticked and dormant articles as read."
   (interactive "P")
   (gnus-set-global-variables)
   (save-excursion
-    (let ((beg (point)))
-      ;; We check that there are unread articles.
-      (when (or all (gnus-summary-find-prev))
-       (gnus-summary-catchup all t beg))))
+    (gnus-save-hidden-threads
+      (let ((beg (point)))
+       ;; We check that there are unread articles.
+       (when (or all (gnus-summary-find-prev))
+         (gnus-summary-catchup all t beg)))))
   (gnus-summary-position-point))
 
 (defun gnus-summary-catchup-all (&optional quietly)
@@ -12258,26 +12575,27 @@ with that article."
                 (gnus-simplify-subject-fuzzy
                  (mail-header-subject (gnus-data-header (car data)))))
                (t nil)))
+        (end-point (save-excursion
+                     (if (gnus-summary-go-to-next-thread) 
+                         (point) (point-max))))
         articles)
-    (if (not data)
-       ()                              ; This article doesn't exist.
-      (while data
-       (and (or (not top-subject)
-                (string= top-subject
-                         (if (eq gnus-thread-operation-ignore-subject 'fuzzy)
-                             (gnus-simplify-subject-fuzzy
-                              (mail-header-subject
-                               (gnus-data-header (car data))))
-                           (gnus-simplify-subject-re
-                            (mail-header-subject
-                             (gnus-data-header (car data)))))))
-            (setq articles (cons (gnus-data-number (car data)) articles)))
-       (if (and (setq data (cdr data))
-                (> (gnus-data-level (car data)) top-level))
-           ()
-         (setq data nil)))
-      ;; Return the list of articles.
-      (nreverse articles))))
+    (while (and data
+               (< (gnus-data-pos (car data)) end-point))
+      (when (or (not top-subject)
+               (string= top-subject
+                        (if (eq gnus-thread-operation-ignore-subject 'fuzzy)
+                            (gnus-simplify-subject-fuzzy
+                             (mail-header-subject
+                              (gnus-data-header (car data))))
+                          (gnus-simplify-subject-re
+                           (mail-header-subject
+                            (gnus-data-header (car data)))))))
+       (push (gnus-data-number (car data)) articles))
+      (unless (and (setq data (cdr data))
+                  (> (gnus-data-level (car data)) top-level))
+       (setq data nil)))
+    ;; Return the list of articles.
+    (nreverse articles)))
 
 (defun gnus-summary-rethread-current ()
   "Rethread the thread the current article is part of."
@@ -12335,8 +12653,8 @@ is non-nil or the Subject: of both articles are the same."
        (set-buffer gnus-summary-buffer)
        (gnus-summary-unmark-all-processable)
        (gnus-summary-rethread-current)
-       (message "Article %d is now the child of article %d."
-                current-article parent-article)))))
+       (gnus-message 3 "Article %d is now the child of article %d."
+                     current-article parent-article)))))
 
 (defun gnus-summary-toggle-threads (&optional arg)
   "Toggle showing conversation threads.
@@ -12541,8 +12859,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.
@@ -12633,15 +12951,19 @@ Argument REVERSE means reverse order."
 (defun gnus-sortable-date (date)
   "Make sortable string by string-lessp from DATE.
 Timezone package is used."
-  (let* ((date (timezone-fix-time date nil nil)) ;[Y M D H M S]
-        (year (aref date 0))
-        (month (aref date 1))
-        (day (aref date 2)))
-    (timezone-make-sortable-date
-     year month day
-     (timezone-make-time-string
-      (aref date 3) (aref date 4) (aref date 5)))))
-
+  (condition-case ()
+      (progn
+       (setq date (inline (timezone-fix-time 
+                           date nil 
+                           (aref (inline (timezone-parse-date date)) 4))))
+       (inline
+         (timezone-make-sortable-date
+          (aref date 0) (aref date 1) (aref date 2)
+          (inline
+            (timezone-make-time-string
+             (aref date 3) (aref date 4) (aref date 5))))))
+    (error "")))
+  
 ;; Summary saving commands.
 
 (defun gnus-summary-save-article (&optional n not-saved)
@@ -12654,6 +12976,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
@@ -12666,33 +12990,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)))
-           (gnus-article-hide-headers nil 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)))))
+                (or gnus-saved-headers gnus-visible-headers))
+               (gnus-article-buffer save-buffer))
+           (gnus-article-hide-headers 1 t)))
        (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))
 
@@ -12790,8 +13118,21 @@ save those articles instead."
 (defun gnus-read-move-group-name (prompt default articles prefix)
   "Read a group name."
   (let* ((split-name (gnus-get-split-value gnus-move-split-methods))
+        (minibuffer-confirm-incomplete nil) ; XEmacs
+        group-map
+        (dum (mapatoms
+              (lambda (g) 
+                (and (boundp g)
+                     (symbol-name g)
+                     (memq 'respool
+                           (assoc (symbol-name
+                                   (car (gnus-find-method-for-group
+                                         (symbol-name g))))
+                                  gnus-valid-select-methods))
+                     (push (list (symbol-name g)) group-map)))
+              gnus-active-hashtb))
         (prom
-         (format "Where do you want to %s %s? "
+         (format "%s %s to:"
                  prompt
                  (if (> (length articles) 1)
                      (format "these %d articles" (length articles))
@@ -12799,25 +13140,33 @@ save those articles instead."
         (to-newsgroup
          (cond
           ((null split-name)
-           (completing-read
-            (concat prom
-                    (if default
-                        (format "(default %s) " default)
-                      ""))
-            gnus-active-hashtb nil nil prefix))
+           (gnus-completing-read default prom
+                                 group-map nil nil prefix
+                                 'gnus-group-history))
           ((= 1 (length split-name))
-           (completing-read prom gnus-active-hashtb
-                            nil nil (cons (car split-name) 0)))
+           (gnus-completing-read (car split-name) prom group-map
+                                 nil nil nil
+                                 'gnus-group-history))
           (t
-           (completing-read
-            prom (mapcar (lambda (el) (list el)) (nreverse split-name)))))))
-
+           (gnus-completing-read nil prom 
+                                 (mapcar (lambda (el) (list el))
+                                         (nreverse split-name))
+                                 nil nil nil
+                                 'gnus-group-history)))))
     (when to-newsgroup
       (if (or (string= to-newsgroup "")
              (string= to-newsgroup prefix))
          (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))
 
@@ -12835,20 +13184,25 @@ 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 (mapcar (lambda (el) (list el))
-                                    (nreverse split-name)))
-           (let ((result (completing-read
-                          (concat prompt " ") split-name nil nil)))
-             (concat gnus-article-save-directory
-                     (if (string= result "")
-                         (caar split-name)
-                       result)))))))
+           (setq split-name (nreverse split-name))
+           (let (result)
+             (let ((file-name-history (nconc split-name file-name-history)))
+               (setq result
+                     (read-file-name
+                      (concat prompt " (`M-p' for defaults) ")
+                      gnus-article-save-directory
+                      (car split-name))))
+             (car (push result file-name-history)))))))
     ;; If we have read a directory, we append the default file name.
     (when (file-directory-p file)
       (setq file (concat (file-name-as-directory file)
@@ -12865,8 +13219,7 @@ save those articles instead."
 (defun gnus-summary-save-in-rmail (&optional filename)
   "Append this article to Rmail file.
 Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
+Directory to save to is default to `gnus-article-save-directory'."
   (interactive)
   (gnus-set-global-variables)
   (let ((default-name
@@ -12879,20 +13232,18 @@ is initialized from the SAVEDIR environment variable."
                (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)))
 
 (defun gnus-summary-save-in-mail (&optional filename)
   "Append this article to Unix mail file.
 Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
+Directory to save to is default to `gnus-article-save-directory'."
   (interactive)
   (gnus-set-global-variables)
   (let ((default-name
@@ -12909,23 +13260,21 @@ is initialized from the SAVEDIR environment variable."
                            (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)))
 
 (defun gnus-summary-save-in-file (&optional filename)
   "Append this article to file.
 Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
+Directory to save to is default to `gnus-article-save-directory'."
   (interactive)
   (gnus-set-global-variables)
   (let ((default-name
@@ -12938,20 +13287,18 @@ is initialized from the SAVEDIR environment variable."
                (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)))
 
 (defun gnus-summary-save-body-in-file (&optional filename)
   "Append this article body to a file.
 Optional argument FILENAME specifies file name.
-The directory to save in defaults to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
+The directory to save in defaults to `gnus-article-save-directory'."
   (interactive)
   (gnus-set-global-variables)
   (let ((default-name
@@ -12964,15 +13311,14 @@ is initialized from the SAVEDIR environment variable."
                (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-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)))
 
@@ -12988,11 +13334,10 @@ is initialized from the SAVEDIR environment variable."
                              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
@@ -13048,9 +13393,9 @@ is initialized from the SAVEDIR environment variable."
                  ": " (or (cdr (assq 'execute (car pslist))) "") "\n")
          (setq e (point))
          (forward-line -1)             ; back to `b'
-         (add-text-properties
-          b e (list 'gnus-number gnus-reffed-article-number
-                    gnus-mouse-face-prop gnus-mouse-face))
+         (gnus-add-text-properties
+          b (1- e) (list 'gnus-number gnus-reffed-article-number
+                         gnus-mouse-face-prop gnus-mouse-face))
          (gnus-data-enter
           after-article gnus-reffed-article-number
           gnus-unread-mark b (car pslist) 0 (- e b))
@@ -13073,13 +13418,20 @@ is initialized from the SAVEDIR environment variable."
   (save-excursion
     (gnus-article-setup-buffer)
     (set-buffer gnus-article-buffer)
+    (setq buffer-read-only nil)
     (let ((command (if automatic command (read-string "Command: " command)))
-         (buffer-read-only nil))
+         ;; Just binding this here doesn't help, because there might
+         ;; be output from the process after exiting the scope of 
+         ;; this `let'.
+         ;; (buffer-read-only nil)
+         )
       (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."
@@ -13135,6 +13487,8 @@ is initialized from the SAVEDIR environment variable."
     "\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-b" gnus-bug)
 
   (substitute-key-definition
@@ -13217,7 +13571,7 @@ The following commands are available:
 ;; from the head of the article.
 (defun gnus-article-set-window-start (&optional line)
   (set-window-start
-   (get-buffer-window gnus-article-buffer)
+   (get-buffer-window gnus-article-buffer t)
    (save-excursion
      (set-buffer gnus-article-buffer)
      (goto-char (point-min))
@@ -13276,7 +13630,9 @@ The following commands are available:
                      (setq do-update-line article)
                      (setq article (mail-header-id header))
                      (let ((gnus-override-method gnus-refer-article-method))
-                       (gnus-read-header article)))
+                       (gnus-read-header article))
+                     (setq gnus-newsgroup-sparse
+                           (delq article gnus-newsgroup-sparse)))
                     ((vectorp header)
                      ;; It's a real article.
                      (setq article (mail-header-id header)))
@@ -13297,8 +13653,19 @@ The following commands are available:
                            (gnus-group-enter-directory dir)))))))))
 
          (cond
+          ;; Refuse to select canceled articles.
+          ((and (numberp article)
+                gnus-summary-buffer
+                (get-buffer gnus-summary-buffer)
+                (buffer-name (get-buffer gnus-summary-buffer))
+                (eq (cdr (save-excursion
+                           (set-buffer gnus-summary-buffer)
+                           (assq article gnus-newsgroup-reads)))
+                    gnus-canceled-mark))
+           nil)
           ;; We first check `gnus-original-article-buffer'.
           ((and (get-buffer gnus-original-article-buffer)
+                (numberp article)
                 (save-excursion
                   (set-buffer gnus-original-article-buffer)
                   (and (equal (car gnus-original-article) group)
@@ -13324,6 +13691,7 @@ The following commands are available:
              (if (gnus-request-article article group (current-buffer))
                  (progn
                    (and gnus-keep-backlog
+                        (numberp article)
                         (gnus-backlog-enter-article
                          group article (current-buffer)))
                    'article))))
@@ -13333,6 +13701,7 @@ The following commands are available:
       ;; Take the article from the original article buffer
       ;; and place it in the buffer it's supposed to be in.
       (when (and (get-buffer gnus-article-buffer)
+                ;;(numberp article)
                 (equal (buffer-name (current-buffer))
                        (buffer-name (get-buffer gnus-article-buffer))))
        (save-excursion
@@ -13349,17 +13718,23 @@ The following commands are available:
          (setq gnus-original-article (cons group article))))
     
       ;; Update sparse articles.
-      (when do-update-line
-       (save-excursion
+      (when (and do-update-line
+                (or (numberp article)
+                    (stringp article)))
+       (let ((buf (current-buffer)))
          (set-buffer gnus-summary-buffer)
          (gnus-summary-update-article do-update-line)
-         (gnus-summary-goto-subject do-update-line)
+         (gnus-summary-goto-subject do-update-line nil t)
          (set-window-point (get-buffer-window (current-buffer) t)
-                           (point)))))))
+                           (point))
+         (set-buffer buf))))))
 
 (defun gnus-read-header (id &optional header)
   "Read the headers of article ID and enter them into the Gnus system."
   (let ((group gnus-newsgroup-name)
+       (gnus-override-method 
+        (and (gnus-news-group-p gnus-newsgroup-name)
+             gnus-refer-article-method))       
        where)
     ;; First we check to see whether the header in question is already
     ;; fetched.
@@ -13373,14 +13748,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))
@@ -13406,11 +13776,24 @@ The following commands are available:
                ;; numbers for this article.
                (mail-header-set-number header gnus-reffed-article-number))
            (decf gnus-reffed-article-number)
+           (gnus-remove-header (mail-header-number header))
            (push header gnus-newsgroup-headers)
            (setq gnus-current-headers header)
            (push (mail-header-number header) gnus-newsgroup-limit))
          header)))))
 
+(defun gnus-remove-header (number)
+  "Remove header NUMBER from `gnus-newsgroup-headers'."
+  (if (and gnus-newsgroup-headers
+          (= number (mail-header-number (car gnus-newsgroup-headers))))
+      (pop gnus-newsgroup-headers)
+    (let ((headers gnus-newsgroup-headers))
+      (while (and (cdr headers)
+                 (not (= number (mail-header-number (cadr headers)))))
+       (pop headers))
+      (when (cdr headers)
+       (setcdr headers (cddr headers))))))
+
 (defun gnus-article-prepare (article &optional all-headers header)
   "Prepare ARTICLE in article mode buffer.
 ARTICLE should either be an article number or a Message-ID.
@@ -13451,10 +13834,8 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                (setq gnus-current-article article)
                (gnus-summary-mark-article article gnus-canceled-mark))
              (unless (memq article gnus-newsgroup-sparse)
-               (gnus-message
-                1 "No such article (may have expired or been canceled)")
-               (ding)
-               nil))
+               (gnus-error
+                1 "No such article (may have expired or been canceled)")))
          (if (or (eq result 'pseudo) (eq result 'nneething))
              (progn
                (save-excursion
@@ -13508,22 +13889,24 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                        (memq article gnus-newsgroup-marked)
                        (memq article gnus-newsgroup-dormant)
                        (memq article gnus-newsgroup-unreads)))))
-           ;; Hooks for getting information from the article.
-           ;; This hook must be called before being narrowed.
-           (let (buffer-read-only)
-             (run-hooks 'internal-hook)
-             (run-hooks 'gnus-article-prepare-hook)
-             ;; Decode MIME message.
-             (if gnus-show-mime
-                 (if (or (not gnus-strict-mime)
-                         (gnus-fetch-field "Mime-Version"))
-                     (funcall gnus-show-mime-method)
-                   (funcall gnus-decode-encoded-word-method)))
-             ;; Perform the article display hooks.
-             (run-hooks 'gnus-article-display-hook))
-           ;; Do page break.
-           (goto-char (point-min))
-           (and gnus-break-pages (gnus-narrow-to-page))
+           (when (or (numberp article)
+                     (stringp article))
+             ;; Hooks for getting information from the article.
+             ;; This hook must be called before being narrowed.
+             (let (buffer-read-only)
+               (run-hooks 'internal-hook)
+               (run-hooks 'gnus-article-prepare-hook)
+               ;; Decode MIME message.
+               (if gnus-show-mime
+                   (if (or (not gnus-strict-mime)
+                           (gnus-fetch-field "Mime-Version"))
+                       (funcall gnus-show-mime-method)
+                     (funcall gnus-decode-encoded-word-method)))
+               ;; Perform the article display hooks.
+               (run-hooks 'gnus-article-display-hook))
+             ;; Do page break.
+             (goto-char (point-min))
+             (and gnus-break-pages (gnus-narrow-to-page)))
            (gnus-set-mode-line 'article)
            (gnus-configure-windows 'article)
            (goto-char (point-min))
@@ -13544,12 +13927,25 @@ Provided for backwards compatibility."
       gnus-inhibit-hiding
       (gnus-article-hide-headers)))
 
+(defsubst gnus-article-header-rank ()
+  "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
+  (let ((list gnus-sorted-header-list)
+       (i 0))
+    (while list
+      (when (looking-at (car list))
+       (setq list nil))
+      (setq list (cdr list))
+      (incf i))
+    i))
+
 (defun gnus-article-hide-headers (&optional arg delete)
   "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")
-  (unless (gnus-article-check-hidden-text 'headers arg)
+  (interactive (gnus-hidden-arg))
+  (if (gnus-article-check-hidden-text 'headers arg)
+      ;; Show boring headers as well.
+      (gnus-article-show-hidden-text 'boring-headers)
     ;; This function might be inhibited.
     (unless gnus-inhibit-hiding
       (save-excursion
@@ -13558,6 +13954,7 @@ always hide."
          (let ((buffer-read-only nil)
                (props (nconc (list 'gnus-type 'headers)
                              gnus-hidden-properties))
+               (max (1+ (length gnus-sorted-header-list)))
                (ignored (when (not (stringp gnus-visible-headers))
                           (cond ((stringp gnus-ignored-headers)
                                  gnus-ignored-headers)
@@ -13570,6 +13967,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)
@@ -13578,7 +13976,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)
@@ -13592,52 +13992,30 @@ always hide."
              (beginning-of-line)
              ;; We add the headers we want to keep to a list and delete
              ;; them from the buffer.
-             (if (or (and visible (looking-at visible))
-                     (and ignored (not (looking-at ignored))))
-                 (progn
-                   (push (buffer-substring
-                          (setq beg (point))
-                          (progn
-                            (forward-line 1)
-                            ;; Be sure to get multi-line headers...
-                            (re-search-forward "^[^ \t]*:" nil t)
-                            (beginning-of-line)
-                            (point)))
-                         want-list)
-                   (delete-region beg (point)))
-               (forward-line 1)))
-           ;; Sort the headers that we want to display.
-           (setq want-list (sort want-list 'gnus-article-header-less))
-           (goto-char (point-min))
-           (while want-list
-             (insert (pop want-list)))
-           ;; We make the unwanted headers invisible.
-           (if delete
-               (delete-region (point-min) (point-max))
-             ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
-             (gnus-hide-text-type (point) (point-max) 'headers))))))))
-
-(defsubst gnus-article-header-rank (header)
-  "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
-  (let ((list gnus-sorted-header-list)
-       (i 0))
-    (while list
-      (when (string-match (car list) header)
-       (setq list nil))
-      (setq list (cdr list))
-      (incf i))
-    i))
-
-(defun gnus-article-header-less (h1 h2)
-  "Say whether string H1 is \"less\" than string H2."
-  (< (gnus-article-header-rank h1)
-     (gnus-article-header-rank h2)))
+             (gnus-put-text-property 
+              (point) (1+ (point)) 'message-rank
+              (if (or (and visible (looking-at visible))
+                      (and ignored
+                           (not (looking-at ignored))))
+                  (gnus-article-header-rank) 
+                (+ 2 max)))
+             (forward-line 1))
+           (message-sort-headers-1)
+           (when (setq beg (text-property-any 
+                            (point-min) (point-max) 'message-rank (+ 2 max)))
+             ;; We make the unwanted headers invisible.
+             (if delete
+                 (delete-region beg (point-max))
+               ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
+               (gnus-hide-text-type beg (point-max) 'headers))
+             ;; Work around XEmacs lossage.
+             (gnus-put-text-property (point-min) beg 'invisible nil))))))))
 
 (defun gnus-article-hide-boring-headers (&optional arg)
   "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)
@@ -13665,16 +14043,16 @@ always hide."
                 'boring-headers)))
             ;; Hide boring Newsgroups header.
             ((eq elem 'newsgroups)
-             (when (equal (mail-fetch-field "newsgroups")
+             (when (equal (message-fetch-field "newsgroups")
                           (gnus-group-real-name gnus-newsgroup-name))
                (gnus-article-hide-header "newsgroups")))
             ((eq elem 'followup-to)
-             (when (equal (mail-fetch-field "followup-to")
-                          (mail-fetch-field "newsgroups"))
+             (when (equal (message-fetch-field "followup-to")
+                          (message-fetch-field "newsgroups"))
                (gnus-article-hide-header "followup-to")))
             ((eq elem 'reply-to)
-             (let ((from (mail-fetch-field "from"))
-                   (reply-to (mail-fetch-field "reply-to")))
+             (let ((from (message-fetch-field "from"))
+                   (reply-to (message-fetch-field "reply-to")))
                (when (and
                       from reply-to
                       (equal 
@@ -13683,7 +14061,7 @@ always hide."
                                        reply-to))))
                  (gnus-article-hide-header "reply-to"))))
             ((eq elem 'date)
-             (let ((date (mail-fetch-field "date")))
+             (let ((date (message-fetch-field "date")))
                (when (and date
                           (< (gnus-days-between date (current-time-string))
                              4))
@@ -13712,17 +14090,18 @@ always hide."
       (while (search-forward "\b" nil t)
        (let ((next (following-char))
              (previous (char-after (- (point) 2))))
-         (cond ((eq next previous)
-                (put-text-property (- (point) 2) (point) 'invisible t)
-                (put-text-property (point) (1+ (point)) 'face 'bold))
-               ((eq next ?_)
-                (put-text-property (1- (point)) (1+ (point)) 'invisible t)
-                (put-text-property
-                 (- (point) 2) (1- (point)) 'face 'underline))
-               ((eq previous ?_)
-                (put-text-property (- (point) 2) (point) 'invisible t)
-                (put-text-property
-                 (point) (1+ (point))  'face 'underline))))))))
+         (cond 
+          ((eq next previous)
+           (gnus-put-text-property (- (point) 2) (point) 'invisible t)
+           (gnus-put-text-property (point) (1+ (point)) 'face 'bold))
+          ((eq next ?_)
+           (gnus-put-text-property (1- (point)) (1+ (point)) 'invisible t)
+           (gnus-put-text-property
+            (- (point) 2) (1- (point)) 'face 'underline))
+          ((eq previous ?_)
+           (gnus-put-text-property (- (point) 2) (point) 'invisible t)
+           (gnus-put-text-property
+            (point) (1+ (point))       'face 'underline))))))))
 
 (defun gnus-article-word-wrap ()
   "Format too long lines."
@@ -13781,7 +14160,7 @@ always hide."
          from)
       (save-restriction
        (nnheader-narrow-to-headers)
-       (setq from (mail-fetch-field "from"))
+       (setq from (message-fetch-field "from"))
        (goto-char (point-min))
        (when (and gnus-article-x-face-command
                   (or force
@@ -13806,25 +14185,33 @@ 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")))))))))
 
-(defun gnus-headers-decode-quoted-printable ()
+(defalias 'gnus-headers-decode-quoted-printable 'gnus-decode-rfc1522)
+(defun gnus-decode-rfc1522 ()
   "Hack to remove QP encoding from headers."
   (let ((case-fold-search t)
        (inhibit-point-motion-hooks t)
+       (buffer-read-only nil)
        string)
-    (goto-char (point-min))
-    (while (re-search-forward "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
-      (setq string (match-string 1))
-      (narrow-to-region (match-beginning 0) (match-end 0))
-      (delete-region (point-min) (point-max))
-      (insert string)
-      (gnus-mime-decode-quoted-printable (goto-char (point-min)) (point-max))
-      (subst-char-in-region (point-min) (point-max) ?_ ? )
-      (widen)
-      (goto-char (point-min)))))
+    (save-restriction
+      (narrow-to-region
+       (goto-char (point-min))
+       (or (search-forward "\n\n" nil t) (point-max)))
+
+      (while (re-search-forward 
+             "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
+       (setq string (match-string 1))
+       (narrow-to-region (match-beginning 0) (match-end 0))
+       (delete-region (point-min) (point-max))
+       (insert string)
+       (gnus-mime-decode-quoted-printable (goto-char (point-min)) (point-max))
+       (subst-char-in-region (point-min) (point-max) ?_ ? )
+       (widen)
+       (goto-char (point-min))))))
 
 (defun gnus-article-de-quoted-unreadable (&optional force)
   "Do a naive translation of a quoted-printable-encoded article.
@@ -13839,24 +14226,26 @@ or not."
     (let ((case-fold-search t)
          (buffer-read-only nil)
          (type (gnus-fetch-field "content-transfer-encoding")))
+      (gnus-decode-rfc1522)
       (when (or force
-               (and type (string-match "quoted-printable" type)))
-       (gnus-headers-decode-quoted-printable)
+               (and type (string-match "quoted-printable" (downcase type))))
        (goto-char (point-min))
        (search-forward "\n\n" nil 'move)
        (gnus-mime-decode-quoted-printable (point) (point-max))))))
 
 (defun gnus-mime-decode-quoted-printable (from to)
   "Decode Quoted-Printable in the region between FROM and TO."
+  (interactive "r")
   (goto-char from)
   (while (search-forward "=" to t)
     (cond ((eq (following-char) ?\n)
           (delete-char -1)
           (delete-char 1))
          ((looking-at "[0-9A-F][0-9A-F]")
-          (delete-char -1)
-          (insert (hexl-hex-string-to-integer
-                   (buffer-substring (point) (+ 2 (point)))))
+          (subst-char-in-region
+           (1- (point)) (point) ?=
+           (hexl-hex-string-to-integer
+            (buffer-substring (point) (+ 2 (point)))))
           (delete-char 2))
          ((looking-at "=")
           (delete-char 1))
@@ -13866,7 +14255,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)
@@ -13901,7 +14290,7 @@ always hide."
   "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)
@@ -13921,9 +14310,19 @@ always hide."
        (while (looking-at "[ \t]$")
          (gnus-delete-line))))))
 
+(defvar mime::preview/content-list)
+(defvar mime::preview-content-info/point-min)
 (defun gnus-narrow-to-signature ()
   "Narrow to the signature."
   (widen)
+  (if (and (boundp 'mime::preview/content-list)
+          mime::preview/content-list)
+      (let ((pcinfo (car (last mime::preview/content-list))))
+       (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)
@@ -13937,17 +14336,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."
@@ -14005,7 +14416,8 @@ how much time has lapsed since DATE."
         (date (and (vectorp header) (mail-header-date header)))
         (date-regexp "^Date: \\|^X-Sent: ")
         (now (current-time))
-        (inhibit-point-motion-hooks t))
+        (inhibit-point-motion-hooks t)
+        bface eface)
     (when (and date (not (string= date "")))
       (save-excursion
        (set-buffer gnus-article-buffer)
@@ -14013,83 +14425,101 @@ how much time has lapsed since DATE."
          (nnheader-narrow-to-headers)
          (let ((buffer-read-only nil))
            ;; Delete any old Date headers.
-           (if (zerop (message-remove-header date-regexp t))
-               (beginning-of-line)
+           (if (re-search-forward date-regexp nil t)
+               (progn
+                 (setq bface (get-text-property (gnus-point-at-bol) 'face)
+                       eface (get-text-property (1- (gnus-point-at-eol))
+                                                'face))
+                 (message-remove-header date-regexp t)
+                 (beginning-of-line))
              (goto-char (point-max)))
-           (insert
-            (cond
-             ;; Convert to the local timezone.  We have to slap a
-             ;; `condition-case' round the calls to the timezone
-             ;; functions since they aren't particularly resistant to
-             ;; buggy dates.
-             ((eq type 'local)
-              (concat "Date: " (condition-case ()
-                                   (timezone-make-date-arpa-standard date)
-                                 (error date))
-                      "\n"))
-             ;; Convert to Universal Time.
-             ((eq type 'ut)
-              (concat "Date: "
-                      (condition-case ()
-                          (timezone-make-date-arpa-standard date nil "UT")
-                        (error date))
-                      "\n"))
-             ;; Get the original date from the article.
-             ((eq type 'original)
-              (concat "Date: " date "\n"))
-             ;; Do an X-Sent lapsed format.
-             ((eq type 'lapsed)
-              ;; If the date is seriously mangled, the timezone
-              ;; functions are liable to bug out, so we condition-case
-              ;; the entire thing.
-              (let* ((real-time
-                      (condition-case ()
-                          (gnus-time-minus
-                           (gnus-encode-date
-                            (timezone-make-date-arpa-standard
-                             (current-time-string now)
-                             (current-time-zone now) "UT"))
-                           (gnus-encode-date
-                            (timezone-make-date-arpa-standard
-                             date nil "UT")))
-                        (error '(0 0))))
-                     (real-sec (+ (* (float (car real-time)) 65536)
-                                  (cadr real-time)))
-                     (sec (abs real-sec))
-                     num prev)
-                (if (zerop sec)
-                    "X-Sent: Now\n"
-                  (concat
-                   "X-Sent: "
-                   ;; This is a bit convoluted, but basically we go
-                   ;; through the time units for years, weeks, etc,
-                   ;; and divide things to see whether that results
-                   ;; in positive answers.
-                   (mapconcat
-                    (lambda (unit)
-                      (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
-                          ;; The (remaining) seconds are too few to
-                          ;; be divided into this time unit.
-                          ""
-                        ;; It's big enough, so we output it.
-                        (setq sec (- sec (* num (cdr unit))))
-                        (prog1
-                            (concat (if prev ", " "") (int-to-string
-                                                       (floor num))
-                                    " " (symbol-name (car unit))
-                                    (if (> num 1) "s" ""))
-                          (setq prev t))))
-                    gnus-article-time-units "")
-                   ;; If dates are odd, then it might appear like the
-                   ;; article was sent in the future.
-                   (if (> real-sec 0)
-                       " ago\n"
-                     " in the future\n")))))
-             (t
-              (error "Unknown conversion type: %s" type)))))
-         ;; Do highlighting.
-         (when (and highlight (gnus-visual-p 'article-highlight 'highlight))
-           (gnus-article-highlight-headers)))))))
+           (insert (gnus-make-date-line date type))
+           ;; Do highlighting.
+           (forward-line -1)
+           (when (and (gnus-visual-p 'article-highlight 'highlight)
+                      (looking-at "\\([^:]+\\): *\\(.*\\)$"))
+             (gnus-put-text-property (match-beginning 1) (match-end 1)
+                                'face bface)
+             (gnus-put-text-property (match-beginning 2) (match-end 2)
+                                'face eface))))))))
+
+(defun gnus-make-date-line (date type)
+  "Return a DATE line of TYPE."
+  (cond
+   ;; Convert to the local timezone.  We have to slap a
+   ;; `condition-case' round the calls to the timezone
+   ;; functions since they aren't particularly resistant to
+   ;; buggy dates.
+   ((eq type 'local)
+    (concat "Date: " (condition-case ()
+                        (timezone-make-date-arpa-standard date)
+                      (error date))
+           "\n"))
+   ;; Convert to Universal Time.
+   ((eq type 'ut)
+    (concat "Date: "
+           (condition-case ()
+               (timezone-make-date-arpa-standard date nil "UT")
+             (error date))
+           "\n"))
+   ;; Get the original date from the article.
+   ((eq type 'original)
+    (concat "Date: " date "\n"))
+   ;; Do an X-Sent lapsed format.
+   ((eq type 'lapsed)
+    ;; If the date is seriously mangled, the timezone
+    ;; functions are liable to bug out, so we condition-case
+    ;; the entire thing.
+    (let* ((now (current-time))
+          (real-time
+           (condition-case ()
+               (gnus-time-minus
+                (gnus-encode-date
+                 (timezone-make-date-arpa-standard
+                  (current-time-string now)
+                  (current-time-zone now) "UT"))
+                (gnus-encode-date
+                 (timezone-make-date-arpa-standard
+                  date nil "UT")))
+             (error '(0 0))))
+          (real-sec (+ (* (float (car real-time)) 65536)
+                       (cadr real-time)))
+          (sec (abs real-sec))
+          num prev)
+      (cond
+       ((equal real-time '(0 0))
+       "X-Sent: Unknown\n")
+       ((zerop sec)
+       "X-Sent: Now\n")
+       (t
+       (concat
+        "X-Sent: "
+        ;; This is a bit convoluted, but basically we go
+        ;; through the time units for years, weeks, etc,
+        ;; and divide things to see whether that results
+        ;; in positive answers.
+        (mapconcat
+         (lambda (unit)
+           (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
+               ;; The (remaining) seconds are too few to
+               ;; be divided into this time unit.
+               ""
+             ;; It's big enough, so we output it.
+             (setq sec (- sec (* num (cdr unit))))
+             (prog1
+                 (concat (if prev ", " "") (int-to-string
+                                            (floor num))
+                         " " (symbol-name (car unit)) 
+                         (if (> num 1) "s" ""))
+               (setq prev t))))
+         gnus-article-time-units "")
+        ;; If dates are odd, then it might appear like the
+        ;; article was sent in the future.
+        (if (> real-sec 0)
+            " ago\n"
+          " in the future\n"))))))
+   (t
+    (error "Unknown conversion type: %s" type))))
 
 (defun gnus-article-date-local (&optional highlight)
   "Convert the current article date to the local timezone."
@@ -14113,7 +14543,7 @@ function and want to see what the date was before converting."
   (if (gnus-visual-p 'article-highlight 'highlight)
       (gnus-article-highlight-some)))
 
-;; Article savers.
+;;; Article savers.
 
 (defun gnus-output-to-rmail (file-name)
   "Append the current article to an Rmail file named FILE-NAME."
@@ -14168,20 +14598,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
       ;;