*** empty log message ***
[gnus] / lisp / gnus.el
index 3ebec59..9fb10de 100644 (file)
@@ -35,6 +35,9 @@
 
 (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.
 
@@ -130,10 +133,12 @@ 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.")
 
@@ -272,13 +277,11 @@ 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.")
 
-(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.")
+(defvar gnus-article-save-directory gnus-directory
+  "*Name of the directory articles will be saved in (default \"~/News\").")
 
-(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-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.
@@ -600,9 +603,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.")
 
@@ -969,7 +969,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>.
@@ -1207,13 +1208,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)
@@ -1468,7 +1470,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-headers-decode-quoted-printable)
+(add-hook 'gnus-parse-headers-hook 'gnus-decode-rfc1522)
 
 (defvar gnus-exit-group-hook nil
   "*A hook called when exiting (not quitting) summary mode.")
@@ -1533,9 +1535,23 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
 \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.")
 
@@ -1581,6 +1597,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)
@@ -1694,7 +1712,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)
 
@@ -1702,13 +1721,13 @@ 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.76"
+(defconst gnus-version "September Gnus v0.90"
   "Version number 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"))
+  '((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.")
 
 (defvar gnus-group-buffer "*Group*")
@@ -2010,7 +2029,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)
@@ -2086,11 +2106,17 @@ 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)))))
 
@@ -2330,7 +2356,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
@@ -2350,7 +2376,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 ":                                 :")
@@ -2366,7 +2392,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")
@@ -2431,7 +2457,7 @@ Thank you for your help in stamping out bugs.
       (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)
@@ -2532,30 +2558,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)
@@ -2571,7 +2606,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)
@@ -2585,7 +2620,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)))))
 
@@ -2756,7 +2791,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)
@@ -2790,7 +2825,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))
@@ -2808,7 +2843,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))
@@ -2825,7 +2860,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.
@@ -2836,7 +2871,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
 
