Sync up with Pterodactyl Gnus 0.31.
authoryamaoka <yamaoka>
Wed, 16 Sep 1998 00:18:36 +0000 (00:18 +0000)
committeryamaoka <yamaoka>
Wed, 16 Sep 1998 00:18:36 +0000 (00:18 +0000)
A snapshot is available from
 ftp://ftp.jpl.org/pub/tmp/semi-gnus-pgnus-ichikawa-19980916-1.tar.gz

25 files changed:
ChangeLog
lisp/ChangeLog
lisp/base64.el
lisp/date.el [deleted file]
lisp/dgnushack.el
lisp/gnus-agent.el
lisp/gnus-art.el
lisp/gnus-mailcap.el
lisp/gnus-msg.el
lisp/gnus-salt.el
lisp/gnus-sum.el
lisp/gnus.el
lisp/lpath.el
lisp/mail-parse.el
lisp/message.el
lisp/mm-bodies.el
lisp/mm-decode.el
lisp/mm-view.el
lisp/mm.el [deleted file]
lisp/nndoc.el
lisp/rfc2047.el
lisp/rfc2231.el
texi/gnus-ja.texi
texi/gnus.texi
texi/message.texi

index 6c681e6..7baa73a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+1998-09-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.020.
+
+       * lisp/ietf-drums.el: New file.
+       * lisp/date.el: Abolished.
+       * lisp/mm.el: Abolished.
+
+       * Sync up with Pterodactyl Gnus 0.31.
+
+1998-09-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-encode-message-body): Copied from
+       Pterodactyl Gnus 0.30. It is useless for Semi-gnus but usefull for
+       reducing differences while at work for synchronizing up. It will
+       be removed when the Gnus becomes stable.
+       * lisp/gnus-art.el (gnus-mime-display-alternative)
+       (gnus-display-mime) (gnus-widget-press-button)
+       (gnus-insert-mime-button) (gnus-mime-copy-part)
+       (gnus-mime-view-part) (gnus-mime-pipe-part) (gnus-mime-save-part)
+       (gnus-mime-button-map) (gnus-mime-button-line-format-alist)
+       (gnus-mime-button-line-format)
+       (article-mime-decode-quoted-printable-buffer)
+       (article-de-quoted-unreadable) (article-decode-charset)
+       (article-decode-mime-words) (gnus-decode-header-function)
+       (gnus-display-mime-function): Ditto.
+
 1998-09-14  Katsumi Yamaoka   <yamaoka@jpl.org>
 
        * lisp/gnus-art.el (article-decode-encoded-words): Renamed from
index 3167492..7a63038 100644 (file)
@@ -1,4 +1,113 @@
-Sun Sep 13 09:37:37 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+Mon Sep 14 18:55:38 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.31 is released.
+
+1998-09-14 15:12:59  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-exit): Destroy MIME.
+
+       * mm-decode.el (mm-display-part): Accept no-default.
+
+       * gnus-art.el (gnus-insert-mime-button): buffer-size doesn't take
+       a parameter.
+
+       * gnus-sum.el (gnus-summary-insert-line): Don't exclude faces.
+       (gnus-summary-prepare-threads): Ditto.
+
+       * gnus.el (gnus-article-mode-map): Make sparse keymap.
+
+       * gnus-art.el (gnus-mime-button-line-format-alist): Allow a %d spec.
+       (gnus-mime-button-line-format): Doc fix.
+       (gnus-insert-mime-button): Use it.
+       (gnus-article-add-button): Use widget-convert-button.
+
+       * gnus.el ((featurep 'gnus-xmas)): Defalias gnus-decode-rfc1522 to
+       ignore.
+
+       * mm-decode.el (mm-alternative-precedence): Ditto.
+
+1998-09-14 15:12:49  Conrad Sauerwald  <conrad@stack.nl>
+
+       * mm-decode.el (mm-user-automatic-display): Use enriched.
+
+1998-09-14 15:09:12  Paul Fisher  <rao@gnu.org>
+
+       * mm-decode.el (mm-dissect-multipart): Have the part start on the
+       right place.
+
+1998-09-14 14:33:34  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-inews-add-send-actions): Mark silently.
+
+       * gnus-art.el (article-update-date-lapsed): Only update header if
+       buffer is dispalyed in frame.
+       (gnus-article-prepare-display): New function.
+       (gnus-article-prepare): Use it.
+
+1998-09-14 08:16:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-inline-part): New command and keystroke.
+
+       * mm-view.el (mm-insert-inline): New function.
+
+       * mm-decode.el (mm-pipe-part): Bugged.
+
+       * gnus-agent.el (gnus-agent-send-mail): Don't encode.
+
+       * mm-bodies.el (mm-encode-body): Move over the body.
+
+       * nnmbox.el (nnmbox-read-mbox): Enable multibyte.
+
+       * rfc2047.el (rfc2047-q-encode-region): Would bug out.
+
+1998-09-13  François Pinard  <pinard@iro.umontreal.ca>
+
+       * nndoc.el: Make nndoc-dissection-alist simpler for MIME, adjust all
+          related functions.  Handle message/rfc822 parts.  Display subject on
+          multipart summary lines.  Display name on sub-parts when available.
+
+1998-09-14 07:36:38  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+
+       * mailcap.el (mailcap-command-p): New version.
+
+1998-09-13  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus-agent.el (gnus-agent-expire): Stop expiry barfing on killed
+       groups.
+
+1998-09-13 18:34:06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-make-date): Remove weekday name.
+
+       * mm-decode.el (mm-dissect-buffer): Protect against broken
+       headers.
+
+       * mailcap.el (mailcap-command-in-path-p): New function.
+       (mailcap-command-p): Renamed.
+
+1998-09-13 17:58:47  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+
+       * rfc2047.el (eval): Autoload.
+
+1998-09-13 12:22:40  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-decode-encoded-word-functions): New variable.
+       (gnus-multi-decode-encoded-word-string): New function.
+       (gnus-encoded-word-method-alist): New variable.
+       (gnus-decode-encoded-word-functions): Removed.
+
+1998-09-13  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-int.el (gnus-request-replace-article): Replace
+       message-narrow-to-headers with message-narrow-to-head
+
+1998-09-13 12:05:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * drums.el (drums-quote-string): Reversed match.
+
+       * message.el (message-make-date): Use weekday name.
+
+Sun Sep 11 10:27:15 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
        * gnus.el: Pterodactyl Gnus v0.30 is released.
 
@@ -11,7 +120,7 @@ Sun Sep 13 09:37:37 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        (gnus-decode-encoded-word-function): New variable.
 
        * gnus-msg.el (gnus-copy-article-buffer): Decode the right
-       buffer. 
+       buffer.
 
        * gnus-art.el (gnus-insert-mime-button): Use widget.
        (gnus-widget-press-button): New function.
@@ -32,21 +141,21 @@ Sun Sep 13 09:37:37 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-13 07:58:59  Shenghuo ZHU  <zsh@cs.rochester.edu>
 
        * gnus-sum.el (gnus-summary-move-article): Don't decode accepting
-       articles. 
+       articles.
 
 1998-09-13 07:23:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * mm-util.el (mm-mime-charset): Try to use safe-charsets.
        (mm-default-mime-charset): New variable.
 
-       * rfc2047.el (rfc2047-dissect-region): Dissect using tspecials. 
+       * rfc2047.el (rfc2047-dissect-region): Dissect using tspecials.
 
        * drums.el (drums-quote-string): Reversed test.
 
 1998-09-12 14:29:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * mm-util.el (mm-insert-rfc822-headers): Possibly not quote
-       string. 
+       string.
 
        * drums.el (drums-quote-string): New function.
 
@@ -65,7 +174,7 @@ Sat Sep 12 13:27:15 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-12 11:30:01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * drums.el (drums-parse-address): Returned a list instead of a
-       string. 
+       string.
        (drums-remove-whitespace): Skip comments.
        (drums-parse-addresses): Didn't work.
 
@@ -82,10 +191,10 @@ Sat Sep 12 09:17:30 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * message.el (message-narrow-to-headers-or-head): New function.
 
        * gnus-int.el (gnus-request-accept-article): Narrow to the right
-       region. 
+       region.
 
        * message.el (message-send-news): Encode body after checking
-       syntax. 
+       syntax.
 
        * gnus-art.el (gnus-mime-button-line-format): Allow descriptions.
 
@@ -99,10 +208,10 @@ Sat Sep 12 09:17:30 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        text with annotations.
 
        * message.el (message-make-date): Fix sign for negative time
-       zones. 
+       zones.
 
        * mm-view.el (mm-inline-image): Insert a space at the end of the
-       image. 
+       image.
 
        * mail-parse.el: New file.
 
@@ -111,7 +220,7 @@ Sat Sep 12 09:17:30 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * drums.el (drums-content-type-get): Removed.
        (drums-parse-content-type): Ditto.
 
-       * mailcap.el (mailcap-mime-data): Use symbols instead of strings. 
+       * mailcap.el (mailcap-mime-data): Use symbols instead of strings.
 
 Fri Sep 11 18:23:34 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
@@ -143,12 +252,12 @@ Fri Sep 11 12:32:50 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
        * mm-decode.el (mm-last-shell-command): New variable.
 
-       * mailcap.el (mailcap-mime-info): Allow returning all matches. 
+       * mailcap.el (mailcap-mime-info): Allow returning all matches.
 
        * mm-decode.el (mm-save-part): New function.
 
        * gnus-art.el (article-decode-charset): Protect against buggy
-       content-types. 
+       content-types.
        (gnus-mime-pipe-part): New command.
        (gnus-mime-save-part): New command.
        (gnus-mime-button-map): New keymap.
@@ -163,10 +272,10 @@ Fri Sep 11 12:32:50 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * gnus-art.el (gnus-article-save): Comment fix.
 
        * gnus-int.el (gnus-start-news-server): When in batch, don't
-       prompt. 
+       prompt.
 
        * gnus-cache.el (gnus-cache-possibly-enter-article): Don't
-       decode. 
+       decode.
 
        * mm-decode.el (mm-inline-media-tests): Add audio.
        (mm-inline-audio): New function.
