2001-12-18 01:00:00 ShengHuo ZHU <zsh@cs.rochester.edu>
[gnus] / lisp / gnus-sum.el
index 3167efe..88e7462 100644 (file)
@@ -434,7 +434,7 @@ this variable specifies group names."
   :group 'gnus-summary-marks
   :type 'character)
 
-(defcustom gnus-forwarded-mark ?O
+(defcustom gnus-forwarded-mark ?F
   "*Mark used for articles that have been forwarded."
   :group 'gnus-summary-marks
   :type 'character)
@@ -450,7 +450,12 @@ this variable specifies group names."
   :type 'character)
 
 (defcustom gnus-saved-mark ?S
-  "*Mark used for articles that have been saved to."
+  "*Mark used for articles that have been saved."
+  :group 'gnus-summary-marks
+  :type 'character)
+
+(defcustom gnus-unseen-mark ?.
+  "*Mark used for articles that haven't been seen."
   :group 'gnus-summary-marks
   :type 'character)
 
@@ -691,7 +696,7 @@ This variable is local to the summary buffers."
 (defcustom gnus-summary-mode-hook nil
   "*A hook for Gnus summary mode.
 This hook is run before any variables are set in the summary buffer."
-  :options '(turn-on-gnus-mailing-list-mode)
+  :options '(turn-on-gnus-mailing-list-mode gnus-pick-mode)
   :group 'gnus-summary-various
   :type 'hook)
 
@@ -993,6 +998,11 @@ that were fetched.  Say, for nnultimate groups."
   :group 'gnus-summary
   :type '(choice boolean regexp))
 
+(defcustom gnus-summary-muttprint-program "muttprint"
+  "Command (and optional arguments) used to run Muttprint."
+  :group 'gnus-summary
+  :type 'string)
+
 ;;; Internal variables
 
 (defvar gnus-summary-display-cache nil)
@@ -1066,7 +1076,8 @@ that were fetched.  Say, for nnultimate groups."
     (?l (bbb-grouplens-score gnus-tmp-header) ?s)
     (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
     (?U gnus-tmp-unread ?c)
-    (?f (gnus-summary-from-or-to-or-newsgroups gnus-tmp-header) ?s)
+    (?f (gnus-summary-from-or-to-or-newsgroups gnus-tmp-header gnus-tmp-from)
+       ?s)
     (?t (gnus-summary-number-of-articles-in-thread
         (and (boundp 'thread) (car thread)) gnus-tmp-level)
        ?d)
@@ -1075,7 +1086,9 @@ that were fetched.  Say, for nnultimate groups."
        ?c)
     (?u gnus-tmp-user-defined ?s)
     (?P (gnus-pick-line-number) ?d)
-    (?B gnus-tmp-thread-tree-header-string ?s))
+    (?B gnus-tmp-thread-tree-header-string ?s)
+    (user-date (gnus-user-date
+               ,(macroexpand '(mail-header-date gnus-tmp-header))) ?s))
   "An alist of format specifications that can appear in summary lines.
 These are paired with what variables they correspond with, along with
 the type of the variable (string, integer, character, etc).")
@@ -1178,6 +1191,15 @@ the type of the variable (string, integer, character, etc).")
 (defvar gnus-newsgroup-dormant nil
   "List of dormant articles in the current newsgroup.")
 
+(defvar gnus-newsgroup-unseen nil
+  "List of unseen articles in the current newsgroup.")
+
+(defvar gnus-newsgroup-seen nil
+  "Range of seen articles in the current newsgroup.")
+
+(defvar gnus-newsgroup-articles nil
+  "List of articles in the current newsgroup.")
+
 (defvar gnus-newsgroup-scored nil
   "List of scored articles in the current newsgroup.")
 
@@ -1219,7 +1241,8 @@ the type of the variable (string, integer, character, etc).")
     gnus-newsgroup-expirable
     gnus-newsgroup-processable gnus-newsgroup-killed
     gnus-newsgroup-downloadable gnus-newsgroup-undownloaded
-    gnus-newsgroup-unsendable
+    gnus-newsgroup-unsendable gnus-newsgroup-unseen
+    gnus-newsgroup-seen gnus-newsgroup-articles
     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
     gnus-newsgroup-headers gnus-newsgroup-threads
     gnus-newsgroup-prepared gnus-summary-highlight-line-function
@@ -1245,7 +1268,19 @@ the type of the variable (string, integer, character, etc).")
   "Variables that are buffer-local to the summary buffers.")
 
 (defvar gnus-newsgroup-variables nil
-  "Variables that have separate values in the newsgroups.")
+  "A list of variables that have separate values in different newsgroups.
+A list of newsgroup (summary buffer) local variables, or cons of
+variables and their default values (when the default values are not
+nil), that should be made global while the summary buffer is active.
+These variables can be used to set variables in the group parameters
+while still allowing them to affect operations done in other
+buffers. For example:
+
+(setq gnus-newsgroup-variables
+     '(message-use-followup-to
+       (gnus-visible-headers .
+        \"^From:\\\\|^Newsgroups:\\\\|^Subject:\\\\|^Date:\\\\|^To:\")))
+")
 
 ;; Byte-compiler warning.
 (eval-when-compile (defvar gnus-article-mode-map))
@@ -1512,6 +1547,7 @@ increase the score of each group you read."
     gnus-mouse-2 gnus-mouse-pick-article
     "m" gnus-summary-mail-other-window
     "a" gnus-summary-post-news
+    "i" gnus-summary-news-other-window
     "x" gnus-summary-limit-to-unread
     "s" gnus-summary-isearch-article
     "t" gnus-summary-toggle-header
@@ -1585,6 +1621,7 @@ increase the score of each group you read."
     "d" gnus-summary-limit-exclude-dormant
     "t" gnus-summary-limit-to-age
     "x" gnus-summary-limit-to-extra
+    "p" gnus-summary-limit-to-display-predicate
     "E" gnus-summary-limit-include-expunged
     "c" gnus-summary-limit-exclude-childless-dormant
     "C" gnus-summary-limit-mark-excluded-as-read
@@ -1684,6 +1721,7 @@ increase the score of each group you read."
     "l" gnus-summary-stop-page-breaking
     "r" gnus-summary-caesar-message
     "t" gnus-summary-toggle-header
+    "g" gnus-summary-toggle-smiley
     "v" gnus-summary-verbose-headers
     "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
     "p" gnus-article-verify-x-pgp-sig
@@ -1768,6 +1806,7 @@ increase the score of each group you read."
     "h" gnus-summary-save-article-folder
     "v" gnus-summary-save-article-vm
     "p" gnus-summary-pipe-output
+    "P" gnus-summary-muttprint
     "s" gnus-soup-add-article)
 
   (gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map)
@@ -1878,6 +1917,7 @@ increase the score of each group you read."
              ["Stop page breaking" gnus-summary-stop-page-breaking t]
              ["Verbose header" gnus-summary-verbose-headers t]
              ["Toggle header" gnus-summary-toggle-header t]
+             ["Toggle smiley" gnus-summary-toggle-smiley t]
              ["Html" gnus-article-wash-html t]
              ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t]
              ["HZ" gnus-article-decode-HZ t])
@@ -1895,6 +1935,7 @@ increase the score of each group you read."
              ["Save body in file" gnus-summary-save-article-body-file t]
              ["Pipe through a filter" gnus-summary-pipe-output t]
              ["Add to SOUP packet" gnus-soup-add-article t]
+             ["Print with Muttprint" gnus-summary-muttprint t]
              ["Print" gnus-summary-print-article t])
             ("Backend"
              ["Respool article..." gnus-summary-respool-article t]
@@ -1979,7 +2020,7 @@ increase the score of each group you read."
     (easy-menu-define
       gnus-summary-post-menu gnus-summary-mode-map ""
       `("Post"
-       ["Post an article" gnus-summary-post-news
+       ["Send a message (mail or news)" gnus-summary-post-news
         ,@(if (featurep 'xemacs) '(t)
             '(:help "Post an article"))]
        ["Followup" gnus-summary-followup
@@ -2005,6 +2046,7 @@ increase the score of each group you read."
        ["Resend message" gnus-summary-resend-message t]
        ["Send bounced mail" gnus-summary-resend-bounced-mail t]
        ["Send a mail" gnus-summary-mail-other-window t]
+       ["Create a local message" gnus-summary-news-other-window t]
        ["Uuencode and post" gnus-uu-post-news
         ,@(if (featurep 'xemacs) '(t)
             '(:help "Post a uuencoded article"))]
@@ -2056,6 +2098,7 @@ increase the score of each group you read."
         ["Age..." gnus-summary-limit-to-age t]
         ["Extra..." gnus-summary-limit-to-extra t]
         ["Score" gnus-summary-limit-to-score t]
+        ["Display Predicate" gnus-summary-limit-to-display-predicate t]
         ["Unread" gnus-summary-limit-to-unread t]
         ["Non-dormant" gnus-summary-limit-exclude-dormant t]
         ["Articles" gnus-summary-limit-to-articles t]
@@ -2741,7 +2784,7 @@ display only a single character."
 
 (defun gnus-summary-buffer-name (group)
   "Return the summary buffer name of GROUP."
-  (concat "*Summary " group "*"))
+  (concat "*Summary " (gnus-group-decoded-name group) "*"))
 
 (defun gnus-summary-setup-buffer (group)
   "Initialize summary buffer."
@@ -2885,32 +2928,31 @@ buffer that was in action when the last article was fetched."
    (point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
    (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
 
-(defun gnus-summary-from-or-to-or-newsgroups (header)
-  (let ((to (cdr (assq 'To (mail-header-extra header))))
-       (newsgroups (cdr (assq 'Newsgroups (mail-header-extra header))))
-       (mail-parse-charset gnus-newsgroup-charset)
+(defun gnus-summary-extract-address-component (from)
+  (or (car (funcall gnus-extract-address-components from))
+      from))
+
+(defun gnus-summary-from-or-to-or-newsgroups (header gnus-tmp-from)
+  (let ((mail-parse-charset gnus-newsgroup-charset)
+       ; Is it really necessary to do this next part for each summary line?
+       ; Luckily, doesn't seem to slow things down much.
        (mail-parse-ignored-charsets
         (save-excursion (set-buffer gnus-summary-buffer)
                         gnus-newsgroup-ignored-charsets)))
-    (cond
-     ((and to
-          gnus-ignored-from-addresses
-          (string-match gnus-ignored-from-addresses
-                        (mail-header-from header)))
-      (concat "-> "
-             (or (car (funcall gnus-extract-address-components
-                               (funcall
-                                gnus-decode-encoded-word-function to)))
-                 (funcall gnus-decode-encoded-word-function to))))
-     ((and newsgroups
-          gnus-ignored-from-addresses
-          (string-match gnus-ignored-from-addresses
-                        (mail-header-from header)))
-      (concat "=> " newsgroups))
-     (t
-      (or (car (funcall gnus-extract-address-components
-                       (mail-header-from header)))
-         (mail-header-from header))))))
+    (or
+     (and gnus-ignored-from-addresses
+         (string-match gnus-ignored-from-addresses gnus-tmp-from)
+         (let ((extra-headers (mail-header-extra header))
+               to
+               newsgroups)
+           (cond
+            ((setq to (cdr (assq 'To extra-headers)))
+             (concat "-> "
+                     (gnus-summary-extract-address-component
+                      (funcall gnus-decode-encoded-word-function to))))
+            ((setq newsgroups (cdr (assq 'Newsgroups extra-headers)))
+             (concat "=> " newsgroups)))))
+     (gnus-summary-extract-address-component gnus-tmp-from))))
 
 (defun gnus-summary-insert-line (gnus-tmp-header
                                 gnus-tmp-level gnus-tmp-current
@@ -2928,13 +2970,20 @@ buffer that was in action when the last article was fetched."
              ?                         ;Whitespace
            (if (< gnus-tmp-score gnus-summary-default-score)
                gnus-score-below-mark gnus-score-over-mark)))
+        (gnus-tmp-number (mail-header-number gnus-tmp-header))
         (gnus-tmp-replied
          (cond (gnus-tmp-process gnus-process-mark)
                ((memq gnus-tmp-current gnus-newsgroup-cached)
                 gnus-cached-mark)
                (gnus-tmp-replied gnus-replied-mark)
+               ((memq gnus-tmp-current gnus-newsgroup-forwarded)
+                gnus-forwarded-mark)
                ((memq gnus-tmp-current gnus-newsgroup-saved)
                 gnus-saved-mark)
+               ((memq gnus-tmp-number gnus-newsgroup-recent)
+                gnus-recent-mark)
+               ((memq gnus-tmp-number gnus-newsgroup-unseen)
+                gnus-unseen-mark)
                (t gnus-no-mark)))
         (gnus-tmp-from (mail-header-from gnus-tmp-header))
         (gnus-tmp-name
@@ -2949,7 +2998,6 @@ buffer that was in action when the last article was fetched."
                       (1+ (match-beginning 0)) (1- (match-end 0))))
           (t gnus-tmp-from)))
         (gnus-tmp-subject (mail-header-subject gnus-tmp-header))
-        (gnus-tmp-number (mail-header-number gnus-tmp-header))
         (gnus-tmp-opening-bracket (if gnus-tmp-dummy ?\< ?\[))
         (gnus-tmp-closing-bracket (if gnus-tmp-dummy ?\> ?\]))
         (buffer-read-only nil))
@@ -2957,8 +3005,9 @@ buffer that was in action when the last article was fetched."
       (setq gnus-tmp-name gnus-tmp-from))
     (unless (numberp gnus-tmp-lines)
       (setq gnus-tmp-lines -1))
-    (when (= gnus-tmp-lines -1)
-      (setq gnus-tmp-lines "?"))
+    (if (= gnus-tmp-lines -1)
+       (setq gnus-tmp-lines "?")
+      (setq gnus-tmp-lines (number-to-string gnus-tmp-lines)))
     (gnus-put-text-property
      (point)
      (progn (eval gnus-summary-line-format-spec) (point))
@@ -4333,6 +4382,8 @@ or a straight list of headers."
                    gnus-saved-mark)
                   ((memq number gnus-newsgroup-recent)
                    gnus-recent-mark)
+                  ((memq number gnus-newsgroup-unseen)
+                   gnus-unseen-mark)
                   (t gnus-no-mark))
             gnus-tmp-from (mail-header-from gnus-tmp-header)
             gnus-tmp-name
@@ -4347,28 +4398,29 @@ or a straight list of headers."
                          (1+ (match-beginning 0)) (1- (match-end 0))))
              (t gnus-tmp-from))
             gnus-tmp-thread-tree-header-string
-            (cond 
+            (cond
              ((not gnus-show-threads) "")
              ((zerop gnus-tmp-level)
-              (if (cdar thread) 
+              (if (cdar thread)
                   (or gnus-sum-thread-tree-root subject)
                 (or gnus-sum-thread-tree-single-indent subject)))
              (t
               (concat (apply 'concat
-                             (mapcar (lambda (item) 
-                                       (if (= item 1) 
+                             (mapcar (lambda (item)
+                                       (if (= item 1)
                                            gnus-sum-thread-tree-vertical
                                          gnus-sum-thread-tree-indent))
                                      (cdr (reverse tree-stack))))
-                      (if (nth 1 thread) 
+                      (if (nth 1 thread)
                           gnus-sum-thread-tree-leaf-with-other
                         gnus-sum-thread-tree-single-leaf)))))
            (when (string= gnus-tmp-name "")
              (setq gnus-tmp-name gnus-tmp-from))
            (unless (numberp gnus-tmp-lines)
              (setq gnus-tmp-lines -1))
-           (when (= gnus-tmp-lines -1)
-             (setq gnus-tmp-lines "?"))
+           (if (= gnus-tmp-lines -1)
+               (setq gnus-tmp-lines "?")
+             (setq gnus-tmp-lines (number-to-string gnus-tmp-lines)))
            (gnus-put-text-property
             (point)
             (progn (eval gnus-summary-line-format-spec) (point))
@@ -4488,8 +4540,8 @@ If SELECT-ARTICLES, only select those articles from GROUP."
         articles fetched-articles cached)
 
     (unless (gnus-check-server
-            (setq gnus-current-select-method
-                  (gnus-find-method-for-group group)))
+            (set (make-local-variable 'gnus-current-select-method)
+                 (gnus-find-method-for-group group)))
       (error "Couldn't open server"))
 
     (or (and entry (not (eq (car entry) t))) ; Either it's active...
@@ -4509,23 +4561,40 @@ If SELECT-ARTICLES, only select those articles from GROUP."
     (setq gnus-newsgroup-name group
          gnus-newsgroup-unselected nil
          gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
-    
-    (setq gnus-newsgroup-display (gnus-group-find-parameter group 'display))
-    (setq gnus-newsgroup-display
-         (cond
-          ((eq gnus-newsgroup-display 'all)
-           (setq gnus-newsgroup-display 'identity))
-          ((arrayp gnus-newsgroup-display)
-           (gnus-summary-display-make-predicate
-            (mapcar 'identity gnus-newsgroup-display)))
-          (t
-           nil)))
-      
-    (gnus-summary-setup-default-charset)
 
-    ;; Adjust and set lists of article marks.
-    (when info
-      (gnus-adjust-marked-articles info))
+    (let ((display (gnus-group-find-parameter group 'display)))
+      (setq gnus-newsgroup-display
+           (cond
+            ((not (zerop (or (car-safe read-all) 0)))
+             ;; The user entered the group with C-u SPC/RET, let's show
+             ;; all articles.
+             'gnus-not-ignore)
+            ((eq display 'all)
+             'gnus-not-ignore)
+            ((arrayp display)
+             (gnus-summary-display-make-predicate (mapcar 'identity display)))
+            ((numberp display)
+             ;; The following is probably the "correct" solution, but
+             ;; it makes Gnus fetch all headers and then limit the
+             ;; articles (which is slow), so instead we hack the
+             ;; select-articles parameter instead. -- Simon Josefsson
+             ;; <jas@kth.se>
+             ;;
+             ;; (gnus-byte-compile
+             ;;  `(lambda () (> number ,(- (cdr (gnus-active group))
+             ;;                         display)))))
+             (setq select-articles
+                   (gnus-uncompress-range
+                    (cons (let ((tmp (- (cdr (gnus-active group)) display)))
+                            (if (> tmp 0)
+                                tmp
+                              1))
+                          (cdr (gnus-active group)))))
+             nil)
+            (t
+             nil))))
+
+    (gnus-summary-setup-default-charset)
 
     ;; Kludge to avoid having cached articles nixed out in virtual groups.
     (when (gnus-virtual-group-p group)
@@ -4540,6 +4609,10 @@ If SELECT-ARTICLES, only select those articles from GROUP."
 
     (gnus-update-read-articles group gnus-newsgroup-unreads)
 
+    ;; Adjust and set lists of article marks.
+    (when info
+      (gnus-adjust-marked-articles info))
+
     (if (setq articles select-articles)
        (setq gnus-newsgroup-unselected
              (gnus-sorted-intersection
@@ -4571,12 +4644,22 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       ;; Set the initial limit.
       (setq gnus-newsgroup-limit (copy-sequence articles))
       ;; Remove canceled articles from the list of unread articles.
+      (setq fetched-articles
+           (mapcar (lambda (headers) (mail-header-number headers))
+                   gnus-newsgroup-headers))
+      (setq gnus-newsgroup-articles fetched-articles)
       (setq gnus-newsgroup-unreads
            (gnus-set-sorted-intersection
-            gnus-newsgroup-unreads
-            (setq fetched-articles
-                  (mapcar (lambda (headers) (mail-header-number headers))
-                          gnus-newsgroup-headers))))
+            gnus-newsgroup-unreads fetched-articles))
+
+      (let ((marks (assq 'seen (gnus-info-marks info))))
+       ;; The `seen' marks are treated specially.
+       (when (setq gnus-newsgroup-seen (cdr marks))
+         (dolist (article gnus-newsgroup-articles)
+           (unless (gnus-member-of-range
+                    article gnus-newsgroup-seen)
+             (push article gnus-newsgroup-unseen)))))
+
       ;; Removed marked articles that do not exist.
       (gnus-update-missing-marks
        (gnus-sorted-complement fetched-articles articles))
@@ -4613,11 +4696,13 @@ If SELECT-ARTICLES, only select those articles from GROUP."
   (when (= (length display) 1)
     (setq display (car display)))
   (unless gnus-summary-display-cache
-    (dolist (elem gnus-article-mark-lists)
-       (push (cons (cdr elem)
-                   (gnus-byte-compile
-                    `(lambda () (gnus-article-marked-p ',(cdr elem)))))
-             gnus-summary-display-cache)))
+    (dolist (elem (append (list (cons 'read 'read)
+                               (cons 'unseen 'unseen))
+                         gnus-article-mark-lists))
+      (push (cons (cdr elem)
+                 (gnus-byte-compile
+                  `(lambda () (gnus-article-marked-p ',(cdr elem)))))
+           gnus-summary-display-cache)))
   (let ((gnus-category-predicate-alist gnus-summary-display-cache))
     (gnus-get-predicate display)))
 
@@ -4656,6 +4741,8 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       (memq article gnus-newsgroup-cached))
      ((eq type 'forward)
       (memq article gnus-newsgroup-forwarded))
+     ((eq type 'seen)
+      (not (memq article gnus-newsgroup-unseen)))
      ((eq type 'recent)
       (memq article gnus-newsgroup-recent))
      (t t))))
@@ -4668,7 +4755,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
          (if (or read-all
                  (and (zerop (length gnus-newsgroup-marked))
                       (zerop (length gnus-newsgroup-unreads)))
-                 gnus-newsgroup-display)
+                 (eq gnus-newsgroup-display 'gnus-not-ignore))
              ;; We want to select the headers for all the articles in
              ;; the group, so we select either all the active
              ;; articles in the group, or (if that's nil), the
@@ -4764,6 +4851,15 @@ If SELECT-ARTICLES, only select those articles from GROUP."
       (setq marks (cdr marks)))
     out))
 
+(defun gnus-article-mark-to-type (mark)
+  "Return the type of MARK."
+  (or (cadr (assq mark gnus-article-special-mark-lists))
+      'list))
+
+(defun gnus-article-unpropagatable-p (mark)
+  "Return whether MARK should be propagated to backend."
+  (memq mark gnus-article-unpropagated-mark-lists))
+
 (defun gnus-adjust-marked-articles (info)
   "Set all article lists and remove all marks that are no longer valid."
   (let* ((marked-lists (gnus-info-marks info))
@@ -4771,28 +4867,26 @@ If SELECT-ARTICLES, only select those articles from GROUP."
         (min (car active))
         (max (cdr active))
         (types gnus-article-mark-lists)
-        (uncompressed '(score bookmark killed))
-        marks var articles article mark)
-
-    (while marked-lists
-      (setq marks (pop marked-lists))
-      (set (setq var (intern (format "gnus-newsgroup-%s"
-                                    (car (rassq (setq mark (car marks))
-                                                types)))))
-          (if (memq (car marks) uncompressed) (cdr marks)
-            (gnus-uncompress-range (cdr marks))))
+        marks var articles article mark mark-type)
 
-      (setq articles (symbol-value var))
+    (dolist (marks marked-lists)
+      (setq mark (car marks)
+           mark-type (gnus-article-mark-to-type mark)
+           var (intern (format "gnus-newsgroup-%s" (car (rassq mark types)))))
 
-      ;; All articles have to be subsets of the active articles.
+      ;; We set the variable according to the type of the marks list,
+      ;; and then adjust the marks to a subset of the active articles.
       (cond
        ;; Adjust "simple" lists.
-       ((memq mark '(tick dormant expire reply save))
-       (while articles
-         (when (or (< (setq article (pop articles)) min) (> article max))
-           (set var (delq article (symbol-value var))))))
+       ((eq mark-type 'list)
+       (set var (setq articles (gnus-uncompress-range (cdr marks))))
+       (when (memq mark '(tick dormant expire reply save))
+         (while articles
+           (when (or (< (setq article (pop articles)) min) (> article max))
+             (set var (delq article (symbol-value var)))))))
        ;; Adjust assocs.
-       ((memq mark uncompressed)
+       ((eq mark-type 'tuple)
+       (set var (setq articles (cdr marks)))
        (when (not (listp (cdr (symbol-value var))))
          (set var (list (symbol-value var))))
        (when (not (listp (cdr articles)))
@@ -4801,36 +4895,37 @@ If SELECT-ARTICLES, only select those articles from GROUP."
          (when (or (not (consp (setq article (pop articles))))
                    (< (car article) min)
                    (> (car article) max))
-           (set var (delq article (symbol-value var))))))))))
+           (set var (delq article (symbol-value var))))))
+       ((eq mark-type 'range)
+       (cond
+        ((eq mark 'seen))))))))
 
 (defun gnus-update-missing-marks (missing)
   "Go through the list of MISSING articles and remove them from the mark lists."
   (when missing
-    (let ((types gnus-article-mark-lists)
-         var m)
+    (let (var m)
       ;; Go through all types.
-      (while types
-       (setq var (intern (format "gnus-newsgroup-%s" (car (pop types)))))
-       (when (symbol-value var)
-        ;; This list has articles.  So we delete all missing articles
-         ;; from it.
-         (setq m missing)
-         (while m
-           (set var (delq (pop m) (symbol-value var)))))))))
+      (dolist (elem gnus-article-mark-lists)
+       (when (eq (gnus-article-mark-to-type (cdr elem)) 'list)
+         (setq var (intern (format "gnus-newsgroup-%s" (car elem))))
+         (when (symbol-value var)
+           ;; This list has articles.  So we delete all missing
+           ;; articles from it.
+           (setq m missing)
+           (while m
+             (set var (delq (pop m) (symbol-value var))))))))))
 
 (defun gnus-update-marks ()
   "Enter the various lists of marked articles into the newsgroup info list."
   (let ((types gnus-article-mark-lists)
        (info (gnus-get-info gnus-newsgroup-name))
-       (uncompressed '(score bookmark killed))
        type list newmarked symbol delta-marks)
     (when info
       ;; Add all marks lists to the list of marks lists.
       (while (setq type (pop types))
        (setq list (symbol-value
                    (setq symbol
-                         (intern (format "gnus-newsgroup-%s"
-                                         (car type))))))
+                         (intern (format "gnus-newsgroup-%s" (car type))))))
 
        (when list
          ;; Get rid of the entries of the articles that have the
@@ -4849,27 +4944,26 @@ If SELECT-ARTICLES, only select those articles from GROUP."
                (setq arts (cdr arts)))
              (setq list (cdr all)))))
 
-       (unless (memq (cdr type) uncompressed)
+       (when (eq (cdr type) 'seen)
+         (setq list
+               (if list
+                   (gnus-add-to-range list gnus-newsgroup-unseen)
+                 (gnus-compress-sequence gnus-newsgroup-articles))))
+
+       (when (eq (gnus-article-mark-to-type (cdr type)) 'list)
          (setq list (gnus-compress-sequence (set symbol (sort list '<)) t)))
 
-       (when (gnus-check-backend-function
-              'request-set-mark gnus-newsgroup-name)
-         ;; propagate flags to server, with the following exceptions:
-         ;; uncompressed:s are not proper flags (they are cons cells)
-         ;; cache is a internal gnus flag
-         ;; download are local to one gnus installation (well)
-         ;; unsend are for nndraft groups only
-         ;; xxx: generality of this?  this suits nnimap anyway
-         (unless (memq (cdr type) (append '(cache download unsend)
-                                          uncompressed))
-           (let* ((old (cdr (assq (cdr type) (gnus-info-marks info))))
-                  (del (gnus-remove-from-range (gnus-copy-sequence old) list))
-                  (add (gnus-remove-from-range
-                        (gnus-copy-sequence list) old)))
-             (when add
-               (push (list add 'add (list (cdr type))) delta-marks))
-             (when del
-               (push (list del 'del (list (cdr type))) delta-marks)))))
+       (when (and (gnus-check-backend-function
+                   'request-set-mark gnus-newsgroup-name)
+                  (not (gnus-article-unpropagatable-p (cdr type))))
+         (let* ((old (cdr (assq (cdr type) (gnus-info-marks info))))
+                (del (gnus-remove-from-range (gnus-copy-sequence old) list))
+                (add (gnus-remove-from-range
+                      (gnus-copy-sequence list) old)))
+           (when add
+             (push (list add 'add (list (cdr type))) delta-marks))
+           (when del
+             (push (list del 'del (list (cdr type))) delta-marks))))
 
        (when list
          (push (cons (cdr type) list) newmarked)))
@@ -5073,9 +5167,11 @@ The resulting hash table is returned, or nil if no Xrefs were found."
             (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
             (gnus-info-set-read ',info ',(gnus-info-read info))
             (gnus-get-unread-articles-in-group ',info (gnus-active ,group))
+            (gnus-request-set-mark ,group (list (list ',range 'del '(read))))
             (gnus-group-update-group ,group t))))
       ;; Add the read articles to the range.
       (gnus-info-set-read info range)
+      (gnus-request-set-mark group (list (list range 'add '(read))))
       ;; Then we have to re-compute how many unread
       ;; articles there are in this group.
       (when active
@@ -6753,24 +6849,35 @@ If given a prefix, remove all limits."
       (gnus-summary-limit nil 'pop)
     (gnus-summary-position-point)))
 
-(defun gnus-summary-limit-to-subject (subject &optional header)
-  "Limit the summary buffer to articles that have subjects that match a regexp."
-  (interactive "sLimit to subject (regexp): ")
+(defun gnus-summary-limit-to-subject (subject &optional header not-matching)
+  "Limit the summary buffer to articles that have subjects that match a regexp.
+If NOT-MATCHING, excluding articles that have subjects that match a regexp."
+  (interactive
+   (list (read-string (if current-prefix-arg
+                         "Exclude subject (regexp): "
+                       "Limit to subject (regexp): "))
+        nil current-prefix-arg))
   (unless header
     (setq header "subject"))
   (when (not (equal "" subject))
     (prog1
        (let ((articles (gnus-summary-find-matching
-                        (or header "subject") subject 'all)))
+                        (or header "subject") subject 'all nil nil
+                        not-matching)))
          (unless articles
            (error "Found no matches for \"%s\"" subject))
          (gnus-summary-limit articles))
       (gnus-summary-position-point))))
 
-(defun gnus-summary-limit-to-author (from)
-  "Limit the summary buffer to articles that have authors that match a regexp."
-  (interactive "sLimit to author (regexp): ")
-  (gnus-summary-limit-to-subject from "from"))
+(defun gnus-summary-limit-to-author (from &optional not-matching)
+  "Limit the summary buffer to articles that have authors that match a regexp.
+If NOT-MATCHING, excluding articles that have authors that match a regexp."
+  (interactive
+   (list (read-string (if current-prefix-arg
+                         "Exclude author (regexp): "
+                       "Limit to author (regexp): "))
+        current-prefix-arg))
+  (gnus-summary-limit-to-subject from "from" not-matching))
 
 (defun gnus-summary-limit-to-age (age &optional younger-p)
   "Limit the summary buffer to articles that are older than (or equal) AGE days.
@@ -6810,30 +6917,48 @@ articles that are younger than AGE days."
        (gnus-summary-limit (nreverse articles)))
     (gnus-summary-position-point)))
 
-(defun gnus-summary-limit-to-extra (header regexp)
+(defun gnus-summary-limit-to-extra (header regexp &optional not-matching)
   "Limit the summary buffer to articles that match an 'extra' header."
   (interactive
    (let ((header
          (intern
           (gnus-completing-read
            (symbol-name (car gnus-extra-headers))
-           "Limit extra header:"
+           (if current-prefix-arg
+               "Exclude extra header:"
+             "Limit extra header:")
            (mapcar (lambda (x)
                      (cons (symbol-name x) x))
                    gnus-extra-headers)
            nil
            t))))
      (list header
-          (read-string (format "Limit to header %s (regexp): " header)))))
+          (read-string (format "%s header %s (regexp): "
+                               (if current-prefix-arg "Exclude" "Limit to")
+                               header))
+          current-prefix-arg)))
   (when (not (equal "" regexp))
     (prog1
        (let ((articles (gnus-summary-find-matching
-                        (cons 'extra header) regexp 'all)))
+                        (cons 'extra header) regexp 'all nil nil
+                        not-matching)))
          (unless articles
            (error "Found no matches for \"%s\"" regexp))
          (gnus-summary-limit articles))
       (gnus-summary-position-point))))
 
+(defun gnus-summary-limit-to-display-predicate ()
+  "Limit the summary buffer to the predicated in the `display' group parameter."
+  (interactive)
+  (unless gnus-newsgroup-display
+    (error "There is no `display' group parameter"))
+  (let (articles)
+    (dolist (number gnus-newsgroup-articles)
+      (when (funcall gnus-newsgroup-display)
+       (push number articles)))
+    (gnus-summary-limit articles))
+  (gnus-summary-position-point))
+
 (defalias 'gnus-summary-delete-marked-as-read 'gnus-summary-limit-to-unread)
 (make-obsolete
  'gnus-summary-delete-marked-as-read 'gnus-summary-limit-to-unread)
@@ -6886,12 +7011,9 @@ Returns how many articles were removed."
        (gnus-summary-limit articles))
     (gnus-summary-position-point)))
 
-(defun gnus-summary-limit-to-score (&optional score)
+(defun gnus-summary-limit-to-score (score)
   "Limit to articles with score at or above SCORE."
-  (interactive "P")
-  (setq score (if score
-                 (prefix-numeric-value score)
-               (or gnus-summary-default-score 0)))
+  (interactive "NLimit to articles with score of at least: ")
   (let ((data gnus-newsgroup-data)
        articles)
     (while data
@@ -7093,7 +7215,7 @@ fetch-old-headers verbiage, and so on."
   ;; Most groups have nothing to remove.
   (if (or gnus-inhibit-limiting
          (and (null gnus-newsgroup-dormant)
-              (eq gnus-newsgroup-display 'identity)
+              (eq gnus-newsgroup-display 'gnus-not-ignore)
               (not (eq gnus-fetch-old-headers 'some))
               (not (numberp gnus-fetch-old-headers))
               (not (eq gnus-fetch-old-headers 'invisible))
@@ -7610,13 +7732,14 @@ fetched headers for, whether they are displayed or not."
     (nreverse articles)))
 
 (defun gnus-summary-find-matching (header regexp &optional backward unread
-                                         not-case-fold)
+                                         not-case-fold not-matching)
   "Return a list of all articles that match REGEXP on HEADER.
 The search stars on the current article and goes forwards unless
 BACKWARD is non-nil.  If BACKWARD is `all', do all articles.
 If UNREAD is non-nil, only unread articles will
 be taken into consideration.  If NOT-CASE-FOLD, case won't be folded
-in the comparisons."
+in the comparisons. If NOT-MATCHING, return a list of all articles that
+not match REGEXP on HEADER."
   (let ((case-fold-search (not not-case-fold))
        articles d func)
     (if (consp header)
@@ -7637,8 +7760,12 @@ in the comparisons."
       (when (and (or (not unread)      ; We want all articles...
                     (gnus-data-unread-p d)) ; Or just unreads.
                 (vectorp (gnus-data-header d)) ; It's not a pseudo.
-                (string-match regexp
-                              (funcall func (gnus-data-header d)))) ; Match.
+                (if not-matching
+                    (not (string-match
+                          regexp
+                          (funcall func (gnus-data-header d))))
+                  (string-match regexp
+                                (funcall func (gnus-data-header d)))))
        (push (gnus-data-number d) articles))) ; Success!
     (nreverse articles)))
 
@@ -7696,6 +7823,13 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
     (when gnus-page-broken
       (gnus-narrow-to-page))))
 
+(defun gnus-summary-print-truncate-and-quote (string &optional len)
+  "Truncate to LEN and quote all \"(\"'s in STRING."
+  (gnus-replace-in-string (if (and len (> (length string) len))
+                             (substring string 0 len)
+                           string)
+                         "[()]" "\\\\\\&"))
+
 (defun gnus-summary-print-article (&optional filename n)
   "Generate and print a PostScript image of the N next (mail) articles.
 
@@ -7725,9 +7859,13 @@ to save in."
              (let ((ps-left-header
                     (list
                      (concat "("
-                             (mail-header-subject gnus-current-headers) ")")
+                             (gnus-summary-print-truncate-and-quote
+                              (mail-header-subject gnus-current-headers)
+                              66) ")")
                      (concat "("
-                             (mail-header-from gnus-current-headers) ")")))
+                             (gnus-summary-print-truncate-and-quote
+                              (mail-header-from gnus-current-headers)
+                              45) ")")))
                    (ps-right-header
                     (list
                      "/pagenumberstring load"
@@ -7743,31 +7881,46 @@ to save in."
   (ps-despool filename))
 
 (defun gnus-summary-show-article (&optional arg)
-  "Force re-fetching of the current article.
+  "Force redisplaying of the current article.
 If ARG (the prefix) is a number, show the article with the charset
 defined in `gnus-summary-show-article-charset-alist', or the charset
-inputed.
+input.
 If ARG (the prefix) is non-nil and not a number, show the raw article
-without any article massaging functions being run."
+without any article massaging functions being run.  Normally, the key strokes 
+are `C-u g'."
   (interactive "P")
   (cond
    ((numberp arg)
+    (gnus-summary-show-article t)
     (let ((gnus-newsgroup-charset
           (or (cdr (assq arg gnus-summary-show-article-charset-alist))
-              (mm-read-coding-system "Charset: ")))
+              (mm-read-coding-system
+               "View as charset: "
+               (save-excursion
+                 (set-buffer gnus-article-buffer)
+                 (let ((coding-systems
+                        (detect-coding-region (point) (point-max))))
+                   (or (car-safe coding-systems)
+                       coding-systems))))))
          (gnus-newsgroup-ignored-charsets 'gnus-all))
       (gnus-summary-select-article nil 'force)
       (let ((deps gnus-newsgroup-dependencies)
-           head header)
+           head header lines)
        (save-excursion
          (set-buffer gnus-original-article-buffer)
          (save-restriction
            (message-narrow-to-head)
-           (setq head (buffer-string)))
+           (setq head (buffer-string))
+           (goto-char (point-min))
+           (unless (re-search-forward "^lines:[ \t]\\([0-9]+\\)" nil t)
+             (goto-char (point-max))
+             (widen)
+             (setq lines (1- (count-lines (point) (point-max))))))
          (with-temp-buffer
            (insert (format "211 %d Article retrieved.\n"
                            (cdr gnus-article-current)))
            (insert head)
+           (if lines (insert (format "Lines: %d\n" lines)))
            (insert ".\n")
            (let ((nntp-server-buffer (current-buffer)))
              (setq header (car (gnus-get-newsgroup-headers deps t))))))
@@ -7776,9 +7929,8 @@ without any article massaging functions being run."
         header)
        (gnus-summary-update-article-line
         (cdr gnus-article-current) header)
-       (if (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
-           (gnus-summary-update-secondary-mark
-            (cdr gnus-article-current))))))
+       (when (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
+         (gnus-summary-update-secondary-mark (cdr gnus-article-current))))))
    ((not arg)
     ;; Select the article the normal way.
     (gnus-summary-select-article nil 'force))
@@ -7912,10 +8064,6 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
   (interactive "P")
   (unless action
     (setq action 'move))
-  ;; Disable marking as read.
-  (let (gnus-mark-article-hook)
-    (save-window-excursion
-      (gnus-summary-select-article)))
   ;; Check whether the source group supports the required functions.
   (cond ((and (eq action 'move)
              (not (gnus-check-backend-function
@@ -7990,7 +8138,7 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
                      (mail-header-xref (gnus-summary-article-header article))
                      " ")))
           (setq new-xref (concat (gnus-group-real-name gnus-newsgroup-name)
-                                 ":" article))
+                                 ":" (number-to-string article)))
           (unless xref
             (setq xref (list (system-name))))
           (setq new-xref
@@ -8007,7 +8155,8 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
                                (gnus-request-accept-article
                                 to-newsgroup select-method (not articles))))
               (setq new-xref (concat new-xref " " (car art-group)
-                                     ":" (cdr art-group)))
+                                     ":"
+                                     (number-to-string (cdr art-group))))
               ;; Now we have the new Xrefs header, so we insert
               ;; it and replace the new article.
               (nnheader-replace-header "Xref" new-xref)
@@ -8066,25 +8215,26 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
                  (setcdr gnus-newsgroup-active to-article))
 
                (while marks
-                 (when (memq article (symbol-value
-                                      (intern (format "gnus-newsgroup-%s"
-                                                      (caar marks)))))
-                   (push (cdar marks) to-marks)
-                   ;; If the other group is the same as this group,
-                   ;; then we have to add the mark to the list.
-                   (when (equal to-group gnus-newsgroup-name)
-                     (set (intern (format "gnus-newsgroup-%s" (caar marks)))
-                          (cons to-article
-                                (symbol-value
-                                 (intern (format "gnus-newsgroup-%s"
-                                                 (caar marks)))))))
-                   ;; Copy the marks to other group.
-                   (gnus-add-marked-articles
-                    to-group (cdar marks) (list to-article) info))
+                 (when (eq (gnus-article-mark-to-type (cdar marks)) 'list)
+                   (when (memq article (symbol-value
+                                        (intern (format "gnus-newsgroup-%s"
+                                                        (caar marks)))))
+                     (push (cdar marks) to-marks)
+                     ;; If the other group is the same as this group,
+                     ;; then we have to add the mark to the list.
+                     (when (equal to-group gnus-newsgroup-name)
+                       (set (intern (format "gnus-newsgroup-%s" (caar marks)))
+                            (cons to-article
+                                  (symbol-value
+                                   (intern (format "gnus-newsgroup-%s"
+                                                   (caar marks)))))))
+                     ;; Copy the marks to other group.
+                     (gnus-add-marked-articles
+                      to-group (cdar marks) (list to-article) info)))
                  (setq marks (cdr marks)))
 
                (gnus-request-set-mark to-group (list (list (list to-article)
-                                                           'set
+                                                           'add
                                                            to-marks))))
 
              (gnus-dribble-enter
@@ -8110,12 +8260,10 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
          (gnus-summary-mark-article article gnus-canceled-mark))))
       (gnus-summary-remove-process-mark article))
     ;; Re-activate all groups that have been moved to.
-    (while to-groups
-      (save-excursion
-       (set-buffer gnus-group-buffer)
-       (when (gnus-group-goto-group (car to-groups) t)
-         (gnus-group-get-new-news-this-group 1 t))
-       (pop to-groups)))
+    (save-excursion
+      (set-buffer gnus-group-buffer)
+      (let ((gnus-group-marked to-groups))
+       (gnus-group-get-new-news-this-group nil t)))
 
     (gnus-kill-buffer copy-buf)
     (gnus-summary-position-point)
@@ -8135,10 +8283,9 @@ re-spool using this method."
   (gnus-summary-move-article n nil nil 'crosspost))
 
 (defcustom gnus-summary-respool-default-method nil
-  "Default method for respooling an article.
+  "Default method type for respooling an article.
 If nil, use to the current newsgroup method."
-  :type '(choice (gnus-select-method :value (nnml ""))
-                (const nil))
+  :type 'symbol
   :group 'gnus-summary-mail)
 
 (defun gnus-summary-respool-article (&optional n method)
@@ -8274,7 +8421,7 @@ This will be the case if the article has both been mailed and posted."
           (expirable (if total
                          (progn
                            ;; We need to update the info for
-                       ;; this group for `gnus-list-of-read-articles'
+                           ;; this group for `gnus-list-of-read-articles'
                            ;; to give us the right answer.
                            (gnus-run-hooks 'gnus-exit-group-hook)
                            (gnus-summary-update-info)
@@ -8537,6 +8684,15 @@ groups."
   (execute-kbd-macro (concat (this-command-keys) key))
   (gnus-article-edit-done))
 
+
+(defun gnus-summary-toggle-smiley (&optional arg)
+  "Toggle the display of smilies as small graphical icons."
+  (interactive "P")
+  (save-excursion
+    (set-buffer gnus-article-buffer)
+    (gnus-smiley-display arg)
+    ))
+
 ;;; Respooling
 
 (defun gnus-summary-respool-query (&optional silent trace)
@@ -8941,6 +9097,8 @@ Iff NO-EXPIRE, auto-expiry will be inhibited."
          gnus-saved-mark)
         ((memq article gnus-newsgroup-recent)
          gnus-recent-mark)
+        ((memq article gnus-newsgroup-unseen)
+         gnus-unseen-mark)
         (t gnus-no-mark))
    'replied)
   (when (gnus-visual-p 'summary-highlight 'highlight)
@@ -9709,7 +9867,9 @@ The variable `gnus-default-article-saver' specifies the saver function."
            (gnus-message 1 "Article %d is unsaveable" article))
        ;; This is a real article.
        (save-window-excursion
-         (gnus-summary-select-article t nil nil article))
+         (let ((gnus-display-mime-function nil)
+               (gnus-article-prepare-hook nil))
+           (gnus-summary-select-article t nil nil article)))
        (save-excursion
          (set-buffer save-buffer)
          (erase-buffer)
@@ -9793,6 +9953,17 @@ save those articles instead."
   (let ((gnus-default-article-saver 'gnus-summary-save-body-in-file))
     (gnus-summary-save-article arg)))
 
+(defun gnus-summary-muttprint (&optional arg)
+  "Print the current article using Muttprint.
+If N is a positive number, save the N next articles.
+If N is a negative number, save the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+save those articles instead."
+  (interactive "P")
+  (require 'gnus-art)
+  (let ((gnus-default-article-saver 'gnus-summary-pipe-to-muttprint))
+    (gnus-summary-save-article arg t)))
+
 (defun gnus-summary-pipe-message (program)
   "Pipe the current article through PROGRAM."
   (interactive "sProgram: ")