@@ -3101,6 +3136,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 ()
@@ -3622,7 +3661,9 @@ simple-first is t, first argument is already simplified."
 
 (defun gnus-completing-read (default prompt &rest args)
   ;; Like `completing-read', except that DEFAULT is the default argument.
-  (let* ((prompt (concat prompt " (default " default ") "))
+  (let* ((prompt (if default 
+                    (concat prompt " (default " default ") ")
+                  (concat prompt " ")))
         (answer (apply 'completing-read prompt args)))
     (if (or (null answer) (zerop (length answer)))
        default
@@ -3654,17 +3695,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.
@@ -3712,17 +3766,17 @@ 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))
+    (gnus-put-text-property (max (1- b) (point-min))
                       b 'intangible nil)))
 
 (defun gnus-hide-text-type (b e type)
@@ -3739,10 +3793,23 @@ simple-first is t, first argument is already simplified."
                 (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)
@@ -4208,9 +4275,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 level 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
@@ -4231,10 +4301,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)
@@ -4396,7 +4466,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
@@ -4536,7 +4606,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)
@@ -4544,7 +4614,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"))
@@ -4585,6 +4655,8 @@ If REGEXP, only list groups matching REGEXP."
 (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.
@@ -4771,16 +4843,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
@@ -4807,13 +4881,14 @@ 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))))
+        (entry (and group (gnus-gethash group gnus-newsrc-hashtb)))
+        gnus-group-indentation)
     (and entry
         (not (gnus-ephemeral-group-p group))
         (gnus-dribble-enter
          (concat "(gnus-group-set-info '"
                  (prin1-to-string (nth 2 entry)) ")")))
+    (setq gnus-group-indentation (gnus-group-group-indentation))
     (gnus-delete-line)
     (gnus-group-insert-group-line-info group)
     (forward-line -1)
@@ -4892,7 +4967,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.
@@ -4960,24 +5035,39 @@ already."
        (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.
+            (mode-string (eval gformat)))
+       ;; Say whether the dribble buffer has been modified.
+       (setq mode-line-modified
+             (if (and gnus-dribble-buffer
+                      (buffer-name gnus-dribble-buffer)
+                      (buffer-modified-p gnus-dribble-buffer)
+                      (save-excursion
+                        (set-buffer gnus-dribble-buffer)
+                        (not (zerop (buffer-size)))))
+                 "---*- " "----- "))
+       ;; If 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))))))
 
 (defun gnus-group-group-name ()
   "Get the name of the newsgroup on the current line."
@@ -5050,24 +5140,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))
 
@@ -5166,6 +5255,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)))
@@ -5275,7 +5365,9 @@ 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)))
 
   (when (equal group "")
     (error "Empty group name"))
@@ -5436,35 +5528,40 @@ 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.
@@ -5680,9 +5777,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.
@@ -5697,9 +5792,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.
@@ -5722,9 +5815,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.
@@ -5749,14 +5840,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."
@@ -5903,7 +5989,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.
 
@@ -5946,11 +6032,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)))
@@ -6086,7 +6174,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)
@@ -6101,7 +6191,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
@@ -6270,28 +6360,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)
@@ -6315,7 +6384,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.
@@ -6324,7 +6393,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)
@@ -6449,7 +6519,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))))
@@ -6514,8 +6584,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))
@@ -7059,6 +7135,7 @@ The following commands are available:
   (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-display-table ()
@@ -7384,12 +7461,10 @@ This is all marks except unread, ticked, dormant, and expirable."
 (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
@@ -7442,7 +7517,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)
@@ -7978,7 +8053,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.
@@ -7993,7 +8068,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)
@@ -8003,15 +8079,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)
@@ -8458,7 +8535,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)
@@ -8528,13 +8605,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))
@@ -8849,12 +8932,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...
@@ -9015,6 +9099,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))
@@ -9300,8 +9385,13 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
          (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 (mail-header-number header) gnus-newsgroup-sparse))
       (gnus-rebuild-thread (mail-header-id header))
-      (gnus-summary-goto-subject (setq number (mail-header-number header))))
+      (gnus-summary-goto-subject (setq number (mail-header-number header))
+                                nil t))
     (when (and (numberp number)
               (> number 0))
       ;; We have to update the boundaries even if we can't fetch the
@@ -9377,12 +9467,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
@@ -9715,7 +9807,6 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
     (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
@@ -9733,8 +9824,6 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
       (gnus-group-jump-to-group group)
       (gnus-group-next-unread-group 1))
     (run-hooks 'gnus-summary-exit-hook)
-    (unless gnus-single-article-buffer
-      (setq gnus-article-current nil))
     (if temporary
        nil                             ;Nothing to do.
       ;; If we have several article buffers, we kill them at exit.
@@ -9872,6 +9961,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)
@@ -10086,15 +10181,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.
@@ -10102,6 +10197,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
@@ -10277,25 +10375,30 @@ 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)))
 
@@ -10815,7 +10918,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.
@@ -10871,7 +10974,8 @@ Return how many articles were fetched."
                    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))
@@ -10960,46 +11064,45 @@ 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.
+            're-search-backward 're-search-forward))
+       (sum (current-buffer))
+       (found nil))
+    ;; Hidden thread subtrees must be searchedtoo.
     (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))
+    (set-buffer gnus-article-buffer)
+    (while (not found)
+      (gnus-message 7 "Searching article: %d..." gnus-current-article)
+      (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)))
+       ;; 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))))))
+    (set-buffer sum)
+    ;; Return whether we found the regexp.
+    (eq found 'found)))
 
 (defun gnus-summary-find-matching (header regexp &optional backward unread
                                          not-case-fold)
@@ -11098,6 +11201,7 @@ article massaging functions being run."
          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))
 
@@ -11209,9 +11313,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)
@@ -11223,7 +11327,8 @@ 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 (or select-method 
                        (gnus-find-method-for-group to-newsgroup)))
@@ -11452,7 +11557,7 @@ latter case, they will be copied into the relevant groups."
       (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)
@@ -11464,8 +11569,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
@@ -11500,11 +11606,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)
@@ -11526,7 +11630,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.
@@ -11591,7 +11696,16 @@ groups."
        (gnus-summary-update-article (cdr gnus-article-current))
        (when gnus-use-cache
          (gnus-cache-update-article 
-          (cdr gnus-article-current) (car gnus-article-current))))
+          (cdr gnus-article-current) (car 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)))))
@@ -12325,26 +12439,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."
@@ -12700,14 +12815,11 @@ 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)))))
+  (setq date (timezone-fix-time date nil nil))
+  (timezone-make-sortable-date
+   (aref date 0) (aref date 2) (aref date 2)
+   (timezone-make-time-string
+    (aref date 3) (aref date 4) (aref date 5))))
 
 ;; Summary saving commands.
 
@@ -12857,8 +12969,20 @@ 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))
+        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))
@@ -12866,19 +12990,19 @@ 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))
@@ -12908,14 +13032,15 @@ save those articles instead."
             (concat gnus-article-save-directory (car split-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)
@@ -12932,8 +13057,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
@@ -12958,8 +13082,7 @@ is initialized from the SAVEDIR environment variable."
 (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
@@ -12991,8 +13114,7 @@ is initialized from the SAVEDIR environment variable."
 (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
@@ -13017,8 +13139,7 @@ is initialized from the SAVEDIR environment variable."
 (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
@@ -13115,7 +13236,7 @@ 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
+         (gnus-add-text-properties
           b e (list 'gnus-number gnus-reffed-article-number
                     gnus-mouse-face-prop gnus-mouse-face))
          (gnus-data-enter
@@ -13140,8 +13261,13 @@ 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
@@ -13284,7 +13410,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))
@@ -13343,7 +13469,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)))
@@ -13364,8 +13492,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)
@@ -13401,6 +13540,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
@@ -13417,17 +13557,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.
@@ -13574,22 +13720,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))
@@ -13610,6 +13758,17 @@ 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,
@@ -13659,7 +13818,7 @@ always hide."
              (beginning-of-line)
              ;; We add the headers we want to keep to a list and delete
              ;; them from the buffer.
-             (put-text-property 
+             (gnus-put-text-property 
               (point) (1+ (point)) 'message-rank
               (if (or (and visible (looking-at visible))
                       (and ignored
@@ -13674,18 +13833,9 @@ always hide."
              (if delete
                  (delete-region beg (point-max))
                ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
-               (gnus-hide-text-type beg (point-max) '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))
+               (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.
@@ -13719,16 +13869,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 
@@ -13737,7 +13887,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))
@@ -13767,15 +13917,15 @@ always hide."
        (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))
+                (gnus-put-text-property (- (point) 2) (point) 'invisible t)
+                (gnus-put-text-property (point) (1+ (point)) 'face 'bold))
                ((eq next ?_)
-                (put-text-property (1- (point)) (1+ (point)) 'invisible t)
-                (put-text-property
+                (gnus-put-text-property (1- (point)) (1+ (point)) 'invisible t)
+                (gnus-put-text-property
                  (- (point) 2) (1- (point)) 'face 'underline))
                ((eq previous ?_)
-                (put-text-property (- (point) 2) (point) 'invisible t)
-                (put-text-property
+                (gnus-put-text-property (- (point) 2) (point) 'invisible t)
+                (gnus-put-text-property
                  (point) (1+ (point))  'face 'underline))))))))
 
 (defun gnus-article-word-wrap ()
@@ -13835,7 +13985,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
@@ -13864,21 +14014,28 @@ always hide."
                (process-send-region "gnus-x-face" beg end)
                (process-send-eof "gnus-x-face")))))))))
 
-(defun gnus-headers-decode-quoted-printable ()
+(defalias 'gnus-header-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.
@@ -13893,24 +14050,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" (downcase type))))
-       (gnus-headers-decode-quoted-printable)
        (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))
@@ -14071,89 +14230,98 @@ how much time has lapsed since DATE."
            (if (re-search-forward date-regexp nil t)
                (progn
                  (setq bface (get-text-property (gnus-point-at-bol) 'face)
-                       eface (get-text-property (gnus-point-at-eol) '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.
-         (beginning-of-line)
-         (when (and highlight (gnus-visual-p 'article-highlight 'highlight)
-                    (looking-at "\\([^:]\\): *\\(.*\\)$"))
-           (put-text-property (match-beginning 1) (match-end 1)
-                              'face bface)
-           (put-text-property (match-beginning 2) (match-end 2)
-                              'face eface)))))))
+           (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."
@@ -14516,17 +14684,17 @@ If NEWSGROUP is nil, return the global kill file name instead."
    ((or (null newsgroup)
        (string-equal newsgroup ""))
     (expand-file-name gnus-kill-file-name
-                     (or gnus-kill-files-directory "~/News")))
+                     gnus-kill-files-directory))
    ;; Append ".KILL" to newsgroup name.
    ((gnus-use-long-file-name 'not-kill)
     (expand-file-name (concat (gnus-newsgroup-savable-name newsgroup)
                              "." gnus-kill-file-name)
-                     (or gnus-kill-files-directory "~/News")))
+                     gnus-kill-files-directory))
    ;; Place "KILL" under the hierarchical directory.
    (t
     (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
                              "/" gnus-kill-file-name)
-                     (or gnus-kill-files-directory "~/News")))))
+                     gnus-kill-files-directory))))
 
 \f
 ;;;
@@ -14571,7 +14739,8 @@ If NEWSGROUP is nil, return the global kill file name instead."
       (bury-buffer (current-buffer))
       (set-buffer-modified-p nil)
       (let ((auto (make-auto-save-file-name))
-           (gnus-dribble-ignore t))
+           (gnus-dribble-ignore t)
+           modes)
        (when (or (file-exists-p auto) (file-exists-p dribble-file))
          ;; Load whichever file is newest -- the auto save file
          ;; or the "real" file.
@@ -14582,9 +14751,9 @@ If NEWSGROUP is nil, return the global kill file name instead."
            (set-buffer-modified-p t))
          ;; Set the file modes to reflect the .newsrc file modes.
          (save-buffer)
-         (when (file-exists-p gnus-current-startup-file)
-           (set-file-modes dribble-file
-                           (file-modes gnus-current-startup-file)))
+         (when (and (file-exists-p gnus-current-startup-file)
+                    (setq modes (file-modes gnus-current-startup-file)))
+           (set-file-modes dribble-file modes))
          ;; Possibly eval the file later.
          (when (gnus-y-or-n-p
                 "Auto-save file exists.  Do you want to read it? ")
@@ -15021,9 +15190,12 @@ If GROUP is nil, all groups on METHOD are scanned."
                       (gnus-server-extend-method group method))
                      (t
                       method)))
-         (if (equal (cadr method) "")
-             method
-           (gnus-server-add-address method))))))
+         (cond ((equal (cadr method) "")
+                method)
+               ((null (cadr method))
+                (list (car method) ""))
+               (t
+                (gnus-server-add-address method)))))))
 
 (defun gnus-check-backend-function (func group)
   "Check whether GROUP supports function FUNC."
@@ -15103,7 +15275,9 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
        (gnus-find-new-newsgroups))
 
     ;; We might read in new NoCeM messages here.
-    (when gnus-use-nocem 
+    (when (and gnus-use-nocem 
+              (not level)
+              (not dont-connect))
       (gnus-nocem-scan-groups))
 
     ;; Find the number of unread articles in each non-dead group.
@@ -15273,7 +15447,7 @@ the server for new groups."
          (file-exists-p (concat gnus-startup-file ".eld")))
       nil
     (gnus-message 6 "First time user; subscribing you to default groups")
-    (unless gnus-have-read-active-file
+    (unless (gnus-read-active-file-p)
       (gnus-read-active-file))
     (setq gnus-newsrc-last-checked-date (current-time-string))
     (let ((groups gnus-default-subscribed-newsgroups)
@@ -15445,9 +15619,9 @@ newsgroup."
   (let ((newsrc (cdr gnus-newsrc-alist))
        bogus group entry info)
     (gnus-message 5 "Checking bogus newsgroups...")
-    (unless gnus-have-read-active-file
+    (unless (gnus-read-active-file-p)
       (gnus-read-active-file))
-    (when (member gnus-select-method gnus-have-read-active-file)
+    (when (gnus-read-active-file-p)
       ;; Find all bogus newsgroup that are subscribed.
       (while newsrc
        (setq info (pop newsrc)
@@ -15612,20 +15786,19 @@ newsgroup."
          (when (<= (gnus-info-level info) foreign-level)
            (setq active (gnus-activate-group group 'scan))
            (unless (inline (gnus-virtual-group-p group))
-             (inline (gnus-close-group group))))
-
+             (inline (gnus-close-group group)))
+           (when (fboundp (intern (concat (symbol-name (car method))
+                                          "-request-update-info")))
+             (inline (gnus-request-update-info info method))))
        ;; These groups are native or secondary.
        (when (and (<= (gnus-info-level info) level)
                   (not gnus-read-active-file))
          (setq active (gnus-activate-group group 'scan))
          (inline (gnus-close-group group))))
 
+      ;; Get the number of unread articles in the group.
       (if active
-         (inline (gnus-get-unread-articles-in-group 
-                  info active
-                  (and method
-                       (fboundp (intern (concat (symbol-name (car method))
-                                                "-request-update-info"))))))
+         (inline (gnus-get-unread-articles-in-group info active))
        ;; The group couldn't be reached, so we nix out the number of
        ;; unread articles and stuff.
        (gnus-set-active group nil)
@@ -15767,6 +15940,31 @@ Returns whether the updating was successful."
        (setq killed (cdr killed)))
       (setq lists (cdr lists)))))
 
+(defun gnus-get-killed-groups ()
+  "Go through the active hashtb and all all unknown groups as killed."
+  ;; First make sure active file has been read.
+  (unless (gnus-read-active-file-p)
+    (let ((gnus-read-active-file t))
+      (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))
+
 ;; Get the active file(s) from the backend(s).
 (defun gnus-read-active-file ()
   (gnus-group-set-mode-line)
@@ -15829,7 +16027,7 @@ Returns whether the updating was successful."
                  (unless (equal method gnus-message-archive-method)
                    (gnus-error 1 "Cannot read active file from %s server."
                                (car method)))
-               (gnus-active-to-gnus-format method)
+               (gnus-active-to-gnus-format method gnus-active-hashtb)
                ;; We mark this active file as read.
                (push method gnus-have-read-active-file)
                (gnus-message 5 "%sdone" mesg))))))
@@ -16025,8 +16223,59 @@ If FORCE is non-nil, the .newsrc file is read."
            (gnus-message 5 "Reading %s...done" newsrc-file)))
 
       ;; Read any slave files.
-      (or gnus-slave
-         (gnus-master-read-slave-newsrc)))))
+      (unless gnus-slave
+       (gnus-master-read-slave-newsrc))
+      
+      ;; Convert old to new.
+      (gnus-convert-old-newsrc))))
+
+(defun gnus-continuum-version (version)
+  "Return VERSION as a floating point number."
+  (when (string-match "^\\([^ ]+\\)? ?Gnus v?\\([0-9.]+\\)$" version)
+    (let* ((alpha (and (match-beginning 1) (match-string 1 version)))
+          (number (match-string 2 version))
+          major minor least)
+      (string-match "\\([0-9]\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?" number)
+      (setq major (string-to-number (match-string 1 number)))
+      (setq minor (string-to-number (match-string 2 number)))
+      (setq least (if (match-beginning 3)
+                     (string-to-number (match-string 3 number))
+                   0))
+      (string-to-number
+       (if (zerop major)
+          (format "%s00%02d%02d"
+                  (cond 
+                   ((string= alpha "(ding)") "4.99")
+                   ((string= alpha "September") "5.01")
+                   ((string= alpha "Red") "5.03"))
+                  minor least)
+        (format "%d.%02d%20d" major minor least))))))
+
+(defun gnus-convert-old-newsrc ()
+  "Convert old newsrc into the new format, if needed."
+  (let ((fcv (and gnus-newsrc-file-version
+                 (gnus-continuum-version gnus-newsrc-file-version))))
+    (cond
+     ;; No .newsrc.eld file was loaded.
+     ((null fcv) nil)
+     ;; Gnus 5 .newsrc.eld was loaded.
+     ((< fcv (gnus-continuum-version "September Gnus v0.1"))
+      (gnus-convert-old-ticks)))))
+
+(defun gnus-convert-old-ticks ()
+  (let ((newsrc (cdr gnus-newsrc-alist))
+       marks info dormant ticked)
+    (while (setq info (pop newsrc))
+      (when (setq marks (gnus-info-marks info))
+       (setq dormant (cdr (assq 'dormant marks))
+             ticked (cdr (assq 'tick marks)))
+       (when (or dormant ticked)
+         (gnus-info-set-read
+          info
+          (gnus-add-to-range
+           (gnus-info-read info)
+           (nconc (gnus-uncompress-range dormant)
+                  (gnus-uncompress-range ticked)))))))))
 
 (defun gnus-read-newsrc-el-file (file)
   (let ((ding-file (concat file "d")))
@@ -16395,7 +16644,8 @@ If FORCE is non-nil, the .newsrc file is read."
          (kill-buffer (current-buffer))
          (gnus-message
           5 "Saving %s.eld...done" gnus-current-startup-file))
-       (gnus-dribble-delete-file)))))
+       (gnus-dribble-delete-file)
+       (gnus-group-set-mode-line)))))
 
 (defun gnus-gnus-to-quick-newsrc-format ()
   "Insert Gnus variables such as gnus-newsrc-alist in lisp format."
@@ -16658,7 +16908,7 @@ If FORCE is non-nil, the .newsrc file is read."
          (setq b (point))
          (insert-buffer-substring buffer)
          ;; Tag the beginning of the article with the ident.
-         (put-text-property b (1+ b) 'gnus-backlog ident))))))
+         (gnus-put-text-property b (1+ b) 'gnus-backlog ident))))))
 
 (defun gnus-backlog-remove-oldest-article ()
   (save-excursion
@@ -16676,6 +16926,29 @@ If FORCE is non-nil, the .newsrc file is read."
         (point) (next-single-property-change
                  (1+ (point)) 'gnus-backlog nil (point-max)))))))
 
+(defun gnus-backlog-remove-article (group number)
+  "Remove article NUMBER in GROUP from the backlog."
+  (when (numberp number)
+    (gnus-backlog-setup)
+    (let ((ident (intern (concat group ":" (int-to-string number))
+                        gnus-backlog-hashtb))
+         beg end)
+      (when (memq ident gnus-backlog-articles)
+       ;; It was in the backlog.
+       (save-excursion
+         (set-buffer (gnus-backlog-buffer))
+         (let (buffer-read-only)
+           (when (setq beg (text-property-any
+                            (point-min) (point-max) 'gnus-backlog
+                            ident))
+             ;; Find the end (i. e., the beginning of the next article).
+             (setq end
+                   (next-single-property-change
+                    (1+ beg) 'gnus-backlog (current-buffer) (point-max)))
+             (delete-region beg end)
+             ;; Return success.
+             t)))))))
+
 (defun gnus-backlog-request-article (group number buffer)
   (when (numberp number)
     (gnus-backlog-setup)