@@ -184,7 +293,7 @@ Fri Sep 11 08:09:40 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-11 07:38:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus-art.el (article-remove-trailing-blank-lines): Don't remove
-       annotations. 
+       annotations.
 
        * gnus.el ((featurep 'gnus-xmas)): New
        'gnus-annotation-in-region-p alias.
@@ -232,22 +341,22 @@ Thu Sep 10 04:03:29 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-10 01:58:24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus-sum.el (gnus-summary-show-article): Don't decode chars if
-       PREFIX. 
+       PREFIX.
 
        * parse-time.el (parse-time-rules): Accept times that look like
-       "h:mm". 
+       "h:mm".
 
        * message.el (message-make-date): Use zone properly.
 
        * gnus.el: Autoload gnus-batch.
 
        * gnus-art.el (article-de-quoted-unreadable): Do not do
-       gnus-article-decode-rfc1522. 
+       gnus-article-decode-rfc1522.
 
        * gnus-msg.el (gnus-inews-do-gcc): Use it.
 
        * gnus-int.el (gnus-request-accept-article): Accept a no-encode
-       param. 
+       param.
 
        * message.el (message-encode-message-body): Check for us-ascii.
 
@@ -304,7 +413,7 @@ Tue Sep  8 21:43:03 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-08 11:40:45  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * rfc2047.el (rfc2047-decode-region): Only decode when in
-       multibyte. 
+       multibyte.
 
        * nnheader.el (nnheader-pathname-coding-system): Changed to binary.
 
@@ -312,10 +421,10 @@ Tue Sep  8 21:43:03 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        (gnus-request-accept-article): Encode.
 
        * gnus-art.el (gnus-request-article-this-buffer): Decode charsets
-       here. 
+       here.
 
        * gnus.el (gnus-article-display-hook): Take the charset functions
-       out.  
+       out.
 
        * time-date.el (safe-date-to-time): New function.
 
@@ -364,7 +473,7 @@ Tue Sep  8 04:29:23 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
        * time-date.el (time-to-seconds): Renamed.
 
-       * parse-time.el (parse-time-string): Downcase before handling. 
+       * parse-time.el (parse-time-string): Downcase before handling.
        (parse-time-rules): Times without seconds have 0 seconds.
 
        * rfc2047.el (rfc2047-encode-region): New version.
@@ -414,10 +523,10 @@ Sun Sep  6 21:19:26 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * date.el (if): Use parse-time.
 
        * gnus-score.el (gnus-summary-score-entry): Make into a command
-       again. 
+       again.
 
        * gnus-group.el (gnus-group-get-new-news-this-group): Only call if
-       gnus-agent. 
+       gnus-agent.
 
        * gnus.el (gnus-agent-meta-information-header): Moved here.
 
@@ -452,7 +561,7 @@ Sun Sep  6 21:19:26 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-05 22:23:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus-art.el (gnus-article-decode-charset): Only decode text
-       things. 
+       things.
 
        * message.el (message-output): Use rmail.
 
@@ -460,7 +569,7 @@ Sun Sep  6 21:19:26 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        word part.
 
        * mm-util.el (mm-charset-to-coding-system): Use
-       rfc2047-default-charset. 
+       rfc2047-default-charset.
        (mm-known-charsets): New variable.
 
        * message.el (message-caesar-region): Bugged out.
@@ -484,7 +593,7 @@ Sat Sep  5 21:55:01 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        from the headers.
 
        * rfc2047.el (rfc2047-decode-region): Use the mm decoding
-       functions. 
+       functions.
 
        * gnus-group.el (gnus-group-sort-selected-flat): Didn't work at
        all.
@@ -527,7 +636,7 @@ Sat Sep  5 01:45:52 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * gnus-util.el (gnus-output-to-rmail): Removed.
 
        * gnus-art.el (gnus-summary-save-in-rmail): Use
-       gnus-output-to-rmailrmail-output-to-rmail-file. 
+       gnus-output-to-rmailrmail-output-to-rmail-file.
 
        * rfc2047.el (rfc2047-decode-region): Fold case.
        (rfc2047-decode): Use decode-string.
@@ -546,10 +655,10 @@ Thu Sep  3 15:23:22 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-02 14:38:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus-msg.el (gnus-post-method): Use opened servers, and remove
-       ducplicates. 
+       ducplicates.
        (gnus-inews-insert-mime-headers): Removed.
 
-       * message.el (message-caesar-region): Protect against MULE chars. 
+       * message.el (message-caesar-region): Protect against MULE chars.
 
 1998-09-02 00:36:23  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
 
@@ -558,14 +667,14 @@ Thu Sep  3 15:23:22 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-02 00:31:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus-art.el (gnus-article-decode-charset): Use real
-       read-coding-system. 
+       read-coding-system.
 
 1998-09-01 17:58:40  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * mm-bodies.el (mm-decode-body): Protect against malformed
-       base64. 
+       base64.
        (mm-decode-body): Check that buffer-file-coding-system is
-       non-nil. 
+       non-nil.
 
 Tue Sep  1 10:29:33 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
@@ -574,7 +683,7 @@ Tue Sep  1 10:29:33 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-09-01 09:14:33  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus-util.el (gnus-strip-whitespace): Already defined.
-       Removed. 
+       Removed.
 
        * gnus-art.el (gnus-article-decode-charset): Strip whitespace.
 
@@ -594,7 +703,7 @@ Tue Sep  1 10:29:33 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * gnus-sum.el (gnus-summary-mode-line-format): Ditto.
 
        * gnus-art.el (gnus-article-mode-line-format): Use short group
-       format. 
+       format.
 
 Mon Aug 31 23:03:13 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
@@ -618,7 +727,7 @@ Mon Aug 31 22:14:50 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * message.el (message-encode-message-body): Ditto.
 
        * gnus-art.el (gnus-article-decode-mime-words): New command and
-       keystroke. 
+       keystroke.
        (gnus-article-decode-charset): Ditto.
        (gnus-article-decode-charset): Only work under MULE.
 
@@ -723,7 +832,7 @@ Sun Aug 30 17:46:01 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * mm-encode.el (mm-q-encode-region): New function.
 
        * qp.el (quoted-printable-encode-region): Take an optional CLASS
-       param. 
+       param.
 
        * mm-encode.el (mm-encode-word-region): Downcase.
 
@@ -748,7 +857,7 @@ Sun Aug 30 15:28:01 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
        * message.el (message-narrow-to-header): New function.
 
-       * gnus-art.el (gnus-article-decode-mime-words): Place point in the 
+       * gnus-art.el (gnus-article-decode-mime-words): Place point in the
        right buffer.
 
 Sun Aug 30 12:15:54 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
@@ -781,7 +890,7 @@ Sun Aug 30 00:59:15 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
        * nnheader.el (fboundp): Protect code-coding-string.
 
-       * gnus-art.el (gnus-article-mode): Check that set-buffer-multibyte 
+       * gnus-art.el (gnus-article-mode): Check that set-buffer-multibyte
        is available.
 
 Sat Aug 29 23:24:31 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
@@ -790,7 +899,7 @@ Sat Aug 29 23:24:31 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
 1998-08-29 22:38:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-art.el (gnus-article-mode): Make article buffer multibyte. 
+       * gnus-art.el (gnus-article-mode): Make article buffer multibyte.
        (gnus-hack-decode-rfc1522): Removed.
 
        * mm-decode.el (mm-charset-coding-system-alist): Check better.
@@ -802,7 +911,7 @@ Sat Aug 29 22:20:39 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 1998-08-29 20:53:29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus-art.el (gnus-article-decode-mime-words): New command and
-       keystroke. 
+       keystroke.
 
        * qp.el (quoted-printable-decode-region): Don't use hexl.
 
@@ -825,7 +934,7 @@ Sat Aug 29 22:20:39 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
        * gnus-ems.el (fboundp): Don't bind mail-file-babyl-p.
 
        * gnus-art.el (article-mime-decode-quoted-printable): Don't use
-       hexl. 
+       hexl.
 
        * nnheader.el (nnheader-temp-write): Removed.
 
@@ -836,4 +945,3 @@ Sat Aug 29 20:34:17 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 Sat Aug 29 19:32:06 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
 
        * gnus.el: Gnus v0.2 is released.
-
index 3d89247..093673e 100644 (file)
@@ -25,8 +25,6 @@
 ;;; Boston, MA 02111-1307, USA.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(require 'mm-util)
-
 ;; For non-MULE
 (if (not (fboundp 'char-int))
     (fset 'char-int 'identity))
@@ -110,7 +108,7 @@ base64-encoder-program.")
      (base64-insert-char char count ignored buffer))))
 
 (defun base64-xemacs-insert-char (char &optional count ignored buffer)
-  (if (and buffer (eq buffer (current-buffer)))
+  (if (or (null buffer) (eq buffer (current-buffer)))
       (insert-char char count)
     (save-excursion
       (set-buffer buffer)
@@ -276,4 +274,6 @@ base64-encoder-program.")
        (buffer-string)
       (kill-buffer (current-buffer)))))  
 
+(fset 'base64-decode-string 'base64-decode)
+
 (provide 'base64)
diff --git a/lisp/date.el b/lisp/date.el
deleted file mode 100644 (file)
index b593e1c..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-;;; date.el --- Date and time handling functions
-;; Copyright (C) 1998 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
-;;     Masanobu Umeda <umerin@mse.kyutech.ac.jp>
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'timezone)
-
-(defun parse-time-string (date)
-  "Convert DATE into time."
-  (decode-time
-   (condition-case ()
-       (let* ((d1 (timezone-parse-date date))
-             (t1 (timezone-parse-time (aref d1 3))))
-        (apply 'encode-time
-               (mapcar (lambda (el)
-                         (and el (string-to-number el)))
-                       (list
-                        (aref t1 2) (aref t1 1) (aref t1 0)
-                        (aref d1 2) (aref d1 1) (aref d1 0)
-                        (number-to-string
-                         (* 60 (timezone-zone-to-minute (aref d1 4))))))))
-     ;; If we get an error, then we just return a 0 time.
-     (error (list 0 0)))))
-
-(defun date-to-time (date)
-  "Convert DATE into time."
-  (apply 'encode-time (parse-time-string date)))
-
-(defun time-less-p (t1 t2)
-  "Say whether time T1 is less than time T2."
-  (or (< (car t1) (car t2))
-      (and (= (car t1) (car t2))
-          (< (nth 1 t1) (nth 1 t2)))))
-
-(defun days-to-time (days)
-  "Convert DAYS into time."
-  (let* ((seconds (* 1.0 days 60 60 24))
-        (rest (expt 2 16))
-        (ms (condition-case nil (floor (/ seconds rest))
-              (range-error (expt 2 16)))))
-    (list ms (condition-case nil (round (- seconds (* ms rest)))
-              (range-error (expt 2 16))))))
-
-(defun time-since (time)
-  "Return the time since TIME, which is either an internal time or a date."
-  (when (stringp time)
-    ;; Convert date strings to internal time.
-    (setq time (date-to-time time)))
-  (let* ((current (current-time))
-        (rest (when (< (nth 1 current) (nth 1 time))
-                (expt 2 16))))
-    (list (- (+ (car current) (if rest -1 0)) (car time))
-         (- (+ (or rest 0) (nth 1 current)) (nth 1 time)))))
-
-(defun subtract-time (t1 t2)
-  "Subtract two internal times."
-  (let ((borrow (< (cadr t1) (cadr t2))))
-    (list (- (car t1) (car t2) (if borrow 1 0))
-         (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
-
-(defun date-to-day (date)
-  "Return the number of days between year 1 and DATE."
-  (time-to-day (date-to-time date)))
-  
-(defun days-between (date1 date2)
-  "Return the number of days between DATE1 and DATE2."
-  (- (date-to-day date1) (date-to-day date2)))
-
-(defun date-leap-year-p (year)
-  "Return t if YEAR is a leap year."
-  (or (and (zerop (% year 4))
-          (not (zerop (% year 100))))
-      (zerop (% year 400))))
-
-(defun time-to-day-in-year (time)
-  "Return the day number within the year of the date month/day/year."
-  (let* ((tim (decode-time time))
-        (month (nth 4 tim))
-        (day (nth 3 tim))
-        (year (nth 5 tim))
-        (day-of-year (+ day (* 31 (1- month)))))
-    (when (> month 2)
-      (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10)))
-      (when (date-leap-year-p year)
-       (setq day-of-year (1+ day-of-year))))
-    day-of-year))
-
-(defun time-to-day (time)
-  "The number of days between the Gregorian date 0001-12-31bce and TIME.
-The Gregorian date Sunday, December 31, 1bce is imaginary."
-  (let* ((tim (decode-time time))
-        (month (nth 4 tim))
-        (day (nth 3 tim))
-        (year (nth 5 tim)))
-    (+ (time-to-day-in-year time)      ;       Days this year
-       (* 365 (1- year))               ;       + Days in prior years
-       (/ (1- year) 4)                 ;       + Julian leap years
-       (- (/ (1- year) 100))           ;       - century years
-       (/ (1- year) 400))))            ;       + Gregorian leap years
-
-(provide 'date)
-
-;;; date.el ends here
index a5d1d65..c2b4f82 100644 (file)
@@ -30,7 +30,6 @@
 
 (require 'cl)
 (require 'bytecomp)
-(push "~/lisp/custom" load-path)
 (push "." load-path)
 (load "./lpath.el" nil t)
 
index 479f601..1d7fd45 100644 (file)
@@ -341,7 +341,7 @@ agent minor mode in all Gnus buffers."
      (concat "^" (regexp-quote mail-header-separator) "\n"))
     (replace-match "\n")
     (gnus-agent-insert-meta-information 'mail)
-    (gnus-request-accept-article "nndraft:queue")))
+    (gnus-request-accept-article "nndraft:queue" nil t t)))
 
 (defun gnus-agent-insert-meta-information (type &optional method)
   "Insert meta-information into the message that says how it's to be posted.
@@ -535,9 +535,13 @@ the actual number of articles toggled is returned."
     (gnus-make-directory (file-name-directory file))
     (let ((coding-system-for-write
           gnus-agent-file-coding-system))
-      (write-region (point-min) (point-max) file nil 'silent)))
-  (when (file-exists-p (gnus-agent-lib-file "active"))
-    (delete-file (gnus-agent-lib-file "active"))))
+      (write-region (point-min) (point-max) file nil 'silent))
+
+    );;<-- correct?
+
+    (when (file-exists-p (gnus-agent-lib-file "active"))
+      (delete-file (gnus-agent-lib-file "active"))))
+;  )
 
 (defun gnus-agent-save-group-info (method group active)
   (when (gnus-agent-method-p method)
@@ -1421,7 +1425,7 @@ The following commands are available:
               (gnus-agent-save-alist group)
                ;; Mark all articles up to the first article
               ;; in `gnus-article-alist' as read.
-              (when (caar gnus-agent-article-alist)
+              (when (and info (caar gnus-agent-article-alist))
                 (setcar (nthcdr 2 info)
                         (gnus-range-add
                          (nth 2 info)
index d440f6d..521cd03 100644 (file)
@@ -95,7 +95,7 @@
 
 (defcustom gnus-ignored-headers
   '("^Path:" "^Expires:" "^Date-Received:" "^References:" "^Xref:" "^Lines:"
-    "^Relay-Version:" "^Message-ID:" "^Approved:" "^Sender:" "^Received:" 
+    "^Relay-Version:" "^Message-ID:" "^Approved:" "^Sender:" "^Received:"
     "^X-UIDL:" "^MIME-Version:" "^Return-Path:" "^In-Reply-To:"
     "^Content-Type:" "^Content-Transfer-Encoding:" "^X-WebTV-Signature:"
     "^X-MimeOLE:" "^X-MSMail-Priority:" "^X-Priority:" "^X-Loop:"
     "^X-Complaints-To:" "^X-NNTP-Posting-Host:" "^X-Orig.*:"
     "^Abuse-Reports-To:" "^Cache-Post-Path:" "^X-Article-Creation-Date:"
     "^X-Poster:" "^X-Mail2News-Path:" "^X-Server-Date:" "^X-Cache:"
-    "^Originator:" "^X-Problems-To:" "^X-Auth-User:" "^X-Post-Time:" 
+    "^Originator:" "^X-Problems-To:" "^X-Auth-User:" "^X-Post-Time:"
     "^X-Admin:" "^X-UID:" "^Resent-[-A-Za-z]+:" "^X-Mailing-List:"
     "^Precedence:" "^Original-[-A-Za-z]+:" "^X-filename:" "^X-Orcpt:"
     "^Old-Received:" "^X-Pgp-Fingerprint:" "^X-Pgp-Key-Id:"
@@ -556,6 +556,14 @@ displayed by the first non-nil matching CONTENT face."
   :group 'gnus-article-headers
   :type 'hook)
 
+(defcustom gnus-display-mime-function 'gnus-display-mime
+  "Function to display MIME articles."
+  :group 'gnus-article-headers
+  :type 'function)
+
+(defvar gnus-decode-header-function 'mail-decode-encoded-word-region
+  "Function used to decode headers.")
+
 ;;; Internal variables
 
 (defvar article-lapsed-timer nil)
@@ -958,6 +966,46 @@ characters to translate to."
                  (process-send-region "article-x-face" beg end)
                  (process-send-eof "article-x-face"))))))))))
 
+(defun article-decode-mime-words ()
+  "Decode all MIME-encoded words in the article."
+  (interactive)
+  (save-excursion
+    (set-buffer gnus-article-buffer)
+    (let ((inhibit-point-motion-hooks t)
+         buffer-read-only)
+      (mail-decode-encoded-word-region (point-min) (point-max)))))
+
+(defun article-decode-charset (&optional prompt)
+  "Decode charset-encoded text in the article.
+If PROMPT (the prefix), prompt for a coding system to use."
+  (interactive "P")
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-head)
+      (let* ((inhibit-point-motion-hooks t)
+            (ct (message-fetch-field "Content-Type" t))
+            (cte (message-fetch-field "Content-Transfer-Encoding" t))
+            (ctl (and ct (condition-case ()
+                             (mail-header-parse-content-type ct)
+                           (error nil))))
+            (charset (cond
+                      (prompt
+                       (mm-read-coding-system "Charset to decode: "))
+                      (ctl
+                       (mail-content-type-get ctl 'charset))
+                      (gnus-newsgroup-name
+                       (gnus-group-find-parameter
+                        gnus-newsgroup-name 'charset))))
+            buffer-read-only)
+       (goto-char (point-max))
+       (widen)
+       (narrow-to-region (point) (point-max))
+       (when (or (not ct)
+                 (equal (car ctl) "text/plain"))
+         (mm-decode-body
+          charset (and cte (intern (downcase
+                                    (gnus-strip-whitespace cte))))))))))
+
 (defun article-decode-encoded-words ()
   "Remove encoded-word encoding from headers."
   (let (buffer-read-only)
@@ -967,6 +1015,24 @@ characters to translate to."
       (eword-decode-header charset)
       )))
 
+(defun article-de-quoted-unreadable (&optional force)
+  "Translate a quoted-printable-encoded article.
+If FORCE, decode the article whether it is marked as quoted-printable
+or not."
+  (interactive (list 'force))
+  (save-excursion
+    (let ((buffer-read-only nil)
+         (type (gnus-fetch-field "content-transfer-encoding")))
+      (when (or force
+               (and type (string-match "quoted-printable" (downcase type))))
+       (goto-char (point-min))
+       (search-forward "\n\n" nil 'move)
+       (quoted-printable-decode-region (point) (point-max))))))
+
+(defun article-mime-decode-quoted-printable-buffer ()
+  "Decode Quoted-Printable in the current buffer."
+  (quoted-printable-decode-region (point-min) (point-max)))
+
 (defun article-hide-pgp (&optional arg)
   "Toggle hiding of any PGP headers and signatures in the current article.
 If given a negative prefix, always show; if given a positive prefix,
@@ -1397,7 +1463,8 @@ function and want to see what the date was before converting."
   (let (deactivate-mark)
     (save-excursion
       (ignore-errors
-        (when (gnus-buffer-live-p gnus-article-buffer)
+        (when (and (gnus-buffer-live-p gnus-article-buffer)
+                  (get-buffer-window gnus-article-buffer))
           (set-buffer gnus-article-buffer)
           (goto-char (point-min))
           (when (re-search-forward "^X-Sent:" nil t)
@@ -2083,22 +2150,7 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                      (or all-headers gnus-show-all-headers))))
            (when (or (numberp article)
                      (stringp article))
-             (let ((method
-                    (if gnus-show-mime
-                        (progn
-                          (mime-parse-buffer)
-                          gnus-article-display-method-for-mime)
-                      gnus-article-display-method-for-traditional)))
-               ;; Hooks for getting information from the article.
-               ;; This hook must be called before being narrowed.
-               (gnus-run-hooks 'gnus-tmp-internal-hook)
-               (gnus-run-hooks 'gnus-article-prepare-hook)
-               ;; Display message.
-               (funcall method)
-               ;; Associate this article with the current summary buffer.
-               (setq gnus-article-current-summary summary-buffer)
-               ;; Perform the article display hooks.
-               (gnus-run-hooks 'gnus-article-display-hook))
+             (gnus-article-prepare-display)
              ;; Do page break.
              (goto-char (point-min))
              (setq gnus-page-broken
@@ -2112,6 +2164,179 @@ If ALL-HEADERS is non-nil, no headers are hidden."
            (set-window-point (get-buffer-window (current-buffer)) (point))
            t))))))
 
+(defun gnus-article-prepare-display ()
+  "Make the current buffer look like a nice article."
+  (let ((method (if gnus-show-mime
+                   (progn
+                     (mime-parse-buffer)
+                     gnus-article-display-method-for-mime)
+                 gnus-article-display-method-for-traditional)))
+    ;; Hooks for getting information from the article.
+    ;; This hook must be called before being narrowed.
+    (gnus-run-hooks 'gnus-tmp-internal-hook)
+    (gnus-run-hooks 'gnus-article-prepare-hook)
+    ;; Display message.
+    (funcall method)
+    ;; Associate this article with the current summary buffer.
+    (setq gnus-article-current-summary summary-buffer)
+    ;; Perform the article display hooks.
+    (gnus-run-hooks 'gnus-article-display-hook)))
+
+;;;
+;;; Gnus MIME viewing functions
+;;;
+
+(defvar gnus-mime-button-line-format "%{%([%t%d%n]%)%}\n"
+  "The following specs can be used:
+%t  The MIME type
+%n  The `name' parameter
+%n  The description, if any
+%l  The length of the encoded part")
+
+(defvar gnus-mime-button-line-format-alist
+  '((?t gnus-tmp-type ?s)
+    (?n gnus-tmp-name ?s)
+    (?d gnus-tmp-description ?s)
+    (?l gnus-tmp-length ?d)))
+
+(defvar gnus-mime-button-map nil)
+(unless gnus-mime-button-map
+  (setq gnus-mime-button-map (copy-keymap gnus-article-mode-map))
+  (define-key gnus-mime-button-map gnus-mouse-2 'gnus-article-push-button)
+  (define-key gnus-mime-button-map "\r" 'gnus-article-press-button)
+  (define-key gnus-mime-button-map "\M-\r" 'gnus-mime-view-part)
+  (define-key gnus-mime-button-map "v" 'gnus-mime-view-part)
+  (define-key gnus-mime-button-map "o" 'gnus-mime-save-part)
+  (define-key gnus-mime-button-map "c" 'gnus-mime-copy-part)
+  (define-key gnus-mime-button-map "i" 'gnus-mime-inline-part)
+  (define-key gnus-mime-button-map "|" 'gnus-mime-pipe-part))
+
+(defun gnus-mime-save-part ()
+  "Save the MIME part under point."
+  (interactive)
+  (let ((data (get-text-property (point) 'gnus-data)))
+    (mm-save-part data)))
+
+(defun gnus-mime-pipe-part ()
+  "Pipe the MIME part under point to a process."
+  (interactive)
+  (let ((data (get-text-property (point) 'gnus-data)))
+    (mm-pipe-part data)))
+
+(defun gnus-mime-view-part ()
+  "Interactively choose a view method for the MIME part under point."
+  (interactive)
+  (let ((data (get-text-property (point) 'gnus-data)))
+    (mm-interactively-view-part data)))
+
+(defun gnus-mime-copy-part ()
+  "Put the the MIME part under point into a new buffer."
+  (interactive)
+  (let* ((data (get-text-property (point) 'gnus-data))
+        (contents (mm-get-part data)))
+    (switch-to-buffer (generate-new-buffer "*decoded*"))
+    (insert contents)
+    (goto-char (point-min))))
+
+(defun gnus-mime-inline-part ()
+  "Insert the MIME part under point into the current buffer."
+  (interactive)
+  (let* ((data (get-text-property (point) 'gnus-data))
+        (contents (mm-get-part data))
+        (b (point))
+        buffer-read-only)
+    (forward-line 2)
+    (mm-insert-inline data contents)
+    (goto-char b)))
+
+(defun gnus-insert-mime-button (handle)
+  (let ((gnus-tmp-name (mail-content-type-get (mm-handle-type handle) 'name))
+       (gnus-tmp-type (car (mm-handle-type handle)))
+       (gnus-tmp-description (mm-handle-description handle))
+       (gnus-tmp-length (save-excursion
+                          (set-buffer (mm-handle-buffer handle))
+                          (buffer-size)))
+       b e)
+    (setq gnus-tmp-name
+      (if gnus-tmp-name
+         (concat " (" gnus-tmp-name ")")
+       ""))
+    (setq gnus-tmp-description
+      (if gnus-tmp-description
+         (concat " (" gnus-tmp-description ")")
+       ""))
+    (setq b (point))
+    (gnus-eval-format
+     gnus-mime-button-line-format gnus-mime-button-line-format-alist
+     `(local-map ,gnus-mime-button-map
+                keymap ,gnus-mime-button-map
+                gnus-callback mm-display-part
+                gnus-data ,handle))
+    (setq e (point))
+    (widget-convert-button 'link b e :action 'gnus-widget-press-button)))
+
+(defun gnus-widget-press-button (elems el)
+  (goto-char (widget-get elems :from))
+  (gnus-article-press-button))
+
+(defun gnus-display-mime ()
+  "Insert MIME buttons in the buffer."
+  (let (ct ctl)
+    (save-restriction
+      (mail-narrow-to-head)
+      (when (setq ct (mail-fetch-field "content-type"))
+       (setq ctl (mail-header-parse-content-type ct))))
+    (let* ((handles (mm-dissect-buffer))
+          handle name type b e)
+      (mapcar 'mm-destroy-part gnus-article-mime-handles)
+      (setq gnus-article-mime-handles handles)
+      (when handles
+       (goto-char (point-min))
+       (search-forward "\n\n" nil t)
+       (delete-region (point) (point-max))
+       (if (not (equal (car ctl) "multipart/alternative"))
+           (while (setq handle (pop handles))
+             (gnus-insert-mime-button handle)
+             (insert "\n\n")
+             (when (and (mm-automatic-display-p (car (mm-handle-type handle)))
+                        (or (not (mm-handle-disposition handle))
+                            (equal (car (mm-handle-disposition handle))
+                                   "inline")))
+               (forward-line -2)
+               (mm-display-part handle t)
+               (goto-char (point-max))))
+         ;; Here we have multipart/alternative
+         (gnus-mime-display-alternative handles))))))
+
+(defun gnus-mime-display-alternative (handles &optional preferred)
+  (let* ((preferred (mm-preferred-alternative handles preferred))
+        (ihandles handles)
+        handle buffer-read-only)
+    (goto-char (point-min))
+    (search-forward "\n\n" nil t)
+    (delete-region (point) (point-max))
+    (mapcar 'mm-remove-part gnus-article-mime-handles)
+    (setq gnus-article-mime-handles handles)
+    (while (setq handle (pop handles))
+      (gnus-add-text-properties
+       (point)
+       (progn
+        (insert (format "[%c] %-18s"
+                        (if (equal handle preferred) ?* ? )
+                        (car (mm-handle-type handle))))
+        (point))
+       `(local-map ,gnus-mime-button-map
+                  keymap ,gnus-mime-button-map
+                  gnus-callback
+                  (lambda (handles)
+                    (gnus-mime-display-alternative
+                     ',ihandles ,(car (mm-handle-type handle))))
+                  gnus-data ,handle))
+      (insert "  "))
+    (insert "\n\n")
+    (when preferred
+      (mm-display-part preferred))))
+
 (defun gnus-article-wash-status ()
   "Return a string which display status of article washing."
   (save-excursion
@@ -2522,7 +2747,7 @@ If given a prefix, show the hidden text instead."
 
        ;; Decode charsets.
        (run-hooks 'gnus-article-decode-hook))
-      
+
       ;; Update sparse articles.
       (when (and do-update-line
                 (or (numberp article)
@@ -2705,7 +2930,7 @@ groups."
     ("\\bin\\( +article\\| +message\\)? +\\(<\\([^\n @<>]+@[^\n @<>]+\\)>\\)" 2
      t gnus-button-message-id 3)
     ("\\(<URL: *\\)mailto: *\\([^> \n\t]+\\)>" 0 t gnus-url-mailto 2)
-    ("mailto:\\([a-zA-Z.-@_+0-9%]+\\)" 0 t gnus-url-mailto 1)
+    ("mailto:\\([-a-zA-Z.@_+0-9%]+\\)" 0 t gnus-url-mailto 1)
     ("\\bmailto:\\([^ \n\t]+\\)" 0 t gnus-url-mailto 1)
     ;; This is how URLs _should_ be embedded in text...
     ("<URL: *\\([^>]*\\)>" 0 t gnus-button-embedded-url 1)
index 44ae372..0cf68b2 100644 (file)
       (viewer . "open %s")
       (type   . "application/postscript")
       (test   . (eq (mm-device-type) 'ns)))
-     ("postscript" 
+     ("postscript"
       (viewer . "ghostview %s")
       (type . "application/postscript")
       (test   . (eq (mm-device-type) 'x))
       (type   . "audio/*")))
     ("message"
      ("rfc-*822"
+      (viewer . gnus-article-prepare-display)
+      (test   . (and (featurep 'gnus)
+                    (gnus-alive-p)))
+      (type   . "message/rfc-822"))
+     ("rfc-*822"
       (viewer . vm-mode)
       (test   . (fboundp 'vm-mode))
       (type   . "message/rfc-822"))
       (viewer . view-mode)
       (test   . (fboundp 'view-mode))
       (type   . "message/rfc-822"))
-     ("rfc-*822" 
+     ("rfc-*822"
       (viewer . fundamental-mode)
       (type   . "message/rfc-822")))
     ("image"
       (type    . "text/plain"))
      ("enriched"
       (viewer . enriched-decode-region)
-      (test   . (fboundp 'enriched-decode-region))
+      (test   . (fboundp 'enriched-decode))
       (type   . "text/enriched"))
      ("html"
       (viewer . mm-w3-prepare-buffer)
@@ -425,7 +430,7 @@ If FORCE, re-parse even if already parsed."
                (setq done t))))
          (setq value (buffer-substring val-pos (point))))
        (setq results (cons (cons name value) results)))
-      results)))  
+      results)))
 
 (defun mailcap-mailcap-entry-passes-test (info)
   ;; Return t iff a mailcap entry passes its test clause or no test
@@ -591,7 +596,7 @@ If FORCE, re-parse even if already parsed."
 
 (defun mailcap-mime-info (string &optional request)
   "Get the MIME viewer command for STRING, return nil if none found.
-Expects a complete content-type header line as its argument. 
+Expects a complete content-type header line as its argument.
 
 Second argument REQUEST specifies what information to return.  If it is
 nil or the empty string, the viewer (second field of the mailcap
@@ -815,6 +820,17 @@ correspond to.")
       (setq extn (concat "." extn)))
   (cdr (assoc (downcase extn) mailcap-mime-extensions)))
 
+(defun mailcap-command-p (command)
+  "Say whether COMMAND is in the exec path."
+  (let ((path (if (file-name-absolute-p command) '(nil) exec-path))
+       file)
+    (catch 'found
+      (while path
+       (when (and (file-executable-p
+                   (setq file (expand-file-name command (pop path))))
+                  (not (file-directory-p file)))
+         (throw 'found file))))))
+
 (provide 'mailcap)
 
 ;;; mailcap.el ends here
index a594c28..a23d93c 100644 (file)
@@ -256,12 +256,12 @@ If ARG is 1, prompt for a group name to find the posting style."
   (let ((gnus-newsgroup-name
         (if arg
             (if (= 1 (prefix-numeric-value arg))
-                (completing-read "Use style of group: " gnus-active-hashtb nil
+                (completing-read "Use posting style of group: "
+                                 gnus-active-hashtb nil
                                  (gnus-read-active-file-p))
               (gnus-group-group-name))
           "")))
-    (gnus-setup-message 'message (message-mail))
-    ))
+    (gnus-setup-message 'message (message-mail))))
 
 (defun gnus-group-post-news (&optional arg)
   "Start composing a news message.
@@ -546,7 +546,7 @@ If SILENT, don't prompt the user."
      ((and (eq gnus-post-method 'current)
           (not (eq (car group-method) 'nndraft))
           (not arg))
-      group-method) 
+      group-method)
      ((and gnus-post-method
           (not (eq gnus-post-method 'current)))
       gnus-post-method)
@@ -690,7 +690,8 @@ The current group name will be inserted at \"%s\".")
        (gnus-summary-select-article)
        (set-buffer gnus-original-article-buffer)
        (if (and (<= (length (message-tokenize-header
-                             (setq newsgroups (mail-fetch-field "newsgroups"))
+                             (setq newsgroups
+                                   (mail-fetch-field "newsgroups"))
                              ", "))
                     1)
                 (or (not (setq followup-to (mail-fetch-field "followup-to")))
@@ -997,7 +998,7 @@ this is a reply."
          (and gnus-newsgroup-name
               (gnus-group-find-parameter
                gnus-newsgroup-name 'gcc-self)))
-        result 
+        result
         (groups
          (cond
           ((null gnus-message-archive-method)
@@ -1101,7 +1102,7 @@ this is a reply."
            (if (and (not (stringp (car attribute)))
                     (not (eq 'body (car attribute)))
                     (not (setq variable
-                               (cdr (assq (car attribute) 
+                               (cdr (assq (car attribute)
                                           gnus-posting-style-alist)))))
                (message "Couldn't find attribute %s" (car attribute))
              ;; We get the value.
index e98762e..9a73698 100644 (file)
@@ -519,12 +519,14 @@ Two predefined functions are available:
 
 (defun gnus-tree-article-region (article)
   "Return a cons with BEG and END of the article region."
-  (let ((pos (text-property-any (point-min) (point-max) 'gnus-number article)))
+  (let ((pos (text-property-any
+             (point-min) (point-max) 'gnus-number article)))
     (when pos
       (cons pos (next-single-property-change pos 'gnus-number)))))
 
 (defun gnus-tree-goto-article (article)
-  (let ((pos (text-property-any (point-min) (point-max) 'gnus-number article)))
+  (let ((pos (text-property-any
+             (point-min) (point-max) 'gnus-number article)))
     (when pos
       (goto-char pos))))
 
index 6061845..28e87da 100644 (file)
@@ -318,7 +318,7 @@ and non-`vertical', do both horizontal and vertical recentering."
   "*If non-nil, ignore articles with identical Message-ID headers."
   :group 'gnus-summary
   :type 'boolean)
-  
+
 (defcustom gnus-single-article-buffer t
   "*If non-nil, display all articles in the same buffer.
 If nil, each group will get its own article buffer."
@@ -1010,6 +1010,25 @@ variable (string, integer, character, etc).")
 ;; Byte-compiler warning.
 (defvar gnus-article-mode-map)
 
+;; MIME stuff.
+
+(defvar gnus-encoded-word-method-alist
+  '(("chinese" mail-decode-encoded-word-string rfc1843-decode-string)
+    (".*" mail-decode-encoded-word-string))
+  "Alist of regexps (to match group names) and lists of functions to be applied.")
+
+(defun gnus-multi-decode-encoded-word-string (string)
+  "Apply the functions from `gnus-encoded-word-method-alist' that match."
+  (let ((alist gnus-encoded-word-method-alist)
+       elem)
+    (while (setq elem (pop alist))
+      (when (string-match (car elem) gnus-newsgroup-name)
+       (pop elem)
+       (while elem
+         (setq string (funcall (pop elem) string)))
+       (setq alist nil)))
+    string))
+
 ;; Subject simplification.
 
 (defun gnus-simplify-whitespace (str)
@@ -1248,7 +1267,7 @@ increase the score of each group you read."
     "L" gnus-summary-lower-score
     "\M-i" gnus-symbolic-argument
     "h" gnus-summary-select-article-buffer
-    
+
     "V" gnus-summary-score-map
     "X" gnus-uu-extract-map
     "S" gnus-summary-send-map)
@@ -2442,7 +2461,7 @@ marks of articles."
       (setq gnus-tmp-name gnus-tmp-from))
     (unless (numberp gnus-tmp-lines)
       (setq gnus-tmp-lines 0))
-    (gnus-put-text-property-excluding-characters-with-faces
+    (gnus-put-text-property
      (point)
      (progn (eval gnus-summary-line-format-spec) (point))
      'gnus-number gnus-tmp-number)
@@ -2691,7 +2710,7 @@ If NO-DISPLAY, don't generate a summary buffer."
          (goto-char (point-min))
          (gnus-summary-position-point)
          (gnus-configure-windows 'summary 'force)
-         (gnus-set-mode-line 'summary))        
+         (gnus-set-mode-line 'summary))
        (when (get-buffer-window gnus-group-buffer t)
          ;; Gotta use windows, because recenter does weird stuff if
          ;; the current buffer ain't the displayed window.
@@ -3798,7 +3817,7 @@ or a straight list of headers."
              (setq gnus-tmp-name gnus-tmp-from))
            (unless (numberp gnus-tmp-lines)
              (setq gnus-tmp-lines 0))
-           (gnus-put-text-property-excluding-characters-with-faces
+           (gnus-put-text-property
             (point)
             (progn (eval gnus-summary-line-format-spec) (point))
             'gnus-number number)
@@ -4336,7 +4355,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
       ;; Then we add the read articles to the range.
       (gnus-add-to-range
        ninfo (setq articles (sort articles '<))))))
-  
+
 (defun gnus-group-make-articles-read (group articles)
   "Update the info of GROUP to say that ARTICLES are read."
   (let* ((num 0)
@@ -5051,7 +5070,7 @@ The prefix argument ALL means to select all articles."
          (gnus-update-read-articles
           group (append gnus-newsgroup-unreads gnus-newsgroup-unselected))
          ;; Set the current article marks.
-         (let ((gnus-newsgroup-scored 
+         (let ((gnus-newsgroup-scored
                 (if (and (not gnus-save-score)
                          (not non-destructive))
                     nil
@@ -6192,7 +6211,7 @@ If ALL, mark even excluded ticked and dormants as read."
 (defsubst gnus-cut-thread (thread)
   "Go forwards in the thread until we find an article that we want to display."
   (when (or (eq gnus-fetch-old-headers 'some)
-           (eq gnus-fetch-old-headers 'invisible)          
+           (eq gnus-fetch-old-headers 'invisible)
            (eq gnus-build-sparse-threads 'some)
            (eq gnus-build-sparse-threads 'more))
     ;; Deal with old-fetched headers and sparse threads.
@@ -6794,14 +6813,14 @@ to save in."
              (set-buffer buffer)
              (gnus-article-delete-invisible-text)
              (let ((ps-left-header
-                    (list 
+                    (list
                      (concat "("
                              (mail-header-subject gnus-current-headers) ")")
                      (concat "("
                              (mail-header-from gnus-current-headers) ")")))
-                   (ps-right-header 
-                    (list 
-                     "/pagenumberstring load" 
+                   (ps-right-header
+                    (list
+                     "/pagenumberstring load"
                      (concat "("
                              (mail-header-date gnus-current-headers) ")"))))
                (gnus-run-hooks 'gnus-ps-print-hook)
@@ -7108,7 +7127,7 @@ and `request-accept' functions."
 
        ;;;!!!Why is this necessary?
        (set-buffer gnus-summary-buffer)
-       
+
        (gnus-summary-goto-subject article)
        (when (eq action 'move)
          (gnus-summary-mark-article article gnus-canceled-mark))))
@@ -7568,7 +7587,7 @@ the actual number of articles marked is returned."
   "Mark ARTICLE replied and update the summary line."
   (push article gnus-newsgroup-replied)
   (let ((buffer-read-only nil))
-    (when (gnus-summary-goto-subject article)
+    (when (gnus-summary-goto-subject article nil t)
       (gnus-summary-update-secondary-mark article))))
 
 (defun gnus-summary-set-bookmark (article)
index 51c0b3e..2e3c1b3 100644 (file)
@@ -253,10 +253,10 @@ is restarted, and sometimes reloaded."
 (defconst gnus-product-name "T-gnus"
   "Product name of this version of gnus.")
 
-(defconst gnus-version-number "6.10.019"
+(defconst gnus-version-number "6.10.020"
   "Version number for this version of gnus.")
 
-(defconst gnus-original-version-number "0.30"
+(defconst gnus-original-version-number "0.31"
     "Version number for this version of Gnus.")
 
 (defconst gnus-original-product-name "Pterodactyl Gnus"
@@ -300,7 +300,8 @@ be set in `.emacs' instead."
   (defalias 'gnus-deactivate-mark 'deactivate-mark)
   (defalias 'gnus-window-edges 'window-edges)
   (defalias 'gnus-key-press-event-p 'numberp)
-  (defalias 'gnus-annotation-in-region-p 'ignore))
+  (defalias 'gnus-annotation-in-region-p 'ignore)
+  (defalias 'gnus-decode-rfc1522 'ignore))
 
 ;; We define these group faces here to avoid the display
 ;; update forced when creating new faces.
@@ -1817,7 +1818,7 @@ This restriction may disappear in later versions of Gnus."
       (define-key keymap (pop keys) 'undefined))))
 
 (defvar gnus-article-mode-map
-  (let ((keymap (make-keymap)))
+  (let ((keymap (make-sparse-keymap)))
     (gnus-suppress-keymap keymap)
     keymap))
 (defvar gnus-summary-mode-map
index bcd48a3..ca8dc7a 100644 (file)
@@ -40,8 +40,9 @@
                     set-buffer-multibyte
                     find-non-ascii-charset-region char-charset
                     find-charset-region base64-decode-string
+                    base64-encode-string
                     find-coding-systems-region get-charset-property
-                    coding-system-get))
+                    coding-system-get w3-region))
       (maybe-bind '(global-face-data
                    mark-active transient-mark-mode mouse-selection-click-count
                    mouse-selection-click-count-buffer buffer-display-table
                 pp-to-string color-name 
                 gnus-mule-get-coding-system decode-coding-string
                 mail-aliases-setup
-                url-view-url w3-prepare-buffer char-int)))
+                url-view-url w3-prepare-buffer
+                char-int
+                annotationp delete-annotation make-image-specifier
+                make-annotation base64-decode-string base64-encode-string
+                w3-do-setup w3-region)))
 
 (setq load-path (cons "." load-path))
 (require 'custom)
index 095e114..99bd017 100644 (file)
@@ -36,7 +36,7 @@
 
 ;;; Code:
 
-(require 'drums)
+(require 'ietf-drums)
 (require 'rfc2231)
 (require 'rfc2047)
 
 (defalias 'mail-header-parse-content-disposition 'rfc2231-parse-string)
 (defalias 'mail-content-type-get 'rfc2231-get-value)
 
-(defalias 'mail-header-remove-comments 'drums-remove-comments)
-(defalias 'mail-header-remove-whitespace 'drums-remove-whitespace)
-(defalias 'mail-header-get-comment 'drums-get-comment)
-(defalias 'mail-header-parse-address 'drums-parse-address)
-(defalias 'mail-header-parse-addresses 'drums-parse-addresses)
-(defalias 'mail-header-parse-date 'drums-parse-date)
-(defalias 'mail-narrow-to-head 'drums-narrow-to-header)
-(defalias 'mail-quote-string 'drums-quote-string)
+(defalias 'mail-header-remove-comments 'ietf-drums-remove-comments)
+(defalias 'mail-header-remove-whitespace 'ietf-drums-remove-whitespace)
+(defalias 'mail-header-get-comment 'ietf-drums-get-comment)
+(defalias 'mail-header-parse-address 'ietf-drums-parse-address)
+(defalias 'mail-header-parse-addresses 'ietf-drums-parse-addresses)
+(defalias 'mail-header-parse-date 'ietf-drums-parse-date)
+(defalias 'mail-narrow-to-head 'ietf-drums-narrow-to-header)
+(defalias 'mail-quote-string 'ietf-drums-quote-string)
 
 (defalias 'mail-header-narrow-to-field 'rfc2047-narrow-to-field)
 (defalias 'mail-encode-encoded-word-region 'rfc2047-encode-region)
index f6b7146..e44e4ad 100644 (file)
@@ -2853,7 +2853,8 @@ If NOW, use that time instead."
     (when (< zone 0)
       (setq sign ""))
     ;; We do all of this because XEmacs doesn't have the %z spec.
-    (concat (format-time-string "%d %b %Y %H:%M:%S " (or now (current-time)))
+    (concat (format-time-string
+            "%d %b %Y %H:%M:%S " (or now (current-time)))
            (format "%s%02d%02d"
                    sign (/ zone 3600)
                    (% zone 3600)))))
@@ -4510,6 +4511,35 @@ regexp varstr."
       (setq idx (1+ idx)))
     string))
 
+;;;
+;;; MIME functions
+;;;
+
+(defun message-encode-message-body ()
+  "Examine the message body, encode it, and add the requisite headers."
+  (when (featurep 'mule)
+    (save-excursion
+      (save-restriction
+       (message-narrow-to-headers-or-head)
+       (message-remove-header
+        "^Content-Transfer-Encoding:\\|^Content-Type:\\|^Mime-Version:" t)
+       (goto-char (point-max))
+       (widen)
+       (narrow-to-region (point) (point-max))
+       (let* ((charset (mm-encode-body))
+              (encoding (mm-body-encoding)))
+         (when (consp charset)
+           (error "Can't encode messages with multiple charsets (yet)"))
+         (widen)
+         (message-narrow-to-headers-or-head)
+         (goto-char (point-max))
+         (setq charset (or charset (mm-mule-charset-to-mime-charset 'ascii)))
+         ;; We don't insert MIME headers if they only say the default.
+         (unless (and (eq charset 'us-ascii)
+                      (eq encoding '7bit))
+           (mm-insert-rfc822-headers charset encoding))
+         (mm-encode-body))))))
+
 (run-hooks 'message-load-hook)
 
 (provide 'message)
index 2cc3dbb..a2699f5 100644 (file)
@@ -25,8 +25,8 @@
 ;;; Code:
 
 (eval-and-compile
-  (if (not (fboundp 'base64-encode-string))
-      (require 'base64)))
+  (or (fboundp  'base64-encode-region)
+      (autoload 'base64-decode-region "base64" nil t)))
 (require 'mm-util)
 (require 'rfc2047)
 (require 'qp)
@@ -62,7 +62,10 @@ If no encoding was done, nil is returned."
            (while (not (eobp))
              (if (eq (char-charset (following-char)) 'ascii)
                  (when start
-                   (mm-encode-coding-region start (point) mime-charset)
+                   (save-restriction
+                     (narrow-to-region start (point))
+                     (mm-encode-coding-region start (point) mime-charset)
+                     (goto-char (point-max)))
                    (setq start nil))
                (unless start
                  (setq start (point))))
index 3f0055f..027a46a 100644 (file)
@@ -37,6 +37,8 @@
     ("image/xpm" mm-inline-image (featurep 'xpm))
     ("image/bmp" mm-inline-image (featurep 'bmp))
     ("text/plain" mm-inline-text t)
+    ("text/enriched" mm-inline-text t)
+    ("text/richtext" mm-inline-text t)
     ("text/html" mm-inline-text (featurep 'w3))
     ("audio/wav" mm-inline-audio
      (and (or (featurep 'nas-sound) (featurep 'native-sound))
     ("text/.*" . inline)))
 
 (defvar mm-user-automatic-display
-  '("text/plain" "text/html" "image/gif"))
+  '("text/plain" "text/enriched" "text/richtext" "text/html" "image/gif"))
 
-(defvar mm-alternative-precedence '("text/plain" "text/html")
+(defvar mm-alternative-precedence
+  '("text/plain" "text/enriched" "text/richtext" "text/html")
   "List that describes the precedence of alternative parts.")
 
 (defvar mm-tmp-directory "/tmp/"
@@ -93,7 +96,8 @@
        (when (and (or no-strict-mime
                       (mail-fetch-field "mime-version"))
                   (setq ct (mail-fetch-field "content-type")))
-         (setq ctl (mail-header-parse-content-type ct)
+         (setq ctl (condition-case () (mail-header-parse-content-type ct)
+                     (error nil))
                cte (mail-fetch-field "content-transfer-encoding")
                cd (mail-fetch-field "content-disposition")
                description (mail-fetch-field "content-description")
                                        (mail-header-remove-comments
                                         cte)))))
            no-strict-mime
-           (and cd (mail-header-parse-content-disposition cd))))))
+           (and cd (condition-case ()
+                       (mail-header-parse-content-disposition cd)
+                     (error nil)))))))
        (when id
          (push (cons id result) mm-content-id-alist))
        result))))
   (let ((boundary (concat "\n--" (mail-content-type-get ctl 'boundary)))
        start parts end)
     (while (search-forward boundary nil t)
-      (forward-line -1)
+      (goto-char (match-beginning 0))
       (when start
        (save-excursion
          (save-restriction
       (insert-buffer-substring obuf beg)
       (current-buffer))))
 
-(defun mm-display-part (handle)
+(defun mm-display-part (handle &optional no-default)
   "Display the MIME part represented by HANDLE."
   (save-excursion
     (mailcap-parse-mailcaps)
            (progn
              (forward-line 1)
              (mm-display-inline handle))
-         (mm-display-external
-          handle (or user-method method 'mailcap-save-binary-file)))))))
+         (when (or user-method
+                   method
+                   (not no-default))
+           (mm-display-external
+            handle (or user-method method 'mailcap-save-binary-file))))))))
 
 (defun mm-display-external (handle method)
   "Display HANDLE using METHOD."
   (let* ((type (car (mm-handle-type handle)))
         (function (cadr (assoc type mm-inline-media-tests))))
     (funcall function handle)))
-        
+
 (defun mm-inlinable-p (type)
   "Say whether TYPE can be displayed inline."
   (let ((alist mm-inline-media-tests)
@@ -318,7 +327,7 @@ This overrides entries in the mailcap file."
 
 (defun mm-pipe-part (handle)
   "Pipe HANDLE to a process."
-  (let* ((name (mail-content-type-get (car (mm-handle-type handle)) 'name))
+  (let* ((name (mail-content-type-get (mm-handle-type handle) 'name))
         (command
          (read-string "Shell command on MIME part: " mm-last-shell-command)))
     (mm-with-unibyte-buffer
index b9756e9..10ab086 100644 (file)
          (save-window-excursion
            (w3-region (point-min) (point-max))
            (setq text (buffer-string))))
-       (let ((b (point)))
-         (insert text)
-         (mm-handle-set-undisplayer
-          handle
-          `(lambda ()
-             (let (buffer-read-only)
-               (delete-region ,(set-marker (make-marker) b)
-                              ,(set-marker (make-marker) (point)))))))))
+       (mm-insert-inline handle text)))
+     ((or (equal type "enriched")
+         (equal type "richtext"))
+      (save-excursion
+       (mm-with-unibyte-buffer
+         (insert-buffer-substring (mm-handle-buffer handle))
+         (mm-decode-content-transfer-encoding (mm-handle-encoding handle))
+         (save-window-excursion
+           (enriched-decode (point-min) (point-max))
+           (setq text (buffer-string))))
+       (mm-insert-inline handle text)))
      )))
 
+(defun mm-insert-inline (handle text)
+  "Insert TEXT inline from HANDLE."
+  (let ((b (point)))
+    (insert text)
+    (mm-handle-set-undisplayer
+     handle
+     `(lambda ()
+       (let (buffer-read-only)
+         (delete-region ,(set-marker (make-marker) b)
+                        ,(set-marker (make-marker) (point))))))))
+  
 (defun mm-inline-audio (handle)
   (message "Not implemented"))
 
diff --git a/lisp/mm.el b/lisp/mm.el
deleted file mode 100644 (file)
index 1b57cb1..0000000
+++ /dev/null
@@ -1,1283 +0,0 @@
-;;; mm.el,v --- Mailcap parsing routines, and MIME handling
-;; Author: wmperry
-;; Created: 1996/05/28 02:46:51
-;; Version: 1.96
-;; Keywords: mail, news, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1994, 1995, 1996 by William M. Perry <wmperry@cs.indiana.edu>
-;;; Copyright (c) 1996 - 1998 Free Software Foundation, Inc.
-;;;
-;;; This file is not part of GNU Emacs, but the same permissions apply.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;;; GNU General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Generalized mailcap parsing and access routines
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;
-;;; Data structures
-;;; ---------------
-;;; The mailcap structure is an assoc list of assoc lists.
-;;; 1st assoc list is keyed on the major content-type
-;;; 2nd assoc list is keyed on the minor content-type (which can be a regexp)
-;;;
-;;; Which looks like:
-;;; -----------------
-;;; (
-;;;  ("application"
-;;;   ("postscript" . <info>)
-;;;  )
-;;;  ("text"
-;;;   ("plain" . <info>)
-;;;  )
-;;; )
-;;;
-;;; Where <info> is another assoc list of the various information
-;;; related to the mailcap RFC.  This is keyed on the lowercase
-;;; attribute name (viewer, test, etc).  This looks like:
-;;; (("viewer" . viewerinfo)
-;;;  ("test"   . testinfo)
-;;;  ("xxxx"   . "string")
-;;; )
-;;;
-;;; Where viewerinfo specifies how the content-type is viewed.  Can be
-;;; a string, in which case it is run through a shell, with
-;;; appropriate parameters, or a symbol, in which case the symbol is
-;;; funcall'd, with the buffer as an argument.
-;;;
-;;; testinfo is a list of strings, or nil.  If nil, it means the
-;;; viewer specified is always valid.  If it is a list of strings,
-;;; these are used to determine whether a viewer passes the 'test' or
-;;; not.
-;;;
-;;; The main interface to this code is:
-;;;
-;;; To set everything up:
-;;;
-;;;  (mm-parse-mailcaps [path])
-;;;
-;;;  Where PATH is a unix-style path specification (: separated list
-;;;  of strings).  If PATH is nil, the environment variable MAILCAPS
-;;;  will be consulted.  If there is no environment variable, then a
-;;;  default list of paths is used.
-;;;
-;;; To retrieve the information:
-;;;  (mm-mime-info st [nd] [request])
-;;;
-;;;  Where st and nd are positions in a buffer that contain the
-;;;  content-type header information of a mail/news/whatever message.
-;;;  st can optionally be a string that contains the content-type
-;;;  information.
-;;;
-;;;  Third argument REQUEST specifies what information to return.  If
-;;;  it is nil or the empty string, the viewer (second field of the
-;;;  mailcap entry) will be returned.  If it is a string, then the
-;;;  mailcap field corresponding to that string will be returned
-;;;  (print, description, whatever).  If a number, then all the
-;;;  information for this specific viewer is returned.
-;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Variables, etc
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(eval-and-compile
-  (require 'cl)
-;LMI was here
-  ;;(require 'devices)
-  )
-
-(defconst mm-version (let ((x "1.96"))
-                      (if (string-match "Revision: \\([^ \t\n]+\\)" x)
-                          (substring x (match-beginning 1) (match-end 1))
-                        x))
-  "Version # of MM package")
-
-(defvar mm-parse-args-syntax-table
-  (copy-syntax-table emacs-lisp-mode-syntax-table)
-  "A syntax table for parsing sgml attributes.")
-
-(modify-syntax-entry ?' "\"" mm-parse-args-syntax-table)
-(modify-syntax-entry ?` "\"" mm-parse-args-syntax-table)
-(modify-syntax-entry ?{ "(" mm-parse-args-syntax-table)
-(modify-syntax-entry ?} ")" mm-parse-args-syntax-table)
-
-(defvar mm-mime-data
-  '(
-    ("multipart"   . (
-                     ("alternative". (("viewer" . mm-multipart-viewer)
-                                      ("type"   . "multipart/alternative")))
-                     ("mixed"      . (("viewer" . mm-multipart-viewer)
-                                      ("type"   . "multipart/mixed")))
-                     (".*"         . (("viewer" . mm-save-binary-file)
-                                      ("type"   . "multipart/*")))
-                     )
-     )
-    ("application" . (
-                     ("x-x509-ca-cert" . (("viewer" . ssl-view-site-cert)
-                                          ("test" . (fboundp 'ssl-view-site-cert))
-                                          ("type" . "application/x-x509-ca-cert")))
-                     ("x-x509-user-cert" . (("viewer" . ssl-view-user-cert)
-                                            ("test" . (fboundp 'ssl-view-user-cert))
-                                            ("type" . "application/x-x509-user-cert")))
-                     ("octet-stream" . (("viewer" . mm-save-binary-file)
-                                        ("type" ."application/octet-stream")))
-                     ("dvi"        . (("viewer" . "open %s")
-                                      ("type"   . "application/dvi")
-                                      ("test"   . (eq (device-type) 'ns))))
-                     ("dvi"        . (("viewer" . "xdvi %s")
-                                      ("test"   . (eq (device-type) 'x))
-                                      ("needsx11")
-                                      ("type"   . "application/dvi")))
-                     ("dvi"        . (("viewer" . "dvitty %s")
-                                      ("test"   . (not (getenv "DISPLAY")))
-                                      ("type"   . "application/dvi")))
-                     ("emacs-lisp" . (("viewer" . mm-maybe-eval)
-                                      ("type"   . "application/emacs-lisp")))
-;                    ("x-tar"      . (("viewer" . tar-mode)
-;                                     ("test"   . (fboundp 'tar-mode))
-;                                     ("type"   . "application/x-tar")))
-                     ("x-tar"      . (("viewer" . mm-save-binary-file)
-                                      ("type"   . "application/x-tar")))
-                     ("x-latex"    . (("viewer" . tex-mode)
-                                      ("test"   . (fboundp 'tex-mode))
-                                      ("type"   . "application/x-latex")))
-                     ("x-tex"      . (("viewer" . tex-mode)
-                                      ("test"   . (fboundp 'tex-mode))
-                                      ("type"   . "application/x-tex")))
-                     ("latex"      . (("viewer" . tex-mode)
-                                      ("test"   . (fboundp 'tex-mode))
-                                      ("type"   . "application/latex")))
-                     ("tex"        . (("viewer" . tex-mode)
-                                      ("test"   . (fboundp 'tex-mode))
-                                      ("type"   . "application/tex")))
-                     ("texinfo"    . (("viewer" . texinfo-mode)
-                                      ("test"   . (fboundp 'texinfo-mode))
-                                      ("type"   . "application/tex")))
-                     ("zip"        . (("viewer" . mm-save-binary-file)
-                                      ("type"   . "application/zip")
-                                      ("copiousoutput")))
-                     ("pdf"        . (("viewer" . "acroread %s")
-                                      ("type"   . "application/pdf")))
-                     ("postscript" . (("viewer" . "open %s")
-                                      ("type"   . "application/postscript")
-                                      ("test"   . (eq (device-type) 'ns))))
-                     ("postscript" . (("viewer" . "ghostview %s")
-                                      ("type" . "application/postscript")
-                                      ("test"   . (eq (device-type) 'x))
-                                      ("needsx11")))
-                     ("postscript" . (("viewer" . "ps2ascii %s")
-                                      ("type" . "application/postscript")
-                                      ("test" . (not (getenv "DISPLAY")))
-                                      ("copiousoutput")))
-                     ))
-    ("audio"       . (
-                     ("x-mpeg" . (("viewer" . "maplay %s")
-                                  ("type"   . "audio/x-mpeg")))
-                     (".*" . (("viewer" . mm-play-sound-file)
-                              ("test"   . (or (featurep 'nas-sound)
-                                              (featurep 'native-sound)))
-                              ("type"   . "audio/*")))
-                     (".*" . (("viewer" . "showaudio")
-                              ("type"   . "audio/*")))
-                     ))
-    ("message"     . (
-                     ("rfc-*822" . (("viewer" . vm-mode)
-                                    ("test"   . (fboundp 'vm-mode))
-                                    ("type"   . "message/rfc-822")))
-                     ("rfc-*822" . (("viewer" . w3-mode)
-                                    ("test"   . (fboundp 'w3-mode))
-                                    ("type"   . "message/rfc-822")))
-                     ("rfc-*822" . (("viewer" . view-mode)
-                                    ("test"   . (fboundp 'view-mode))
-                                    ("type"   . "message/rfc-822")))
-                     ("rfc-*822" . (("viewer" . fundamental-mode)
-                                    ("type"   . "message/rfc-822")))
-                     ))
-    ("image"       . (
-                     ("x-xwd" . (("viewer"  . "xwud -in %s")
-                                 ("type"    . "image/x-xwd")
-                                 ("compose" . "xwd -frame > %s")
-                                 ("test"    . (eq (device-type) 'x))
-                                 ("needsx11")))
-                     ("x11-dump" . (("viewer" . "xwud -in %s")
-                                    ("type" . "image/x-xwd")
-                                    ("compose" . "xwd -frame > %s")
-                                    ("test"   . (eq (device-type) 'x))
-                                    ("needsx11")))
-                     ("windowdump" . (("viewer" . "xwud -in %s")
-                                      ("type" . "image/x-xwd")
-                                      ("compose" . "xwd -frame > %s")
-                                      ("test"   . (eq (device-type) 'x))
-                                      ("needsx11")))
-                     (".*" . (("viewer" . "open %s")
-                              ("type"   . "image/*")
-                              ("test"   . (eq (device-type) 'ns))))
-                     (".*" . (("viewer" . "xv -perfect %s")
-                              ("type" . "image/*")
-                              ("test"   . (eq (device-type) 'x))
-                              ("needsx11")))
-                     ))
-    ("text"        . (
-                     ("plain" . (("viewer"  . w3-mode)
-                                 ("test"    . (fboundp 'w3-mode))
-                                 ("type"    . "text/plain")))
-                     ("plain" . (("viewer"  . view-mode)
-                                 ("test"    . (fboundp 'view-mode))
-                                 ("type"    . "text/plain")))
-                     ("plain" . (("viewer"  . fundamental-mode)
-                                 ("type"    . "text/plain")))
-                     ("enriched" . (("viewer" . enriched-decode-region)
-                                    ("test"   . (fboundp
-                                                 'enriched-decode-region))
-                                    ("type"   . "text/enriched")))
-                     ("html"  . (("viewer" . w3-prepare-buffer)
-                                 ("test"   . (fboundp 'w3-prepare-buffer))
-                                 ("type"   . "text/html")))
-                     ))
-    ("video"       . (
-                     ("mpeg" . (("viewer" . "mpeg_play %s")
-                                ("type"   . "video/mpeg")
-                                ("test"   . (eq (device-type) 'x))
-                                ("needsx11")))
-                     ))
-    ("x-world"     . (
-                     ("x-vrml" . (("viewer"  . "webspace -remote %s -URL %u")
-                                  ("type"    . "x-world/x-vrml")
-                                  ("description"
-                                   "VRML document")))))
-    ("archive"     . (
-                     ("tar"  . (("viewer" . tar-mode)
-                                ("type" . "archive/tar")
-                                ("test" . (fboundp 'tar-mode))))
-                     ))
-    )
-  "*The mailcap structure is an assoc list of assoc lists.
-1st assoc list is keyed on the major content-type
-2nd assoc list is keyed on the minor content-type (which can be a regexp)
-
-Which looks like:
------------------
-(
- (\"application\"
-  (\"postscript\" . <info>)
- )
- (\"text\"
-  (\"plain\" . <info>)
- )
-)
-
-Where <info> is another assoc list of the various information
-related to the mailcap RFC.  This is keyed on the lowercase
-attribute name (viewer, test, etc).  This looks like:
-((\"viewer\" . viewerinfo)
- (\"test\"   . testinfo)
- (\"xxxx\"   . \"string\")
-)
-
-Where viewerinfo specifies how the content-type is viewed.  Can be
-a string, in which case it is run through a shell, with
-appropriate parameters, or a symbol, in which case the symbol is
-funcall'd, with the buffer as an argument.
-
-testinfo is a list of strings, or nil.  If nil, it means the
-viewer specified is always valid.  If it is a list of strings,
-these are used to determine whether a viewer passes the 'test' or
-not.")
-
-(defvar mm-content-transfer-encodings
-  '(("base64"     . base64-decode-region)
-    ("7bit"       . ignore)
-    ("8bit"       . ignore)
-    ("binary"     . ignore)
-    ("x-compress" . ("uncompress" "-c"))
-    ("x-gzip"     . ("gzip" "-dc"))
-    ("compress"   . ("uncompress" "-c"))
-    ("gzip"       . ("gzip" "-dc"))
-    ("x-hqx"      . ("mcvert" "-P" "-s" "-S"))
-    ("quoted-printable" . mm-decode-quoted-printable)
-    )
-  "*An assoc list of content-transfer-encodings and how to decode them.")
-
-(defvar mm-download-directory nil
-  "*Where downloaded files should go by default.")
-
-(defvar mm-temporary-directory (or (getenv "TMPDIR") "/tmp")
-  "*Where temporary files go.")
-
-\f
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; A few things from w3 and url, just in case this is used without them
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun mm-generate-unique-filename (&optional fmt)
-  "Generate a unique filename in mm-temporary-directory"
-  (if (not fmt)
-      (let ((base (format "mm-tmp.%d" (user-real-uid)))
-           (fname "")
-           (x 0))
-       (setq fname (format "%s%d" base x))
-       (while (file-exists-p
-               (expand-file-name fname mm-temporary-directory))
-         (setq x (1+ x)
-               fname (concat base (int-to-string x))))
-       (expand-file-name fname mm-temporary-directory))
-    (let ((base (concat "mm" (int-to-string (user-real-uid))))
-         (fname "")
-         (x 0))
-      (setq fname (format fmt (concat base (int-to-string x))))
-      (while (file-exists-p
-             (expand-file-name fname mm-temporary-directory))
-       (setq x (1+ x)
-             fname (format fmt (concat base (int-to-string x)))))
-      (expand-file-name fname mm-temporary-directory))))
-
-(if (and (fboundp 'copy-tree)
-        (subrp (symbol-function 'copy-tree)))
-    (fset 'mm-copy-tree 'copy-tree)
-  (defun mm-copy-tree (tree)
-    (if (consp tree)
-       (cons (mm-copy-tree (car tree))
-             (mm-copy-tree (cdr tree)))
-      (if (vectorp tree)
-         (let* ((new (copy-sequence tree))
-                (i (1- (length new))))
-           (while (>= i 0)
-             (aset new i (mm-copy-tree (aref new i)))
-             (setq i (1- i)))
-           new)
-       tree))))
-
-;LMI was here
-;(require 'mule-sysdp)
-
-(if (not (fboundp 'w3-save-binary-file))
-    (defun mm-save-binary-file ()
-      ;; Ok, this is truly fucked.  In XEmacs, if you use the mouse to select
-      ;; a URL that gets saved via this function, read-file-name will pop up a
-      ;; dialog box for file selection.  For some reason which buffer we are in
-      ;; gets royally screwed (even with save-excursions and the whole nine
-      ;; yards).  SO, we just keep the old buffer name around and away we go.
-      (let ((old-buff (current-buffer))
-           (file (read-file-name "Filename to save as: "
-                                 (or mm-download-directory "~/")
-                                 (file-name-nondirectory (url-view-url t))
-                                 nil
-                                 (file-name-nondirectory (url-view-url t))))
-           (require-final-newline nil))
-       (set-buffer old-buff)
-       (mule-write-region-no-coding-system (point-min) (point-max) file)
-       (kill-buffer (current-buffer))))
-  (fset 'mm-save-binary-file 'w3-save-binary-file))
-
-(defun mm-maybe-eval ()
-  "Maybe evaluate a buffer of emacs lisp code"
-  (if (yes-or-no-p "This is emacs-lisp code, evaluate it? ")
-      (eval-buffer (current-buffer))
-    (emacs-lisp-mode)))
-
-\f
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; The mailcap parser
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mm-viewer-unescape (format &optional filename url)
-  (save-excursion
-    (set-buffer (get-buffer-create " *mm-parse*"))
-    (erase-buffer)
-    (insert format)
-    (goto-char (point-min))
-    (while (re-search-forward "%\\(.\\)" nil t)
-       (let ((escape (aref (match-string 1) 0)))
-        (replace-match "" t t)
-        (case escape
-          (?% (insert "%"))
-          (?s (insert (or filename "\"\"")))
-          (?u (insert (or url "\"\""))))))
-    (buffer-string)))
-
-(defun mm-in-assoc (elt list)
-  ;; Check to see if ELT matches any of the regexps in the car elements of LIST
-  (let (rslt)
-    (while (and list (not rslt))
-      (and (car (car list))
-          (string-match (car (car list)) elt)
-          (setq rslt (car list)))
-      (setq list (cdr list)))
-    rslt))
-
-(defun mm-replace-regexp (regexp to-string)
-  ;; Quiet replace-regexp.
-  (goto-char (point-min))
-  (while (re-search-forward regexp nil t)
-    (replace-match to-string t nil)))
-
-(defun mm-parse-mailcaps (&optional path)
-  ;; Parse out all the mailcaps specified in a unix-style path string PATH
-  (cond
-   (path nil)
-   ((getenv "MAILCAPS") (setq path (getenv "MAILCAPS")))
-   ((memq system-type '(ms-dos ms-windows windows-nt))
-    (setq path (mapconcat 'expand-file-name '("~/mail.cap" "~/etc/mail.cap")
-                         ";")))
-   (t (setq path (mapconcat 'expand-file-name
-                           '("~/.mailcap"
-                             "/etc/mailcap:/usr/etc/mailcap"
-                             "/usr/local/etc/mailcap") ":"))))
-  (let ((fnames (reverse
-                (mm-string-to-tokens path
-                                     (if (memq system-type
-                                               '(ms-dos ms-windows windows-nt))
-                                         ?;
-                                       ?:))))
-       fname)
-    (while fnames
-      (setq fname (car fnames))
-      (if (and (file-exists-p fname) (file-readable-p fname))
-         (mm-parse-mailcap (car fnames)))
-      (setq fnames (cdr fnames)))))
-
-(defun mm-parse-mailcap (fname)
-  ;; Parse out the mailcap file specified by FNAME
-  (let (major                          ; The major mime type (image/audio/etc)
-       minor                           ; The minor mime type (gif, basic, etc)
-       save-pos                        ; Misc saved positions used in parsing
-       viewer                          ; How to view this mime type
-       info                            ; Misc info about this mime type
-       )
-    (save-excursion
-      (set-buffer (get-buffer-create " *mailcap*"))
-      (erase-buffer)
-      (insert-file-contents fname)
-      (set-syntax-table mm-parse-args-syntax-table)
-      (mm-replace-regexp "#.*" "")              ; Remove all comments
-      (mm-replace-regexp "\n+" "\n")         ; And blank lines
-      (mm-replace-regexp "\\\\[ \t\n]+" " ") ; And collapse spaces
-      (mm-replace-regexp (concat (regexp-quote "\\") "[ \t]*\n") "")
-      (goto-char (point-max))
-      (skip-chars-backward " \t\n")
-      (delete-region (point) (point-max))
-      (goto-char (point-min))
-      (while (not (eobp))
-       (skip-chars-forward " \t\n")
-       (setq save-pos (point)
-             info nil)
-       (skip-chars-forward "^/;")
-       (downcase-region save-pos (point))
-       (setq major (buffer-substring save-pos (point)))
-       (skip-chars-forward "/ \t\n")
-       (setq save-pos (point))
-       (skip-chars-forward "^;")
-       (downcase-region save-pos (point))
-       (setq minor
-             (cond
-              ((= ?* (or (char-after save-pos) 0)) ".*")
-              ((= (point) save-pos) ".*")
-              (t (buffer-substring save-pos (point)))))
-       (skip-chars-forward "; \t\n")
-       ;;; Got the major/minor chunks, now for the viewers/etc
-       ;;; The first item _must_ be a viewer, according to the
-       ;;; RFC for mailcap files (#1343)
-       (skip-chars-forward "; \t\n")
-       (setq save-pos (point))
-       (skip-chars-forward "^;\n")
-       (if (= (or (char-after save-pos) 0) ?')
-           (setq viewer (progn
-                          (narrow-to-region (1+ save-pos) (point))
-                          (goto-char (point-min))
-                          (prog1
-                              (read (current-buffer))
-                            (goto-char (point-max))
-                            (widen))))
-         (setq viewer (buffer-substring save-pos (point))))
-       (setq save-pos (point))
-       (end-of-line)
-       (setq info (nconc (list (cons "viewer" viewer)
-                               (cons "type" (concat major "/"
-                                                    (if (string= minor ".*")
-                                                        "*" minor))))
-                         (mm-parse-mailcap-extras save-pos (point))))
-       (mm-mailcap-entry-passes-test info)
-       (mm-add-mailcap-entry major minor info)))))
-
-(defun mm-parse-mailcap-extras (st nd)
-  ;; Grab all the extra stuff from a mailcap entry
-  (let (
-       name                            ; From name=
-       value                           ; its value
-       results                         ; Assoc list of results
-       name-pos                        ; Start of XXXX= position
-       val-pos                         ; Start of value position
-       done                            ; Found end of \'d ;s?
-       )
-    (save-restriction
-      (narrow-to-region st nd)
-      (goto-char (point-min))
-      (skip-chars-forward " \n\t;")
-      (while (not (eobp))
-       (setq done nil)
-       (skip-chars-forward " \";\n\t")
-       (setq name-pos (point))
-       (skip-chars-forward "^ \n\t=")
-       (downcase-region name-pos (point))
-       (setq name (buffer-substring name-pos (point)))
-       (skip-chars-forward " \t\n")
-       (if (/= (or (char-after (point)) 0)  ?=) ; There is no value
-           (setq value nil)
-         (skip-chars-forward " \t\n=")
-         (setq val-pos (point))
-         (if (memq (char-after val-pos) '(?\" ?'))
-             (progn
-               (setq val-pos (1+ val-pos))
-               (condition-case nil
-                   (progn
-                     (forward-sexp 1)
-                     (backward-char 1))
-                 (error (goto-char (point-max)))))
-           (while (not done)
-             (skip-chars-forward "^;")
-             (if (= (or (char-after (1- (point))) 0) ?\\ )
-                 (progn
-                   (subst-char-in-region (1- (point)) (point) ?\\ ? )
-                   (skip-chars-forward ";"))
-               (setq done t))))
-         (setq value (buffer-substring val-pos (point))))
-       (setq results (cons (cons name value) results)))
-      results)))  
-
-(defun mm-string-to-tokens (str &optional delim)
-  "Return a list of words from the string STR"
-  (setq delim (or delim ? ))
-  (let (results y)
-    (mapcar
-     (function
-      (lambda (x)
-       (cond
-        ((and (= x delim) y) (setq results (cons y results) y nil))
-        ((/= x delim) (setq y (concat y (char-to-string x))))
-        (t nil)))) str)
-    (nreverse (cons y results))))
-
-(defun mm-mailcap-entry-passes-test (info)
-  ;; Return t iff a mailcap entry passes its test clause or no test
-  ;; clause is present.
-  (let (status                         ; Call-process-regions return value
-       (test (assoc "test" info)); The test clause
-       )
-    (setq status (and test (mm-string-to-tokens (cdr test))))
-    (if (and (assoc "needsx11" info) (not (getenv "DISPLAY")))
-       (setq status nil)
-      (cond
-       ((and (equal (nth 0 status) "test")
-            (equal (nth 1 status) "-n")
-            (or (equal (nth 2 status) "$DISPLAY")
-                (equal (nth 2 status) "\"$DISPLAY\"")))
-       (setq status (if (getenv "DISPLAY") t nil)))
-       ((and (equal (nth 0 status) "test")
-            (equal (nth 1 status) "-z")
-            (or (equal (nth 2 status) "$DISPLAY")
-                (equal (nth 2 status) "\"$DISPLAY\"")))
-       (setq status (if (getenv "DISPLAY") nil t)))
-       (test nil)
-       (t nil)))
-    (and test (listp test) (setcdr test status))))
-
-(defun mm-parse-args (st &optional nd nodowncase)
-  ;; Return an assoc list of attribute/value pairs from an RFC822-type string
-  (let (
-       name                            ; From name=
-       value                           ; its value
-       results                         ; Assoc list of results
-       name-pos                        ; Start of XXXX= position
-       val-pos                         ; Start of value position
-       )
-    (save-excursion
-      (if (stringp st)
-         (progn
-           (set-buffer (get-buffer-create " *mm-temp*"))
-           (set-syntax-table mm-parse-args-syntax-table)
-           (erase-buffer)
-           (insert st)
-           (setq st (point-min)
-                 nd (point-max)))
-       (set-syntax-table mm-parse-args-syntax-table))
-      (save-restriction
-       (narrow-to-region st nd)
-       (goto-char (point-min))
-       (while (not (eobp))
-         (skip-chars-forward "; \n\t")
-         (setq name-pos (point))
-         (skip-chars-forward "^ \n\t=;")
-         (if (not nodowncase)
-             (downcase-region name-pos (point)))
-         (setq name (buffer-substring name-pos (point)))
-         (skip-chars-forward " \t\n")
-         (if (/= (or (char-after (point)) 0)  ?=) ; There is no value
-             (setq value nil)
-           (skip-chars-forward " \t\n=")
-           (setq val-pos (point)
-                 value
-                 (cond
-                  ((or (= (or (char-after val-pos) 0) ?\")
-                       (= (or (char-after val-pos) 0) ?'))
-                   (buffer-substring (1+ val-pos)
-                                     (condition-case ()
-                                         (prog2
-                                             (forward-sexp 1)
-                                             (1- (point))
-                                           (skip-chars-forward "\""))
-                                       (error
-                                        (skip-chars-forward "^ \t\n")
-                                        (point)))))
-                  (t
-                   (buffer-substring val-pos
-                                     (progn
-                                       (skip-chars-forward "^;")
-                                       (skip-chars-backward " \t")
-                                       (point)))))))
-         (setq results (cons (cons name value) results))
-         (skip-chars-forward "; \n\t"))
-       results))))
-\f
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; The action routines.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mm-possible-viewers (major minor)
-  ;; Return a list of possible viewers from MAJOR for minor type MINOR
-  (let ((exact '())
-       (wildcard '()))
-    (while major
-      (cond
-       ((equal (car (car major)) minor)
-       (setq exact (cons (cdr (car major)) exact)))
-       ((string-match (car (car major)) minor)
-       (setq wildcard (cons (cdr (car major)) wildcard))))
-      (setq major (cdr major)))
-    (nconc (nreverse exact) (nreverse wildcard))))
-
-(defun mm-unescape-mime-test (test type-info)
-  (let ((buff (get-buffer-create " *unescape*"))
-       save-pos save-chr subst)
-    (cond
-     ((symbolp test) test)
-     ((and (listp test) (symbolp (car test))) test)
-     ((or (stringp test)
-         (and (listp test) (stringp (car test))
-              (setq test (mapconcat 'identity test " "))))
-      (save-excursion
-       (set-buffer buff)
-       (erase-buffer)
-       (insert test)
-       (goto-char (point-min))
-       (while (not (eobp))
-         (skip-chars-forward "^%")
-         (if (/= (- (point)
-                    (progn (skip-chars-backward "\\\\")
-                           (point)))
-                 0) ; It is an escaped %
-             (progn
-               (delete-char 1)
-               (skip-chars-forward "%."))
-           (setq save-pos (point))
-           (skip-chars-forward "%")
-           (setq save-chr (char-after (point)))
-           (cond
-            ((null save-chr) nil)
-            ((= save-chr ?t)
-             (delete-region save-pos (progn (forward-char 1) (point)))
-             (insert (or (cdr (assoc "type" type-info)) "\"\"")))
-            ((= save-chr ?M)
-             (delete-region save-pos (progn (forward-char 1) (point)))
-             (insert "\"\""))
-            ((= save-chr ?n)
-             (delete-region save-pos (progn (forward-char 1) (point)))
-             (insert "\"\""))
-            ((= save-chr ?F)
-             (delete-region save-pos (progn (forward-char 1) (point)))
-             (insert "\"\""))
-            ((= save-chr ?{)
-             (forward-char 1)
-             (skip-chars-forward "^}")
-             (downcase-region (+ 2 save-pos) (point))
-             (setq subst (buffer-substring (+ 2 save-pos) (point)))
-             (delete-region save-pos (1+ (point)))
-             (insert (or (cdr (assoc subst type-info)) "\"\"")))
-            (t nil))))
-       (buffer-string)))
-     (t (error "Bad value to mm-unescape-mime-test. %s" test)))))
-
-(defun mm-viewer-passes-test (viewer-info type-info)
-  ;; Return non-nil iff the viewer specified by VIEWER-INFO passes its
-  ;; test clause (if any).
-  (let* ((test-info   (assoc "test"   viewer-info))
-        (test (cdr test-info))
-        (viewer (cdr (assoc "viewer" viewer-info)))
-        (default-directory (expand-file-name "~/"))
-        status
-        parsed-test
-       )
-    (cond
-     ((not test-info) t)               ; No test clause
-     ((not test) nil)                  ; Already failed test
-     ((eq test t) t)                   ; Already passed test
-     ((and (symbolp test)              ; Lisp function as test
-          (fboundp test))
-      (funcall test type-info))
-     ((and (symbolp test)              ; Lisp variable as test
-          (boundp test))
-      (symbol-value test))
-     ((and (listp test)                        ; List to be eval'd
-          (symbolp (car test)))
-      (eval test))
-     (t
-      (setq test (mm-unescape-mime-test test type-info)
-           test (list shell-file-name nil nil nil shell-command-switch test)
-           status (apply 'call-process test))
-      (= 0 status)))))
-
-(defun mm-add-mailcap-entry (major minor info)
-  (let ((old-major (assoc major mm-mime-data)))
-    (if (null old-major)               ; New major area
-       (setq mm-mime-data
-             (cons (cons major (list (cons minor info)))
-                   mm-mime-data))
-      (let ((cur-minor (assoc minor old-major)))
-       (cond
-        ((or (null cur-minor)          ; New minor area, or
-             (assoc "test" info))      ; Has a test, insert at beginning
-         (setcdr old-major (cons (cons minor info) (cdr old-major))))
-        ((and (not (assoc "test" info)); No test info, replace completely
-              (not (assoc "test" cur-minor)))
-         (setcdr cur-minor info))
-        (t
-         (setcdr old-major (cons (cons minor info) (cdr old-major)))))))))
-
-\f
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; The main whabbo
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mm-viewer-lessp (x y)
-  ;; Return t iff viewer X is more desirable than viewer Y
-  (let ((x-wild (string-match "[*?]" (or (cdr-safe (assoc "type" x)) "")))
-       (y-wild (string-match "[*?]" (or (cdr-safe (assoc "type" y)) "")))
-       (x-lisp (not (stringp (or (cdr-safe (assoc "viewer" x)) ""))))
-       (y-lisp (not (stringp (or (cdr-safe (assoc "viewer" y)) "")))))
-    (cond
-     ((and x-lisp (not y-lisp))
-      t)
-     ((and (not y-lisp) x-wild (not y-wild))
-      t)
-     ((and (not x-wild) y-wild)
-      t)
-     (t nil))))
-
-(defun mm-mime-info (st &optional nd request)
-  "Get the mime viewer command for HEADERLINE, return nil if none found.
-Expects a complete content-type header line as its argument.  This can
-be simple like text/html, or complex like text/plain; charset=blah; foo=bar
-
-Third argument REQUEST specifies what information to return.  If it is
-nil or the empty string, the viewer (second field of the mailcap
-entry) will be returned.  If it is a string, then the mailcap field
-corresponding to that string will be returned (print, description,
-whatever).  If a number, then all the information for this specific
-viewer is returned."
-  (let (
-       major                           ; Major encoding (text, etc)
-       minor                           ; Minor encoding (html, etc)
-       info                            ; Other info
-       save-pos                        ; Misc. position during parse
-       major-info                      ; (assoc major mm-mime-data)
-       minor-info                      ; (assoc minor major-info)
-       test                            ; current test proc.
-       viewers                         ; Possible viewers
-       passed                          ; Viewers that passed the test
-       viewer                          ; The one and only viewer
-       )
-    (save-excursion
-      (cond
-       ((null st)
-       (set-buffer (get-buffer-create " *mimeparse*"))
-       (erase-buffer)
-       (insert "text/plain")
-       (setq st (point-min)))
-       ((stringp st)
-       (set-buffer (get-buffer-create " *mimeparse*"))
-       (erase-buffer)
-       (insert st)
-       (setq st (point-min)))
-       ((null nd)
-       (narrow-to-region st (progn (goto-char st) (end-of-line) (point))))
-       (t (narrow-to-region st nd)))
-      (goto-char st)
-      (skip-chars-forward ": \t\n")
-      (buffer-enable-undo)
-      (setq viewer
-           (catch 'mm-exit
-             (setq save-pos (point))
-             (skip-chars-forward "^/")
-             (downcase-region save-pos (point))
-             (setq major (buffer-substring save-pos (point)))
-             (if (not (setq major-info (cdr (assoc major mm-mime-data))))
-                 (throw 'mm-exit nil))
-             (skip-chars-forward "/ \t\n")
-             (setq save-pos (point))
-             (skip-chars-forward "^ \t\n;")
-             (downcase-region save-pos (point))
-             (setq minor (buffer-substring save-pos (point)))
-             (if (not
-                  (setq viewers (mm-possible-viewers major-info minor)))
-                 (throw 'mm-exit nil))
-             (skip-chars-forward "; \t")
-             (if (eolp)
-                 nil                           ; No qualifiers
-               (setq save-pos (point))
-               (end-of-line)
-               (setq info (mm-parse-args save-pos (point)))
-               )
-             (while viewers
-               (if (mm-viewer-passes-test (car viewers) info)
-                   (setq passed (cons (car viewers) passed)))
-               (setq viewers (cdr viewers)))
-             (setq passed (sort (nreverse passed) 'mm-viewer-lessp))
-             (car passed)))
-      (if (and (stringp (cdr (assoc "viewer" viewer)))
-              passed)
-         (setq viewer (car passed)))
-      (widen)
-      (cond
-       ((and (null viewer) (not (equal major "default")))
-       (mm-mime-info "default" nil request))
-       ((or (null request) (equal request ""))
-       (mm-unescape-mime-test (cdr (assoc "viewer" viewer)) info))
-       ((stringp request)
-       (if (or (string= request "test") (string= request "viewer"))
-           (mm-unescape-mime-test (cdr-safe (assoc request viewer)) info)))
-       (t
-       ;; MUST make a copy *sigh*, else we modify mm-mime-data
-       (setq viewer (mm-copy-tree viewer))
-       (let ((view (assoc "viewer" viewer))
-             (test (assoc "test" viewer)))
-         (if view (setcdr view (mm-unescape-mime-test (cdr view) info)))
-         (if test (setcdr test (mm-unescape-mime-test (cdr test) info))))
-       viewer)))))
-
-\f
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Experimental MIME-types parsing
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar mm-mime-extensions
-  '(
-    (""          . "text/plain")
-    (".abs"      . "audio/x-mpeg")
-    (".aif"      . "audio/aiff")
-    (".aifc"     . "audio/aiff")
-    (".aiff"     . "audio/aiff")
-    (".ano"      . "application/x-annotator")
-    (".au"       . "audio/ulaw")
-    (".avi"      . "video/x-msvideo")
-    (".bcpio"    . "application/x-bcpio")
-    (".bin"      . "application/octet-stream")
-    (".cdf"      . "application/x-netcdr")
-    (".cpio"     . "application/x-cpio")
-    (".csh"      . "application/x-csh")
-    (".dvi"      . "application/x-dvi")
-    (".el"       . "application/emacs-lisp")
-    (".eps"      . "application/postscript")
-    (".etx"      . "text/x-setext")
-    (".exe"      . "application/octet-stream")
-    (".fax"      . "image/x-fax")
-    (".gif"      . "image/gif")
-    (".hdf"      . "application/x-hdf")
-    (".hqx"      . "application/mac-binhex40")
-    (".htm"      . "text/html")
-    (".html"     . "text/html")
-    (".icon"     . "image/x-icon")
-    (".ief"      . "image/ief")
-    (".jpg"      . "image/jpeg")
-    (".macp"     . "image/x-macpaint")
-    (".man"      . "application/x-troff-man")
-    (".me"       . "application/x-troff-me")
-    (".mif"      . "application/mif")
-    (".mov"      . "video/quicktime")
-    (".movie"    . "video/x-sgi-movie")
-    (".mp2"      . "audio/x-mpeg")
-    (".mp2a"     . "audio/x-mpeg2")
-    (".mpa"      . "audio/x-mpeg")
-    (".mpa2"     . "audio/x-mpeg2")
-    (".mpe"      . "video/mpeg")
-    (".mpeg"     . "video/mpeg")
-    (".mpega"    . "audio/x-mpeg")
-    (".mpegv"    . "video/mpeg")
-    (".mpg"      . "video/mpeg")
-    (".mpv"      . "video/mpeg")
-    (".ms"       . "application/x-troff-ms")
-    (".nc"       . "application/x-netcdf")
-    (".nc"       . "application/x-netcdf")
-    (".oda"      . "application/oda")
-    (".pbm"      . "image/x-portable-bitmap")
-    (".pdf"      . "application/pdf")
-    (".pgm"      . "image/portable-graymap")
-    (".pict"     . "image/pict")
-    (".png"      . "image/png")
-    (".pnm"      . "image/x-portable-anymap")
-    (".ppm"      . "image/portable-pixmap")
-    (".ps"       . "application/postscript")
-    (".qt"       . "video/quicktime")
-    (".ras"      . "image/x-raster")
-    (".rgb"      . "image/x-rgb")
-    (".rtf"      . "application/rtf")
-    (".rtx"      . "text/richtext")
-    (".sh"       . "application/x-sh")
-    (".sit"      . "application/x-stuffit")
-    (".snd"      . "audio/basic")
-    (".src"      . "application/x-wais-source")
-    (".tar"      . "archive/tar")
-    (".tcl"      . "application/x-tcl")
-    (".tcl"      . "application/x-tcl")
-    (".tex"      . "application/x-tex")
-    (".texi"     . "application/texinfo")
-    (".tga"      . "image/x-targa")
-    (".tif"      . "image/tiff")
-    (".tiff"     . "image/tiff")
-    (".tr"       . "application/x-troff")
-    (".troff"    . "application/x-troff")
-    (".tsv"      . "text/tab-separated-values")
-    (".txt"      . "text/plain")
-    (".vbs"      . "video/mpeg")
-    (".vox"      . "audio/basic")
-    (".vrml"     . "x-world/x-vrml")
-    (".wav"      . "audio/x-wav")
-    (".wrl"      . "x-world/x-vrml")
-    (".xbm"      . "image/xbm")
-    (".xpm"      . "image/x-pixmap")
-    (".xwd"      . "image/windowdump")
-    (".zip"      . "application/zip")
-    (".ai"       . "application/postscript")
-    (".jpe"      . "image/jpeg")
-    (".jpeg"     . "image/jpeg")
-    )
-  "*An assoc list of file extensions and the MIME content-types they
-correspond to.")
-
-(defun mm-parse-mimetypes (&optional path)
-  ;; Parse out all the mimetypes specified in a unix-style path string PATH
-  (cond
-   (path nil)
-   ((getenv "MIMETYPES") (setq path (getenv "MIMETYPES")))
-   ((memq system-type '(ms-dos ms-windows windows-nt))
-    (setq path (mapconcat 'expand-file-name
-                         '("~/mime.typ" "~/etc/mime.typ") ";")))
-   (t (setq path (mapconcat 'expand-file-name
-                           '("~/.mime-types"
-                             "/etc/mime-types:/usr/etc/mime-types"
-                             "/usr/local/etc/mime-types"
-                             "/usr/local/www/conf/mime-types") ":"))))
-  (let ((fnames (reverse
-                (mm-string-to-tokens path
-                                     (if (memq system-type
-                                               '(ms-dos ms-windows windows-nt))
-                                         ?;
-                                       ?:))))
-       fname)
-    (while fnames
-      (setq fname (car fnames))
-      (if (and (file-exists-p fname) (file-readable-p fname))
-         (mm-parse-mimetype-file (car fnames)))
-      (setq fnames (cdr fnames)))))
-
-(defun mm-parse-mimetype-file (fname)
-  ;; Parse out a mime-types file
-  (let (type                           ; The MIME type for this line
-       extns                           ; The extensions for this line
-       save-pos                        ; Misc. saved buffer positions
-       )
-    (save-excursion
-      (set-buffer (get-buffer-create " *mime-types*"))
-      (erase-buffer)
-      (insert-file-contents fname)
-      (mm-replace-regexp "#.*" "")
-      (mm-replace-regexp "\n+" "\n")
-      (mm-replace-regexp "[ \t]+$" "")
-      (goto-char (point-max))
-      (skip-chars-backward " \t\n")
-      (delete-region (point) (point-max))
-      (goto-char (point-min))
-      (while (not (eobp))
-       (skip-chars-forward " \t\n")
-       (setq save-pos (point))
-       (skip-chars-forward "^ \t")
-       (downcase-region save-pos (point))
-       (setq type (buffer-substring save-pos (point)))
-       (while (not (eolp))
-         (skip-chars-forward " \t")
-         (setq save-pos (point))
-         (skip-chars-forward "^ \t\n")
-         (setq extns (cons (buffer-substring save-pos (point)) extns)))
-       (while extns
-         (setq mm-mime-extensions
-               (cons
-                (cons (if (= (string-to-char (car extns)) ?.)
-                          (car extns)
-                        (concat "." (car extns))) type) mm-mime-extensions)
-               extns (cdr extns)))))))
-
-(defun mm-extension-to-mime (extn)
-  "Return the MIME content type of the file extensions EXTN"
-  (if (and (stringp extn)
-          (not (eq (string-to-char extn) ?.)))
-      (setq extn (concat "." extn)))
-  (cdr (assoc (downcase extn) mm-mime-extensions)))
-
-\f
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Editing/Composition of body parts
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mm-compose-type (type)
-  ;; Compose a body section of MIME-type TYPE.
-  (let* ((info (mm-mime-info type nil 5))
-        (fnam (mm-generate-unique-filename))
-        (comp (or (cdr (assoc "compose" info))))
-        (ctyp (cdr (assoc "composetyped" info)))
-        (buff (get-buffer-create " *mimecompose*"))
-        (typeit (not ctyp))
-        (retval "")
-        (usef nil))
-    (setq comp (mm-unescape-mime-test (or comp ctyp) info))
-    (while (string-match "\\([^\\\\]\\)%s" comp)
-      (setq comp (concat (substring comp 0 (match-end 1)) fnam
-                        (substring comp (match-end 0) nil))
-           usef t))
-    (call-process shell-file-name nil
-                 (if usef nil buff)
-                 nil shell-command-switch comp)
-    (setq retval
-         (concat
-          (if typeit (concat "Content-type: " type "\r\n\r\n") "")
-          (if usef
-              (save-excursion
-                (set-buffer buff)
-                (erase-buffer)
-                (insert-file-contents fnam)
-                (buffer-string))
-            (save-excursion
-              (set-buffer buff)
-              (buffer-string)))
-          "\r\n"))
-    retval))   
-\f
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Misc.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mm-type-to-file (type)
-  "Return the file extension for content-type TYPE"
-  (rassoc type mm-mime-extensions))
-
-\f
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Miscellaneous MIME viewers written in elisp
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mm-play-sound-file (&optional buff)
-  "Play a sound file in buffer BUFF (defaults to current buffer)"
-  (setq buff (or buff (current-buffer)))
-  (let ((fname (mm-generate-unique-filename "%s.au"))
-       (synchronous-sounds t))         ; Play synchronously
-    (mule-write-region-no-coding-system (point-min) (point-max) fname)
-    (kill-buffer (current-buffer))
-    (play-sound-file fname)
-    (condition-case ()
-       (delete-file fname)
-      (error nil))))
-    
-(defun mm-parse-mime-headers (&optional no-delete)
-  "Return a list of the MIME headers at the top of this buffer.  If
-optional argument NO-DELETE is non-nil, don't delete the headers."
-  (let* ((st (point-min))
-        (nd (progn
-              (goto-char (point-min))
-              (skip-chars-forward " \t\n")
-              (if (re-search-forward "^\r*$" nil t)
-                  (1+ (point))
-                (point-max))))
-        save-pos
-        status
-        hname
-        hvalu
-        result
-        search
-        )
-    (narrow-to-region st (min nd (point-max)))
-    (goto-char (point-min))
-    (while (not (eobp))
-      (skip-chars-forward " \t\n\r")
-      (setq save-pos (point))
-      (skip-chars-forward "^:\n\r")
-      (downcase-region save-pos (point))
-      (setq hname (buffer-substring save-pos (point)))
-      (skip-chars-forward ": \t ")
-      (setq save-pos (point))
-      (skip-chars-forward "^\n\r")
-      (setq search t)
-      (while search
-       (skip-chars-forward "^\n\r")
-       (save-excursion
-         (skip-chars-forward "\n\r")
-         
-         (setq search
-               (string-match "[ \t]"
-                             (char-to-string
-                              (or (char-after (point)) ?a)))))
-       (if search
-           (skip-chars-forward "\n\r")))
-      (setq hvalu (buffer-substring save-pos (point))
-           result (cons (cons hname hvalu) result)))
-    (or no-delete (delete-region st nd))
-    result))
-
-(defun mm-find-available-multiparts (separator &optional buf)
-  "Return a list of mime-headers for the various body parts of a 
-multipart message in buffer BUF with separator SEPARATOR.
-The different multipart specs are put in `mm-temporary-directory'."
-  (let ((sep (concat "^--" separator "\r*$"))
-       headers
-       fname
-       results)
-    (save-excursion
-      (and buf (set-buffer buf))
-      (goto-char (point-min))
-      (while (re-search-forward sep nil t)
-       (let ((st (set-marker (make-marker)
-                             (progn
-                               (forward-line 1)
-                               (beginning-of-line)
-                               (point))))
-             (nd (set-marker (make-marker)
-                             (if (re-search-forward sep nil t)
-                                 (1- (match-beginning 0))
-                               (point-max)))))
-         (narrow-to-region st nd)
-         (goto-char st)
-         (if (looking-at "^\r*$")
-             (insert "Content-type: text/plain\n"
-                     "Content-length: " (int-to-string (- nd st)) "\n"))
-         (setq headers (mm-parse-mime-headers)
-               fname (mm-generate-unique-filename))
-         (let ((x (or (cdr (assoc "content-type" headers)) "text/plain")))
-           (if (string-match "name=\"*\\([^ \"]+\\)\"*" x)
-               (setq fname (expand-file-name
-                            (substring x (match-beginning 1)
-                                       (match-end 1))
-                            mm-temporary-directory))))
-         (widen)
-         (if (assoc "content-transfer-encoding" headers)
-             (let ((coding (cdr
-                            (assoc "content-transfer-encoding" headers)))
-                   (cmd nil))
-               (setq coding (and coding (downcase coding))
-                     cmd (or (cdr (assoc coding
-                                         mm-content-transfer-encodings))
-                             (read-string
-                              (concat "How shall I decode " coding "? ")
-                              "cat")))
-               (if (string= cmd "") (setq cmd "cat"))
-               (if (stringp cmd)
-                   (shell-command-on-region st nd cmd t)
-                 (funcall cmd st nd))
-               (or (eq cmd 'ignore) (set-marker nd (point)))))
-         (write-region st nd fname nil 5)
-         (delete-region st nd)
-         (setq results (cons
-                        (cons
-                         (cons "mm-filename" fname) headers) results)))))
-    results))
-
-(defun mm-format-multipart-as-html (&optional buf type)
-  (if buf (set-buffer buf))
-  (let* ((boundary (if (string-match
-                       "boundary[ \t]*=[ \t\"]*\\([^ \"\t\n]+\\)"
-                       type)
-                      (regexp-quote
-                       (substring type (match-beginning 1) (match-end 1)))))
-        (parts    (mm-find-available-multiparts boundary)))
-    (erase-buffer)
-    (insert "<html>\n"
-           " <head>\n"
-           "  <title>Multipart Message</title>\n"
-           " </head>\n"
-           " <body>\n"
-           "   <h1> Multipart message encountered </h1>\n"
-           "   <p> I have encountered a multipart MIME message.\n"
-           "       The following parts have been detected.  Please\n"
-           "       select which one you want to view.\n"
-           "   </p>\n"
-           "   <ul>\n"
-           (mapconcat 
-            (function (lambda (x)
-                        (concat "    <li> <a href=\"file:"
-                                (cdr (assoc "mm-filename" x))
-                                "\">"
-                                (or (cdr (assoc "content-description" x)) "")
-                                "--"
-                                (or (cdr (assoc "content-type" x))
-                                    "unknown type")
-                                "</a> </li>")))
-            parts "\n")
-           "   </ul>\n"
-           " </body>\n"
-           "</html>\n"
-           "<!-- Automatically generated by MM v" mm-version "-->\n")))
-
-(defun mm-multipart-viewer ()
-  (mm-format-multipart-as-html
-   (current-buffer)
-   (cdr (assoc "content-type" url-current-mime-headers)))
-  (let ((w3-working-buffer (current-buffer)))
-    (w3-prepare-buffer)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Transfer encodings we can decrypt automatically
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mm-decode-quoted-printable (&optional st nd)
-  (interactive)
-  (setq st (or st (point-min))
-       nd (or nd (point-max)))
-  (save-restriction
-    (narrow-to-region st nd)
-    (save-excursion
-      (let ((buffer-read-only nil))
-       (goto-char (point-min))
-       (while (re-search-forward "=[0-9A-F][0-9A-F]" nil t)
-         (replace-match 
-          (char-to-string 
-           (+
-            (* 16 (mm-hex-char-to-integer 
-                   (char-after (1+ (match-beginning 0)))))
-            (mm-hex-char-to-integer
-             (char-after (1- (match-end 0))))))))))
-    (goto-char (point-max))))
-
-;; Taken from hexl.el.
-(defun mm-hex-char-to-integer (character)
-  "Take a char and return its value as if it was a hex digit."
-  (if (and (>= character ?0) (<= character ?9))
-      (- character ?0)
-    (let ((ch (logior character 32)))
-      (if (and (>= ch ?a) (<= ch ?f))
-         (- ch (- ?a 10))
-       (error (format "Invalid hex digit `%c'." ch))))))
-
-
-\f
-(require 'base64)
-(provide 'mm)
index f885c46..f417484 100644 (file)
@@ -143,10 +143,13 @@ from the document.")
 (defvoo nndoc-head-begin-function nil)
 (defvoo nndoc-body-end nil)
 ;; nndoc-dissection-alist is a list of sublists.  Each sublist holds the
-;; following items.  ARTICLE is an ordinal starting at 1.  HEAD-BEGIN,
-;; HEAD-END, BODY-BEGIN and BODY-END are positions in the `nndoc' buffer.
-;; LINE-COUNT is a count of lines in the body.  SUBJECT, MESSAGE-ID and
-;; REFERENCES, only present for MIME dissections, are field values.
+;; following items.  ARTICLE act as the association key and is an ordinal
+;; starting at 1.  HEAD-BEGIN [0], HEAD-END [1], BODY-BEGIN [2] and BODY-END
+;; [3] are positions in the `nndoc' buffer.  LINE-COUNT [4] is a count of
+;; lines in the body.  For MIME dissections only, ARTICLE-INSERT [5] and
+;; SUMMARY-INSERT [6] give headers to insert for full article or summary line
+;; generation, respectively.  Other headers usually follow directly from the
+;; buffer.  Value `nil' means no insert.
 (defvoo nndoc-dissection-alist nil)
 (defvoo nndoc-prepare-body-function nil)
 (defvoo nndoc-generate-head-function nil)
@@ -158,8 +161,6 @@ from the document.")
 (defvoo nndoc-current-buffer nil
   "Current nndoc news buffer.")
 (defvoo nndoc-address nil)
-(defvoo nndoc-mime-header nil)
-(defvoo nndoc-mime-subject nil)
 
 (defconst nndoc-version "nndoc 1.0"
   "nndoc version.")
@@ -459,30 +460,19 @@ from the document.")
       t)))
 
 (defun nndoc-transform-mime-parts (article)
-  (unless (= article 1)
-    ;; Ensure some MIME-Version.
-    (goto-char (point-min))
-    (search-forward "\n\n")
-    (let ((case-fold-search nil)
-         (limit (point)))
+  (let* ((entry (cdr (assq article nndoc-dissection-alist)))
+        (headers (nth 5 entry)))
+    (when headers
       (goto-char (point-min))
-      (or (save-excursion (re-search-forward "^MIME-Version:" limit t))
-         (insert "MIME-Version: 1.0\n")))
-    ;; Generate default header before entity fields.
-    (goto-char (point-min))
-    (nndoc-generate-mime-parts-head article t)))
-
-(defun nndoc-generate-mime-parts-head (article &optional body-present)
-  (let ((entry (cdr (assq (if body-present 1 article) nndoc-dissection-alist))))
-    (let ((subject (if body-present
-                      nndoc-mime-subject
-                    (concat "<" (nth 5 entry) ">")))
-         (message-id (nth 6 entry))
-         (references (nth 7 entry)))
-      (insert nndoc-mime-header)
-      (and subject (insert "Subject: " subject "\n"))
-      (and message-id (insert "Message-ID: " message-id "\n"))
-      (and references (insert "References: " references "\n")))))
+      (insert headers))))
+
+(defun nndoc-generate-mime-parts-head (article)
+  (let* ((entry (cdr (assq article nndoc-dissection-alist)))
+        (headers (nth 6 entry)))
+    (when headers
+      (insert headers))
+    (insert-buffer-substring
+     nndoc-current-buffer (car entry) (nth 1 entry))))
 
 (defun nndoc-clari-briefs-type-p ()
   (when (let ((case-fold-search nil))
@@ -668,92 +658,127 @@ the header of this entity, and one article per sub-entity."
        nndoc-mime-split-ordinal 0)
   (save-excursion
     (set-buffer nndoc-current-buffer)
-    (message-narrow-to-head)
-    (let ((case-fold-search t)
-         (message-id (message-fetch-field "Message-ID"))
-         (references (message-fetch-field "References")))
-      (setq nndoc-mime-header (buffer-substring (point-min) (point-max))
-           nndoc-mime-subject (message-fetch-field "Subject"))
-      (while (string-match "\
-^\\(Subject\\|Message-ID\\|References\\|Lines\\|\
-MIME-Version\\|Content-Type\\|Content-Transfer-Encoding\\|\
-\\):.*\n\\([ \t].*\n\\)*"
-                          nndoc-mime-header)
-       (setq nndoc-mime-header (replace-match "" t t nndoc-mime-header)))
-      (widen)
-      (nndoc-dissect-mime-parts-sub (point-min) (point-max)
-                                   nil message-id references))))
-
-(defun nndoc-dissect-mime-parts-sub (begin end position message-id references)
-  "Dissect an entity within a composite MIME message.
-The article, which corresponds to a MIME entity, extends from BEGIN to END.
+    (nndoc-dissect-mime-parts-sub (point-min) (point-max) nil nil nil)))
+
+(defun nndoc-dissect-mime-parts-sub (head-begin body-end article-insert
+                                               position parent)
+  "Dissect an entity, within a composite MIME message.
+The complete message or MIME entity extends from HEAD-BEGIN to BODY-END.
+ARTICLE-INSERT should be added at beginning for generating a full article.
 The string POSITION holds a dotted decimal representation of the article
 position in the hierarchical structure, it is nil for the outer entity.
-The generated article should use MESSAGE-ID and REFERENCES field values."
-  ;; Note: `case-fold-search' is already `t' from the calling function.
-  (let ((head-begin begin)
-       (body-end end)
-       head-end body-begin type subtype composite comment)
-    (save-excursion
+PARENT is the message-ID of the parent summary line, or nil for none."
+  (let ((case-fold-search t)
+       (message-id (nnmail-message-id))
+       head-end body-begin summary-insert message-rfc822 multipart-any
+       subject content-type type subtype boundary-regexp)
       ;; Gracefully handle a missing body.
       (goto-char head-begin)
       (if (search-forward "\n\n" body-end t)
          (setq head-end (1- (point))
                body-begin (point))
-       (setq head-end end
-             body-begin end))
+      (setq head-end body-end
+           body-begin body-end))
+    (narrow-to-region head-begin head-end)
       ;; Save MIME attributes.
       (goto-char head-begin)
-      (if (re-search-forward "\
-^Content-Type: *\\([^ \t\n/;]+\\)/\\([^ \t\n/;]+\\)"
-                            head-end t)
-         (setq type (downcase (match-string 1))
-               subtype (downcase (match-string 2)))
+    (setq content-type (message-fetch-field "Content-Type"))
+    (when content-type
+      (when (string-match "^ *\\([^ \t\n/;]+\\)/\\([^ \t\n/;]+\\)" content-type)
+       (setq type (downcase (match-string 1 content-type))
+             subtype (downcase (match-string 2 content-type))
+             message-rfc822 (and (string= type "message")
+                                 (string= subtype "rfc822"))
+             multipart-any (string= type "multipart")))
+      (when (string-match ";[ \t\n]*name=\\([^ \t\n;]+\\)" content-type)
+       (setq subject (match-string 1 content-type)))
+      (when (string-match "boundary=\"?\\([^\"\n]*[^\" \t\n]\\)" content-type)
+       (setq boundary-regexp (concat "\n--"
+                                     (regexp-quote
+                                      (match-string 1 content-type))
+                                     "\\(--\\)?[ \t]*\n"))))
+    (unless subject
+      (when (or multipart-any (not article-insert))
+       (setq subject (message-fetch-field "Subject"))))
+    (unless type
        (setq type "text"
              subtype "plain"))
-      (setq composite (string= type "multipart")
-           comment (concat position
-                           (when (and position composite) ".")
-                           (when composite "*")
-                           (when (or position composite) " ")
+    ;; Prepare the article and summary inserts.
+    (unless article-insert
+      (setq article-insert (buffer-substring (point-min) (point-max))
+           head-end head-begin))
+    (setq summary-insert article-insert)
+    ;; - summary Subject.
+    (setq summary-insert
+         (let ((line (concat "Subject: <" position
+                             (and position multipart-any ".")
+                             (and multipart-any "*")
+                             (and (or position multipart-any) " ")
                            (cond ((string= subtype "plain") type)
                                  ((string= subtype "basic") type)
-                                 (t subtype))))
+                                   (t subtype))
+                             ">"
+                             (and subject " ")
+                             subject
+                             "\n")))
+           (if (string-match "Subject:.*\n\\([ \t].*\n\\)*" summary-insert)
+               (replace-match line t t summary-insert)
+             (concat summary-insert line))))
+    ;; - summary Message-ID.
+    (setq summary-insert
+         (let ((line (concat "Message-ID: " message-id "\n")))
+           (if (string-match "Message-ID:.*\n\\([ \t].*\n\\)*" summary-insert)
+               (replace-match line t t summary-insert)
+             (concat summary-insert line))))
+    ;; - summary References.
+    (when parent
+      (setq summary-insert
+           (let ((line (concat "References: " parent "\n")))
+             (if (string-match "References:.*\n\\([ \t].*\n\\)*"
+                               summary-insert)
+                 (replace-match line t t summary-insert)
+               (concat summary-insert line)))))
       ;; Generate dissection information for this entity.
       (push (list (incf nndoc-mime-split-ordinal)
                  head-begin head-end body-begin body-end
                  (count-lines body-begin body-end)
-                 comment message-id references)
+               article-insert summary-insert)
            nndoc-dissection-alist)
       ;; Recurse for all sub-entities, if any.
-      (goto-char head-begin)
-      (when (re-search-forward
-            (concat "\
-^Content-Type: *multipart/\\([a-z]+\\);\\(.*;\\)*"
-                    "[ \t\n]*[ \t]boundary=\"?\\([^\"\n]*[^\" \t\n]\\)")
-          head-end t)
-       (let ((boundary (concat "\n--" (match-string 3) "\\(--\\)?[ \t]*\n"))
-             (part-counter 0)
-             begin end eof-flag)
-         (goto-char head-end)
-         (setq eof-flag (not (re-search-forward boundary body-end t)))
+    (widen)
+    (cond
+     (message-rfc822
+      (save-excursion
+       (nndoc-dissect-mime-parts-sub body-begin body-end nil
+                                     position message-id)))
+     ((and multipart-any boundary-regexp)
+      (let ((part-counter 0)
+           part-begin part-end eof-flag)
+       (while (string-match "\
+^\\(Lines\\|Content-\\(Type\\|Transfer-Encoding\\)\\):.*\n\\([ \t].*\n\\)*"
+                            article-insert)
+         (setq article-insert (replace-match "" t t article-insert)))
+       (let ((case-fold-search nil))
+         (goto-char body-begin)
+         (setq eof-flag (not (re-search-forward boundary-regexp body-end t)))
          (while (not eof-flag)
-           (setq begin (point))
-           (cond ((re-search-forward boundary body-end t)
+           (setq part-begin (point))
+           (cond ((re-search-forward boundary-regexp body-end t)
                   (or (not (match-string 1))
                       (string= (match-string 1) "")
                       (setq eof-flag t))
                   (forward-line -1)
-                  (setq end (point))
+                  (setq part-end (point))
                   (forward-line 1))
-                 (t (setq end body-end
+                 (t (setq part-end body-end
                           eof-flag t)))
-           (nndoc-dissect-mime-parts-sub begin end
-                                         (concat position (when position ".")
-                                                 (format "%d"
-                                                         (incf part-counter)))
-                                         (nnmail-message-id)
-                                         message-id)))))))
+           (save-excursion
+             (nndoc-dissect-mime-parts-sub
+              part-begin part-end article-insert
+              (concat position
+                      (and position ".")
+                      (format "%d" (incf part-counter)))
+              message-id)))))))))
 
 ;;;###autoload
 (defun nndoc-add-type (definition &optional position)
index fdeb989..8878a78 100644 (file)
 
 (eval-and-compile
   (eval
-   '(if (not (fboundp 'base64-encode-string))
-       (require 'base64))))
+   '(unless (fboundp 'base64-decode-string)
+      (autoload 'base64-decode-string "base64")
+      (autoload 'base64-encode-region "base64" nil t))))
 (require 'qp)
 (require 'mm-util)
-(require 'drums)
+(require 'ietf-drums)
 
 (defvar rfc2047-default-charset 'iso-8859-1
   "Default MIME charset -- does not need encoding.")
@@ -148,7 +149,8 @@ Should be called narrowed to the head of the message."
     (save-restriction
       (narrow-to-region b e)
       (goto-char (point-min))
-      (while (re-search-forward (concat "[^" drums-tspecials " \t\n]+") nil t)
+      (while (re-search-forward
+             (concat "[^" ietf-drums-tspecials " \t\n]+") nil t)
        (push
         (list (match-beginning 0) (match-end 0)
               (car
@@ -229,7 +231,7 @@ Should be called narrowed to the head of the message."
          (pop alist))
        (goto-char (point-min))
        (while (not (eobp))
-         (forward-char 64)
+         (goto-char (min (point-max) (+ 64 (point))))
          (search-backward "=" nil (- (point) 2))
          (unless (eobp)
            (insert "\n")))))))
@@ -305,9 +307,7 @@ If your Emacs implementation can't decode CHARSET, it returns nil."
       (mm-decode-coding-string
        (cond
        ((equal "B" encoding)
-        (if (fboundp 'base64-decode-string)
-            (base64-decode-string string)
-          (base64-decode string)))
+        (base64-decode-string string))
        ((equal "Q" encoding)
         (quoted-printable-decode-string
          (mm-replace-chars-in-string string ?_ ? )))
index 2998472..e7a0417 100644 (file)
@@ -23,7 +23,7 @@
 
 ;;; Code:
 
-(require 'drums)
+(require 'ietf-drums)
 
 (defun rfc2231-get-value (ct attribute)
   "Return the value of ATTRIBUTE from CT."
 The list will be on the form
  `(name (attribute . value) (attribute . value)...)"
   (with-temp-buffer
-    (let ((ttoken (drums-token-to-list drums-text-token))
-         (stoken (drums-token-to-list drums-tspecials))
-         (ntoken (drums-token-to-list "0-9"))
+    (let ((ttoken (ietf-drums-token-to-list ietf-drums-text-token))
+         (stoken (ietf-drums-token-to-list ietf-drums-tspecials))
+         (ntoken (ietf-drums-token-to-list "0-9"))
          (prev-value "")
          display-name mailbox c display-string parameters
          attribute value type subtype number encoded
          prev-attribute)
-      (drums-init (mail-header-remove-whitespace
+      (ietf-drums-init (mail-header-remove-whitespace
                   (mail-header-remove-comments string)))
-      (let ((table (copy-syntax-table drums-syntax-table)))
+      (let ((table (copy-syntax-table ietf-drums-syntax-table)))
        (modify-syntax-entry ?\' "w" table)
        (set-syntax-table table))
       (setq c (following-char))
index f98699f..923d4b1 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo                  @c -*-texinfo-*-
 
 @setfilename gnus-ja
-@settitle Semi-gnus 6.10.019 Manual
+@settitle Semi-gnus 6.10.020 Manual
 @synindex fn cp
 @synindex vr cp
 @synindex pg cp
@@ -345,7 +345,7 @@ into another language, under the above conditions for modified versions.
 @tex
 
 @titlepage
-@title Semi-gnus 6.10.019 Manual
+@title Semi-gnus 6.10.020 Manual
 
 @author by Lars Magne Ingebrigtsen
 @author by members of Semi-gnus mailing-list
@@ -399,7 +399,7 @@ Semi-gnus \e$B$O!"Bg$-$J3($,F~$C$F$$$?$j$5$^$6$^$J7A<0$rMQ$$$?$j$7$F$$$k$A$g$C\e(B
 \e$B$J8@8l7w$r:9JL$7$^$;$s!#$"$"!"%/%j%s%4%s$NJ}$O\e(B Unicode Next Generation\e$B$r\e(B
 \e$B$*BT$A$/$@$5$$!#\e(B
 
-\e$B$3$N@bL@=q$O\e(B Semi-gnus 6.10.019 \e$B$KBP1~$7$^$9!#\e(B
+\e$B$3$N@bL@=q$O\e(B Semi-gnus 6.10.020 \e$B$KBP1~$7$^$9!#\e(B
 
 @end ifinfo
 
index d1af82a..abc4dbd 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo                  @c -*-texinfo-*-
 
 @setfilename gnus
-@settitle Semi-gnus 6.10.019 Manual
+@settitle Semi-gnus 6.10.020 Manual
 @synindex fn cp
 @synindex vr cp
 @synindex pg cp
@@ -318,7 +318,7 @@ into another language, under the above conditions for modified versions.
 @tex
 
 @titlepage
-@title Semi-gnus 6.10.019 Manual
+@title Semi-gnus 6.10.020 Manual
 
 @author by Lars Magne Ingebrigtsen
 @page
@@ -361,7 +361,7 @@ internationalization/localization and multiscript features based on MULE
 API.  So Semi-gnus does not discriminate various language communities.
 Oh, if you are a Klingon, please wait Unicode Next Generation.
 
-This manual corresponds to Semi-gnus 6.10.019.
+This manual corresponds to Semi-gnus 6.10.020.
 
 @end ifinfo
 
index c9d2568..a048867 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo                  @c -*-texinfo-*-
 
 @setfilename message
-@settitle Pterodactyl Message 0.30 Manual
+@settitle Pterodactyl Message 0.31 Manual
 @synindex fn cp
 @synindex vr cp
 @synindex pg cp
@@ -42,7 +42,7 @@ into another language, under the above conditions for modified versions.
 @tex
 
 @titlepage
-@title Pterodactyl Message 0.30 Manual
+@title Pterodactyl Message 0.31 Manual
 
 @author by Lars Magne Ingebrigtsen
 @page
@@ -83,7 +83,7 @@ Message mode buffers.
 * Key Index::         List of Message mode keys.
 @end menu
 
-This manual corresponds to Pterodactyl Message 0.30.  Message is
+This manual corresponds to Pterodactyl Message 0.31.  Message is
 distributed with the Gnus distribution bearing the same version number
 as this manual.