*** empty log message ***
[gnus] / lisp / gnus-sum.el
index 53c7cac..3bda04e 100644 (file)
@@ -332,7 +332,7 @@ the primary sort function should be the last.  You should probably
 always include `gnus-thread-sort-by-number' in the list of sorting
 functions -- preferably first.
 
-Ready-mady functions include `gnus-thread-sort-by-number',
+Ready-made functions include `gnus-thread-sort-by-number',
 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
 `gnus-thread-sort-by-date', `gnus-thread-sort-by-score' and
 `gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').")
@@ -419,8 +419,130 @@ variable.")
 The hook is intended to mark an article as read (or unread)
 automatically when it is selected.")
 
+(defvar gnus-group-no-more-groups-hook nil
+  "*A hook run when returning to group mode having no more (unread) groups.")
+
+(defvar gnus-summary-selected-face 'underline
+  "Face used for highlighting the current article in the summary buffer.")
+
+(defvar gnus-summary-highlight 
+  (cond
+   ((not (eq gnus-display-type 'color))
+    '(((> score default) . bold)
+      ((< score default) . italic)))
+   ((eq gnus-background-mode 'dark)
+    (list
+     (cons 
+      '(= mark gnus-canceled-mark)
+      (custom-face-lookup "yellow" "black" nil
+                         nil nil nil))
+     (cons '(and (> score default) 
+                (or (= mark gnus-dormant-mark)
+                    (= mark gnus-ticked-mark)))
+          (custom-face-lookup 
+           "pink" nil nil t nil nil))
+     (cons '(and (< score default) 
+                (or (= mark gnus-dormant-mark)
+                    (= mark gnus-ticked-mark)))
+          (custom-face-lookup "pink" nil nil 
+                              nil t nil))
+     (cons '(or (= mark gnus-dormant-mark)
+               (= mark gnus-ticked-mark))
+          (custom-face-lookup 
+           "pink" nil nil nil nil nil))
+
+     (cons
+      '(and (> score default) (= mark gnus-ancient-mark))
+      (custom-face-lookup "medium blue" nil nil t
+                         nil nil))
+     (cons 
+      '(and (< score default) (= mark gnus-ancient-mark))
+      (custom-face-lookup "SkyBlue" nil nil
+                         nil t nil))
+     (cons 
+      '(= mark gnus-ancient-mark)
+      (custom-face-lookup "SkyBlue" nil nil
+                         nil nil nil))
+     (cons '(and (> score default) (= mark gnus-unread-mark))
+          (custom-face-lookup "white" nil nil t
+                              nil nil))
+     (cons '(and (< score default) (= mark gnus-unread-mark))
+          (custom-face-lookup "white" nil nil
+                              nil t nil))
+     (cons '(= mark gnus-unread-mark)
+          (custom-face-lookup
+           "white" nil nil nil nil nil))
+
+     (cons '(> score default) 'bold)
+     (cons '(< score default) 'italic)))
+   (t
+    (list
+     (cons
+      '(= mark gnus-canceled-mark)
+      (custom-face-lookup
+       "yellow" "black" nil nil nil nil))
+     (cons '(and (> score default) 
+                (or (= mark gnus-dormant-mark)
+                    (= mark gnus-ticked-mark)))
+          (custom-face-lookup "firebrick" nil nil
+                              t nil nil))
+     (cons '(and (< score default) 
+                (or (= mark gnus-dormant-mark)
+                    (= mark gnus-ticked-mark)))
+          (custom-face-lookup "firebrick" nil nil
+                              nil t nil))
+     (cons 
+      '(or (= mark gnus-dormant-mark)
+          (= mark gnus-ticked-mark))
+      (custom-face-lookup 
+       "firebrick" nil nil nil nil nil))
+
+     (cons '(and (> score default) (= mark gnus-ancient-mark))
+          (custom-face-lookup "RoyalBlue" nil nil
+                              t nil nil))
+     (cons '(and (< score default) (= mark gnus-ancient-mark))
+          (custom-face-lookup "RoyalBlue" nil nil
+                              nil t nil))
+     (cons 
+      '(= mark gnus-ancient-mark)
+      (custom-face-lookup
+       "RoyalBlue" nil nil nil nil nil))
+
+     (cons '(and (> score default) (/= mark gnus-unread-mark))
+          (custom-face-lookup "DarkGreen" nil nil
+                              t nil nil))
+     (cons '(and (< score default) (/= mark gnus-unread-mark))
+          (custom-face-lookup "DarkGreen" nil nil
+                              nil t nil))
+     (cons
+      '(/= mark gnus-unread-mark)
+      (custom-face-lookup "DarkGreen" nil nil 
+                         nil nil nil))
+
+     (cons '(> score default) 'bold)
+     (cons '(< score default) 'italic))))
+  "Controls the highlighting of summary buffer lines. 
+
+Below is a list of `Form'/`Face' pairs.  When deciding how a a
+particular summary line should be displayed, each form is
+evaluated.  The content of the face field after the first true form is
+used.  You can change how those summary lines are displayed, by
+editing the face field.  
+
+It is also possible to change and add form fields, but currently that
+requires an understanding of Lisp expressions.  Hopefully this will
+change in a future release.  For now, you can use the following
+variables in the Lisp expression:
+
+score:   The article's score
+default: The default article score.
+below:   The score below which articles are automatically marked as read. 
+mark:    The article's mark.")
+
 ;;; Internal variables
 
