Importing Gnus v5.8.2.
authorueno <ueno>
Sat, 4 Dec 1999 16:51:56 +0000 (16:51 +0000)
committerueno <ueno>
Sat, 4 Dec 1999 16:51:56 +0000 (16:51 +0000)
27 files changed:
lisp/ChangeLog
lisp/dgnushack.el
lisp/gnus-art.el
lisp/gnus-cache.el
lisp/gnus-int.el
lisp/gnus-msg.el
lisp/gnus-start.el
lisp/gnus-sum.el
lisp/gnus-uu.el
lisp/gnus.el
lisp/mail-source.el
lisp/message.el
lisp/mm-bodies.el
lisp/mm-util.el
lisp/mm-view.el
lisp/mml.el
lisp/nnfolder.el
lisp/nnmh.el
lisp/nnslashdot.el
lisp/nntp.el
lisp/nnultimate.el
lisp/nnweb.el
lisp/rfc2047.el
texi/ChangeLog
texi/gnus.texi
texi/gnusmail.texi [new file with mode: 0644]
texi/message.texi

index 46c0f9c..16f290a 100644 (file)
@@ -1,3 +1,184 @@
+Fri Dec  3 20:34:11 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v5.8.2 is released.
+
+Fri Dec  3 20:09:41 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v5.8.1 is released.
+
+1999-11-11  Hrvoje Niksic  <hniksic@iskon.hr>
+
+       * mml.el (mml-insert-tag): Don't close the tag.
+       (mml-insert-empty-tag): New function.
+       (mml-attach-file): Use mml-insert-empty-tag instead of
+       mml-insert-tag.
+       (mml-attach-buffer): Ditto.
+       (mml-attach-external): Ditto.
+       (mml-insert-multipart): Ditto.
+
+1999-12-03 08:49:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-request-article): Return -1 if not find
+       the article number.
+
+1999-12-03 01:12:41  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-find-method-for-group): The method of a new group
+       is not the native one.
+
+1999-12-03 01:26:55  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-button-embedded-url): Always call browse-url. 
+
+1999-12-02 18:00:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Use
+       mm-with-unibyte-current-buffer. 
+       (nnultimate-request-article): Ditto.
+
+1999-12-02 14:57:46  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-retrieve-groups): Set to process buffer.
+
+1999-12-02 11:14:50  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-with-unibyte-current-buffer): New macro.
+       * nnweb.el (nnweb-retrieve-headers): Use it.
+       (nnweb-request-article): Use it.
+       
+       * nnweb.el (nnweb-dejanews-create-mapping): Set a default date in
+       case matching failed.
+
+1999-12-02  John Wiegley <jwiegley@inprise.com>
+
+       * mail-source.el (mail-source-keyword-map): Add backslash to
+       Delete-flag.
+
+1999-12-02 07:24:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-group-charset-alist): Default nnweb groups to
+       Latin-1.
+       (gnus-group-charset-alist): No, don't.
+
+       * nnweb.el (nnweb-init): Make the buffer unibyte.
+
+1999-12-01 23:02:48  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-set-common-1): Fix to get the
+       default value.
+
+1999-12-02 00:27:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-read-groups): Unibyte.
+
+       * nnultimate.el (nnultimate-request-list): Use unibyte.
+
+       * gnus-uu.el (gnus-uu-grab-articles): Bind
+       gnus-display-mime-function to nil.
+
+       * message.el (message-send-mail-with-sendmail): Use the
+       user-mail-address variable.
+
+       * gnus-art.el (gnus-ignored-headers): More headers.
+
+       * message.el (message-shorten-1): Use list.
+
+1999-12-01 21:59:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-configure-posting-styles): Ignore nil
+       signatures. 
+
+       * nnweb.el (nnweb-dejanews-create-mapping): Get the data.
+       (nnweb-dejanews-create-mapping): Do the properish date.
+
+1999-12-01 17:41:21  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-common-keyword-map): New variable.
+       (mail-source-bind-common): New macro.
+       (mail-source-fetch): Support plugged mail source.
+       * gnus-int.el (gnus-request-scan): Use them.
+
+1999-12-01 21:59:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-message): Check whether charset is a
+       string. 
+
+       * nnslashdot.el (nnslashdot-request-post): Insert <p>'s.
+
+       * message.el (message-mode-map): Changed keystroke for
+       message-yank-buffer. 
+
+1999-11-26  Hrvoje Niksic  <hniksic@iskon.hr>
+
+       * message.el (message-shorten-references): Cut references to 31
+       elements, then either fold them or shorten them to 988 characters.
+       (message-shorten-1): New function.
+       (message-cater-to-broken-inn): New variable.
+
+1999-12-01 21:47:10  Eric Marsden  <emarsden@mail.dotcom.fr>
+
+       * nnslashdot.el (nnslashdot-lose): New function.
+
+1999-12-01 21:08:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-message): Not the right type of charset is 
+       being fetched here.  Let the group charset rule.
+       (mm-inline-message): Ignore us-ascii.
+
+1999-11-24  Carsten Leonhardt  <leo@arioch.oche.de>
+
+       * mail-source.el (mail-source-fetch-maildir): work around the
+       ommitted "file-regular-p" in efs/ange-ftp
+
+1999-12-01 19:59:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-generate-mime-1): Don't insert extra empty line.
+       (mml-generate-mime-1): Use the encoding param.
+
+       * gnus-sum.el (gnus-summary-show-article): Don't bind gnus-visual.
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Require
+       gnus-art before binding its variables.
+
+       * gnus-art.el (gnus-article-prepare-display): Run the prepare
+       after the MIME.
+
+1999-12-01 19:48:14  Rupa Schomaker  <rupa-list@rupa.com>
+
+       * message.el (message-clone-locals): Use it.
+
+       * gnus-msg.el (gnus-configure-posting-styles): Make
+       user-mail-address local.
+
+1999-11-20  Simon Josefsson  <jas@pdc.kth.se>
+
+        * gnus-start.el (gnus-get-unread-articles): Scan each method only
+       once.
+
+1999-12-01 17:37:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-generate-new-buffer-clone-locals): Use varstr.
+       (message-clone-locals): Ditto.
+
+       * gnus-sum.el (gnus-summary-enter-digest-group): Have the digest
+       group inherit reply-to or from.
+
+1999-12-01 13:04:09  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-show-article): Support numbered ARG
+       for charset.
+       (gnus-summary-show-article-charset-alist): New variable.
+       
+       * mm-bodies.el (mm-decode-string): Support gnus-all and
+       gnus-unknown.
+       (mm-decode-body): Ditto.
+       * rfc2047.el (rfc2047-decode): Ditto.
+
+1999-12-01 17:37:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-delete-incoming): Change default to
+       t.
+
 Wed Dec  1 16:31:31 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
        * gnus.el: Pterodactyl Gnus v0.99 is released.
index 5af2e61..76b8c88 100644 (file)
@@ -53,6 +53,7 @@
 (defvar srcdir (or (getenv "srcdir") "."))
 
 (push srcdir load-path)
+;(push "/usr/share/emacs/site-lisp" load-path)
 (load (expand-file-name "lpath.el" srcdir) nil t)
 
 (defalias 'device-sound-enabled-p 'ignore)
index 809169d..0c01793 100644 (file)
     "^X-Sun-Charset:" "^X-Accept-Language:" "^X-Envelope-Sender:"
     "^List-[A-Za-z]+:" "^X-Listprocessor-Version:"
     "^X-Received:" "^X-Distribute:" "^X-Sequence:" "^X-Juno-Line-Breaks:"
-    "^X-Notes-Item:" "^X-MS-TNEF-Correlator:" "^x-uunet-gateway:")
+    "^X-Notes-Item:" "^X-MS-TNEF-Correlator:" "^x-uunet-gateway:"
+    "^X-Received:" "^Content-length:" "X-precedence:")
   "*All headers that start with this regexp will be hidden.
 This variable can also be a list of regexps of headers to be ignored.
 If `gnus-visible-headers' is non-nil, this variable will be ignored."
@@ -2724,9 +2725,9 @@ If ALL-HEADERS is non-nil, no headers are hidden."
     (setq buffer-read-only nil
          gnus-article-wash-types nil)
     (gnus-run-hooks 'gnus-tmp-internal-hook)
-    (gnus-run-hooks 'gnus-article-prepare-hook)
     (when gnus-display-mime-function
-      (funcall gnus-display-mime-function))))
+      (funcall gnus-display-mime-function))
+    (gnus-run-hooks 'gnus-article-prepare-hook)))
 
 ;;;
 ;;; Gnus MIME viewing functions
@@ -4390,10 +4391,7 @@ forbidden in URL encoding."
 
 (defun gnus-button-embedded-url (address)
   "Browse ADDRESS."
-  ;; In Emacs 20, `browse-url-browser-function' may be an alist.
-  (if (listp browse-url-browser-function)
-      (browse-url (gnus-strip-whitespace address))
-    (funcall browse-url-browser-function (gnus-strip-whitespace address))))
+  (browse-url (gnus-strip-whitespace address)))
 
 ;;; Next/prev buttons in the article buffer.
 
