2002-11-29 ShengHuo ZHU <zsh@cs.rochester.edu>
[gnus] / lisp / gnus-group.el
index 94d1184..168ebc8 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-group.el --- group mode commands for Gnus
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -39,6 +39,8 @@
 (require 'time-date)
 (require 'gnus-ems)
 
+(eval-when-compile (require 'mm-url))
+
 (defcustom gnus-group-archive-directory
   "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
   "*The address of the (ding) archives."
@@ -141,7 +143,7 @@ list."
                         (function-item gnus-group-sort-by-rank)
                         (function :tag "other" nil))))
 
-(defcustom gnus-group-line-format "%M\%S\%p\%P\%5y: %(%g%)%l\n"
+(defcustom gnus-group-line-format "%M\%S\%p\%P\%5y: %(%g%)%l %O\n"
   "*Format of group lines.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
@@ -159,6 +161,7 @@ with some simple extensions.
 %G    Group name (string)
 %g    Qualified group name (string)
 %c    Short (collapsed) group name.  See `gnus-group-uncollapsed-levels'.
+%C    Group comment (string)
 %D    Group description (string)
 %s    Select method (string)
 %o    Moderated group (char, \"m\")
@@ -173,13 +176,10 @@ with some simple extensions.
 %E    Icon as defined by `gnus-group-icon-list'.
 %u    User defined specifier.  The next character in the format string should
       be a letter.  Gnus will call the function gnus-user-format-function-X,
-      where X is the letter following %u.  The function will be passed the
-      current header as argument.  The function should return a string, which
-      will be inserted into the buffer just like information from any other
-      group specifier.
-
-Text between %( and %) will be highlighted with `gnus-mouse-face' when
-the mouse point move inside the area.  There can only be one such area.
+      where X is the letter following %u.  The function will be passed a 
+      single dummy parameter as argument..  The function should return a
+      string, which will be inserted into the buffer just like information
+      from any other group specifier.
 
 Note that this format specification is not always respected.  For
 reasons of efficiency, when listing killed groups, this specification
@@ -191,7 +191,11 @@ 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."
+effect.
+
+General format specifiers can also be used.
+See Info node `(gnus)Formatting Variables'."
+  :link '(custom-manual "(gnus)Formatting Variables")
   :group 'gnus-group-visual
   :type 'string)
 
@@ -412,7 +416,7 @@ For example:
 
 (defcustom gnus-group-name-charset-group-alist
   (if (or (and (fboundp 'find-coding-system) (find-coding-system 'utf-8))
-         (and (fboundp 'coding-system-p) (coding-system-p 'utf-8)))
+         (and (fboundp 'coding-system-p) (coding-system-p 'utf-8)))
       '((".*" . utf-8))
     nil)
   "Alist of group regexp and the charset for group names.
@@ -473,6 +477,7 @@ simple manner.")
     (?g gnus-tmp-group ?s)
     (?G gnus-tmp-qualified-group ?s)
     (?c (gnus-short-group-name gnus-tmp-group) ?s)
+    (?C gnus-tmp-comment ?s)
     (?D gnus-tmp-newsgroup-description ?s)
     (?o gnus-tmp-moderated ?c)
     (?O gnus-tmp-moderated-string ?s)
@@ -543,6 +548,7 @@ simple manner.")
     "l" gnus-group-list-groups
     "L" gnus-group-list-all-groups
     "m" gnus-group-mail
+    "i" gnus-group-news
     "g" gnus-group-get-new-news
     "\M-g" gnus-group-get-new-news-this-group
     "R" gnus-group-restart
@@ -697,6 +703,8 @@ simple manner.")
     "f" gnus-score-flush-cache)
 
   (gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map)
+    "c" gnus-group-fetch-charter
+    "C" gnus-group-fetch-control
     "d" gnus-group-describe-group
     "f" gnus-group-fetch-faq
     "v" gnus-version)
@@ -741,6 +749,12 @@ simple manner.")
        ,@(if (featurep 'xemacs) nil
            '(:help "Display description of the current group"))]
        ["Fetch FAQ" gnus-group-fetch-faq (gnus-group-group-name)]
+       ["Fetch charter" gnus-group-fetch-charter :active (gnus-group-group-name)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Display the charter of the current group"))]
+       ["Fetch control message" gnus-group-fetch-control :active (gnus-group-group-name)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Display the archived control message for the current group"))]
        ;; Actually one should check, if any of the marked groups gives t for
        ;; (gnus-check-backend-function 'request-expire-articles ...)
        ["Expire articles" gnus-group-expire-articles
@@ -748,7 +762,7 @@ simple manner.")
                 (gnus-check-backend-function
                  'request-expire-articles
                  (gnus-group-group-name))) gnus-group-marked)]
-       ["Set group level" gnus-group-set-current-level
+       ["Set group level..." gnus-group-set-current-level
        (gnus-group-group-name)]
        ["Select quick" gnus-group-quick-select-group (gnus-group-group-name)]
        ["Customize" gnus-group-customize (gnus-group-group-name)]
@@ -785,7 +799,8 @@ simple manner.")
        ["Sort by score" gnus-group-sort-groups-by-score t]
        ["Sort by level" gnus-group-sort-groups-by-level t]
        ["Sort by unread" gnus-group-sort-groups-by-unread t]
-       ["Sort by name" gnus-group-sort-groups-by-alphabet t])
+       ["Sort by name" gnus-group-sort-groups-by-alphabet t]
+       ["Sort by real name" gnus-group-sort-groups-by-real-name t])
        ("Sort process/prefixed"
        ["Default sort" gnus-group-sort-selected-groups
         (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
@@ -800,6 +815,8 @@ simple manner.")
        ["Sort by unread" gnus-group-sort-selected-groups-by-unread
         (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
        ["Sort by name" gnus-group-sort-selected-groups-by-alphabet
+        (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
+       ["Sort by real name" gnus-group-sort-selected-groups-by-real-name
         (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))])
        ("Mark"
        ["Mark group" gnus-group-mark-group
@@ -815,22 +832,22 @@ simple manner.")
        ["Execute command" gnus-group-universal-argument
         (or gnus-group-marked (gnus-group-group-name))])
        ("Subscribe"
-       ["Subscribe to a group" gnus-group-unsubscribe-group t]
+       ["Subscribe to a group..." gnus-group-unsubscribe-group t]
        ["Kill all newsgroups in region" gnus-group-kill-region t]
        ["Kill all zombie groups" gnus-group-kill-all-zombies
         gnus-zombie-list]
        ["Kill all groups on level..." gnus-group-kill-level t])
        ("Foreign groups"
-       ["Make a foreign group" gnus-group-make-group t]
-       ["Add a directory group" gnus-group-make-directory-group t]
+       ["Make a foreign group..." gnus-group-make-group t]
+       ["Add a directory group..." gnus-group-make-directory-group t]
        ["Add the help group" gnus-group-make-help-group t]
        ["Add the archive group" gnus-group-make-archive-group t]
-       ["Make a doc group" gnus-group-make-doc-group t]
-       ["Make a web group" gnus-group-make-web-group t]
-       ["Make a kiboze group" gnus-group-make-kiboze-group t]
-       ["Make a virtual group" gnus-group-make-empty-virtual t]
-       ["Add a group to a virtual" gnus-group-add-to-virtual t]
-       ["Rename group" gnus-group-rename-group
+       ["Make a doc group..." gnus-group-make-doc-group t]
+       ["Make a web group..." gnus-group-make-web-group t]
+       ["Make a kiboze group..." gnus-group-make-kiboze-group t]
+       ["Make a virtual group..." gnus-group-make-empty-virtual t]
+       ["Add a group to a virtual..." gnus-group-add-to-virtual t]
+       ["Rename group..." gnus-group-rename-group
         (gnus-check-backend-function
          'request-rename-group (gnus-group-group-name))]
        ["Delete group" gnus-group-delete-group
@@ -844,9 +861,12 @@ simple manner.")
        ["Next unread same level" gnus-group-next-unread-group-same-level t]
        ["Previous unread same level"
         gnus-group-prev-unread-group-same-level t]
-       ["Jump to group" gnus-group-jump-to-group t]
+       ["Jump to group..." gnus-group-jump-to-group t]
        ["First unread group" gnus-group-first-unread-group t]
        ["Best unread group" gnus-group-best-unread-group t])
+       ("Sieve"
+       ["Generate" gnus-sieve-generate t]
+       ["Generate and update" gnus-sieve-update t])
        ["Delete bogus groups" gnus-group-check-bogus-groups t]
        ["Find new newsgroups" gnus-group-find-new-groups t]
        ["Transpose" gnus-group-transpose-groups
@@ -864,19 +884,20 @@ simple manner.")
        ["Save areas" gnus-soup-save-areas (fboundp 'gnus-soup-pack-packet)]
        ["Brew SOUP" gnus-group-brew-soup (fboundp 'gnus-soup-pack-packet)])
        ["Send a mail" gnus-group-mail t]
-       ["Post an article..." gnus-group-post-news t]
+       ["Send a message (mail or news)" gnus-group-post-news t]
+       ["Create a local message" gnus-group-news t]
        ["Check for new news" gnus-group-get-new-news
        ,@(if (featurep 'xemacs) '(t)
            '(:help "Get newly arrived articles"))
        ]
-       ["Send delayed articles" gnus-delay-send-drafts
+       ["Send queued messages" gnus-delay-send-queue
        ,@(if (featurep 'xemacs) '(t)
-           '(:help "Send all articles that are scheduled to be sent now"))
+           '(:help "Send all messages that are scheduled to be sent now"))
        ]
        ["Activate all groups" gnus-activate-all-groups t]
        ["Restart Gnus" gnus-group-restart t]
        ["Read init file" gnus-group-read-init-file t]
-       ["Browse foreign server" gnus-group-browse-foreign-server t]
+       ["Browse foreign server..." gnus-group-browse-foreign-server t]
        ["Enter server buffer" gnus-group-enter-server-mode t]
        ["Expire all expirable articles" gnus-group-expire-all-groups t]
        ["Generate any kiboze groups" nnkiboze-generate-groups t]
@@ -899,9 +920,11 @@ simple manner.")
 
 ;; Emacs 21 tool bar.  Should be no-op otherwise.
 (defun gnus-group-make-tool-bar ()
-  (if (and (fboundp 'tool-bar-add-item-from-menu)
-          (default-value 'tool-bar-mode)
-          (not gnus-group-toolbar-map))
+  (if (and 
+       (condition-case nil (require 'tool-bar) (error nil))
+       (fboundp 'tool-bar-add-item-from-menu)
+       (default-value 'tool-bar-mode)
+       (not gnus-group-toolbar-map))
       (setq gnus-group-toolbar-map
            (let ((tool-bar-map (make-sparse-keymap))
                  (load-path (mm-image-load-path)))
@@ -1009,7 +1032,7 @@ The following commands are available:
     (when gnus-carpal
       (gnus-carpal-setup-buffer 'group))))
 
-(defsubst gnus-group-name-charset (method group)
+(defun gnus-group-name-charset (method group)
   (if (null method)
       (setq method (gnus-find-method-for-group group)))
   (let ((item (assoc method gnus-group-name-charset-method-alist))
@@ -1023,7 +1046,7 @@ The following commands are available:
                  result (cdr item))))
       result)))
 
-(defsubst gnus-group-name-decode (string charset)
+(defun gnus-group-name-decode (string charset)
   (if (and string charset (featurep 'mule))
       (mm-decode-coding-string string charset)
     string))
@@ -1307,6 +1330,9 @@ if it is a string, only list groups matching REGEXP."
         (gnus-tmp-qualified-group
          (gnus-group-name-decode (gnus-group-real-name gnus-tmp-group)
                                  group-name-charset))
+        (gnus-tmp-comment 
+         (or (gnus-group-get-parameter gnus-tmp-group 'comment t)
+             gnus-tmp-group))
         (gnus-tmp-newsgroup-description
          (if gnus-description-hashtb
              (or (gnus-group-name-decode
@@ -1704,7 +1730,7 @@ Take into consideration N (the prefix) and the list of marked groups."
          (setq n (1- n))
          (gnus-group-next-group way)))
       (nreverse groups)))
-   ((gnus-region-active-p)
+   ((and (gnus-region-active-p) (mark))
     ;; Work on the region between point and mark.
     (let ((max (max (point) (mark)))
          groups)
@@ -1835,13 +1861,13 @@ be permanent."
      (gnus-group-prefixed-name group method) method)))
 
 ;;;###autoload
-(defun gnus-fetch-group (group)
+(defun gnus-fetch-group (group &optional articles)
   "Start Gnus if necessary and enter GROUP.
 Returns whether the fetching was successful or not."
   (interactive (list (completing-read "Group name: " gnus-active-hashtb)))
   (unless (get-buffer gnus-group-buffer)
     (gnus-no-server))
-  (gnus-group-read-group nil nil group))
+  (gnus-group-read-group articles nil group))
 
 ;;;###autoload
 (defun gnus-fetch-group-other-frame (group)
@@ -1862,13 +1888,15 @@ Returns whether the fetching was successful or not."
 ;; if selection was successful.
 (defun gnus-group-read-ephemeral-group (group method &optional activate
                                              quit-config request-only
-                                             select-articles)
+                                             select-articles
+                                             parameters)
   "Read GROUP from METHOD as an ephemeral group.
 If ACTIVATE, request the group first.
 If QUIT-CONFIG, use that window configuration when exiting from the
 ephemeral group.
 If REQUEST-ONLY, don't actually read the group; just request it.
 If SELECT-ARTICLES, only select those articles.
+If PARAMETERS, use those as the group parameters.
 
 Return the name of the group if selection was successful."
   ;; Transform the select method into a unique server.
@@ -1879,15 +1907,19 @@ Return the name of the group if selection was successful."
          (,(intern (format "%s-address" (car method))) ,(cadr method))
          ,@(cddr method)))
   (let ((group (if (gnus-group-foreign-p group) group
-                (gnus-group-prefixed-name group method))))
+                (gnus-group-prefixed-name (gnus-group-real-name group)
+                                          method))))
     (gnus-sethash
      group
      `(-1 nil (,group
               ,gnus-level-default-subscribed nil nil ,method
-              ((quit-config .
-                            ,(if quit-config quit-config
-                               (cons gnus-summary-buffer
-                                     gnus-current-window-configuration))))))
+              ,(cons
+                (if quit-config
+                    (cons 'quit-config quit-config)
+                  (cons 'quit-config
+                        (cons gnus-summary-buffer
+                              gnus-current-window-configuration)))
+                parameters)))
      gnus-newsrc-hashtb)
     (push method gnus-ephemeral-servers)
     (set-buffer gnus-group-buffer)
@@ -2060,7 +2092,7 @@ If EXCLUDE-GROUP, do not go to that group."
       (forward-line 1))
     (when best-point
       (goto-char best-point))
-    (gnus-summary-position-point)
+    (gnus-group-position-point)
     (and best-point (gnus-group-group-name))))
 
 (defun gnus-group-first-unread-group ()
@@ -2173,6 +2205,10 @@ doing the deletion."
          (gnus-group-goto-group group)
          (gnus-group-kill-group 1 t)
          (gnus-sethash group nil gnus-active-hashtb)
+         (when (and (boundp 'gnus-cache-active-hashtb)
+                    gnus-cache-active-hashtb)
+           (gnus-sethash group nil gnus-cache-active-hashtb)
+           (setq gnus-cache-active-altered t))
          t))
     (gnus-group-position-point)))
 
@@ -2257,7 +2293,7 @@ and NEW-NAME will be prompted for."
      `(lambda (form)
        (gnus-group-edit-group-done ',part ,group form)))
     (local-set-key
-     "\C-c\C-i" 
+     "\C-c\C-i"
      (gnus-create-info-command
       (cond
        ((eq part 'method)
@@ -2326,20 +2362,33 @@ and NEW-NAME will be prompted for."
       (setcar entry (eval (cadar entry)))))
   (gnus-group-make-group group method))
 
-(defun gnus-group-make-help-group ()
-  "Create the Gnus documentation group."
+(defun gnus-group-make-help-group (&optional noerror)
+  "Create the Gnus documentation group.
+Optional argument NOERROR modifies the behavior of this function when the
+group already exists:
+- if not given, and error is signaled,
+- if t, stay silent,
+- if anything else, just print a message."
   (interactive)
   (let ((name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help")))
        (file (nnheader-find-etc-directory "gnus-tut.txt" t)))
-    (when (gnus-gethash name gnus-newsrc-hashtb)
-      (error "Documentation group already exists"))
-    (if (not file)
-       (gnus-message 1 "Couldn't find doc group")
-      (gnus-group-make-group
-       (gnus-group-real-name name)
-       (list 'nndoc "gnus-help"
-            (list 'nndoc-address file)
-            (list 'nndoc-article-type 'mbox)))))
+    (if (gnus-gethash name gnus-newsrc-hashtb)
+       (cond ((eq noerror nil)
+              (error "Documentation group already exists"))
+             ((eq noerror t)
+              ;; stay silent
+              )
+             (t
+              (gnus-message 1 "Documentation group already exists")))
+      ;; else:
+      (if (not file)
+         (gnus-message 1 "Couldn't find doc group")
+       (gnus-group-make-group
+        (gnus-group-real-name name)
+        (list 'nndoc "gnus-help"
+              (list 'nndoc-address file)
+              (list 'nndoc-article-type 'mbox))))
+      ))
   (gnus-group-position-point))
 
 (defun gnus-group-make-doc-group (file type)
@@ -2660,6 +2709,12 @@ If REVERSE, sort in reverse order."
   (interactive "P")
   (gnus-group-sort-groups 'gnus-group-sort-by-alphabet reverse))
 
+(defun gnus-group-sort-groups-by-real-name (&optional reverse)
+  "Sort the group buffer alphabetically by real (unprefixed) group name.
+If REVERSE, sort in reverse order."
+  (interactive "P")
+  (gnus-group-sort-groups 'gnus-group-sort-by-real-name reverse))
+
 (defun gnus-group-sort-groups-by-unread (&optional reverse)
   "Sort the group buffer by number of unread articles.
 If REVERSE, sort in reverse order."
@@ -2738,6 +2793,13 @@ sort in reverse order."
   (interactive (gnus-interactive "P\ny"))
   (gnus-group-sort-selected-groups n 'gnus-group-sort-by-alphabet reverse))
 
+(defun gnus-group-sort-selected-groups-by-real-name (&optional n reverse)
+  "Sort the group buffer alphabetically by real group name.
+Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
+sort in reverse order."
+  (interactive (gnus-interactive "P\ny"))
+  (gnus-group-sort-selected-groups n 'gnus-group-sort-by-real-name reverse))
+
 (defun gnus-group-sort-selected-groups-by-unread (&optional n reverse)
   "Sort the group buffer by number of unread articles.
 Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
@@ -2797,10 +2859,10 @@ sort in reverse order."
 
 (defun gnus-group-sort-by-method (info1 info2)
   "Sort alphabetically by backend name."
-  (string< (symbol-name (car (gnus-find-method-for-group
-                             (gnus-info-group info1) info1)))
-          (symbol-name (car (gnus-find-method-for-group
-                             (gnus-info-group info2) info2)))))
+  (string< (car (gnus-find-method-for-group
+                (gnus-info-group info1) info1))
+          (car (gnus-find-method-for-group
+                (gnus-info-group info2) info2))))
 
 (defun gnus-group-sort-by-server (info1 info2)
   "Sort alphabetically by server name."
@@ -3443,7 +3505,7 @@ to use."
     (gnus-group-group-name)
     (when current-prefix-arg
       (completing-read
-       "Faq dir: " (and (listp gnus-group-faq-directory)
+       "FAQ dir: " (and (listp gnus-group-faq-directory)
                        (mapcar #'list
                                gnus-group-faq-directory))))))
   (unless group
@@ -3462,6 +3524,51 @@ to use."
          (find-file file)
          (setq found t))))))
 
+(defun gnus-group-fetch-charter (group)
+  "Fetch the charter for the current group.
+If given a prefix argument, prompt for a group."
+  (interactive
+   (list (or (when current-prefix-arg
+              (completing-read "Group: " gnus-active-hashtb))
+            (gnus-group-group-name)
+            gnus-newsgroup-name)))
+  (unless group
+    (error "No group name given"))
+  (require 'mm-url)
+  (let ((name (mm-url-form-encode-xwfu (gnus-group-real-name group)))
+       url hierarchy)
+    (when (string-match "\\(^[^\\.]+\\)\\..*" name)
+      (setq hierarchy (match-string 1 name))
+      (if (setq url (cdr (assoc hierarchy gnus-group-charter-alist)))
+         (browse-url (eval url))
+       (gnus-group-fetch-control group)))))
+
+(defun gnus-group-fetch-control (group)
+  "Fetch the archived control messages for the current group.
+If given a prefix argument, prompt for a group."
+  (interactive
+   (list (or (when current-prefix-arg
+              (completing-read "Group: " gnus-active-hashtb))
+            (gnus-group-group-name)
+            gnus-newsgroup-name)))
+  (unless group
+    (error "No group name given"))
+  (let ((name (gnus-group-real-name group))
+       hierarchy)
+    (when (string-match "\\(^[^\\.]+\\)\\..*" name)
+      (setq hierarchy (match-string 1 name))
+      (if gnus-group-fetch-control-use-browse-url
+         (browse-url (concat "ftp://ftp.isc.org/usenet/control/"
+                             hierarchy "/" name ".Z"))
+       (let ((enable-local-variables nil))
+         (gnus-group-read-ephemeral-group
+          group
+          `(nndoc ,group (nndoc-address 
+                          ,(find-file-noselect
+                            (concat "/ftp@ftp.isc.org:/usenet/control/" 
+                                    hierarchy "/" name ".Z")))
+                  (nndoc-article-type mbox)) t nil nil))))))
+
 (defun gnus-group-describe-group (force &optional group)
   "Display a description of the current newsgroup."
   (interactive (list current-prefix-arg (gnus-group-group-name)))
@@ -3625,7 +3732,7 @@ group."
 
 (defun gnus-group-find-new-groups (&optional arg)
   "Search for new groups and add them.
-Each new group will be treated with `gnus-subscribe-newsgroup-method.'
+Each new group will be treated with `gnus-subscribe-newsgroup-method'.
 With 1 C-u, use the `ask-server' method to query the server for new
 groups.
 With 2 C-u's, use most complete method possible to query the server
@@ -3666,7 +3773,11 @@ The hook gnus-suspend-gnus-hook is called before actually suspending."
   ;; Kill Gnus buffers except for group mode buffer.
   (let ((group-buf (get-buffer gnus-group-buffer)))
     (mapcar (lambda (buf)
-             (unless (member buf (list group-buf gnus-dribble-buffer))
+             (unless (or (member buf (list group-buf gnus-dribble-buffer))
+                         (progn
+                           (save-excursion
+                             (set-buffer buf)
+                             (eq major-mode 'message-mode))))
                (gnus-kill-buffer buf)))
            (gnus-buffers))
     (gnus-kill-gnus-frames)
@@ -3986,22 +4097,30 @@ This command may read the active file."
 
 (defun gnus-group-mark-article-read (group article)
   "Mark ARTICLE read."
-  (gnus-activate-group group)
   (let ((buffer (gnus-summary-buffer-name group))
-       (mark gnus-read-mark))
-    (unless
-       (and
-        (get-buffer buffer)
-        (with-current-buffer buffer
-          (when gnus-newsgroup-prepared
-            (when (and gnus-newsgroup-auto-expire
-                       (memq mark gnus-auto-expirable-marks))
-              (setq mark gnus-expirable-mark))
-            (setq mark (gnus-request-update-mark
-                        group article mark))
-            (gnus-mark-article-as-read article mark)
-            (setq gnus-newsgroup-active (gnus-active group))
-            t)))
+       (mark gnus-read-mark)
+       active n)
+    (if (get-buffer buffer)
+       (with-current-buffer buffer
+         (setq active gnus-newsgroup-active)
+         (gnus-activate-group group)
+         (when gnus-newsgroup-prepared
+           (when (and gnus-newsgroup-auto-expire
+                      (memq mark gnus-auto-expirable-marks))
+             (setq mark gnus-expirable-mark))
+           (setq mark (gnus-request-update-mark
+                       group article mark))
+           (gnus-mark-article-as-read article mark)
+           (setq gnus-newsgroup-active (gnus-active group))
+           (when active
+             (setq n (1+ (cdr active)))
+             (while (<= n (cdr gnus-newsgroup-active))
+               (unless (eq n article)
+                 (push n gnus-newsgroup-unselected))
+               (setq n (1+ n)))
+             (setq gnus-newsgroup-unselected
+                   (nreverse gnus-newsgroup-unselected)))))
+      (gnus-activate-group group)
       (gnus-group-make-articles-read group
                                     (list article))
       (when (gnus-group-auto-expirable-p group)