+(defvar gnus-scores-exclude-files nil)
+
 (defvar gnus-summary-display-table 
   ;; Change the display table. Odd characters have a tendency to mess
   ;; up nicely formatted displays - we make all possible glyphs
@@ -433,7 +555,7 @@ automatically when it is selected.")
        (i 32))
     (while (>= (setq i (1- i)) 0)
       (aset table i [??]))
-    ;; ... but not newline and cr, of course. (cr is necessary for the
+    ;; ... but not newline and cr, of course.  (cr is necessary for the
     ;; selective display).
     (aset table ?\n nil)
     (aset table ?\r nil)
@@ -727,7 +849,7 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
          (replace-match "" t t))))))
 
 (defun gnus-simplify-subject-fuzzy (subject)
-  "Siplify a subject string fuzzily."
+  "Simplify a subject string fuzzily."
   (save-excursion
     (gnus-set-work-buffer)
     (let ((case-fold-search t))
@@ -871,7 +993,7 @@ increase the score of each group you read."
     "|" gnus-summary-pipe-output
     "\M-k" gnus-summary-edit-local-kill
     "\M-K" gnus-summary-edit-global-kill
-    "V" gnus-version
+    ;; "V" gnus-version
     "\C-c\C-d" gnus-summary-describe-group
     "q" gnus-summary-exit
     "Q" gnus-summary-exit-no-update
@@ -892,7 +1014,6 @@ increase the score of each group you read."
     "\M-*" gnus-cache-remove-article
     "\M-&" gnus-summary-universal-argument
     "\C-l" gnus-recenter
-    "\M-\C-g" gnus-summary-prepare 
     "I" gnus-summary-increase-score
     "L" gnus-summary-lower-score
 
@@ -923,7 +1044,7 @@ increase the score of each group you read."
     "K" gnus-summary-kill-same-subject
     "P" gnus-uu-mark-map)
 
-  (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mode-map)
+  (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map)
     "c" gnus-summary-clear-above
     "u" gnus-summary-tick-above
     "m" gnus-summary-mark-above
@@ -980,6 +1101,10 @@ increase the score of each group you read."
     "#" gnus-uu-mark-thread
     "\M-#" gnus-uu-unmark-thread)
 
+  (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
+    "g" gnus-summary-prepare 
+    "c" gnus-summary-insert-cached-articles)
+
   (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
     "c" gnus-summary-catchup-and-exit
     "C" gnus-summary-catchup-all-and-exit
@@ -1106,14 +1231,13 @@ increase the score of each group you read."
          ["Clear above" gnus-summary-clear-above t])
         ["Current score" gnus-summary-current-score t]
         ["Set score" gnus-summary-set-score t]
-        ["Customize score file" gnus-score-customize t]
         ["Switch current score file..." gnus-score-change-score-file t]
         ["Set mark below..." gnus-score-set-mark-below t]
         ["Set expunge below..." gnus-score-set-expunge-below t]
         ["Edit current score file" gnus-score-edit-current-scores t]
         ["Edit score file" gnus-score-edit-file t]
         ["Trace score" gnus-score-find-trace t]
-        ["Find words" gnus-score-find-favuorite-words t]
+        ["Find words" gnus-score-find-favourite-words t]
         ["Rescore buffer" gnus-summary-rescore t]
         ["Increase score..." gnus-summary-increase-score t]
         ["Lower score..." gnus-summary-lower-score t]))))
@@ -1136,7 +1260,7 @@ increase the score of each group you read."
        (gnus-score-set-default 'gnus-score-default-header 'h)
        :style radio 
        :selected (eq gnus-score-default-header 'h )]
-       ["Message-Id" (gnus-score-set-default 'gnus-score-default-header 'i)
+       ["Message-ID" (gnus-score-set-default 'gnus-score-default-header 'i)
        :style radio 
        :selected (eq gnus-score-default-header 'i )]
        ["Thread" (gnus-score-set-default 'gnus-score-default-header 't)
@@ -1285,7 +1409,7 @@ increase the score of each group you read."
         (gnus-check-backend-function
          'request-replace-article gnus-newsgroup-name)]
        ["Import file..." gnus-summary-import-article t]
-       ["Chek if posted" gnus-summary-article-posted-p t]
+       ["Check if posted" gnus-summary-article-posted-p t]
        ["Edit article" gnus-summary-edit-article
         (not (gnus-group-read-only-p))]
        ["Delete article" gnus-summary-delete-article
@@ -1766,12 +1890,19 @@ The following commands are available:
 (defmacro gnus-summary-skip-intangible ()
   "If the current article is intangible, then jump to a different article."
   '(let ((to (get-text-property (point) 'gnus-intangible)))
-    (and to (gnus-summary-goto-subject to))))
+     (and to (gnus-summary-goto-subject to))))
 
 (defmacro gnus-summary-article-intangible-p ()
   "Say whether this article is intangible or not."
   '(get-text-property (point) 'gnus-intangible))
 