index fcb8bb5..0cc99b5 100644 (file)
@@ -175,6 +175,7 @@ it's not cached."
            t                           ; The article already is saved.
          (save-excursion
            (set-buffer nntp-server-buffer)
+           (require 'gnus-art)
            (let ((gnus-use-cache nil)
                  (gnus-article-decode-hook nil))
              (gnus-request-article-this-buffer number group))
index bc94a5c..5b6264d 100644 (file)
@@ -413,13 +413,14 @@ If BUFFER, insert the article in that group."
 (defun gnus-request-scan (group gnus-command-method)
   "Request a SCAN being performed in GROUP from GNUS-COMMAND-METHOD.
 If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
-  (when gnus-plugged
-    (let ((gnus-command-method
-          (if group (gnus-find-method-for-group group) gnus-command-method))
-         (gnus-inhibit-demon t))
-      (funcall (gnus-get-function gnus-command-method 'request-scan)
-              (and group (gnus-group-real-name group))
-              (nth 1 gnus-command-method)))))
+  (let ((gnus-command-method
+        (if group (gnus-find-method-for-group group) gnus-command-method))
+       (gnus-inhibit-demon t)
+       (mail-source-plugged gnus-plugged))
+    (if (or gnus-plugged (not (gnus-agent-method-p gnus-command-method)))
+       (funcall (gnus-get-function gnus-command-method 'request-scan)
+                (and group (gnus-group-real-name group))
+                (nth 1 gnus-command-method)))))
 
 (defsubst gnus-request-update-info (info gnus-command-method)
   "Request that GNUS-COMMAND-METHOD update INFO."
index 4bd55a6..55fdbbf 100644 (file)
@@ -1198,11 +1198,13 @@ this is a reply."
                     ((eq 'signature (car result))
                      (set (make-local-variable 'message-signature) nil)
                      (set (make-local-variable 'message-signature-file) nil)
-                     `(lambda ()
-                        (save-excursion
-                          (let ((message-signature ,(cdr result)))
-                            (when message-signature
-                              (message-insert-signature))))))
+                     (if (not (cdr result))
+                         'ignore
+                       `(lambda ()
+                          (save-excursion
+                            (let ((message-signature ,(cdr result)))
+                              (when message-signature
+                                (message-insert-signature)))))))
                     (t
                      (let ((header
                             (if (symbolp (car result))
@@ -1216,6 +1218,8 @@ this is a reply."
       (when (or name address)
        (add-hook 'message-setup-hook
                  `(lambda ()
+                    (set (make-local-variable 'user-mail-address)
+                         ,(or (cdr address) user-mail-address))
                     (let ((user-full-name ,(or (cdr name) (user-full-name)))
                           (user-mail-address
                            ,(or (cdr address) user-mail-address)))
index ed5cd3a..7358bd6 100644 (file)
@@ -1498,7 +1498,7 @@ newsgroup."
                  gnus-activate-foreign-newsgroups)
                 (t 0))
           level))
-        info group active method retrievegroups)
+        scanned-methods info group active method retrievegroups)
     (gnus-message 5 "Checking new news...")
 
     (while newsrc
@@ -1542,7 +1542,10 @@ newsgroup."
                  (setcdr (assoc method retrievegroups)
                          (cons group (cdr (assoc method retrievegroups))))
                (push (list method group) retrievegroups))
-         (setq active (gnus-activate-group group 'scan))
+           (if (member method scanned-methods)
+               (setq active (gnus-activate-group group))
+             (setq active (gnus-activate-group group 'scan))
+             (push method scanned-methods))
            (inline (gnus-close-group group))))))
 
       ;; Get the number of unread articles in the group.
index dfc7dd9..2e9f183 100644 (file)
@@ -849,6 +849,17 @@ This variable uses the same syntax as `gnus-emphasis-alist'."
                                             gnus-emphasis-highlight-words)))))
   :group 'gnus-summary-visual)
 
+(defcustom gnus-summary-show-article-charset-alist
+  nil
+  "Alist of number and charset.
+The article will be shown with the charset corresponding to the
+numbered argument.
+For example: ((1 . cn-gb-2312) (2 . big5))."
+  :type '(repeat (cons (number :tag "Argument" 1)
+                      (symbol :tag "Charset")))
+  :group 'gnus-charset)
+
+
 ;;; Internal variables
 
 (defvar gnus-article-mime-handles nil)
@@ -6801,8 +6812,14 @@ to guess what the document format is."
                           (list (cons 'save-article-group ogroup))))
           (case-fold-search t)
           (buf (current-buffer))
-          dig)
+          dig to-address)
       (save-excursion
+       (set-buffer gnus-original-article-buffer)
+       ;; Have the digest group inherit the main mail address of
+       ;; the parent article.
+       (when (setq to-address (or (message-fetch-field "reply-to")
+                                  (message-fetch-field "from")))
+         (setq params (append (list (cons 'to-address to-address)))))
        (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
@@ -7110,12 +7127,23 @@ to save in."
 
 (defun gnus-summary-show-article (&optional arg)
   "Force re-fetching of the current article.
-If ARG (the prefix) is non-nil, show the raw article without any
-article massaging functions being run."
+If ARG (the prefix) is a number, show the article with the charset 
+defined in `gnus-summary-show-article-charset-alist', or the charset
+inputed.
+If ARG (the prefix) is non-nil and not a number, show the raw article 
+without any article massaging functions being run."
   (interactive "P")
-  (if (not arg)
-      ;; Select the article the normal way.
-      (gnus-summary-select-article nil 'force)
+  (cond 
+   ((numberp arg)
+    (let ((gnus-newsgroup-charset 
+          (or (cdr (assq arg gnus-summary-show-article-charset-alist))
+              (read-coding-system "Charset: ")))
+         (gnus-newsgroup-ignored-charsets 'gnus-all))
+      (gnus-summary-select-article nil 'force)))
+   ((not arg)
+    ;; Select the article the normal way.
+    (gnus-summary-select-article nil 'force))
+   (t
     ;; We have to require this here to make sure that the following
     ;; dynamic binding isn't shadowed by autoloading.
     (require 'gnus-async)
@@ -7125,14 +7153,13 @@ article massaging functions being run."
          gnus-article-prepare-hook
          gnus-article-decode-hook
          gnus-display-mime-function
-         gnus-break-pages
-         gnus-visual)
+         gnus-break-pages)
       ;; Destroy any MIME parts.
       (when (gnus-buffer-live-p gnus-article-buffer)
        (save-excursion
          (set-buffer gnus-article-buffer)
          (mm-destroy-parts gnus-article-mime-handles)))
-      (gnus-summary-select-article nil 'force)))
+      (gnus-summary-select-article nil 'force))))
   (gnus-summary-goto-subject gnus-current-article)
   (gnus-summary-position-point))
 
@@ -9375,10 +9402,9 @@ If REVERSE, save parts that do not match TYPE."
     (setq gnus-newsgroup-charset
          (or gnus-newsgroup-ephemeral-charset
              (and gnus-newsgroup-name
-                  (or (gnus-group-find-parameter gnus-newsgroup-name
-                                                 'charset)
+                  (or (gnus-group-find-parameter gnus-newsgroup-name 'charset)
                       (let ((alist gnus-group-charset-alist)
-                            elem (charset nil))
+                            elem charset)
                         (while (setq elem (pop alist))
                           (when (and name
                                      (string-match (car elem) name))
index b68af25..72845ef 100644 (file)
@@ -1210,7 +1210,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
        (gnus-inhibit-treatment t)
        has-been-begin article result-file result-files process-state
        gnus-summary-display-article-function
-       gnus-article-prepare-hook
+       gnus-article-prepare-hook gnus-display-mime-function
        article-series files)
 
     (while (and articles
index 057b9b0..c9d9050 100644 (file)
@@ -260,10 +260,10 @@ is restarted, and sometimes reloaded."
   :link '(custom-manual "(gnus)Exiting Gnus")
   :group 'gnus)
 
-(defconst gnus-version-number "0.99"
+(defconst gnus-version-number "5.8.2"
   "Version number for this version of Gnus.")
 
-(defconst gnus-version (format "Pterodactyl Gnus v%s" gnus-version-number)
+(defconst gnus-version (format "Gnus v%s" gnus-version-number)
   "Version string for this version of Gnus.")
 
 (defcustom gnus-inhibit-startup-message nil
@@ -2743,6 +2743,8 @@ If NEWSGROUP is nil, return the global kill file name instead."
   (or gnus-override-method
       (and (not group)
           gnus-select-method)
+      (and (not (gnus-group-entry group)) ;; a new group
+          (gnus-group-name-to-method group))
       (let ((info (or info (gnus-get-info group)))
            method)
        (if (or (not info)
index 96cbc14..8d73bc6 100644 (file)
@@ -55,7 +55,7 @@ This variable is a list of mail source specifiers."
   :group 'mail-source
   :type 'integer)
 
-(defcustom mail-source-delete-incoming nil
+(defcustom mail-source-delete-incoming t
   "*If non-nil, delete incoming files after handling."
   :group 'mail-source
   :type 'boolean)
@@ -66,6 +66,11 @@ This variable is a list of mail source specifiers."
   "A dynamically bound string that says what the current mail source is.")
 
 (eval-and-compile
+  (defvar mail-source-common-keyword-map
+    '((:plugged))
+    "Mapping from keywords to default values.
+Common keywords should be listed here.")
+
   (defvar mail-source-keyword-map
     '((file
        (:prescript)
@@ -100,7 +105,7 @@ This variable is a list of mail source specifiers."
        (:password)
        (:mailbox "INBOX")
        (:predicate "UNSEEN UNDELETED")
-       (:fetchflag "\Deleted")
+       (:fetchflag "\\Deleted")
        (:dontexpunge))
       (webmail
        (:subtype hotmail)
@@ -121,6 +126,8 @@ All keywords that can be used must be listed here."))
 
 (defvar mail-source-password-cache nil)
 
+(defvar mail-source-plugged t)
+
 ;;; Functions
 
 (eval-and-compile
@@ -168,6 +175,39 @@ the `mail-source-keyword-map' variable."
               (mail-source-value value)
             (mail-source-value (cadr default)))))))
 
+(eval-and-compile
+  (defun mail-source-bind-common-1 ()
+    (let* ((defaults mail-source-common-keyword-map)
+          default bind)
+      (while (setq default (pop defaults))
+       (push (list (mail-source-strip-keyword (car default))
+                   nil)
+             bind))
+      bind)))
+
+(defun mail-source-set-common-1 (source)
+  (let* ((type (pop source))
+        (defaults mail-source-common-keyword-map)
+        (defaults-1 (cdr (assq type mail-source-keyword-map)))
+        default value keyword)
+    (while (setq default (pop defaults))
+      (set (mail-source-strip-keyword (setq keyword (car default)))
+          (if (setq value (plist-get source keyword))
+              (mail-source-value value)
+            (if (setq value (assq  keyword defaults-1))
+                (mail-source-value (cadr value))
+              (mail-source-value (cadr default))))))))
+
+(defmacro mail-source-bind-common (source &rest body)
+  "Return a `let' form that binds all common variables.
+See `mail-source-bind'."
+  `(let ,(mail-source-bind-common-1)
+     (mail-source-set-common-1 source)
+     ,@body))
+
+(put 'mail-source-bind-common 'lisp-indent-function 1)
+(put 'mail-source-bind-common 'edebug-form-spec '(form body))
+
 (defun mail-source-value (value)
   "Return the value of VALUE."
   (cond
@@ -187,24 +227,26 @@ the `mail-source-keyword-map' variable."
 CALLBACK will be called with the name of the file where (some of)
 the mail from SOURCE is put.
 Return the number of files that were found."
-  (save-excursion
-    (let ((function (cadr (assq (car source) mail-source-fetcher-alist)))
-         (found 0))
-      (unless function
-       (error "%S is an invalid mail source specification" source))
-      ;; If there's anything in the crash box, we do it first.
-      (when (file-exists-p mail-source-crash-box)
-       (message "Processing mail from %s..." mail-source-crash-box)
-       (setq found (mail-source-callback
-                     callback mail-source-crash-box)))
-      (+ found
-         (condition-case err
-             (funcall function source callback)
-           (error
-            (unless (yes-or-no-p
-                    (format "Mail source error (%s).  Continue? " err))
-              (error "Cannot get new mail."))
-            0))))))
+  (mail-source-bind-common source
+    (if (or mail-source-plugged plugged)
+       (save-excursion
+         (let ((function (cadr (assq (car source) mail-source-fetcher-alist)))
+               (found 0))
+           (unless function
+             (error "%S is an invalid mail source specification" source))
+           ;; If there's anything in the crash box, we do it first.
+           (when (file-exists-p mail-source-crash-box)
+             (message "Processing mail from %s..." mail-source-crash-box)
+             (setq found (mail-source-callback
+                          callback mail-source-crash-box)))
+           (+ found
+              (condition-case err
+                  (funcall function source callback)
+                (error
+                 (unless (yes-or-no-p
+                          (format "Mail source error (%s).  Continue? " err))
+                   (error "Cannot get new mail."))
+                 0))))))))
 
 (defun mail-source-make-complex-temp-name (prefix)
   (let ((newname (make-temp-name prefix))
@@ -439,7 +481,7 @@ If ARGS, PROMPT is used as an argument to `format'."
     (let ((found 0)
          (mail-source-string (format "maildir:%s" path)))
       (dolist (file (directory-files path t))
-       (when (and (file-regular-p file)
+       (when (and (not (file-directory-p file))
                   (not (if function
                            (funcall function file mail-source-crash-box)
                          (rename-file file mail-source-crash-box))))
index 4929c84..a0642c1 100644 (file)
@@ -384,10 +384,9 @@ always query the user whether to use the value.  If it is the symbol
                 (const use)
                 (const ask)))
 
-;; stuff relating to broken sendmail in MMDF
 (defcustom message-sendmail-f-is-evil nil
-  "*Non-nil means that \"-f username\" should not be added to the sendmail
-command line, because it is even more evil than leaving it out."
+  "*Non-nil means that \"-f username\" should not be added to the sendmail command line.
+Doing so would be even more evil than leaving it out."
   :group 'message-sending
   :type 'boolean)
 
@@ -407,6 +406,11 @@ might set this variable to '(\"-f\" \"you@some.where\")."
   :group 'message-sending
   :type '(repeat string))
 
+(defvar message-cater-to-broken-inn t
+  "Non-nil means Gnus should not fold the `References' header.
+Folding `References' makes ancient versions of INN create incorrect
+NOV lines.")
+
 (defvar gnus-post-method)
 (defvar gnus-select-method)
 (defcustom message-post-method
@@ -1300,7 +1304,7 @@ Point is left at the beginning of the narrowed-to region."
   (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups)
 
   (define-key message-mode-map "\C-c\C-y" 'message-yank-original)
-  (define-key message-mode-map "\C-c\C-Y" 'message-yank-buffer)
+  (define-key message-mode-map "\C-c\M-\C-y" 'message-yank-buffer)
   (define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message)
   (define-key message-mode-map "\C-c\C-w" 'message-insert-signature)
   (define-key message-mode-map "\C-c\M-h" 'message-insert-headers)
@@ -2173,7 +2177,7 @@ the user from the mailer."
 (defun message-send-mail-with-sendmail ()
   "Send off the prepared buffer with sendmail."
   (let ((errbuf (if message-interactive
-                   (generate-new-buffer " sendmail errors")
+                   (message-generate-new-buffer-clone-locals " sendmail errors")
                  0))
        resend-to-addresses delimline)
     (let ((case-fold-search t))
@@ -2210,7 +2214,10 @@ the user from the mailer."
                     ;; But some systems are more broken with -f, so
                     ;; we'll let users override this.
                     (if (null message-sendmail-f-is-evil)
-                        (list "-f" (user-login-name)))
+                        (list "-f"
+                              (if (null user-mail-address)
+                                  (user-login-name)
+                                user-mail-address)))
                     ;; These mean "report errors by mail"
                     ;; and "deliver in background".
                     (if (null message-interactive) '("-oem" "-odb"))
@@ -3175,7 +3182,7 @@ Headers already prepared in the buffer are not modified."
 
 (defun message-fill-header (header value)
   (let ((begin (point))
-       (fill-column 990)
+       (fill-column 78)
        (fill-prefix "\t"))
     (insert (capitalize (symbol-name header))
            ": "
@@ -3194,23 +3201,60 @@ Headers already prepared in the buffer are not modified."
        (replace-match " " t t))
       (goto-char (point-max)))))
 
+(defun message-shorten-1 (list cut surplus)
+  ;; Cut SURPLUS elements out of LIST, beginning with CUTth one.
+  (setcdr (nthcdr (- cut 2) list)
+         (nthcdr (+ (- cut 2) surplus 1) list)))
+
 (defun message-shorten-references (header references)
-  "Limit REFERENCES to be shorter than 988 characters."
-  (let ((max 988)
-       (cut 4)
+  "Trim REFERENCES to be less than 31 Message-ID long, and fold them.
+If folding is disallowed, also check that the REFERENCES are less
+than 988 characters long, and if they are not, trim them until they are."
+  (let ((maxcount 31)
+       (count 0)
+       (cut 6)
        refs)
     (with-temp-buffer
       (insert references)
       (goto-char (point-min))
+      ;; Cons a list of valid references.
       (while (re-search-forward "<[^>]+>" nil t)
        (push (match-string 0) refs))
-      (setq refs (nreverse refs))
-      (while (> (length (mapconcat 'identity refs " ")) max)
-       (when (< (length refs) (1+ cut))
-         (decf cut))
-       (setcdr (nthcdr cut refs) (cddr (nthcdr cut refs)))))
-    (insert (capitalize (symbol-name header)) ": "
-           (mapconcat 'identity refs " ") "\n")))
+      (setq refs (nreverse refs)
+           count (length refs)))
+
+    ;; If the list has more than MAXCOUNT elements, trim it by
+    ;; removing the CUTth element and the required number of
+    ;; elements that follow.
+    (when (> count maxcount)
+      (let ((surplus (- count maxcount)))
+       (message-shorten-1 refs cut surplus)
+       (decf count surplus)))
+
+    ;; If folding is disallowed, make sure the total length (including
+    ;; the spaces between) will be less than MAXSIZE characters.
+    (when message-cater-to-broken-inn
+      (let ((maxsize 988)
+           (totalsize (+ (apply #'+ (mapcar #'length refs))
+                         (1- count)))
+           (surplus 0)
+           (ptr (nthcdr (1- cut) refs)))
+       ;; Decide how many elements to cut off...
+       (while (> totalsize maxsize)
+         (decf totalsize (1+ (length (car ptr))))
+         (incf surplus)
+         (setq ptr (cdr ptr)))
+       ;; ...and do it.
+       (when (> surplus 0)
+         (message-shorten-1 refs cut surplus))))
+
+    ;; Finally, collect the references back into a string and insert
+    ;; it into the buffer.
+    (let ((refstring (mapconcat #'identity refs " ")))
+      (if message-cater-to-broken-inn
+         (insert (capitalize (symbol-name header)) ": "
+                 refstring "\n")
+       (message-fill-header header refstring)))))
 
 (defun message-position-point ()
   "Move point to where the user probably wants to find it."
@@ -4138,20 +4182,22 @@ regexp varstr."
   (let ((oldbuf (current-buffer)))
     (save-excursion
       (set-buffer (generate-new-buffer name))
-      (message-clone-locals oldbuf)
+      (message-clone-locals oldbuf varstr)
       (current-buffer))))
 
-(defun message-clone-locals (buffer)
+(defun message-clone-locals (buffer &optional varstr)
   "Clone the local variables from BUFFER to the current buffer."
   (let ((locals (save-excursion
                  (set-buffer buffer)
                  (buffer-local-variables)))
-       (regexp "^gnus\\|^nn\\|^message"))
+       (regexp "^gnus\\|^nn\\|^message\\|^user-mail-address"))
     (mapcar
      (lambda (local)
        (when (and (consp local)
                  (car local)
-                 (string-match regexp (symbol-name (car local))))
+                 (string-match regexp (symbol-name (car local)))
+                 (or (null varstr)
+                     (string-match varstr (symbol-name (car local)))))
         (ignore-errors
           (set (make-local-variable (car local))
                (cdr local)))))
@@ -4197,7 +4243,7 @@ regexp varstr."
                (delete-char 1)
              (search-forward "\n\n")
              (setq lines (buffer-substring (point-min) (1- (point))))
-             (delete-region (point-min)  (point))))))
+             (delete-region (point-min) (point))))))
       (save-restriction
        (message-narrow-to-headers-or-head)
        (message-remove-header "Mime-Version")
index ad7bbeb..64bcac3 100644 (file)
@@ -95,7 +95,7 @@ If no encoding was done, nil is returned."
                (setq start nil)))
            charset)))))))
 
-(defun mm-body-encoding (charset)
+(defun mm-body-encoding (charset &optional encoding)
   "Do Content-Transfer-Encoding and return the encoding of the current buffer."
   (let ((bits (mm-body-7-or-8)))
     (cond
@@ -104,7 +104,8 @@ If no encoding was done, nil is returned."
      ((eq charset mail-parse-charset)
       bits)
      (t
-      (let ((encoding (or (cdr (assq charset mm-body-charset-encoding-alist))
+      (let ((encoding (or encoding
+                         (cdr (assq charset mm-body-charset-encoding-alist))
                          (mm-qp-or-base64))))
        (mm-encode-content-transfer-encoding encoding "text/plain")
        encoding)))))
@@ -179,15 +180,22 @@ If no encoding was done, nil is returned."
 The characters in CHARSET should then be decoded."
   (if (stringp charset)
     (setq charset (intern (downcase charset))))
-  (if (or (not charset) (memq charset mail-parse-ignored-charsets))
+  (if (or (not charset) 
+         (eq 'gnus-all mail-parse-ignored-charsets)
+         (memq 'gnus-all mail-parse-ignored-charsets)
+         (memq charset mail-parse-ignored-charsets))
       (setq charset mail-parse-charset))
   (save-excursion
     (when encoding
       (mm-decode-content-transfer-encoding encoding type))
     (when (featurep 'mule)
-      (let (mule-charset)
-       (when (and charset
-                  (setq mule-charset (mm-charset-to-coding-system charset))
+      (let ((mule-charset (mm-charset-to-coding-system charset)))
+       (if (and (not mule-charset)
+                (listp mail-parse-ignored-charsets)
+                (memq 'gnus-unknown mail-parse-ignored-charsets))
+           (setq mule-charset 
+                 (mm-charset-to-coding-system mail-parse-charset)))
+       (when (and charset mule-charset
                   ;; buffer-file-coding-system
                   ;;Article buffer is nil coding system
                   ;;in XEmacs
@@ -201,13 +209,20 @@ The characters in CHARSET should then be decoded."
   "Decode STRING with CHARSET."
   (if (stringp charset)
     (setq charset (intern (downcase charset))))
-  (if (or (not charset) (memq charset mail-parse-ignored-charsets))
+  (if (or (not charset) 
+         (eq 'gnus-all mail-parse-ignored-charsets)
+         (memq 'gnus-all mail-parse-ignored-charsets)
+         (memq charset mail-parse-ignored-charsets))
       (setq charset mail-parse-charset))
   (or
    (when (featurep 'mule)
-     (let (mule-charset)
-       (when (and charset
-                 (setq mule-charset (mm-charset-to-coding-system charset))
+      (let ((mule-charset (mm-charset-to-coding-system charset)))
+       (if (and (not mule-charset)
+                (listp mail-parse-ignored-charsets)
+                (memq 'gnus-unknown mail-parse-ignored-charsets))
+           (setq mule-charset 
+                 (mm-charset-to-coding-system mail-parse-charset)))
+       (when (and charset mule-charset
                  (mm-multibyte-p)
                  (or (not (eq mule-charset 'ascii))
                      (setq mule-charset mail-parse-charset)))
index a23a7f6..8006fec 100644 (file)
@@ -271,6 +271,24 @@ See also `with-temp-file' and `with-output-to-string'."
 (put 'mm-with-unibyte-buffer 'lisp-indent-function 0)
 (put 'mm-with-unibyte-buffer 'edebug-form-spec '(body))
 
+(defmacro mm-with-unibyte-current-buffer (&rest forms)
+  "Evaluate FORMS there like `progn' in current buffer."
+  (let ((multibyte (make-symbol "multibyte")))
+    `(if (or (string-match "XEmacs\\|Lucid" emacs-version)
+            (not (fboundp 'set-buffer-multibyte)))
+        (progn
+          ,@forms)
+       (let ((,multibyte (default-value 'enable-multibyte-characters)))
+        (unwind-protect
+            (let ((buffer-file-coding-system mm-binary-coding-system)
+                  (coding-system-for-read mm-binary-coding-system)
+                  (coding-system-for-write mm-binary-coding-system))
+              (set-buffer-multibyte nil)
+              ,@forms)
+          (set-buffer-multibyte ,multibyte))))))
+(put 'mm-with-unibyte-current-buffer 'lisp-indent-function 0)
+(put 'mm-with-unibyte-current-buffer 'edebug-form-spec '(body))
+
 (defun mm-find-charset-region (b e)
   "Return a list of charsets in the region."
   (cond
index 25c6773..908fa8a 100644 (file)
        (charset (mail-content-type-get
                  (mm-handle-type handle) 'charset))
        gnus-displaying-mime handles)
+    (when (and charset
+              (stringp charset))
+      (setq charset (intern (downcase charset)))
+      (when (eq charset 'us-ascii)
+       (setq charset nil)))
     (save-excursion
       (save-restriction
        (narrow-to-region b b)
        (mm-insert-part handle)
        (let (gnus-article-mime-handles
-             (gnus-newsgroup-charset (or charset gnus-newsgroup-charset)))
+             (gnus-newsgroup-charset
+              (or charset gnus-newsgroup-charset)))
          (run-hooks 'gnus-article-decode-hook)
          (gnus-article-prepare-display)
          (setq handles gnus-article-mime-handles))
index e84e955..9203465 100644 (file)
@@ -241,7 +241,8 @@ called for this message.")
                  (delete-region (+ (match-beginning 0) 2)
                                 (+ (match-beginning 0) 3))))))
            (setq charset (mm-encode-body))
-           (setq encoding (mm-body-encoding charset))
+           (setq encoding (mm-body-encoding charset 
+                                            (cdr (assq 'encoding cont))))
            (setq coded (buffer-string)))
        (mm-with-unibyte-buffer
          (cond
@@ -300,7 +301,6 @@ called for this message.")
         (let ((mml-boundary (mml-compute-boundary cont)))
           (insert (format "Content-Type: multipart/%s; boundary=\"%s\"\n"
                           type mml-boundary))
-          (insert "\n")
           (setq cont (cddr cont))
           (while cont
             (insert "\n--" mml-boundary "\n")
@@ -654,7 +654,14 @@ called for this message.")
        (when (string-match "[\"\\~/* \t\n]" value)
          (setq value (prin1-to-string value)))
        (insert (format " %s=%s" key value)))))
-  (insert ">\n<#/" name ">\n"))
+  (insert ">\n"))
+
+(defun mml-insert-empty-tag (name &rest plist)
+  "Insert an empty MML tag described by NAME and PLIST."
+  (when (symbolp name)
+    (setq name (symbol-name name)))
+  (apply #'mml-insert-tag name plist)
+  (insert "<#/" name ">\n"))
 
 ;;; Attachment functions.
 
@@ -671,8 +678,8 @@ description of the attachment."
          (type (mml-minibuffer-read-type file))
          (description (mml-minibuffer-read-description)))
      (list file type description)))
-  (mml-insert-tag 'part 'type type 'filename file 'disposition "attachment"
-                 'description description))
+  (mml-insert-empty-tag 'part 'type type 'filename file
+                       'disposition "attachment" 'description description))
 
 (defun mml-attach-buffer (buffer &optional type description)
   "Attach a buffer to the outgoing MIME message.
@@ -682,8 +689,8 @@ See `mml-attach-file' for details of operation."
          (type (mml-minibuffer-read-type buffer "text/plain"))
          (description (mml-minibuffer-read-description)))
      (list buffer type description)))
-  (mml-insert-tag 'part 'type type 'buffer buffer 'disposition "attachment"
-                 'description description))
+  (mml-insert-empty-tag 'part 'type type 'buffer buffer
+                       'disposition "attachment" 'description description))
 
 (defun mml-attach-external (file &optional type description)
   "Attach an external file into the buffer.
@@ -694,8 +701,8 @@ TYPE is the MIME type to use."
          (type (mml-minibuffer-read-type file))
          (description (mml-minibuffer-read-description)))
      (list file type description)))
-  (mml-insert-tag 'external 'type type 'name file 'disposition "attachment"
-                 'description description))
+  (mml-insert-empty-tag 'external 'type type 'name file
+                       'disposition "attachment" 'description description))
 
 (defun mml-insert-multipart (&optional type)
   (interactive (list (completing-read "Multipart type (default mixed): "
@@ -704,7 +711,7 @@ TYPE is the MIME type to use."
                     nil nil "mixed")))
   (or type
       (setq type "mixed"))
-  (mml-insert-tag "multipart" 'type type)
+  (mml-insert-empty-tag "multipart" 'type type)
   (forward-line -1))
 
 (defun mml-preview (&optional raw)
index 783d8d0..c1bbb10 100644 (file)
@@ -184,11 +184,13 @@ If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.")
          (if (numberp article)
              (cons nnfolder-current-group article)
            (goto-char (point-min))
-           (search-forward (concat "\n" nnfolder-article-marker))
            (cons nnfolder-current-group
-                 (string-to-int
-                  (buffer-substring
-                   (point) (progn (end-of-line) (point)))))))))))
+                 (if (search-forward (concat "\n" nnfolder-article-marker) 
+                                     nil t)
+                     (string-to-int
+                      (buffer-substring
+                       (point) (progn (end-of-line) (point))))
+                   -1))))))))
 
 (deffoo nnfolder-request-group (group &optional server dont-check)
   (nnfolder-possibly-change-group group server t)
index 0224709..0adde1f 100644 (file)
@@ -60,7 +60,7 @@
 
 (defvoo nnmh-status-string "")
 (defvoo nnmh-group-alist nil)
-(defvoo nnmh-allow-delete-final nil)
+(defvar nnmh-allow-delete-final nil)
 
 \f
 
index c28e35c..fbf1509 100644 (file)
 
 (deffoo nnslashdot-retrieve-headers (articles &optional group server fetch-old)
   (nnslashdot-possibly-change-server group server)
-  (unless gnus-nov-is-evil
-    (if nnslashdot-threaded
-       (nnslashdot-threaded-retrieve-headers articles group)
-      (nnslashdot-sane-retrieve-headers articles group))))
+  (condition-case why
+      (unless gnus-nov-is-evil
+        (if nnslashdot-threaded
+            (nnslashdot-threaded-retrieve-headers articles group)
+          (nnslashdot-sane-retrieve-headers articles group)))
+    (search-failed (nnslashdot-lose why))))
   
 (deffoo nnslashdot-threaded-retrieve-headers (articles group)
   (let ((last (car (last articles)))
 (deffoo nnslashdot-request-article (article &optional group server buffer)
   (nnslashdot-possibly-change-server group server)
   (let (contents)
-    (save-excursion
-      (set-buffer nnslashdot-buffer)
-      (let ((case-fold-search t))
-       (goto-char (point-min))
-       (when (and (stringp article)
-                  (string-match "%\\([0-9]+\\)@" article))
-         (setq article (string-to-number (match-string 1 article))))
-       (when (numberp article)
-         (if (= article 1)
-             (progn
-               (re-search-forward "Posted by .* on ")
-               (forward-line 1)
+    (condition-case why
+       (save-excursion
+         (set-buffer nnslashdot-buffer)
+         (let ((case-fold-search t))
+           (goto-char (point-min))
+           (when (and (stringp article)
+                      (string-match "%\\([0-9]+\\)@" article))
+             (setq article (string-to-number (match-string 1 article))))
+           (when (numberp article)
+             (if (= article 1)
+                 (progn
+                   (re-search-forward "Posted by .* on ")
+                   (forward-line 1)
+                   (setq contents
+                         (buffer-substring
+                          (point)
+                          (progn
+                            (re-search-forward
+                             "<p>.*A href=http://slashdot.org/article.pl")
+                            (match-beginning 0)))))
+               (search-forward (format "<a name=\"%d\">" (1- article)))
                (setq contents
                      (buffer-substring
-                      (point)
-                      (progn
-                        (re-search-forward
-                         "<p>.*A href=http://slashdot.org/article.pl")
-                        (match-beginning 0)))))
-           (search-forward (format "<a name=\"%d\">" (1- article)))
-           (setq contents
-                 (buffer-substring
-                  (re-search-forward "<td[^>]+>")
-                  (search-forward "</td>")))))))
+                      (re-search-forward "<td[^>]+>")
+                      (search-forward "</td>")))))))
+      (search-failed (nnslashdot-lose why)))
+
     (when contents
       (save-excursion
        (set-buffer (or buffer nntp-server-buffer))
   (nnslashdot-possibly-change-server nil server)
   (let ((number 0)
        sid elem description articles gname)
-    ;; First we do the Ultramode to get info on all the latest groups.
-    (with-temp-buffer
-      (nnweb-insert "http://slashdot.org/slashdot.xml")
-      (goto-char (point-min))
-      (while (search-forward "<story>" nil t)
-       (narrow-to-region (point) (search-forward "</story>"))
-       (goto-char (point-min))
-       (re-search-forward "<title>\\([^<]+\\)</title>")
-       (setq description (match-string 1))
-       (re-search-forward "<url>\\([^<]+\\)</url>")
-       (setq sid (match-string 1))
-       (string-match "/\\([0-9/]+\\).shtml" sid)
-       (setq sid (match-string 1 sid))
-       (re-search-forward "<comments>\\([^<]+\\)</comments>")
-       (setq articles (string-to-number (match-string 1)))
-       (setq gname (concat description " (" sid ")"))
-       (if (setq elem (assoc gname nnslashdot-groups))
-           (setcar (cdr elem) articles)
-         (push (list gname articles sid) nnslashdot-groups))
-       (goto-char (point-max))
-       (widen)))
-    ;; Then do the older groups.
-    (while (> (- nnslashdot-group-number number) 0)
-      (with-temp-buffer
-       (let ((case-fold-search t))
-         (nnweb-insert (format nnslashdot-active-url number))
-         (goto-char (point-min))
-         (while (re-search-forward
-                 "article.pl\\?sid=\\([^&]+\\).*<b>\\([^<]+\\)</b>" nil t)
-           (setq sid (match-string 1)
-                 description (match-string 2))
-           (forward-line 1)
-           (when (re-search-forward "<b>\\([0-9]+\\)</b>" nil t)
-             (setq articles (string-to-number (match-string 1))))
-           (setq gname (concat description " (" sid ")"))
-           (if (setq elem (assoc gname nnslashdot-groups))
-               (setcar (cdr elem) articles)
-             (push (list gname articles sid) nnslashdot-groups)))))
-      (incf number 30))
+    (condition-case why
+        ;; First we do the Ultramode to get info on all the latest groups.
+        (mm-with-unibyte-buffer
+          (nnweb-insert "http://slashdot.org/slashdot.xml")
+          (goto-char (point-min))
+          (while (search-forward "<story>" nil t)
+            (narrow-to-region (point) (search-forward "</story>"))
+            (goto-char (point-min))
+            (re-search-forward "<title>\\([^<]+\\)</title>")
+            (setq description (match-string 1))
+            (re-search-forward "<url>\\([^<]+\\)</url>")
+            (setq sid (match-string 1))
+            (string-match "/\\([0-9/]+\\).shtml" sid)
+            (setq sid (match-string 1 sid))
+            (re-search-forward "<comments>\\([^<]+\\)</comments>")
+            (setq articles (string-to-number (match-string 1)))
+            (setq gname (concat description " (" sid ")"))
+            (if (setq elem (assoc gname nnslashdot-groups))
+                (setcar (cdr elem) articles)
+              (push (list gname articles sid) nnslashdot-groups))
+            (goto-char (point-max))
+            (widen)))
+      ;; Then do the older groups.
+      (while (> (- nnslashdot-group-number number) 0)
+        (mm-with-unibyte-buffer
+          (let ((case-fold-search t))
+            (nnweb-insert (format nnslashdot-active-url number))
+            (goto-char (point-min))
+            (while (re-search-forward
+                    "article.pl\\?sid=\\([^&]+\\).*<b>\\([^<]+\\)</b>" nil t)
+              (setq sid (match-string 1)
+                    description (match-string 2))
+              (forward-line 1)
+              (when (re-search-forward "<b>\\([0-9]+\\)</b>" nil t)
+                (setq articles (string-to-number (match-string 1))))
+              (setq gname (concat description " (" sid ")"))
+              (if (setq elem (assoc gname nnslashdot-groups))
+                  (setcar (cdr elem) articles)
+                (push (list gname articles sid) nnslashdot-groups)))))
+        (incf number 30))
+      (search-failed (nnslashdot-lose why)))
     (nnslashdot-write-groups)
     (nnslashdot-generate-active)
     t))
-
+  
 (deffoo nnslashdot-request-newgroups (date &optional server)
   (nnslashdot-possibly-change-server nil server)
   (nnslashdot-generate-active)
          (insert "</blockquote>\n")
          (setq quoted nil)))
       (forward-line 1))
+    (goto-char (point-min))
+    (while (re-search-forward "^ *\n" nil t)
+      (replace-match "<p>\n"))
     (widen)
     (when (message-goto-signature)
       (forward-line -1)
 (defun nnslashdot-read-groups ()
   (let ((file (expand-file-name "groups" nnslashdot-directory)))
     (when (file-exists-p file)
-      (with-temp-buffer
+      (mm-with-unibyte-buffer
        (insert-file-contents file)
        (goto-char (point-min))
        (setq nnslashdot-groups (read (current-buffer)))))))
       (insert (prin1-to-string (car elem))
              " " (number-to-string (cadr elem)) " 1 y\n"))))
 
+(defun nnslashdot-lose (why)
+  (error "Slashdot HTML has changed; please get a new version of nnslashdot"))
+
 (provide 'nnslashdot)
 
 ;;; nnslashdot.el ends here
index 39c3dc5..b3ed322 100644 (file)
@@ -495,6 +495,7 @@ noticing asynchronous data.")
            (received 0)
            (last-point (point-min))
            (nntp-inhibit-erase t)
+           (buf (nntp-find-connection-buffer nntp-server-buffer))
            (command (if nntp-server-list-active-group "LIST ACTIVE" "GROUP")))
        (while groups
          ;; Send the command to the server.
@@ -506,6 +507,9 @@ noticing asynchronous data.")
                    (zerop (% count nntp-maximum-request)))
            (nntp-accept-response)
            (while (progn
+                    ;; Search `blue moon' in this file for the
+                    ;; reason why set-buffer here.
+                    (set-buffer buf)
                     (goto-char last-point)
                     ;; Count replies.
                     (while (re-search-forward "^[0-9]" nil t)
@@ -515,10 +519,12 @@ noticing asynchronous data.")
              (nntp-accept-response))))
 
        ;; Wait for the reply from the final command.
+       (set-buffer buf)
        (goto-char (point-max))
        (re-search-backward "^[0-9]" nil t)
        (when (looking-at "^[23]")
          (while (progn
+                  (set-buffer buf)
                   (goto-char (point-max))
                   (if (not nntp-server-list-active-group)
                       (not (re-search-backward "\r?\n" (- (point) 3) t))
@@ -526,6 +532,7 @@ noticing asynchronous data.")
            (nntp-accept-response)))
 
        ;; Now all replies are received.  We remove CRs.
+       (set-buffer buf)
        (goto-char (point-min))
        (while (search-forward "\r" nil t)
          (replace-match "" t t))
index b2ff2bf..b1962ac 100644 (file)
            (set-buffer nntp-server-buffer)
            (erase-buffer))
        (setq nnultimate-articles nil)
-       (with-temp-buffer
+       (mm-with-unibyte-buffer
          (dolist (elem fetchers)
            (setq pages 1
                  current-page 1
        (setq nnultimate-headers (sort headers 'car-less-than-car))
        (save-excursion
          (set-buffer nntp-server-buffer)
-         (erase-buffer)
-         (dolist (header nnultimate-headers)
-           (nnheader-insert-nov (cdr header)))))
+         (mm-with-unibyte-current-buffer
+           (erase-buffer)
+           (dolist (header nnultimate-headers)
+             (nnheader-insert-nov (cdr header))))))
       'nov)))
 
 (deffoo nnultimate-request-group (group &optional server dont-check)
        (goto-char (point-min))
        (insert "Content-Type: text/html\nMIME-Version: 1.0\n")
        (let ((header (cdr (assq article nnultimate-headers))))
-         (nnheader-insert-header header))
+         (mm-with-unibyte-current-buffer
+           (nnheader-insert-header header)))
        (nnheader-report 'nnultimate "Fetched article %s" article)
        (cons group article)))))
 
 (deffoo nnultimate-request-list (&optional server)
   (nnultimate-possibly-change-server nil server)
-  (with-temp-buffer
+  (mm-with-unibyte-buffer
     (nnweb-insert
      (if (string-match "/$" nnultimate-address)
         (concat nnultimate-address "Ultimate.cgi")
         (furls (list (concat nnultimate-address (format furl sid))))
         contents forum-contents furl-fetched a subject href
         garticles topic tinfo old-max inc parse)
-    (with-temp-buffer
+    (mm-with-unibyte-buffer
       (while furls
        (erase-buffer)
        (nnweb-insert (pop furls))
   (setq nnultimate-groups-alist nil)
   (let ((file (expand-file-name "groups" nnultimate-directory)))
     (when (file-exists-p file)
-      (with-temp-buffer
+      (mm-with-unibyte-buffer
        (insert-file-contents file)
        (goto-char (point-min))
        (setq nnultimate-groups-alist (read (current-buffer)))))))
index 9d855f9..875853a 100644 (file)
@@ -113,9 +113,10 @@ and `altavista'.")
     (set-buffer nntp-server-buffer)
     (erase-buffer)
     (let (article header)
-      (while (setq article (pop articles))
-       (when (setq header (cadr (assq article nnweb-articles)))
-         (nnheader-insert-nov header)))
+      (mm-with-unibyte-current-buffer
+       (while (setq article (pop articles))
+         (when (setq header (cadr (assq article nnweb-articles)))
+           (nnheader-insert-nov header))))
       'nov)))
 
 (deffoo nnweb-request-scan (&optional group server)
@@ -169,7 +170,8 @@ and `altavista'.")
     (let* ((header (cadr (assq article nnweb-articles)))
           (url (and header (mail-header-xref header))))
       (when (or (and url
-                    (nnweb-fetch-url url))
+                    (mm-with-unibyte-current-buffer
+                      (nnweb-fetch-url url)))
                (and (stringp article)
                     (nnweb-definition 'id t)
                     (let ((fetch (nnweb-definition 'id))
@@ -178,8 +180,9 @@ and `altavista'.")
                         (setq art (match-string 1 article)))
                       (and fetch
                            art
-                           (nnweb-fetch-url
-                            (format fetch article))))))
+                           (mm-with-unibyte-current-buffer
+                             (nnweb-fetch-url
+                              (format fetch article)))))))
        (unless nnheader-callback-function
          (funcall (nnweb-definition 'article))
          (nnweb-decode-entities))
@@ -231,7 +234,7 @@ and `altavista'.")
 (defun nnweb-read-overview (group)
   "Read the overview of GROUP and build the map."
   (when (file-exists-p (nnweb-overview-file group))
-    (with-temp-buffer
+    (mm-with-unibyte-buffer
       (nnheader-insert-file-contents (nnweb-overview-file group))
       (goto-char (point-min))
       (let (header)
@@ -299,22 +302,34 @@ and `altavista'.")
   (unless (gnus-buffer-live-p nnweb-buffer)
     (setq nnweb-buffer
          (save-excursion
-           (nnheader-set-temp-buffer
-            (format " *nnweb %s %s %s*" nnweb-type nnweb-search server))))))
+           (let ((multibyte (default-value 'enable-multibyte-characters)))
+             (unwind-protect
+                 (progn
+                   (setq-default enable-multibyte-characters nil)
+                   (nnheader-set-temp-buffer
+                    (format " *nnweb %s %s %s*"
+                            nnweb-type nnweb-search server)))
+               (setq-default enable-multibyte-characters multibyte))
+             (current-buffer))))))
 
 (defun nnweb-fetch-url (url)
-  (save-excursion
-    (if (not nnheader-callback-function)
-       (let ((buf (current-buffer)))
-         (save-excursion
-           (set-buffer nnweb-buffer)
+  (let (buf)
+    (save-excursion
+      (if (not nnheader-callback-function)
+         (progn
+           (with-temp-buffer
+             (mm-enable-multibyte)
+             (let ((coding-system-for-read 'binary)
+                   (coding-system-for-write 'binary)
+                   (default-process-coding-system 'binary))
+               (nnweb-insert url))
+             (setq buf (buffer-string)))
            (erase-buffer)
-           (url-insert-file-contents url)
-           (copy-to-buffer buf (point-min) (point-max))
-           t))
-      (nnweb-url-retrieve-asynch
-       url 'nnweb-callback (current-buffer) nnheader-callback-function)
-      t)))
+           (insert buf)
+           t)
+       (nnweb-url-retrieve-asynch
+        url 'nnweb-callback (current-buffer) nnheader-callback-function)
+       t))))
 
 (defun nnweb-callback (buffer callback)
   (when (gnus-buffer-live-p url-working-buffer)
@@ -368,18 +383,20 @@ and `altavista'.")
          (dolist (row (nth 2 (car (nth 2 table))))
            (setq a (nnweb-parse-find 'a row)
                  url (cdr (assq 'href (nth 1 a)))
-                 text (nnweb-text row))
+                 text (nreverse (nnweb-text row)))
            (when a
-             (setq subject (nth 2 text)
-                   group (nth 4 text)
-                   date (nth 5 text)
-                   from (nth 6 text))
-             (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date)
-             (setq date (format "%s %s %s"
-                                (car (rassq (string-to-number
-                                             (match-string 2 date))
-                                            parse-time-months))
-                                (match-string 3 date) (match-string 1 date)))
+             (setq subject (nth 4 text)
+                   group (nth 2 text)
+                   date (nth 1 text)
+                   from (nth 0 text))
+             (if (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date)
+                 (setq date (format "%s %s 00:00:00 %s"
+                                    (car (rassq (string-to-number
+                                                 (match-string 2 date))
+                                                parse-time-months))
+                                    (match-string 3 date) 
+                                    (match-string 1 date)))
+               (setq date "Jan 1 00:00:00 0000"))
              (incf i)
              (setq url (concat url "&fmt=text"))
              (unless (nnweb-get-hashtb url)
index 1a08b3c..3344753 100644 (file)
@@ -338,9 +338,16 @@ Valid ENCODINGs are \"B\" and \"Q\".
 If your Emacs implementation can't decode CHARSET, it returns nil."
   (if (stringp charset)
     (setq charset (intern (downcase charset))))
-  (if (or (not charset) (memq charset mail-parse-ignored-charsets))
+  (if (or (not charset) 
+         (eq 'gnus-all mail-parse-ignored-charsets)
+         (memq 'gnus-all mail-parse-ignored-charsets)
+         (memq charset mail-parse-ignored-charsets))
       (setq charset mail-parse-charset))
   (let ((cs (mm-charset-to-coding-system charset)))
+    (if (and (not cs) charset 
+            (listp mail-parse-ignored-charsets)
+            (memq 'gnus-unknown mail-parse-ignored-charsets))
+      (setq cs (mm-charset-to-coding-system mail-parse-charset)))
     (when cs
       (when (and (eq cs 'ascii)
                 mail-parse-charset)
index 54e7f9b..dd82a2b 100644 (file)
@@ -1,8 +1,24 @@
+1999-12-03 00:02:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Other Gnus Versions): New.
+       (Gnus Versions): Made into own node.
+
+1999-12-02 00:00:00  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Paging the Article): Addition.
+       (History): Addition.
+
+1999-11-24  Carsten Leonhardt  <leo@arioch.oche.de>
+
+       * gnus.texi (Mail Source Specifiers): Mention maildir in the
+         overview and the possibility to use remote maildirs.
+
 1999-12-01 14:21:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus.texi (Topic Parameters): Addition.
        (Summary Message Commands): New.
        (Canceling and Superseding): Made into subsection.
+       (Charsets): Addition.
 
 1999-11-30 10:54:31  Shenghuo ZHU  <zsh@cs.rochester.edu>
 
index f77798e..bf60769 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo                  @c -*-texinfo-*-  -*- coding: iso-latin-1 -*-
 
 @setfilename gnus
-@settitle Pterodactyl Gnus  Manual
+@settitle Gnus Manual
 @synindex fn cp
 @synindex vr cp
 @synindex pg cp
@@ -319,7 +319,7 @@ into another language, under the above conditions for modified versions.
 @tex
 
 @titlepage
-@title Pterodactyl Gnus  Manual
+@title Gnus Manual
 
 @author by Lars Magne Ingebrigtsen
 @page
@@ -355,7 +355,7 @@ can be gotten by any nefarious means you can think of---@sc{nntp}, local
 spool or your mbox file.  All at the same time, if you want to push your
 luck.
 
-This manual corresponds to Pterodactyl Gnus .
+This manual corresponds to Gnus 5.8.2.
 
 @end ifinfo
 
@@ -3910,11 +3910,24 @@ Scroll the current article one line backward
 @kindex A g (Summary)
 @kindex g (Summary)
 @findex gnus-summary-show-article
+@vindex gnus-summary-show-article-charset-alist
 (Re)fetch the current article (@code{gnus-summary-show-article}).  If
 given a prefix, fetch the current article, but don't run any of the
 article treatment functions.  This will give you a ``raw'' article, just
 the way it came from the server.
 
+If given a numerical prefix, you can do semi-manual charset stuff.
+@kbd{C-u 0 g cn-gb-2312 RET} will decode the message as if it were
+encoded in the @code{cn-gb-2312} charset.  If you have
+
+@lisp
+(setq gnus-summary-show-article-charset-alist 
+      '((1 . cn-gb-2312) 
+        (2 . big5)))
+@end lisp
+
+then you can say @kbd{C-u 1 g} to get the same effect.
+
 @item A <
 @itemx <
 @kindex < (Summary)
@@ -7159,9 +7172,9 @@ instance, @kbd{3 b} means ``view the third @sc{mime} part''.
 
 @table @kbd
 @item b
-@itemx K b
+@itemx K v
 @kindex b (Summary)
-@kindex K b (Summary)
+@kindex K v (Summary)
 View the @sc{mime} part.
 
 @item K o
@@ -7312,6 +7325,42 @@ on a group-by-group basis using the group parameters (@pxref{Group
 Parameters}).  The default value is @code{(unknown-8bit)}, which is
 something some agents insist on having in there.
 
+@cindex Russina
+@cindex koi8-r
+@cindex koi8-u
+@cindex iso-8859-5
+@cindex coding system aliases
+@cindex preferred charset
+
+Other charset tricks that may be useful, although not Gnus-specific:
+
+If there are several @sc{mime} charsets that encode the same Emacs
+charset, you can choose what charset to use by saying the following:
+
+@lisp
+(put-charset-property 'cyrillic-iso8859-5
+                      'preferred-coding-system 'koi8-r)
+@end lisp
+
+This means that Russian will be encoded using @code{koi8-r} instead of
+the default @code{iso-8859-5} @sc{mime} charset.
+
+If you want to read messages in @code{koi8-u}, you can cheat and say
+
+@lisp
+(define-coding-system-alias 'koi8-u 'koi8-r)
+@end lisp
+
+This will almost do the right thing.
+
+And finally, to read charsets like @code{windows-1251}, you can say
+something like
+
+@lisp
+(codepage-setup 1251)
+(define-coding-system-alias 'windows-1251 'cp1251)
+@end lisp
+
 
 @node Article Commands
 @section Article Commands
@@ -10275,7 +10324,8 @@ month's rent money.
 @subsection Mail Sources
 
 Mail can be gotten from many different sources---the mail spool, from a
-POP mail server, or from a procmail directory, for instance.
+POP mail server, from a procmail directory, or from a maildir, for
+instance.
 
 @menu
 * Mail Source Specifiers::       How to specify what a mail source is.
@@ -10489,9 +10539,9 @@ Use @samp{movemail} to move the mail:
 @end lisp
 
 @item maildir
-Get mail from a maildir. This is a type of mailbox currently only
-supported by qmail, where each file in a special directory contains
-exactly one mail.
+Get mail from a maildir. This is a type of mailbox that is supported by
+at least qmail and postfix, where each file in a special directory
+contains exactly one mail.
 
 Keywords:
 
@@ -10502,16 +10552,24 @@ The path of the directory where the mails are stored.  The default is
 
 If you sometimes look at your mail through a pop3 daemon before fetching
 them with Gnus, you may also have to fetch your mails from the
-@code{cur} directory inside the maildir, like in the following example.
+@code{cur} directory inside the maildir, like in the first example
+below.
+
+You can also get mails from remote hosts (because maildirs don't suffer
+from locking problems).
 
 @end table
 
-An example maildir mail source:
+Two example maildir mail sources:
 
 @lisp
 (maildir :path "/home/user-name/Maildir/cur")
 @end lisp
 
+@lisp
+(maildir :path "/user@@remotehost.org:~/Maildir/new")
+@end lisp
+
 @item imap
 Get mail from a @sc{imap} server. If you don't want to use @sc{imap} as intended,
 as a network mail reading protocol (ie with nnimap), for some reason or
@@ -17497,6 +17555,27 @@ spunky name, we decided that the name was @emph{too} spunky, so we
 renamed it back again to ``Gnus''.  But in mixed case.  ``Gnus'' vs.
 ``@sc{gnus}''.  New vs. old.
 
+@menu
+* Gnus Versions::       What Gnus versions have been released.
+* Other Gnus Versions:: Other Gnus versions that also have been released.
+* Why?::                What's the point of Gnus?
+* Compatibility::       Just how compatible is Gnus with @sc{gnus}?
+* Conformity::          Gnus tries to conform to all standards.
+* Emacsen::             Gnus can be run on a few modern Emacsen.
+* Gnus Development::    How Gnus is developed.
+* Contributors::        Oodles of people.
+* New Features::        Pointers to some of the new stuff in Gnus.
+* Newest Features::     Features so new that they haven't been written yet.
+@end menu
+
+
+@node Gnus Versions
+@subsection Gnus Versions
+@cindex Pterodactyl Gnus
+@cindex ding Gnus
+@cindex September Gnus
+@cindex Quassia Gnus
+
 The first ``proper'' release of Gnus 5 was done in November 1995 when it
 was included in the Emacs 19.30 distribution (132 (ding) Gnus releases
 plus 15 Gnus 5.0 releases).
@@ -17507,8 +17586,12 @@ releases)) was released under the name ``Gnus 5.2'' (40 releases).
 On July 28th 1996 work on Red Gnus was begun, and it was released on
 January 25th 1997 (after 84 releases) as ``Gnus 5.4'' (67 releases).
 
-On September 13th 1997, Quassia Gnus was started and lasted 37
-releases.  If was released as ``Gnus 5.6 on March 8th 1998.
+On September 13th 1997, Quassia Gnus was started and lasted 37 releases.
+If was released as ``Gnus 5.6'' on March 8th 1998 (46 releases).
+
+Gnus 5.6 begat Pterodactyl Gnus on August 29th 1998 and was released as
+``Gnus 5.8'' (after 99 releases and a CVS repository) on December 3rd
+1999. 
 
 If you happen upon a version of Gnus that has a prefixed name --
 ``(ding) Gnus'', ``September Gnus'', ``Red Gnus'', ``Quassia Gnus'' --
@@ -17517,16 +17600,21 @@ Slowly.  Whatever you do, don't run.  Walk away, calmly, until you're
 out of its reach.  Find a proper released version of Gnus and snuggle up
 to that instead.
 
-@menu
-* Why?::                What's the point of Gnus?
-* Compatibility::       Just how compatible is Gnus with @sc{gnus}?
-* Conformity::          Gnus tries to conform to all standards.
-* Emacsen::             Gnus can be run on a few modern Emacsen.
-* Gnus Development::    How Gnus is developed.
-* Contributors::        Oodles of people.
-* New Features::        Pointers to some of the new stuff in Gnus.
-* Newest Features::     Features so new that they haven't been written yet.
-@end menu
+
+@node Other Gnus Versions
+@subsection Other Gnus Versions
+@cindex Semi-gnus
+
+In addition to the versions of Gnus which have had their releases
+coordinated by Lars, one major development has been Semi-gnus from
+Japan.  It's based on a library called @sc{semi}, which provides
+@sc{mime} capabilities.
+
+These Gnusae are based mainly on Gnus 5.6 and Pterodactyl Gnus.
+Collectively, they are called ``Semi-gnus'', and different strains are
+called T-gnus, ET-gnus, Nana-gnus and Chaos.  These provide powerful
+@sc{mime} and multilingualization things, especially important for
+Japanese users.
 
 
 @node Why?
@@ -19989,6 +20077,9 @@ fetching.
 Be able to forward groups of messages as MIME digests.
 
 @item
+nnweb should include the "get whole article" article when getting articles. 
+
+@item
 Solve the halting problem.
 
 @c TODO
diff --git a/texi/gnusmail.texi b/texi/gnusmail.texi
new file mode 100644 (file)
index 0000000..7c8c66b
--- /dev/null
@@ -0,0 +1,708 @@
+@node Mail with Gnus, , Key bindings, Top
+@comment  node-name,  next,  previous,  up
+@chapter Mail with Gnus
+
+Quite a few people wish to read mail with Gnus but stumble across a few
+issues which make this a bit difficult.  This comes from the fact that
+Gnus is really a newsreader, and thus it treats mail in a newsreaderly
+fashion.  It is not desirable to change this, because it is a wonderful
+thing and this is what distinguishes Gnus from other mail readers.  In
+this little tutorial, I'll try to explain what ``newsreaderly fashion''
+means and how exactly Gnus treats mail.
+
+Specific pieces of behavior can always be changed, but if you desire to
+make Gnus behave like a conventional mail reader, think again.  It will
+be an uphill battle.  Maybe a different mail reader is for you?  But
+also, read on.  Maybe you'll find the right behavior in the description
+below.
+
+@c ------------------------------------------------------------ 
+@section Gnus Terminology
+@c ------------------------------------------------------------ 
+
+First, let's talk about a few terms which I'm going to use which might
+be unfamiliar to you.
+
+@table @dfn
+@item Posting, Article, Message, Mail
+These are all related terms.  A news message might also be called a
+posting or an article, whereas a mail message is known as a mail.  Since
+Gnus treats both news and mail, the distinction isn't as clear.  In the
+following, I'll use the term ``message'' for the generic case and ``news
+message'' and ``mail message'' for the specific cases.  But sometimes, I
+might use ``posting'' or ``article'', too, both synonymous with
+``message''.
+
+@item Backend
+Gnus can read messages from various sources.  On the one hand, there is
+news, and on the other hand, there is mail.  News can be read from a
+news server (an NNTP server), or from a so-called spool directory.  Mail
+can be read in various formats.
+
+Generally speaking, a backend describes the way Gnus accesses a set of
+messages.  For a news server, this is the Network News Transfer
+Protocol, NNTP, and thus there is a backend ``nntp''.  For mail stored
+in the same format that the MH message handling system used, there is
+the backend ``nnmh''.  And so on.  See below for a list of backends.
+
+@item Server
+Whereas a backend describes the mechanism used by Gnus to access the
+messages, a server is a specific instance of that mechanism.  You might
+create a specific server for accessing the host @file{news.frob.org}
+using NNTP, say.  Or you might create a server for accessing the
+MH-style directory @file{~/OldMail}.
+
+If you are a programmer, think of a backend as the class and of a server
+as an object (instance) of that class.  If you are a cook, think of a
+backend as an apple pie recipe (say), and think of a server as an actual
+apple pie.  (Yummy!)  If you live in a huge city, think of a backend as
+a bus (or tram, or underground) line (the Circle Line comes to mind),
+and think of a server as a specific bus (or tram train, or underground
+train).  The one at 8:15 last Monday morning, for example.  If you drive
+a car, think of a backend as the model and make and of a server as a
+specific car.
+
+Obviously, there can be two servers using the same backend.  (Two
+instances of the same class, two apple pies baked according to the same
+recipe, two busses going the same route, two cars of the same model.)
+
+@item (Select) method
+Just another term for server.
+
+@item Native server
+This is the primary server, so to speak.  Most people let their news
+server be the native server, hence:
+@lisp
+(setq gnus-select-method '(nntp "news.frob.org"))
+@end lisp
+Groups from the native server are also known as native groups.
+
+@item Secondary select methods
+This is a list of other servers which one also wishes to use.  Many
+people are only going to have two servers, one native (for news) and one
+secondary (for mail).  Thus:
+@lisp
+(setq gnus-secondary-select-methods '((nnml "")))
+@end lisp
+Note that there is one more pair of parentheses in order to be able to
+mention more than one seconary select method.
+
+Groups from a secondary server are also known as secondary groups.
+
+In order to be able to distinguish native groups from secondary groups,
+each server is identified with a (unique) name and that name is used as
+a prefix for the secondary groups.  Thus, you might have a group
+@file{gnu.emacs.help} (which is native) and another group
+@file{nnml:mail.misc} (which is secondary).  A plus character is used if
+the name of a server is not the empty string.  For example, given the
+following in your @file{.gnus} file
+@lisp
+(setq gnus-secondary-select-methods
+      '((nnml "work" (nnml-directory "~/Mail.work/"))
+        (nnml "play" (nnml-directory "~/Mail.play/"))))
+@end lisp
+you might have the groups @file{nnml+work:boss} and
+@file{nnml+play:so}@footnote{``SO'' standing for ``significant other'',
+i.e.@ girlfriend or boyfriend}.
+
+@item Group
+Well, if you've read news before, you know about different news groups.
+One of my favorites is @file{gnu.emacs.gnus}, and I wish I would read
+@file{alt.fan.pratchett}.  Since Gnus treats mail in a newsreaderly
+fashion, it is obvious that it uses groups rather than ``folders'' like
+other mail readers do.  So with Gnus there are news groups and mail
+groups, where mail groups are known as mail folders to other programs.
+
+Each group belongs to a certain server, and each server uses a certain
+backend.
+
+@item Expiry
+News servers offer news groups which contain news postings.  New news
+postings come in, so the news postings accumulate, and pretty soon the
+new hard disk is full.  This is not good news at all.
+
+Thus, a news server does what is known as @dfn{expiry}: it deletes old
+messages.  Of course, on a news server, expiry happens with no regard of
+whether people have already seen the message in question; instead, the
+news server admin chooses expiry times based on available disk space and
+maybe on the normal amount of traffic in a news group.
+
+But mail messages should be under the users' control, so there better be
+no server which deletes messages regardless of users having seen them!
+Instead, Gnus adopts a scheme where users say which messages may be
+deleted, and Gnus takes care of deleting them after a while.  (They are
+not deleted immediately in case you made a mistake, or in case you wish
+to refer back to an old article.)
+
+@item Article marks
+Gnus distinguishes between a number of article marks, which indicate
+whether they have been looked at, or are considered important, or the
+like.  Marks are represented by a character.
+
+If that character is a space, it looks as if the message isn't marked at
+all.  These messages are called @dfn{unmarked}, the mark character used
+is a space, and marking a message with space is considered to be the
+same as removing all marks---after all, such messages are unmarked.  You
+can type @kbd{M-u} to remove all marks and make an article unmarked.
+
+Articles that are considered important or where you wish to indicate
+that you have to deal with them later can be @dfn{ticked}.  The mark
+character used for ticked messages is the exclamation mark, and you can
+use @kbd{u} or @kbd{!} to tick messages.  Ticked messages are always
+shown when you enter a group.
+
+There is the @dfn{dormant} mark which is similar to the ticked mark but
+does not imply importance or urgency; thus, dormant messages aren't
+shown by default.  The mark character used is the question mark, and you
+can mark messages as dormant using the @kbd{?} key.
+
+So far, each kind of mark was associated with one character (as was the
+absence of any mark).  But articles which you have read are a bit
+different, since lots of different characters are used here.  The
+important thing to realize is that these messages are treated in the
+same way by Gnus; the different characters are only used as an
+information for the user.
+
+Articles which are marked as read because you have actually read them
+(the normal case, one would think) are marked with the `R' character.
+(Type @kbd{@key{SPC}} or @kbd{g} to read a message, or click on it using
+the middle mouse button, @kbd{@key{mouse-2}}.)  You can also mark a
+message as read without actually reading it, this is indicated with the
+`r' character and can be achieved with @kbd{d} or @kbd{M r}.
+
+After exiting a group and then entering it again (some time later), the
+messages that had been marked as read before appear with the `O'
+character.
+
+To reiterate: the difference between `r', `R' and `O' is only an
+information for the user.
+
+@end table
+
+
+
+@c ------------------------------------------------------------
+@section Choosing a mail backend
+@c ------------------------------------------------------------
+
+The Gnus manual lists quite a few backends.  Of these, the news backends
+pose no problem: you use the @code{nntp} backend if you access a news
+server and the @code{nnspool} backend if you have a local news spool
+directory.  (Leafnode users should use @code{nntp} so that the leafnode
+program can see what you are doing and choose the groups to download
+accordingly.)  But the mail backends are more difficult.  There are many
+of them, and it is not obvious which is the best choice.  In quite a few
+cases, this is because there is no single best choice; or maybe what's
+the best choice depends on the group or changes over time.
+
+Below, I'll give a list of mail backends.  While I say something about
+how messages are stored, I'll try to emphasize what that means for you
+as a user.
+
+Let's try to structure the discussion a bit.  We have servers, which
+contain groups, which in turn contain messages.  How could we store this
+on disk?  After some thought, you'll quickly come up with the following
+alternatives:  You could store all messages from a server in one file.
+The second alternative is to store all messages from one group in one
+file, different groups are stored in different files.  A third
+alternative is to store each message in one file; in this case, one
+could use a directory per group.  A very interesting fourth alternative
+is not to store the messages at all but instead to use the Oracle of
+Delphi (say) to predict what the messages will be; this saves a lot of
+disk space.  I won't talk about the fourth alternative in the following.
+
+
+@subsection Backends with one file per server
+
+Many people use just two servers, the native server for news and a
+secondary server for mail.  Thus, this alternative would mean that you
+store all your mail in one file.  Since Emacs has no fancy mechanisms to
+access parts of files, this means that Gnus loads that file into main
+memory at startup, and all your mails are kept in main memory all the
+time.  (Of course, copies are written to disk every now and then, for
+safekeeping!)
+
+I think you can pretty much figure out the consequences on your own,
+now:
+@itemize @bullet
+@item
+Handling large amounts of mail will be a problem.  (Emacs has a maximum
+file size of 128 MB.)
+
+@item
+Some operations on mails will be fast, since they are in-memory
+operations.  (Saving everything to disk will be slow, though.)
+
+@item
+Some operations on mails will be slow, since they have to search through
+the whole file.
+
+@item
+It is convenient to have all mail stored in one file: you can easily
+transfer it to another computer using FTP, say, or store it on a floppy
+or Zip disk or a tape.
+
+@end itemize
+
+Conclusion: If you don't have a lot of mail to deal with and like the
+convenience of storing it all in one file, one of these backends might
+be for you.  However, since Gnus really shines when dealing with lots of
+mails, most Gnus users can be expected to deal with quite a large volume
+of mail.  Thus, I don't think many Gnus users choose one of these
+backends.
+
+@table @code
+@item nnmbox
+This backend uses the well-known ``mbox'' format for storing mails.  In
+this format, a message begins with the five characters @code{From_} (the
+last character is a space) at the beginning of a line, and ends with an
+empty line.
+
+@item nnbabyl
+This backend uses the lesser known ``babyl'' format for storing mails.
+This uses delimiters for the beginning and the end of a message which
+are less likely to occur in a message.
+
+@quotation
+CCC Are they guaranteed to never occur?
+@end quotation
+
+One advantage of a babyl file over an mbox file is that it is possible
+to insert information about a message in the babyl file, without having
+to change the message itself.  In an mbox file, the only place to put
+such information is the message header, which is part of the message.
+Thus, adding information about a message to an mbox file means that one
+has to change the message.
+
+I think Gnus doesn't make use of this advantage, though.  Gnus stores
+information about messages in an extra file, @file{~/.newsrc.eld}.
+
+@end table
+
+@quotation
+CCC Can somebody provide me with some more arguments in favor of one of
+the formats?
+
+CCC Is it possible to just use an existing babyl file for Gnus, by
+creating a new nnmbox server and pointing it at the file?  What about
+mbox?
+@end quotation
+
+
+@subsection Backends with one file per group
+
+Storing all messages in a group in one file provides a nice middle
+ground between the one file per server type of backend and the one file
+per message type of backend.  Using lots of little files wastes disk
+space; since this approach uses a moderate number of files, less disk
+space is wasted.
+
+@quotation
+CCC Which operations are fast using this kind of backend?  Which are
+slow? 
+@end quotation
+
+@table @code
+@item nnfolder
+This backend uses the same file format as @code{nnmbox}, but uses the
+one file per group approach.
+
+@end table
+
+There is no ``nnbabylfolder'' backend which uses babyl format.
+
+
+@subsection Backends with one file per message
+
+If the number of messages grows so large that even the size of a single
+group exceeds the limit which can be handled by the file-per-group
+backends, you need to think about using one of the backends mentioned
+here.
+
+This category also includes @code{nnml}, the backend which is fastest if
+you have lots of messages.
+
+@table @code
+@item nnmh
+This backend uses the same file format (and directory structure) as MH,
+i.e.@ a group is a directory, and each message is stored in a file, and
+the file names are numbers.
+
+Since @code{nnml} is so similar to @code{nnmh} but a lot faster, only
+unusual situations could warrant using this backend.  You may want to
+use @code{nnmh} if you wish to use Gnus in parallel to your old MH based
+reader.
+
+Normally, you should not let two programs write the same Gnus directory
+(not even two instances of Gnus!), but if you really must, you may wish
+to use @code{nnmh}, since there the probability of things breaking is
+smaller than with the other backends.
+
+@item nnml
+This backend is like @code{nnmh} but also includes an extra file
+@file{.overview} in each directory (group) which contains some headers
+from each message.  Thus, where @code{nnmh} needs to open every file in
+a group to examine its headers, @code{nnml} (normally) needs to only
+read the @file{.overview} file, which is a lot faster.
+@end table
+
+
+@subsection Other mail backends
+
+There is one other mail backend, for keeping messages on an IMAP server.
+
+@table @code
+@item nnimap
+This backend transforms Gnus into an IMAP client.  The general idea of
+IMAP is to store and manipulate the mails on a server (similar to NNTP
+for news).
+
+@code{nnimap} only works with the current development version of Gnus,
+though.  See @url{http://www.extundo.com/nnimap/} for @code{nnimap} and
+see @url{http://www.gnus.org/} for Gnus.  Don't forget to subscribe to
+both the Gnus and the nnimap mailing lists since you are using alpha
+grade software which can be exptected to have bugs.  Be prepared to
+submit meaningful bug reports if you encounter bugs.
+
+Rumor has it that @code{nnimap} will be integrated with the next version
+of Gnus (version 5.8, presumably), when that comes out.
+
+@end table
+
+
+@subsection Summary
+
+If you must talk to an IMAP server, the choice is clear.  But if you
+keep mails on your local disk, the choice isn't as clear-cut.  I think
+that @code{nnml} is generally the best choice unless you have real great
+disk space trouble.  Then, you should be thinking about @code{nnfolder}.
+
+I'm not sure if there is a situation where @code{nnmbox} or
+@code{nnbabyl} is desirable.
+
+@quotation
+CCC Tell me about it if you know more!
+@end quotation
+
+
+@c ------------------------------------------------------------
+@section Auto-expire versus total-expire
+@c ------------------------------------------------------------
+
+Every now and then, people ask about auto-expire and total-expire.
+Since both of these features are means to the same end, and since they
+are similar and dissimilar at the same time, great confusion can result
+in the unsuspecting new Gnus user.  I'll try to explain how each works
+and which one to use.  However, be prepared that there will be no clear
+recommendation: both work well, so for many situations both are
+appropriate.  So it is more a matter of taste which one to choose.  And
+I can't help you with that!
+
+
+@subsection What is expiry?
+
+Gnus treats mail in a newsreaderly fashion, so it is useful to examine
+the situation for news.  Your news server periodically contacts other
+news servers and exchanges messages with the other server.  The two news
+servers exchange lists of messages, and messages present in one server
+but not in the other are sent to the other server.  This works in both
+directions.  Many connections between news servers exist, and this is
+the way how postings travel from you into the world: when you post a
+message, your news server stores it and offers it to the other servers
+in the message list exchanging phase.  Since the other servers aren't
+going to have the posting you just wrote, it gets transferred and
+finally can be seen all over the world.
+
+You can quickly see that new messages will be arriving at your news
+server, which stores them on disk.  So something has got to happen else
+the disk will fill up real fast.  That ``something'' is expiry: the
+oldest messages are deleted to make room for the new ones.  Normally, a
+news server can be configured on a per-group basis which messages should
+be deleted.  In some groups, messages might be deleted which are older
+than a day, in other groups, messages might be kept for a month.
+
+This means if you go on vacation then come back later to read news, you
+are likely to miss some postings if the expiration time for the groups
+you read is shorter than the time you were on vacation.
+
+How does that apply to mail?
+
+Well, mail should stay more under the control of the user than news is.
+When you come back from a vacation, you expect to see all messages
+arrived during that time, not only the recent ones!
+
+Because of this, Gnus offers you the @kbd{E} key.  This marks a message
+as expirable.  No mail is ever deleted from disk, unless it is
+expirable.  Every once in a while (by default, whenever you quit a group
+by hitting @kbd{q} in the Summary buffer), the expiry process is run,
+which goes through all expirable messages (of a group) and expires it if
+old enough.  By default, messages older than seven days are ``old
+enough''.  Seven days, that is, since it was marked as expirable.
+
+@quotation
+CCC Last sentence correct?
+@end quotation
+
+``But when I read a message, exit the group, then enter it again, the
+message is gone!''
+
+Right.  By default, Gnus hides messages which have already been read.
+If you are the keyboard type, you can hit @kbd{C-u @key{RET}} or
+@kbd{C-u @key{SPC}} to enter the group or @kbd{C-u M-g} when in the
+group to look at the read messages.  If you are the mousey type, you may
+wish to use the ``See old articles'' entry in the ``Group'' menu.
+
+@quotation
+CCC How does one code menu entries in TeXinfo?
+@end quotation
+
+
+@subsection Why auto-expire and total-expire?
+
+When reading mail, by default Gnus marks as read each message that you
+read.  If you want to mark it as expirable, you have to hit @kbd{E}.
+Many people are subscribed to mailing lists and they configure Gnus to
+put mails from a mailing list into their own group.  Most messages in
+such groups should be expirable, once read.  But hitting @kbd{E} all the
+gets old real quick.  Hence, auto-expire and total-expire were invented.
+
+
+@subsection Auto-expire vs.@ total-expire
+
+Auto-expire and total-expire both aim at the same goal: articles which
+are read should normally be expired, only if one does something special
+should these articles be saved on disk.  But what happens when a message
+is being read by you, the user?  Well, the message is marked as read
+(with the `R' mark).  So, what can be done to make these messages
+expire?  Well, two approaches come to mind: one idea is to change the
+mark that is attached to messages that you read, and the other idea is
+to make the `R' articles expirable.  These are @emph{exactly} the things
+that are done in Gnus: auto-expire means to change the mark that is
+attached to a message that is being read, and total-expire means to
+change the meaning of the `R' mark to mean expirable.
+
+A more precise description of auto-expire might be the following: If an
+article is unmarked and then selected for reading,@footnote{Using
+@kbd{g}, or @kbd{@key{mouse-2}}, or by moving to it with @kbd{n} or
+@kbd{p}, or by one of the many other methods provided by Gnus.} it is
+marked with `E', as if the user had hit @kbd{E}.
+
+It is important to realize that auto-expire has @emph{no other}
+consequences.  Selecting a message for reading which wasn't unmarked
+doesn't do anything special, and hitting @kbd{d} on a message also
+doesn't do anything special.  (It therefore marks the message as read,
+not as expirable!)
+
+Now, forget about auto-expire, empty your mind and prepare to learn
+about total-expire.  Like I said, total-expire changes what it means for
+an article to be marked as read.
+
+A more precise description of total-expire might be the following: When
+the expire process is run (for example, when you leave a group with
+@kbd{q}), all messages marked as read are considered to be expirable, as
+if they had been marked with `E'.  Recall that there are several ways to
+mark a message as read: by reading it, by hitting @kbd{d} on it, and in
+a few other ways which I haven't mentioned so far.  Recall that, in
+addition to the messages marked with `R', also those marked with `r' or
+`O' are considered to be marked as read.
+
+Can auto-expire and total-expire be used together?  Well, in principle
+they can, but that doesn't make sense.  Just using total-expire alone
+achieves the same effect.
+
+So, how do auto-expire and total-expire compare?  Well, for once thing,
+hitting @kbd{d} on a message means it is expirable if total-expire is
+on (since it is marked as read and all messages marked as read are
+considered expirable when total-expire is on), but it is not expirable
+if auto-expire is on (since it is marked as read and only articles
+marked expirable (`E') are considered to be expirable).  If you want to
+mark a message as expirable when total-expire is off, use @kbd{E}.
+
+One way of comparing auto-expire and total-expire is to compare the
+message marks that are available, and what they mean.  Since auto-expire
+does not change the meaning of marks, its behavior is the same as in the
+default case.  It's only important whether total-expire is on or off.
+Thus, there are only two cases: the default case and the total-expire
+case.
+
+@subsubsection Article marks with and without total-expire
+
+The following are the default article marks and behavior:
+
+@table @dfn
+@item unmarked
+All new messages are unmarked.  This means you haven't seen them.  They
+are always shown and won't be deleted.
+
+@item read
+Messages marked as read are not shown by default but kept on disk till
+hell freezes over.  You can show them with @kbd{C-u M-g} from the
+summary buffer, or with @kbd{C-u @key{SPC}} or with the `Group' menu
+item `See old articles' from the group buffer.
+
+Depending on the setting of @var{gnus-fetch-old-headers}, a message
+marked as read might be shown if there is a followup or reply to it.
+
+@item dormant
+Dormant messages aren't shown by default but kept on disk till hell
+freezes over.  You can show them with @kbd{/ D} from the summary buffer.
+If there is a reply or followup to a dormant message, the dormant
+message is also shown.
+
+@item ticked
+Ticked messages are always shown and kept on disk till hell freezes
+over.
+
+@item expirable
+Expirable messages will be deleted in due time.  They are not shown by
+default, but you can make them appear with @kbd{C-u M-g} and so on,
+similar to the read ones.
+
+@end table
+
+Please note that the behavior for ticked messages is similar to the
+unread ones, and that the behavior of dormant messages is similar to the
+read ones.  Especially the second fact will become important when we
+look at
+
+The behavior of the article marks with total-expire:
+
+@table @dfn
+@item unmarked
+Same as in the default case.
+
+@item expirable
+Same as in the default case.
+
+@item read
+Same as expirable.
+
+@item dormant
+Same as in the default case.
+
+@item ticked
+Same as in the default case.
+
+@end table
+
+As you can see, only the behavior of the read messages is different, and
+you can use the dormant mark if you want to achieve behavior similar to
+the behavior of read messages in the default case.
+
+
+@subsubsection Speed issues
+
+Total-expire may be slow when expiry happens.  Why is that?  Well, Gnus
+keeps an explicit list of all expirable messages (the ones marked `E'
+without taking total-expire into account), as well as a list of dormant
+messages, and a list of ticked messages.  Normally, when expiration time
+comes, Gnus goes through all articles in the expire list and looks if
+they are old enough to be expired.
+
+However, for read messages the situation is different.  Here, Gnus just
+keeps a list of ranges of article numbers to be able to distinguish read
+messages from unmarked ones.  The assumption is that a message is to be
+considered marked as read if it falls in one of the ranges and isn't
+mentioned in any of the expirable, dormant or ticked lists.
+
+When total-expire is turned on, Gnus needs to go through all messages in
+the read range in order to look if it's in one of the lists.  If the
+message is not in the ticked or dormant list, it is expirable and thus
+Gnus looks to see if it is old enough.
+
+Obviously, going through all the articles in the read ranges takes more
+time than going through just the list of expirable articles.
+
+Something can be done about the speed issue, though.  Normally, the
+expiry process is started whenever you leave a group.  I suggest that
+you disable this and instead run expiry just once per day, for example
+while you are going for lunch.  This means that expiry still takes a
+long time, but you don't see it and thus it doesn't bother you.
+
+Here's how to do that: You disable the expire-on-group-exit thing with
+the following line in your @file{~/.gnus} file:
+@lisp
+(remove-hook 'gnus-summary-prepare-exit-hook
+             'gnus-summary-expire-articles)
+@end lisp
+And before you leave for lunch, you hit @kbd{C-M-x}, or @kbd{M-x
+gnus-group-expire-all-groups @key{RET}}.
+
+
+@subsubsection Functionality
+
+Adaptive scoring doesn't work with auto-expire.  (But normal scoring
+still works fine.)  Adaptive scoring works fine with total-expire.
+
+
+@subsubsection A summary
+
+Well, it is difficult to sum up the whole discussion.  I used to use
+total-expire but have switched to auto-expire a long time ago.  I liked
+the fact that I could use one more kind of article mark.  I also liked
+the fact that marking a message as read works the same in auto-expirable
+groups and in normal mail groups: you hit @kbd{E}.  (With total-expire,
+you normally hit @kbd{d} but must remember to use @kbd{E} for those
+groups where total-expire is off.)  And I liked that auto-expire is
+faster.
+
+On the other hand, adaptive scoring is surely a very useful feature (I'm
+just beginning to use it), so many people might prefer total-expire.
+
+And on a third hand, maybe the key binding issue isn't so important
+after all.  You see, in mail groups the @kbd{d} key means `keep this
+message for archival purposes', whereas in many other modes (dired, CCC
+others?) it stands for `delete'.  I propose to make it mean delete in
+mail groups, too, with the following line in
+@file{~/.gnus}:@footnote{See the chapter on key bindings; maybe you need
+a `require' statement.}
+@lisp
+(define-key gnus-summary-mode-map "d" 'gnus-summary-mark-as-expirable)
+@end lisp
+Marking messages as expirable (rather than read) in news groups does no
+harm, nor does it harm to do so in total-expirable mail groups.  The old
+`keep this message' semantics can still be had by marking a message as
+dormant or by using @kbd{M r} (in non-total-expirable groups only).
+
+
+@c ------------------------------------------------------------ 
+@section Migrating old mail
+@c ------------------------------------------------------------ 
+
+Probably, you've been reading mail in pre-Gnus times, right?  And surely
+you wish to carry this over to Gnus.  Well, I haven't found a real good
+way to do it, but I can offer a few suggestions for doing it at least
+semi-automatically.
+
+One way of getting at your old mail is to type @kbd{G f}, and to then
+enter the name of your old mail file.  This provides read-only access to
+your mails.  For some people, this might be sufficient.  (With @kbd{G
+f}, you have created an @code{nndoc} group.)
+
+Some people might want to have their mails available in their normal
+mail groups hierarchy.  That's simple, just create an @code{nndoc} group
+for your mail file, then mark all messages in it with @kbd{M P a}, then
+copy all of them over to a normal mail group, with @kbd{B c}.
+
+This is good for people who wish to keep their old arrangement of
+folders, and who have a one-to-one correspondence between old mail files
+and new Gnus groups.  But some people might wish to split up their mails
+differently.  For them, it might be useful to set up
+@var{nnmail-split-methods} correctly and to use @kbd{B r} instead of
+@kbd{B c}.  This goes through all process-marked messages and subjects
+them to the same splitting process that newly arriving messages go
+through.  (Whee!  What a run-on sentence!)
+
+
+@section TODO
+
+@table @bullet
+@item
+Say something about the cache.  Though this belongs in the news reading
+tips, right?  Hm.
+@end table
+
+
+@c Local Variables:
+@c TeX-master: "tutorials.texi"
+@c End:
index f910c06..4f3060f 100644 (file)
@@ -421,8 +421,8 @@ Move to the signature of the message (@code{message-goto-signature}).
 Yank the message that's being replied to into the message buffer
 (@code{message-yank-original}).
 
-@item C-c C-Y
-@kindex C-c C-Y
+@item C-c M-C-y
+@kindex C-c M-C-y
 @findex message-yank-buffer
 Prompt for a buffer name and yank the contents of that buffer into the
 message buffer (@code{message-yank-buffer}).