Synch to No Gnus 200407171659.
[elisp/gnus.git-] / lisp / gnus-group.el
index c0d8f01..7818828 100644 (file)
 (require 'time-date)
 (require 'gnus-ems)
 
-(eval-when-compile (require 'mm-url))
+(eval-when-compile 
+  (require 'mm-url)
+  (let ((features (cons 'gnus-group features)))
+    (require 'gnus-sum))
+  (unless (boundp 'gnus-cache-active-hashtb)
+    (defvar gnus-cache-active-hashtb nil)))
+
+(autoload 'gnus-agent-total-fetched-for "gnus-agent")
+(autoload 'gnus-cache-total-fetched-for "gnus-cache")
 
 (defcustom gnus-group-archive-directory
-  "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
+  "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
   "*The address of the (ding) archives."
   :group 'gnus-group-foreign
   :type 'directory)
 
 (defcustom gnus-group-recent-archive-directory
-  "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/"
+  "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/"
   "*The address of the most recent (ding) articles."
   :group 'gnus-group-foreign
   :type 'directory)
@@ -145,7 +153,7 @@ list."
                         (function-item gnus-group-sort-by-rank)
                         (function :tag "other" nil))))
 
-(defcustom gnus-group-line-format "%M\%S\%p\%P\%5y:%B%(%g%)%l %O\n"
+(defcustom gnus-group-line-format "%M\%S\%p\%P\%5y:%B%(%g%)%O\n"
   "*Format of group lines.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
@@ -174,11 +182,11 @@ with some simple extensions.
 %P    Topic indentation (string)
 %m    Whether there is new(ish) mail in the group (char, \"%\")
 %w    Number of new(ish) mails in the group (integer)
-%l    Whether there are GroupLens predictions for this group (string)
 %n    Select from where (string)
 %z    A string that look like `<%s:%n>' if a foreign select method is used
 %d    The date the group was last entered.
 %E    Icon as defined by `gnus-group-icon-list'.
+%F    The disk space used by the articles fetched by both the cache and agent.
 %u    User defined specifier.  The next character in the format string should
       be a letter.  Gnus will call the function gnus-user-format-function-X,
       where X is the letter following %u.  The function will be passed a
@@ -193,10 +201,10 @@ output may end up looking strange when listing both alive and killed
 groups.
 
 If you use %o or %O, reading the active file will be slower and quite
-a bit of extra memory will be used.  %D will also worsen performance.
-Also note that if you change the format specification to include any
-of these specs, you must probably re-start Gnus to see them go into
-effect.
+a bit of extra memory will be used.  %D and %F will also worsen
+performance.  Also note that if you change the format specification to
+include any of these specs, you must probably re-start Gnus to see
+them go into effect.
 
 General format specifiers can also be used.
 See Info node `(gnus)Formatting Variables'."
@@ -432,12 +440,19 @@ For example:
 
 (defcustom gnus-group-jump-to-group-prompt nil
   "Default prompt for `gnus-group-jump-to-group'.
-If non-nil, the value should be a string, e.g. \"nnml:\",
-in which case `gnus-group-jump-to-group' offers \"Group: nnml:\"
-in the minibuffer prompt."
+
+If non-nil, the value should be a string or an alist.  If it is a string,
+e.g. \"nnml:\", in which case `gnus-group-jump-to-group' offers \"Group:
+nnml:\" in the minibuffer prompt.
+
+If it is an alist, it must consist of \(NUMBER .  PROMPT\) pairs, for example:
+\((1 .  \"\") (2 .  \"nnfolder+archive:\")).  The element with number 0 is
+used when no prefix argument is given to `gnus-group-jump-to-group'."
   :group 'gnus-group-various
   :type '(choice (string :tag "Prompt string")
-                (const :tag "Empty" nil)))
+                (const :tag "Empty" nil)
+                (repeat (cons (integer :tag "Argument")
+                              (string :tag "Prompt string")))))
 
 (defvar gnus-group-listing-limit 1000
   "*A limit of the number of groups when listing.
@@ -494,7 +509,6 @@ simple manner.")
     (?P gnus-group-indentation ?s)
     (?E gnus-tmp-group-icon ?s)
     (?B gnus-tmp-summary-live ?c)
-    (?l gnus-tmp-grouplens ?s)
     (?z gnus-tmp-news-method-string ?s)
     (?m (gnus-group-new-mail gnus-tmp-group) ?c)
     (?w (if (gnus-news-group-p gnus-tmp-group)
@@ -505,7 +519,9 @@ simple manner.")
            )))
        ?s)
     (?d (gnus-group-timestamp-string gnus-tmp-group) ?s)
-    (?u gnus-tmp-user-defined ?s)))
+    (?u gnus-tmp-user-defined ?s)
+    (?F (gnus-total-fetched-for gnus-tmp-group) ?s)
+    ))
 
 (defvar gnus-group-mode-line-format-alist
   `((?S gnus-tmp-news-server ?s)
@@ -624,7 +640,7 @@ simple manner.")
   "a" gnus-group-make-archive-group
   "k" gnus-group-make-kiboze-group
   "l" gnus-group-nnimap-edit-acl
-  "m" gnus-group-make-group
+  "m" gnus-group-make-group-simple
   "n" gnus-group-make-shimbun-group
   "E" gnus-group-edit-group
   "e" gnus-group-edit-group-method
@@ -894,6 +910,7 @@ simple manner.")
        ["Kill all groups on level..." gnus-group-kill-level t])
        ("Foreign groups"
        ["Make a foreign group..." gnus-group-make-group t]
+       ["Make a foreign group..." gnus-group-make-group-simple t]
        ["Make a shimbun group..." gnus-group-make-shimbun-group t]
        ["Add a directory group..." gnus-group-make-directory-group t]
        ["Add the help group" gnus-group-make-help-group t]
@@ -1034,7 +1051,8 @@ The following commands are available:
   (use-local-map gnus-group-mode-map)
   (buffer-disable-undo)
   (setq truncate-lines t)
-  (setq buffer-read-only t)
+  (setq buffer-read-only t
+       show-trailing-whitespace nil)
   (gnus-set-default-directory)
   (gnus-update-format-specifications nil 'group 'group-mode)
   (gnus-update-group-mark-positions)
@@ -1163,7 +1181,7 @@ Also see the `gnus-group-use-permanent-levels' variable."
   (gnus-group-setup-buffer)
   (gnus-update-format-specifications nil 'group 'group-mode)
   (let ((case-fold-search nil)
-       (props (text-properties-at (gnus-point-at-bol)))
+       (props (text-properties-at (point-at-bol)))
        (empty (= (point-min) (point-max)))
        (group (gnus-group-group-name))
        number)
@@ -1195,7 +1213,7 @@ Also see the `gnus-group-use-permanent-levels' variable."
                     (point-min) (point-max)
                     'gnus-group (gnus-intern-safe
                                  group gnus-active-hashtb))))
-         (let ((newsrc (cdddr (gnus-gethash group gnus-newsrc-hashtb))))
+         (let ((newsrc (cdddr (gnus-group-entry group))))
            (while (and newsrc
                        (not (gnus-goto-char
                              (text-property-any
@@ -1250,7 +1268,7 @@ if it is a string, only list groups matching REGEXP."
              group (gnus-info-group info)
              params (gnus-info-params info)
              newsrc (cdr newsrc)
-             unread (car (gnus-gethash group gnus-newsrc-hashtb)))
+             unread (gnus-group-unread group))
        (when not-in-list
          (setq not-in-list (delete group not-in-list)))
        (when (gnus-group-prepare-logic
@@ -1350,7 +1368,7 @@ if it is a string, only list groups matching REGEXP."
   "Update the current line in the group buffer."
   (let* ((buffer-read-only nil)
         (group (gnus-group-group-name))
-        (entry (and group (gnus-gethash group gnus-newsrc-hashtb)))
+        (entry (and group (gnus-group-entry group)))
         gnus-group-indentation)
     (when group
       (and entry
@@ -1367,7 +1385,7 @@ if it is a string, only list groups matching REGEXP."
 
 (defun gnus-group-insert-group-line-info (group)
   "Insert GROUP on the current line."
-  (let ((entry (gnus-gethash group gnus-newsrc-hashtb))
+  (let ((entry (gnus-group-entry group))
        (gnus-group-indentation (gnus-group-group-indentation))
        active info)
     (if entry
@@ -1464,10 +1482,6 @@ if it is a string, only list groups matching REGEXP."
         (gnus-tmp-process-marked
          (if (member gnus-tmp-group gnus-group-marked)
              gnus-process-mark ? ))
-        (gnus-tmp-grouplens
-         (or (and gnus-use-grouplens
-                  (bbb-grouplens-group-p gnus-tmp-group))
-             ""))
         (buffer-read-only nil)
         header gnus-tmp-header)        ; passed as parameter to user-funcs.
     (beginning-of-line)
@@ -1496,7 +1510,7 @@ if it is a string, only list groups matching REGEXP."
   "Highlight the current line according to `gnus-group-highlight'."
   (let* ((list gnus-group-highlight)
         (p (point))
-        (end (gnus-point-at-eol))
+        (end (point-at-eol))
         ;; now find out where the line starts and leave point there.
         (beg (progn (beginning-of-line) (point)))
         (group (gnus-group-group-name))
@@ -1547,7 +1561,7 @@ already."
            (loc (point-min))
            found buffer-read-only)
        ;; Enter the current status into the dribble buffer.
-       (let ((entry (gnus-gethash group gnus-newsrc-hashtb)))
+       (let ((entry (gnus-group-entry group)))
          (when (and entry
                     (not (gnus-ephemeral-group-p group)))
            (gnus-dribble-enter
@@ -1572,7 +1586,7 @@ already."
          ;; go, and insert it there (or at the end of the buffer).
          (if gnus-goto-missing-group-function
              (funcall gnus-goto-missing-group-function group)
-           (let ((entry (cddr (gnus-gethash group gnus-newsrc-hashtb))))
+           (let ((entry (cddr (gnus-group-entry group))))
              (while (and entry (car entry)
                          (not
                           (gnus-goto-char
@@ -1632,24 +1646,24 @@ already."
 
 (defun gnus-group-group-name ()
   "Get the name of the newsgroup on the current line."
-  (let ((group (get-text-property (gnus-point-at-bol) 'gnus-group)))
+  (let ((group (get-text-property (point-at-bol) 'gnus-group)))
     (when group
       (symbol-name group))))
 
 (defun gnus-group-group-level ()
   "Get the level of the newsgroup on the current line."
-  (get-text-property (gnus-point-at-bol) 'gnus-level))
+  (get-text-property (point-at-bol) 'gnus-level))
 
 (defun gnus-group-group-indentation ()
   "Get the indentation of the newsgroup on the current line."
-  (or (get-text-property (gnus-point-at-bol) 'gnus-indentation)
+  (or (get-text-property (point-at-bol) 'gnus-indentation)
       (and gnus-group-indentation-function
           (funcall gnus-group-indentation-function))
       ""))
 
 (defun gnus-group-group-unread ()
   "Get the number of unread articles of the newsgroup on the current line."
-  (get-text-property (gnus-point-at-bol) 'gnus-unread))
+  (get-text-property (point-at-bol) 'gnus-unread))
 
 (defun gnus-group-new-mail (group)
   (if (nnmail-new-mail-p (gnus-group-real-name group))
@@ -1707,6 +1721,18 @@ If FIRST-TOO, the current line is also eligible as a target."
       (goto-char (or pos beg))
       (and pos t))))
 
+(defun gnus-total-fetched-for (group)
+  (let* ((size-in-cache (or (gnus-cache-total-fetched-for group) 0))
+        (size-in-agent (or (gnus-agent-total-fetched-for group) 0))
+        (size (+ size-in-cache size-in-agent))
+        (suffix '("B" "K" "M" "G"))
+        (scale 1024.0)
+        (cutoff (* 10 scale)))
+    (while (> size cutoff)
+      (setq size (/ size scale)
+           suffix (cdr suffix)))
+    (format "%5.1f%s" size (car suffix))))
+
 ;;; Gnus group mode commands
 
 ;; Group marking.
@@ -1728,15 +1754,14 @@ If FIRST-TOO, the current line is also eligible as a target."
        ;; Go to the mark position.
        (beginning-of-line)
        (forward-char (or (cdr (assq 'process gnus-group-mark-positions)) 2))
-       (subst-char-in-region
-        (point) (1+ (point)) (char-after)
-        (if unmark
-            (progn
-              (setq gnus-group-marked (delete group gnus-group-marked))
-              ? )
+       (delete-char 1)
+       (if unmark
+           (progn
+             (setq gnus-group-marked (delete group gnus-group-marked))
+             (insert-char ? 1 t))
           (setq gnus-group-marked
                 (cons group (delete group gnus-group-marked)))
-          gnus-process-mark)))
+          (insert-char gnus-process-mark 1 t)))
       (unless no-advance
        (gnus-group-next-group 1))
       (decf n))
@@ -1901,8 +1926,7 @@ group."
     (unless group
       (error "No group on current line"))
     (setq marked (gnus-info-marks
-                 (nth 2 (setq entry (gnus-gethash
-                                     group gnus-newsrc-hashtb)))))
+                 (nth 2 (setq entry (gnus-group-entry group)))))
     ;; This group might be a dead group.  In that case we have to get
     ;; the number of unread articles from `gnus-active-hashtb'.
     (setq number
@@ -1923,7 +1947,10 @@ group."
 No article is selected automatically.
 If the group is opened, just switch the summary buffer.
 If ALL is non-nil, already read articles become readable.
-If ALL is a number, fetch this number of articles."
+If ALL is a positive number, fetch this number of the latest
+articles in the group.
+If ALL is a negative number, fetch this number of the earliest
+articles in the group."
   (interactive "P")
   (when (and (eobp) (not (gnus-group-group-name)))
     (forward-line -1))
@@ -2079,14 +2106,23 @@ Return the name of the group if selection was successful."
         (message "Quit reading the ephemeral group")
         nil)))))
 
-(defun gnus-group-jump-to-group (group)
-  "Jump to newsgroup GROUP."
+(defun gnus-group-jump-to-group (group &optional prompt)
+  "Jump to newsgroup GROUP.
+
+If PROMPT (the prefix) is a number, use the prompt specified in
+`gnus-group-jump-to-group-prompt'."
   (interactive
-   (list (gnus-group-completing-read-group-name
-         "Group: " gnus-active-hashtb nil
-         (gnus-read-active-file-p)
-         gnus-group-jump-to-group-prompt
-         'gnus-group-history)))
+   (list (mm-string-make-unibyte
+         (completing-read
+          "Group: " gnus-active-hashtb nil
+          (gnus-read-active-file-p)
+          (if current-prefix-arg
+              (cdr (assq current-prefix-arg gnus-group-jump-to-group-prompt))
+            (or (and (stringp gnus-group-jump-to-group-prompt)
+                     gnus-group-jump-to-group-prompt)
+                (let ((p (cdr (assq 0 gnus-group-jump-to-group-prompt))))
+                  (and (stringp p) p))))
+          'gnus-group-history))))
 
   (when (equal group "")
     (error "Empty group name"))
@@ -2255,6 +2291,16 @@ If EXCLUDE-GROUP, do not go to that group."
   (interactive)
   (gnus-enter-server-buffer))
 
+(defun gnus-group-make-group-simple (&optional group)
+  "Add a new newsgroup.
+The user will be prompted for GROUP."
+  (interactive
+   (list (completing-read "Group: " gnus-active-hashtb
+                         nil nil nil 'gnus-group-history)))
+  (gnus-group-make-group
+   (gnus-group-real-name group)
+   (gnus-group-server group)))
+
 (defun gnus-group-make-group (name &optional method address args)
   "Add a new newsgroup.
 The user will be prompted for a NAME, for a select METHOD, and an
@@ -2273,15 +2319,14 @@ ADDRESS."
                    method))))
         (nname (if method (gnus-group-prefixed-name name meth) name))
         backend info)
-    (when (gnus-gethash nname gnus-newsrc-hashtb)
+    (when (gnus-group-entry nname)
       (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))
+         (gnus-group-entry (gnus-group-group-name)))
      t)
     ;; Make it active.
     (gnus-set-active nname (cons 1 0))
@@ -2319,8 +2364,6 @@ ADDRESS."
        (lambda (group)
          (gnus-group-delete-group group nil t))))))
 
-(defvar gnus-cache-active-altered)
-
 (defun gnus-group-delete-group (group &optional force no-prompt)
   "Delete the current group.  Only meaningful with editable groups.
 If FORCE (the prefix) is non-nil, all the articles in the group will
@@ -2349,11 +2392,7 @@ be removed from the server, even when it's empty."
          (gnus-message 6 "Deleting group %s...done" group)
          (gnus-group-goto-group group)
          (gnus-group-kill-group 1 t)
-         (gnus-sethash group nil gnus-active-hashtb)
-         (if (boundp 'gnus-cache-active-hashtb)
-             (when gnus-cache-active-hashtb
-               (gnus-sethash group nil gnus-cache-active-hashtb)
-               (setq gnus-cache-active-altered t)))
+         (gnus-set-active group nil)
          t))
     (gnus-group-position-point)))
 
@@ -2523,7 +2562,7 @@ group already exists:
   (interactive)
   (let ((name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help")))
        (file (nnheader-find-etc-directory "gnus-tut.txt" t)))
-    (if (gnus-gethash name gnus-newsrc-hashtb)
+    (if (gnus-group-entry name)
        (cond ((eq noerror nil)
               (error "Documentation group already exists"))
              ((eq noerror t)
@@ -2681,7 +2720,7 @@ Given a prefix, create a full group."
   (interactive "P")
   (let ((group (gnus-group-prefixed-name
                (if all "ding.archives" "ding.recent") '(nndir ""))))
-    (when (gnus-gethash group gnus-newsrc-hashtb)
+    (when (gnus-group-entry group)
       (error "Archive group already exists"))
     (gnus-group-make-group
      (gnus-group-real-name group)
@@ -2705,7 +2744,7 @@ mail messages or news articles in files that have numeric names."
   (let ((ext "")
        (i 0)
        group)
-    (while (or (not group) (gnus-gethash group gnus-newsrc-hashtb))
+    (while (or (not group) (gnus-group-entry group))
       (setq group
            (gnus-group-prefixed-name
             (expand-file-name ext dir)
@@ -2724,7 +2763,7 @@ score file entries for articles to include in the group."
    (list
     (read-string "nnkiboze group name: ")
     (read-string "Source groups (regexp): ")
-    (let ((headers (mapcar (lambda (group) (list group))
+    (let ((headers (mapcar 'list
                           '("subject" "from" "number" "date" "message-id"
                             "references" "chars" "lines" "xref"
                             "followup" "all" "body" "head")))
@@ -2775,7 +2814,7 @@ score file entries for articles to include in the group."
   (let* ((method (list 'nnvirtual "^$"))
         (pgroup (gnus-group-prefixed-name group method)))
     ;; Check whether it exists already.
-    (when (gnus-gethash pgroup gnus-newsrc-hashtb)
+    (when (gnus-group-entry pgroup)
       (error "Group %s already exists" pgroup))
     ;; Subscribe the new group after the group on the current line.
     (gnus-subscribe-group pgroup (gnus-group-group-name) method)
@@ -2947,7 +2986,7 @@ If REVERSE, sort in reverse order."
   (let (entries infos)
     ;; First find all the group entries for these groups.
     (while groups
-      (push (nthcdr 2 (gnus-gethash (pop groups) gnus-newsrc-hashtb))
+      (push (nthcdr 2 (gnus-group-entry (pop groups)))
            entries))
     ;; Then sort the infos.
     (setq infos
@@ -3028,8 +3067,8 @@ sort in reverse order."
 
 (defun gnus-group-sort-by-unread (info1 info2)
   "Sort by number of unread articles."
-  (let ((n1 (car (gnus-gethash (gnus-info-group info1) gnus-newsrc-hashtb)))
-       (n2 (car (gnus-gethash (gnus-info-group info2) gnus-newsrc-hashtb))))
+  (let ((n1 (gnus-group-unread (gnus-info-group info1)))
+       (n2 (gnus-group-unread (gnus-info-group info1))))
     (< (or (and (numberp n1) n1) 0)
        (or (and (numberp n2) n2) 0))))
 
@@ -3169,10 +3208,10 @@ Cross references (Xref: header) of articles are ignored."
 If ALL is non-nil, all articles are marked as read.
 The return value is the number of articles that were marked as read,
 or nil if no action could be taken."
-  (let* ((entry (gnus-gethash group gnus-newsrc-hashtb))
+  (let* ((entry (gnus-group-entry group))
         (num (car entry))
-        (marks (nth 3 (nth 2 entry)))
-        (unread (gnus-list-of-unread-articles group)))
+        (marks (gnus-info-marks (nth 2 entry)))
+        (unread (gnus-sequence-of-unread-articles group)))
     ;; Remove entries for this group.
     (nnmail-purge-split-history (gnus-group-real-name group))
     ;; Do the updating only if the newsgroup isn't killed.
@@ -3185,16 +3224,17 @@ or nil if no action could be taken."
                                                 'del '(tick))
                                           (list (cdr (assq 'dormant marks))
                                                 'del '(dormant))))
-       (setq unread (gnus-uncompress-range
-                     (gnus-range-add (gnus-range-add
-                                      unread (cdr (assq 'dormant marks)))
-                                     (cdr (assq 'tick marks)))))
+       (setq unread (gnus-range-add (gnus-range-add
+                                      unread (cdr (assq 'dormant marks)))
+                                     (cdr (assq 'tick marks))))
        (gnus-add-marked-articles group 'tick nil nil 'force)
        (gnus-add-marked-articles group 'dormant nil nil 'force))
       ;; Do auto-expirable marks if that's required.
       (when (gnus-group-auto-expirable-p group)
-       (gnus-add-marked-articles group 'expire unread)
-       (gnus-request-set-mark group (list (list unread 'add '(expire)))))
+        (gnus-range-map (lambda (article)
+                          (gnus-add-marked-articles group 'expire (list article))
+                          (gnus-request-set-mark group (list (list (list article) 'add '(expire)))))
+                        unread))
       (let ((gnus-newsgroup-name group))
        (gnus-run-hooks 'gnus-group-catchup-group-hook))
       num)))
@@ -3327,7 +3367,7 @@ group line."
          (gnus-read-active-file-p)
          nil
          'gnus-group-history)))
-  (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb)))
+  (let ((newsrc (gnus-group-entry group)))
     (cond
      ((string-match "^[ \t]*$" group)
       (error "Empty group name"))
@@ -3351,7 +3391,7 @@ group line."
                gnus-level-zombie)
           gnus-level-killed)
        (when (gnus-group-group-name)
-        (gnus-gethash (gnus-group-group-name) gnus-newsrc-hashtb)))
+        (gnus-group-entry (gnus-group-group-name))))
       (unless silent
        (gnus-group-update-group group)))
      (t (error "No such newsgroup: %s" group)))
@@ -3390,12 +3430,10 @@ The killed newsgroups can be yanked by using \\[gnus-group-yank-group]."
           (count-lines
            (progn
              (goto-char begin)
-             (beginning-of-line)
-             (point))
+             (point-at-bol))
            (progn
              (goto-char end)
-             (beginning-of-line)
-             (point))))))
+             (point-at-bol))))))
     (goto-char begin)
     (beginning-of-line)                        ;Important when LINES < 1
     (gnus-group-kill-group lines)))
@@ -3419,7 +3457,7 @@ of groups killed."
          (setq level (gnus-group-group-level))
          (gnus-delete-line)
          (when (and (not discard)
-                    (setq entry (gnus-gethash group gnus-newsrc-hashtb)))
+                    (setq entry (gnus-group-entry group)))
            (gnus-undo-register
              `(progn
                 (gnus-group-goto-group ,(gnus-group-group-name))
@@ -3442,7 +3480,7 @@ of groups killed."
          (funcall gnus-group-change-level-function
                   group gnus-level-killed 3))
        (cond
-        ((setq entry (gnus-gethash group gnus-newsrc-hashtb))
+        ((setq entry (gnus-group-entry group))
          (push (cons (car entry) (nth 2 entry))
                gnus-list-of-killed-groups)
          (setcdr (cdr entry) (cdddr entry)))
@@ -3475,7 +3513,7 @@ yanked) a list of yanked groups is returned."
       (setq prev (gnus-group-group-name))
       (gnus-group-change-level
        info (gnus-info-level (cdr info)) gnus-level-killed
-       (and prev (gnus-gethash prev gnus-newsrc-hashtb))
+       (and prev (gnus-group-entry prev))
        t)
       (gnus-group-insert-group-line-info group)
       (gnus-undo-register
@@ -3556,7 +3594,7 @@ entail asking the server for the groups."
   ;; First we make sure that we have really read the active file.
   (unless (gnus-read-active-file-p)
     (let ((gnus-read-active-file t)
-         (gnus-agent nil))             ; Trick the agent into ignoring the active file.
+         (gnus-agent gnus-plugged)); If we're actually plugged, store the active file in the agent.
       (gnus-read-active-file)))
   ;; Find all groups and sort them.
   (let ((groups
@@ -3641,7 +3679,8 @@ re-scanning.  If ARG is non-nil and not a number, this will force
 (defun gnus-group-get-new-news-this-group (&optional n dont-scan)
   "Check for newly arrived news in the current group (and the N-1 next groups).
 The difference between N and the number of newsgroup checked is returned.
-If N is negative, this group and the N-1 previous groups will be checked."
+If N is negative, this group and the N-1 previous groups will be checked.
+If DONT-SCAN is non-nil, scan non-activated groups as well."
   (interactive "P")
   (let* ((groups (gnus-group-process-prefix n))
         (ret (if (numberp n) (- n (length groups)) 0))
@@ -3657,15 +3696,17 @@ If N is negative, this group and the N-1 previous groups will be checked."
       (gnus-group-remove-mark group)
       ;; Bypass any previous denials from the server.
       (gnus-remove-denial (setq method (gnus-find-method-for-group group)))
-      (if (gnus-activate-group group (if dont-scan nil 'scan))
-         (progn
-           (gnus-get-unread-articles-in-group
-            (gnus-get-info group) (gnus-active group) t)
+      (if (gnus-activate-group group (if dont-scan nil 'scan) nil method)
+         (let ((info (gnus-get-info group))
+               (active (gnus-active group)))
+           (when info
+             (gnus-request-update-info info method))
+           (gnus-get-unread-articles-in-group info active)
            (unless (gnus-virtual-group-p group)
              (gnus-close-group group))
            (when gnus-agent
              (gnus-agent-save-group-info
-              method (gnus-group-real-name group) (gnus-active group)))
+              method (gnus-group-real-name group) active))
            (gnus-group-update-group group))
        (if (eq (gnus-server-status (gnus-find-method-for-group group))
                'denied)
@@ -3967,10 +4008,8 @@ The hook `gnus-suspend-gnus-hook' is called before actually suspending."
   (let ((group-buf (get-buffer gnus-group-buffer)))
     (mapcar (lambda (buf)
              (unless (or (member buf (list group-buf gnus-dribble-buffer))
-                         (progn
-                           (save-excursion
-                             (set-buffer buf)
-                             (eq major-mode 'message-mode))))
+                         (with-current-buffer buf
+                           (eq major-mode 'message-mode)))
                (gnus-kill-buffer buf)))
            (gnus-buffers))
     (setq gnus-backlog-articles nil)
@@ -4056,17 +4095,15 @@ and the second element is the address."
                     ;; Suggested by mapjph@bath.ac.uk.
                     (completing-read
                      "Address: "
-                     (mapcar (lambda (server) (list server))
-                             gnus-secondary-servers)))
+                     (mapcar 'list gnus-secondary-servers)))
             ;; We got a server name.
             how))))
   (gnus-browse-foreign-server method))
 
 (defun gnus-group-set-info (info &optional method-only-group part)
   (when (or info part)
-    (let* ((entry (gnus-gethash
-                  (or method-only-group (gnus-info-group info))
-                  gnus-newsrc-hashtb))
+    (let* ((entry (gnus-group-entry
+                  (or method-only-group (gnus-info-group info))))
           (part-info info)
           (info (if method-only-group (nth 2 entry) info))
           method)
@@ -4104,10 +4141,9 @@ and the second element is the address."
              (gnus-group-make-group (gnus-info-group info))))
          (gnus-message 6 "Note: New group created")
          (setq entry
-               (gnus-gethash (gnus-group-prefixed-name
-                              (gnus-group-real-name (gnus-info-group info))
-                              (or (gnus-info-method info) gnus-select-method))
-                             gnus-newsrc-hashtb))))
+               (gnus-group-entry (gnus-group-prefixed-name
+                                  (gnus-group-real-name (gnus-info-group info))
+                                  (or (gnus-info-method info) gnus-select-method))))))
       ;; Whether it was a new group or not, we now have the entry, so we
       ;; can do the update.
       (if entry