This commit was manufactured by cvs2svn to create tag 'for-semi-1_1'.
[elisp/gnus.git-] / lisp / gnus-sum.el
index a5f34a9..79e31a3 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-sum.el --- summary mode commands for Semi-gnus
-;; Copyright (C) 1996,97 Free Software Foundation, Inc.
+;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
 (require 'gnus-undo)
 (require 'std11)
 (require 'mime-view)
+
+(or (get-unified-alist mime-acting-condition '((type . text)))
+    (error "Please install latest SEMI."))
+
 (autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
 (autoload 'gnus-set-summary-default-charset "gnus-i18n" nil t)
 
@@ -126,9 +130,12 @@ comparing subjects."
 
 (defcustom gnus-simplify-subject-functions nil
   "List of functions taking a string argument that simplify subjects.
-The functions are applied recursively."
+The functions are applied recursively.
+
+Useful functions to put in this list include: `gnus-simplify-subject-re',
+`gnus-simplify-subject-fuzzy' and `gnus-simplify-whitespace'."
   :group 'gnus-thread
-  :type '(repeat (list function)))
+  :type '(repeat function))
 
 (defcustom gnus-simplify-ignored-prefixes nil
   "*Regexp, matches for which are removed from subject lines when simplifying fuzzily."
@@ -149,7 +156,7 @@ non-nil and non-`some', fill in all gaps that Gnus manages to guess."
 
 (defcustom gnus-summary-thread-gathering-function
   'gnus-gather-threads-by-subject
-  "Function used for gathering loose threads.
+  "*Function used for gathering loose threads.
 There are two pre-defined functions: `gnus-gather-threads-by-subject',
 which only takes Subjects into consideration; and
 `gnus-gather-threads-by-references', which compared the References
@@ -493,7 +500,7 @@ list of parameters to that command."
   :type 'boolean)
 
 (defcustom gnus-summary-dummy-line-format
-  "*  %(:                          :%) %S\n"
+  "  %(:                          :%) %S\n"
   "*The format specification for the dummy roots in the summary buffer.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
@@ -660,13 +667,8 @@ is not run if `gnus-visual' is nil."
   :group 'gnus-summary-visual
   :type 'hook)
 
-;; 1997/5/4 by MORIOKA Tomohiko <morioka@jaist.ac.jp>
 (defcustom gnus-structured-field-decoder
-  (function
-   (lambda (string)
-     (eword-decode-structured-field-body
-      (std11-unfold-string string) 'must-unfold)
-     ))
+  #'eword-decode-and-unfold-structured-field
   "Function to decode non-ASCII characters in structured field for summary."
   :group 'gnus-various
   :type 'function)
@@ -749,8 +751,15 @@ automatically when it is selected."
      . gnus-summary-high-unread-face)
     ((and (< score default) (= mark gnus-unread-mark))
      . gnus-summary-low-unread-face)
-    ((memq mark (list gnus-unread-mark gnus-downloadable-mark
-                     gnus-undownloaded-mark))
+    ((= mark gnus-unread-mark)
+     . gnus-summary-normal-unread-face)
+    ((and (> score default) (memq mark (list gnus-downloadable-mark
+                                            gnus-undownloaded-mark)))
+     . gnus-summary-high-unread-face)
+    ((and (< score default) (memq mark (list gnus-downloadable-mark
+                                            gnus-undownloaded-mark)))
+     . gnus-summary-low-unread-face)
+    ((memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
      . gnus-summary-normal-unread-face)
     ((> score default)
      . gnus-summary-high-read-face)
@@ -758,7 +767,7 @@ automatically when it is selected."
      . gnus-summary-low-read-face)
     (t
      . gnus-summary-normal-read-face))
-  "Controls the highlighting of summary buffer lines.
+  "*Controls the highlighting of summary buffer lines.
 
 A list of (FORM . FACE) pairs.  When deciding how a a particular
 summary line should be displayed, each form is evaluated.  The content
@@ -1228,6 +1237,7 @@ increase the score of each group you read."
     "\C-c\C-v\C-v" gnus-uu-decode-uu-view
     "\C-d" gnus-summary-enter-digest-group
     "\M-\C-d" gnus-summary-read-document
+    "\M-\C-e" gnus-summary-edit-parameters
     "\C-c\C-b" gnus-bug
     "*" gnus-cache-enter-article
     "\M-*" gnus-cache-remove-article
@@ -1367,7 +1377,6 @@ increase the score of each group you read."
     "e" gnus-article-emphasize
     "w" gnus-article-fill-cited-article
     "c" gnus-article-remove-cr
-    "q" gnus-article-de-quoted-unreadable
     "f" gnus-article-display-x-face
     "l" gnus-summary-stop-page-breaking
     "r" gnus-summary-caesar-message
@@ -1399,6 +1408,7 @@ increase the score of each group you read."
     "l" gnus-article-date-local
     "e" gnus-article-date-lapsed
     "o" gnus-article-date-original
+    "i" gnus-article-date-iso8601
     "s" gnus-article-date-user)
 
   (gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map)
@@ -1600,6 +1610,7 @@ increase the score of each group you read."
        ["Citation" gnus-article-highlight-citation t])
        ("Date"
        ["Local" gnus-article-date-local t]
+       ["ISO8601" gnus-article-date-iso8601 t]
        ["UT" gnus-article-date-ut t]
        ["Original" gnus-article-date-original t]
        ["Lapsed" gnus-article-date-lapsed t]
@@ -1618,7 +1629,6 @@ increase the score of each group you read."
        ["Word wrap" gnus-article-fill-cited-article t]
        ["CR" gnus-article-remove-cr t]
        ["Show X-Face" gnus-article-display-x-face t]
-       ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
        ["UnHTMLize" gnus-article-treat-html t]
        ["Rot 13" gnus-summary-caesar-message t]
        ["Unix pipe" gnus-summary-pipe-message t]
@@ -1829,6 +1839,7 @@ increase the score of each group you read."
         'request-expire-articles gnus-newsgroup-name)]
        ["Edit local kill file" gnus-summary-edit-local-kill t]
        ["Edit main kill file" gnus-summary-edit-global-kill t]
+       ["Edit group parameters" gnus-summary-edit-parameters t]
        ("Exit"
        ["Catchup and exit" gnus-summary-catchup-and-exit t]
        ["Catchup all and exit" gnus-summary-catchup-and-exit t]
@@ -1841,7 +1852,7 @@ increase the score of each group you read."
        ["Rescan group" gnus-summary-rescan-group t]
        ["Update dribble" gnus-summary-save-newsrc t])))
 
-    (run-hooks 'gnus-summary-menu-hook)))
+    (gnus-run-hooks 'gnus-summary-menu-hook)))
 
 (defun gnus-score-set-default (var value)
   "A version of set that updates the GNU Emacs menu-bar."
@@ -1976,7 +1987,7 @@ The following commands are available:
   (add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
   (make-local-hook 'pre-command-hook)
   (add-hook 'pre-command-hook 'gnus-set-global-variables nil t)
-  (run-hooks 'gnus-summary-mode-hook)
+  (gnus-run-hooks 'gnus-summary-mode-hook)
   (gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
   (gnus-update-summary-mark-positions))
 
@@ -2187,10 +2198,12 @@ article number."
         (gnus-summary-last-subject))))
 
 (defmacro gnus-summary-article-header (&optional number)
+  "Return the header of article NUMBER."
   `(gnus-data-header (gnus-data-find
                      ,(or number '(gnus-summary-article-number)))))
 
 (defmacro gnus-summary-thread-level (&optional number)
+  "Return the level of thread that starts with article NUMBER."
   `(if (and (eq gnus-summary-make-false-root 'dummy)
            (get-text-property (point) 'gnus-intangible))
        0
@@ -2198,10 +2211,12 @@ article number."
                       ,(or number '(gnus-summary-article-number))))))
 
 (defmacro gnus-summary-article-mark (&optional number)
+  "Return the mark of article NUMBER."
   `(gnus-data-mark (gnus-data-find
                    ,(or number '(gnus-summary-article-number)))))
 
 (defmacro gnus-summary-article-pos (&optional number)
+  "Return the position of the line of article NUMBER."
   `(gnus-data-pos (gnus-data-find
                   ,(or number '(gnus-summary-article-number)))))
 
@@ -2224,6 +2239,7 @@ article number."
        gnus-summary-default-score 0))
 
 (defun gnus-summary-article-children (&optional number)
+  "Return a list of article numbers that are children of article NUMBER."
   (let* ((data (gnus-data-find-list (or number (gnus-summary-article-number))))
         (level (gnus-data-level (car data)))
         l children)
@@ -2235,6 +2251,7 @@ article number."
     (nreverse children)))
 
 (defun gnus-summary-article-parent (&optional number)
+  "Return the article number of the parent of article NUMBER."
   (let* ((data (gnus-data-find-list (or number (gnus-summary-article-number))
                                    (gnus-data-list t)))
         (level (gnus-data-level (car data))))
@@ -2259,6 +2276,11 @@ This is all marks except unread, ticked, dormant, and expirable."
           (= mark gnus-expirable-mark))))
 
 (defmacro gnus-article-mark (number)
+  "Return the MARK of article NUMBER.
+This macro should only be used when computing the mark the \"first\"
+time; i.e., when generating the summary lines.  After that,
+`gnus-summary-article-mark' should be used to examine the
+marks of articles."
   `(cond
     ((memq ,number gnus-newsgroup-unsendable) gnus-unsendable-mark)
     ((memq ,number gnus-newsgroup-undownloaded) gnus-undownloaded-mark)
@@ -2512,7 +2534,7 @@ This is all marks except unread, ticked, dormant, and expirable."
      'gnus-number gnus-tmp-number)
     (when (gnus-visual-p 'summary-highlight 'highlight)
       (forward-line -1)
-      (run-hooks 'gnus-summary-update-hook)
+      (gnus-run-hooks 'gnus-summary-update-hook)
       (forward-line 1))))
 
 (defun gnus-summary-update-line (&optional dont-update)
@@ -2544,7 +2566,7 @@ This is all marks except unread, ticked, dormant, and expirable."
         'score))
       ;; Do visual highlighting.
       (when (gnus-visual-p 'summary-highlight 'highlight)
-       (run-hooks 'gnus-summary-update-hook)))))
+       (gnus-run-hooks 'gnus-summary-update-hook)))))
 
 (defvar gnus-tmp-new-adopts nil)
 
@@ -2586,14 +2608,12 @@ the thread are to be displayed."
       (and (consp elem)                        ; Has to be a cons.
           (consp (cdr elem))           ; The cdr has to be a list.
           (symbolp (car elem))         ; Has to be a symbol in there.
-          (not (memq (car elem)
-                     '(quit-config to-address to-list to-group)))
           (ignore-errors               ; So we set it.
             (make-local-variable (car elem))
             (set (car elem) (eval (nth 1 elem))))))))
 
 (defun gnus-summary-read-group (group &optional show-all no-article
-                                     kill-buffer no-display)
+                                     kill-buffer no-display backward)
   "Start reading news in newsgroup GROUP.
 If SHOW-ALL is non-nil, already read articles are also listed.
 If NO-ARTICLE is non-nil, no article is selected initially.
@@ -2608,6 +2628,11 @@ If NO-DISPLAY, don't generate a summary buffer."
                                  (setq show-all nil)))))
                (eq gnus-auto-select-next 'quietly))
       (set-buffer gnus-group-buffer)
+      ;; The entry function called above goes to the next
+      ;; group automatically, so we go two groups back
+      ;; if we are searching for the previous group.
+      (when backward
+       (gnus-group-prev-unread-group 2))
       (if (not (equal group (gnus-group-group-name)))
          (setq group (gnus-group-group-name))
        (setq group nil)))
@@ -2675,7 +2700,7 @@ If NO-DISPLAY, don't generate a summary buffer."
            (gnus-copy-sequence
             (gnus-active gnus-newsgroup-name)))
       ;; You can change the summary buffer in some way with this hook.
-      (run-hooks 'gnus-select-group-hook)
+      (gnus-run-hooks 'gnus-select-group-hook)
       ;; Set any local variables in the group parameters.
       (gnus-summary-set-local-parameters gnus-newsgroup-name)
       (gnus-update-format-specifications
@@ -2713,7 +2738,7 @@ If NO-DISPLAY, don't generate a summary buffer."
              ((and gnus-newsgroup-scored show-all)
               (gnus-summary-limit-include-expunged t))))
       ;; Function `gnus-apply-kill-file' must be called in this hook.
-      (run-hooks 'gnus-apply-kill-hook)
+      (gnus-run-hooks 'gnus-apply-kill-hook)
       (if (and (zerop (buffer-size))
               (not no-display))
          (progn
@@ -2757,7 +2782,7 @@ If NO-DISPLAY, don't generate a summary buffer."
            (select-window owin)))
        ;; Mark this buffer as "prepared".
        (setq gnus-newsgroup-prepared t)
-       (run-hooks 'gnus-summary-prepared-hook)
+       (gnus-run-hooks 'gnus-summary-prepared-hook)
        t)))))
 
 (defun gnus-summary-prepare ()
@@ -2767,7 +2792,7 @@ If NO-DISPLAY, don't generate a summary buffer."
     (erase-buffer)
     (setq gnus-newsgroup-data nil
          gnus-newsgroup-data-reverse nil)
-    (run-hooks 'gnus-summary-generate-hook)
+    (gnus-run-hooks 'gnus-summary-generate-hook)
     ;; Generate the buffer, either with threads or without.
     (when gnus-newsgroup-headers
       (gnus-summary-prepare-threads
@@ -2781,7 +2806,7 @@ If NO-DISPLAY, don't generate a summary buffer."
     (setq gnus-newsgroup-data (nreverse gnus-newsgroup-data))
     ;; Call hooks for modifying summary buffer.
     (goto-char (point-min))
-    (run-hooks 'gnus-summary-prepare-hook)))
+    (gnus-run-hooks 'gnus-summary-prepare-hook)))
 
 (defsubst gnus-general-simplify-subject (subject)
   "Simply subject by the same rules as gnus-gather-threads-by-subject."
@@ -3707,7 +3732,7 @@ or a straight list of headers."
             'gnus-number number)
            (when gnus-visual-p
              (forward-line -1)
-             (run-hooks 'gnus-summary-update-hook)
+             (gnus-run-hooks 'gnus-summary-update-hook)
              (forward-line 1))
 
            (setq gnus-tmp-prev-subject subject)))
@@ -4298,7 +4323,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
       (set-buffer nntp-server-buffer)
       ;; Translate all TAB characters into SPACE characters.
       (subst-char-in-region (point-min) (point-max) ?\t ?  t)
-      (run-hooks 'gnus-parse-headers-hook)
+      (gnus-run-hooks 'gnus-parse-headers-hook)
       (let ((case-fold-search t)
            in-reply-to header p lines)
        (goto-char (point-min))
@@ -4329,7 +4354,6 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (if (search-forward "\nsubject: " nil t)
-                 ;; 1997/5/4 by MORIOKA Tomohiko <morioka@jaist.ac.jp>
                  (funcall
                   gnus-unstructured-field-decoder (nnheader-header-value))
                "(none)"))
@@ -4337,7 +4361,6 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (if (search-forward "\nfrom: " nil t)
-                 ;; 1997/5/4 by MORIOKA Tomohiko <morioka@jaist.ac.jp>
                  (funcall
                   gnus-structured-field-decoder (nnheader-header-value))
                "(nobody)"))
@@ -4349,10 +4372,12 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            ;; Message-ID.
            (progn
              (goto-char p)
-             (setq id (if (search-forward "\nmessage-id:" nil t)
-                          (buffer-substring
-                           (1- (or (search-forward "<" nil t) (point)))
-                           (or (search-forward ">" nil t) (point)))
+             (setq id (if (re-search-forward
+                           "^message-id: *\\(<[^\n\t> ]+>\\)" nil t)
+                          ;; We do it this way to make sure the Message-ID
+                          ;; is (somewhat) syntactically valid.
+                          (buffer-substring (match-beginning 1)
+                                            (match-end 1))
                         ;; If there was no message-id, we just fake one
                         ;; to make subsequent routines simpler.
                         (nnheader-generate-fake-message-id))))
@@ -4501,7 +4526,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                         (setq ref
                               (buffer-substring
                                (1+ (point))
-                               (search-backward "<" beg t)))
+                               (or (search-backward "<" beg t) beg)))
                       (setq ref nil))
                     (goto-char beg))
                   (gnus-nov-field))    ; refs
@@ -4569,7 +4594,7 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
     (save-excursion
       (set-buffer nntp-server-buffer)
       ;; Allow the user to mangle the headers before parsing them.
-      (run-hooks 'gnus-parse-headers-hook)
+      (gnus-run-hooks 'gnus-parse-headers-hook)
       (goto-char (point-min))
       (while (not (eobp))
        (condition-case ()
@@ -4631,8 +4656,13 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
 
 (defun gnus-summary-insert-subject (id &optional old-header use-old-header)
   "Find article ID and insert the summary line for that article."
-  (let ((header (if (and old-header use-old-header)
-                   old-header (gnus-read-header id)))
+  (let ((header (cond ((and old-header use-old-header)
+                      old-header)
+                     ((and (numberp id)
+                           (gnus-number-to-header id))
+                      (gnus-number-to-header id))
+                     (t
+                      (gnus-read-header id))))
        (number (and (numberp id) id))
        pos d)
     (when header
@@ -4640,7 +4670,8 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
       ;; article we have fetched.
       (when (and (not gnus-show-threads)
                 old-header)
-       (when (setq d (gnus-data-find (mail-header-number old-header)))
+       (when (and number
+                  (setq d (gnus-data-find (mail-header-number old-header))))
          (goto-char (gnus-data-pos d))
          (gnus-data-remove
           number
@@ -4654,6 +4685,7 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
            (delq (setq number (mail-header-number header))
                  gnus-newsgroup-sparse))
       (setq gnus-newsgroup-ancient (delq number gnus-newsgroup-ancient))
+      (push number gnus-newsgroup-limit)
       (gnus-rebuild-thread (mail-header-id header))
       (gnus-summary-goto-subject number nil t))
     (when (and (numberp number)
@@ -4677,44 +4709,47 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
   "Return a list of articles to be worked upon.         The prefix argument,
 the list of process marked articles, and the current article will be
 taken into consideration."
-  (cond
-   (n
-    ;; A numerical prefix has been given.
-    (setq n (prefix-numeric-value n))
-    (let ((backward (< n 0))
-         (n (abs (prefix-numeric-value n)))
-         articles article)
-      (save-excursion
-       (while
-           (and (> n 0)
-                (push (setq article (gnus-summary-article-number))
-                      articles)
-                (if backward
-                    (gnus-summary-find-prev nil article)
-                  (gnus-summary-find-next nil article)))
-         (decf n)))
-      (nreverse articles)))
-   ((gnus-region-active-p)
-    ;; Work on the region between point and mark.
-    (let ((max (max (point) (mark)))
-         articles article)
-      (save-excursion
-       (goto-char (min (point) (mark)))
-       (while
-           (and
-            (push (setq article (gnus-summary-article-number)) articles)
-            (gnus-summary-find-next nil article)
-            (< (point) max)))
-       (nreverse articles))))
-   (gnus-newsgroup-processable
-    ;; There are process-marked articles present.
-    ;; Save current state.
-    (gnus-summary-save-process-mark)
-    ;; Return the list.
-    (reverse gnus-newsgroup-processable))
-   (t
-    ;; Just return the current article.
-    (list (gnus-summary-article-number)))))
+  (save-excursion
+    (set-buffer gnus-summary-buffer)
+    (cond
+     (n
+      ;; A numerical prefix has been given.
+      (setq n (prefix-numeric-value n))
+      (let ((backward (< n 0))
+           (n (abs (prefix-numeric-value n)))
+           articles article)
+       (save-excursion
+         (while
+             (and (> n 0)
+                  (push (setq article (gnus-summary-article-number))
+                        articles)
+                  (if backward
+                      (gnus-summary-find-prev nil article)
+                    (gnus-summary-find-next nil article)))
+           (decf n)))
+       (nreverse articles)))
+     ((and (gnus-region-active-p) (mark))
+      (message "region active")
+      ;; Work on the region between point and mark.
+      (let ((max (max (point) (mark)))
+           articles article)
+       (save-excursion
+         (goto-char (min (point) (mark)))
+         (while
+             (and
+              (push (setq article (gnus-summary-article-number)) articles)
+              (gnus-summary-find-next nil article)
+              (< (point) max)))
+         (nreverse articles))))
+     (gnus-newsgroup-processable
+      ;; There are process-marked articles present.
+      ;; Save current state.
+      (gnus-summary-save-process-mark)
+      ;; Return the list.
+      (reverse gnus-newsgroup-processable))
+     (t
+      ;; Just return the current article.
+      (list (gnus-summary-article-number))))))
 
 (defun gnus-summary-save-process-mark ()
   "Push the current set of process marked articles on the stack."
@@ -5063,13 +5098,15 @@ If FORCE (the prefix), also save the .newsrc file(s)."
   "Exit reading current newsgroup, and then return to group selection mode.
 gnus-exit-group-hook is called with no arguments if that value is non-nil."
   (interactive)
+  (gnus-set-global-variables)
   (gnus-kill-save-kill-buffer)
+  (gnus-async-halt-prefetch)
   (let* ((group gnus-newsgroup-name)
         (quit-config (gnus-group-quit-config gnus-newsgroup-name))
         (mode major-mode)
          (group-point nil)
         (buf (current-buffer)))
-    (run-hooks 'gnus-summary-prepare-exit-hook)
+    (gnus-run-hooks 'gnus-summary-prepare-exit-hook)
     ;; If we have several article buffers, we kill them at exit.
     (unless gnus-single-article-buffer
       (gnus-kill-buffer gnus-original-article-buffer)
@@ -5082,9 +5119,11 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
       (gnus-dup-enter-articles))
     (when gnus-use-trees
       (gnus-tree-close group))
+    ;; Remove entries for this group.
+    (nnmail-purge-split-history (gnus-group-real-name group))
     ;; Make all changes in this group permanent.
     (unless quit-config
-      (run-hooks 'gnus-exit-group-hook)
+      (gnus-run-hooks 'gnus-exit-group-hook)
       (gnus-summary-update-info)
       ;; Do adaptive scoring, and possibly save score files.
       (when gnus-newsgroup-adaptive
@@ -5096,7 +5135,7 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
     (set-buffer gnus-group-buffer)
     (unless quit-config
       (gnus-group-jump-to-group group))
-    (run-hooks 'gnus-summary-exit-hook)
+    (gnus-run-hooks 'gnus-summary-exit-hook)
     (unless (or quit-config
                ;; If this group has disappeared from the summary
                ;; buffer, don't skip forwards.
@@ -5147,6 +5186,8 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
     (when (or no-questions
              gnus-expert-user
              (gnus-y-or-n-p "Discard changes to this group and exit? "))
+      (gnus-async-halt-prefetch)
+      (gnus-run-hooks 'gnus-summary-prepare-exit-hook)
       ;; If we have several article buffers, we kill them at exit.
       (unless gnus-single-article-buffer
        (gnus-kill-buffer gnus-article-buffer)
@@ -5378,7 +5419,7 @@ previous group instead."
            (when (gnus-buffer-live-p current-buffer)
              (set-buffer current-buffer)
              (gnus-summary-exit))
-           (run-hooks 'gnus-group-no-more-groups-hook))
+           (gnus-run-hooks 'gnus-group-no-more-groups-hook))
        ;; We try to enter the target group.
        (gnus-group-jump-to-group target-group)
        (let ((unreads (gnus-group-group-unread)))
@@ -5386,7 +5427,8 @@ previous group instead."
                       (and unreads (not (zerop unreads))))
                   (gnus-summary-read-group
                    target-group nil no-article
-                   (and (buffer-name current-buffer) current-buffer)))
+                   (and (buffer-name current-buffer) current-buffer)
+                   nil backward))
              (setq entered t)
            (setq current-group target-group
                  target-group nil)))))))
@@ -5442,6 +5484,7 @@ returned."
                (if backward
                    (gnus-summary-find-prev unread)
                  (gnus-summary-find-next unread)))
+      (gnus-summary-show-thread)
       (setq n (1- n)))
     (when (/= 0 n)
       (gnus-message 7 "No more%s articles"
@@ -5506,7 +5549,7 @@ Given a prefix, will force an `article' buffer configuration."
        (if gnus-summary-display-article-function
            (funcall gnus-summary-display-article-function article all-header)
          (gnus-article-prepare article all-header))
-      (run-hooks 'gnus-select-article-hook)
+      (gnus-run-hooks 'gnus-select-article-hook)
       (when (and gnus-current-article
                 (not (zerop gnus-current-article)))
        (gnus-summary-goto-subject gnus-current-article))
@@ -5884,7 +5927,7 @@ If ALL-HEADERS is non-nil, no header lines are hidden."
   (interactive)
   (prog1
       (when gnus-last-article
-       (gnus-summary-goto-article gnus-last-article))
+       (gnus-summary-goto-article gnus-last-article nil t))
     (gnus-summary-position-point)))
 
 (defun gnus-summary-pop-article (number)
@@ -6459,6 +6502,11 @@ or `gnus-select-method', no matter what backend the article comes from."
              (gnus-summary-select-article nil nil nil number)
            (gnus-message 3 "Couldn't fetch article %s" message-id))))))))
 
+(defun gnus-summary-edit-parameters ()
+  "Edit the group parameters of the current group."
+  (interactive)
+  (gnus-group-edit-group gnus-newsgroup-name 'params))
+
 (defun gnus-summary-enter-digest-group (&optional force)
   "Enter an nndoc group based on the current article.
 If FORCE, force a digest interpretation.  If not, try
@@ -6747,8 +6795,8 @@ that name.  If FILENAME is a number, prompt the user for the name of the file
 to save in."
   (interactive (list (ps-print-preprint current-prefix-arg)
                     current-prefix-arg))
-  (dolist (nbr (gnus-summary-work-articles n))
-    (gnus-summary-select-article 'all nil 'pseudo nbr)
+  (dolist (article (gnus-summary-work-articles n))
+    (gnus-summary-select-article nil nil 'pseudo article)
     (gnus-eval-in-buffer-window gnus-article-buffer
       (let ((buffer (generate-new-buffer " *print*")))
        (unwind-protect
@@ -6767,7 +6815,7 @@ to save in."
                      "/pagenumberstring load" 
                      (concat "("
                              (mail-header-date gnus-current-headers) ")"))))
-               (run-hooks 'gnus-ps-print-hook)
+               (gnus-run-hooks 'gnus-ps-print-hook)
                (ps-print-buffer-with-faces filename)))
          (kill-buffer buffer))))))
 
@@ -6826,7 +6874,7 @@ If ARG is a negative number, hide the unwanted header lines."
        (setq e (1- (or (search-forward "\n\n" nil t) (point-max)))))
       (insert-buffer-substring gnus-original-article-buffer 1 e)
       (let ((article-inhibit-hiding t))
-       (run-hooks 'gnus-article-display-hook))
+       (gnus-run-hooks 'gnus-article-display-hook))
       (when (or (not hidden) (and (numberp arg) (< arg 0)))
        (gnus-article-hide-headers)))))
 
@@ -6868,7 +6916,8 @@ forward."
     (when (gnus-visual-p 'page-marker)
       (let ((buffer-read-only nil))
        (gnus-remove-text-with-property 'gnus-prev)
-       (gnus-remove-text-with-property 'gnus-next)))))
+       (gnus-remove-text-with-property 'gnus-next))
+      (setq gnus-page-broken nil))))
 
 (defun gnus-summary-move-article (&optional n to-newsgroup
                                            select-method action)
@@ -7071,6 +7120,9 @@ and `request-accept' functions."
              (gnus-request-replace-article
               article gnus-newsgroup-name (current-buffer)))))
 
+       ;;;!!!Why is this necessary?
+       (set-buffer gnus-summary-buffer)
+       
        (gnus-summary-goto-subject article)
        (when (eq action 'move)
          (gnus-summary-mark-article article gnus-canceled-mark))))
@@ -7166,7 +7218,7 @@ latter case, they will be copied into the relevant groups."
       (set-buffer (get-buffer-create " *import file*"))
       (buffer-disable-undo (current-buffer))
       (erase-buffer)
-      (insert-file-contents file)
+      (nnheader-insert-file-contents file)
       (goto-char (point-min))
       (unless (nnheader-article-p)
        ;; This doesn't look like an article, so we fudge some headers.
@@ -7211,7 +7263,7 @@ This will be the case if the article has both been mailed and posted."
                            ;; We need to update the info for
                            ;; this group for `gnus-list-of-read-articles'
                            ;; to give us the right answer.
-                           (run-hooks 'gnus-exit-group-hook)
+                           (gnus-run-hooks 'gnus-exit-group-hook)
                            (gnus-summary-update-info)
                            (gnus-list-of-read-articles gnus-newsgroup-name))
                        (setq gnus-newsgroup-expirable
@@ -7225,13 +7277,14 @@ This will be the case if the article has both been mailed and posted."
        ;; through the expiry process.
        (gnus-message 6 "Expiring articles...")
        ;; The list of articles that weren't expired is returned.
-       (if expiry-wait
-           (let ((nnmail-expiry-wait-function nil)
-                 (nnmail-expiry-wait expiry-wait))
-             (setq es (gnus-request-expire-articles
-                       expirable gnus-newsgroup-name)))
-         (setq es (gnus-request-expire-articles
-                   expirable gnus-newsgroup-name)))
+       (save-excursion
+         (if expiry-wait
+             (let ((nnmail-expiry-wait-function nil)
+                   (nnmail-expiry-wait expiry-wait))
+               (setq es (gnus-request-expire-articles
+                         expirable gnus-newsgroup-name)))
+           (setq es (gnus-request-expire-articles
+                     expirable gnus-newsgroup-name))))
        (unless total
          (setq gnus-newsgroup-expirable es))
        ;; We go through the old list of expirable, and mark all
@@ -7251,10 +7304,10 @@ This will be the case if the article has both been mailed and posted."
 This means that *all* articles that are marked as expirable will be
 deleted forever, right now."
   (interactive)
-  (or gnus-expert-user
-      (gnus-yes-or-no-p
-       "Are you really, really, really sure you want to delete all these messages? ")
-      (error "Phew!"))
+  (unless gnus-expert-user
+    (gnus-yes-or-no-p
+     "Are you really, really, really sure you want to delete all these messages? ")
+    (error "Phew!"))
   (gnus-summary-expire-articles t))
 
 ;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
@@ -7367,17 +7420,17 @@ groups."
     (unless no-highlight
       (save-excursion
        (set-buffer gnus-article-buffer)
-       (run-hooks 'gnus-article-display-hook)
+       (gnus-run-hooks 'gnus-article-display-hook)
        (set-buffer gnus-original-article-buffer)
        (gnus-request-article
         (cdr gnus-article-current)
         (car gnus-article-current) (current-buffer))))
     ;; Prettify the summary buffer line.
     (when (gnus-visual-p 'summary-highlight 'highlight)
-      (run-hooks 'gnus-visual-mark-article-hook))))
+      (gnus-run-hooks 'gnus-visual-mark-article-hook))))
 
 (defun gnus-summary-edit-wash (key)
-  "Perform editing command in the article buffer."
+  "Perform editing command KEY in the article buffer."
   (interactive
    (list
     (progn
@@ -7654,38 +7707,41 @@ returned."
 
 (defun gnus-summary-mark-article-as-unread (mark)
   "Mark the current article quickly as unread with MARK."
-  (let ((article (gnus-summary-article-number)))
-    (if (<= article 0)
-       (progn
-         (gnus-error 1 "Can't mark negative article numbers")
-         nil)
-      (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
-      (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
-      (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
-      (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
-      (cond ((= mark gnus-ticked-mark)
-            (push article gnus-newsgroup-marked))
-           ((= mark gnus-dormant-mark)
-            (push article gnus-newsgroup-dormant))
-           (t
-            (push article gnus-newsgroup-unreads)))
-      (setq gnus-newsgroup-reads
-           (delq (assq article gnus-newsgroup-reads)
-                 gnus-newsgroup-reads))
-
-      ;; See whether the article is to be put in the cache.
-      (and gnus-use-cache
-          (vectorp (gnus-summary-article-header article))
-          (save-excursion
-            (gnus-cache-possibly-enter-article
-             gnus-newsgroup-name article
-             (gnus-summary-article-header article)
-             (= mark gnus-ticked-mark)
-             (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
-
-      ;; Fix the mark.
-      (gnus-summary-update-mark mark 'unread)
-      t)))
+  (let* ((article (gnus-summary-article-number))
+        (old-mark (gnus-summary-article-mark article)))
+    (if (eq mark old-mark)
+       t
+      (if (<= article 0)
+         (progn
+           (gnus-error 1 "Can't mark negative article numbers")
+           nil)
+       (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+       (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
+       (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
+       (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
+       (cond ((= mark gnus-ticked-mark)
+              (push article gnus-newsgroup-marked))
+             ((= mark gnus-dormant-mark)
+              (push article gnus-newsgroup-dormant))
+             (t
+              (push article gnus-newsgroup-unreads)))
+       (setq gnus-newsgroup-reads
+             (delq (assq article gnus-newsgroup-reads)
+                   gnus-newsgroup-reads))
+
+       ;; See whether the article is to be put in the cache.
+       (and gnus-use-cache
+            (vectorp (gnus-summary-article-header article))
+            (save-excursion
+              (gnus-cache-possibly-enter-article
+               gnus-newsgroup-name article
+               (gnus-summary-article-header article)
+               (= mark gnus-ticked-mark)
+               (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
+
+       ;; Fix the mark.
+       (gnus-summary-update-mark mark 'unread)
+       t))))
 
 (defun gnus-summary-mark-article (&optional article mark no-expire)
   "Mark ARTICLE with MARK.  MARK can be any character.
@@ -7708,32 +7764,35 @@ marked."
                    (= mark gnus-duplicate-mark))))
        (setq mark gnus-expirable-mark))
   (let* ((mark (or mark gnus-del-mark))
-        (article (or article (gnus-summary-article-number))))
-    (unless article
-      (error "No article on current line"))
-    (if (not (if (or (= mark gnus-unread-mark)
-                    (= mark gnus-ticked-mark)
-                    (= mark gnus-dormant-mark))
-                (gnus-mark-article-as-unread article mark)
-              (gnus-mark-article-as-read article mark)))
+        (article (or article (gnus-summary-article-number)))
+        (old-mark (gnus-summary-article-mark article)))
+    (if (eq mark old-mark)
        t
-      ;; See whether the article is to be put in the cache.
-      (and gnus-use-cache
-          (not (= mark gnus-canceled-mark))
-          (vectorp (gnus-summary-article-header article))
-          (save-excursion
-            (gnus-cache-possibly-enter-article
-             gnus-newsgroup-name article
-             (gnus-summary-article-header article)
-             (= mark gnus-ticked-mark)
-             (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
-
-      (when (gnus-summary-goto-subject article nil t)
-       (let ((buffer-read-only nil))
-         (gnus-summary-show-thread)
-         ;; Fix the mark.
-         (gnus-summary-update-mark mark 'unread)
-         t)))))
+      (unless article
+       (error "No article on current line"))
+      (if (not (if (or (= mark gnus-unread-mark)
+                      (= mark gnus-ticked-mark)
+                      (= mark gnus-dormant-mark))
+                  (gnus-mark-article-as-unread article mark)
+                (gnus-mark-article-as-read article mark)))
+         t
+       ;; See whether the article is to be put in the cache.
+       (and gnus-use-cache
+            (not (= mark gnus-canceled-mark))
+            (vectorp (gnus-summary-article-header article))
+            (save-excursion
+              (gnus-cache-possibly-enter-article
+               gnus-newsgroup-name article
+               (gnus-summary-article-header article)
+               (= mark gnus-ticked-mark)
+               (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
+
+       (when (gnus-summary-goto-subject article nil t)
+         (let ((buffer-read-only nil))
+           (gnus-summary-show-thread)
+           ;; Fix the mark.
+           (gnus-summary-update-mark mark 'unread)
+           t))))))
 
 (defun gnus-summary-update-secondary-mark (article)
   "Update the secondary (read, process, cache) mark."
@@ -7749,7 +7808,7 @@ marked."
         (t gnus-unread-mark))
    'replied)
   (when (gnus-visual-p 'summary-highlight 'highlight)
-    (run-hooks 'gnus-summary-update-hook))
+    (gnus-run-hooks 'gnus-summary-update-hook))
   t)
 
 (defun gnus-summary-update-mark (mark type)
@@ -7784,7 +7843,8 @@ marked."
     (push (cons article mark) gnus-newsgroup-reads)
     ;; Possibly remove from cache, if that is used.
     (when gnus-use-cache
-      (gnus-cache-enter-remove-article article))))
+      (gnus-cache-enter-remove-article article))
+    t))
 
 (defun gnus-mark-article-as-unread (article &optional mark)
   "Enter ARTICLE in the pertinent lists and remove it from others."
@@ -8043,7 +8103,8 @@ If prefix argument ALL is non-nil, all articles are marked as read."
   (interactive "P")
   (when (gnus-summary-catchup all quietly nil 'fast)
     ;; Select next newsgroup or exit.
-    (if (eq gnus-auto-select-next 'quietly)
+    (if (and (not (gnus-group-quit-config gnus-newsgroup-name))
+            (eq gnus-auto-select-next 'quietly))
        (gnus-summary-next-group nil)
       (gnus-summary-exit))))
 
@@ -8139,7 +8200,9 @@ is non-nil or the Subject: of both articles are the same."
                         (gnus-summary-article-header parent-article))))
        (unless (and message-id (not (equal message-id "")))
          (error "No message-id in desired parent"))
-       (gnus-summary-select-article t t nil current-article)
+       ;; We don't want the article to be marked as read.
+       (let (gnus-mark-article-hook)
+         (gnus-summary-select-article t t nil current-article))
        (set-buffer gnus-original-article-buffer)
        (let ((buf (format "%s" (buffer-string))))
          (nnheader-temp-write nil
@@ -8701,7 +8764,7 @@ save those articles instead."
   (cond ((assq 'execute props)
         (gnus-execute-command (cdr (assq 'execute props)))))
   (let ((gnus-current-article (gnus-summary-article-number)))
-    (run-hooks 'gnus-mark-article-hook)))
+    (gnus-run-hooks 'gnus-mark-article-hook)))
 
 (defun gnus-execute-command (command &optional automatic)
   (save-excursion
@@ -8947,7 +9010,9 @@ save those articles instead."
       (when buffers
        (map-y-or-n-p
         "Update summary buffer %s? "
-        (lambda (buf) (switch-to-buffer buf) (gnus-summary-exit))
+        (lambda (buf)
+          (switch-to-buffer buf)
+          (gnus-summary-exit))
         buffers)))))
 
 
@@ -8958,13 +9023,13 @@ save those articles instead."
   (gnus-summary-preview-mime-message (gnus-summary-article-number))
   )
 
-(autoload 'mime-combine-message/partials-automatically
+(autoload 'mime-method-to-combine-message/partial-pieces
   "mime-partial"
   "Internal method to combine message/partial messages automatically.")
 
 (set-atype 'mime-acting-condition
-          '((type . "message/partial")
-            (method . mime-combine-message/partials-automatically)
+          '((type . message)(subtype . partial)
+            (method . mime-method-to-combine-message/partial-pieces)
             (major-mode . gnus-original-article-mode)
             (summary-buffer-exp . gnus-summary-buffer)
             ))