+(defun gnus-article-read-p (article)
+  "Say whether ARTICLE is read or not."
+  (not (or (memq article gnus-newsgroup-marked)
+          (memq article gnus-newsgroup-unreads)
+          (memq article gnus-newsgroup-unselected)
+          (memq article gnus-newsgroup-dormant))))
+
 ;; Some summary mode macros.
 
 (defmacro gnus-summary-article-number ()
@@ -1836,7 +1967,7 @@ article number."
                                    (gnus-data-list t)))
         (level (gnus-data-level (car data))))
     (if (zerop level)
-       () ; This is a root.
+       ()                              ; This is a root.
       ;; We search until we find an article with a level less than
       ;; this one.  That function has to be the parent.
       (while (and (setq data (cdr data))
@@ -1954,12 +2085,16 @@ This is all marks except unread, ticked, dormant, and expirable."
        (setq gnus-article-buffer article-buffer)
        (setq gnus-original-article-buffer original)
        (setq gnus-reffed-article-number reffed)
-       (setq gnus-current-score-file score-file)))))
+       (setq gnus-current-score-file score-file)
+       ;; The article buffer also has local variables.
+       (when (gnus-buffer-live-p gnus-article-buffer)
+         (set-buffer gnus-article-buffer)
+         (setq gnus-summary-buffer summary))))))
 
 (defun gnus-summary-last-article-p (&optional article)
   "Return whether ARTICLE is the last article in the buffer."
   (if (not (setq article (or article (gnus-summary-article-number))))
-      t ; All non-existant numbers are the last article. :-)
+      t                                        ; All non-existent numbers are the last article.  :-)
     (not (cdr (gnus-data-find-list article)))))
 
 (defun gnus-make-thread-indent-array ()
@@ -2011,10 +2146,12 @@ This is all marks except unread, ticked, dormant, and expirable."
    (point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
    (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
 
-(defun gnus-summary-insert-line
-  (gnus-tmp-header gnus-tmp-level gnus-tmp-current gnus-tmp-unread
-                  gnus-tmp-replied gnus-tmp-expirable gnus-tmp-subject-or-nil
-                  &optional gnus-tmp-dummy gnus-tmp-score gnus-tmp-process)
+(defun gnus-summary-insert-line (gnus-tmp-header 
+                                gnus-tmp-level gnus-tmp-current 
+                                gnus-tmp-unread gnus-tmp-replied 
+                                gnus-tmp-expirable gnus-tmp-subject-or-nil
+                                &optional gnus-tmp-dummy gnus-tmp-score 
+                                gnus-tmp-process)
   (let* ((gnus-tmp-indentation (aref gnus-thread-indent-array gnus-tmp-level))
         (gnus-tmp-lines (mail-header-lines gnus-tmp-header))
         (gnus-tmp-score (or gnus-tmp-score gnus-summary-default-score 0))
@@ -2121,7 +2258,7 @@ the thread are to be displayed."
       number)))
 
 (defun gnus-summary-set-local-parameters (group)
- "Go through the local params of GROUP and set all variable specs in that list."
 "Go through the local params of GROUP and set all variable specs in that list."
   (let ((params (gnus-group-find-parameter group))
        elem)
     (while params
@@ -2278,7 +2415,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        (when kill-buffer
          (gnus-kill-or-deaden-summary kill-buffer))
        (when (get-buffer-window gnus-group-buffer t)
-         ;; Gotta use windows, because recenter does wierd stuff if
+         ;; Gotta use windows, because recenter does weird stuff if
          ;; the current buffer ain't the displayed window.
          (let ((owin (selected-window)))
            (select-window (get-buffer-window gnus-group-buffer t))
@@ -2379,16 +2516,17 @@ If NO-DISPLAY, don't generate a summary buffer."
        (thhashtb (gnus-make-hashtable 1023))
        (prev threads)
        (result threads)
-       ids references id gthread gid entered)
+       ids references id gthread gid entered ref)
     (while threads
       (when (setq references (mail-header-references (caar threads)))
        (setq id (mail-header-id (caar threads))
              ids (gnus-split-references references)
              entered nil)
-       (while ids
-         (if (not (setq gid (gnus-gethash (car ids) idhashtb)))
+       (while (setq ref (pop ids))
+         (setq ids (delete ref ids))
+         (if (not (setq gid (gnus-gethash ref idhashtb)))
              (progn
-               (gnus-sethash (car ids) id idhashtb)
+               (gnus-sethash ref id idhashtb)
                (gnus-sethash id threads thhashtb))
            (setq gthread (gnus-gethash gid thhashtb))
            (unless entered
@@ -2406,8 +2544,7 @@ If NO-DISPLAY, don't generate a summary buffer."
            (setq entered t)
            ;; Remove it from the list of threads.
            (setcdr prev (cdr threads))
-           (setq threads prev))
-         (setq ids (cdr ids))))
+           (setq threads prev))))
       (setq prev threads)
       (setq threads (cdr threads)))
     result))
@@ -2440,7 +2577,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        header references generation relations 
        cthread subject child end pthread relation)
     ;; First we create an alist of generations/relations, where 
-    ;; generations is how much we trust the ralation, and the relation
+    ;; generations is how much we trust the relation, and the relation
     ;; is parent/child.
     (gnus-message 7 "Making sparse threads...")
     (save-excursion
@@ -2622,8 +2759,8 @@ If NO-DISPLAY, don't generate a summary buffer."
        (setq thread (cdr thread))
        (while thread
          (unless (memq (setq thr (gnus-id-to-thread
-                                     (gnus-root-id
-                                      (mail-header-id (caar thread)))))
+                                  (gnus-root-id
+                                   (mail-header-id (caar thread)))))
                        roots)
            (push thr roots))
          (setq thread (cdr thread)))
@@ -2743,7 +2880,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        (setq thread (gnus-gethash last-id dep)))
       (when thread
        (prog1
-           thread ; We return this thread.
+           thread                      ; We return this thread.
          (unless dont-remove
            (if (stringp (car thread))
                (progn
@@ -2775,28 +2912,20 @@ If NO-DISPLAY, don't generate a summary buffer."
   "Sort THREADS."
   (if (not gnus-thread-sort-functions)
       threads
-    (let ((func (if (= 1 (length gnus-thread-sort-functions))
-                   (car gnus-thread-sort-functions)
-                 `(lambda (t1 t2)
-                    ,(gnus-make-sort-function 
-                      (reverse gnus-thread-sort-functions))))))
-      (gnus-message 7 "Sorting threads...")
-      (prog1
-         (sort threads func)
-       (gnus-message 7 "Sorting threads...done")))))
+    (gnus-message 7 "Sorting threads...")
+    (prog1
+       (sort threads (gnus-make-sort-function gnus-thread-sort-functions))
+      (gnus-message 7 "Sorting threads...done"))))
 
 (defun gnus-sort-articles (articles)
   "Sort ARTICLES."
   (when gnus-article-sort-functions
-    (let ((func (if (= 1 (length gnus-article-sort-functions))
-                   (car gnus-article-sort-functions)
-                 `(lambda (t1 t2)
-                    ,(gnus-make-sort-function 
-                      (reverse gnus-article-sort-functions))))))
-      (gnus-message 7 "Sorting articles...")
-      (prog1
-         (setq gnus-newsgroup-headers (sort articles func))
-       (gnus-message 7 "Sorting articles...done")))))
+    (gnus-message 7 "Sorting articles...")
+    (prog1
+       (setq gnus-newsgroup-headers
+             (sort articles (gnus-make-sort-function 
+                             gnus-article-sort-functions)))
+      (gnus-message 7 "Sorting articles...done"))))
 
 ;; Written by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
 (defmacro gnus-thread-header (thread)
@@ -2897,10 +3026,10 @@ Unscored articles will be counted as having a score of zero."
              (mapcar 'gnus-thread-total-score
                      (cdr (gnus-gethash (mail-header-id root)
                                         gnus-newsgroup-dependencies)))
-                (if (> (mail-header-number root) 0)
-                    (list (or (cdr (assq (mail-header-number root) 
-                                         gnus-newsgroup-scored))
-                              gnus-summary-default-score 0))))
+             (if (> (mail-header-number root) 0)
+                 (list (or (cdr (assq (mail-header-number root) 
+                                      gnus-newsgroup-scored))
+                           gnus-summary-default-score 0))))
             (list gnus-summary-default-score)
             '(0))))
 
@@ -3671,6 +3800,8 @@ The resulting hash table is returned, or nil if no Xrefs were found."
        headers id id-dep ref-dep end ref)
     (save-excursion
       (set-buffer nntp-server-buffer)
+      ;; Translate all TAB characters into SPACE characters.
+      (subst-char-in-region (point-min) (point-max) ?\t ?  t)
       (run-hooks 'gnus-parse-headers-hook)
       (let ((case-fold-search t)
            in-reply-to header p lines)
@@ -3815,38 +3946,6 @@ The resulting hash table is returned, or nil if no Xrefs were found."
 (defmacro gnus-nov-field ()
   '(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
 
-;; Goes through the xover lines and returns a list of vectors
-(defun gnus-get-newsgroup-headers-xover (sequence &optional 
-                                                 force-new dependencies)
-  "Parse the news overview data in the server buffer, and return a
-list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
-  ;; Get the Xref when the users reads the articles since most/some
-  ;; NNTP servers do not include Xrefs when using XOVER.
-  (setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
-  (let ((cur nntp-server-buffer)
-       (dependencies (or dependencies gnus-newsgroup-dependencies))
-       number headers header)
-    (save-excursion
-      (set-buffer nntp-server-buffer)
-      ;; Allow the user to mangle the headers before parsing them.
-      (run-hooks 'gnus-parse-headers-hook)
-      (goto-char (point-min))
-      (while (and sequence (not (eobp)))
-       (setq number (read cur))
-       (while (and sequence (< (car sequence) number))
-         (setq sequence (cdr sequence)))
-       (and sequence
-            (eq number (car sequence))
-            (progn
-              (setq sequence (cdr sequence))
-              (if (setq header
-                        (inline (gnus-nov-parse-line
-                                 number dependencies force-new)))
-                  (setq headers (cons header headers)))))
-       (forward-line 1))
-      (setq headers (nreverse headers)))
-    headers))
-
 ;; This function has to be called with point after the article number
 ;; on the beginning of the line.
 (defun gnus-nov-parse-line (number dependencies &optional force-new)
@@ -3859,70 +3958,100 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
     (narrow-to-region (point) eol)
     (or (eobp) (forward-char))
 
-    (condition-case nil
-       (setq header
-             (vector
-              number                   ; number
-              (gnus-nov-field)         ; subject
-              (gnus-nov-field)         ; from
-              (gnus-nov-field)         ; date
-              (setq id (or (gnus-nov-field)
-                           (concat "none+"
-                                   (int-to-string
-                                    (setq none (1+ none)))))) ; id
-              (progn
-                (save-excursion
-                  (let ((beg (point)))
-                    (search-forward "\t" eol)
-                    (if (search-backward ">" beg t)
-                        (setq ref
-                              (buffer-substring
-                               (1+ (point))
-                               (search-backward "<" beg t)))
-                      (setq ref nil))))
-                (gnus-nov-field))      ; refs
-              (gnus-nov-read-integer)  ; chars
-              (gnus-nov-read-integer)  ; lines
-              (if (= (following-char) ?\n)
-                  nil
-                (gnus-nov-field))      ; misc
-              ))
-      (error (progn
-              (gnus-error 4 "Strange nov line")
-              (setq header nil)
-              (goto-char eol))))
+    (setq header
+         (vector
+          number                       ; number
+          (gnus-nov-field)             ; subject
+          (gnus-nov-field)             ; from
+          (gnus-nov-field)             ; date
+          (setq id (or (gnus-nov-field)
+                       (concat "none+"
+                               (int-to-string
+                                (setq none (1+ none)))))) ; id
+          (progn
+            (save-excursion
+              (let ((beg (point)))
+                (search-forward "\t" eol)
+                (if (search-backward ">" beg t)
+                    (setq ref
+                          (buffer-substring
+                           (1+ (point))
+                           (search-backward "<" beg t)))
+                  (setq ref nil))))
+            (gnus-nov-field))          ; refs
+          (gnus-nov-read-integer)      ; chars
+          (gnus-nov-read-integer)      ; lines
+          (if (= (following-char) ?\n)
+              nil
+            (gnus-nov-field))          ; misc
+          ))
 
     (widen)
 
     ;; We build the thread tree.
-    (when header
-      (when (equal id ref)
-       ;; This article refers back to itself.  Naughty, naughty.
-       (setq ref nil))
-      (if (boundp (setq id-dep (intern id dependencies)))
-         (if (and (car (symbol-value id-dep))
-                  (not force-new))
-             ;; An article with this Message-ID has already been seen,
-             ;; so we ignore this one, except we add any additional
-             ;; Xrefs (in case the two articles came from different
-             ;; servers.
-             (progn
-               (mail-header-set-xref
-                (car (symbol-value id-dep))
-                (concat (or (mail-header-xref
-                             (car (symbol-value id-dep))) "")
-                        (or (mail-header-xref header) "")))
-               (setq header nil))
-           (setcar (symbol-value id-dep) header))
-       (set id-dep (list header))))
-    (when header
-      (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
-         (setcdr (symbol-value ref-dep)
-                 (nconc (cdr (symbol-value ref-dep))
-                        (list (symbol-value id-dep))))
-       (set ref-dep (list nil (symbol-value id-dep)))))
+    (when (equal id ref)
+      ;; This article refers back to itself.  Naughty, naughty.
+      (setq ref nil))
+    (if (boundp (setq id-dep (intern id dependencies)))
+       (if (and (car (symbol-value id-dep))
+                (not force-new))
+           ;; An article with this Message-ID has already been seen,
+           ;; so we ignore this one, except we add any additional
+           ;; Xrefs (in case the two articles came from different
+           ;; servers.
+           (progn
+             (mail-header-set-xref
+              (car (symbol-value id-dep))
+              (concat (or (mail-header-xref
+                           (car (symbol-value id-dep))) "")
+                      (or (mail-header-xref header) "")))
+             (setq header nil))
+         (setcar (symbol-value id-dep) header))
+      (set id-dep (list header)))
+    (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
+       (setcdr (symbol-value ref-dep)
+               (nconc (cdr (symbol-value ref-dep))
+                      (list (symbol-value id-dep))))
+      (set ref-dep (list nil (symbol-value id-dep))))
     header))
 
+;; Goes through the xover lines and returns a list of vectors
+(defun gnus-get-newsgroup-headers-xover (sequence &optional 
+                                                 force-new dependencies)
+  "Parse the news overview data in the server buffer, and return a
+list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
+  ;; Get the Xref when the users reads the articles since most/some
+  ;; NNTP servers do not include Xrefs when using XOVER.
+  (setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
+  (let ((cur nntp-server-buffer)
+       (dependencies (or dependencies gnus-newsgroup-dependencies))
+       number headers header)
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      ;; Allow the user to mangle the headers before parsing them.
+      (run-hooks 'gnus-parse-headers-hook)
+      (goto-char (point-min))
+      (while (not (eobp))
+       (condition-case ()
+           (while (and sequence (not (eobp)))
+             (setq number (read cur))
+             (while (and sequence
+                         (< (car sequence) number))
+               (setq sequence (cdr sequence)))
+             (and sequence
+                  (eq number (car sequence))
+                  (progn
+                    (setq sequence (cdr sequence))
+                    (push (inline (gnus-nov-parse-line
+                                   number dependencies force-new))
+                          headers)))
+             (forward-line 1))
+         (error
+          (progn
+            (gnus-error 4 "Strange nov line")
+            (forward-line 1)))))
+      (nreverse headers))))
+
 (defun gnus-article-get-xrefs ()
   "Fill in the Xref value in `gnus-current-headers', if necessary.
 This is meant to be called in `gnus-article-internal-prepare-hook'."
@@ -4181,13 +4310,13 @@ displayed, no centering will be performed."
     ;; The user has to want it.
     (when gnus-auto-center-summary
       (when (get-buffer-window gnus-article-buffer)
-       ;; Only do recentering when the article buffer is displayed,
-       ;; Set the window start to either `bottom', which is the biggest
-       ;; possible valid number, or the second line from the top,
-       ;; whichever is the least.
-       (set-window-start
-       window (min bottom (save-excursion 
-                            (forward-line (- top)) (point)))))
+       ;; Only do recentering when the article buffer is displayed,
+       ;; Set the window start to either `bottom', which is the biggest
+       ;; possible valid number, or the second line from the top,
+       ;; whichever is the least.
+       (set-window-start
+        window (min bottom (save-excursion 
+                             (forward-line (- top)) (point)))))
       ;; Do horizontal recentering while we're at it.
       (when (and (get-buffer-window (current-buffer) t)
                 (not (eq gnus-auto-center-summary 'vertical)))
@@ -4218,7 +4347,7 @@ displayed, no centering will be performed."
 ;; the range of active articles.
 (defun gnus-list-of-unread-articles (group)
   (let* ((read (gnus-info-read (gnus-get-info group)))
-        (active (gnus-active group))
+        (active (or (gnus-active group) (gnus-activate-group group)))
         (last (cdr active))
         first nlast unread)
     ;; If none are read, then all are unread.
@@ -4411,7 +4540,7 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
          (bury-buffer gnus-article-buffer))
        ;; We clear the global counterparts of the buffer-local
        ;; variables as well, just to be on the safe side.
-       (gnus-configure-windows 'group 'force)
+       (set-buffer gnus-group-buffer)
        (gnus-summary-clear-local-variables)
        ;; Return to group mode buffer.
        (if (eq mode 'gnus-summary-mode)
@@ -4427,9 +4556,18 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
        (if (not (buffer-name (car quit-config)))
            (gnus-configure-windows 'group 'force)
          (set-buffer (car quit-config))
-         (and (eq major-mode 'gnus-summary-mode)
-              (gnus-set-global-variables))
-         (gnus-configure-windows (cdr quit-config))))
+         (cond ((eq major-mode 'gnus-summary-mode)
+                (gnus-set-global-variables))
+               ((eq major-mode 'gnus-article-mode)
+                (save-excursion
+                  ;; The `gnus-summary-buffer' variable may point
+                  ;; to the old summary buffer when using a single
+                  ;; article buffer.
+                  (unless (gnus-buffer-live-p gnus-summary-buffer)
+                    (set-buffer gnus-group-buffer))
+                  (set-buffer gnus-summary-buffer)
+                  (gnus-set-global-variables))))
+         (gnus-configure-windows (cdr quit-config) 'force)))
       (unless quit-config
        (setq gnus-newsgroup-name nil)))))
 
@@ -4621,7 +4759,8 @@ previous group instead."
            (gnus-message 5 "Returning to the group buffer")
            (setq entered t)
            (set-buffer current-buffer)
-           (gnus-summary-exit))
+           (gnus-summary-exit)
+           (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)))
@@ -4712,6 +4851,7 @@ If optional argument UNREAD is non-nil, only unread article is selected."
 (defun gnus-summary-goto-subject (article &optional force silent)
   "Go the subject line of ARTICLE.
 If FORCE, also allow jumping to articles not currently shown."
+  (interactive "nArticle number: ")
   (let ((b (point))
        (data (gnus-data-find article)))
     ;; We read in the article if we have to.
@@ -5370,7 +5510,7 @@ fetch-old-headers verbiage, and so on."
               (not (eq gnus-build-sparse-threads 'more))
               (null gnus-thread-expunge-below)
               (not gnus-use-nocem)))
-      () ; Do nothing.
+      ()                               ; Do nothing.
     (push gnus-newsgroup-limit gnus-newsgroup-limits)
     (setq gnus-newsgroup-limit nil)
     (mapatoms
@@ -5576,40 +5716,51 @@ If FORCE, force a digest interpretation.  If not, try
 to guess what the document format is."
   (interactive "P")
   (gnus-set-global-variables)
-  (gnus-summary-select-article)
-  (let* ((name (format "%s-%d"
-                      (gnus-group-prefixed-name
-                       gnus-newsgroup-name (list 'nndoc ""))
-                      gnus-current-article))
-        (ogroup gnus-newsgroup-name)
-        (params (append (gnus-info-params (gnus-get-info ogroup))
-                        (list (cons 'to-group ogroup))))
-        (case-fold-search t)
-        (buf (current-buffer))
-        dig)
+  (let ((conf gnus-current-window-configuration))
     (save-excursion
-      (setq dig (nnheader-set-temp-buffer " *gnus digest buffer*"))
-      (insert-buffer-substring gnus-original-article-buffer)
-      (narrow-to-region
-       (goto-char (point-min))
-       (or (search-forward "\n\n" nil t) (point)))
-      (goto-char (point-min))
-      (delete-matching-lines "^\\(Path\\):\\|^From ")
-      (widen))
-    (unwind-protect
-       (if (gnus-group-read-ephemeral-group
-            name `(nndoc ,name (nndoc-address
-                                ,(get-buffer dig))
-                         (nndoc-article-type ,(if force 'digest 'guess))) t)
-           ;; Make all postings to this group go to the parent group.
-           (nconc (gnus-info-params (gnus-get-info name))
-                  params)
-         ;; Couldn't select this doc group.
-         (switch-to-buffer buf)
-         (gnus-set-global-variables)
-         (gnus-configure-windows 'summary)
-         (gnus-message 3 "Article couldn't be entered?"))
-      (kill-buffer dig))))
+      (gnus-summary-select-article))
+    (setq gnus-current-window-configuration conf)
+    (let* ((name (format "%s-%d"
+                        (gnus-group-prefixed-name
+                         gnus-newsgroup-name (list 'nndoc ""))
+                        (save-excursion
+                          (set-buffer gnus-summary-buffer)
+                          gnus-current-article)))
+          (ogroup gnus-newsgroup-name)
+          (params (append (gnus-info-params (gnus-get-info ogroup))
+                          (list (cons 'to-group ogroup))))
+          (case-fold-search t)
+          (buf (current-buffer))
+          dig)
+      (save-excursion
+       (setq dig (nnheader-set-temp-buffer " *gnus digest buffer*"))
+       (insert-buffer-substring gnus-original-article-buffer)
+       ;; Remove lines that may lead nndoc to misinterpret the
+       ;; document type.
+       (narrow-to-region
+        (goto-char (point-min))
+        (or (search-forward "\n\n" nil t) (point)))
+       (goto-char (point-min))
+       (delete-matching-lines "^\\(Path\\):\\|^From ")
+       (widen))
+      (unwind-protect
+         (let ((gnus-current-window-configuration
+                (if (and (boundp 'gnus-pick-mode)
+                         (symbol-value (intern "gnus-pick-mode")))
+                    'pick 'summary)))
+           (if (gnus-group-read-ephemeral-group
+                name `(nndoc ,name (nndoc-address ,(get-buffer dig))
+                             (nndoc-article-type 
+                              ,(if force 'digest 'guess))) t)
+               ;; Make all postings to this group go to the parent group.
+               (nconc (gnus-info-params (gnus-get-info name))
+                      params)
+             ;; Couldn't select this doc group.
+             (switch-to-buffer buf)
+             (gnus-set-global-variables)
+             (gnus-configure-windows 'summary)
+             (gnus-message 3 "Article couldn't be entered?")))
+       (kill-buffer dig)))))
 
 (defun gnus-summary-read-document (n)
   "Open a new group based on the current article(s).
@@ -5621,7 +5772,7 @@ Obeys the standard process/prefix convention."
                         (list (cons 'to-group ogroup))))
         article group egroup groups vgroup)
     (while (setq article (pop articles))
-      (setq group (format "%s-%d" gnus-newsgroup-name gnus-current-article))
+      (setq group (format "%s-%d" gnus-newsgroup-name article))
       (gnus-summary-remove-process-mark article)
       (when (gnus-summary-display-article article)
        (save-excursion
@@ -5651,7 +5802,7 @@ Obeys the standard process/prefix convention."
       (error "None of the articles could be interpreted as documents"))
      ((gnus-group-read-ephemeral-group
        (setq vgroup (format
-                    "%s-%s" gnus-newsgroup-name
+                    "nnvirtual:%s-%s" gnus-newsgroup-name
                     (format-time-string "%Y%m%dT%H%M%S" (current-time))))
        `(nnvirtual ,vgroup (nnvirtual-component-groups ,groups))
        t
@@ -5707,9 +5858,6 @@ Optional argument BACKWARD means do search for backward.
        (gnus-article-display-hook nil)
        (gnus-mark-article-hook nil)    ;Inhibit marking as read.
        (gnus-use-article-prefetch nil)
-       (re-search
-        (if backward
-            're-search-backward 're-search-forward))
        (sum (current-buffer))
        (found nil)
        point)
@@ -5849,7 +5997,7 @@ article massaging functions being run."
          gnus-visual)
       (gnus-summary-select-article nil 'force)))
   (gnus-summary-goto-subject gnus-current-article)
-;  (gnus-configure-windows 'article)
+                                       ;  (gnus-configure-windows 'article)
   (gnus-summary-position-point))
 
 (defun gnus-summary-verbose-headers (&optional arg)
@@ -5997,7 +6145,7 @@ and `request-accept' functions."
        ((eq action 'move)
         (gnus-request-move-article
          article                       ; Article to move
-         gnus-newsgroup-name           ; From newsgrouo
+         gnus-newsgroup-name           ; From newsgroup
          (nth 1 (gnus-find-method-for-group
                  gnus-newsgroup-name)) ; Server
          (list 'gnus-request-accept-article
@@ -6335,7 +6483,7 @@ groups."
 
 (defalias 'gnus-summary-edit-article-postpone 'gnus-article-edit-exit)
 
-(defun gnus-summary-edit-article-done (references read-only buffer)
+(defun gnus-summary-edit-article-done (&optional references read-only buffer)
   "Make edits to the current article permanent."
   (interactive)
   ;; Replace the article.
@@ -6345,9 +6493,10 @@ groups."
                 (current-buffer))))
       (error "Couldn't replace article.")
     ;; Update the summary buffer.
-    (if (equal (message-tokenize-header references " ")
-              (message-tokenize-header
-               (or (message-fetch-field "references") "") " "))
+    (if (and references
+            (equal (message-tokenize-header references " ")
+                   (message-tokenize-header
+                    (or (message-fetch-field "references") "") " ")))
        ;; We only have to update this line.
        (save-excursion
          (save-restriction
@@ -6358,7 +6507,7 @@ groups."
              (gnus-summary-update-article-line
               (cdr gnus-article-current) header))))
       ;; Update threads.
-      (set-buffer buffer)
+      (set-buffer (or buffer gnus-summary-buffer))
       (gnus-summary-update-article (cdr gnus-article-current)))
     ;; Prettify the article buffer again.
     (save-excursion
@@ -6393,8 +6542,8 @@ groups."
       (goto-char (point-min))
       (search-forward "\n\n")
       (narrow-to-region (point-min) (point))
-      (pp-eval-expression
-       (list 'quote (mapcar 'car (nnmail-article-group 'identity)))))))
+      (message "This message would go to %s"
+              (mapconcat 'car (nnmail-article-group 'identity) ", ")))))
 
 ;; Summary marking commands.
 
@@ -6750,7 +6899,8 @@ marked."
   (let ((forward (cdr (assq type gnus-summary-mark-positions)))
         (buffer-read-only nil))
     (re-search-backward "[\n\r]" (gnus-point-at-bol) 'move-to-limit)
-    (and (looking-at "\r") (setq forward (1+ forward)))
+    (when (looking-at "\r") 
+      (incf forward))
     (when (and forward
                (<= (+ forward (point)) (point-max)))
       ;; Go to the right position on the line.
@@ -7126,7 +7276,7 @@ is non-nil or the Subject: of both articles are the same."
   (save-window-excursion
     (let ((gnus-article-buffer " *reparent*")
          (current-article (gnus-summary-article-number))
-         ; first grab the marked article, otherwise one line up.
+                                       ; first grab the marked article, otherwise one line up.
          (parent-article (if (not (null gnus-newsgroup-processable))
                              (car gnus-newsgroup-processable)
                            (save-excursion
@@ -7255,34 +7405,6 @@ Return the article number moved to, or nil if moving was impossible."
          (gnus-summary-article-number)
        (goto-char beg)))))
 
-(defun gnus-summary-go-to-next-thread-old (&optional previous)
-  "Go to the same level (or less) next thread.
-If PREVIOUS is non-nil, go to previous thread instead.
-Return the article number moved to, or nil if moving was impossible."
-  (if (and (eq gnus-summary-make-false-root 'dummy)
-          (gnus-summary-article-intangible-p))
-      (let ((beg (point)))
-       (while (and (zerop (forward-line 1))
-                   (not (gnus-summary-article-intangible-p))
-                   (not (zerop (save-excursion 
-                                 (gnus-summary-thread-level))))))
-       (if (eobp)
-           (progn
-             (goto-char beg)
-             nil)
-         (point)))
-    (let* ((level (gnus-summary-thread-level))
-          (article (gnus-summary-article-number))
-          (data (cdr (gnus-data-find-list article (gnus-data-list previous))))
-          oart)
-      (while data
-       (if (<= (gnus-data-level (car data)) level)
-           (setq oart (gnus-data-number (car data))
-                 data nil)
-         (setq data (cdr data))))
-      (and oart
-          (gnus-summary-goto-subject oart)))))
-
 (defun gnus-summary-next-thread (n &optional silent)
   "Go to the same level next N'th thread.
 If N is negative, search backward instead.
@@ -7293,8 +7415,7 @@ If SILENT, don't output messages."
   (interactive "p")
   (gnus-set-global-variables)
   (let ((backward (< n 0))
-       (n (abs n))
-       old dum int)
+       (n (abs n)))
     (while (and (> n 0)
                (gnus-summary-go-to-next-thread backward))
       (decf n))
@@ -7405,7 +7526,7 @@ Argument REVERSE means reverse order."
   (gnus-summary-sort 'author reverse))
 
 (defun gnus-summary-sort-by-subject (&optional reverse)
-  "Sort summary buffer by subject alphabetically. `Re:'s are ignored.
+  "Sort summary buffer by subject alphabetically.  `Re:'s are ignored.
 If case-fold-search is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
   (interactive "P")
@@ -7682,7 +7803,7 @@ save those articles instead."
          (forward-line 1)
          (setq b (point))
          (insert "    " (file-name-nondirectory
-                               (cdr (assq 'name (car pslist))))
+                         (cdr (assq 'name (car pslist))))
                  ": " (or (cdr (assq 'execute (car pslist))) "") "\n")
          (setq e (point))
          (forward-line -1)             ; back to `b'
@@ -7778,9 +7899,6 @@ save those articles instead."
                  (t gnus-reffed-article-number))
                 (current-buffer))
          (insert " Article retrieved.\n"))
-       ;(when (and header
-       ;          (memq (mail-header-number header) gnus-newsgroup-sparse))
-       ;  (setcar (gnus-id-to-thread id) nil))
        (if (not (setq header (car (gnus-get-newsgroup-headers))))
            ()                          ; Malformed head.
          (unless (memq (mail-header-number header) gnus-newsgroup-sparse)
@@ -7875,6 +7993,49 @@ save those articles instead."
          (funcall gnus-summary-highlight-line-function article face))))
     (goto-char p)))
 
+(defun gnus-update-read-articles (group unread)
+  "Update the list of read articles in GROUP."
+  (let* ((active (or gnus-newsgroup-active (gnus-active group)))
+        (entry (gnus-gethash group gnus-newsrc-hashtb))
+        (info (nth 2 entry))
+        (prev 1)
+        (unread (sort (copy-sequence unread) '<))
+        read)
+    (if (or (not info) (not active))
+       ;; There is no info on this group if it was, in fact,
+       ;; killed.  Gnus stores no information on killed groups, so
+       ;; there's nothing to be done.
+       ;; One could store the information somewhere temporarily,
+       ;; perhaps...  Hmmm...
+       ()
+      ;; Remove any negative articles numbers.
+      (while (and unread (< (car unread) 0))
+       (setq unread (cdr unread)))
+      ;; Remove any expired article numbers
+      (while (and unread (< (car unread) (car active)))
+       (setq unread (cdr unread)))
+      ;; Compute the ranges of read articles by looking at the list of
+      ;; unread articles.
+      (while unread
+       (if (/= (car unread) prev)
+           (setq read (cons (if (= prev (1- (car unread))) prev
+                              (cons prev (1- (car unread)))) read)))
+       (setq prev (1+ (car unread)))
+       (setq unread (cdr unread)))
+      (when (<= prev (cdr active))
+       (setq read (cons (cons prev (cdr active)) read)))
+      (gnus-undo-register
+       `(progn
+          (gnus-info-set-marks ,info ,(gnus-info-marks info))
+          (gnus-info-set-read ,info ,(gnus-info-read info))
+          (gnus-get-unread-articles-in-group ,info (gnus-active ,group))))
+      ;; Enter this list into the group info.
+      (gnus-info-set-read
+       info (if (> (length read) 1) (nreverse read) read))
+      ;; Set the number of unread articles in gnus-newsrc-hashtb.
+      (gnus-get-unread-articles-in-group info (gnus-active group))
+      t)))
+
 (provide 'gnus-sum)
 
 ;;; gnus-sum.el ends here