diff --exclude=*.elc --exclude=*~ --exclude=*-[0-9] --exclude=gnus --exclude=readme --context --recursive pub/dgnus/lisp/ChangeLog dgnus/lisp/ChangeLog
*** pub/dgnus/lisp/ChangeLog	Sat Apr 22 09:13:23 1995
--- dgnus/lisp/ChangeLog	Mon Apr 24 18:20:02 1995
***************
*** 1,10 ****
  Sat Apr 22 07:27:25 1995  Lars Magne Ingebrigtsen  <larsi@gymir.ifi.uio.no>
  
  	* gnus.el: Pushed all score code out to a separate file.
! 
  	* gnus-score.el: New file.
  
  	* gnus.el (gnus-newsrc-alist): Name change from gnus-newsrc-assoc.
  
  Sat Apr 22 04:54:11 1995  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
  
--- 1,77 ----
+ Mon Apr 24 17:38:36 1995  Lars Magne Ingebrigtsen  <larsi@bera.ifi.uio.no>
+ 
+ 	* nntp.el (nntp-kill-connection): Add a small wait after timing
+ 	out. 
+ 
+ 	* gnus.el (gnus-format-max-width): Didn't work with numbers.
+ 	(gnus-group-first-unread-group): Wouldn't select the first group.
+ 
+ 	* nntp.el (nntp-default-sentinel): Would fail to find the name of
+ 	the server.
+ 
+ 	* gnus.el (gnus-group-unsubscribe-current-group): Did not toggle
+ 	properly. 
+ 	(gnus-group-set-current-level): Warn about illegal levels.
+ 
+ Mon Apr 24 17:22:27 1995  Lars Magne Ingebrigtsen  <larsi@hymir.ifi.uio.no>
+ 
+ 	* gnus.el (gnus-summary-recenter): New version from Sudish.
+ 
+ Mon Apr 24 00:05:59 1995  Christian Limpach  <chris@nice.ch>
+ 
+ 	* gnus.el (gnus-article-display-x-face): avoid
+ 	re-search-forwarding the whole article buffer
+ 
+ Mon Apr 24 16:46:06 1995  Lars Magne Ingebrigtsen  <larsi@hymir.ifi.uio.no>
+ 
+ 	* gnus.el (gnus-seconds-since-epoch): New function.
+ 
+ 	* nntp.el (nntp-open-server): Set wrong variable for the port
+ 	number. 
+ 
+ 	* gnus.el (gnus-summary-refer-article): Don't bug out on nil
+ 	refer-article-methods. 
+ 
+ Mon Apr 24 16:05:56 1995  Lars Magne Ingebrigtsen  <larsi@bera.ifi.uio.no>
+ 
+ 	* gnus.el (gnus-article-x-face-command): New value.
+ 
+ Sun Apr 23 11:19:32 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+ 
+ 	* nnspool.el (nnspool-request-post): Post asynchronously.
+ 
+ 	* nntp.el: Many changes related to asynchronous article fetching. 
+ 
+ 	* gnus.el (gnus-asynchronous): New variable.
+ 	(gnus-article-date-ut, gnus-article-date-local,
+ 	gnus-article-date-lapsed):  New commands and keystrokes.
+ 
+ Sun Apr 23 05:34:11 1995  Lars Magne Ingebrigtsen  <larsi@gymir.ifi.uio.no>
+ 
+ 	* gnus-score.el (gnus-score-adaptive-alist): New variable.
+ 	(gnus-score-adaptive): New function.
+ 
+ 	* gnus.el (gnus-article-de-quoted-unreadable): Translate = on the
+ 	end of lines.
+ 	(gnus-del-mark): Name change from gnus-dread-mark.
+ 	(gnus-use-adaptive-scoring): New variable.
+ 	(gnus-summary-exit): Use it.
+ 
+ 	* gnus-message.el (gnus-post-news): Don't bug out on posting with
+ 	followup-to methods.
+ 
+ 	* gnus.el (gnus-group-set-current-level): Bug fix.
+ 	(gnus-request-post-buffer): Open server if it isn't open.
+ 
  Sat Apr 22 07:27:25 1995  Lars Magne Ingebrigtsen  <larsi@gymir.ifi.uio.no>
  
  	* gnus.el: Pushed all score code out to a separate file.
! 	
  	* gnus-score.el: New file.
  
  	* gnus.el (gnus-newsrc-alist): Name change from gnus-newsrc-assoc.
+ 
+ 	* gnus.el: 0.57 is released.
  
  Sat Apr 22 04:54:11 1995  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
  
diff --exclude=*.elc --exclude=*~ --exclude=*-[0-9] --exclude=gnus --exclude=readme --context --recursive pub/dgnus/lisp/gnus-message.el dgnus/lisp/gnus-message.el
*** pub/dgnus/lisp/gnus-message.el	Sat Apr 22 09:13:14 1995
--- dgnus/lisp/gnus-message.el	Sun Apr 23 07:31:49 1995
***************
*** 226,232 ****
  					       gnus-newsgroup-name
  					       gnus-newsrc-hashtb)))))
  		     (if (and (boundp 'gnus-followup-to-function)
! 			      gnus-followup-to-function)
  			 (setq follow-to
  			       (save-excursion
  				 (set-buffer article-buffer)
--- 226,233 ----
  					       gnus-newsgroup-name
  					       gnus-newsrc-hashtb)))))
  		     (if (and (boundp 'gnus-followup-to-function)
! 			      gnus-followup-to-function
! 			      article-buffer)
  			 (setq follow-to
  			       (save-excursion
  				 (set-buffer article-buffer)
diff --exclude=*.elc --exclude=*~ --exclude=*-[0-9] --exclude=gnus --exclude=readme --context --recursive pub/dgnus/lisp/gnus-score.el dgnus/lisp/gnus-score.el
*** pub/dgnus/lisp/gnus-score.el	Sat Apr 22 09:13:14 1995
--- dgnus/lisp/gnus-score.el	Sun Apr 23 13:51:33 1995
***************
*** 1,8 ****
  ;;; gnus-score --- scoring code for Gnus
  ;; Copyright (C) 1995 Free Software Foundation, Inc.
  
! ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
! ;;	Per Abrahamsen <amanda@iesd.auc.dk>
  ;; Keywords: news
  
  ;; This file is part of GNU Emacs.
--- 1,8 ----
  ;;; gnus-score --- scoring code for Gnus
  ;; Copyright (C) 1995 Free Software Foundation, Inc.
  
! ;; Author: Per Abrahamsen <amanda@iesd.auc.dk>
! ;;	Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
  ;; Keywords: news
  
  ;; This file is part of GNU Emacs.
***************
*** 36,41 ****
--- 36,53 ----
  (defvar gnus-orphan-score nil
    "*All orphans get this score added. Set in the score file.")
  
+ (defvar gnus-adaptive-score-alist
+   '((gnus-unread-mark)
+     (gnus-ticked-mark (from 4))
+     (gnus-dormant-mark (from 5))
+     (gnus-del-mark (from -4) (subject -1))
+     (gnus-read-mark (from 4) (subject 2))
+     (gnus-expirable-mark (from -1) (subject -1))
+     (gnus-killed-mark (from -1) (subject -3))
+     (gnus-kill-file-mark)
+     (gnus-catchup-mark (from -1) (subject -1)))
+   "*Alist of marks and scores.")
+ 
  
  
  ;; Internal variables.
***************
*** 239,245 ****
  	      (nth 1 (assoc header gnus-header-index)))
        (error "No article on current line"))))
  
! (defun gnus-summary-score-entry (header match type score date &optional prompt)
    "Enter score file entry.
  HEADER is the header being scored.
  MATCH is the string we are looking for.
--- 251,258 ----
  	      (nth 1 (assoc header gnus-header-index)))
        (error "No article on current line"))))
  
! (defun gnus-summary-score-entry 
!   (header match type score date &optional prompt silent)
    "Enter score file entry.
  HEADER is the header being scored.
  MATCH is the string we are looking for.
***************
*** 266,271 ****
--- 279,285 ----
  				     (if (< score 0) "lower" "raise"))
  			     match)))
      (and (>= (nth 1 (assoc header gnus-header-index)) 0)
+ 	 (not silent)
  	 (gnus-summary-score-effect header match type score))
      (and (= score gnus-score-interactive-default-score)
  	 (setq score nil))
***************
*** 277,286 ****
  		  (list match score))
  		 (t
  		  (list match))))
! 	  (old (gnus-score-get header)))
!       (gnus-score-set
!        header
!        (if old (cons new old) (list new))))
      (gnus-score-set 'touched '(t))))
  
  (defun gnus-summary-score-effect (header match type score)
--- 291,310 ----
  		  (list match score))
  		 (t
  		  (list match))))
! 	  (old (gnus-score-get header))
! 	  elem)
!       ;; We see whether we can collapse some score entries.
!       ;; This isn't quite correct, because there may be more elements
!       ;; later on with the same key that have matching elems... Hm.
!       (if (and old
! 	       (setq elem (assoc match old))
! 	       (eq (nth 3 elem) (nth 3 new))
! 	       (or (and (numberp (nth 2 elem)) (numberp (nth 2 new)))
! 		   (and (not (nth 2 elem)) (not (nth 2 new)))))
! 	  ;; Yup, we just add this new score to the old elem.
! 	  (setcar (cdr elem) (+ (nth 1 elem) (nth 1 new)))
! 	;; Nope, we have to add a new elem.
! 	(gnus-score-set header (if old (cons new old) (list new)))))
      (gnus-score-set 'touched '(t))))
  
  (defun gnus-summary-score-effect (header match type score)
***************
*** 1219,1224 ****
--- 1243,1285 ----
      (if score-file 
  	(gnus-short-group-name (file-name-nondirectory score-file))
        "none")))
+ 
+ (defun gnus-score-adaptive ()
+   (save-excursion
+     (let* ((malist (gnus-copy-sequence gnus-adaptive-score-alist))
+ 	   (alist malist)
+ 	   (date (current-time-string)) 
+ 	   elem headers)
+       ;; First we transform the adaptive rule alist into something
+       ;; that's faster to process.
+       (while malist
+ 	(setq elem (car malist))
+ 	(if (symbolp (car elem))
+ 	    (setcar elem (symbol-value (car elem))))
+ 	(setq elem (cdr elem))
+ 	(while elem
+ 	  (setcdr (car elem) 
+ 		  (cons (symbol-name (car (car elem))) (cdr (car elem))))
+ 	  (setcar (car elem) 
+ 		  (intern 
+ 		   (concat "gnus-header-" 
+ 			   (downcase (symbol-name (car (car elem)))))))
+ 	  (setq elem (cdr elem)))
+ 	(setq malist (cdr malist)))
+       ;; The we score away.
+       (goto-char (point-min))
+       (while (not (eobp))
+ 	(setq elem (cdr (assq (gnus-summary-article-mark) alist)))
+ 	(if (not elem)
+ 	    ()
+ 	  (setq headers (gnus-get-header-by-number 
+ 			 (gnus-summary-article-number)))
+ 	  (while elem
+ 	    (gnus-summary-score-entry 
+ 	     (nth 1 (car elem)) (funcall (car (car elem)) headers)
+ 	     's (nth 2 (car elem)) date nil t)
+ 	    (setq elem (cdr elem))))
+ 	(forward-line 1)))))
  
  ;;;
  ;;; Score mode.
diff --exclude=*.elc --exclude=*~ --exclude=*-[0-9] --exclude=gnus --exclude=readme --context --recursive pub/dgnus/lisp/gnus-visual.el dgnus/lisp/gnus-visual.el
*** pub/dgnus/lisp/gnus-visual.el	Sat Apr 22 09:13:16 1995
--- dgnus/lisp/gnus-visual.el	Sun Apr 23 13:23:22 1995
***************
*** 211,216 ****
--- 211,220 ----
     ""
     '("Article"
       ("Hide"
+       ("Date"
+        ["Local" gnus-article-date-local t]
+        ["UT" gnus-article-date-local t]
+        ["Lapsed" gnus-article-date-local t])
        ["Headers" gnus-article-hide-headers t]
        ["Signature" gnus-article-hide-signature t]
        ["Citation" gnus-article-hide-citation t]
diff --exclude=*.elc --exclude=*~ --exclude=*-[0-9] --exclude=gnus --exclude=readme --context --recursive pub/dgnus/lisp/gnus.el dgnus/lisp/gnus.el
*** pub/dgnus/lisp/gnus.el	Sat Apr 22 09:13:17 1995
--- dgnus/lisp/gnus.el	Mon Apr 24 18:17:34 1995
***************
*** 249,254 ****
--- 249,260 ----
  with the header name, and the cdr should be a string with the header
  value.")
  
+ (defvar gnus-asynchronous nil
+   "*If non-nil, Gnus will supply backends with data needed for async article fetching.")
+ 
+ (defvar gnus-asynchronous-article-function nil
+   "*Function for picking articles to pre-fetch, possibly.")
+ 
  (defvar gnus-large-newsgroup 200
    "*The number of articles which indicates a large newsgroup.
  If the number of articles in a newsgroup is greater than this value,
***************
*** 347,352 ****
--- 353,361 ----
  (defvar gnus-score-file-suffix "SCORE"
    "*Suffix of the score files.")
  
+ (defvar gnus-use-adaptive-scoring nil
+   "*If non-nil, use some adaptive scoring scheme.")
+ 
  (defvar gnus-fetch-old-headers nil
    "*Non-nil means that Gnus will try to build threads by grabbing old headers.
  If an unread article in the group refers to an older, already read (or
***************
*** 693,700 ****
  
  ;; Added by Ethan Bradford <ethanb@ptolemy.astro.washington.edu>.
  (defvar gnus-mail-courtesy-message
!   "*The following message is a courtesy copy of an article\nthat has been posted as well.\n\n"
!   "This is inserted at the start of a mailed copy of a posted message.
  If this variable is nil, no such courtesy message will be added.")
  
  (defvar gnus-break-pages t
--- 702,709 ----
  
  ;; Added by Ethan Bradford <ethanb@ptolemy.astro.washington.edu>.
  (defvar gnus-mail-courtesy-message
!   "The following message is a courtesy copy of an article\nthat has been posted as well.\n\n"
!   "*This is inserted at the start of a mailed copy of a posted message.
  If this variable is nil, no such courtesy message will be added.")
  
  (defvar gnus-break-pages t
***************
*** 793,800 ****
    "*Mark used for ticked articles.")
  (defvar gnus-dormant-mark ??
    "*Mark used for dormant articles.")
! (defvar gnus-dread-mark ?D
!   "*Mark used for read articles.")
  (defvar gnus-read-mark ?d
    "*Mark used for read articles.")
  (defvar gnus-expirable-mark ?E
--- 802,809 ----
    "*Mark used for ticked articles.")
  (defvar gnus-dormant-mark ??
    "*Mark used for dormant articles.")
! (defvar gnus-del-mark ?D
!   "*Mark used for del'd articles.")
  (defvar gnus-read-mark ?d
    "*Mark used for read articles.")
  (defvar gnus-expirable-mark ?E
***************
*** 1108,1114 ****
  (add-hook 'gnus-article-display-hook 'gnus-article-hide-headers-if-wanted)
  (add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
  
! (defconst gnus-article-x-face-command "uncompface | ikon2xbm | xv -"
    "String or function to be executed to display an X-Face header.
  If it is a string, the command will be executed in a sub-shell
  asynchronously. The compressed face will be piped to this command.") 
--- 1117,1124 ----
  (add-hook 'gnus-article-display-hook 'gnus-article-hide-headers-if-wanted)
  (add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
  
! (defvar gnus-article-x-face-command
!   "{ echo '/* WidthH, HeightH */'; uncompface; } | icontopbm | xv -"
    "String or function to be executed to display an X-Face header.
  If it is a string, the command will be executed in a sub-shell
  asynchronously. The compressed face will be piped to this command.") 
***************
*** 1222,1227 ****
--- 1232,1239 ----
  (defvar gnus-current-move-group nil)
  
  (defvar gnus-newsgroup-dependencies nil)
+ (defvar gnus-newsgroup-threads nil)
+ (defvar gnus-newsgroup-async nil)
  (defconst gnus-group-edit-buffer "*Gnus edit newsgroup*")
  
  (defconst gnus-group-line-format-alist
***************
*** 1291,1297 ****
  	(list ?S 'subject ?s)
  	(list ?e 'unselected ?d)
  	(list ?u 'user-defined ?s)
! 	(list ?s '(gnus-current-score-file-nondirectory)?s)))
  
  (defconst gnus-group-mode-line-format-alist 
    (list (list ?S 'news-server ?s)
--- 1303,1309 ----
  	(list ?S 'subject ?s)
  	(list ?e 'unselected ?d)
  	(list ?u 'user-defined ?s)
! 	(list ?s '(gnus-current-score-file-nondirectory) ?s)))
  
  (defconst gnus-group-mode-line-format-alist 
    (list (list ?S 'news-server ?s)
***************
*** 1303,1309 ****
  (defconst gnus-maintainer "Lars Magne Ingebrigtsen <larsi@ifi.uio.no>"
    "The mail address of the Gnus maintainer.")
  
! (defconst gnus-version "(ding) Gnus v0.57"
    "Version number for this version of Gnus.")
  
  (defvar gnus-info-nodes
--- 1315,1321 ----
  (defconst gnus-maintainer "Lars Magne Ingebrigtsen <larsi@ifi.uio.no>"
    "The mail address of the Gnus maintainer.")
  
! (defconst gnus-version "(ding) Gnus v0.58"
    "Version number for this version of Gnus.")
  
  (defvar gnus-info-nodes
***************
*** 1484,1489 ****
--- 1496,1502 ----
      gnus-last-article gnus-article-internal-prepare-hook
      gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
      gnus-newsgroup-scored gnus-newsgroup-kill-headers
+     gnus-newsgroup-threads gnus-newsgroup-async
      gnus-score-alist gnus-current-score-file gnus-summary-expunge-below 
      gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files
      gnus-newsgroup-history gnus-newsgroup-ancient)
***************
*** 1561,1566 ****
--- 1574,1581 ----
    (autoload 'gnus-summary-score-map "gnus-score" nil nil 'keymap)
    (autoload 'gnus-score-save "gnus-score")
    (autoload 'gnus-score-headers "gnus-score")
+   (autoload 'gnus-current-score-file-nondirectory "gnus-score")
+   (autoload 'gnus-score-adaptive "gnus-score")
  
    (autoload 'gnus-group-post-news "gnus-message")
    (autoload 'gnus-summary-post-news "gnus-message")
***************
*** 1578,1583 ****
--- 1593,1602 ----
    (autoload 'gnus-summary-mail-forward "gnus-message")
    (autoload 'gnus-summary-mail-other-window "gnus-message")
    (autoload 'gnus-mail-reply-using-mail "gnus-message")
+   (autoload 'gnus-mail-yank-original "gnus-message")
+   (autoload 'gnus-mail-send-and-exit "gnus-message")
+   (autoload 'gnus-mail-forward-using-mail "gnus-message")
+   (autoload 'gnus-mail-other-window-using-mail "gnus-message")
  
    )
  
***************
*** 1765,1772 ****
        (setq gnus-summary-mark-positions pos))))
  
  (defun gnus-format-max-width (var length)
!   (let (result)
!     (if (> (length (setq result (eval var))) length)
  	(format "%s" (substring result 0 length))
        (format "%s" result))))
  
--- 1784,1793 ----
        (setq gnus-summary-mark-positions pos))))
  
  (defun gnus-format-max-width (var length)
!   (let (result
!         (val (eval var)))
!     (if (> (length (setq result (if (numberp val) (int-to-string val) val))) 
! 	   length)
  	(format "%s" (substring result 0 length))
        (format "%s" result))))
  
***************
*** 2359,2371 ****
    (interactive)
    (pop-to-buffer "*Gnus Bug*")
    (erase-buffer)
    (mail-setup gnus-maintainer "[Gnus Bug Report] " nil nil nil nil)
    (goto-char (point-min))
    (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
    (forward-line 1)
    (insert (format "%s\n%s\n\n" (gnus-version) (emacs-version)))
    (gnus-debug)
-   (mail-mode)
    (message ""))
  
  (defun gnus-debug ()
--- 2380,2392 ----
    (interactive)
    (pop-to-buffer "*Gnus Bug*")
    (erase-buffer)
+   (mail-mode)
    (mail-setup gnus-maintainer "[Gnus Bug Report] " nil nil nil nil)
    (goto-char (point-min))
    (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
    (forward-line 1)
    (insert (format "%s\n%s\n\n" (gnus-version) (emacs-version)))
    (gnus-debug)
    (message ""))
  
  (defun gnus-debug ()
***************
*** 2447,2452 ****
--- 2468,2490 ----
      (timezone-absolute-from-gregorian 
       (nth 1 dat) (nth 2 dat) (car dat))))
  
+ (defun gnus-seconds-since-epoch (date)
+   (let* ((tdate (mapcar (lambda (ti) (and ti (string-to-int ti)))
+ 			(timezone-parse-date date)))
+ 	 (ttime (mapcar (lambda (ti) (and ti (string-to-int ti)))
+ 			(timezone-parse-time
+ 			 (aref (timezone-parse-date date) 3))))
+ 	 (edate (mapcar (lambda (ti) (and ti (string-to-int ti)))
+ 			(timezone-parse-date "Jan 1 12:00:00 1970")))
+ 	 (tday (- (timezone-absolute-from-gregorian 
+ 		   (nth 1 tdate) (nth 2 tdate) (nth 0 tdate))
+ 		  (timezone-absolute-from-gregorian 
+ 		   (nth 1 edate) (nth 2 edate) (nth 0 edate)))))
+     (+ (nth 2 ttime)
+        (* (nth 1 ttime) 60)
+        (* 1.0 (nth 0 ttime) 60 60)
+        (* 1.0 tday 60 60 24))))
+ 
  (defun gnus-file-newer-than (file date)
    (let ((fdate (nth 5 (file-attributes file))))
      (or (> (car fdate) (car date))
***************
*** 3503,3509 ****
    "Go to the first group with unread articles."
    (interactive)
    (goto-char (point-min))
!   (gnus-group-next-unread-group 1))
  
  (defun gnus-group-enter-server-mode ()
    "Jump to the server buffer."
--- 3541,3549 ----
    "Go to the first group with unread articles."
    (interactive)
    (goto-char (point-min))
!   (or (get-text-property (point) 'gnus-unread)
!       (gnus-group-next-unread-group 1))
!   (gnus-group-position-cursor))
  
  (defun gnus-group-enter-server-mode ()
    "Jump to the server buffer."
***************
*** 3782,3790 ****
  
  (defun gnus-group-set-current-level (n level)
    "Set the level of the next N groups to LEVEL."
!   (interactive "P\nnLevel: ")
    (let (group)
!     (while (and (< n 0)
  		(setq group (gnus-group-group-name)))
        (and (setq group (gnus-group-group-name))
  	   (message "Changed level of %s from %d to %d" 
--- 3822,3832 ----
  
  (defun gnus-group-set-current-level (n level)
    "Set the level of the next N groups to LEVEL."
!   (interactive "p\nnLevel: ")
!   (or (and (>= level 1) (<= level gnus-level-killed))
!       (error "Illegal level: %d" level))
    (let (group)
!     (while (and (> n 0)
  		(setq group (gnus-group-group-name)))
        (and (setq group (gnus-group-group-name))
  	   (message "Changed level of %s from %d to %d" 
***************
*** 3803,3810 ****
    (let ((group (gnus-group-group-name)))
      (or group (error "No newsgroup on current line"))
      (or arg (setq arg (if (<= (gnus-group-group-level) gnus-level-subscribed)
! 			  (1+ gnus-level-subscribed) 
! 			gnus-level-default-unsubscribed)))
      (gnus-group-unsubscribe-group group arg)
      (gnus-group-next-group 1)))
  
--- 3845,3852 ----
    (let ((group (gnus-group-group-name)))
      (or group (error "No newsgroup on current line"))
      (or arg (setq arg (if (<= (gnus-group-group-level) gnus-level-subscribed)
! 			  gnus-level-default-unsubscribed
! 			gnus-level-default-subscribed)))
      (gnus-group-unsubscribe-group group arg)
      (gnus-group-next-group 1)))
  
***************
*** 4709,4714 ****
--- 4751,4759 ----
    (define-key gnus-summary-article-map "hd" 'gnus-article-remove-cr)
    (define-key gnus-summary-article-map "hq" 'gnus-article-de-quoted-unreadable)
    (define-key gnus-summary-article-map "hf" 'gnus-article-display-x-face)
+   (define-key gnus-summary-article-map "ht" 'gnus-article-date-ut)
+   (define-key gnus-summary-article-map "h\C-t" 'gnus-article-date-local)
+   (define-key gnus-summary-article-map "hT" 'gnus-article-date-lapsed)
    (define-key gnus-summary-article-map "m" 'gnus-summary-toggle-mime)
    (define-key gnus-summary-article-map "s" 'gnus-summary-isearch-article)
  
***************
*** 5031,5036 ****
--- 5076,5091 ----
  	  (pop-to-buffer gnus-summary-buffer)
  	  (gnus-set-mode-line 'summary)
  	  (gnus-summary-position-cursor)
+ 	  ;; If in async mode, we send some info to the backend.
+ 	  (and gnus-newsgroup-async
+ 	       (setq gnus-newsgroup-threads (nreverse gnus-newsgroup-threads))
+ 	       (gnus-request-asynchronous 
+ 		gnus-newsgroup-name
+ 		(if (and gnus-asynchronous-article-function
+ 			 (fboundp gnus-asynchronous-article-function))
+ 		    (funcall gnus-asynchronous-article-function
+ 			     gnus-newsgroup-threads)
+ 		  gnus-newsgroup-threads)))
  	  (gnus-kill-buffer kill-buffer)))
      ;; Cannot select newsgroup GROUP.
      (message "Couldn't select newsgroup")
***************
*** 5040,5046 ****
      (gnus-group-next-unread-group 1)))
  
  (defun gnus-summary-prepare ()
!   "Prepare summary list of current newsgroup in summary buffer."
    (let ((buffer-read-only nil))
      (erase-buffer)
      (gnus-summary-prepare-threads 
--- 5095,5101 ----
      (gnus-group-next-unread-group 1)))
  
  (defun gnus-summary-prepare ()
!   ;; Generate the summary buffer.
    (let ((buffer-read-only nil))
      (erase-buffer)
      (gnus-summary-prepare-threads 
***************
*** 5448,5453 ****
--- 5503,5512 ----
         (header
  	(setq number (header-number header)
  	      subject (header-subject header))
+ 	(and gnus-newsgroup-async
+ 	     (setq gnus-newsgroup-threads
+ 		   (cons (cons (header-number header)
+ 			       (header-lines header)) gnus-newsgroup-threads)))
  	(gnus-summary-insert-line
  	 nil header level nil 
  	 (cond ((memq number gnus-newsgroup-marked) gnus-ticked-mark)
***************
*** 5498,5503 ****
--- 5557,5568 ----
      (setq gnus-newsgroup-unselected nil)
      (setq gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
  
+     (and gnus-asynchronous
+ 	 (gnus-check-backend-function 
+ 	  'request-asynchronous gnus-newsgroup-name)
+ 	 (setq gnus-newsgroup-async
+ 	       (gnus-request-asynchronous gnus-newsgroup-name)))
+ 
      (if (not (setq articles (gnus-articles-to-read group read-all)))
  	nil
        ;; Init the dependencies hash table.
***************
*** 6370,6375 ****
--- 6435,6461 ----
    (or (cdr (assq (gnus-summary-article-number) gnus-newsgroup-scored))
        gnus-summary-default-score 0))
  
+ ;; Written by Sudish Joseph <joseph@cis.ohio-state.edu>.
+ (defun gnus-summary-recenter-new ()
+   "Center point in the summary window.
+ If `gnus-auto-center-summary' is nil, or the article buffer isn't
+ displayed, no centering will be performed." 
+   ;; Suggested by earle@mahendo.JPL.NASA.GOV (Greg Earle).
+   ;; Recenter only when requested. Suggested by popovich@park.cs.columbia.edu.
+   (sit-for 0)
+   (and gnus-auto-center-summary
+        (get-buffer-window gnus-article-buffer)
+        (let* ((height (window-height))
+ 	      (w-end (window-end))
+ 	      (top (cond ((< height 4) 0)
+ 			 ((< height 6) 1)
+ 			 (t 2))))
+ 	 (and (= w-end (point-max))
+              ;; adjust for blank lines at the bottom of the window
+ 	     (setq top (+ (count-lines (window-start) (point))
+ 			  (- height (count-lines (window-start) w-end) 2))))
+ 	 (recenter top))))
+ 
  (defun gnus-summary-recenter ()
    "Center point in the summary window.
  If `gnus-auto-center-summary' is nil, or the article buffer isn't
***************
*** 6544,6551 ****
  	  (headers gnus-newsgroup-headers))
        (gnus-close-group group)
        (run-hooks 'gnus-exit-group-hook)
-       (and (fboundp 'gnus-score-save)
- 	   (funcall 'gnus-score-save))
        (gnus-update-read-articles 
         group gnus-newsgroup-unreads gnus-newsgroup-unselected 
         gnus-newsgroup-marked
--- 6630,6635 ----
***************
*** 6556,6561 ****
--- 6640,6650 ----
        (and gnus-use-cross-reference
  	   (gnus-mark-xrefs-as-read 
  	    group headers gnus-newsgroup-unreads gnus-newsgroup-expirable))
+       ;; Do adaptive scoring, and possibly save score files.
+       (and gnus-use-adaptive-scoring
+ 	   (gnus-score-adaptive))
+       (and (fboundp 'gnus-score-save)
+ 	   (funcall 'gnus-score-save))
        ;; Do not switch windows but change the buffer to work.
        (set-buffer gnus-group-buffer)
        (or (eq 'nndigest method)
***************
*** 6705,6711 ****
  	  t)
        (goto-char (point-min)))))
  
! (defun gnus-summary-next-subject (n &optional unread)
    "Go to next N'th summary line.
  If N is negative, go to the previous N'th subject line.
  If UNREAD is non-nil, only unread articles are selected.
--- 6794,6800 ----
  	  t)
        (goto-char (point-min)))))
  
! (defun gnus-summary-next-subject (n &optional unread dont-display)
    "Go to next N'th summary line.
  If N is negative, go to the previous N'th subject line.
  If UNREAD is non-nil, only unread articles are selected.
***************
*** 6714,6725 ****
    (interactive "p")
    (let ((backward (< n 0))
  	(n (abs n)))
!   (while (and (> n 0)
! 	      (gnus-summary-search-forward unread nil backward))
!     (setq n (1- n)))
!   (gnus-summary-recenter)
!   (if (/= 0 n) (message "No more%s articles" (if unread " unread" "")))
!   (gnus-summary-position-cursor)
    n))
  
  (defun gnus-summary-next-unread-subject (n)
--- 6803,6816 ----
    (interactive "p")
    (let ((backward (< n 0))
  	(n (abs n)))
!     (while (and (> n 0)
! 		(gnus-summary-search-forward unread nil backward))
!       (setq n (1- n)))
!     (if (/= 0 n) (message "No more%s articles" (if unread " unread" "")))
!     (or dont-display
! 	(progn
! 	  (gnus-summary-recenter)
! 	  (gnus-summary-position-cursor)))
    n))
  
  (defun gnus-summary-next-unread-subject (n)
***************
*** 7100,7107 ****
        (if header
  	  (gnus-summary-goto-article (header-number header))
  	(let ((gnus-override-method gnus-refer-article-method))
! 	  (or (gnus-server-opened gnus-refer-article-method)
! 	      (gnus-open-server gnus-refer-article-method))
  	  (if (gnus-article-prepare 
  	       message-id nil (gnus-read-header message-id))
  	      (progn
--- 7191,7199 ----
        (if header
  	  (gnus-summary-goto-article (header-number header))
  	(let ((gnus-override-method gnus-refer-article-method))
! 	  (and gnus-refer-article-method
! 	       (or (gnus-server-opened gnus-refer-article-method)
! 		   (gnus-open-server gnus-refer-article-method)))
  	  (if (gnus-article-prepare 
  	       message-id nil (gnus-read-header message-id))
  	      (progn
***************
*** 7681,7692 ****
      (save-excursion
        (let ((level (gnus-summary-thread-level)))
  	(gnus-summary-raise-score score)
! 	(while (and (zerop (gnus-summary-next-subject 1))
  		    (> (gnus-summary-thread-level) level))
  	  (gnus-summary-raise-score score))
  	(setq e (point))))
      (or (zerop (gnus-summary-next-subject 1 t))
  	(goto-char e)))
    (gnus-summary-position-cursor)
    (gnus-set-mode-line 'summary))
  
--- 7773,7785 ----
      (save-excursion
        (let ((level (gnus-summary-thread-level)))
  	(gnus-summary-raise-score score)
! 	(while (and (zerop (gnus-summary-next-subject 1 nil t))
  		    (> (gnus-summary-thread-level) level))
  	  (gnus-summary-raise-score score))
  	(setq e (point))))
      (or (zerop (gnus-summary-next-subject 1 t))
  	(goto-char e)))
+   (gnus-summary-recenter)
    (gnus-summary-position-cursor)
    (gnus-set-mode-line 'summary))
  
***************
*** 7780,7788 ****
  	  (if unmark
  	      (gnus-summary-remove-process-mark (gnus-summary-article-number))
  	    (gnus-summary-set-process-mark (gnus-summary-article-number)))
! 	  (zerop (gnus-summary-next-subject (if backward -1 1))))
      (setq n (1- n)))
    (if (/= 0 n) (message "No more articles"))
    n))
  
  (defun gnus-summary-unmark-as-processable (n)
--- 7873,7883 ----
  	  (if unmark
  	      (gnus-summary-remove-process-mark (gnus-summary-article-number))
  	    (gnus-summary-set-process-mark (gnus-summary-article-number)))
! 	  (zerop (gnus-summary-next-subject (if backward -1 1) nil t)))
      (setq n (1- n)))
    (if (/= 0 n) (message "No more articles"))
+   (gnus-summary-recenter)
+   (gnus-summary-position-cursor)
    n))
  
  (defun gnus-summary-unmark-as-processable (n)
***************
*** 7900,7912 ****
    (gnus-set-global-variables)
    (let ((backward (< n 0))
  	(n (abs n))
! 	(mark (or mark gnus-dread-mark)))
    (while (and (> n 0)
  	      (gnus-summary-mark-article nil mark no-expire)
  	      (zerop (gnus-summary-next-subject 
! 		      (if backward -1 1) gnus-summary-goto-unread)))
      (setq n (1- n)))
    (if (/= 0 n) (message "No more %sarticles" (if mark "" "unread ")))
    (gnus-set-mode-line 'summary)
    n))
  
--- 7995,8009 ----
    (gnus-set-global-variables)
    (let ((backward (< n 0))
  	(n (abs n))
! 	(mark (or mark gnus-del-mark)))
    (while (and (> n 0)
  	      (gnus-summary-mark-article nil mark no-expire)
  	      (zerop (gnus-summary-next-subject 
! 		      (if backward -1 1) gnus-summary-goto-unread t)))
      (setq n (1- n)))
    (if (/= 0 n) (message "No more %sarticles" (if mark "" "unread ")))
+   (gnus-summary-recenter)
+   (gnus-summary-position-cursor)
    (gnus-set-mode-line 'summary)
    n))
  
***************
*** 7923,7935 ****
         gnus-newsgroup-auto-expire 
         (or (not mark)
  	   (and (numberp mark) (or (= mark gnus-killed-mark)
! 				   (= mark gnus-dread-mark)
  				   (= mark gnus-catchup-mark)
  				   (= mark gnus-low-score-mark)
  				   (= mark gnus-read-mark))))
         (setq mark gnus-expirable-mark))
    (let* ((buffer-read-only nil)
! 	 (mark (or (and (stringp mark) (aref mark 0)) mark gnus-dread-mark))
  	 (article (or article (gnus-summary-article-number))))
      (if (or (= mark gnus-unread-mark) 
  	    (= mark gnus-ticked-mark) 
--- 8020,8032 ----
         gnus-newsgroup-auto-expire 
         (or (not mark)
  	   (and (numberp mark) (or (= mark gnus-killed-mark)
! 				   (= mark gnus-del-mark)
  				   (= mark gnus-catchup-mark)
  				   (= mark gnus-low-score-mark)
  				   (= mark gnus-read-mark))))
         (setq mark gnus-expirable-mark))
    (let* ((buffer-read-only nil)
! 	 (mark (or (and (stringp mark) (aref mark 0)) mark gnus-del-mark))
  	 (article (or article (gnus-summary-article-number))))
      (if (or (= mark gnus-unread-mark) 
  	    (= mark gnus-ticked-mark) 
***************
*** 7963,7969 ****
  (defun gnus-mark-article-as-read (article &optional mark)
    "Enter ARTICLE in the pertinent lists and remove it from others."
    ;; Make the article expirable.
!   (let ((mark (or (and (stringp mark) (aref mark 0)) mark gnus-dread-mark)))
      (if (= mark gnus-expirable-mark)
  	(setq gnus-newsgroup-expirable (cons article gnus-newsgroup-expirable))
        (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)))
--- 8060,8066 ----
  (defun gnus-mark-article-as-read (article &optional mark)
    "Enter ARTICLE in the pertinent lists and remove it from others."
    ;; Make the article expirable.
!   (let ((mark (or (and (stringp mark) (aref mark 0)) mark gnus-del-mark)))
      (if (= mark gnus-expirable-mark)
  	(setq gnus-newsgroup-expirable (cons article gnus-newsgroup-expirable))
        (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)))
***************
*** 8033,8046 ****
  The difference between N and the actual number of articles marked is
  returned."
    (interactive "p")
!   (gnus-summary-mark-forward n gnus-dread-mark t))
  
  (defun gnus-summary-mark-as-read-backward (n)
    "Mark the N articles as read backwards.
  The difference between N and the actual number of articles marked is
  returned."
    (interactive "p")
!   (gnus-summary-mark-forward (- n) gnus-dread-mark t))
  
  (defun gnus-summary-mark-as-read (&optional article mark)
    "Mark current article as read.
--- 8130,8143 ----
  The difference between N and the actual number of articles marked is
  returned."
    (interactive "p")
!   (gnus-summary-mark-forward n gnus-del-mark t))
  
  (defun gnus-summary-mark-as-read-backward (n)
    "Mark the N articles as read backwards.
  The difference between N and the actual number of articles marked is
  returned."
    (interactive "p")
!   (gnus-summary-mark-forward (- n) gnus-del-mark t))
  
  (defun gnus-summary-mark-as-read (&optional article mark)
    "Mark current article as read.
***************
*** 8087,8093 ****
  		    (not (memq (gnus-summary-article-number)
  			       gnus-newsgroup-dormant))))
  	       (gnus-summary-mark-article
! 		(gnus-summary-article-number) gnus-dread-mark))
  	      t)
  	    (zerop (forward-line 1))))))
  
--- 8184,8190 ----
  		    (not (memq (gnus-summary-article-number)
  			       gnus-newsgroup-dormant))))
  	       (gnus-summary-mark-article
! 		(gnus-summary-article-number) gnus-del-mark))
  	      t)
  	    (zerop (forward-line 1))))))
  
***************
*** 8102,8108 ****
    (gnus-summary-remove-lines-marked-with 
     (concat (mapconcat
  	    (lambda (char) (char-to-string (symbol-value char)))
! 	    '(gnus-dread-mark gnus-read-mark
  	      gnus-killed-mark gnus-kill-file-mark
  	      gnus-low-score-mark gnus-expirable-mark)
  	    ""))))
--- 8199,8205 ----
    (gnus-summary-remove-lines-marked-with 
     (concat (mapconcat
  	    (lambda (char) (char-to-string (symbol-value char)))
! 	    '(gnus-del-mark gnus-read-mark
  	      gnus-killed-mark gnus-kill-file-mark
  	      gnus-low-score-mark gnus-expirable-mark)
  	    ""))))
***************
*** 8386,8391 ****
--- 8483,8490 ----
  		    (> (gnus-summary-thread-level) level)))
        (while (and (zerop (gnus-summary-next-subject 1))
  		  (> (gnus-summary-thread-level) level))))
+     (gnus-summary-recenter)
+     (gnus-summary-position-cursor)
      (let ((oart (gnus-summary-article-number)))
        (and (/= oart article) oart))))
  
***************
*** 9345,9351 ****
      (set-buffer gnus-article-buffer)
      (goto-char (point-min))
      (if (or (not gnus-article-x-face-command)
! 	    (not (re-search-forward "^X-Face: " nil t)))
  	()
        (let ((face
  	     (buffer-substring
--- 9444,9451 ----
      (set-buffer gnus-article-buffer)
      (goto-char (point-min))
      (if (or (not gnus-article-x-face-command)
! 	    (and (re-search-forward "^\\($\\|X-Face: \\)" nil t)
! 		 (looking-at "^$")))
  	()
        (let ((face
  	     (buffer-substring
***************
*** 9385,9391 ****
  	     (* 16 (gnus-hex-char-to-integer 
  		    (char-after (1+ (match-beginning 0)))))
  	     (gnus-hex-char-to-integer
! 	      (char-after (1- (match-end 0)))))) t t))))))
  
  ;; Taken from hexl.el.
  (defun gnus-hex-char-to-integer (character)
--- 9485,9495 ----
  	     (* 16 (gnus-hex-char-to-integer 
  		    (char-after (1+ (match-beginning 0)))))
  	     (gnus-hex-char-to-integer
! 	      (char-after (1- (match-end 0)))))) t t))
! 	(goto-char (point-min))
! 	(search-forward "\n\n" nil t)
! 	(while (search-forward "=\n" nil t)
! 	  (replace-match "" t t))))))
  
  ;; Taken from hexl.el.
  (defun gnus-hex-char-to-integer (character)
***************
*** 9397,9402 ****
--- 9501,9566 ----
  	  (- ch (- ?a 10))
  	(error (format "Invalid hex digit `%c'." ch))))))
  
+ (defun gnus-article-date-ut (date type)
+   "Convert DATE date to universal time in the current article.
+ If TYPE is `local', convert to local time; if it is `lapsed', output
+ how much time has lapsed since DATE."
+   (interactive (list (header-date gnus-current-headers) 'ut))
+   (if (not date)
+       ()
+     (save-excursion
+       (set-buffer gnus-article-buffer)
+       (let ((buffer-read-only nil))
+ 	(goto-char (point-min))
+ 	(if (re-search-forward "^Date: \\|^X-Sent: " nil t)
+ 	    (delete-region (gnus-point-at-bol)
+ 			   (progn (forward-line 1) (point)))
+ 	  (- (search-forward "\n\n") 2))
+ 	(insert
+ 	 (cond 
+ 	  ((eq type 'local)
+ 	   (concat "Date: " (timezone-make-date-arpa-standard date) "\n"))
+ 	  ((eq type 'ut)
+ 	   (concat "Date: " (timezone-make-date-arpa-standard date nil "UT")
+ 		   "\n"))
+ 	  ((eq type 'lapsed)
+ 	   (let* ((sec (- (gnus-seconds-since-epoch (current-time-string))
+ 			  (gnus-seconds-since-epoch date)))
+ 		  (units (list (cons 'year (* 1.0 365 24 60 60))
+ 			       (cons 'week (* 7 24 60 60))
+ 			       (cons 'day (* 24 60 60))
+ 			       (cons 'hour (* 60 60))
+ 			       (cons 'minute 60)
+ 			       (cons 'second 1)))
+ 		  num prev)
+ 	     (concat
+ 	      "X-Sent: "
+ 	      (mapconcat 
+ 	       (lambda (unit)
+ 		 (if (zerop (setq num (floor (/ sec (cdr unit)))))
+ 		     ""
+ 		   (setq sec (- sec (* num (cdr unit))))
+ 		   (prog1
+ 		       (concat (if prev ", " "") (int-to-string num)
+ 			       " " (symbol-name (car unit))
+ 			       (if (> num 1) "s" ""))
+ 		     (setq prev t))))
+ 	       units "")
+ 	      " ago\n")))
+ 	  (t
+ 	   (error "Unknown conversion type: %s" type))))))))
+ 
+ (defun gnus-article-date-local (date)
+   "Convert the current article date to the local timezone."
+   (interactive (list (header-date gnus-current-headers)))
+   (gnus-article-date-ut date 'local))
+ 
+ (defun gnus-article-date-lapsed (date)
+   "Convert the current article date to time lapsed since it was sent."
+   (interactive (list (header-date gnus-current-headers)))
+   (gnus-article-date-ut date 'lapsed))
+ 
+ 
  ;; Article savers.
  
  (defun gnus-output-to-rmail (file-name)
***************
*** 10118,10123 ****
--- 10282,10292 ----
      (funcall (gnus-get-function method 'request-group) 
  	     (gnus-group-real-name group) (nth 1 method) dont-check)))
  
+ (defun gnus-request-asynchronous (group &optional articles)
+   (let ((method (gnus-find-method-for-group group)))
+     (funcall (gnus-get-function method 'request-asynchronous) 
+ 	     (gnus-group-real-name group) (nth 1 method) articles)))
+ 
  (defun gnus-list-active-group (group)
    (let ((method (gnus-find-method-for-group group))
  	(func 'list-active-group))
***************
*** 10169,10174 ****
--- 10338,10346 ----
  					gnus-valid-select-methods)))
  	       gnus-post-method
  	     (gnus-find-method-for-group gnus-newsgroup-name))))
+      (or (gnus-server-opened method)
+ 	 (gnus-open-server method)
+ 	 (error "Can't open server %s:%s" (car method) (nth 1 method)))
       (let ((mail-self-blind nil)
  	   (mail-archive-file-name nil))
         (funcall (gnus-get-function method 'request-post-buffer) 
diff --exclude=*.elc --exclude=*~ --exclude=*-[0-9] --exclude=gnus --exclude=readme --context --recursive pub/dgnus/lisp/nnspool.el dgnus/lisp/nnspool.el
*** pub/dgnus/lisp/nnspool.el	Sat Apr 22 09:13:18 1995
--- dgnus/lisp/nnspool.el	Mon Apr 24 17:43:36 1995
***************
*** 305,328 ****
  (defun nnspool-request-post (&optional server)
    "Post a new news in current buffer."
    (save-excursion
!     ;; We have to work in the server buffer because of NEmacs hack.
!     (copy-to-buffer nntp-server-buffer (point-min) (point-max))
!     (set-buffer nntp-server-buffer)
!     (apply (function call-process-region)
! 	   (point-min) (point-max)
! 	   nnspool-inews-program 'delete t nil nnspool-inews-switches)
!     (prog1
! 	(or (zerop (buffer-size))
! 	    ;; If inews returns strings, it must be error message 
! 	    ;;  unless SPOOLNEWS is defined.  
! 	    ;; This condition is very weak, but there is no good rule 
! 	    ;;  identifying errors when SPOOLNEWS is defined.  
! 	    ;; Suggested by ohm@kaba.junet.
! 	    (string-match "spooled" (buffer-string)))
        ;; Make status message by unfolding lines.
        (subst-char-in-region (point-min) (point-max) ?\n ?\\ 'noundo)
        (setq nnspool-status-string (buffer-string))
!       (erase-buffer))))
  
  (fset 'nnspool-request-post-buffer 'nntp-request-post-buffer)
  
--- 305,330 ----
  (defun nnspool-request-post (&optional server)
    "Post a new news in current buffer."
    (save-excursion
!     (let* ((inews-buffer (generate-new-buffer " *nnspool post*"))
! 	   (proc (apply 'start-process "*nnspool inews*" inews-buffer
! 			nnspool-inews-program nnspool-inews-switches)))
!       (set-process-sentinel proc 'nnspool-inews-sentinel)
!       (process-send-region proc (point-min) (point-max))
!       (process-send-eof proc)
!       t)))
! 
! (defun nnspool-inews-sentinel (proc status)
!   (save-excursion
!     (set-buffer (process-buffer proc))
!     (goto-char (point-min))
!     (if (or (zerop (buffer-size))
! 	    (search-forward "spooled" nil t))
! 	()
        ;; Make status message by unfolding lines.
        (subst-char-in-region (point-min) (point-max) ?\n ?\\ 'noundo)
        (setq nnspool-status-string (buffer-string))
!       (message "nnspool: %s" nnspool-status-string)
!       (kill-buffer (current-buffer)))))
  
  (fset 'nnspool-request-post-buffer 'nntp-request-post-buffer)
  
diff --exclude=*.elc --exclude=*~ --exclude=*-[0-9] --exclude=gnus --exclude=readme --context --recursive pub/dgnus/lisp/nntp.el dgnus/lisp/nntp.el
*** pub/dgnus/lisp/nntp.el	Sat Apr 22 09:13:18 1995
--- dgnus/lisp/nntp.el	Mon Apr 24 18:20:00 1995
***************
*** 129,134 ****
--- 129,138 ----
  then use this hook to rsh to the remote machine and start a proxy NNTP
  server there that you can connect to.")
  
+ (defvar nntp-async-number 5
+   "*How many articles should be prefetched when in asynchronous mode.")
+ 
+ 
  
  
  (defconst nntp-version "nntp 4.0"
***************
*** 151,156 ****
--- 155,165 ----
  (defvar nntp-server-list-active-group 'try)
  (defvar nntp-current-group "")
  
+ (defvar nntp-async-process nil)
+ (defvar nntp-async-buffer nil)
+ (defvar nntp-async-articles nil)
+ (defvar nntp-async-fetched nil)
+ 
  
  (defvar nntp-current-server nil)
  (defvar nntp-server-alist nil)
***************
*** 169,174 ****
--- 178,187 ----
     (list 'nntp-connection-timeout nntp-connection-timeout)
     (list 'nntp-news-default-headers nntp-news-default-headers)
     (list 'nntp-prepare-server-hook nntp-prepare-server-hook) 
+    '(nntp-async-process nil)
+    '(nntp-async-buffer nil)
+    '(nntp-async-articles nil)
+    '(nntp-async-fetched nil)
     '(nntp-server-process nil)
     '(nntp-status-string nil)
     '(nntp-server-xover try)
***************
*** 194,202 ****
  	    (last-point (point-min)))
  	;; Send HEAD command.
  	(while sequence
! 	  (nntp-send-strings-to-server "HEAD" (car sequence))
! 	  (setq sequence (cdr sequence))
! 	  (setq count (1+ count))
  	  ;; Every 400 header requests we have to read stream in order
  	  ;;  to avoid deadlock.
  	  (if (or (null sequence)	;All requests have been sent.
--- 207,217 ----
  	    (last-point (point-min)))
  	;; Send HEAD command.
  	(while sequence
! 	  (nntp-send-strings-to-server 
! 	   "HEAD" (if (numberp (car sequence)) (int-to-string (car sequence))
! 		    (car sequence)))
! 	  (setq sequence (cdr sequence)
! 		count (1+ count))
  	  ;; Every 400 header requests we have to read stream in order
  	  ;;  to avoid deadlock.
  	  (if (or (null sequence)	;All requests have been sent.
***************
*** 307,313 ****
        t
      (if (or (stringp (car defs))
  	    (numberp (car defs)))
! 	(setq defs (cons (list 'nntp-server-port (car defs)) (cdr defs))))
      (or (assq 'nntp-address defs)
  	(setq defs (append defs (list (list 'nntp-address server)))))
      (if (and nntp-current-server
--- 322,328 ----
        t
      (if (or (stringp (car defs))
  	    (numberp (car defs)))
! 	(setq defs (cons (list 'nntp-port-number (car defs)) (cdr defs))))
      (or (assq 'nntp-address defs)
  	(setq defs (append defs (list (list 'nntp-address server)))))
      (if (and nntp-current-server
***************
*** 347,354 ****
    "Close all server connections."
    (let (proc)
      (while nntp-server-alist
!       (setq proc (nth 1 (assq 'nntp-server-process (car nntp-server-alist))))
!       (and proc (delete-process proc))
        (setq nntp-server-alist (cdr nntp-server-alist)))
      (setq nntp-current-server nil)))
  
--- 362,377 ----
    "Close all server connections."
    (let (proc)
      (while nntp-server-alist
!       (and 
!        (setq proc (nth 1 (assq 'nntp-server-process (car nntp-server-alist))))
!        (delete-process proc))
!       (and 
!        (setq proc (nth 1 (assq 'nntp-async-process (car nntp-server-alist))))
!        (delete-process proc))
!       (and (setq proc (nth 1 (assq 'nntp-async-buffer
! 				   (car nntp-server-alist))))
! 	   (buffer-name proc)
! 	   (kill-buffer proc))
        (setq nntp-server-alist (cdr nntp-server-alist)))
      (setq nntp-current-server nil)))
  
***************
*** 373,388 ****
  (defun nntp-request-article (id &optional newsgroup server buffer)
    "Request article ID (message-id or number)."
    (nntp-possibly-change-server newsgroup server)
!   (unwind-protect
!       (progn
! 	(if buffer (set-process-buffer nntp-server-process buffer))
! 	(let ((nntp-server-buffer (or buffer nntp-server-buffer))
! 	      (id (or (and (numberp id) (int-to-string id)) id)))
! 	  ;; If NEmacs, end of message may look like: "\256\215" (".^M")
! 	  (prog1
! 	      (nntp-send-command "^\\.\r$" "ARTICLE" id)
! 	    (nntp-decode-text))))
!     (if buffer (set-process-buffer nntp-server-process nntp-server-buffer))))
  
  (defun nntp-request-body (id &optional newsgroup server)
    "Request body of article ID (message-id or number)."
--- 396,447 ----
  (defun nntp-request-article (id &optional newsgroup server buffer)
    "Request article ID (message-id or number)."
    (nntp-possibly-change-server newsgroup server)
! 
!   (let (found)
! 
!     ;; First we see whether we can get the article from the async buffer. 
!     (if (and (numberp id)
! 	     nntp-async-articles
! 	     (memq id nntp-async-fetched))
! 	(save-excursion
! 	  (set-buffer nntp-async-buffer)
! 	  (let ((opoint (point))
! 		beg end)
! 	    (if (and (or (re-search-forward (concat "2?? +" id) nil t)
! 			 (progn
! 			   (goto-char (point-min))
! 			   (re-search-forward (concat "2?? +" id) opoint t)))
! 		     (progn
! 		       (beginning-of-line)
! 		       (setq beg (point)
! 			     end (re-search-forward "^\\.\r?\n" nil t))))
! 		(progn
! 		  (setq found t)
! 		  (save-excursion
! 		    (set-buffer (or buffer nntp-server-buffer))
! 		    (erase-buffer)
! 		    (insert-buffer-substring nntp-async-buffer beg end)
! 		    (let ((nntp-server-buffer (current-buffer)))
! 		      (nntp-decode-text)))
! 		  (delete-region beg end)
! 		  (and nntp-async-articles
! 		       (nntp-async-fetch-articles id)))))))
! 
!     (if found 
! 	t
!       ;; The article was not in the async buffer, so we fetch it now.
!       (unwind-protect
! 	  (progn
! 	    (if buffer (set-process-buffer nntp-server-process buffer))
! 	    (let ((nntp-server-buffer (or buffer nntp-server-buffer))
! 		  (art (or (and (numberp id) (int-to-string id)) id)))
! 	      ;; If NEmacs, end of message may look like: "\256\215" (".^M")
! 	      (prog1
! 		  (nntp-send-command "^\\.\r$" "ARTICLE" art)
! 		(nntp-decode-text)
! 		(and nntp-async-articles (nntp-async-fetch-articles id)))))
! 	(if buffer (set-process-buffer 
! 		    nntp-server-process nntp-server-buffer))))))
  
  (defun nntp-request-body (id &optional newsgroup server)
    "Request body of article ID (message-id or number)."
***************
*** 415,420 ****
--- 474,491 ----
      (goto-char (point-min))
      (looking-at "[23]")))
  
+ (defun nntp-request-asynchronous (group &optional server articles)
+   (or (nntp-async-server-opened)
+       (nntp-async-open-server)
+       (error "Can't open second connection to %s" nntp-address))
+   (setq nntp-async-articles articles)
+   (setq nntp-async-fetched nil)
+   (save-excursion
+     (set-buffer nntp-async-buffer)
+     (erase-buffer))
+   (nntp-async-send-strings "GROUP" group)
+   t)
+ 
  (defun nntp-list-active-group (group &optional server)
    (nntp-send-command "^.*\r$" "LIST ACTIVE" group))
  
***************
*** 589,604 ****
  
  (defun nntp-default-sentinel (proc status)
    "Default sentinel function for NNTP server process."
!   (let ((servers nntp-server-alist))
      ;; Go through the alist of server names and find the name of the
      ;; server that the process that sent the signal is connected to.
      ;; If you get my drift.
!     (while (and servers 
! 		(not (equal proc (nth 1 (assq 'nntp-server-process
! 					      (car servers))))))
!       (setq servers (cdr servers)))
!     (message "nntp: Connection closed to server %s." 
! 	     (or (car (car servers)) "(none)"))
      (ding)))
  
  (defun nntp-kill-connection (server)
--- 660,678 ----
  
  (defun nntp-default-sentinel (proc status)
    "Default sentinel function for NNTP server process."
!   (let ((servers nntp-server-alist)
! 	server)
      ;; Go through the alist of server names and find the name of the
      ;; server that the process that sent the signal is connected to.
      ;; If you get my drift.
!     (if (equal proc nntp-server-process)
! 	(setq server nntp-address)
!       (while (and servers 
! 		  (not (equal proc (nth 1 (assq 'nntp-server-process
! 						(car servers))))))
! 	(setq servers (cdr servers)))
!       (setq server (car (car servers))))
!     (message "nntp: Connection closed to server %s." (or server "(none)"))
      (ding)))
  
  (defun nntp-kill-connection (server)
***************
*** 608,614 ****
      (nntp-close-server server)
      (setq nntp-status-string 
  	  (message "Connection timed out to server %s." server))
!     (ding)))
  
  ;; Encoding and decoding of NNTP text.
  
--- 682,689 ----
      (nntp-close-server server)
      (setq nntp-status-string 
  	  (message "Connection timed out to server %s." server))
!     (ding)
!     (sit-for 1)))
  
  ;; Encoding and decoding of NNTP text.
  
***************
*** 762,783 ****
  
  (defun nntp-send-strings-to-server (&rest strings)
    "Send list of STRINGS to news server as command and its arguments."
!   (let ((cmd (car strings))
! 	(strings (cdr strings)))
!     ;; Command and each argument must be separated by one or more spaces.
!     (while strings
!       (setq cmd (concat cmd " " (car strings)))
!       (setq strings (cdr strings)))
!     ;; Command line must be terminated by a CR-LF.
!     (if (not (nntp-server-opened nntp-current-server))
  	(progn
  	  (nntp-close-server nntp-address)
! 	  (if (not (nntp-open-server nntp-address))
! 	      (error (nntp-status-message)))
! 	  (save-excursion
! 	    (set-buffer nntp-server-buffer)
! 	    (erase-buffer))))
!     (process-send-string nntp-server-process (concat cmd "\r\n"))))
  
  (defun nntp-send-region-to-server (begin end)
    "Send current buffer region (from BEGIN to END) to news server."
--- 837,851 ----
  
  (defun nntp-send-strings-to-server (&rest strings)
    "Send list of STRINGS to news server as command and its arguments."
!   (let ((cmd (concat (mapconcat (lambda (s) s) strings " ") "\r\n")))
!     ;; We open the nntp server if it is down.
!     (or (nntp-server-opened nntp-current-server)
  	(progn
  	  (nntp-close-server nntp-address)
! 	  (nntp-open-server nntp-address))
! 	(error (nntp-status-message)))
!     ;; Send the strings.
!     (process-send-string nntp-server-process cmd)))
  
  (defun nntp-send-region-to-server (begin end)
    "Send current buffer region (from BEGIN to END) to news server."
***************
*** 938,943 ****
--- 1006,1052 ----
  	   (setq nntp-server-list-active-group nil))
  	  (t
  	   (setq nntp-server-list-active-group t)))))
+ 
+ (defun nntp-async-server-opened ()
+   (and nntp-async-process
+        (memq (process-status nntp-async-process) '(open run))))
+ 
+ (defun nntp-async-open-server ()
+   (save-excursion
+     (set-buffer (generate-new-buffer " *async-nntp*"))
+     (setq nntp-async-buffer (current-buffer))
+     (buffer-disable-undo))
+   (let ((nntp-server-process nil)
+ 	(nntp-server-buffer nntp-async-buffer))
+     (nntp-open-server-semi-internal nntp-address nntp-port-number)
+     (setq nntp-async-process nntp-server-process)
+     (set-process-buffer nntp-async-process nntp-async-buffer)))
+ 
+ (defun nntp-async-fetch-articles (article)
+   (if (stringp article)
+       ()
+     (let ((articles (memq (assq article nntp-async-articles) 
+ 			  nntp-async-articles))
+ 	  (max (cond ((numberp nntp-async-number)
+ 		      nntp-async-number) 
+ 		     ((eq nntp-async-number t)
+ 		      (length nntp-async-articles))
+ 		     (t 0)))
+ 	  nart)
+       (while (and (>= (setq max (1- max)) 0)
+ 		  articles)
+ 	(or (memq (setq nart (car (car articles))) nntp-async-fetched)
+ 	    (progn
+ 	      (nntp-async-send-strings "ARTICLE " (int-to-string nart))
+ 	      (setq nntp-async-fetched (cons nart nntp-async-fetched))))
+ 	(setq articles (cdr articles))))))
+ 
+ (defun nntp-async-send-strings (&rest strings)
+   (let ((cmd (concat (mapconcat (lambda (s) s) strings " ") "\r\n")))
+     (or (nntp-async-server-opened)
+ 	(nntp-async-open-server)
+ 	(error (nntp-status-message)))
+     (process-send-string nntp-async-process cmd)))
  
  (provide 'nntp)
  
diff --exclude=*.elc --exclude=*~ --exclude=*-[0-9] --exclude=gnus --exclude=readme --context --recursive pub/dgnus/texi/gnus.texi dgnus/texi/gnus.texi
*** pub/dgnus/texi/gnus.texi	Sat Apr 22 09:13:26 1995
--- dgnus/texi/gnus.texi	Mon Apr 24 16:24:27 1995
***************
*** 148,154 ****
  The @code{gnus-uu} package has changed drastically. @xref{Decoding
  Articles}. 
  
! One major compatability question if the presence of several summary
  buffers.  All variables that are relevant while reading a group are
  buffer-local to the summary buffer they belong in.  Although most
  important variables have their values copied into their global
--- 148,154 ----
  The @code{gnus-uu} package has changed drastically. @xref{Decoding
  Articles}. 
  
! One major compatibility question if the presence of several summary
  buffers.  All variables that are relevant while reading a group are
  buffer-local to the summary buffer they belong in.  Although most
  important variables have their values copied into their global
***************
*** 165,171 ****
  @cindex hilit19
  @cindex highlighting
  Old hilit19 code does not work at all.  In fact, you should probably
! remove all hihit code from all Gnus hooks
  (@code{gnus-group-prepare-hook}, @code{gnus-summary-prepare-hook} and
  @code{gnus-summary-article-hook}).  (Well, at the very least the first
  two.)  Gnus provides various integrated functions for highlighting.
--- 165,171 ----
  @cindex hilit19
  @cindex highlighting
  Old hilit19 code does not work at all.  In fact, you should probably
! remove all hilit code from all Gnus hooks
  (@code{gnus-group-prepare-hook}, @code{gnus-summary-prepare-hook} and
  @code{gnus-summary-article-hook}).  (Well, at the very least the first
  two.)  Gnus provides various integrated functions for highlighting.
***************
*** 205,211 ****
  endurance, what with my "oh, that's a neat idea <type type>, yup, I'll
  release it right away <ship off> no wait, that doesn't work at all <type
  type>, yup, I'll ship that one off right away <ship off> no, wait, that
! aboslutely does not work" policy for releases.  Microsoft - bah.  I'm
  @emph{much} worse.
  
  I would like to take this opportunity to thank the Academy for...  oops,
--- 205,211 ----
  endurance, what with my "oh, that's a neat idea <type type>, yup, I'll
  release it right away <ship off> no wait, that doesn't work at all <type
  type>, yup, I'll ship that one off right away <ship off> no, wait, that
! absolutely does not work" policy for releases.  Microsoft - bah.  I'm
  @emph{much} worse.
  
  I would like to take this opportunity to thank the Academy for...  oops,
***************
*** 219,225 ****
  highlighting (as well as the soon-to-come @sc{soup} support) was written
  by Per Abrahamsen.
  @item
! Innumarable bug fixes were written by Sudish Joseph.
  @item
  I stole some pieces from the XGnus distribution by Felix Lee and JWZ.
  @item 
--- 219,225 ----
  highlighting (as well as the soon-to-come @sc{soup} support) was written
  by Per Abrahamsen.
  @item
! Innumerable bug fixes were written by Sudish Joseph.
  @item
  I stole some pieces from the XGnus distribution by Felix Lee and JWZ.
  @item 
***************
*** 261,267 ****
  @emph{before} headers are hidden, via
  @code{gnus-article-hide-headers-if-wanted} which is run from
  @code{gnus-article-display-hook}.  The act of hiding the headers undoes
! all of the hilighting already done.  A similar effect occured in vanilla
  @sc{gnus 4.1} if @code{gnus-show-mime} was set to @code{t}, since
  @sc{mime} processing, too, is done after this hook is executed.
  
--- 261,267 ----
  @emph{before} headers are hidden, via
  @code{gnus-article-hide-headers-if-wanted} which is run from
  @code{gnus-article-display-hook}.  The act of hiding the headers undoes
! all of the hilighting already done.  A similar effect occurred in vanilla
  @sc{gnus 4.1} if @code{gnus-show-mime} was set to @code{t}, since
  @sc{mime} processing, too, is done after this hook is executed.
  
***************
*** 323,337 ****
  next millennium.
  
  @itemize @bullet
- @item 
- Asynchronous article and header fetching would be very nice.  Pleasant.
- Even useful.  I might even have come up with an idea as to how to
- implement it (two connections, a bit @code{run-at-time}, and lots of
- glue), but this will probably not be implemented within the next few
- months.  In fact, I would put money on it not being implemented before
- (ding) is released, so this is more for Gnus 6.0.  Asynchronous posting,
- however, could possibly be included much sooner, as it is a separate
- issue. 
  @item
  Native @sc{mime} support is something that should be done.  I was hoping
  I could steal code from @code{Mew}, the @sc{mime} mail reader for Emacs,
--- 323,328 ----
***************
*** 347,356 ****
  (caching @sc{nov} headers or not?) before jumping into it.  It would
  require much twiddling of Gnus internals to make it work transparently.
  @item
- Gnus could detect which articles in you read and which articles you
- kill, and then employ some adaptive scoring scheme.  That could
- potentially be quite interesting, and it's easy enough to implement.
- @item
  When the user references the parent of an article, some sort of
  re-threading should be done to build a proper tree.  The same goes for
  article expunging.  However, as it stands, it's not a trivial issue to
--- 338,343 ----
***************
*** 587,593 ****
  Subscribe all new groups alphabetically.
  @item gnus-subscribe-hierarchically
  @vindex gnus-subscribe-hierarchically
! Subscribe all new groups hierarchially.
  @item gnus-subscribe-interactively
  @vindex gnus-subscribe-interactively
  Subscribe new groups interactively.  This means that Gnus will ask
--- 574,580 ----
  Subscribe all new groups alphabetically.
  @item gnus-subscribe-hierarchically
  @vindex gnus-subscribe-hierarchically
! Subscribe all new groups hierarchically.
  @item gnus-subscribe-interactively
  @vindex gnus-subscribe-interactively
  Subscribe new groups interactively.  This means that Gnus will ask
***************
*** 603,609 ****
  A closely related variable is
  @code{gnus-subscribe-hierarchical-interactive}.  (That's quite a
  mouthful.)  If this variable is non-@code{nil}, Gnus will ask you in a
! hierarchial fashion whether to subscribe to new groups or not.  Gnus
  will ask you for each sub-hierarchy whether you want to descend the
  hierarchy or not.
  
--- 590,596 ----
  A closely related variable is
  @code{gnus-subscribe-hierarchical-interactive}.  (That's quite a
  mouthful.)  If this variable is non-@code{nil}, Gnus will ask you in a
! hierarchical fashion whether to subscribe to new groups or not.  Gnus
  will ask you for each sub-hierarchy whether you want to descend the
  hierarchy or not.
  
***************
*** 711,717 ****
  @cindex auto-save
  
  Whenever you do something that changes the Gnus data (reading articles,
! cathing up, killing/subscribing groups), the change is added to a
  special @dfn{dribble buffer}.  This buffer is auto-saved the normal
  Emacs way.  If your Emacs should crash before you have saved the
  @file{.newsrc} files, all changes you have made can be recovered from
--- 698,704 ----
  @cindex auto-save
  
  Whenever you do something that changes the Gnus data (reading articles,
! catching up, killing/subscribing groups), the change is added to a
  special @dfn{dribble buffer}.  This buffer is auto-saved the normal
  Emacs way.  If your Emacs should crash before you have saved the
  @file{.newsrc} files, all changes you have made can be recovered from
***************
*** 751,757 ****
  that you actually subscribe to.
  
  Note that if you subscribe to lots and lots of groups, setting this
! variable to @code{nil} will probabaly make Gnus slower, not faster.  At
  present, having this variable @code{nil} will slow Gnus down
  considerably, unless you read news over a 2400 baud modem.  
  
--- 738,744 ----
  that you actually subscribe to.
  
  Note that if you subscribe to lots and lots of groups, setting this
! variable to @code{nil} will probably make Gnus slower, not faster.  At
  present, having this variable @code{nil} will slow Gnus down
  considerably, unless you read news over a 2400 baud modem.  
  
***************
*** 787,793 ****
  @item gnus-inhibit-startup-message
  @vindex gnus-inhibit-startup-message
  If non-@code{nil}, the startup message won't be displayed.  That way,
! your boss might not notice thay you are reading news instead of doing
  your job.
  @item gnus-no-groups-message
  @vindex gnus-no-groups-message
--- 774,780 ----
  @item gnus-inhibit-startup-message
  @vindex gnus-inhibit-startup-message
  If non-@code{nil}, the startup message won't be displayed.  That way,
! your boss might not notice that you are reading news instead of doing
  your job.
  @item gnus-no-groups-message
  @vindex gnus-no-groups-message
***************
*** 804,810 ****
  
  @menu
  * Group Buffer Format::    Information listed and how you can change it.
! * Group Manouvering::      Commands for moving in the group buffer.
  * Selecting a Group::      Actually reading news.
  * Group Subscribing::      Unsubscribing, killing, subscribing.
  * Group Levels::           Levels? What are those, then?
--- 791,797 ----
  
  @menu
  * Group Buffer Format::    Information listed and how you can change it.
! * Group Maneuvering::      Commands for moving in the group buffer.
  * Selecting a Group::      Actually reading news.
  * Group Subscribing::      Unsubscribing, killing, subscribing.
  * Group Levels::           Levels? What are those, then?
***************
*** 858,864 ****
  never examined by Gnus.  Gnus stores all real information it needs using
  text properties.
  
! (Note that if you make a really strange, wonderful, spreadsheat-like
  layout, everybody will believe you are hard at work with the accounting
  instead of wasting time reading news.)
  
--- 845,851 ----
  never examined by Gnus.  Gnus stores all real information it needs using
  text properties.
  
! (Note that if you make a really strange, wonderful, spreadsheet-like
  layout, everybody will believe you are hard at work with the accounting
  instead of wasting time reading news.)
  
***************
*** 923,930 ****
  Default select method.
  @end table
  
! @node Group Manouvering
! @section Group Manouvering
  @cindex group movement
  
  All movement commands understand the numeric prefix and will behave as
--- 910,917 ----
  Default select method.
  @end table
  
! @node Group Maneuvering
! @section Group Maneuvering
  @cindex group movement
  
  All movement commands understand the numeric prefix and will behave as
***************
*** 1136,1142 ****
  @vindex gnus-level-subscribed
  Gnus considers groups on between levels 1 and
  @code{gnus-level-subscribed} (inclusive) to be subscribed,
! @code{gnus-level-subscribed} (ecxlusive) and
  @code{gnus-level-unsubscribed} (inclusive) to be unsubscribed,
  @code{gnus-level-zombie} to be zombies (walking dead) and
  @code{gnus-level-killed} to be killed, completely dead.  Gnus treats
--- 1123,1129 ----
  @vindex gnus-level-subscribed
  Gnus considers groups on between levels 1 and
  @code{gnus-level-subscribed} (inclusive) to be subscribed,
! @code{gnus-level-subscribed} (exclusive) and
  @code{gnus-level-unsubscribed} (inclusive) to be unsubscribed,
  @code{gnus-level-zombie} to be zombies (walking dead) and
  @code{gnus-level-killed} to be killed, completely dead.  Gnus treats
***************
*** 1155,1161 ****
  @vindex gnus-level-default-unsubscribed
  @vindex gnus-level-default-subscribed
  Two closely related variables are @code{gnus-level-default-subscribed}
! and @code{gnus-level-default-unsubscribed}, which are the leves that new
  groups will be put on if they are (un)subscribed.  These two variables
  should, of course, be inside the relevant legal ranges.
  
--- 1142,1148 ----
  @vindex gnus-level-default-unsubscribed
  @vindex gnus-level-default-subscribed
  Two closely related variables are @code{gnus-level-default-subscribed}
! and @code{gnus-level-default-unsubscribed}, which are the levels that new
  groups will be put on if they are (un)subscribed.  These two variables
  should, of course, be inside the relevant legal ranges.
  
***************
*** 1381,1386 ****
--- 1368,1380 ----
  @vindex nntp-prepare-server-hook
  A hook run before attempting to connect to an @sc{nntp} server.
  
+ @item nntp-async-number
+ @vindex nntp-async-number
+ How many articles should be pre-fetched when in asynchronous mode.  If
+ this variable is @code{t}, @code{nntp} will pre-fetch all the articles
+ that it can without bound.  If it is @code{nil}, no pre-fetching will be
+ made.
+ 
  @end table
  
  @node nnspool
***************
*** 1521,1527 ****
  that are to be part of the nnkiboze groups.
  
  Please limit the number of component groups by using restrictive
! regexps.  Otherwise your sysadm may become annoyed with you, and the
  @sc{nntp} site may throw you off and never let you back in again.
  Stranger things have happened.
  
--- 1515,1521 ----
  that are to be part of the nnkiboze groups.
  
  Please limit the number of component groups by using restrictive
! regexps.  Otherwise your sysadmin may become annoyed with you, and the
  @sc{nntp} site may throw you off and never let you back in again.
  Stranger things have happened.
  
***************
*** 2197,2203 ****
  @kindex z (Group)
  @findex gnus-group-suspend
  Suspend Gnus (@code{gnus-group-suspend}).  This doesn't really exit Gnus,
! but it kills all buffers exept the Group buffer.  I'm not sure why this
  is a gain, but then who am I to judge?
  @item q
  @kindex q (Group)
--- 2191,2197 ----
  @kindex z (Group)
  @findex gnus-group-suspend
  Suspend Gnus (@code{gnus-group-suspend}).  This doesn't really exit Gnus,
! but it kills all buffers except the Group buffer.  I'm not sure why this
  is a gain, but then who am I to judge?
  @item q
  @kindex q (Group)
***************
*** 2305,2311 ****
  @kindex M-d (Group)
  @findex gnus-group-describe-all-groups
  Describe all groups (@code{gnus-group-describe-all-groups}).  If given a
! prefix, force Gnus to re-read the descriptoion file from the server.
  @item ?
  @kindex ? (Group)
  @findex gnus-group-describe-briefly
--- 2299,2305 ----
  @kindex M-d (Group)
  @findex gnus-group-describe-all-groups
  Describe all groups (@code{gnus-group-describe-all-groups}).  If given a
! prefix, force Gnus to re-read the description file from the server.
  @item ?
  @kindex ? (Group)
  @findex gnus-group-describe-briefly
***************
*** 2329,2342 ****
  move around, read articles, post articles and reply to articles.
  
  @menu
! * Summary Buffer Format::       Deciding how the summar buffer is to look.
! * Summary Manouvering::         Moving around the summary buffer.
  * Choosing Articles::           Reading articles.
  * Paging the Article::          Scrolling the current article.
  * Reply Followup and Post::     Posting articles.
  * Cancelling and Superseding::  "Whoops, I shouldn't have called him that."
  * Ticking and Marking::         Marking articles as read, expirable, etc.
  * Threading::                   How threads are made.
  * Exiting the Summary Buffer::  Returning to the Group buffer.
  * Process/Prefix::              A convention used by many treatment commands.
  * Saving Articles::             Ways of customizing article saving.
--- 2323,2337 ----
  move around, read articles, post articles and reply to articles.
  
  @menu
! * Summary Buffer Format::       Deciding how the summary buffer is to look.
! * Summary Maneuvering::         Moving around the summary buffer.
  * Choosing Articles::           Reading articles.
  * Paging the Article::          Scrolling the current article.
  * Reply Followup and Post::     Posting articles.
  * Cancelling and Superseding::  "Whoops, I shouldn't have called him that."
  * Ticking and Marking::         Marking articles as read, expirable, etc.
  * Threading::                   How threads are made.
+ * Asynchronous Fetching::       Gnus might be able to pre-fetch articles.
  * Exiting the Summary Buffer::  Returning to the Group buffer.
  * Process/Prefix::              A convention used by many treatment commands.
  * Saving Articles::             Ways of customizing article saving.
***************
*** 2413,2419 ****
  Opening bracket, which is normally @samp{\[}, but can also be @samp{<}
  for adopted articles.
  @item \]
! Closing bracked, which is normally @samp{\]}, but can also be @samp{>}
  for adopted articles.
  @item <
  One space for each thread level.
--- 2408,2414 ----
  Opening bracket, which is normally @samp{\[}, but can also be @samp{<}
  for adopted articles.
  @item \]
! Closing bracket, which is normally @samp{\]}, but can also be @samp{>}
  for adopted articles.
  @item <
  One space for each thread level.
***************
*** 2485,2491 ****
  Number of unselected articles in this group.
  @item Z
  A string with the number of unread and unselected articles represented
! either as @samp{<%U(+%u) more>} if there are both anread and unselected
  articles, and just as @samp{<%U more>} if there are just unread articles
  and no unselected ones.
  @item g
--- 2480,2486 ----
  Number of unselected articles in this group.
  @item Z
  A string with the number of unread and unselected articles represented
! either as @samp{<%U(+%u) more>} if there are both unread and unselected
  articles, and just as @samp{<%U more>} if there are just unread articles
  and no unselected ones.
  @item g
***************
*** 2500,2507 ****
  @end table
  
  
! @node Summary Manouvering
! @section Summary Manouvering
  @cindex summary movement
  
  All the straight movement commands understand the numeric prefix and
--- 2495,2502 ----
  @end table
  
  
! @node Summary Maneuvering
! @section Summary Maneuvering
  @cindex summary movement
  
  All the straight movement commands understand the numeric prefix and
***************
*** 2550,2556 ****
  
  @vindex gnus-auto-select-same
  If @code{gnus-auto-select-same} is non-@code{nil}, all the movement
! commands wil try to go to the next article with the same subject as the
  current.  This variable is not particularly useful if you use a threaded
  display.
  
--- 2545,2551 ----
  
  @vindex gnus-auto-select-same
  If @code{gnus-auto-select-same} is non-@code{nil}, all the movement
! commands will try to go to the next article with the same subject as the
  current.  This variable is not particularly useful if you use a threaded
  display.
  
***************
*** 2699,2705 ****
  @item DEL
  @kindex DEL (Summary)
  @findex gnus-summary-prev-page
! Scoll the current article back one page (@code{gnus-summary-prev-page}). 
  @item RET
  @kindex RET (Summary)
  @findex gnus-summary-scroll-up
--- 2694,2700 ----
  @item DEL
  @kindex DEL (Summary)
  @findex gnus-summary-prev-page
! Scroll the current article back one page (@code{gnus-summary-prev-page}). 
  @item RET
  @kindex RET (Summary)
  @findex gnus-summary-scroll-up
***************
*** 3231,3237 ****
  @table @samp
  @item D
  Articles that are marked as read.  They have a @samp{D}
! (@code{gnus-dread-mark}) in the first column.  These are articles that the
  user has marked as read more or less manually.
  @item d
  Articles that are actually read are marked with @samp{d}
--- 3226,3232 ----
  @table @samp
  @item D
  Articles that are marked as read.  They have a @samp{D}
! (@code{gnus-del-mark}) in the first column.  These are articles that the
  user has marked as read more or less manually.
  @item d
  Articles that are actually read are marked with @samp{d}
***************
*** 3599,3605 ****
  @kindex T k (Summary)
  @kindex M-C-k (Summary)
  @findex gnus-summary-kill-thread
! Mark all articles in the current subtread as read
  (@code{gnus-summary-kill-thread}).  If the prefix argument is positive,
  remove all marks instead.  If the prefix argument is negative, tick
  articles instead.
--- 3594,3600 ----
  @kindex T k (Summary)
  @kindex M-C-k (Summary)
  @findex gnus-summary-kill-thread
! Mark all articles in the current subthread as read
  (@code{gnus-summary-kill-thread}).  If the prefix argument is positive,
  remove all marks instead.  If the prefix argument is negative, tick
  articles instead.
***************
*** 3665,3670 ****
--- 3660,3720 ----
  Ascend the thread (@code{gnus-summary-up-thread}).
  @end table
  
+ @node Asynchronous Fetching
+ @section Asynchronous Article Fetching
+ @cindex asynchronous article fetching
+ 
+ If you read your news from an @sc{nntp} server that's far away, the
+ network latencies may make reading articles a chore.  You have to way
+ for a while after pressing @kbd{n} to go to the next article before the
+ article appears.  Why can't Gnus just go ahead and fetch the article
+ while you are reading the previous one?  Why not, indeed.
+ 
+ First, some caveats.  There are some pitfalls to using asynchronous
+ article fetching, especially the way Gnus does it.  
+ 
+ Let's say you are reading article 1, which is short, and article 2 is
+ quite long, and you are not interested in reading that.  Gnus does not
+ know this, so it goes ahead and fetches article 2.  You decide to read
+ article 3, but since Gnus is in the process of fetching article 2, the
+ connection is blocked.
+ 
+ To avoid these situations, Gnus will open two (count 'em two)
+ connections to the server.  Some people may think this isn't a very nice
+ thing to do, but I don't see any real alternatives.  Setting up that
+ extra connection takes some time, so Gnus startup will be slower.
+ 
+ Gnus will fetch more articles than you will read.  This will mean that
+ the link between your machine and the @sc{nntp} server will become more
+ loaded than if you didn't use article pre-fetch.  The server itself will
+ also become more loaded - both with the extra article requests, and the
+ extra connection.
+ 
+ Ok, so now you know that you shouldn't really use this thing... unless
+ you really want to.
+ 
+ @vindex gnus-asynchronous
+ Here's how:  Set @code{gnus-asynchronous} to @code{t}.  The rest should
+ happen automatically.
+ 
+ @vindex nntp-async-number
+ You can control how many articles that are to be pre-fetched by setting
+ @code{nntp-async-number}.  This is five by default, which means that when
+ you read an article in the group, @code{nntp} will pre-fetch the next
+ five articles.  If this variable is @code{t}, @code{nntp} will pre-fetch
+ all the articles that it can without bound.  If it is @code{nil}, no
+ pre-fetching will be made.
+ 
+ @vindex gnus-asynchronous-article-function
+ You may wish to create some sort of scheme for choosing which articles
+ that @code{nntp} should consider as candidates for pre-fetching.  For
+ instance, you may wish to pre-fetch all articles with high scores, and
+ not pre-fetch low-scored articles.  You can do that by setting the
+ @code{gnus-asynchronous-article-function}, which will be called with an
+ alist where the keys are the article numbers.  Your function should
+ return an alist where the articles you are not interested in have been
+ removed.  You could also do sorting on article score and the like. 
+ 
  @node Exiting the Summary Buffer
  @section Exiting the Summary Buffer
  @cindex summary exit
***************
*** 4091,4097 ****
  @item gnus-uu-do-not-unpack-archives
  @vindex gnus-uu-do-not-unpack-archives
  Non-@code{nil} means that @code{gnus-uu} won't peek inside archives
! looking for files to dispay.
  
  @item gnus-uu-view-and-save
  @vindex gnus-uu-view-and-save
--- 4141,4147 ----
  @item gnus-uu-do-not-unpack-archives
  @vindex gnus-uu-do-not-unpack-archives
  Non-@code{nil} means that @code{gnus-uu} won't peek inside archives
! looking for files to display.
  
  @item gnus-uu-view-and-save
  @vindex gnus-uu-view-and-save
***************
*** 4210,4216 ****
  @code{nil}, all files that use the same viewing command will be given as
  a list of parameters to that command.
  
! So; there you are, reading your @emph{pseduo-articles} in your
  @emph{virtual newsgroup} from the @emph{virtual server}; and you think:
  Why isn't anything real anymore? How did we get here?
  
--- 4260,4266 ----
  @code{nil}, all files that use the same viewing command will be given as
  a list of parameters to that command.
  
! So; there you are, reading your @emph{pseudo-articles} in your
  @emph{virtual newsgroup} from the @emph{virtual server}; and you think:
  Why isn't anything real anymore? How did we get here?
  
***************
*** 4328,4334 ****
  @node Finding the Parent
  @section Finding the Parent
  @cindex parent articles
! @cindex refering articles
  
  @findex gnus-summary-refer-parent-article
  @kindex ^ (Summary)
--- 4378,4384 ----
  @node Finding the Parent
  @section Finding the Parent
  @cindex parent articles
! @cindex referring articles
  
  @findex gnus-summary-refer-parent-article
  @kindex ^ (Summary)
***************
*** 4390,4395 ****
--- 4440,4446 ----
  * Score Variables::          Customize your scoring.  (My, what terminology).
  * Score File Format::        What a score file may contain.
  * Score File Editing::       You can edit score files by hand as well.
+ * Adaptive Scoring::         Big Sister Gnus *knows* what you read.
  * Scoring Tips::             How to score effectively.
  * Reverse Scoring::          That problem child of old is not problem.
  * Global Score Files::       Earth-spanning, ear-splitting score files.
***************
*** 4838,4843 ****
--- 4889,4945 ----
  you were wondering.
  @end table
  
+ @node Adaptive Scoring
+ @subsection Adaptive Scoring
+ @cindex adaptive scoring
+ 
+ If all this scoring is getting you down, Gnus has a way of making it all
+ happen automatically - as if by magic.  Or rather, as if by artificial
+ stupidity, to be precise.
+ 
+ @vindex gnus-use-adaptive-scoring
+ When you read an article, or mark an article as read, or kill an
+ article, you leave marks behind.  On exit from the group, Gnus can sniff
+ these marks and add score elements depending on what marks it finds.
+ You turn on this ability by setting @code{gnus-use-adaptive-scoring} to
+ @code{t}. 
+ 
+ @vindex gnus-adaptive-score-alist
+ To give you complete control over the scoring process, you can customize
+ the @code{gnus-adaptive-score-alist} variable.  By default, it looks
+ something like this:
+ 
+ @lisp
+ (defvar gnus-adaptive-score-alist
+   '((gnus-unread-mark)
+     (gnus-ticked-mark (from 4))
+     (gnus-dormant-mark (from 5))
+     (gnus-del-mark (from -4) (subject -1))
+     (gnus-read-mark (from 4) (subject 2))
+     (gnus-expirable-mark (from -1) (subject -1))
+     (gnus-killed-mark (from -1) (subject -3))
+     (gnus-kill-file-mark)
+     (gnus-catchup-mark (from -1) (subject -1))))
+ @end lisp
+ 
+ As you see, each element in this alist has a mark as a key (either a
+ variable name or a "real" mark - a character).  Following this key is a
+ random number of header/score pairs.  
+ 
+ To take @code{gnus-del-mark} as an example - this alist says that all
+ articles that have that mark (ie. are marked with @samp{D}) will have a
+ score entry added to lower based on the @code{From} header by -4, and
+ lowered by @code{Subject} by -1.  Change this to fit your prejudices. 
+ 
+ If you use this scheme, you should set @code{mark-below} to something
+ small - like -300, perhaps, to avoid having small random changes result
+ in articles getting marked as read.
+ 
+ After using adaptive scoring for a week or so, Gnus should start to
+ become properly trained and enhance the authors you like best, and kill
+ the authors you like least, without you having to say so explicitly. 
+ 
+ 
  @node Scoring Tips
  @subsection Scoring Tips
  @cindex scoring tips
***************
*** 5300,5313 ****
  makes in The Hands Of The Mad); @code{gnus-article-treat-overstrike}
  (which treats @samp{^H_} in a reasonable manner);
  @code{gnus-article-remove-cr} (which removes trailing carriage returns);
! @code{gnus-article-de-quoted-unreadble} (which does a naive decoding of
  articles encoded with Quoted-Printable); and
  @code{gnus-article-display-x-face} (which displays any X-Face headers).
  
  You can, of course, write your own functions.  The functions are called
  from the article buffer, and you can do anything you like, pretty much.
  There is no information that you have to keep in the buffer - you can
! change everything.  However, you shouldn't delete anu headers.  Instead
  make them invisible if you want to make them go away.
  
  @node Article Keymap
--- 5402,5415 ----
  makes in The Hands Of The Mad); @code{gnus-article-treat-overstrike}
  (which treats @samp{^H_} in a reasonable manner);
  @code{gnus-article-remove-cr} (which removes trailing carriage returns);
! @code{gnus-article-de-quoted-unreadable} (which does a naive decoding of
  articles encoded with Quoted-Printable); and
  @code{gnus-article-display-x-face} (which displays any X-Face headers).
  
  You can, of course, write your own functions.  The functions are called
  from the article buffer, and you can do anything you like, pretty much.
  There is no information that you have to keep in the buffer - you can
! change everything.  However, you shouldn't delete any headers.  Instead
  make them invisible if you want to make them go away.
  
  @node Article Keymap
***************
*** 5381,5391 ****
  @item gnus-break-pages
  Controls whether @dfn{page breaking} is to take place.  If this variable
  is non-@code{nil}, the articles will be divided into pages whenever a
! page delimeter appears in the article.  If this variable is @code{nil},
  paging will not be done.
! @item gnus-page-delimeter
  @vindex gnus-page-delimiter
! This is the delimeter mentioned above.  By default, it is @samp{^L}
  (form linefeed).
  @end table
  
--- 5483,5493 ----
  @item gnus-break-pages
  Controls whether @dfn{page breaking} is to take place.  If this variable
  is non-@code{nil}, the articles will be divided into pages whenever a
! page delimiter appears in the article.  If this variable is @code{nil},
  paging will not be done.
! @item gnus-page-delimiter
  @vindex gnus-page-delimiter
! This is the delimiter mentioned above.  By default, it is @samp{^L}
  (form linefeed).
  @end table
  
***************
*** 5490,5496 ****
  (nntp "news.funet.fi" (nntp-port-number 15))
  @end lisp
  
! You should read the documention to each backend to find out what
  variables are relevant, but here's an @code{nnmh} example. 
  
  @code{nnmh} is a mail backend that reads a spool-like structure.  Say
--- 5592,5598 ----
  (nntp "news.funet.fi" (nntp-port-number 15))
  @end lisp
  
! You should read the documentation to each backend to find out what
  variables are relevant, but here's an @code{nnmh} example. 
  
  @code{nnmh} is a mail backend that reads a spool-like structure.  Say
***************
*** 5679,5685 ****
  @node Slow Terminal Connection
  @section Slow Terminal Connection
  
! Let's say you use your home computer for dialling up the system that
  runs Emacs and Gnus.  If your modem is slow, you want to reduce the
  amount of data that is sent over the wires as much as possible.
  
--- 5781,5787 ----
  @node Slow Terminal Connection
  @section Slow Terminal Connection
  
! Let's say you use your home computer for dialing up the system that
  runs Emacs and Gnus.  If your modem is slow, you want to reduce the
  amount of data that is sent over the wires as much as possible.
  
