From 7f4eb44ef54b7bbcbe6f4fdcbb2d774f317d1901 Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Tue, 15 Sep 2015 09:57:27 +0200 Subject: [PATCH] adding mew as email client. --- bba.org | 83 + elpa/mew-20150813.2354/dir | 19 + elpa/mew-20150813.2354/etc/Mew.img | 13 + elpa/mew-20150813.2354/etc/Mew.png | Bin 0 -> 48019 bytes elpa/mew-20150813.2354/etc/Mew.xbm | 590 +++ elpa/mew-20150813.2354/etc/Mew.xpm | 442 +++ elpa/mew-20150813.2354/etc/mew-Audio.xpm | 42 + elpa/mew-20150813.2354/etc/mew-Blank.xpm | 40 + elpa/mew-20150813.2354/etc/mew-External.xpm | 42 + elpa/mew-20150813.2354/etc/mew-Folder.xpm | 41 + elpa/mew-20150813.2354/etc/mew-Image.xpm | 44 + .../etc/mew-Octet-Stream.xpm | 44 + elpa/mew-20150813.2354/etc/mew-Postscript.xpm | 42 + elpa/mew-20150813.2354/etc/mew-Rfc822.xpm | 43 + elpa/mew-20150813.2354/etc/mew-Text.xpm | 40 + elpa/mew-20150813.2354/etc/mew-Unknown.xpm | 41 + elpa/mew-20150813.2354/etc/mew-Video.xpm | 44 + elpa/mew-20150813.2354/etc/mew-attach.xpm | 36 + elpa/mew-20150813.2354/etc/mew-cite.xpm | 36 + elpa/mew-20150813.2354/etc/mew-forward.xpm | 36 + elpa/mew-20150813.2354/etc/mew-inc.xpm | 37 + elpa/mew-20150813.2354/etc/mew-lock.xpm | 30 + elpa/mew-20150813.2354/etc/mew-next.xpm | 36 + elpa/mew-20150813.2354/etc/mew-pgp-enc.xpm | 36 + elpa/mew-20150813.2354/etc/mew-pgp-sigenc.xpm | 36 + elpa/mew-20150813.2354/etc/mew-pgp-sign.xpm | 36 + elpa/mew-20150813.2354/etc/mew-prev.xpm | 36 + elpa/mew-20150813.2354/etc/mew-queue.xpm | 36 + elpa/mew-20150813.2354/etc/mew-refile.xpm | 36 + elpa/mew-20150813.2354/etc/mew-reply.xpm | 36 + elpa/mew-20150813.2354/etc/mew-send.xpm | 36 + elpa/mew-20150813.2354/etc/mew-sep.xpm | 36 + elpa/mew-20150813.2354/etc/mew-show.xpm | 36 + elpa/mew-20150813.2354/etc/mew-write.xpm | 36 + elpa/mew-20150813.2354/etc/mew-yank.xpm | 36 + elpa/mew-20150813.2354/mew-addrbook.el | 576 +++ elpa/mew-20150813.2354/mew-attach.el | 878 +++++ elpa/mew-20150813.2354/mew-auth.el | 102 + elpa/mew-20150813.2354/mew-autoloads.el | 81 + elpa/mew-20150813.2354/mew-blvs.el | 90 + elpa/mew-20150813.2354/mew-bq.el | 1199 ++++++ elpa/mew-20150813.2354/mew-cache.el | 265 ++ elpa/mew-20150813.2354/mew-complete.el | 812 ++++ elpa/mew-20150813.2354/mew-config.el | 642 ++++ elpa/mew-20150813.2354/mew-const.el | 373 ++ elpa/mew-20150813.2354/mew-darwin.el | 120 + elpa/mew-20150813.2354/mew-decode.el | 1157 ++++++ elpa/mew-20150813.2354/mew-demo.el | 145 + elpa/mew-20150813.2354/mew-draft.el | 1030 +++++ elpa/mew-20150813.2354/mew-edit.el | 1202 ++++++ elpa/mew-20150813.2354/mew-encode.el | 1385 +++++++ elpa/mew-20150813.2354/mew-env.el | 359 ++ elpa/mew-20150813.2354/mew-exec.el | 692 ++++ elpa/mew-20150813.2354/mew-ext.el | 523 +++ elpa/mew-20150813.2354/mew-fib.el | 123 + elpa/mew-20150813.2354/mew-func.el | 1669 +++++++++ elpa/mew-20150813.2354/mew-gemacs.el | 465 +++ elpa/mew-20150813.2354/mew-header.el | 547 +++ elpa/mew-20150813.2354/mew-highlight.el | 385 ++ elpa/mew-20150813.2354/mew-imap.el | 1878 ++++++++++ elpa/mew-20150813.2354/mew-imap2.el | 659 ++++ elpa/mew-20150813.2354/mew-key.el | 690 ++++ elpa/mew-20150813.2354/mew-lang-jp.el | 219 ++ elpa/mew-20150813.2354/mew-lang-kr.el | 43 + elpa/mew-20150813.2354/mew-lang-latin.el | 88 + elpa/mew-20150813.2354/mew-local.el | 426 +++ elpa/mew-20150813.2354/mew-mark.el | 931 +++++ elpa/mew-20150813.2354/mew-message.el | 341 ++ elpa/mew-20150813.2354/mew-mime.el | 989 +++++ elpa/mew-20150813.2354/mew-minibuf.el | 1058 ++++++ elpa/mew-20150813.2354/mew-mule.el | 170 + elpa/mew-20150813.2354/mew-mule3.el | 422 +++ elpa/mew-20150813.2354/mew-net.el | 911 +++++ elpa/mew-20150813.2354/mew-nntp.el | 744 ++++ elpa/mew-20150813.2354/mew-nntp2.el | 446 +++ elpa/mew-20150813.2354/mew-passwd.el | 354 ++ elpa/mew-20150813.2354/mew-pgp.el | 1267 +++++++ elpa/mew-20150813.2354/mew-pick.el | 853 +++++ elpa/mew-20150813.2354/mew-pkg.el | 4 + elpa/mew-20150813.2354/mew-pop.el | 991 +++++ elpa/mew-20150813.2354/mew-refile.el | 946 +++++ elpa/mew-20150813.2354/mew-scan.el | 908 +++++ elpa/mew-20150813.2354/mew-search.el | 814 ++++ elpa/mew-20150813.2354/mew-smime.el | 501 +++ elpa/mew-20150813.2354/mew-smtp.el | 782 ++++ elpa/mew-20150813.2354/mew-sort.el | 527 +++ elpa/mew-20150813.2354/mew-ssh.el | 258 ++ elpa/mew-20150813.2354/mew-ssl.el | 313 ++ elpa/mew-20150813.2354/mew-summary.el | 415 +++ elpa/mew-20150813.2354/mew-summary2.el | 819 ++++ elpa/mew-20150813.2354/mew-summary3.el | 491 +++ elpa/mew-20150813.2354/mew-summary4.el | 1229 ++++++ elpa/mew-20150813.2354/mew-syntax.el | 1057 ++++++ elpa/mew-20150813.2354/mew-thread.el | 1183 ++++++ elpa/mew-20150813.2354/mew-unix.el | 149 + elpa/mew-20150813.2354/mew-vars.el | 3319 +++++++++++++++++ elpa/mew-20150813.2354/mew-vars2.el | 1012 +++++ elpa/mew-20150813.2354/mew-vars3.el | 225 ++ elpa/mew-20150813.2354/mew-varsx.el | 268 ++ elpa/mew-20150813.2354/mew-virtual.el | 245 ++ elpa/mew-20150813.2354/mew-win32.el | 244 ++ elpa/mew-20150813.2354/mew.el | 775 ++++ elpa/mew-20150813.2354/mew.info | 132 + elpa/mew-20150813.2354/mew.info-1 | 1421 +++++++ elpa/mew-20150813.2354/mew.info-2 | 1430 +++++++ elpa/mew-20150813.2354/mew.info-3 | 1573 ++++++++ elpa/mew-20150813.2354/mew.info-4 | 1576 ++++++++ elpa/mew-20150813.2354/mew.info-5 | 277 ++ elpa/mew-20150813.2354/mew.ja.info | 130 + elpa/mew-20150813.2354/mew.ja.info-1 | 2065 ++++++++++ elpa/mew-20150813.2354/mew.ja.info-2 | 2135 +++++++++++ elpa/mew-20150813.2354/mew.ja.info-3 | 1886 ++++++++++ elpa/mew-readme.txt | 4 + 113 files changed, 59666 insertions(+) create mode 100644 elpa/mew-20150813.2354/dir create mode 100644 elpa/mew-20150813.2354/etc/Mew.img create mode 100644 elpa/mew-20150813.2354/etc/Mew.png create mode 100644 elpa/mew-20150813.2354/etc/Mew.xbm create mode 100644 elpa/mew-20150813.2354/etc/Mew.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Audio.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Blank.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-External.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Folder.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Image.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Octet-Stream.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Postscript.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Rfc822.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Text.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Unknown.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-Video.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-attach.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-cite.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-forward.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-inc.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-lock.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-next.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-pgp-enc.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-pgp-sigenc.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-pgp-sign.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-prev.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-queue.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-refile.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-reply.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-send.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-sep.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-show.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-write.xpm create mode 100644 elpa/mew-20150813.2354/etc/mew-yank.xpm create mode 100644 elpa/mew-20150813.2354/mew-addrbook.el create mode 100644 elpa/mew-20150813.2354/mew-attach.el create mode 100644 elpa/mew-20150813.2354/mew-auth.el create mode 100644 elpa/mew-20150813.2354/mew-autoloads.el create mode 100644 elpa/mew-20150813.2354/mew-blvs.el create mode 100644 elpa/mew-20150813.2354/mew-bq.el create mode 100644 elpa/mew-20150813.2354/mew-cache.el create mode 100644 elpa/mew-20150813.2354/mew-complete.el create mode 100644 elpa/mew-20150813.2354/mew-config.el create mode 100644 elpa/mew-20150813.2354/mew-const.el create mode 100644 elpa/mew-20150813.2354/mew-darwin.el create mode 100644 elpa/mew-20150813.2354/mew-decode.el create mode 100644 elpa/mew-20150813.2354/mew-demo.el create mode 100644 elpa/mew-20150813.2354/mew-draft.el create mode 100644 elpa/mew-20150813.2354/mew-edit.el create mode 100644 elpa/mew-20150813.2354/mew-encode.el create mode 100644 elpa/mew-20150813.2354/mew-env.el create mode 100644 elpa/mew-20150813.2354/mew-exec.el create mode 100644 elpa/mew-20150813.2354/mew-ext.el create mode 100644 elpa/mew-20150813.2354/mew-fib.el create mode 100644 elpa/mew-20150813.2354/mew-func.el create mode 100644 elpa/mew-20150813.2354/mew-gemacs.el create mode 100644 elpa/mew-20150813.2354/mew-header.el create mode 100644 elpa/mew-20150813.2354/mew-highlight.el create mode 100644 elpa/mew-20150813.2354/mew-imap.el create mode 100644 elpa/mew-20150813.2354/mew-imap2.el create mode 100644 elpa/mew-20150813.2354/mew-key.el create mode 100644 elpa/mew-20150813.2354/mew-lang-jp.el create mode 100644 elpa/mew-20150813.2354/mew-lang-kr.el create mode 100644 elpa/mew-20150813.2354/mew-lang-latin.el create mode 100644 elpa/mew-20150813.2354/mew-local.el create mode 100644 elpa/mew-20150813.2354/mew-mark.el create mode 100644 elpa/mew-20150813.2354/mew-message.el create mode 100644 elpa/mew-20150813.2354/mew-mime.el create mode 100644 elpa/mew-20150813.2354/mew-minibuf.el create mode 100644 elpa/mew-20150813.2354/mew-mule.el create mode 100644 elpa/mew-20150813.2354/mew-mule3.el create mode 100644 elpa/mew-20150813.2354/mew-net.el create mode 100644 elpa/mew-20150813.2354/mew-nntp.el create mode 100644 elpa/mew-20150813.2354/mew-nntp2.el create mode 100644 elpa/mew-20150813.2354/mew-passwd.el create mode 100644 elpa/mew-20150813.2354/mew-pgp.el create mode 100644 elpa/mew-20150813.2354/mew-pick.el create mode 100644 elpa/mew-20150813.2354/mew-pkg.el create mode 100644 elpa/mew-20150813.2354/mew-pop.el create mode 100644 elpa/mew-20150813.2354/mew-refile.el create mode 100644 elpa/mew-20150813.2354/mew-scan.el create mode 100644 elpa/mew-20150813.2354/mew-search.el create mode 100644 elpa/mew-20150813.2354/mew-smime.el create mode 100644 elpa/mew-20150813.2354/mew-smtp.el create mode 100644 elpa/mew-20150813.2354/mew-sort.el create mode 100644 elpa/mew-20150813.2354/mew-ssh.el create mode 100644 elpa/mew-20150813.2354/mew-ssl.el create mode 100644 elpa/mew-20150813.2354/mew-summary.el create mode 100644 elpa/mew-20150813.2354/mew-summary2.el create mode 100644 elpa/mew-20150813.2354/mew-summary3.el create mode 100644 elpa/mew-20150813.2354/mew-summary4.el create mode 100644 elpa/mew-20150813.2354/mew-syntax.el create mode 100644 elpa/mew-20150813.2354/mew-thread.el create mode 100644 elpa/mew-20150813.2354/mew-unix.el create mode 100644 elpa/mew-20150813.2354/mew-vars.el create mode 100644 elpa/mew-20150813.2354/mew-vars2.el create mode 100644 elpa/mew-20150813.2354/mew-vars3.el create mode 100644 elpa/mew-20150813.2354/mew-varsx.el create mode 100644 elpa/mew-20150813.2354/mew-virtual.el create mode 100644 elpa/mew-20150813.2354/mew-win32.el create mode 100644 elpa/mew-20150813.2354/mew.el create mode 100644 elpa/mew-20150813.2354/mew.info create mode 100644 elpa/mew-20150813.2354/mew.info-1 create mode 100644 elpa/mew-20150813.2354/mew.info-2 create mode 100644 elpa/mew-20150813.2354/mew.info-3 create mode 100644 elpa/mew-20150813.2354/mew.info-4 create mode 100644 elpa/mew-20150813.2354/mew.info-5 create mode 100644 elpa/mew-20150813.2354/mew.ja.info create mode 100644 elpa/mew-20150813.2354/mew.ja.info-1 create mode 100644 elpa/mew-20150813.2354/mew.ja.info-2 create mode 100644 elpa/mew-20150813.2354/mew.ja.info-3 create mode 100644 elpa/mew-readme.txt diff --git a/bba.org b/bba.org index 70db8e2e..0bd5ced0 100644 --- a/bba.org +++ b/bba.org @@ -1130,6 +1130,89 @@ With this you can do /sudo:ssh-host:file-on-ssh-host #+END_SRC +* [[http://www.mew.org][mew]] email + +#+BEGIN_SRC emacs-lisp + (autoload 'mew "mew" nil t) + (autoload 'mew-send "mew" nil t) + + ;; Optional setup (Red Mail menu): + (setq read-mail-command 'mew) + + ;; Optional setup (e.g. C-xm for sending a message): + (autoload 'new-user-agent-compose "mew" nil t) + + (if (boundp 'mail-user-agent) + (setq mail-user-agent 'mew-user-agent)) + (if (fboundp 'define-mail-user-agent) + (define-mail-user-agent + 'mew-user-agent + 'mew-user-agent-compose + 'mew-draft-send-message + 'mew-draft-kill + 'mew-send-hook)) +#+END_SRC + +When booting, Mew reads the file [[~/.mew.el]]. All Mew configurations +should be written in this file. + +To configure your e-mail address, the followings are necessary. + +#+BEGIN_SRC emacs-lisp :tangle no + ;; (setq mew-name "your name") ;; (user-full-name) + ;; (setq mew-user "user name of e-mail address") ;; (user-login-name) + (setq mew-mail-domain "domain of e-mail address") +#+END_SRC + +To send e-mail messages by SMTP, the following is necessary. + +#+BEGIN_SRC emacs-lisp :tangle no + (setq mew-smtp-server "your SMTP server") ;; if not localhost + ;; (setq mew-smtp-ssl t) + ;; (setq mew-smtp-port "587") + +#+END_SRC + +If you want to use POP to receive e-mail messages, the followings are +necessary. + +#+BEGIN_SRC emacs-lisp :tangle no + ;; (setq mew-pop-user "your POP account") ;; (user-login-name) + (setq mew-pop-server "your POP server") ;; if not localhost +#+END_SRC + +If you want to use a local mailbox to receive e-mail messages, the +followings are necessary. + +#+BEGIN_SRC emacs-lisp :tangle no + ;; To use local mailbox "mbox" or "maildir" instead of POP + (setq mew-mailbox-type 'mew) + (setq new-mbox-command "incm") + (setq mew-mbox-command-arg "-u -d /path/to/mbox") + ;; If /path/to/mbox is a file, it means "mbox". + ;; If /path/to/mbox is a directory, it means "maildir". +#+END_SRC + +If you want to use IMAP to receive e-mail-messages, the followings are +necessary. + +#+BEGIN_SRC emacs-lisp :tangle no + (setq mew-proto "%") + ;; (setq mew-imap-user "your IMAP account) ;; (user-login-name) + (setq mew-imap-server "your IMAP server") ;; if not localhost + ;; (setq mew-imap-ssl t) + ;; (setq mew-imap-port "993) + ;; (setq mew-prog-ssl-arg "fips=no\nverify=0\n") +#+END_SRC + +To read and/or write articles of NetNews, the followings are +necessary. + +#+BEGIN_SRC emacs-lisp :tangle no + ;; (setq mew-nntp-user "your NNTP account") + (setq mew-nntp-server "your NNTP server") +#+END_SRC + * elfeed #+BEGIN_SRC emacs-lisp (if (>= emacs-major-version 24) diff --git a/elpa/mew-20150813.2354/dir b/elpa/mew-20150813.2354/dir new file mode 100644 index 00000000..0f2efff7 --- /dev/null +++ b/elpa/mew-20150813.2354/dir @@ -0,0 +1,19 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "?" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Message User Agent +* Mew: (mew.info). Messaging in the Emacs World. +* Mew-J: (mew.ja.info). Messaging in the Emacs World. diff --git a/elpa/mew-20150813.2354/etc/Mew.img b/elpa/mew-20150813.2354/etc/Mew.img new file mode 100644 index 00000000..9124463f --- /dev/null +++ b/elpa/mew-20150813.2354/etc/Mew.img @@ -0,0 +1,13 @@ +0$,0&a+]/"0z6[;v>8D:F310'&+{.<1!48688z;u>5B;FS10&O,{.L4@68;yA#D2F5I 10'!-,1!4:9&;Y>t@uDzFQ10$>&E+}1a699^>T@|DrI"10#n'_+{.>293z8~6A3CZF3IP10&_-#1[3h::>|@uFy10'%+m/Z3|:6;yA$D2F9J110'o.C293x6;:6;e>5A3CTFqHx10'/.\3`7W8x<5><@uCrJB10$~&O,;.<1)4x6;9&<5>6CvGQ10'/+\/"3Y7g;^>tCdGQ10'&.C1Y6I>FASF5I010&_,?1)6{8w>|Fy10#n&?)\.>293`6X>FB3FCJ010)@/[193`68<5>6A3CSF9IP10'_),1=8z<5>5A3CVI 10)@/Z1+7W8w;y>5@{CtGYI210*N.<1a3Z6_9X;e>vA'D2GfIP10$~&a),- .J2=3i7{9&FBSC\FqI:10'm+_.Z4:6G:6;wBWDrG!J010&?*L.<1Y6I<5>D@uGQHy10&M*<+_1:7_;W>DASF510'a+{.>3x6;<5>6A#DrHr10)>,{.B0z7[<5>6A#DrHt10)@1;9Z>DDtF910'm) 193\7W;f?T@wCr10'_+{.B296;96>8E"F310&_+c/Z0{3h7W;]>t@uCbHt10&^+c.z0z3h::>ED2F9Hr10&M) .z0}689^A7F2IX10'!+c.z3Y6[>xCbHr10&_,{.<193`8x<5A$DrF5I010'!.^4x6H<9Cv10&E)\+\/^1)9'?\@tCrF5J010'f+{.>498z;u@{CTFq10&a.~3h69=%>6CrHt10&),/\3`6y>XDsFA10'.) .z1!6Y8A3F9IR10#~&A,<.B5)8zFD6F2I 10"O#b&}(}+k1=69:F;V>xCdI010"@&a+\/"3Y6;fAWFSJ010!($>).1b6G8x>|CSFy10$B&>),.|1!6w8z;e?T@uCZFqHr10!/&E)].>1Y3h69:6;e>8ASFCIP10"A#n)>.B296[FD2FC10!/'!+l/Z0}3x::;eB3C[J@10#o']) +{1"4x8T@wFQHt10'&/#6[;W>DB3CSFUJ010!1$>) +{1!4:9&;W>t@{FS10!1$~)@/[193Z6?9V>8ASFC10! %&)>.B0{3x::;eB5CbHq10#p)\+m1Y3\6G:6;W>DD610#o&}) .Z0}4y6W;^>TB7FCIT10! #b&],1;3`699>;W>]B7C{GcIX10!!#n&(}-/.z1.586K9W='>=ASC\G!Hu10!'%>&G)=,C.L1=4y7+96;j>tA=E"FvI"10!4%>&R)\,%/Z1n3`6|:G;y>FB7CcFyI510$S)F,{.d1]3j6{9>='>}BECvGcI510!G$>&a*L,\ASE&FqI:10!?$~&E(}.^4x6G8w>XDrFAHt10"?#_&]) .[4|6G8w>DB5FBJ010!?&>),+_.Z0}4:6G9!<7>D@wDDF9I510!?#`)$+\.Z2A3Z7g9~=?>bB5CcGQI:10!g)$.Z0}486H:6;y?UB[DFFFIS10!?'a+k/Z0{3h8z<5>=A3DtG:JZ10"?#f)<+_/Z3|:6;yB6AdCTH&JU10!g&>)d.<1a7h8z^ASE@G+I{10"?#n&?,C.;4@9(=BUD>H&I{10"?#~&?+{.>5)9Z;V>\ASD1a3Z6w9&;Y>tBEC[HEIe10!1&}) /j0}7h=ASCTGyIP10$"-$196?9XA7FsHx10!0$~&A)<.>5)8z<5A%D2I510$F(}-#1:3`8x=%@xE"FAB#D;GsJ010#f&~+m.z1#5*7,:^EAWCsF9I210!_#b&]+m.z2I5:6w8~<5>5A[FuJ@10$@&M*<+c2K:H>D@uCrF9J010"?)\/Z7W>tGQ1(B +0$,0$ &E,;.L7 ;wA#D6Hr10!'$?*E+{.<2A3Z6W8x;i>u@}E"F;I010!/#`&})%,M/b1^5(6\:><:>\AXDzFVJB10"A#f&})-+.{1-496G98<=>EA]CrF{I 10!/$>&A),,<.>1a3y6K:W;]?&@wDCGYI510#p']+1b6{9&<:?\A5D;FAIR10"?#b&]*<+o1;7`96;Y?$@}DCF:JT10!#'m(~/"3j9:8A[CSGcHx10#b'm(}.^0z3h6;97<}>U@}DCF;JT10"G&_+l.z1!3z6?98;]?&@|DFFsJI10"?#b&](}+k.>293i6{9&?fA\E$G{I110!C#_'])..^2B3x7a9h;~?&A4B8!9`8AeCwFEIR10"_#s'a)m,%.~1B4J6K9g=)>}BWCdGvJD10"G$#'m)A,E/j1>5*6[9_='>XBED}AeDzGsHt10"G$"'~)0-?.b1^5@7l9:=g>YA'DGGSI810!_&E)\+].J4<8x=%ASCdGQHq10!('b),+].Z1$4x6I8w<>5AXCTFZHu10!q$(''*f,P0$1n5B8"9@=B?)AhDGG&Ie10!_%C&M+!,#0J1C5j7+:_HA\E6F2JZ10"i$]'2)6,A.C2[3`7{9(<=>VA'E4FBHz10"i$h(3+7.(002f4n8$9l=0>:BVE$FQId10"i%I(W*+-P0Q2t5n82;L"@+C@ELHGJm10"i%u'J+G,X012&5s8t9l=P?AB*EoH\Jn10"i%F'G+7,P/I2n4e8R:m=B?OBaDmG~KK10!@%3(()r,h052'5M8V:0=D?IC-D_GyK!10!'$h'S+6-Q/G335N7?;+=5?)B5C{FEIq10!u%J(.+0-<0<1-5(6\9`;u>~A7D:FCIP10"S'2,O.;2c5(6<9j`B5D;FUI"10"G$#&O)f+|/$1>4@6\9^='>~BDDtA%D2F5I`10!#%.) ,;.<1)7`<9A4CVGQI 10$>*<1Y<5Fq1(B +0$,0!g&M(~,;.>1)6y8~>U@{FuHq10!)%.&B)D+`/"1+4x6L9V;jA]CSFyHq10!c%/&a).,C/l1=5!6[9_;y?iA5D6FZIb10"I$"'n)f-,.~2J3|7i9:=&>~AdD|G%I910"?$(&A)m+/c1;5!6Y:J<>>YA\E&G&JT10"O$#'e)>,C.\1a3]7'9`;z>|A8EvA,D.\1!5:7_9h<~>XA\CvFzJB10"a%3&_)p,%/#2^3b7{8;z?VA4D|FQIZ10!A$R''*P-=//1A5=8!9:}A7DDFZJR10"I$N&G*n,D0$1+4\7l9@='?(B]D;G%Ie10!k%/'2*N,D.d2I5=7+9_=?>yBGC{GfIY10"i$#'/)1,D0$2K4"7|9`<&>yAmCvFCIZ10"Q$R'&)l,%0"1k5@6[9_]A]E6FzJB10!H%(&g*E+/o1>5,7!9?<9>]BHCtGeI910!q#s(R)@-E//1=5A7k9?=9?&@|DVGbI:10"i$ '1*E-P.2c4L7i9@=>?&A=E6FCI410"c%('2)n+o/+1m596K:_<:?~B7C{GfJP10"q%C&e)^-D.D3.4"7i9l~BWE>TBIA>E'F^I:10"i$S(')q-F/01n4R8";+\A(E2G~Ia10!C$G'r)q, /o1c4M6\:KYBHD$>iC2D'HKI?10"y%u(3*7-I/U2c4o81;C=P?BBnD_HHJ%10#6${(T*{.&0W2x6"76:`Jk10#6&;((+Z,P0h2p6%8.:d>0@!C2EGH'I}10!u&<'2+K-U0d2s4m7;O?)AeE'G+JU10!t'/*<+/Z2c4A6[:H;u>~BgDGGsIe10!d#f&)0,}.c293m7y9*<?tB]CvFrI410!h$('q)>-5.d1^3l7|9k=?>HB\CVFSJD10%@']*D,=/Z194|98?eCVGa10!#$>)@.<2I6y9&;V>tFq1(B +0$,0!?#b&N)\.?1Y3`69:F>=ASCVFA10!C#`&M)^+\.D1Y3Z6W:8;e>6ASCVGb10"H$P'e)A,E.^2K4A7i8z=>>8BUCfFzI"10!i%0(&).-?//2B4L6y:J;?dA8D6FCI510!q%H'2*Q,C//5B6\:F<?&A^AhD:FWIX10"O#h'!)E-E/#1>4A7+:XYA\E$FVIX10"d#f'2*@,$.|1B4<7i9:<>>XAUCzFCJT10!3%G&Q*^+p.\1b4}7)::;~>yBDC\GsJ910"S$'''*N,$.|1m4A7):ZXAeD;GyI"10"d#p(&)a,M/n1b4J6`9Z;~?hA5CfF{J410!H$C&g)`,M/_1B4:6`:;;v?XAdD|GqJ910!h$"''*M-?/#1=4A7)9:<>?hA5DFGcI910!c%''/)=,E.K2]3a7)::;~>xBED:GcI210"c$G'/)d, /"1^3l6y:J;z>|BFCvGbIZ10"Q$#'%*N+d/~1+4@6\:GXAeDwFaIU10!i$ 'e)=+o.{2M3z7 9(<9?fA\CvGcI410"i$S(')1-E._2N3z7$9'=?>vA=E'FyJB10"a$R(")d-E0#1]5B6x9j=*>|BXCfGsJD10"G$O&A)l- .J2]486L:V;^?vA>ZBDD6FCIX10"i%C'6)s-E/D1o4M6a:\ ?IC-DlHNJ&10!d%X(D*Q.&/w2$5N8R:lJf10!i%S'2*&,U/O2d5m7A;+<_@QBhD\H&J]10"y$S'8+2-E/D2n4M7|9j<>?xA*i,P0%2N4e71:k.J1Y3Y7_;wA#Dv10&}/Z9VB3J01(B +0$,0!c#_&M) ,<1=6H9V;]>6A3FU10!c#_&]) +\.b0z4<8~<7A7DrFAHq10!g$ &e)^+k.\1-3z7_96;_>TB;CtF9I210"Q$"'g)E-0/$2K3m8!9WY@{DCG[I410"d$F&a)n+/"1>4@6\9^;w>}A7D;G%J210!D%2'&*N,D/l1B4<6a:G;y>}BGCtGfIb10!0%B&O)e+/#1=5*7 9(=9>FBWD;FUIY10!I%.'')-,C._2K3|7 8{==?fA]C{GVI910!s%B&O)p,@.b2M4J7 9@=&?~A]DGFYIe10!H%3'&*a+l/1:5-699j;W?}AeD:GvI:10!q$&'")D,P.B1n3|7l9j=*>XAeE&F[I%10!i$"&O)f+m.\1b3b7+9?;i?~AgD|G%I810!h%0(!*E,?0#0~5L7a9H=?>yAEE&F;JY10!C$G'q)=-0.\1b5*6:[;u>yAcDwGyHr10"i$"'o)E,E.J1c5(7!98=&>>AgCTGzI"10"Q$"'o)E,?/k1c5(7!:G;_?$B=DBF6I810!t%B&f)^-D.>1k5<6I9_;w?hAUE&FSHt10!A$H&^)f+k/|1!5=6G9[;u>~BDD6FRJD10"S$G&b)^-,._2K3b6y9?<>XA&E6FFIY10"i$['G)r,u//2f4S8,:!=B?/B EHG,J&10"i$Y(**g-Q/52p4e82:#=T?>BhEhG;K-10#3$S(g)m-o/D2c4M8!9k<_?yB]EgG{Je10"O$#'&).,P/g2.4}819[=K>}AiF+GJ*10!$%F''*d,P.d1n4M8M:c=>bC(E2@)C?EOG*?~B(DMG:K:10#<$u(:*G-Y0T20557N9t('*D,M/z1p5B7+9k=9?)A;ETB;CsGaI210!g&O*<.~3h6;9V?XA3CTF9IP10&}/Z6w?TIP1(B +0$,0!0$>&F,?193a9&;Y>T@wCrF5J010!?#g)<+d/Z0}3h6y;e>u@{D2F5J@10!'#~&G)]+_.J0{3x6@9V;Y>D@uE"F3Hx10!(%@&F)@,yA3E'F3Id10!L$S'7)2,P/$1C4=6H9`=&>VA[CdFuI910!s$G'*e,C/2K3|7,9^;z>|BECvGZI210"Q$"'&)@-$.^2b4:6`:`;g?xA%E7FYIU10!s%0&a*N+/l1=4A6Y9_='>]B7DDFUIY10"H$P'q)e--/#2K3|7 98<>>VB5,6X9`;y>|AeDvFZJ410"S$ (%)!,M/#1=3j6x9 =5>6BGD2F;I110"Q%B'm)q+}/.2B4H6\9^='>XB5A=DrF[10"h#t'.)I,M/o1m5=6a9Z=?>6B]CcGuHy10!s#c'5)F-+/$2M4 7i:Z=&>xBECvGZI010!3$?&Q*N+_/,0}5)6;97;]>vA#D6F2JD10"g#_(%*>,K/^194A9hDB8CdFzI%10!c#n'"),+_/{1!3y6;:F;z?iAhDGG;Ie10"A#f'"),,@1k7!9&+o.Z2N4@6I9Z='>XA]CfGSI$10!A%'&a*M,?/c1=5*6[:?EHHKJ&10"l%I'2*f,U//1o5B8!9h=B@NAhEGHKK%10"l$T'R*i-P//335C8!:`MBiD?GhI*10#I%]'I*s,V001n5r7E:h<_@HC;EDG5K:10"i$)(')q-@0U2!5R8T9K=Q?BpDHH.Ig10#<$i(2+2,h0/2f5C7,: =B?)AeC}G|Ie10"'%Q'G+F-1/?2S4e7m9k=C?1BaDLG~Im10#Y$+(w*f.8/e2n5B729kXBCE4GYI110%')@.;1a6Y;]>TD3FA10)\6w?TJ01(B +0$,0!?#`&M*<+e.Z0z3\6W;yA$D2F5I 10!!$>&N) ,;1+6{=%>6CvF2I 10!`#b&M-%1:3\7W9(>}CtHt10! $('])F+\/.0{4@6I9^;W>\@xDBF6J@10!!$R'_)D+`0"0{4L68:`?)@uDFF:Ib10!h$"'f)@+m/#2K4A6I9:='>XA]E;FCIZ10!?%3&]*Q,=.c1]3h6{:?,C.[1-586A9g;]?&@|DDGyIZ10!c#o'!*E+{.1)596?9g;Y?|A5E6GbIY10!p'1,E.;1i3Z7,9 &R-0.z1"3Z6;z?TA#DtJT10"a#b'/)$,=.N1Z3\7x9 <5>FB;CtGYI110"S%@&M*a,;/o4M9@^B3CgGqHu10!?$'-(~-;.C1Y3|7W9&<9>TB3CfFqI!10!d$&'')E,M.D2"3m8!9o;@!AHE'F[Hu10"3%H(n)J-l041n4"7l9?=9?)AhE*`+\/"5*9`?~@tC|GZI510!A$H&O)A+m0$1+5<6I:`<7?hA=DCFUIZ10"u%C(3*)-R0'2n5B8$9i=B?BhDHG|Jf10"|%u(x*i,z0d285m85:+=t?ACNEAGFK?10"l$y(**1-F0g1s5M8M:c3@IBqF'G|KE10!t%3('+Q-I/T366.82;E=J@SC@DMG%Ie10")$S(7)f.%/o2b5B8L: =r?>C-CvGzIT10!y%I'1*a,E.d1b3z7 :@4z7):7;y@DAgD|FVI[10"_%h'}+&-?/c1]5A7a9&5BGCTIX10"{$U'w*r-G.d1u4K6c:FTB;CrGR10!i$Q&g*`,M/d1)4:6?8x=CTFA10"m$X(3)z.0/42v4m8$9p^B]C\G{I$10!I%1'g)o, /,1>4:6a:W;]?vA3DtFRJ:10#3%G(A*n-d/{2_5!7|9&OAwE-FVI]10!t$I'1+I,P/D2m4M6Y:J<9@/A]CwF:Ib10"j$R(P)f,%0$2K4"7!:I3?~B*D;G{IY10"($ '2)v.(01265o8r;,=R@JAnDTD;IT10!c&M*@.Z1"488z=%AWFA10'].z:6B3J01(B +0$,0!!$>&E,?.J0{486H8z?eC[FqHr10!a'e,?.J0{486?<>A5CZI210!_#p)d.{1)3Y7_97>FD6FAIP10!$$N&B*L+_.c0{4!9@;V?(@uE&FRJ:10!($S&_*P,E.^1c3i7!:K;w?hA]E;FUIe10!p$#'&*f,D0$2M4!8!9`TB=G#Hx10"t%J&g)q-C.|1N4B8!:k\AWFUJ110"?%0']*]+c/|1Y5*6W:@;v?hA8E&FVIY10"S#_'-)!,K.?2Y3m7_9h;]?yA3D?G#I410!o#h&})1,;.d0}4I6?:[;e>yA#D\B8CzGVIb10"Q$(''*Q,P0#1?4A7+:@BED6FBIT10"P#~'e)<,C/k1]4J7':`=>?+B\EgG>JZ10!q$"(&)q,%.O1m3b6B9W;_?tAUDFG"JZ10!\$I&z)f,U/.2N5<7):#=j?1AiF9IQ10!1$G&O*a+n/105B759k+\.B7W8~>5A3Hr10! &E.<4868;e@uFQHr10!h$R&]*P,;.b1Y3j6W:6;y>DB5CZGVI"10!##x&M)I-0/61C4%8-9C=k>oB}ELFuK(10"Y$U&j)f,&/$2N4"7i;+=@?QC!DCFCIP10"H$#'o*^,P/e1m5G8':$==?%BSC[F3I:10"`$B'~+%0?5!6I9W;k>IAiEGG{J]10!I$"'')1-E.O1n4R7{9o=g?|BWDDGqJu10"D%G'a)n-#.[1!5=6H9`;g?)BIDLG~Ij10!G$H'1*D,M/.1k4 6y:^=9?$B5E:JQ10$F*N.z1+6w88A4I410"C'!),/Z1)3Y6;96>=A3JB10']/Z9VDr1(B +0$,0!?#h)n/o1:5"6\9^;z>~A^BXDTB]D6GsJ910!/$H'a)E,E.J1_4 6<9f<?$B=DDFEIX10!I%C&Q)q--.d2N5A6[9_=)>VB}A5D;F[J410!?%3&_*E+}/#1=5*6W9[='>5@6{9?<7?]A5D;FCIT10"S$S'o)@--/~1B5:6K9h;]?&ASC|FqJ:10"H$"'^)F,|.d1)4=7g9 =6>8BUCZGsHt10!/$H&^)f+{/$2:3l7Y9?;W>\B8CzGVI810"H$ &Q)e--/#1+5<6I9_;y?]A7D;FCI410!t%H'2)a,-/$2c3m8A9k;?yAhD"@+C@DPHZIg10"z$k(4*)-P0O1t4N8`:a=I?>B`EbF_KM10"}$i(7*+,P/51m5:7+9h==?yA;DtG"Id10"Q$F(O*`,d/,2b5B6I:Z<>B[CTFQJ910!t%S'q)G,E.?1j4|7A9h;~?XA4DvFRHx10!c$&'o*)-m/.1;5,6x:J;y>tA$FU10!/$>&A)].Z4<:6;uCVI010!$#~&>.J::Ct10!g$R&}+l293\>VF2I 10!_) .Z6?9VCVI010&~)$3x69,C.L2c4B6<9';Y>D@uFqHt10"t$h('*f,.b2>4I8#9f=:>D@uGc10!0$@'o)`-0.L1b3z6?:[;]>UBCCWFqHx10"4%H(&*f,L/~1:5,6w&A),.[0}7g;Y?dDrFU10'o.c7_;g?TCvJ110#f&~+c.Z0{7_;u>6B3CZF3I010!_,;7W>tJ01(B +0$,0!D$S'r)E-p._2c4M8!9k=??)A]EGF{JZ10!t$S'2)F,M//2c4M8!9k=??)B]DGG{JZ10!t$S'2*f,P//2c4M8!9k=??)B]DGG~Je10!t$S'2*f,P//2c4N8!9k=??)BhE=G&Ie10!y$S'2+1,U//2c5B8L9k=??*A}DGG&Ie10"u%G'3)q-P0$2f5B7,:k=??B`DGG;Ie10"i$H(/)q,D0/1c5B7A:`=J>~A}DGG~Ij10"i$H(&)>,D.d2c5<7l:`XB]D;G%J:10!/$C'o)p+|/n1>4@6a9j;Z?|AYC{GyJU10!q#g') ,L/d1:5B6H:`<9>EB}C{FuI910!q'2,E.Z1#3x7!=??%A[CwFzId10"O$ &Q)]0$4M:`;f>vA;D7FYJB10!A%&&)$+|/^1a3z6?:V;j>TBHD:G#J510!s%0'%)A+d.Z2=3h7\9>;W?(@uDFGSI910!q%''1)D,?/k1k5 6[9h;}?vAgDsF[IX10!_#s'])e+m.z1C4x7+:8XBXA\CVG"Hz10!i#n(").,D.^1c3h7|8,?2CJE@HlI}10#\%I(W*'-x/P3X5B8v:`>4?~CNE@HlI}10!q$S(R*;-E0w1o6%8,;+TAXCbGUI!10"G#~)e.^1Z3\7'::;~>tA'D4F9I010! $~&E,;1!7X8~;u?T@{E2F;JP10#_&M,{0}6G;V?TA#F5I010#b.{3`;W>TGY10'e+{.<1a3m728|;W>=AUCcF310!'&>*<+k.<294J7!:k<@)B]DGH!IZ10!g(~,;.O0}4=7o:Z(~+{0}4x6G;W>t@{I410! %.&?,D0}3h7Y;zA$DvF2I010!A#g)q/50}5A6[9(<=>>A}CgG'Hy10"O#_'%) ,K.z2M3x8!:V;i?tB=DCGuIb10!?#b&>*L.{1)4|96|CTFqHx10&}/Z6w?TGQ1(B +0$,0!t%H'2*f,e/o2c4M8!:`>xB]D6FZIU10!t%H'3*q,P0$1n4M6a:`/.2c5<7,9h=??&B]E7G#JE10!A$H'2*`,%/1c5*7@:<=F?!B]DFF{Ie10!t%F''*f-@//1k5B7 9k=7>HBXE;GeIb10!G%@'&*`,M._2c4A6a9h<>?~A7D]B=CvG#J910!0$B&g)e+0#1>5,7!9j='>~AdD|G"IZ10!c%.'')E-/.[1m5"7):[HBTD|FUIb10!$%F&O)`--.^2J4B7h98<>?hA5E&F{JA10!I%I'3*Q,P/m1C4=6a9;$x(\+Y,j043D5N8T:m>2?+B0EIH^IO10"|&3(,)y,q0U2x628$:l=p?BCHDMHGJj10"5%{'T+6.1/73C5R8F:p=B@)B^DLH^JE10"s&('2*V-`.t2]5q7+:k=i?&AgE4G"IT10"c$~'1)^+k.~2I486K9V=%>6BWFzI010"?#b'})%,{.L5:6?:6;w?TA#CVFqHr10!#%/)@/#3z7W8>T@{DsI410!($ &E*^.B1[6W8x;e>t@wFyHq10#f'_),,|.^5*9_>XB3FC10!!$F)>.L4@6996;]>tA%DrI410$''](},C.;1a6;96D@tGc10!?'%)<+e.z3|9V;]A5Ht10$~&M) ,;2A:?>T@wGQHy10"?&N*<.<2I689&>8ASI!10&E,;.<3`98ASC[10"O&>*<+k.<1Y6?9W><@tCrF510&M(~,;.B0{486?;wA%CZFs10!($~&b).+]/"1-4z6`8x6B[D7GaI210!t#p''*`,e/t2^4"7l9h<=?fBWC[FuJB10!o%H'})f-,.~1:4|7(9Z='>=BSC]GaIU10"?#o'])>+c.z1*6<=>UBGCwG{I%10$ )$,}193\:G>XASDQGzJ'10$>,;4x<5D2GqIp1(B +0$,0!t$S(')v-E//2c5B10!t$S('*f-E//3.5B10!h$((!*e-E//1n5B10!H%B'/)`,M/$1B5=10!q%3''*e,E/l1m3}10"i$S(')q-00$2c4M10"i$S(')r,P0$2c4M10"i$T('*q,P0$3/4M10"i%s(**f,P0'2n5B10"i$S('*f,P0/1c5M10"c$S'o*f,P/,2c4M10"c$((')q,O0#2c4J10"i%0(&)A-D._2M4J10!p%C&g)p, /#2c5*10!h#p(&*N,E.c2]4B10!C$G'/)A-//,2b4=10"P$H'/)A-/0$1k3|10!H$P'q)F--0$2N5B10!3%@(&*Q-?//1C5A10"i%0'&)F-E//2]4M10!t%0'2*Q-E.c3#4M10",%U':)K-V/(2p4E10#M%X(T*&-Z0o2h4r10#I%H'1+Q-0/T2c6#10"h%"'F*@,c/k2c4\10!)#&E*\+o.z1+4810!g&]*>+k/Z1!3x10$~&O,=.B2910$F,C.<293h10$"*<+l1Y3Y10'e.\10$"']+_.Z3`10"O&>)<,3`10#~&A+|2A10'!.>1910!?#`),,}1!4810! $F(},C.<1;5!10!I'')-,?/l1b3}10"G$#&E)m+i0K1C4M10!H$@'2)1-H/E3.4M10!I$O'1)q-E/,2c4b10#4$((Z)F-H0$2h4L10!8%u'G*g-P0(2#5m10!_%>(])\-;0Z2Y4X1(B diff --git a/elpa/mew-20150813.2354/etc/Mew.png b/elpa/mew-20150813.2354/etc/Mew.png new file mode 100644 index 0000000000000000000000000000000000000000..7caa6cb68df33d703a1926e7eab316b62dd9dfd6 GIT binary patch literal 48019 zcmV)HK)t_-P) zG%zSQSTHz1Fg!3YNKiN|C^$G^I6Oc&KsY#1P(VOPKtwn|NH9QLU`R+%NLV;XXkbtz zI8Zb&P&_zLNI+0bI8abnP;6*WbdXSlSWu9NSUf0LL_k(Dgcz~dYh(J(?OlXK) zP>5hahU(6oTixMNc=zv)0h+ycjSm?NL=)8F7ys+rRnCQ@O=+KDh*tqE6!06r3(nDFSZ@a&lI^sw;w zpz!?Y_^fdFu%P(Ni1^TO_|&NQ@Yu2h7n%S700Cl4M?~pS(?^s503ZNKL_t(|+HAf5 zQyXWVF6xx=mWjpKTN{!2VX%a`h?Y~LJXw(h~Lf_UcEF@wbQT`<0*0LF-Bc@Kx-WvuO|8&HEai7oI zEkWk2!1{*1KK;DU=XpNw+wF5@I<2$w@z1o{243Dc;k{09@$v-M zD!5UpoZzRz{^=Jd`?%cK?>V8{c%c4hTw~8WX3sn}o_~Dy9rr8yC*}Qpx>D9(XMd;u z0dabXpJUvr()X{FtMriS{>e^tzgns8RH}4YKB2F9RHff@1{U?RIvn%@8|-37M;ll0 zY8&i(vllNLAk^{GFOPsC!F_y$t7RQy`YE#yR@R@aLr_0`MaVL2_xBl68zp@B(qRc3 ziJ&+kU+7mnqe65`9oDhe1_6Z2Em_c~XAly-X=rYPx4C-!F^pR}bK8083 ztbR{rqjsZQV>Di)LcE|eVsH6qo%l>-sedu!WZc+4F;HP+5-(9Y$nWk|ON?G@L|1gO zo*41~c$r2J8SC4IUS^*ddqU{4UxxWt#$!%MDGY5P(i$&X2AC&R{X5|C7&|-rbat|j zF}}|PLjPuGKRFWx{S%WM?2{~jgp6e*8&w_Kqa#MM^`n|f()qC=wz|qz%B4D>I!pKK z!y9KC1aL*yX@kW2Sw-Jk?CJE1wJ$~hy=3F`xQ5Ib?jCGw+GbJ9X@x`fl}>bg^)rL6 zy8gZ-bYJSM#2q#HJt2evQsv|iCpxw#3~OV1GGVA3>l(^lkhG@C$a})rzC(!a6Sl&HfMJ1*CXmVs^UmJaNO zp~|{2lnsba(XZ4h5<5F8RjDYI83XIsu)(fZ6&)6xBL`YeDSo5n^Ly3favk^+gEuD? z9T9yyy`*jQ@>o~V%9#yi=mIIk$$m|GzS1RvZKvZC((7Y31YVx4ik0d~Z3JPM@0{$= zZ%r9q5@q#|QmyLJ3;gK`;CYpvQQZNwJH*>{z^h}qj>~nN46XdLPB|TDAX|3{hQ4mp zl%qCC&IkpQ6JsPD>;KB9Kr>jYdYRI_MjaVEs*nX?fom2&g}rL^_{^8C>4*U*^9^4e z*Q=90YF`pj2}K6yJ~IIOU$KgL@)fI`HI+BSS1*zz6XlcgNljh%nFKRa`6I#2-k1t3Y3{UA0KZVuOF9db*WrK^sFb+#Sagu?rO5Om*2~3c@5we*6YC5H52H(WCI${`ik-H z*w|3)8yl8`gy5@sg(Qgou+M-!`L+rX5s#TV&~QJgo~c_TxfNY;%gj8Gp4NrsSRa4n z7s@)ipvu0@A8Jqm3m8_a{3pk?(QTkvW{SY{ zQ?Gw@{B-i}*CA$wYNvAM>AHYdj2frkr3*uqx!sc;9b?1DP)ew>N07GZc>)it?(FNP z0p9E!Aw>i&eG4&Ev(hQJr*R9Ut;z10(~b@)3C0equsYbpVH!j_U38()zlz}(>N?A0 z0vq>ePs4&Vj@0)l-o4;Z8&SxTdEpLFhF}-&`lPOi(kmCv{oS{ezCq z{u%drQaMGpCJq(ysTCuW(4))bU-$RVJd2G(_CVcsk>w>+>8H96Y=L6w2v&XFu(|7o z5HMwA_v!XYPZk^Xgk0yXp~M?ZY%63xpiAH}c^7@_*FI3)ejihUF(^XB#h5vw5Thk> z|8p<11vSu$uwaQ?u84A0D%UutzYdekuMA&npm|C;R`l@(FHcVG=t=F(_s`@m+SdEV zpUZ}Qc=;b>8&HR~&dL7H$*HoOkm50GQ9Wj4!EGvG`{cn;$aYZ6)`_qseWaHdeb;sH z@P|?j#`QCJuImJbn^@mCI`wF$KDh4E7>mpGihG*6PHN(7d}E^R5sU+|_M3brpV73f zjFJGn#e}LYR}ZVTC+!cWCN|bjaV{I~ z%&2B%qs5~qhf{si)6LGA53heV0t5#8_^6cEww^!#eI~P2+}e7sX}Kc6&B>Xq!ck2v zb^7W6@00EVU}_fV!dvgX9P9R|COh;7bv-(%rN5f~)_8mdedYzLr$MQ&Tv7O*gzY9QLPww|4XlHy|z{U^3g_eD1VEv`iH4Q zRH<7DU4M_ud->v4KL5N}%oG7{rnvPS*Z!Ex2T%s_gwR0tK zkZ|1~IoR1KZRk}^hnE$ujkA{PxK`@QEx?AzGr;!S9&|gXhNJa+Tfq= z#Otgz#?^j#|7=7#W~~tR&bk3Ssn#^5)+f_hUDeCp$uVoxRLfKWVZ$ot$my1Lb|9|M zOTu!)$g&%Rajlhm)-4#2)n%FV}`FAc3d(esGTzq8<$YYKbD zjserd70=CR_VPk^p?f%GFW{jMbj!x3)l9 z(pktsCXw0t_pQtyGl^U#&)SpUYO>Z&U!7?Kd@C0pAG5#dF_4wZKNDC6VagT5dK(y* z4FxXm)D)Jvn5townat?%Z1YnSM#X%qNf^D3#9mTk6{GR8EUjrF1Hy z#~XF>8YOR|v~D!bm`U3xe_NTE!8+B}owHxxAa$u!Ex>aTYx5fFS0Yo?AO=NJ-mT}E zTw-hQsC-;c8Q(&XbmuElhy9cPMQ_fuD2`dxXH~O&wmQ|c_l!L=29y4fm#2vYI9GL1 z*r`_bbx8NgZZbEo4`lo>*5VhMumj$fHyCAgAUA5^s$yh>jq>R|wGpsUzueIMZiy85 z*oenWAB;(zdJm;s>u~JU@MWq;AEa76$TRZ=pFpftAPZ321fVTG--6)g_saF*`K>5> zQY%LK`2IuX5Bo;Hf!yseyEH194zB(Y&p=z=H?Hs3W-V%)h*hXch4t8s#~^4kboZ%M z%Pe^!WwW zVJAKx>(o82PfgUsKp%tE(!uWTH{=j@^P5U;Q&WnF4fsWFC?<+I@(KC9BR#p*=ehJo zErwf-z56=c1n*yn1AAxvv$E%vjror{xW=Z^gI#b{qnN9ynnJKXe@>ZgPR(uYf!)WIqgwBbv56YWh3#^EbDt?U-&Tim zx#mA>LZxr@Z$Gb={3xjJ>!N6or}ls&>UdRkd{6evthdOrZJG6EcE0%H;ERKjE(t{6 z>R)1OAY7l-G3w3nx2kOU><2pI*A1HJP2Zy$nf1>^*j5=~j__jynVnK$H?QP!sV1&t9#Wdumyul1U=|!!pOyd<9rCdH_ zD)w;hY z%{{lS7qUaTlMP{=Z}dlf1f41Pm9yWVJ~vr0+7Ej7p+2={JiBWA1@A$xddy~}s${fF zrGqL+tH!AfPQ?r;0$e4h0&YcJRYBUPDo&YvRiAb`HuMHBg3VPZ6tdcK;h=CpU!bHH z-5q_rQWj#L&Tv7MQlVTZRE}xPGEpp5X(;HX-(ZaKMQPHYf@e`5wrq_5`Xs=4cHo$ zh`kuy0NU%&lVox+y9bbW7`%o6>`;rj#4bq@@rUio2C&WIL4{Ivy;@yguNKJO9P3@I zGZRxggt3_>+zEb`RX*exY>|<<{4ZQU#QlD@jFGJXr$Q?Y#@Q2vKA3$1x zZZSuKi+_r$$Z6uNf`19^fXREUhp0E`N>wcsxYOI)dQ^MASrT&JeHmmaO+M*XS zHf6^A5a|LzyZ2nnBrxK)zR7P9#sD^x)0pmVs2q8b3VPON)k$w{ z6JJs7cS_Y4*f={ox+Flg%k_y!DjO_>RUv4}+3s82fsl5%m)*@~3(y}*x%8%0a>3`0 zYmnAv$cz?@u5VRiy#jrTKiAf9)aq?*d)9m3r&xX)UY+J_j32WEd5 zsvaO~(po-Ux1^iJde6B&g!c7m_1cKW>z~1GtWEKB_D9(rHW7)M>IHt_6C6%zUmL-j-GD=lTdiXA^t*sptUaV~&9DGr#vZO=U z)~9&&1ze@-ae$k8<>9z0Y+- z-51s(II8Oft3u4b)qQT=7}rv=zS8EbebE(I*K8<4^|1OUK>PH|r9Unu{*?bcqE{mK zte8k3E@UzqoLDhIq7Yw=$JMy1LMTdS%_xN>1{siY^@aA4*z=!1gcuaE05zY@YLBs@2;2&-PAIeAbG2T0XB}w9M!JsaaQ+2hJ@65D7AjAj^&0y+|%wsS+7N`BM!rtN9lU1rk^ft?d6|msMnRq z0afBHGyyIQC&Cr*QY}-pQjNDK#%#(#eqJU=p(K{`%lX15<)g#=L|-re7C-o|B!wiI z{+84Lp&*KqAn?4)#o0RSUV(SJTz0qH>FDJ7`=XrP-3Evd3T%mjHZS^yg@FNH^vkj2 zi^4X+wGViyRajWA@>6hF$ZTB9~2HwjqFE3}7L5QTL+XR|DXKi$rc}sPbHB2~N z9O+Jh?q(n!8E_uMNEv^q`H0i`-CE^3wGjKK6_#}>$#EVW6bZa^N=@Ydl+S>$l)rEy z1!l;mfon8QCzLcbCo3d~y6)+%G>lzElB5U10|nzTo6i^44-U6f!P&(*2L(Xsec&fl zMGx=cCE3F}foP}I*6MiE?y%b}IBRWn*xmg7aO?#%czzcetZDNS@8Sn|zR&CR&W4j~ z2TXOpAijP<8R12B`->OJu>sFbTeq@TptULgom{r2$dZzzW-X;OHeH6xb4H7>RMyuc zl*+Z17@Zxj>!>r{uCwM#t&r78Tk`;CJlIaT7LO>uR7$73rm19j!KCxK|*gXo*D<3T{|7ovKt>%xm ze78F~olcjVbM<+6-pzaZo&3=FEYI$8a2#j0m@Sttn=KZb<#kJo!@+xIV-ROqJJ6J{ zBzbRkxqz+9?Q)I^E6FUp*!GJmP~Cp<;zcs~0#}m$ewV$YH?nv1r@iF@%yl*o+QO12 ztJ~D7t?t)(Ye1<-8>+EL!sMKTi#xzv!Z^ol`M%L*#n#HsOVh%{s4yl7qMXbU zbul)#vU|nVTU{OPT&vZ>Ih;K%r^|)W?{IOQ9dp>ypU0n{Y&DLt~a$o1nt=JUq0cjk#R5`vR#{n+fLp+5axG8ryt7s&p>sxc2p#gixupHNyq zJftaxLn?Wtvc4RTtXM_260C#E0zC;T!_2GpFj znY(T`o0_c-M~|b+$y4d$9PKvFW^Hfd5N_>`ccS?spR9Kn_MDAyvyIQULTxD#+q4p&E%i3`Br- zwg4(rD)qH&$*|<>_YJw-gS=OmjK#8#wdA~IASd~qlK^6A(b&Mr8%TPiT++EXTbrZn| zzY0t{p3WFtu1)-u40Ou|gO6!VPQAU(a7E@~xUzV^&9)dseEWdH=C-z*QzMZ;BoYbb zzM)P{f}{#Wj;eS+HMGRUD-HG{Ii!FsF+85o3PcEe=94mOQ_YIP;Gk!)=eDcQD~7`q z31UE3NhTE--siy{7uRgHTCcWS+pTR>!kSIiYt}0m@K&H~YGzt%G7+ezOQzRw4i%u= zZQr$X#9xR5r=P5r7PHmTZfUnR+w3>(wgqLKMhRTkd~zA?7IGU5iW0uiUai;3mewHi z)~XG|p`hiEgEak=*J#$2^;Gi^2IAi5+cgDdTrL&Za4#8sN}vn{DHQgot6GI#R}n3D z4-R(e-x_Rses@>PfsBEvuOm^a%rIOE+*VYK$|^O$sQX2DLSv)BXf*mH8vVCOBp6pS z*#o0W(g!cS7!!O$!~9UctFM2^GwhY5a9CRdZMFINd3@nrX|TJa4M4WDUtDW$YQ6@@ znyp+@qp6Wd3RoK(&E`u$^s?!qE)+~1pa^E0xgDZyx3}9Y%`G-O4~k*6S!}naqU*~D zBgt4SEFu#2SjNW zW+9tQ#==VYBT1WwpbftbowYD%A(U1E&SZj4aOS4Q#wHSgOP3lOP3&a8eDSr*0Qohj zfyLZPIA67P*l=PRY&Ew)BihZ7hGAJ-Rzfj3EW`cIC+7jLUkb-VAxV(rsy=B;O^O{_ zE2`Hr1E}p?MI~sNwSb-w)$$pdveGnaap+^5HpJ(j)5QjUN{qJzEr?nu08_1yUxSfD z5(T`wApL4i`(}$qKu%dziMD~Mz!Meq0G>9dM5X9TT;3$w#zXkq!c-tasK&|LGMI5) z(F&z%-Gx+l#UY=-4-WSC_20e?{}fh|i))CtVQDrT-W-<~v-xQ6Esn5lZf?G6<*ZG> z3rJeIYgX{pMA+igV1nM7F5<>z=uKh=W_1EpQg*RiPGlJRS_f2}GX+0)dY|j>Z!h5war3 zQD7rL7oSd&REDUk(CY&I_S6VHmrp6}D!2#F%Q2KKVKx?16u0LT5Oq2xSs?kM;E^&*j$L@0*g-O}*gD8s~S&7VOUjFAKnpQ zJ24fIX(1^79+l#NQHrmwqJ}Cfa(Go5TMci@j}{`+(+h!VNeYEXby51r?-@I#R5dX$ z@qq{6-szD8~W5!9IjcM7~t|q+0wY6SFE$e`0HZ?by8eavz7~u^j^Oa`v zg~nIRmsw3~Xwj>irM(p4N*>6_4=~t5VT_DqGQ2ST z$nPh3B|ko>R$qF^y8mUS3F~D&B@`5zN>LP@yi{j&WdOR0mMLn_acvW|ZF3C_-aP=G zK$l3nySojzck!21IhR6Us~2+FGvKsD@p&p%`-QZ~J!hDDx7GwG`8om=;TFyYrJ{ zlC*+*L}_JZrG_o79AJ_E9F_Pom3e3-aDx|O)tlTwLQ5oY7lE75bT0;&H(5hfOTO5J z_7c7aFj_CD>=6;E;TolYMFSqF0$@1}LzRvLAXF*Tu_;tCTCJE^BB_Pm$}$6YRa%k2 z$AE~)wXgthu(k^usmXCXDG-ql*z_uE!5u0e2;zr6AK%~K*E{T+7#I-!VM&D6CQ-UU zBuK{CN8`!t!JW6;Ij*@`Zyq!>KxrxFLI_Z{OiXWKz+e|RJ9A$4c9#pT?6Sp%3f9tY zhW%=>w%ojV>m5NUXdg+EAi^ZbsA#Csc)LxXZxj--B7w;=HJSD49$LpxEgzpNQ&Z+> z9i@H`Q05TtiF3IGh?}FPYB5pFP){PkWS5q00Tjq2Do%12??ICzYrFbPtxTOks`1o8 zB%o8NP&5=(gBa5){K2mS4BWuOAOt*LOhi9?5==oDp3H!y_{gC+5KZQ@z;xa(Db!=i zCSw|gQYaeN*nXVEioI-76g<3ekMAG$4fXZ&cleLw@nr1rT=H>paSl?rCdY)80XbXP zRVEx98Qs>_SDTtHG&NpmYPEc)2@HO<`C3y$W8?Y8hD!h!Li;M{YInDq$cvdRt>$K% zt^H~7*1If!-Z_J zk20+Filynog{BM8R*U7zg@y*ChHK4@jRfw63y=ob2NPn0+ipH@GQVar+Bq#Prk3^& zNy#2&!@>ZzvM5Q)au%C>FPlYqiG{;5mEouW&DW~6mLGMnj!AFVOY29}ggGpb9U#X< zjcUbcSOeZ7F<4{$G&}&dmzKvWsuY)Vo6HPDCfKAQO%xD@aimznUS++PXi7zPO`)WH zJoRzlVIc5nAn-JUmsnC~0yFWT02v5O_!h_v;Dd(4LL|BpTmI$r@RaxfcgPB=oE%MQ zyDawLgYWH1ut9=vVi*p$x39NvfLh?vS~e`t!{x#<%+4lP!eUqvmkZT_Tdg)Lx!cC3 z#s<>`fO@5w3GWqh3>WqMU?FU6TqoSZdDOR-*G#XyW`ZIBT}OYiP?DtwfKM0}L*wHz zMeAiPsjNJJ(nD+M1Z87QsfylDV0HH#i)Dx8z(^B{iQJO9M2G^eC6F-#Y;y_Pv4eED z$f&Imyw7t8{OR}-%?-$uQCU!B*rGmBPYb1=c`xb};LpJ)2xP!^`qPPss${h1plu|A zB(~u5`66VuAijbiYCoM__}S>_@Gl{{kKiM){ZKYY-wM=v1|JTzl{*Ly{LmoZ-`CgQ zH#*Auq*yX0gco6Qvuj98;YoiuD-1{@;#@)NylK^&wUo^+UT8w5FqvM*&Blg{0N2z2 zduwk6L%)B+)OhiH19f#xueDqPxR-4mVzQ8(pGEGXp)bxS*Vgn_;lXZFiG^3?@QN@Z zNbwbU_jK_QTY_6Ycc}LR4%gQU878G9xd_zE;d>Bnd#f2&JH1li2RI#RRni z>9oqiDZ2_(_4^21f*qP0c|x7SXbSj!N==%N1CazaQZW&P{6=RMU6u0NoQ!tLab*>Rm==7{pWV}$ zR~_MV#ta!*8;$Hfh$};I!O~m~#HE#*2@>3dnqWI4c!$g|MHO4vPgm!+$I2KAPzYYaOZSDii$pgUgZ&W7iRrq{3NkQ`aMX%T8_CH>e z`rF&VSX8p6HtHn2Zn=2=70YERX^>#h*JOG1{3Xkq*RPzvNV$T{m#NWwsl{?rd@(1^ z`}pMCq#T}{TU`8PnN1t4lZDA@S}c~F^$(1~2SPe_^z}FOg7ed3gQCT zCB!Qbmsv4|&2rN+0$`n6VoSF&1TMJEy0OH@04Z%W4qPK4rV9(yWntHX5Cv$$*JQz9 za34|>k+o=aCa^F8HK3nBK=4iD2836XqN_?cmRv!>T9Bk^AtGuR>C1X6u2fo6q#+Na zz}4@BEZiIP2!fmU4)|xolaD`n{5ZR~xHxv-KRG@&HsbAZkA$#(Y8}*F}V)EdGCY-8lXJ#e_I<{=4w?wpDdBX+^i4XQ-r1xUizU~YtAt3)FV+W^}( zz&0XIlO_yLNFjV;!8iEc)Kvf9k1mLD86^a&aCk^Xx0IA+4`M^VtIyrz9vmL<_1_*G z84#rK;^O)?6k#$vxv0fv?~m|qyUXR~Cl}X79JWh{W2Vcb3YPEM&F0ImUo)G|TV96< zBbQyibn$}O(P4unGj%xZmdlr0S}wn4bIoTLJ!9SxNf?1R{q$G<5$_1D&Ef{UG-Gff ztHHJSMkBBZv?qY4Z}E9GP1Xy1|CLe%0XVGE^TCjXfFm>Qzjya zQAwnBtuzx2Oi%fyrrzsA_6=_;4BNud5lw4oE3x5zx9j$8m&?`T=6&v-9*=i)ax(k) zv)>jzi7hTJFMhI^9lt*=3O(*_muuWVH_JnD&6h4-ymaApi@B9+wb*Q(me(6E0o=`2F|EiG>i?=r9$BN2Q~~!m1b+T>U`Qh2Oq@m+Q96JA5}e_u1p^&lVRSKYsj4 zc5!n2zBG$!=0b(?i{mj*x2@H3*>wKWCChg%nP9m(TkY2@)VDRiihmZ8S+~Pwf;PA; z=1Wk9%Pm*CM9qKK?SnMU0>RiM&<)M5$T8}I&B@Zr7_>}2pHNeXvoygNVA!hB z+{9EQs+TS{-a+Q*bY$w&08`-r{B2QN4T*&6LV&_qBpMWaLlbzuAUq1e9!TSYFw}SZ z_TTqU`2vp~g=8o$Ewm^c?rGw%Fap;8_{U)FZC7WHtDpCdg#Te~@t+nKKl}V~0m%9% z$HL=YVb*=K^QK!A@6N}BmUas)?Zr!%FE+gT9lQ0-POh`H@xo<-_cBe|w8AL3O|SeF zoGw{h6R>qIOT4dNcpyr#N&m>$WNdLZHW{0p``6?gNQ>|{JBtlC)HgKj6XbGfpY5PS z=(613%v9Za?$)Epxd>rC1pVeaXnmjB0Y~+{XT`CPTT1h`}Rk^yq zgI`)NdhX2RZDCi-vHoH_glr!TEyYQ9Fw$1d;h)neZFZ*!wDs`oZTy|A6D~tv+&jd8eR!#MxRbt(Q&aYu7HCOm8|6yy}|eHyf+nqm_=1pS>DR;K^69ZZGUe+G`45d>+0$3?!N7h z{qv7z7q@qQ_q*Tz(v`pTFJh0J!faHAhEFi^bAzvHdl~^t!{* zZ2FFc)_=f(T`;v;XxhB>+N)+$o4wIwv2@s4TAcT_8G+}WgZyAP{9t$(!)4ez>O~%T z1R9SH|Cf<}{KYSRF|R~Fj=)Y;xAmDweW{^77ilc(!0$E^GMs^mGKTLRk)n?zYF#hj z^ypFa(W6HQ_f+Xr%Cn&mHDZ?31QJ?tFQ-PKwlEBUE0qeWYC19nS$Ie^jz0l|flf5= z^>l=JU}OwzmS8lB_klvlt4rEyd_`Cg#g!E)9#-O!=(KOJmn31(H|?7Wh$IU6?B3pg zN9ha=-*NT3divdhcL;im%<$9MpMLh=_JQm_{r0n;kNsp$Lgt-|O%8ax-T|+}#qk~~ zskm;MTFmwi%jMTiFbbV+do#!i7#lB|E;U}^EanT>P~c1rZEu*Y)^;1f9h9^OJ|}m_ zGsugAFfl;+#QlR2?~jLk!vcZ|013}6{&W)QItkvg-Aj)39rr4FEn_BZohieCmIG(w zArb*;0aa&uA+ivdo(@a|fJ&52_ZTb7B)~)c!%#FQBVy&XA}B~1EtLvHQ!{E%{n$4( zfxF^BIt7%YMKuz^@cufA?Et%*Vyi%b??eDM@v6#dI3#Y0k3zB7YH(GU9vtrL8+?Dz zH}yVDM+%ak*kXrY%FPV&J^Y|^z~hER=;;^dKKbH{?SJ~G$DhRhVb<%qF@manKRh?$ zy*obQ;e}yGx1-O)OJS$Oh74=7T{5-1>}HGmyH@ixGo{`O7aPxCbGuC!uidmGwApP} z+qrfSx5KZ<9w$fb;d}RneLkW^0K_4RWgz%NA*B!9Y5nYg%?M zpNf#OM&s#-8cOBVT)^j>0@~@BNRHGu_&oP@;A?;l>4jXwO@R1I(dg;~ZMB4=l0Ok+ zK8cEHXjNG7`TF_?eS=ejupG$V2-^Cgt(GD~{kMF=kTB#XhcF7u_1k}X{Ml!p{p)NP zA$P>%7RZQ>40*i1Vc&?a+u?M1CZuqW16HfO#rFE^oEzEU%~rFev$f$BAvaWKw6K_=c8S6h6a(f2S#Scem0iOZh!LgpZ?+( zvwnX#JfF-WJM6H<32d(_I#T921K2}4hDtWC(b^`q;t^#gGW{vJ(TNFaTvO7IOHz=u zR!*&ks0$vXQXf={$`+H{hd?fsT6#juKhufS!;fJUP}rhNDTr|@^GEoIU*i#QcO=Mh zHUSKpqqNbYnoUKLEugLmvU z+f|FXgKN9i+GurK&28@1h6ZF^^Q%pb*X-9C?~ZvJ9VT0oqo>DaX|}dYA3eC&fBROi zDDZe8-syBXFc{wQj*Pm;el_;v|Kc6;4h;?a$A&yoEV)~%6|?$2Kj%&t#}rD1yh7`- zWL1i;poo(dot~Ns_@<_P)J>t;LdwM;SSYj_6-kt#0yBz6og3t{uOsQS`el%8Sm>!r zIe{u!bSaHG_5}8raC`z>)2tHGI_8;38r3YVEahZLl~-0C#T7ZctL0^R#m6K8rzt5O zB!`_q4E$3*FGmJ@U432e3;3Ar>3T-#ptH8x=M1(CS_OS#B7ma3kO20JmA1+{VX7iKrV3e z;m6Pk`ca=eOogc4eI0r7Bn~l-FXf;Ki5#Bsa3-pu+!mmyWQ9Ao$le`>)dtk$dATQYP{FFUHx7Z^IyEf?2Nc1~`>%5iuQoN%>LqHNH+wtJf7k8q!9&{nT-~t3ycqKI za2>qM$vb=c`9aq$SGWDOtB%oWac*&A{kOmUZ@>NB7eD`p|8r!h+tIHiwcXmzygINI zrnd~&D%(+I4`UBsBP!_)ZfdVU8HT5(BS=OPt;+ysY06l7v>+}(5EkH1qj5+u+(JgB z`CQ<{TrMJ9l(2=s62MQM(EMcN;nz=yxGHsf(yCU3V|W5_rf23f_-W)dDva5rhIjD= zrU(0aXf{2{^2*ll^IM7Z#J$16o?G_@xSO=fnB#2iSFXE%a{vDQu=bH(6ny<&x2w1N zCLDx|<7nBktJ7k0yB+d4&vmrg9M0Yji^<|1=iAOTG?|(mR?Fo^lilhtH(17m*oedI z^7cAfEH=-5{L8f*?JrmY?5 zyG2&@Jz^Pe^;w7N`a124nIRvKGW94znjo>Jz%(2b?v>&!RjiOyh+;sP2C(!49VQ3y z{5kF9h|!))!0ZA}^~-ehAxjfc-7P$QrlwHc@E7%|`Ye}QQj0lwh$o;hYFfOg;f?D{ zC}T8o1Yh6nzaN|ygTXj~o6qk(SC=LRoxLunPrSu-+dBa6|9;ihGx{U9H~Z6n2EcFe z9@t+O@AbGG{f?VNT1Thd*1@%V?xN`1+qq$$Ykkf9{rev76+~V0b+hS0Lu0emZE3jX z^@sf~n`6k;1@*w@aL}@5xP$&-eu(dN_d1=ugZFr^cWiE492xlGpbMJOYrAP{zd4)S z)wXxo(S<8j{g_MoJntdW>`N=_sw+q|+m6WW{AgPZiP%A&zgo0I^-5X1KVp z5Q);Xq(aA&poPl0VlMt~Pe4fM=@V+>q)_D4RQj2kc$NzM8aLBmEzNHviiv0$ao$W4{#n#E$JFfHM5X%2mkLa+rm~Pw` zT@B`r=BwYmLTg1^9XGBty4{oa?|W}@UT04Syuyv^4wuCWb$0TeJAALB*TeVri?hOD z|7f^>XsElVr}IDmC%fxE+5V4?{&4bO?Vz$#Vl$D(O4jl@w&Mu>;J0*0d)O1S7={rM z5jP%O-6Zdce_?rrmTQGWG%*03r6pSk7&QAGdIWF*Ez(3PNOM6dg2a=cN_#Uw6~NV} z>XN#Yd8R&mNX0DuH1RZ{;#W;2sHCy|M~d1iP0=mM36{K9#n7r0>G}J<2|<#`o5)KP z9=0+*_y?!QBlw&hTn`k%;d;a6{=WAu&-mT(G2yPq{kNV04_pM#-*9p+_aITv-r31H z9BwB90q5}`Cp2vUYF{Uq93IjgP3X6Yqm z>EJpzu2&TOzR_9U33oT^A4V*^d9$;}Erzq%tdgX?(W+;T^mmSwmUcv72p6_A(pyyr zH%eFkRpCz9D zG500K=TtgK`-_0POS#}P{U8a*cbckZp!Ok|^)!^AtZhn>_iw-NW2uE^osk{#8Tnp6 z-~Y~sA9%!pu3J4fJ8a#ZHk+l*dl%t!WE`%6cf&n+-bKvEb%=x8-r>SS+Hv7%w_SC3 zc+O%v-|D>4W_G)-ng6P>fmV-lUU&nyx2@Ce_K&%t(Ojq9($h;Z zpHq-{K^z<&b^Rx|`?lj&cjxGAG6`&Bv><<{Y#bor2p+7!IBU3t!@Q=+Kz9}H>QQtx z9HwQv05=>8Q!{KHD!4*Z$xK zpqKz}Bfp0G1#eXVnxp-BGk?rIjX!0_PLXL@Vy^0LfuvCr>kU z>A^d9?)3}6R^bF130b7W13#&Q9x_fBTPKN4K48x3#vSQUX=y zklWGSF9@RK7y7$~#YtHfMnqSO&3?1TJphhCalhEzGe)5|yP2fj&}m1Vis8e~RoCl_ zziG~_plv~OWm*^eC>o@-E~_!N6iiW8gwatUKr7)SDs+(`ePz}$l%i~*2V<_RYMER- zP7{>K1kW{Ep%9Iuz~wU;2=0?;^hx?@8r5v++0){Z`g92uj`+P4Qk7gNNXy7_)QB%? zDiX49in{D5a-k(MdVAk!>b<@@{0G8}$MXTt^S#bnT^-F$%`mW|PN!$gBaDnp4D*A6 z*UR(L7!SM8+03n-Hd<0^?{Ez9BLmWn)`rGTo_Cm<|ITgs8`Ep{4$Gw`r^C|V@OHXv zrcU>OFxbPn92U3*d#Bxj!YD|BXJACQE8-+P5I&T}Aq<(Doe=&0QPDq}d|XH-x4)nr z%qlxIGj^_8tvOsOXNA1BRm{moD~zCpMF=agSa?+uko%_beHR`@5z#_yksPT9O^wO9 zRkn(ZRyUxSrPNbRgr+CQ28MX|jW;^4wsfF~y^ix95AK|8GdDCk;M7cJ*LCxyc3Zop!`uW4TV0+G zm;JoiJs^6Va2M^ZR*S`M?{wU7d;Q|b*of#C$K?lNSQJF}t)8B4?rm~GfTxULD(;s zg3#SG!g4Aa45q?T(ucw>aXL zKAM+43Q3CcpwHRwa(2D#aCh5WLxT9=aZHYH!r<=chpc8R6pZz^dQ+iFqQE*`7?v4D z39&*J6?_w7EEJiZfR_&l69Jf8G4Nr8dJAeoQRBfVwH&EoZtU<3=%RXaT!k^q=OXb) zE)>Zno)@<=AviKT9$Nb)#1^bYAp^qc;BQdkoi&hnPoZ0yIMu53121&6z=& zRI$(1)x}HVfbj01vkRwo+R=&Ya`L!G{0IpLpZ@{G(J$Whhyn=cXtrFlx0}r^v>Pcu z&}nICfZUF7t>h5EU}u|yv)HXx^EJ<1fxptw@M_z2x9bh0Ig7cCv)C*h6r0^+_oYci zNzT*G?E>H5-_zaKP5YnmP=0AqSy41PWN4+f<3P2n=Q6#4OSD}tck>OQC^BKsWhMgX)&>sE0PzZNEe_$P}K58NUR!-$hqfA zv8blmy1N_%H=+I!B@KFu^R${ug;Gy~K`1tX3+jg0<_X1DgTQr_Xspa@N-*NQ2_PTH zbU=izcL>{duEPq;bWi*!B+n<6E zrS*o_aou#jq0MxuoojbG>{j?PljrVuS2HCEcUKp3vfXOt9IZB6hoi^E^Mjtbwd^7t zngQ=Ue5bFc%hl`XzSZ0B5oZCpyn9gEXGctB|5pr6n4Rg>uu~zc#M!i}!gc}{CZ^+2 zpAbM!V6Cx$6vB;#2|X3V&nI#r*5#%^mO_vvYXx{{RuaFPC_o3#qtUOa`zULf)$RpHgf~(~DAE2Ck71+eHdhU{eVRzFrW@Er5_7Cp+~z zySTS+-Rkws%qQlTm)8L8{JeCR`c^z7nFC5Nr!JQb4%gfLhOPC&`SX8eYUbRoiw%D> z(gyzkKDV2iEEdxhhnus$0_Onvre(V}E7#u4A$>VV#{@6zz+`NBZ7mstYDzP~5Bay> z?sfVG2PD?SqC?Kp9_Z|7<8(Zr^0}S$`mT3u&g>wGL5_I43+|K6eT3vWvG7QI6bgs& ziXxji6D3;n1#hG!lxR=}-$G!UoMy|$kh9ogMw(Gjiko>&&%M!TPRnOjLu!hxbS5C5 zt42SJyjwaAL{sT6p8;t#n5JFTXHv9wBuFM3)@2jJC@%VXd)uwemHHEyBld;7`Y&(z?qdFAnyVX62 z68gadT3)4T?9fj7QS$X8a~SguY)3JD_pw-r4o;uV0^8Nqg^B6m!G7OpXf_-cN2W(a zK?or|M8ug0^AJixk<)3^8ocngo2h12A`yYDLhl9U8i6Z5FV)4@gd*aVY7Gy zV9PtXt~Rc#Ymomy3`*lNSUW$D^ZB{)@sAYxyOZ|cYXi6}zFy&)-R9O;8ee&(!Qtvg z*t#w_JFa)MIe1sk^=6C%N0(FZ{8agvzvoaxOW! zn51RYu=xVt#qkq#U=ft|-2>W1y2=hbxX+HXbZ(vPeouXx^=-DFm=aeYDp^ft<$qzi z@6P-0Pk^#WnZ9XJ7RA*#h#R3sc}RxqTtX2?fnSo-w2l-e42&$Qv}~W|%4u)MC|ebh zg8t?;I*JmK+QYA-wD)=HiTWFAN(K>-X9(}$Z`9ua_4IFm>kRGgtY^KFPTXw6w2oXP5S zc9=~-w&4|rcg*GVaAvo;)9JACH$2WJ#AIieF!pzU^}WAoXlUlH+1qGGReMK!yPNCv z4c>D)h4I*6)ep)Lk4cxoc&B04SaC;pvU~N{8duK54?gK@eSHuUxjjn<5aA^ENK)5%Ef^@Bm zb6f}bR*QpcYX0F}4%niUHFE9|-aY2F*iDw}kZ)`yGqMJGFt^py)X-pRzGi84aLw0H z=y<2w}Z&)m57=eq8*MI15Yk%YWmc|x4N*&kP-D%@GTwPv%fSa9cY&4t9 z-?Mch@qX`n+)d7X*W2Uu_PhLHp$EY?mK+ZkAPS3~w>vN@1Yu?-;`?Am+oQuZ>w3!$ zrn`T3?FWH;P}o%I@H*O>vic|@ECd#QHqqC2`@i-Li-={yiXgx*$l=hc5?w)L({gf} zj(efPR^_6>G$442WD6^nOT|IBRXhfln|h-?BGKV(i@DtD)I%88+$II$9353D9j8K; zlCh0aWPZs&q}k$~XLR%m+LuL5K-=RpANHZ@TT!JTrfpZO&CML=^!l@f?EJX%##^HF z;O^Z!PR~c;_+5`MftcZhCUREJVr_S#fLY9@E2dXWCT`?DKW4F8Oy7fUIIcLl+#ODc zj02Az;hW4z!fl;Y1e>`5j_dF2c+1&^v^&a6_rtUPaer)X@$tMgJjg?!20g)0=tCh2 zY^hH}t3-`*cCNllxn9i*2Z}mRdl+bPGys7Gpo6~Qss6s+pH2T#T!4Phu1KNyBZ_6f zEu*L*n)9XPpe&_`x1n5uMmk}uFJ+)a9G`(~fV@RT%TbGAYWi!KUs^sA$rYE>9Bc!* z1KP2N5(uo^)1{|RpFIV%#Y_S})Sp{|{Cqgkd$YZ*9kvMAQYJOGxtwnAkNlH!lkR5j z?vL*Cyy&_9w|9NQjCl8N-}T&k7c~lX39{VM*lcNPGB><(sqqR5|46ghYHhK5?mDfG z-Wwe^?z=dc2hMTDWVzhfVttK6A%pn5&2>7serf!E*bmZ<|7c(&wzf@9Y?Q-Lksle3<@6fAR3*B=cwruLVgH* z3T)%FqFc%M|mO%pdb~lx%e=5}fGnhBa`yx~@Ac zmS&ULe9L*~onDXkzQj8_IIq|3xzGDN{NP*sjBxj^tAmcKLUzJ6;4pK|E_+*3!}(WC zjvKt!<>t5_wA;u0*4EC>&daVJw%R-0oXh_DrPmrQ4$CF8!(nT43ZieqGr)U=yFc`L zNABKsc>O>6q1Wvd=izdLA9~=zP=kg8lJcC6HdwCe|4~%6aLyqy zla$p7pD!>qcyDTOaCCUkCkms}!j!(pqC}BRmR8~O5FVm5W0NEDg=BRp!;C+5#2*F% z7}SVniBLQcVLe^cz9Oq_KsT~V3-O|q*g)zK)vO`{E-Km6Tn=gNH_!zL3_J2TtxLsw zsi_YqfD}#+2S>-8Xfj)`@#A;BUZ-osJ1z>o0il<)*m*bf?j0C4pYv^}=N;$3)h>_o znyIbX?lC2tRFt4_uirP|`S4vfEuvR53pe3Pg(de`=JvIFPd%bByX@v`7JJ)uko~&*jgi(jY<9nw_jEQkywYg4 zIvkFh4xq?`wS%xFJntSxjP~;VL&Dg|m_NL@xEL0_ZYRYTk@nrA{~}QTzoYd3y7wF% zRIPTH6n4yAI=)RI&k`@lHSL?48ti+o&o>=~X9!VL3nyu3VK6r=)9NuL#}5K2! z(bLqpOv?`bjdqY!l}tj*q~Q|+(f6n6_zY@bDnQtN8V!6rO?ynr&)NEE+5sRKXGgYU z(>#f1IY=%l+p`SFTYR2bT3VWUGVxB=+bA;EprPhwQ@fRO!jIh>3Ydq-xIvDq=N8wKz>9qdZd@&|_{1KNG| z|E8WhqCO2f@K>qKu-yf?g}tl>ha}MvPKJE%`Q9HKjBKuo)M$u>!m*eZ+f-;N!6r19 zNXHg8vQ@e4P|JvFp$IK%q{YxmBBVWs7n2`Gr+k_!YjNLH01pcM%k;na*rHK&mmL-d zsBXqpMJdvLuW5o-Z|}k>JbRY-;~z6iPeZ|nA2@Gyz0J`Pl&mIGQ#;q?xZxcgyX*1# z$2_-tTsw2^Gy43_yHgbT=?=W?`8%!o})BXL{ zPR`!&y1Ucs?Q(EP7mX$h*J*ROI&Qd~_~D0!`HA5>bi6Q+XJl+l@QPz|$(Ual92)F( zx$qvNl6Fw2R@r}?Q9Ysm7FqAr(B5TqgrxODnm5bm5y`V4ZbFr!v{#LfR=kZ0!XqUV ziqS5ntVb4;SJ;wrdtSiRA06V3cU99BYd_q*fEn7t3@vWfo{`_skE)Vb)!D8}MJ;`+QQkt0ztf z3>3weH{X2T=Y2o#`@EE2mByx~3Y5QPrvGE+vjPN`b~Gl;fa%G{XrNhPp34H-uUCFS zHii@?6U$8|1}S>CSu9OAn{PH#zTd<33`(DV&+Dh~GBXjq-F1uSEjOFUae<8VX#qNc zO-=`SxNcMc1@ zv&-H==t>|SlO_M)JxP-Ngw>QvN%Xx1?}#_V28ATLr*-Jn8Ia4y_%0l?ysWzay80T& zlGS4}>uLqY)l_m^GOjp9JS-?u)~vGb7AU#t^|m{Rco7530vOo%`3jo7l9_A*^JG&2 zvTY`rf)ov*a$+t4R#6b|PG!kfY)Y~~$=V8fp7bL<%`Vf%GQq*djxi0tvH0u7jbCj1 z6FDxigq2k0-e6A`XK8CDFlZyw-r?*H=YTBT`rh~LAAaZ@3Q&ye;d|{4k6`Wi(AMgd zhPdk;tyk?lQ3Z*JuFcfYU~1?JdmVg-<)*XAYV~?Oyp6NjZ@=GQbKdsNJNd?jiw#$9 zSZ_IeUA>MV&)Il~5D-2c@KfqG6OKwg$vdHpD)JDK5|PYHj;AQuv{tSe#x+(vU`_{< zdw6pS$Atvdrk>y2s%>rR+KQUFpNK@n!MiS3K#q}NlS+!&Rz*)3&M7IzqqR1ZWS!(_ zkWsV59B^0$pHI@;%za9XGuk3WFY!LUc5rI!$@1#zlh3BW5>_y;woKXZdI4h*xEU~M z^b`D-|;sk-h)qq6sJs>!|e!na^eZFC7FgPesuFAYtfff{o3ypn6Y&pyYRy!QUy(4p~PXOM3$vz361-OLMB$1rYw=; zQ8qS>`t4L=8U>rVNOqlEcPA@OjUl+vzjG_gt6RTDk++atVZu0D!1ommW%<=jeTO33 zs>U>gD3kc7)qmPSsp4@g6AOI8wYOWEEtYo5cze3KDD(343xdnenJ!;#A~I#?h+p}6 zdsi1PU`C2wJ18$}zTVvC?Q%4?HC-a>UT<~`hlkrGi@C8uXuD~)dwq_^D|W%_^bGmX znBUO&KDjIJ=j?ow#l}$(<2fF|jLb;bP8owo9+pQUBU03lBMwP|mIj+GG>*_u-<+Kq z`y!9)JnS{u{g?oE^FQUWa$%WruNb9f=q3z^nG|}5P}oYL1q|R?G8BNb3=g2Bn0lOD zf%Z&BOe|!?sZ5FP`Aj6UlGRmxfuLKV47o5hm7zpyYZcY=LTW=>-O=^Et*><0k?9Dn zVn~o+W*O&_8#=~_f4#Bzi)1X52)eqh1h>uYmd-AFkG;3+&YdnHC4Y<`#B*4y@ufKQkvguZrZ&;AWE$x5O;BB`+GV~*gYTl5f z$WAk8!qppOR>vssw7cw9yAb3%eIs6%iyTx6c?k(TpbR5qSA`w@GSAhD6{An|wQ;g@ z;k+_#{Bv48J+4$X^IKb66#@k;_J6WF999VR4-S)P|cP=(^J}K%P;0Bt^tvugkZKbaz50+a;S@o!gOjc5)(Pyt zW_*{Bm|j)YIIxpMDd@71-`cu6?2g`UO8#9gj~B*u^l+Tzrlp-sOL5=H_wY_)WPH1s za$b|27_Zgg^GFiUb7s>!7aQ7!!t;J#bGWU!qm{SWZnd@%gBTbNd&5x*c7I|O94>*f z28S~!xdmm=L9|wiptTazK=ir;j!(Rz1iMQ3t>#e6&Xtdz9{ud-ur6X|%2kS)s2k=B_63G(1WQ&QrpOm{dAhFS=l0A+(@ClbZe_t(+z*!f+`-p_w_1LxD99t zuu*_QGOLV;p-`}kv)agS?e=b>1C)QcT|&R$arL>;F>3Gb?ep*yn4CS$ly=b_-QI5R zp(y9Xm-?eoLIty_;o>{3-}A;l@;M~uOFaq&q?1DVYdxq`MT zTQfp_n$>m}21U?0MPDHk$64iqz5zC4U^Dk#4W68*w{%S@a{-55G<3A^NM)hOPRP%9 zT3gIEE5#=}`sjp!M+gOoBZ*$Z04LuEqEA5U4Ro~I`R*>k~QC zJcMZIu6GK<-Z0njp{=pi*T%KI+t}{^9?v{nyafS?QWa_o!+Mce*^SYid zlWmo(81VFYL@85(8YR+OW?UT9K4IPUaN;M68;gsqh4C?KQ_6f!6qkuR?ruyIKhU-8 z)YKHZM>cfI%ZiW}q--n&{Z+b%wc2lvYg@HF`q5i^HFDtPRkV=+Y?oP0JhiZ(Oozl^ zcc%@*9v!yMZeH*R^b7_(4v$Ol5JC`0l7qTDo$bPK@Bd)2^Snn0IJic$ji4wvLwaae0>7EJOP3Qo-ag*zEO8&l4pD;Hnc*x4Uf7H)+ z5&94>=_0t0{8Gfr223P53Hr69C}f>t@##}+EjaIEMA`NkIqkFa&8G0-(=ENOrHzA~ z=`rG9Vup1XucwmeRHA1xOL&lkkkS*J!Ynd@h1H$KB)NCtF;ptEE0DR{)rsg9cGN6u z?wTS#OZ*`ZeQ2Ux1(kK~ZvBRAy+_Xb8zO&|J;;!QEWofE#^6;+k%_PbJ!IM&HyA4L zcD|2XHz))GygNwfYVWlZE?D>;54o`a-&w5$$6bAb-GVQ6db@o6Hd}OL$llKLRDF{1MX^m3 z3%?|&n4Zd3s!a1AN0pTBLWrPRg`_`u?cRe2|2Ms}vr34eE~38&bJ|LlY&#b0?zLI3 zS%C>19o@Z7A910eR|*LZHzoD<9^$vC0`Ly;PU}sM$P>l15Rc}4el$8h>ipRG7d*bk z*~EFwEw@{JPNzN0(WP)unjqY2YwzG)=)~dNBVNkBd<5}fzAHB)yV%GCT|7rH$h*ka z(qKdg^am2seFYg5(^^WE)}Q~(*gsI$tHG*`wL>7o8gtu62X&1*EsjGoU0neWn~L1e z;K(tVR39fPW<5^Pw`2#2D@?_%Kv`3Eab?ud*6imPwkP*QI|4FZA`6R! z0-IexH$INKux)#jNw}$K`T}*`s!%k#m&mH07Yd2#NCJZ+T7__+3gU%uSA$R-Ui0+W z+N=?~2Ht{|EE3$V`~#YH3Ykb>zlR`!>;t#uSwia+oB?OZC-yl*-k_Vm?X=s79<;YR zoE?I|@m}wc&~En%w|TF0TbNDvT_fW*(sdEWqt3RAjqeTlhwMJ#mQ!{%4^IdmHQ#bf z3PKlI^5*U9wwv~)uumrE$FrB~?C2o37D7Eed?XMMLX=97MMZXIAZKJLOSkC}j(RZ^ z$!axFzFjjk!q^HD{DW5VEk-Qq5jTc-Qz~qlQlXg&RS;~s*dT^m*jU7oLE$mM#mWlY zR)=w+(N5Gs-^8*eeL3-2W+k>ksW3{ng@RTo*D7eF-lCj#mkj%WDeEwWU2T#ne=vDR z)*bnTgLMzA7x^ODfjZMQbsOifOCUL6)3UJUH?2~HT;Gvw>LBPQfv1pNe=g7=v_cBHN#w5OBl;P;z=NWyOnXG)Qyx!GNRn9- z4SM(tNfroQ1U$W-kU+LIL2CwXi_tM?rXVjM=N%a`K54U4SabGtwOfeF^H;e&;P=fVb)OEDeR!W zS_ca=_V+gRb0yrmCN67uqsNm%fl)8U6v%>z_Jx(~6BKZESo*p}9BLI^@K1sEE~Zbyclrzcm{hp z>lHF?dz-~#wb7r=!+E(*J`nO@7SeA2xWh)MU~jg0y_|)^gqW?liMuU$hgI=L$9L@J z29sG(MwQuN!D+hK*!tb5?DY+K>Fdb0rhj1*q_phe+Dw-ko1D&}3A?QWvcqQFAjB|w z`HHqOsrP!y+>f;iU}i}E^74wmsDTObcfH;Q^p-5Ti@kpqI+ zy}jcj0)uj~l$oZ)fPTfu2;FRbysucKFuJ0!Zl^?Kihg&|-P`RB^pM|PGnrbccN)4PovzZs{9qu4+u>eK5+p-#$EN#slSmNMUhN9_V!EbJS z_s^rFQAEHtYlk!3`d(wNSDF}i*xMT$8rtmM@F?-MD>qDy*K8q zYz$G>to#y3yB` zG8xKeg|1ufATr635s!1`i%Mk|g`Xth0?t0%WZFKD%W5`VyK<%R%C#$vCXmP zveJmaw>R^mID+j?A!qa(6+cms<>$h7pP*~-~Fu-wT(FgW7# z3W9Hl%zI1VyPTL6MG{OXX)&2BoNpqo2wiq_lewWOtW1`RaVKYb_oCT3;PnxIz1?B) z`D~ZpaR^a4>=lL}p-tF3tVn^z_ZzQXzJZLyC;1Q=o$^dnNvG2@3yS0o2HgF0vw0(# z6%{onwpse%41J8igyU1TZ|Ho>!!h~oF>dRf9mwM&(Sji34ijeESb>HW4!jqk*0_QZ z^c}YL6$fd%6vfJ0mE-C$u>*Yd4)$o!_o}h8O?`7Yl}*s^u!_23Uauz*N@jt`Ovv{B zwLkk|7$tmZBslaR9(-x|KMFM|d3tKB=T46&V7+k-dl;BvE$RwfH{We{2_t^V@00xk zM$ercyfYNUF1U6?cHYJJ^;$TGG$VO_Nl>0Y{W-g=LM|OtPCHiU?RV*rpNG=q#*F5@h{q++4eNs>rXb5pe!+nw-!89$Eu4xVm>Vyeh1ucJq41EMvya|x zyxi!JMsu^W*V|&c*1`|V1MzrH@Y6Tud%FVxab(2n@r8U*MM_0e^h>8_5FVr~;2|+5 z@9bc8s#}={3O95VKoE<2;0&(XjBvMn;JtEuGY2yt6*+~qvWbyb;c82Y@2tYq6O?>B-hn9Y{XPIAp2EHU&G9(aACGvMDN87(<-S-=YWj8g-Y;g*- zw{=vjoiYv6V~RyvU}QCv46*K9uV~9(VK^QAy?GozR(?}uwq*<01m0}^(;rNbZDk5( z!5=?-SgSpKz>@EzoShQ`z1`MM?t>dw=uy|AfsI}%<7G9}RmQxa`3axJ#78QbT3kVMxS^=OyaVw|rt!Xonl{=R z*kZX#ZU4buMc*YjfTcI{c}ku^4^pYcMNK25SzcV-+N;tvs3{4*JR$poUG3NY_y<@e zFhqdsOBX9&)SfPuNvLo9UMJ9e&F<5}H!Vi0owAFkb(v8cD#y%L(v)b#|2dAl6B&v=^h%1^} zheo4vlrqSmuQ>m_@`%u7tE{PVR-O(8$hKCS=>|Ej=_=dw2o}J#b12B%ZZn%H#$7WB zKA+$XdA-qG6#Xw`TOUMGgpLm9d?hLiUG2@|@uD(0nNsfw&YR}p^n@N)Ce-1uA8PK6 z@~~X==89>{`zE`0wo)5#cJcP0KpB{zj*F5MaP&F?ehQRao5j?4wb9gW7bW`D+dJKb zjn&%msWB!E%~T#v2%W@49BwZKTSbnln%8lM<4l+7E3aI6A1mdoc0uUswAkGvJ6~hN z7zH!7n&$NZ>k&mL+dnTcvRw~o0AValhcG_lVrUm2uDSALk-!!p0rmV1*1JjR!5;J5 z%BD^?ummBx#MCsZT{SfCVOboDbCohQ+Lpn_h|p1#J6=0@UCWG!_hKLPIHc2HR_Vsr6^1W8J9qawZn`RDuHC^PmNYXAfUb)mrIjqfQ=85Ne zqZ8>I)-ObdebSJBJnVIRRD7O~kN0pcnM_Q-W`5FZ?{Eq-UBk*eR%dZU?W`08!_oOl z#o5s_6EEjRd)AQuVZBmgEIFk_>g%r=zhbcr^9F3~=nC0(nF+eXbD=NH&b`slplgcc_Vfqb0a22p zrP4}9St6&clIw!r?&`%dD*zFOZ|XS7*{dGEKB*=8UBdnQu~;PWllu`lmW;&$-2wXA z+5=;KWvRdh;-?|5tC~|+7BVRqK9#kuF{h?yFHr?byL0L;HlethJ zlBRdYDFKU)kEV0!I3){G@DrRS(~Z*r&wU@i$(288G+EobN2IL&2MS^2xNmJ+KSqCD zmvG)Qf*JOZe8u`&Am;HTn<^~AX_r^oHW;>JgV-4{;k~`R&E;6Y<91VWO?e>2+qkAK zD790z`VhuFB4aXWSY7=J{=2za!H)ZV+2L@AF*%kY>&B9qWbD4DThcWwLIcL=YPPge zQj}@;-9XUO%{3FuVF5-H=fKeI^`^@WmoH(Uyy3F>(&bCZBwmWnGc?PihBmC@$n{d7;bF=@25R)Ka{-n@!9?>`6!I zldLMs6NF4^O77z9ZH>5+@8egvVQQqb`HHo@Hd-~4@e zg4kGk{-Hv_(B8~C@hInJtIe=A=KUL;yriTn6|BW#>T8F_9^(rJvwe+(jIDWK^-b1b0G;s_6_tbnRGZNw&!iGC{;|lq?w56SP`FQbbW)MM^mj|@Ocdhrs$L`Z zL9okQcB@gMdi2xT@Aw5o`X9)*?D2=Mc0nS?ZjXlA!*0X4 zy2(U8!P42)ZMi`)_5Js|U4(+Er%#_h!}0kugC`sw8n&(0@!h(xt2KT_wXdH(zgRx^%Uv$-;GZ_w>+3a$1QV#T0d1QT&2;SdIjp zz8|fj38PZfDmhs#S<%$3%JE69Hh{u6Yx$a<3b;6v%O}`5 z?&eKcwTC!!zo)0OooGvAvvV+*$d;a;K07@J*wcd(W5)l0+4S}6dgBswK=zSdk>jkg z3XP^AjzMaeZF(*+JEOA(606y42CXrvU{FfNi*YR%bzZ(?nwXp|7p0&lAjfM&N5GeH zb_Vm}aK5;U^BbaQhx_~bLL}&dKwX!^^@+nJs_VodP*Kk>r=G+fqc{3VDJv(0euurg z-F$;`-bQlTi-dF(QOL|!o7>T)&r!JU;ywvRq)(;$gpIt#JHD9D=V#+T_|E0lf!P$L z{Vw19(?hzRm0Yo$tJDt84qwq@`)vE5qN$oJ36YqhZ=L+-11%iEqJ!^#_lFa+vy+pP z;{xZA>6Yy6_XzhwgONcYAjugi(qpl-yD*c#uJ1mF%2K`WgNcM)cztlbw0Qs6$a!D0 z%FS`@h;7rNfR4RnDYnEVSupmK|=J~tCh??Cru1!<_4Jn+-^KEw{bG7_WU#06&YjNQo=+mmlD58~v)-E3#nh8*j1XZZ zm6Ri*+tqF7ELJPFTcFO^cD;%R+b>Mc} z?e9;_=e0?d$gooe!IUXKW0j%%F`_S$yQk9~NJxo7?m5;wU{Lzt*^9UOx3AgKVr;Y9 zueabH8=ycGcTdLzjS9cb;wUm}tR${$H5xmLpA<^E{yaT+k79ChR?EpAVw)2ax!GA| zI$(FmwPVbv)b?Q8O$N7`meci|jzwVfvn#m;c{<>Bxjp0xX>!_iU~O$LuTpxwlA+7D zl8t2&qO0dlcXy}7YI+|vTn4%q>Ghqm z3~7}raslk-UB*^N-1{lk!VD9iFV)1{{$q889DDa@w9M&eZNxH1< zTu84RS6|nvl;>)zNZzzntuBg1F^#}yx0p_sma{ zz}3^)iQVLsJ=`!~VaC1OaP{idHV$dieXrk34@r_I+4i>DY9IIM_;S879}i!rVE*6C z&gbJQ-P+BwYiHYsYirwUWK;MpLxpO!LOyv<+B&6QwiuIBdY*8g)%2Z@{&Id^QNyy= z5r`5Y%TWd{%lF~Buy`R7kz(2VVqyam{?AaMc~;*+K*_^}(|s)aIEKT*d-q=-v*8CL zF=L(b5Y4Z9Y@u*|@|t1ltJxK((CM|)-SV7MQdlVS4qB`nXDrCvBJ9|gqUYI?n+hwtk!pKBI6y1()s4rSA7Ly4( zMo_Y$IA*%u%KM{H73bMPkZe0VsTs>y0^GnNgeoR}@E%w9RtLf#g|DZ+~aCo*| zx9d0X+wH?@h1qML64n#RA5+V^3fs2+cYjXzpQ?;I+d~R{)AD>yQPGv)mDE`+mC8uj zLQIUv`sUHm&sbUf?C{0eGgcaZap9O%!+{8|85`R-ctZ7Kn>3Z#RuV zHF!naz#({Tzp^_Mh|HwW7bQiydj)x1Rg$vkYUkX!tz*#GJ=A?R$!}NLP%HT_W`1fA zK*8b^EPTMpg?_|(YtRw_J^qy^1-8&c47j`RbheY@wvp#H5h}37(55ESHH)3H!031s zz4BgJ8lOo&WZh*Wy#wmFIvEcST)))N{82a@pH$;QtJ(SR@Qfh#+_uJJ?Gfc^4g^}^ zx`$_{7l5veC_qh=#k6Bg_@1((@XeiNHr$kjs*+*TIkw1!jXSXe9lgAZ68BMYFn}Q` zB`IZ46;PIxtmLtG_PW(FF$F?}EtDhCjD-Hgddo7)CUOgEu8hW-)0#1^z56weh%kGq zF$_vzs@Uyv_1Jsb2^B1sW+Go$blz@hvRHa3fTz=nEP9=SFf4~B(v=59s`r(kLkd&q z86U7UH~WW`@Z_W#=3346@ZsV1i{G2}8^gG@oHAaltsNfjD;C}#PHD>cfY4=Xb71ys z+{?8qxr1tL9-=*x*Y9vg)cR^CEtMe%**e17a;8(mv?-tlbm7z}+#ayA^n*Gk&`n(1 zJ)-1c8QZo%3ErAEG0nC+F_vpIK(o_>%I>tsPZ3&4WfF2E1Cdb$;{~ojTCYI|wzj1$ zZ?0mK_YOO~q;I{bEhF(NWlLIlmn{Xu8FOV<*T}T%>l(^5+0QeXpG@5w9CHWydr+Ba z!z4*_lcfohd-UiE0E?8cO!QN5N>X$JBJ0nphg!lRj1LbFhb4!-YnX1N_$1}5X0v^0 zd+ncj?W>nB)}GGDlolUuuhslkyFebVj*ojCT$eCBK0Yit+PiZVN_6Inbce~Jv)3c4 zTHI*cNXePfS6jxY16sykyf}FA0v5ht%$s6rkELV>$8-nde3B4hNB@eI#IsM5lbki3CJ0-8B{y9DqsEgI3X$rTwpB0fueCf*bK2S4G6#@@Np*4EYppKZsiKhaG& zMc}T4y#h1@2S?~PnEmom?NO!Bf9v+}cnpK5pT@?=Cnp!jg*H=jyYm1PVVgy=m#<#F z{N|gN-~9YhWk$)>4j-MJISbrz<2%*bk4A zsVs&f3*@&4C$E`pPYtj=eP(D=ysqmf9I*Xh#?&;~c6Ad)149ot!;BkAWIluRQEH{I zND0H{*X$(cv__ZWNH6`Z2Rex44K7%-4lrB;(S1zpPzsDXl=h7a<~SDDUcTTqFCGzCFyBx6-o1B}7p7s^~=1i(XMoC|g^n z`$vY`vb`i{Xj^)_-vO}tAYs2+ z+uaqrU6@_Df1kcECJPR(vo|n3SJJV0tg@%G4sn#$m>z;|)X|s(UKZz*tQ$v7m4G%( z$`oC_*$mWkvzhziV4(jF+?Ko+)+NWi)8**zhdE(dW&BgY)#dPFeYZR@|FHJu;l3Pj z2m}7%;ZFyKA)`nMfF0A0w`&I{+pi2%cu7wH?#s3P+){aeZS8O^%G+!$P682m_*1`d z?;f#UuGuxB9#E!JtK{PYLXV?AA}e}YgC1EbB4$^1j*ci+U@!0C3C?&A4qnjnT(72T z)Wr!HURRG<>FVeR1b2t-(I<=sVJ9S(L~6A~m7SCA;uz<6zjj*Dch?g=uHK;6 zC;37`cW2Mv2Bu3p|L;0Q{|a5>0mC{x#T~ZC9u4^D-QUz%9gW%c^UUL4KwE5sNZsNN z9=ahsnECv3wvUHgHxY4v(#74mbN%}DJ9qB1TkcryeBuy9Q5YmoRmLH~5%Ib(bS_BI z-24~S!xw9nwA5?A^D4Z@$B-!{^6rq2)4C- z=pB|nl?MEN?`=mL*PG4l9-LH&bD#wx;7zEiRw?T_EvHDHfTHi#D+#X;$h2o?fCZ+< zc<@#Y=&iC!^|VHb8F~XCvARg91G#G?GBrJgwl@M?1*!=u%HxE$6-sIk$aO2l9c{$j z-P`5pb9QxiyFJqjg?0V8whr|hrnpdIo7A@;{-JN;AdbE{HW}T2{A2|u#|*~RjSXA} z45U0p%0hs2Kar8>2Ja#$xO2VjP8V6Xjj&b-2!q~1DJIFW81WN1;_ABPAmhq2GqX>> zINUxcs(lzuy)F2L27chY)zoOReb`~O7prRwZC`#Xnmu}6rc7pS?dfw*2iewYwtpYV z$Va!jxaLmIl|x5szEY8SyS>{HOzD-~-3s>3%VJPeauwE=0I$U^bY@y(2f@Mb{r0U8 zZtZk`4`<*wDaV3<7*WhAwlgo1FgTcMR2Sigd*rp%TJ=cR*GqF^zl$Djw>Y=3R9MgH z#dS!8q}MT^N>_UWgF6JYC<#OP{YmOE7WO8e5cK{6Z4b*U=ruthD2wxYbwx>j9*fEM z0-rdb;775n>rPi2biv4R`w2?#ON2q=*bgZ8JG$%+!Rho5MJFb{e0ErSD7w0>EqJ9> z9smF!07*naRBc?xt&eZDqCd}Ovr)va?E@3unwJ9Ft7=6rqIC4A=zo10BnTW{UI zeXF&(smbc{NIF@E0$GkQy_X9R=OVtK5b>K11^Pr|lK0?*ZR<8@7+X$a%$ySYf#p#k zuNt;x6Lf43U%gS2?IKK^zXb_HgPpdzvAW6N6y@|?eO+52Q>K@eD31k*Vj*-+C#)-B zLLE!}$j>*_MfmUX@}l}UMpzDMm4A5ri^aud;PBVr9~vgBo?sHNASIP?Ip88_g{BW- z?VUTVP0iPvt~V3l4i4Un+>5Ep`m(AnkIQ1$9s4c8OR=Y=^+*5y#ful^QpVFu_O!LM zm@S<>y?rjqLF7sehJ9Jjd12qRD*D!mEIv$kciOw{ot+4l%_g(8y=P3O9H+XM&r6Q3 zo;w_WN2H8c&nq(4TK5am!t-551dMS=9NnB63wkdYbEfP-wr*bbiPPHF?(PoGA1R*5 z=N@b9fBc+?K=LsZ5mL*DXnU347#w#G>bdI>14$PY$kpmcN5ods*|}1xlwBZSUyoDj zh5kn!bLPt{k3T20{Yhf#^T#W{US9sERcH~T`HW4pLJH@8WIctvU@+kNq^pa&ey5fG zF%7^+tb}coW<_(3f>I7%e;4|fDXSa)Y_jY%*+d3)9?(R*Lc26m5C{GSM_?~w1Tf3y{dlkx{ zW8VJmj$Ww%A;$fKy7KLbp@&_cIj!povyD3J?IU&ybA%cg5?*NHv*j+CShk-2W>b%$ zq@RM6#A-f|Mo_lR5qp|;zry^qUgYG^tS~1X|ZdiI$YnaN~+M1F3_}-oX zk>qLY5Sms}Y4owwW(T0e*3I*R%OSF#lo#5~H!K3>OXNV%yJhx#V|cCs3m4vEESd9Z z4WfZ~%X+cML@UW`%qV+7!aakH&xK?xn?!`k6rQN56`X$M^Z82tL8ZLKCh#Z-qA7Hr zr4)p>E0oKz-8@UF1y#!xi|b6f808o>3ki$FXHWo1!M5l=Ti$@k3LA=4Q<;)NrkxH1 z`rUkcb2HaO!Kn?Fy>Y{AX|r)H=Jw`xhp0|cX0k`uQ66+*aM9~^`Unrz;=}6N+Q|Vx zZvXh?;50WE35G_bB4c3R%FS>xa!jd!7sA# zc8D=H*`0PeyV@+>&d|C+5?IaF*eY!-(4biMh}rS2dC9W$e2V!Fw7+7FJlh-1oEOrp z$rLJL6v^1z6=s zGKF`q7&E#LkeB={6dpMA@9iO&%tTGW!pE~)&1AHs@Sb9wst|3b#nK^gGaT8^An?z>=)%x zzu(Dq@m-D)3dS`p<#*gLSvW|0Y0sZMV}b0@s4bqc?CdqpbWT}ICv!LQRbu&skmYib z?uZr48xZ#*PCJdwxyhI;V}r7)C_n{ldW{(pb&#%3V#91IwWuxU^BCY~YC@3mP$6h1 z!m{F2rU3QmbrlW$>)4;DX6s`(na5ZUfwN=CE@Ciknf$s$KLW+uK|lg$x3@N#Oid

yG9+WG4`_)HZK6sE0N9QNfKEKcBwAr~nkNaM-sQ;(@ zsyyhv!}YjBQdWiA;()iV&1%FkmPlMMycSliA@C5*U&jtSZG9<~&0+<7WGXS8z^Ydn zgZ45a7$*0i1*9m7QPE{F?(rf$)MYHh$rDFG55OW6XR?`JLc$G`($mBqa+-!MXzOf1 zrL`~1ai{63yPloMtA#VZiqA(JHO(N40cD*DLid;x5*%&m(GYiJrUPd4? z#`>K_)L7Ki6CD0LAz+5a=wp1N>8Yu)DJTS$=(2%@;R3E}8>P%bA%zX-Xe9?=Vh0rz z@$=}#XWNp9VI(3Wf(t!07}6o*-egih)^<$fbM0oc>HS7in?0JIE$T(eekDjt*ty%c z9O2xT-_C8#UAT?QL$lB!ODZsV9>$0Gq+`}w{09-4F|nMdxyYx=k#1TPB-tk6zUJ&yRV>u<-kbAo}IEWhf^c2q1JeT zu??cKs6#_3?K75nO;1JW9)|kuG#l=kPDs-uazdgfJ7S68KhdQm_?71}pl3MrRR}-P z9-O>jMSbn&^6|HnF7TIMjP2FuCcBh$0$>5WNwN*#W|UR5vq(7>&au8 zWyR@fiQ+{@nl?(0#$MwBQ2}&y>e%|a3^f~8pqyqI-Dl{_U8h@QLB*mTU_y3off8bj z`H+3Ve6cpCj9JXMLb-BEmSgw*_XY$`IL7vwuhMYqK zN_w(b&d1ZKq#}PRL7xXR*(c|Q{pQ@hFV`sHh39@lpM3ce&u_L54~|my8%-8o5TS-3 zk1Oe1Zbq4j&WsL?hKut>)V&BF(qt_9?vOCpg^*o+cm&fUhith2?Ae)t3Htg*39@PH zZ;x=NB4o$N6tijodVy%5BgBhDM0%nNIReXK`6+feO7LkZGna*UzEVg*OYn(mh)2o#W#Evngtx$FuKZYZT@6P0X(Dp(Xm`sWR&O(_afSdzq$gLm0Yke9kj zj(f$_X6vwb*d6w+t}a1Vh9&k8eg1)Pcve#8t|;8(1!n~<>z zh6ozl`@r5T7T$J=K*||PVU!>c=`Cpl?ux4KtW#dC#&wpd!E4J~l7ysYqmY6Dw3xq`%%GB+lVjUGtWPL|bHc32G&b@3ANvyE(OL)+E$ zTnWGNE;Ra!kk_41)9Dn`jFbEUcaN?8O2fs=7ca8j`}a(ZEu0Ya20cEXBu8h`x%nI! zIGs)_gMu8z)I@xCLY>L$mFnRiK<#-2bA6 z^nW)ed)+RVypYoAy2HBY!aPD@kur>f6I8^R47Q=#d~o>e0Ao-Wu!*7Yw(VdJh9lF7 zuX~>(hGW^2K*AHe7xe zy$M$vZFVNhJRn5#dd(#%p?j^>uaWO72=gM)vD2(Qi$bP&_NdHL3Fk@{-m zN-#uG1g#TW^OY(Y?Vwt#P`aZGhLoJXyIaiBmEWazSTg&_2xFMeIXq+a1mg|c@^GPU zSu$#bF|R3bb#mIVF)Skwj=4qgZakUPR>}|vux07f1a#Bb_ZkUAz$d@~ z=~q+PHsfWq>S;#Tql&E%r4=0}#qbm{u5}_|g$0GRHWqRAQ!bNr%Q&P+$8+SkQA6#} z=M6cn)<%PX8E>1Q67KO!en0l!&F1Ed^A9l~^pKLu`Qj{v^J0bm_WiZ(v$MBO`_1_~ zhHV)jFwZrJ!mC#my`o3~FQpf8y@Ki4lkLNkDw{vrKP7t>nQ&T8!};n{R3+|vZV`oS$UVd8J zr9b@H{@QtWQr)hMEPR8{Q9z>)n04#$yM4A_JJ2;LHZ!YHVp%(`zM(5~_6FmP$Lug1 z<$v@KlWD(X)%3bv)uFMHmkEuZLMs2++1cTROqLQKkR+BoC8m&v(F<8q9CP0d)DX)=T|%UZ^u*F=y2x`i(Eb+R(~?*`T^ zXO}nGuzyXjpxvenzbN8>O-)aRl_(UF2@*I{i_O${<;r^~FE*O*^!)W--;c#6E6IBKB^6D0GlX!k> zuUb7k0W&^(vrYH>35FF;v7`YerGLM8F#q7;gD)Qe0FdOKka>wDoShkK2r#>6^mqXf zP?JHF!QCHsVNRvqVV1qfRK2{zV$OV@vWqwuS_EN0^&XrZG9p<^!&;|mm+P!xZ8hd@Rwv%*p_Tes0no`3}c*}9iF{;MK9ZLPTp)&$ili^%#pL@ zLzVKwS&E;D;dF+RCY>?;n$E^6w`xT1{8lGhjL?Pxb)D}2kp>2`kfM}PERy?4E- z$#nIm#pxaR{&0A5GM$T41g|`-JRqAqqQCsnmtVrTWU=$)_S-q`H}Kq7-}=1KWy37K zeNaOgpjtg(1F0i9T zR;8Mnnub}Y2B#RQ6`At}++&8@!fOqxK-VAwq$SxGJzgnV%rBwKBp|JGZ6(-ACHrAkTt)8npX;>nWrkt0enK+YjedNPj9!>o7byj1#-9$!4AKl#Pli|rSzbnx=k zx68FgS@HKphWg{+8B31OwkhTtiSiqxxVyc5xP5qd@*0jwrhRruSMTZb+>eP?&sUC~ zKF9Ld(*xtI3TUYAo$CQ&u#{E1-)FPXV zB~!_iT3;|()WD*cd=Tb#btcQQQ$mRgZK0K|l~RdrlwZ!3R{pW@t6werioBSOS?4hp zwaF%=Hkh;%6LwN_;9!KeA=fSb!`mNP8ylLgo6*DAY47Rp_xgPQe{oXPitS)_6ZX3vTc+Tzva7Rtl#~<0oVA5!1kc}!hntXf7?F);uG>*0#u@8 z1iXi9hii`>?eBm2^m%dp$EEV~+R^?I6K8$RPIk}$0-|ts!ML$m=>Sf9Pn-&pRgpE& zt4J2T>p>`k;&|Y$0l024LLuuux?PxBtGc|3Y?TGD6eWeM8m4cu2Bqbl9oEB8)QY>c zy`!)6ozkyzoRod9VP&L}hpd+TUnm9J>Evjrc2bq>)nJ73M&OdIs z)O7u7qnWeZaS69?|7q)ox4ugc=MSPYle2l8*^zl4&;#e$YirM{PamzZ{f*x;?Ki*2 zgg;c=*q$Fngde?*s-u!TH4-^6Kq_NA%c#bg;I+#!3o5JAKMFp|i%ClS8)R zf%z?&mRwN$$&``k8hA_oIu#o12kN?6Qg)Z&tvE<85ei`Up|+%|<0(~1QpAbHVlrEy zyGmKZGKC|iPE3z7+>*^WvYYm}My&R?OH02kE&MdI@Y@~GFFf;fEi`E3!08v+0>e1l zzOKY%=~KzUwU|t8t!>w@Hkq%tao=e%n=W5&GMPBL($w|1iuLW@B+O6s-bue`A!yiBzy;f^3U&;uM42h*3}+14R&- zZ4t>}*+Bo;T_c*gU44O&D9M!cN|c}7!!~rn#dUQ>!7^k92k7t1>*!m^vy=R-RSgJH z*7M}JkXoqy7s_=PepKdVP^}z%BXS-Vc-P+p8 zHie?ynT6fMZ=FZf-_kWWqa1?x!Wmrmkf;LucAnDlp%I^4+CBO&#_9o<@v=jQGd3$t z7L7zA1{}a;DTXm~l8r$QVBRqUaEXPv=m||6kYJQ(B8jS6jpKq< zBQ~uXGP*!q9HHswH|vpJEX@5@CmK`Ki{jUo7SyJjmk*p&C=n17*H~*u*`MU>y zSFN7V6`;)a;Gj5{DIUH;&&{`Hc+Th@O3t?5P!2)fdw2qY338J8S#3s%q6Vi!#C`t- zn|3%cn!!%ld|5q);W;=3oHZ;t21KYojZa`36sEvJp&(ZAAwSDZFDxl6A0x~q##BPb zcq%o{h!=(%>O;}1%)szl=rvc$mGbU$y_8v4*C_!*9ieP!MAyX$**lAMPKHO}y)Hx$Ikc2#yTo{uBBA?v1Ri309I zXq+8EGVz3yHyAs;Fg1o3;(Yf}{Elq|u* zVnk-~TtBdHjrOWArUa-^q1D~84*Jk7BmwP~e zJUMWDmJqj6-QQ;84a~j<@S-|HA6N9g&Q7kgmk*5$jd{pAMrV)y;vJh93&?B#X*PN(sY$s6chc8Y}B-+ql0&T z)Y011_L1`=LWSAlLxAlArjb+0=i^0kM#_Nq(QS*?x|j8bLBzJ7?k-IAb@vj(3 zca4?;ne~J7I{Nlop1@3fh6fMPA?@*TY~g<8snIn zmR8W&L1AqXl7sPOwwf!?fPvn?wn`$qR4Boi>nJc5wH$>(6kydHGcYmcNhPHu@B5)C ziCx-EDdEy(`iI~EC$b;3*f`E=^CSxK`T4*3(GQ1z7@ix-whSiDqJX!h#sPML8 zd)`k&G3j}U{+zj={&afUeRt}A9$T**yrsNv|26VphPz~00P`WbBjdBP^Qhj>&sQp% zT0A;>`V{jctd3C6c~37)F~0@s4uZT+kxlES70IUbLe!Rm8o6+&&(+J^c3KVzAsj`B z;+(`Zc0~o}cHyOTE?tr&wFoGZFqMhEq7d9h5M z9M6$i;k$AA?>RNiW&!2 za+o+LQ-LNtB*I(P2_|aQL&moZ=K8YUnn1Ad=;*nNvro@W%}w_P|BtEvxOZ@Nc=m16 zZlCin{KHU}DDVNLZwHl1JUlZrFfbaOnaJhz-P+O75oFvCPhT9c(}%+oBbHIvB1^J@ zcmPG3fKgQ>vj#k49yiM##>h?Kw14Y{ma01tga*HeO(7r*^3qaTQS!O8L{7U-3DwL} zBBP|jN}Q=aYkAGkCyp~ZpzCRMsi0(2CHSgJZ(&-Dp6c|THbbV(!My4W%S$Bxpu3xF z3)2D>8qFry_J+x7wQ@W^Gx2Z#>R<%GPoFCb zJ`gc6(jTO+zbnd1>QYEfreqeLTxrxy~x3zTG zY&M>E`h3xeGUlHivP6a69G~WkEETRI;bM=qm&|62hdrzAua9(hba!{(Eqt|GJJ>#< z^!DrrZ&W zYK?C$Ofd{V)Di~+#`yxCcge2qy8%{27{mgzyNn+Mraj%=z06T&`2YYHx=BPqR4!Nl zh~(it^nZwB3(9~bMQ3s$S-zLZ<>x1Jgt(KsdS8wc=xUSW%6K?MR#j5tDRz@Ha;2+U z$|%VIFp38KQb8HWX^ZhV8}X%BCdZ`vUZKC6YiYc6@tuaYYbNN$T)up@$?ci=`@j6K zqr=wH^2Z%~FFzvB%+iDK5AiIIu$D)%64%JiRRlEVz4deq;6OxdU(fXP{PkGoh|=Tj z7r%#sdVv86Z~cMEbwb;pW3YOyLaB9H76e&(pt!Cqcg>c33A#mAA&C&R4Wgm`bKo2 zOeU^Y>n3`2&c|N8*gkym^TVTx*tbyJeYTG>%yzx12uMH%Mz3c^GJLrG0$=}sWzsl4X9NDo9mZH50G42s!^e=@5@o<~SwOrS`2U)^ zzMrqds6fI3y4F9?V?TznbdE$H^5|%yDSB zW=x`Z@bTE!*l`>`a8Vc!c13^+>R8ICwi)TFQO(%&v6?}BOa6=5YkwxahLR=_q%781 z`^UHT{p)^;|+@x`!4@g%9#FT|@5wF-OQIw~~cQsdA76yjAEy6=z}Bflj`*`Oda0ozqbZ;^A6;yURUBzj!qBEsPaU1De@KO{nSPybOO+OpWDmaoAU(4IZ4>QJJ8qB+uPfv>+kzeFa7SFzd!rd*|TT+2XMX4gmlw>E%?oY z#Dgs?$gCzS6{`6QTS6Y7yi8qSim-+kVOuNLiiGZuxq7WgxoPv1*1w7{#%(Wzpmz|`kP6}C2-X(4) zIGDsPnSkXkqb%8`=D)z`nB$8nvxL<5k>aL*xO8`ZUc!}lS>K-=vi8F3R8}dbc@$0Y zl1|97;tj}33gCXtT|?1}*~^?(xEabAVp=-QJK{4hn7dhii__P|Rdv=et~U&{cXYJ3 zb#%4&4PPGU?0E0*df$WZ_Tr#%%4stFOYn~GW_D{USxF|h3dLe2SFIL`Rh|$@9{lj+ z$q&^e#&)GH%e?5Hj;^Q15FAgxCm+2=^uGcEL?{41q z-Fy)Cg*_I@tvu2+s@s359C0w?3kYy+cdbnVcCzdSPnp1|fc;$D`rT;f&Qrw;QJyA< zr~e2IroUpFB1Q0eRkz8CHGvUTR>GP^b`V`>WlDLqIk!)^He^K!(Jvu2vP|G|vBfp* zruHJ!N*D;+4Bzaj#dhGg6Co}uPIWR`Dlkj6Lw`qmdq-F2d)?PQZ9mh|)6+wx15(^! zyKlsJ?WWxm{${K2=Rbd!{JvPBSD~1!6iXFCwqE@okhl8NPmC_TilsskSKSoo>wetN z?^m}fM~GA9=Md93*g|Yi2v*XG*F;+awp^=yOAP-mvFN!OG>zO@RA1~wl+`FV^j>~n z=Oj$EhlFI;iYRCOV*a|#8we=gsfh{t zJAn{^>X?$G*_0ZnLrwXX@i`x!RzXM`Ou8iflN zj;82S;SP-p&4@u1oX$z(V1H*jR{y*|Y3S(fMmwyl_w9j;SB#Qn(i6Nn=LsefNklS| z+X7y^&XLGlXXc{eNG~AE?FKAs0OFLc{fNFC9}3rCdlo8ia`-D4i*#1#!fOahtx>F3 zD&H0>iCcD`-C+3i=FNCMzPJKM$UznN6v2f{=r^z^pJEw&ihex*I3WYFXe}Uw$#Q5F z{TmxmdY&^gsIFrQ>6jx#5X!dcX;9idb9aY+W0tVUWtBd$swydB?IRT)UD$L<9Z~@W z9`k^b#(FcNYbu3{3NiG9+oc%TXE3Ivcfj7vPV0~eDXuCT2hc?58yF$}c6D|4cJ=jQ z@%W`V->uI-A0Lr|!P_e<50c43wNR=gi-kh5T&okVIC?2!uU@qzx;Ul(1HL$|#l{RC z@u)(a0W9eP9({zbGN0mbo2Ma8A`t?KxbsY8tXpzA32d-kMFwmQ zctbEfQ<)Z7)qEaRTZJM}^|rd|T~#BYl#-$kS}G0E1-9%rPp7xj+tKZ(vF#{a{M%`q z#{*d^h^e|@Y-dfEh_`)%!$bXjJ-waSu-x0#+jnv3v(K)5HiG=?t1#tX#Lq&Ba4l4d z#ai*(da+O>(26Anm$>@BC2@y#iLVbTQ6|AdO7+?i6|%(HW`lFB@*A~fT(LI@2R;ab zwIY4%m2mLEcUg~D@!3swUpD{p5xWn6h9W0hZ^HwFT5q)ir2>l`P6niOC8j&7OE}}lAzmGyGHMOdy zLc-^SZB=lZV=n_neA4R#ZtF@SqHs*y&9MvaW~tnx6nAoXptE~m*wEk8-`(5W&91Pn zizds}bLTG_EFMqrtME#WRF(vR0Ie`xYu^@Y^Z?gMc8lmbR&gXz5Z95(&aHPeXib|P`Gm88eMLV*geN|6%LGJH!% zwOYAQ;@wLH_Jsh|@(Ipf%IF1Rwxq$qijyryw~4Op-|)B5s>^ECT5&6zz2mdf!=l=y zDM=2;(HqC*3vlQ2tt6Br;0m)gP7H9oK*WSmNscUF2q&_fM(Z%8rc+BY*S3r>+Kp@* zM^JOPWQuG`z!7j>pWz5dpGZYWB2o%WW26JbeHpjZr|CN~XH~!l_dc;S6@?QTn>`rf zD9;MVV$U+WF@Y|Q(c{_py?d(7IA|Eub#!ziHy9YyQ>AMd9zK8eym9)f!7wZZ7xN^y z2gKW?AT5DfD?bOcWi0b3R!Ju+g?gpV;L_`)QEHr&N>I`=HxGesqbaaF{u@bPwJr0H z03RusZRNv0kJoMwZ>SqPk9M;0cpe4;HZ^jCT-*cos%^=|C*)wQ|1QrxMVHa)UXH3N z=E+ioBvEq7KBYki*@cq-8L87 zy=H8Fkr^n<8u3RX1n4P_Qs7bHy>oEy+~ML3&E}ScRe^*cFz1$Lu3ODBlQL{< zr4%K!DLKSz0bt*!AC-nl2a07_k;fSUHUJTOu^f+eb{nIs(WlXEzMB@unU7Jt#ba>} zW?rYUud{>RbUHST59kd>zSq$BiP7W{m(@mr6Ar*kjI;G;kCu)`VKr z>&R}QwZz?{lan&@5ntKhI0n5XR0YO@yn?n!;0_9vT=q`b=krm;5YF=Exc&TnxQ8)Y zQGIp9mv+B`6Ss}vg2Mw~gsk6E}|ugD%Apl zz4W5Yfr{HBmSTdIzp8Om0%&5^4(t?afHp6^H^m_&=VA>Mbk%Aim)J@Kv*C>({lMed zeEy(9)ZNQwy*u5o&uX^kSIrBgeEDtON?CuyzJUp7M6dWgutvGE(XbUPjQKIhG$y{d@9qh{xYL!#1Oa5_&$0xI!eC!20!><*zm#d<)L#!SDp5` zxm&jv?kD zx9>0iPC1y(kK}5}Nyx%|=NBszC6uwH_sbuJ|ddc(&b8-}i0Zp?YK#cVc#fpoZ*U+tobwK7OZXj+#p#HowJiNwg4PFiEF|82YC#dRQJ&f zjfeLSNEdvmSR}Bj%3j4acIC>1-Z-HjHMO;T2o#41H5Xw^u`C^X9NT_M(FBibYC#Z} zf}SWaI3uHS&E|AYOAZGb3i1qTv5nJYzq}ktM;6v0whv{7mc6$8+-f=ZAf;WVl;*OlmVyhqaN&J?RmRrU~u4qal$e=VlrJFv5eSn z-(I{8XF|&&T0Ov4qpBE?W+`nnU}hwMnhilFdl{Orb@i954 zP=UZgWSOuf+Qj%@mnLi%C}m||2+!=b&eoB1*&w{g5nMBp&Cdz0Uyh^}(y2AvL>NJ` zfE0N>wMPF%(z}q>-T!*ZsO}KHJ1n&sjJw9LvYmHUkw9n|$0otYHVn#DR& z2b({-J3ks8J~wPI+3j}O;|ud)0~KY-pOWmSsa9W=gd~V2EmBiL6M+iYHh$}I5g$*4 zhYtM%f)~>f+`>I>=>z@JM21!pw-)1UUb~MgJu>@y*;r6RYucw}lv%saVwt4MDWFV_ z>8<8bvw5^lhQR|z4ulP{mgJUr7G+pbjY2CUYXMS>r5W5f!tDlB88+_Y*lgFWR!SJG z*R5QdEy)if3)n-4oe5ahM&Iz^8bw4(VIyhWo1EGuN@^hRZgdwz=a`U4t3248 z%2ZNOZCNGSE@RpfEA+jx@lq#{?QHMtdmo`}a?)=9{L|0>puzE$NaUXI^}aa9;SB4D zfI4AOs2}l>*Rh~$t$7MAax2QfSP?{P=A?0WcXbqtlyf*a8&W+bxNb!5FeD3>J50klqpPgc679NcJ&WjwY+ow+_}pmQ>Nehg273H{AV=#q<|iu>X8YT|)MGtx@Boqm;l5DjWd+ zvG;g$GZwrb4=P`NIsVDyoEi*=je5QQ(!{h)8k>~#7qA4mZHbEqQPy%Y;BZkMMv)|n zCSZ(mPr_s&aF<|m!Sn3Lgf9g%r-Q9`UzjB{awOZ7L{%^%VgN-0g+QDV-F+BItpnQs z=G`9jzuUODbUD4-qA5?hJ|d;UFncPLiYTE7X#jwYP?D@F0WSq$FJEV5=>@bM1H;2Z zL+|#yb@u%5HM{4=jjw{?ukNfQ5>F^U%271KO4K@+1oX%w*J_AE9B~xcY;b=-qyXUL z8+5tlb^4pvyxO_J5fDc|^X$&QVfBrg}jnh`) z9G$Y_^pYxPnU`9KHqS#DL5xYewzdX`I=24sx=g}!jhBMQUp9|}y_YA^UL8ny&IeU%7)#Y!%>0(T0JqHf+A$8|^w5p{h0`jv6TD_eeV z4|^_M7&DuV<3|0sbL`RuU`tU7)@6DpUJXETLXL7Q_J)?yx9nUx-bu0Z7_C? z{!obc>vhXc2yH<5a&9&->zy6$?>N)0>(%w^`p*xZJNM4V!z0&j-1z4kH-mQw+gxrd zxm75ky;v$j4jPaID!w4QhoYzzT^FIFq!7=Wza8FiVOu_x3GO0rl2JnkA(=~{Yp|KU zzo}tgd~9ZB)@Ym@9UGf4n#Kbj#pkix6=l+5(odL2Nf9jLAAa;v8|kO$a^Xl9a!YRk zUb?78)n$s)MB8PwUI3TN&r{QgWq#|tgaeBi#|(+?gxQMZmpvp8>F0BoM}4qB2*dr@ zv${@k42jt~;@tW+KCzxUWi8KNrU++$>R7nWIF3uzjmj*W25x z>+9}6+oRLHGj#dt<;x@2JpUTbKgj2{a0OzaQmK-_`q z*k-biUbt{+3~}tzsKxx@g*JFYxqCRnqd4pWF(>feAzHCG(2VT1;dHNgWOhOi~F}l zUSo?x@-ho=iSvaM5v^K%u48^LpGLGM^S1FueH)EK@rKKQs#GClFd@CSmr(*fuVvD! z#H2B!epa;`r;JvKe)#uPb<*k$TsND?^k!0qG0A!1!v6#5Yv4ZfiNAFK002dLR9JLV zZ)S9NVRB^v0C?JS&`{R&%uP&B^-WCAOwLv?(KFC9Qn0kpH!#*WFjPn`$}BFabSSRO zEl4cMOwQNKFG>dhd=n4$VylQs0000mdQ@0+Q)y>zVRUtJWdHzp+A~f}Ni6AAAAA@IQg~‡“’’££§£¬³»»¾»Ã»ÃÑÇÑÙÙØÙØÝâÝâÝåÝÝÙÝÙÙãåÝÝååååÝåÝååæããÝãååæåæìååææÝååâåååååååÝååãåâåååååååïåïãïåãååÝææããÝÜØÖÑÉ뤧­µ³¾½µ­­¤˜­½¤†oeoo{om“˜†Œ’|oriiimthho†|K^WWW|||}†}}|}}††|}}}†‡‰™™™¡¤¡Ÿ¡¤¤¦¤¤¡™™™““‰†‡‡†††††‡}}‡†||t|†|tttttnht|||tttn||t|}}†‡‰“™“™Ÿ™“††‰††““““““”™™”™™Ÿ™““ŸŸ¤¥™Ÿ¢¬¥¥ŸŸŸŸ¥Ÿ¤ŸŸ™ŸŸ¤™™¤™™™™™™™™Ÿ˜˜Ÿ˜˜™¤“˜™¤“™˜Œ‰ŒŒ†o666/6;IQr{SQ[[ntoo~™££x‡™§µ»»»»ÃÉ»¾ÉÑÙÙÙÙÙÝãåÙÙåÝâÝÝÙÝÝÝâåãÝååååÞåæååÝåìæåìîìåååååååâåååååååååâååÝâãååååååîîåîåìåæåææÝÞÜãÜÝÝÝÝÝÙ»³³½½ÉÆÃ½³½«µµ¤£³«£mkxŠ˜£§§e]]]Witt|`x|]SSVSS†}||}}|}}}}†‡†‰‰“‘“™™¡Ÿ¡¡¡ŸŸŸ¢Ÿ™Ÿ™™“”‰‡}}‡r’†‡††}|†|†||t††t||ttonn†ttnont|†t|‡†‰“‘™Ÿ™‘™™“†“‰‰‰‰‰“‰”™™“œ™™“Ÿ¥Ÿ™™™¬­ŸŸ¤¥¡Ÿ¥¬¡¬­¤ŸŸ™¡Ÿ¤Ÿ˜Ÿ¥ŸŸ™ŸŸŸ¤ŸŸ¡¤¡Ÿ™¡¤™˜¡™¤™Ÿ˜˜™“‰Œ†eW6A6666/6@J_gggxx‡‡†x†¤«³»»»»Ã¾É¾¾¾¾¾¾ÉÑÑÙÙÝÝÝâåÝâÝãÝãÝØÝãÝåååìÝÝæÝååÜæÝãååååååãåÝåâÝââÝååååèâåâåâãååååîåîååîìåìåæååæææÝåããÖÝÙÑÉÉɽ½½Ã½½½½¤µµ­­µ­­µµ­­§¤˜£¨½Ÿ‘†ttmm†xmm…e]]e]e]h‡†}||tr||||}††‰‰‘“™™Ÿ¤¤¡¡¤ŸŸ¡¡¡Ÿ™™‘‘“‰†}‡‡}†‰††††}||}|||r††|tt|r~tr|†}r|t}}†|}†}†“™‘Ÿ™”™“‰‡““‡‰““‰““œ™”“œ™“Ÿ¬ŸŸŸŸ¬´¥­¥¥¬¤¯­¥­¯ŸŸŸ¡Ÿ­¬¥ŸŸ¤Ÿ¡Ÿ¤ŸŸ¤¥¤¤¤Ÿ¤¤Ÿ™˜Ÿ™¤™™˜™˜˜˜šŒ…_M6/6A666<<6Rgg[g_o‡‡‡†“™§³³»ÉÉÃÇÉÇÍÇɾɾÉÑÑÙÙÙÝÝÝÝÝÝãÝããÝÝÝåÝæÝåæåÝåãæÝÝãååååååååâåÝÝâââååèåååèâåãâåÝïåååîåîåìåæååìåååæåæãåÝãÙÝÙÑÑÑÉɾ¾³¤³ÑÉɽ­Ã½³¤£¤£¤¤˜™¤­…‡™{{x††‰x`]nhehhe†|}}|}}}}}}†}}‡†‰“¡™Ÿ¤«¤¢¥««­¡Ÿ¡™™‘“‡†‡†‡‡}|}††|††|}|}|†}ttt|||nt|r†r|}|t†’†††}†™“Ÿ“‘œ““‰“‰†“““™“™™™™™“Ÿ™™Ÿ¥¡Ÿ¥«¯µ­¥­¥­­­¥¥¬¤Ÿ¤¤¬¥¡¥¬¤¥¢ŸŸ¡¥¤¤¬¤«¦­¤¤­ŸŸ¡¡¡™¤Ÿ¤¤˜˜¤˜‰tRG6<6AGAGQVQSei{xtoort{t‡¡¡«¡³»»¾ÉÑÉÑÑÑÑÑÉØÝÝØÑÙÝãÝÝãÝÝããÝããæÝæååÝÝæããæÝÝÝÝÝæÝååããÙãâãÝååâåâåååãâåïãååïååååìååìåååãììæåìãìæãåãÝÝØØÑÑÑý½½µ½Éƽ½½³£§«¨˜™¤««»·«¯«·«Ÿ™˜˜}m`ei``]^^^‡}t}rt||‡}}r}†‡†‰˜™Ÿ¡¥­¬ŸŸ¡­¦¤¡™Ÿ“““‰‡‡‡‡†}†}|†|}†}r|t}|}tn|†|nt|not|’|~r|||‰†‡‡††““™“”“““““‡‡““““™“™™Ÿ“™™™¤Ÿ¡ŸŸ¤¥­­­¯¯¥¤¯¥¥­¥Ÿ¥Ÿ¡¬¤¦¤«­¦Ÿ¥¥¡­¤¥­­¥¬¤¤¤¤¡¡¤Ÿ˜¤¤¤¤¤Ÿ˜¤¤†tnQAIIIIQVJJVi|˜‡~£´¼»¼ÉÉÑÓÓÑÇÓÓØÙØÒÉÉÉÑÇÑÉÉÉÉѾ¾ÉÙÙÝÝååÙÝåÝÝÝÝÝåÝãÜÝÜÖãÝÜÉÃØÜÖܿܿååååîåååèîîååîåååèåååãåååååååæååææãìæããØÜÑÇæÇÝÝÃҟ™|noom¤³½ÉÑØÙÙÜÜÙæÙÜãæÙææÝÝÝÝ}|††††††}‡†‡|}}|}~||t}‡||‡†‡|†~|}††|}t}|~t††}t|tttnn|†|nn|t††|¤¤™Ÿ™Œ||†Œ¯¨§««§¤˜¡««¨Œ“˜­˜¤«¤˜˜¤˜Š˜£¤¤˜Ÿ«­­µ­­¤­­¤¤­«µ¤¤³­»³µµ³»µ»­­­³­«·­µµ³µ³µµ»³½»µ»³³µ³µ¤¤§¨…|]VJAII;6IA/AA/66‡£x;[VagV_g__]a{«´³§«Ã»ÃÃÇÉÇÒÓÙÓÉÇÇÙÝÙѾ¾ÉÉÑÃÉÉÆÇ¾ÙÙÙååååååååÝÝåååÝãÝããÝÜÝÜÃ³ÓØÜãããããåîåèåîåîåçîîîèèîåîèåååïååìããååæåÝåìæãæÝÝÖÒÙÝÑÒ½­¡¤†š¨¤“Œ˜«½ÉÑÙÙÜãÜÙïÜïæÙÙæÝãÜÝÜÝ|†††|||†|†}|}}|}t|t|ttttt~|tt}tt~t|†||r||~tt|†|nnoooth†Œ}noot’†|“¤˜††¤Ÿ†Œ¥­³«µµ§˜˜«­¡¤­¤˜¤¡«­¤ŸŸŸ¡­¤¤¤¤¤¤¤¤¡¤­­­­­µµ­³¤­¤­«­«µµµµµµ«­«µµ³µµ»»³³»µ³³µ³³³µ«­¤¤¤…}mi_R + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Audio_xpm[] = { +"28 28 6 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c gray90", +"O c gray25", +"+ c gray50", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXooooooooooooooXXXX... ", +" .XXXXo OXXXX... ", +" .XXXXo OXXXX... ", +" .XXXXo +. +.+ OXXXX... ", +" .XXXXo .. .+. OXXXX... ", +" .XXXXo +.+ OXXXX... ", +" XXXXXo OXXXXX+. ", +"o.OXXXo OXXXO.X. ", +" X .XXo ... OXX. X+. ", +" .XX.Xo ..... OX.XX... ", +" .XXXXo ....... OXXXX... ", +" .XXXXo ....+..+. OXXXXX+. ", +" XXXXXo ...+O..O. OX....X. ", +"o....Xo ......O+. OXXXXX+. ", +" XXXXXo ....O+. OXXXX... ", +" .XXXXo .+O+. OXXXX... ", +" .XX.Xo ... OX.XX... ", +" X .XXo OXX. X+. ", +"o.OXXXo OXXXO.X. ", +" XXXXXoOOOOOOOOOOOOOXXXXX+. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Blank.xpm b/elpa/mew-20150813.2354/etc/mew-Blank.xpm new file mode 100644 index 00000000..369bb906 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Blank.xpm @@ -0,0 +1,40 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Blank_xpm[] = { +"28 28 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c gray50", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .X .. XXXXXXXXXXXXX.XXX... ", +" .X.XX.X.XX.XXXXXXXX.XXX... ", +" .X.XX. .. .. . X . .. X... ", +" .X.XX.X.XX.XXX.X.XX.X.X... ", +" .X....X.XX.Xo..X.XX.X.X... ", +" .X.XX.X.XX.X.X.X.XX.X.X... ", +" .X.XX.X.XX.Xo... . .X.X... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXX.XXXXXXXXXXXXXX... ", +" .XXXXXXX.XXXXXXXXXXXXXX... ", +" .XXXXXXX.. X . X. . . X... ", +" .XXXXXXX.X.X.X.X..X.X.X... ", +" .XXXXXXX.X.X...X.XX...X... ", +" .XXXXXXX.X.X.XXX.XX.XXX... ", +" .XXXXXXX.X.X ..X.XX ..X... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-External.xpm b/elpa/mew-20150813.2354/etc/mew-External.xpm new file mode 100644 index 00000000..291c3ccb --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-External.xpm @@ -0,0 +1,42 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_External_xpm[] = { +"28 28 6 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c gray50", +"O c gray90", +"+ c red", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXXoOOO", +" .XXXXXXXXXXXXXXXXXXXXX+++++", +" .XXXXXXXXXXXXXXXXXXXX++++++", +" .XXXXXXXXXXXXXXXXXXX+++++++", +" .XXXXXXXXXXXXXXXXXXX+++++++", +" .XXXXXXXXXXXXXXXXXX++++++++", +" .XXXXXXXXXXXXXXXXXX+++XoooO", +" .XXXXXXXXXXX+XXXXX+++XX... ", +" .XXXXXXXXXX++XXXX+++XXX... ", +" .XXXXXXXXX+++XX+++++XXX... ", +" .XXXXXXXX++++++++++oooo... ", +" .XXXXXXX+++++++++++oooo... ", +" .XXXXXX+++++++++++ooooo...o", +" .XXXXXXX+++++++++oooooo...o", +" .XXXXXXXX++++++oooooooo...o", +" .XXXXXXXXX+++XXXXXXXXXX...o", +" .XXXXXXXXXX++XXXXXXXXXX...o", +" .XXXXXXXXXXX+XXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Folder.xpm b/elpa/mew-20150813.2354/etc/mew-Folder.xpm new file mode 100644 index 00000000..7286a38a --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Folder.xpm @@ -0,0 +1,41 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Folder_xpm[] = { +"28 28 5 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c gray60", +"# c white", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXX....XXXXXXXXXXXXX... ", +" .XXXX.####..XXXXXXXXXXX... ", +" .XXX.#oooo#..........XX... ", +" .XXX.#ooooo########..XX... ", +" .XXX.#ooooooooooooo..XX... ", +" .XXX.#ooooooooooooo..XX... ", +" .XXX.#ooooooooooooo..XX... ", +" .XXX.#ooooooooooooo..XX... ", +" .XXX.#ooooooooooooo..XX... ", +" .XXX.#ooooooooooooo..XX... ", +" .XXX.#ooooooooooooo..XX... ", +" .XXX.#...............XX... ", +" .XXX.................XX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Image.xpm b/elpa/mew-20150813.2354/etc/mew-Image.xpm new file mode 100644 index 00000000..9110b012 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Image.xpm @@ -0,0 +1,44 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Image_xpm[] = { +"28 28 8 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c white", +"O c gray25", +"+ c gray50", +"@ c Yellow", +"# c yellow4", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXoooooooooooooooooXXX... ", +" .XXo...............oXXX... ", +" .XXo.o....OOO......o++X... ", +" .XXo....OOOOOO@..o.o++X... ", +" .XXo...OOOOOOO#@...o++X... ", +" .XXo...OOOOOOOO@...o++X... ", +" .XXo..OOOOOOOO#@#..o++X... ", +" .XXo..OOOOOOOO@@@..o++X... ", +" .XXo..OOOOOOO#@@#..o++X... ", +" .XXo...OOOOO#@@@..@o++X... ", +" .XXo...@#O#@@@@#...o++X... ", +" .XXo....@@@@@@#....o++X... ", +" .XXo......#@#....o.o++X... ", +" .XXo...............o++X... ", +" .XXooooooooooooooooo++X... ", +" .XXXX+++++++++++++++++X... ", +" .XXXX+++++++++++++++++X... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Octet-Stream.xpm b/elpa/mew-20150813.2354/etc/mew-Octet-Stream.xpm new file mode 100644 index 00000000..cc9eff5a --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Octet-Stream.xpm @@ -0,0 +1,44 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_OctetStream_xpm[] = { +"28 28 8 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c gray90", +"O c gray25", +"+ c gray50", +"@ c gold", +"# c white", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXooooooooXXXXXXX... ", +" .XX..O..++++++++..oXXXX... ", +" .XX..O..+++++..+...oXXX... ", +" .XX..O..+++++..+.@..oXX... ", +" .XX..O..+++++..+....+oX... ", +" .XX..O..+++++..+.@@.++X... ", +" .XX..OOO++++++++....++X... ", +" .XX.................++X... ", +" .XX.................++X... ", +" .XX..#############..++X... ", +" .XX..#############..++X... ", +" .XX..#############..++X... ", +" .XX..#############..++X... ", +" .XX..#############..++X... ", +" .XX..#############..++X... ", +" .XX..#############..++X... ", +" .XX..#############..++X... ", +" .XX..#############..++X... ", +" .XXXX+++++++++++++++++X... ", +" .XXXX+++++++++++++++++X... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Postscript.xpm b/elpa/mew-20150813.2354/etc/mew-Postscript.xpm new file mode 100644 index 00000000..6ccaa020 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Postscript.xpm @@ -0,0 +1,42 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Postscript_xpm[] = { +"28 28 6 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c pink", +"O c gray50", +"+ c red", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XX... X .. XXXXXXXXXXX... ", +" .XX.XX.X.XX.XXXXXXXXXXX... ", +" .XX.XX.X.XXXXXXXXXXXXXX... ", +" .XX... X .. XXXXXXXXXXX... ", +" .XX.XXXXXXX.XXXXXXXXXXX... ", +" .XX.XXXX.XX.XXXXXXXXXXX... ", +" .XX.XXXX .. XXXXXXXXoooOOO ", +" .XXXXXXXXXXXXXXXo+++++++++ ", +" .XXXXXXXXXXXXXo++oooXXXOOO+", +" .XXXXXXXXXXXo++oXXXXXXX... ", +" .XXXXXXXXXXo+oXXXXX OO... ", +" .XXXXXXXXXX+oXXXX OOO ... ", +" .XXXXXXXXXo+XXX OO XXXX...O", +" .XXXXXXXXX+oXX O XXXXXX... ", +" .XXXXXXXXo+XXXO XXXXXXX... ", +" .XXXXXXXX+oXX OXXXXXXXX... ", +" .XXXXXXXX+oXXO XXXXXXXX... ", +" .XXXXXXXX+oX OXXXXXXXXX... ", +" .XXXXXXXo+XX OXXXXXXXXX... ", +" .XXXXXXXo+XXO XXXXXXXXX... ", +" ........O+O............... ", +" ......O+O............... ", +" ......O+O............... ", +" + O "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Rfc822.xpm b/elpa/mew-20150813.2354/etc/mew-Rfc822.xpm new file mode 100644 index 00000000..dbc8eb4e --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Rfc822.xpm @@ -0,0 +1,43 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Rfc822_xpm[] = { +"28 28 7 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c gray50", +"O c white", +"+ c brown", +"@ c gray25", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" o.....................X... ", +" o.OOOOOOOOOOOOOOOOOOO.X... ", +" o.OOOOOOOOOOOOOOO+++O.o@.. ", +" o.OOOOOOOOOOOOOOO.++O.o@.. ", +" o.OO...........OO.@+O.o@.. ", +" o.OOOOOOOOOOOOOOOOOOO.o@.. ", +" o.OO.........OOOOOOOO.o@.. ", +" o.OOOOOOOOOOOOOOOOOOO.o@.. ", +" o.OOOOOOOOOOOOOOOOOOO.o@.. ", +" o.OO......O....OOOOOO.o@.. ", +" o.OOOOOOOOOOOOOOOOOOO.o@.. ", +" o.OOOOOOOOOOOOOOOOOOO.o@.. ", +" o.....................o@.. ", +" .XXoooooooooooooooooooo@.. ", +" .XXoooooooooooooooooooo@.. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Text.xpm b/elpa/mew-20150813.2354/etc/mew-Text.xpm new file mode 100644 index 00000000..4f2a6ff7 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Text.xpm @@ -0,0 +1,40 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Text_xpm[] = { +"28 28 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c gray50", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXX XXXXXXXXXXXXXXXXX... ", +" .XXXX.XXXXXXXXXXXXXXXXX... ", +" .XXX . XXX..X.......XXX... ", +" .XXXo oXXXXXXXXXXXXXXXX... ", +" .XXX.X.XXX.....X..X..XX... ", +" .XX ... XXXXXXXXXXXXXXX... ", +" .XX. X .XX...X.X.....XX... ", +" .X...X...XXXXXXXXXXXXXX... ", +" .XXXXXXXXX....X.XXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXX.......X...X.X...XX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XX...X..X...X......XXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XX.......X.X...X....XX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXX...X..X.XXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXX.........X..X....XX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Unknown.xpm b/elpa/mew-20150813.2354/etc/mew-Unknown.xpm new file mode 100644 index 00000000..9ffd260e --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Unknown.xpm @@ -0,0 +1,41 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Unknown_xpm[] = { +"28 28 5 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c gray50", +"O c gray90", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXX ....o XXXXXXX... ", +" .XXXXoXXo.OXXO .oXXooXX... ", +" .XXXXXXo.OXXXXXo. XXXXX... ", +" .XXooXX..XXoooXX.oXooXX... ", +" .XXXXXX..oXXXXXX.oXXXXX... ", +" .XXoooXo.oXoXoX . XoXXX... ", +" .XXXXXXXoXXXXXXooXXXXXX... ", +" .XXoXoXXXXooXXo. XXXXXX... ", +" .XXXXXXXXXXXX .OXXXXXXX... ", +" .XXXXooooXoXO.OXXoXXXXX... ", +" .XXXXXXXXXXXooXXXXXXXXX... ", +" .XXoooXooooX.XXooooXoXX... ", +" .XXXXXXXXXXX XXXXXXXXXX... ", +" .XXooooXoXoXXXoooXoooXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXooooXoX . XoooXXXXX... ", +" .XXXXXXXXXX...XXXXXXXXX... ", +" .XXooXoooXX . XoooooXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-Video.xpm b/elpa/mew-20150813.2354/etc/mew-Video.xpm new file mode 100644 index 00000000..34c2c4d6 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-Video.xpm @@ -0,0 +1,44 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_Video_xpm[] = { +"28 28 8 1", +" s backgroundToolBarColor c None", +". c black", +"X c lightcyan", +"o c brown", +"O c gray50", +"+ c white", +"@ c gray25", +"# c lightblue", +" ", +" ........................ ", +" .XXXXXXXXXXXXXXXXXXXXXX. ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XooooooooooooooooooXXX... ", +" .Xo................oXXX... ", +" .X..................OOX... ", +" .X..+@..######..@+..OOX... ", +" .X.+@.O.######.O.@+.OOX... ", +" .X.+@.O.######.O.@+.OOX... ", +" .X..+@..######..@+..OOX... ", +" .X..................OOX... ", +" .X..................OOX... ", +" .X..................OOX... ", +" .XXXOOOOOOOOOOOOOOOOOOX... ", +" .XXXOOOOOOOOOOOOOOOOOOX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .XXXXXXXXXXXXXXXXXXXXXX... ", +" .......................... ", +" ........................ ", +" ........................ ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-attach.xpm b/elpa/mew-20150813.2354/etc/mew-attach.xpm new file mode 100644 index 00000000..9413fd20 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-attach.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_attach_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +".............. ", +".XXXXXXXXXXXX. ", +".XXXXXXXXXXXX. ", +".XX.. . . ..X. ", +".XXXXXXXXXXXX. ", +".XX.. .............. ", +".XXXXX. . ", +".XX.. . o . ", +".XXXXX. o X. .. . ", +".XXXXX. XooX. .XX. . ", +"....... Xoo.............", +" ooooo. Xoo.oo.ooooo.oo.", +" . ....oo..ooo..oo.", +" . .oo.X...X.oo.", +" . .oo.XXXXX.oo.", +" ......oo.X.X.X.oo.", +" .o.XX.X.XX.o.", +" .oo.XX.XX.oo.", +" .ooo.....ooo.", +" .oo.XXXXX.oo.", +" .............", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-cite.xpm b/elpa/mew-20150813.2354/etc/mew-cite.xpm new file mode 100644 index 00000000..81d5f7b6 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-cite.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_cite_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +" ", +"................... ", +".XXXXXXXXXXXXXXXXX. ", +".XXXXXXXXXXXX...XX. ", +".XXXXXXXXXXXX.o.XX. ", +".XXX.......XX...XX..... ", +".XXXXXXXXXXXXXXXXX.XXX. ", +".XXX.......XXX.XXX.XXX. ", +".XXXXXXXXXXXX.X.XX.XXX. ", +".X.XXXXXXXXXXX.XXX.XXX.o", +".X.XXXXXXXXXXXXXXX.XXX.o", +"...................XXX.o", +" o.oo.XXXXXXXXXXXXXXXX.o", +" . .X.XXXo X....XXXX.o", +" . .X..XXXXXXXXXXXXX.o", +" ........Xo X....XXXX.o", +" .X..XXXXXXXXXX....o", +" .X.XXXo X....X.X.o ", +" .XXXXXXXXXXXXX..o ", +" ...............o ", +" oooooooooooooo ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-forward.xpm b/elpa/mew-20150813.2354/etc/mew-forward.xpm new file mode 100644 index 00000000..70637071 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-forward.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_forward_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +".................. ", +".XXXXXXXXXXXXXXXX.o ", +".XXXXXXXXXXX...XX.o . ", +".XXXXXXXXXXX.o.XX.o.. ", +".XX.......XX...XX...... ", +".XXXXXXXXXXXXXXXX.o.. . ", +".XX.......XXXXXXX.o . . ", +".XXXXXXXXXXXXXXXX.o . ", +".XXXXXXXXXXXXXXXX.o . ", +".XXXXX..................", +"......XXXXXXXXXXXXXXXX.o", +" oooo.XXXXXXXXXXX...XX.o", +" .XXXXXXXXXXX.o.XX.o", +" .XX.......XX...XX.o", +" .XXXXXXXXXXXXXXXX.o", +" .XX.......XXX.XXX.o", +" .XXXXXXXXXXX.X.XX.o", +" .XXXXXXXXXXXX.XXX.o", +" .XXXXXXXXXXXXXXXX.o", +" ..................o", +" oooooooooooooooooo", +" ", +" ",}; diff --git a/elpa/mew-20150813.2354/etc/mew-inc.xpm b/elpa/mew-20150813.2354/etc/mew-inc.xpm new file mode 100644 index 00000000..b18c1e61 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-inc.xpm @@ -0,0 +1,37 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yoshiaki Kasahara + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_inc_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c Gray60", +"o c white", +" ", +" ", +" .............. ", +" .XXX..X..oooooo. ", +" .XXXXXX.XX.oooooo. ", +" .XXXXXXX.XXX.ooooo. ", +" .XXXXXX.X....oooooo.", +" .XXXXXXX.X. .o...o.", +" .XXXXXXX.X.....ooooo.", +" .XXXXXXX.XXX.o.o...o.", +" .XXXXXXX.XX.oo.oo.oo.", +" .XXXXXXX.X.ooo.oo.oo.", +" .XXXXXXX..ooo..oo.oo.", +" .XXXXXXX.ooo.o.ooooo.", +" .XXXXXX.oo..o..ooooo.", +" .XXXXX.o..oooo.ooooo.", +" .XXXX.o.oooooo.oooo..", +" .XXXX..........oo.. ", +" ................. ", +" .ooooooooooooo. ", +" .ooooooooooooo. ", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-lock.xpm b/elpa/mew-20150813.2354/etc/mew-lock.xpm new file mode 100644 index 00000000..195c8863 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-lock.xpm @@ -0,0 +1,30 @@ +/* XPM */ +/* + * Copyright (C) 2003 Yuuichi Teranishi + * Copyright (C) 2003 Kazu Yamamoto + * Copyright (C) 2004 Yoshifumi Nishida + * Copyright notice is the same as Mew's one. + */ +static char * yellow3_xpm[] = { +"14 14 7 1", +" c None", +". c #B07403", +"+ c #EFEE38", +"@ c #603300", +"# c #D0A607", +"$ c #FAFC90", +"% c #241100", +" .++++@ ", +" .+@...+@ ", +" .+@ .+@ ", +" .+@ .+@ ", +" .+@ .+@ ", +"++########@@@@", +"+$$++++++++#@@", +"+$++++%@+++#@@", +"+$+++%%%@++#@@", +"+$+++%%%@++#@@", +"+$++++%@+++#@@", +"+$++++%@+++#@@", +"+$+++++++++#@@", +"++@@@@@@@@@@@@"}; diff --git a/elpa/mew-20150813.2354/etc/mew-next.xpm b/elpa/mew-20150813.2354/etc/mew-next.xpm new file mode 100644 index 00000000..70242781 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-next.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_next_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +" ", +" ", +" ", +" ........ ", +" .XXXXX.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" ...Xoooo.... ", +" .XXooooo.. ", +" .XXooo.. ", +" .XXo.. ", +" .X.. ", +" .. ", +" ", +" ", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-pgp-enc.xpm b/elpa/mew-20150813.2354/etc/mew-pgp-enc.xpm new file mode 100644 index 00000000..226bcbfe --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-pgp-enc.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_pgp_enc_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +"............... ", +".XXXXXXXXXXXXX. ", +".X...X...X...X. ", +".X.X.X.X.X.X.X. ", +".X...X...X...X. ", +".X.XXXXX.X.XXX. ", +".X.XXX...X.XXX. XXXXX ", +".XXXXXXXXXXXXX.Xooooo ", +"..............Xo....Xo. ", +" Xo. Xo. ", +" ooo Xo. Xo. ", +"o...o XXXXXXXXXX.", +"o. ooooooooo X oooooo..", +"o. o....o... X oooooo..", +"oooo. .. . X oooooo..", +" ... X oooooo..", +" X oooooo..", +" X oooooo..", +" ...........", +" ", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-pgp-sigenc.xpm b/elpa/mew-20150813.2354/etc/mew-pgp-sigenc.xpm new file mode 100644 index 00000000..a31a5d1a --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-pgp-sigenc.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_pgp_sigenc_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +"............... ", +".XXXXXXXXXXXXX. ", +".X...X...X...X. ", +".X.X.X.X.X.X.X. ", +".X...X...X...X. ", +".X.XXXXX.X.XXX. ", +".X.XXX...X.XXX. ", +".XXXXXXXXXXXX.. XXXXX ", +"............. Xooooo ", +" .X. Xo....Xo. ", +" .XX. Xo. Xo. ", +" .......XXX. Xo. Xo. ", +" XXXXX.XX X. XXXXXXXXXX.", +" XXXX.XX. . X oooooo..", +" XXX.XX. X. X oooooo..", +" XXX.X. X.X X oooooo..", +" XXX.. X.o X oooooo..", +" XXX.....ooooX oooooo..", +" XX. .ooo X oooooo..", +" X.XXXXX. ...........", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-pgp-sign.xpm b/elpa/mew-20150813.2354/etc/mew-pgp-sign.xpm new file mode 100644 index 00000000..586e85c4 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-pgp-sign.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_pgp_sign_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +"............... .", +".XXXXXXXXXXXXX. .", +".X...X...X...X. ..", +".X.X.X.X.X.X.X. .X.", +".X...X...X...X. .XX.", +".X.XXXXX.X.XXX......XXX.", +".X.XXX...X.XXX.XXX.XXX. ", +".XXXXXXXXXXXXX.XX.XXXX. ", +"...............X.XX. . ", +" .XXXXXXXXXXXXXX.X. X. ", +" .XXXXXXXXXXXXXX.. X.o ", +" .XXXXXXXXXXXXXX.....o ", +" .XXXXXXXXXXXXX. .o ", +" .XX..XXXXXXXXX .ooo", +" .X.X....XX..X.XX X..ooo", +" ..XX.X.X.....X.X..X.o ", +" .XX.X.X.X.XX.X..X.X.o ", +" .XX.X.X.X...XX.X.XX.o ", +" .XXXXXXXXXXXXXXXXXX.o ", +" ....................o ", +" oooooooooooooooooooo ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-prev.xpm b/elpa/mew-20150813.2354/etc/mew-prev.xpm new file mode 100644 index 00000000..aa29da7b --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-prev.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_prev_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +" ", +" ", +" ", +" .. ", +" .X.. ", +" .XXo.. ", +" .XXooo.. ", +" .XXooooo.. ", +" ...Xoooo.... ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .Xoooo.. ", +" .XXXXX.. ", +" ........ ", +" ", +" ", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-queue.xpm b/elpa/mew-20150813.2354/etc/mew-queue.xpm new file mode 100644 index 00000000..8d031c6a --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-queue.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_comp_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +" ", +" . ", +" .X.o ", +" .XXX.o ", +" .XXXXX.o ", +" .XXXoXXX.o ", +" .XXXoXX XX. ", +" ..XXXoXXoXX.oo ", +" ...XXXoXXoXX.oo ", +" ..X.XXXoXXoXX.oo ", +" ..XX.XXXoXXoXX..o ", +" ..XXXX.XXXXoXX. .. ", +" .X.XXXX.XX XX. .X.o ", +" .XX..XXX.XXX...XX.o ", +" .XXXX..XX.X..XXXX.o ", +" .XXXXXX....XXXXXX.o ", +" .XXXXX XX XXXXX.o ", +" .XXX XXXXXX XXX.o ", +" .X XXXXXXXXXX X.o ", +" ................oo ", +" oooooooooooooooo ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-refile.xpm b/elpa/mew-20150813.2354/etc/mew-refile.xpm new file mode 100644 index 00000000..1c3a8db9 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-refile.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_refile_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +" .. ", +" .XX. ", +" o.XXXX. ", +" .XXXXXX. ", +" .XXXX.XX. ", +" .XXXX.XX. ", +" .XXXX.XX. ", +" .... .X XXXX. ", +" .XXXX.. .XXXX. ", +" .XooooX.......... ", +" .XoooooXXXXXXXX.. ", +" .Xooooooooooooo.. ", +" .Xooooooooooooo.. ", +" .Xooooooooooooo.. ", +" .Xooooooooooooo.. ", +" .Xooooooooooooo.. ", +" .Xooooooooooooo.. ", +" .Xooooooooooooo.. ", +" .X............... ", +" ................. ", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-reply.xpm b/elpa/mew-20150813.2354/etc/mew-reply.xpm new file mode 100644 index 00000000..e404edd0 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-reply.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_reply_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" .. ", +" .X. ", +"............... ..XX. ", +".XXXXXXXXXXXXX. .XXXX. ", +".XXXXXXXXXXXXX..XXXX. ", +".XXXXX.........XXXXX. ", +".XXXXX.XXXXXX.XXXXX. ", +".XX....XXXXX.XXX.X..o ", +".XXXXX.XXXXX.XX.XX..o ", +".XXXXX.XXXX.XX.XX.X.o ", +".XX....XXX..X.XX.XX.o ", +".XXXXX.XXX.X.XX.XXX.o ", +".XXXXX.XXX..X..XXXX.o ", +".XX....XXX...XXXXXX.o ", +".XXXXX.XXX.XXXXXXXX.o ", +".XXXXX.XX.XX .oo ", +".XXXXX.X. .oooo", +".XXXXX.XXXXX .oo ", +".......XXXXXXXXXXXX.o ", +" .XXXXXXXXXXXX.o ", +" ..............o ", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-send.xpm b/elpa/mew-20150813.2354/etc/mew-send.xpm new file mode 100644 index 00000000..2aadb21d --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-send.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_send_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +" ", +" ", +" ", +" ", +" ", +" ................", +" .XXXXXXXXXXXXXXX.", +" .XXXXXXXXXXoooXX. ", +" .XXXXXXXXXXoooXX. ", +" .XX.......XXXXXX. ", +" .XXXXXXXXXXXXXXX. ", +" .XX.......XXXXXX.ooooo", +" .XXXXXXXXXXXXXXX.ooooo ", +" ................ooooo ", +" ooooooooooooooooo ", +" ooooooooooooooooo ", +" ooooooooooooooooo ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-sep.xpm b/elpa/mew-20150813.2354/etc/mew-sep.xpm new file mode 100644 index 00000000..dc033771 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-sep.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_sep_xpm[] = { +"2 28 1 1", +" s backgroundToolBarColor c None", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-show.xpm b/elpa/mew-20150813.2354/etc/mew-show.xpm new file mode 100644 index 00000000..b665fa09 --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-show.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_show_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c Gray60", +"o c white", +" ", +" ", +" ............. ", +" ..Xoooooooooo.X ", +" .o.Xoooooooooo.X ", +" .oo.Xoooooooooo.X ", +" .............ooo.X ", +" .XXXXXoooooooooo.X ", +" .ooooooooooooooo.X ", +" .oo..........ooo.X ", +" .ooooooooooooooo.X ", +" .ooooooooooooooo.X ", +" .oo..........ooo.X ", +" .ooooooooooooooo.X ", +" .ooooooooooooooo.X ", +" .oo..........ooo.X ", +" .ooooooooooooooo.X ", +" .ooooooooooooooo.X ", +" .ooooooooooooooo.X ", +" .ooooooooooooooo.X ", +" .................X ", +" XXXXXXXXXXXXXXXXX ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-write.xpm b/elpa/mew-20150813.2354/etc/mew-write.xpm new file mode 100644 index 00000000..424b202a --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-write.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_write_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +" ................... ", +" .XXXXXXXXXX..XXX. ", +" .XXXXXXXXX.XXXX. ", +" .XXXXXXXX.XXXX.. ", +" .XXXXXXX.XX.XX.. ", +" .XXXXXX.XX.XX. . ", +" .XXXXX.X.XX. X. ", +" .XXXXX.X... XX. ", +" .XXXXX... XXX. ", +" .XXXXX.. XXXXX. ", +" .XXXXX.. XXXXXX. ", +" .XXXX. XXXXXXX. ", +" .X.......XXXXXX. ", +" .X.X oo..XXXXXX. ", +" .X.......XXXXXX. ", +" .XX.oo..XXXXXXX. ", +" .XX.XX o..XXXXX. ", +" ....oXX oo....... ", +" .. oo.. ", +" ..ooo.. ", +" ..... ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/etc/mew-yank.xpm b/elpa/mew-20150813.2354/etc/mew-yank.xpm new file mode 100644 index 00000000..9ba7379f --- /dev/null +++ b/elpa/mew-20150813.2354/etc/mew-yank.xpm @@ -0,0 +1,36 @@ +/* XPM */ +/* + * Copyright (C) 1997 Yuuichi Teranishi + * Copyright (C) 1997 Kazu Yamamoto + * Copyright notice is the same as Mew's one. + */ +static char * mew_yank_xpm[] = { +"24 24 4 1", +" s backgroundToolBarColor c None", +". c black", +"X c white", +"o c Gray60", +" ", +" ", +"................... ", +".XXXXXXXXXXXXXXXXX. ", +".XXXXXXXXXXXX...XX. ", +".XXXXXXXXXXXX.o.XX. ", +".XXX.......XX...XX..... ", +".XXXXXXXXXXXXXXXXX.XXX. ", +".XXX.......XXX.XXX.XXX. ", +".XXXXXXXXXXXX.X.XX.XXX. ", +".X.XXXXXXXXXXX.XXX.XXX.o", +".X.XXXXXXXXXXXXXXX.XXX.o", +"...................XXX.o", +" o.oo.XXXXXXXXXXXXXXXX.o", +" . .X.XXXXX......XXX.o", +" . .X..XXXXXXXXXXXXX.o", +" ........XXX......XXX.o", +" .X..XXXXXXXXXX....o", +" .X.XXXXX.......X.o ", +" .XXXXXXXXXXXXX..o ", +" ...............o ", +" oooooooooooooo ", +" ", +" "}; diff --git a/elpa/mew-20150813.2354/mew-addrbook.el b/elpa/mew-20150813.2354/mew-addrbook.el new file mode 100644 index 00000000..e9d5c6bb --- /dev/null +++ b/elpa/mew-20150813.2354/mew-addrbook.el @@ -0,0 +1,576 @@ +;; mew-addrbook.el --- Aliases and personal information + +;; Author: Kazu Yamamoto +;; Created: Mar 22, 1999 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Address book +;;; + +(defvar mew-addrbook-mode-alias "Alias") +(defvar mew-addrbook-mode-personalinfo "Personal Info") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Internal syntax of mew-addrbook-alist +;;; + +;; for mew-complete +(defalias 'mew-addrbook-alias-hit 'assoc) + +;; + +(defvar mew-addrbook-orig-alist nil + "(key (addr1, addr2) nickname name) or (key addr)") + +(defun mew-adbkorigent-by-shortname (user) + (mew-addrbook-alias-hit user mew-addrbook-orig-alist)) + +;; + +(defvar mew-addrbook-alist nil ;; mew-alias-auto-alist is appended + "(key addr) or (key (addr1, addr2) nickname name)") + +(defun mew-adbkent-by-addr-with-alist (addr alist) + (mew-assoc-member-case-equal addr alist 1)) + +(defun mew-adbkent-by-addr (addr) + (mew-adbkent-by-addr-with-alist addr mew-addrbook-alist)) + +(defun mew-adbkent-by-addr2 (addr) + ;; for nickname and name, mew-addrbook-orig-alist is enough and fast + (mew-adbkent-by-addr-with-alist addr mew-addrbook-orig-alist)) + +(defun mew-adbkent-shortname (adbkent) + (nth 0 adbkent)) + +(defun mew-adbkent-addrs (adbkent) + (nth 1 adbkent)) + +(defun mew-adbkent-nickname (adbkent) + (nth 2 adbkent)) + +(defun mew-adbkent-name (adbkent) + (nth 3 adbkent)) + +(defun mew-addrbook-shortname-get (addr) + (mew-adbkent-shortname (mew-adbkent-by-addr addr))) + +(defun mew-addrbook-addrs-get (addr) + (mew-adbkent-addrs (mew-adbkent-by-addr addr))) + +(defun mew-addrbook-nickname-get (addr) + (mew-adbkent-nickname (mew-adbkent-by-addr2 addr))) + +(defun mew-addrbook-name-get (addr) + (mew-adbkent-name (mew-adbkent-by-addr2 addr))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Internal syntax of mew-alias-auto-alist +;;; + +(defvar mew-alias-auto-alist nil + "(key addr)") + +(defun mew-autoent-by-shortname (user) + (assoc user mew-alias-auto-alist)) + +(defun mew-autoent-shortname (autoent) + (nth 0 autoent)) + +(defun mew-autoent-addr (autoent) + (nth 1 autoent)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Setup +;;; + +(defun mew-alias-short-to-full (alist) + (mapcar (lambda (x) (cdr x)) alist)) + +;; duplicated? +(defun mew-alias-full-to-short (alist) + (mapcar (lambda (x) (cons (downcase (mew-addrstr-extract-user x)) x)) alist)) + +(defun mew-addrbook-setup () + (if (and mew-alias-auto-file (null mew-alias-auto-alist)) + ;; make auto-alist only at the initialization time + ;; not at update time (auto-alist have not been saved yet) + (setq mew-alias-auto-alist (mew-lisp-load mew-alias-auto-file))) + (if mew-use-full-alias + (if (mew-autoent-addr (car mew-alias-auto-alist)) + (setq mew-alias-auto-alist + (mew-alias-short-to-full mew-alias-auto-alist))) + (if (null (mew-autoent-addr (car mew-alias-auto-alist))) + (setq mew-alias-auto-alist + (mew-alias-full-to-short mew-alias-auto-alist)))) + (setq mew-addrbook-orig-alist (mew-addrbook-make-alist)) + (mew-addrbook-concat-uniq) + (add-hook 'kill-emacs-hook 'mew-addrbook-clean-up)) + +(defun mew-addrbook-concat-uniq () + (setq mew-addrbook-alist + (append mew-addrbook-orig-alist (copy-sequence mew-alias-auto-alist))) + (setq mew-addrbook-alist (mew-uniq-alist mew-addrbook-alist))) + +(defun mew-addrbook-clean-up () + (remove-hook 'kill-emacs-hook 'mew-addrbook-clean-up) + (when (and mew-alias-auto-file mew-alias-auto-alist) + (mew-lisp-save mew-alias-auto-file mew-alias-auto-alist)) + (setq mew-alias-auto-alist nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Due to the spec of mew-complete, alist must be passed. +;;; + +(defvar mew-alias-expand-prefix nil + "A variable to make 'mew-alias-expand' elegant.") + +;; for completion +(defun mew-addrbook-alias-get (key alist) + (let* ((mew-alias-expand-prefix nil) + (addrs (mew-alias-expand key alist 0)) + (addrx (mapcar 'mew-addrstr-append-domain addrs)) + (ret (mapconcat 'identity addrx ", "))) + (if mew-alias-expand-prefix + (concat mew-alias-expand-prefix ":" ret ";") + ret))) + +(defun mew-alias-expand-addrs (key alist count) + (let ((keys (delete "" (mapcar 'mew-chop (mew-split key ?,)))) + ret) + (dolist (key keys) + (setq ret (nconc ret (mew-alias-expand key alist count)))) + ret)) + +(defun mew-alias-expand (key alist count) + "Expand KEY to a list of addresses according to ALIST. +Infinite loop is prevented by COUNT and 'mew-expand-max-depth'. +Before calling, 'mew-alias-expand-prefix' must be set 'nil'. +If \"prefix:a,b,c;\" is given, 'mew-alias-expand-prefix' +is set to \"prefix\", and (expanded-a expanded-b expanded-c) is +returned." + (cond + ((> count mew-expand-max-depth) key) + ((string-match "^\\([^:]+\\):\\([^;]+\\);$" key) + (if mew-alias-expand-prefix (error ":; must not recurse!")) + (setq mew-alias-expand-prefix (match-string 1 key)) + (setq key (match-string 2 key)) + (mew-alias-expand-addrs key alist (1+ count))) + (t + (let ((crnt (mew-adbkent-addrs (mew-addrbook-alias-hit key alist)))) + (cond + ((null crnt) (list key)) + ((listp crnt) (list (car crnt))) + ((string-match "[^:]+:[^;]+;" crnt) + (mew-alias-expand crnt alist (1+ count))) + ((string-match "," crnt) + (mew-alias-expand-addrs crnt alist (1+ count))) + (t (list crnt))))))) + +(defun mew-addrbook-alias-next (key alist) + (let* ((addrs (mew-adbkent-addrs + (mew-adbkent-by-addr-with-alist key alist)))) + (if (and addrs (listp addrs)) + (mew-get-next addrs key)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; For mew-encode-learn-aliases +;;; + +(defun mew-addrbook-alias-add (addr) + ;; Let's downcase user-name for .mew-alias since it is automatically + ;; maintained. + (when (and (stringp addr) (string-match "@" addr) + (or (null mew-addrbook-alias-not-learn-list) + (not (mew-member-match addr mew-addrbook-alias-not-learn-list)))) + (if mew-use-full-alias + (unless (member (list addr) mew-alias-auto-alist) + (mew-addrbook-alias-cons (list addr))) + (let* ((user (downcase (mew-addrstr-extract-user addr))) + (match-auto (mew-autoent-by-shortname user)) + (match-adbk-orig (mew-adbkorigent-by-shortname user))) + (cond + ((string= user "") + ;; do nothing + ) + (match-adbk-orig + ;; do nothing + ) + (match-auto + (cond + ((string= addr (mew-autoent-addr match-auto)) + ;; Move the entry to the top for the recent-used-first. + (setq mew-alias-auto-alist (delq match-auto mew-alias-auto-alist)) + (setq mew-alias-auto-alist (cons match-auto mew-alias-auto-alist))) + (mew-addrbook-override-by-newone + ;; override match-auto by (user addr) + (setq mew-alias-auto-alist (delq match-auto mew-alias-auto-alist)) + (setq mew-addrbook-alist (delete match-auto mew-addrbook-alist)) + (mew-addrbook-alias-cons (list user addr))) + (t + ;; the old entry remains + ))) + (t + (mew-addrbook-alias-cons (list user addr)))))))) + +(defun mew-addrbook-alias-cons (user-addr) + (setq mew-alias-auto-alist (cons user-addr mew-alias-auto-alist)) + ;; Ideally, user-addr should be inserted in between + ;; mew-addrbook-orig-alist and mew-alist-auto-alist. + ;; But mew-alist-auto-alist is the newest-first order. + ;; So, just cons user-addr to mew-addrbook-alist. + ;; This produces a different alist made by mew-addrbook-setup. + ;; But we do not care. + (setq mew-addrbook-alist (cons user-addr mew-addrbook-alist))) + +(defun mew-addrbook-alias-delete (addr) + (when (and (stringp addr) (string-match "@" addr)) + (let* ((user (downcase (mew-addrstr-extract-user addr))) + (ent (mew-autoent-by-shortname user))) + (when (and ent (string= addr (mew-autoent-addr addr))) + (setq mew-addrbook-alist (delete ent mew-addrbook-alist)) + (setq mew-alias-auto-alist (delq ent mew-alias-auto-alist)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Loading Addrbook files +;;; + +(defun mew-addrbook-insert-file (file cregex &optional unquote) + (let* ((case-fold-search t) + (pars (mew-split file ?,)) ;; parents + (files pars) ;; included + par chr path beg end qchar ret) + ;; include parents files + (dolist (ent pars) + (setq par (expand-file-name ent mew-conf-path)) + (when (file-readable-p par) + (setq ret t) + (mew-insert-file-contents par) + (setq path (file-name-directory par)) + ;; include children files + (while (re-search-forward "^<[ \t]*\\([^ \t\n]+\\).*$" nil t) + (setq chr (expand-file-name (mew-match-string 1) path)) + (replace-match "" nil t) + (when (and (file-readable-p chr) (not (member chr files))) + (mew-insert-file-contents chr) + (setq files (cons chr files)))) + (goto-char (point-max)))) + ;; remove comments + (goto-char (point-min)) + (while (re-search-forward cregex nil t) + (setq beg (match-beginning 0)) + (setq end (match-end 0)) + (beginning-of-line) + (if (/= (point) beg) + (forward-line) + (forward-line) + (setq end (point))) + (delete-region beg end)) + ;; concat continuation lines + ;; "\" must locate on the end of line + (goto-char (point-min)) + (while (re-search-forward "\\\\\n" nil t) + (replace-match "" nil t)) + ;; concat separated lines by comma + (goto-char (point-min)) + (while (re-search-forward ",$" nil t) + (end-of-line) + (forward-char 1) + (delete-char -1)) + ;; replace ", " to "\0" inside/outside quote. + (goto-char (point-min)) + (while (re-search-forward ",[ \t]+" nil t) + (replace-match ",\0" nil t)) + ;; unquote, replace white spaces to "\0". + (goto-char (point-min)) + (if unquote + (catch 'quote + (while (re-search-forward "[\"']" nil t) + (setq qchar (char-before (point))) + ;; (point) is for backward compatibility + (backward-delete-char 1) ;; delete quote + (setq beg (point)) + (if (not (re-search-forward (char-to-string qchar) nil t)) + (throw 'quote nil) ;; error + (backward-delete-char 1) ;; delete quote + (save-restriction + (narrow-to-region beg (point)) + (goto-char (point-min)) + (while (re-search-forward "[ \t]+" nil t) + (replace-match "\0" nil t)) + (goto-char (point-max))))))) ;; just in case + ;; remove optional white spaces + (goto-char (point-min)) + (while (re-search-forward "[ \t]+" nil t) + (replace-match " " nil t)) + ret)) + +(defun mew-addrbook-strsafe (var) + (if (or (string= "" var) (string= "*" var)) + nil + (mew-replace-character var 0 mew-sp))) + +(defun mew-addrbook-make-alist () + (let (alias colon addrs nick name alist) + (with-temp-buffer + (when (mew-addrbook-insert-file + mew-addrbook-file mew-addrbook-comment-regex 'unquote) + (goto-char (point-min)) + (while (re-search-forward "^ ?\\([^ \n:]+\\) ?\\(:?\\) ?\\([^ \t\n]+\\)" nil t) + (setq alias (mew-addrbook-strsafe (mew-match-string 1))) + (setq colon (mew-match-string 2)) + (setq addrs (mew-addrbook-strsafe (mew-match-string 3))) + (if (string= colon ":") + (setq alist (cons (list alias addrs) alist)) + (and addrs (setq addrs (mapcar 'mew-chop (mew-split addrs ?,)))) + (if (looking-at " ?\\([^ \n]*\\) ?\\([^ \n]*\\)") + (progn + (setq nick (mew-addrbook-strsafe (mew-match-string 1))) + (setq name (mew-addrbook-strsafe (mew-match-string 2)))) + (setq nick nil) + (setq name nil)) + (setq alist (cons (list alias addrs nick name) alist)))))) + (nreverse alist))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Addrbook mode +;;; + +(defun mew-summary-addrbook-add (&optional personalinfo) + "Adding the value of From: in Message mode to Addrbook. When +executed with '\\[universal-argument]', it will add personal information. Otherwise, +it will add an alias." + (interactive "P") + (let ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + from shortname addrs name) + (save-excursion + (mew-summary-set-message-buffer fld msg) + (setq from (mew-header-get-value mew-from:))) + (if (null from) + (message "No address to be registered") + ;; assuming From: contains just one address + (setq addrs (mew-addrstr-parse-address from)) + (if (mew-is-my-address mew-regex-my-address-list addrs) + (if personalinfo + (setq addrs (car (mew-header-parse-address-list + (list mew-to:)))) + (setq addrs (mapconcat 'identity + (mew-header-parse-address-list + (list mew-to: mew-cc:)) + ","))) + (when (string-match "\\(.*\\)<.*>" from) + (setq name (match-string 1 from)) + (setq name (mew-chop name))) + (if mew-addrbook-strip-domainpart + (setq shortname (downcase (mew-addrstr-extract-user addrs))) + (setq shortname (downcase addrs)))) + (if (not addrs) + (message "No address to be registered") + (mew-addrbook-prepare-template + personalinfo shortname addrs nil name))))) + +(defun mew-addrbook-prepare-template (personalinfop shortname addrs &optional nickname name) + (delete-other-windows) + (switch-to-buffer (get-buffer-create mew-buffer-addrbook)) + (mew-erase-buffer) + (mew-insert-manual + "#If you want to register this entry, type " + "'\\\\[mew-addrbook-register]'.\n" + "#If you want to NOT register this entry, type " + "'\\\\[mew-addrbook-kill]'.\n") + (mew-addrbook-insert-template "Shortname" shortname) + (mew-addrbook-insert-template "Addresses" addrs) + (cond + (personalinfop + (mew-addrbook-insert-template "Nickname" nickname) + (mew-addrbook-insert-template "Name" name) + (mew-addrbook-mode mew-addrbook-mode-personalinfo)) + (t + (mew-addrbook-mode mew-addrbook-mode-alias))) + (mew-addrbook-insert-template "Comments" nil) + (goto-char (point-min)) + (search-forward ": " nil t)) + +(defun mew-addrbook-insert-template (key val) + (mew-elet + (let ((beg (point))) + (insert key ": ") + (put-text-property beg (point) 'read-only t) + (mew-rear-nonsticky beg (point)) + (and val (insert val)) + (insert "\n")))) + +(defun mew-addrbook-mode (mname) + "A major mode to register Addrbook. + +\\{mew-addrbook-mode-map}" + (interactive) + (setq major-mode 'mew-addrbook-mode) + (setq mode-name mname) + (setq mode-line-buffer-identification (mew-mode-line-id)) + (use-local-map mew-addrbook-mode-map) + (mew-run-mode-hooks 'mew-addrbook-mode-hook) + (setq buffer-undo-list nil)) + +(defun mew-addrbook-nconc (ent) + (setq mew-addrbook-orig-alist (nconc mew-addrbook-orig-alist (list ent))) + (mew-addrbook-concat-uniq)) + +(defun mew-addrbook-register () + "Register information in Addrbook mode to Addrbook." + (interactive) + (let ((shortname (mew-header-get-value "Shortname:")) + (addrs (mew-header-get-value "Addresses:")) + (nickname (mew-header-get-value "Nickname:")) + (name (mew-header-get-value "Name:")) + (comments (mew-header-get-value "Comments:")) + (mode mode-name) + (uniqp t) + buf addrsl errmsg) + (cond + ((string= mode mew-addrbook-mode-alias) + (cond + ((and (null shortname) (null addrs)) + (setq errmsg "Must fill both Shortname and Addresses")) + ((null shortname) + (setq errmsg "Must fill Shortname")) + ((null addrs) + (setq errmsg "Must fill Addresses")))) + (t + (cond + ((null addrs) + (setq errmsg "Must fill Addresses")) + ((and (null shortname) (null nickname) (null name)) + (setq errmsg "Must fill Shortname or Nickname or Name")) + ((and name (string-match "^\"[^\"]*[^\000-\177]" name)) + (setq errmsg "Remove quote around non-ASCII Name"))))) + (if errmsg + (message "%s" errmsg) + (save-excursion + (setq buf (mew-find-file-noselect2 + (expand-file-name mew-addrbook-file mew-conf-path))) + (set-buffer buf) + (goto-char (point-min)) + (if (and shortname + (re-search-forward + (concat "^" (regexp-quote shortname) "[ \t]*:?[ \t]+") nil t)) + (setq uniqp nil)) + (when uniqp + ;; All errors are checked. + (goto-char (point-max)) + (unless (bolp) (insert "\n")) + (cond + ((string= mode mew-addrbook-mode-alias) + (insert shortname ":\t" addrs) + (mew-addrbook-nconc (list shortname addrs))) + (t + (setq addrsl (mew-addrstr-parse-address-list addrs)) + ;; Set mew-addrbook-orig-alist with unquoted strings. + (mew-addrbook-nconc (list shortname addrsl nickname name)) + (unless shortname (setq shortname "*")) + (if (and nickname (string-match "^[^\" \t]+[ \t]+.*$" nickname)) + (setq nickname (concat "\"" nickname "\""))) + (if (and name (string-match "^[^\" \t]+[ \t]+.*$" name)) + (setq name (concat "\"" name "\""))) + (if name + (insert shortname "\t" addrs "\t" (or nickname "*") "\t" name) + (if nickname + (insert shortname "\t" addrs "\t" nickname) + (insert shortname "\t" addrs))))) + (if comments + (insert "\t#" comments "\n") + (insert "\n")) + (save-buffer))) + ;; Addrbook buffer + (mew-remove-buffer buf) + (cond + (uniqp + (mew-addrbook-kill 'no-msg) + (message "Registered to Addrbook")) + (t + (message "Shortname is already used. Change Shortname")))))) + +(defun mew-addrbook-kill (&optional no-msg) + "Kill Addrbook mode." + (interactive "P") + (mew-remove-buffer (current-buffer)) + (or no-msg (message "Not registered"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Editing auto-alist +;;; + +(defun mew-summary-alias-read-buffer () + (save-excursion + (goto-char (point-min)) + ;; An error occurs if the expression is broken. + ;; This is intentional. + (setq mew-alias-auto-alist (read (current-buffer))) + (mew-addrbook-concat-uniq) + nil)) ;; to write + +(defun mew-summary-alias-edit () + "Editing the auto alias file which contains a list of alias-address +pairs. Remove unnecessary entries and save the file by +'\\[save-buffer]'. After saving, the modification is automatically +reflected." + (interactive) + (let ((file mew-alias-auto-file)) + (setq mew-alias-auto-alist + (sort mew-alias-auto-alist (lambda (x y) (string< (car x) (car y))))) + (mew-lisp-save mew-alias-auto-file mew-alias-auto-alist) + (unless (file-name-absolute-p file) + (setq file (expand-file-name file mew-conf-path))) + (switch-to-buffer (mew-find-file-noselect file)) + (emacs-lisp-mode) + (if (boundp 'write-file-functions) + (add-hook 'write-file-functions 'mew-summary-alias-read-buffer nil 'local) + (add-hook 'local-write-file-hooks 'mew-summary-alias-read-buffer)))) + +(provide 'mew-addrbook) + +;;; Copyright Notice: + +;; Copyright (C) 1999-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-addrbook.el ends here diff --git a/elpa/mew-20150813.2354/mew-attach.el b/elpa/mew-20150813.2354/mew-attach.el new file mode 100644 index 00000000..bc31856d --- /dev/null +++ b/elpa/mew-20150813.2354/mew-attach.el @@ -0,0 +1,878 @@ +;;; mew-attach.el --- attachments for Mew Draft mode + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; goodies +;; + +(defun mew-draft-prepare-attachments (&optional no-scroll) + "Prepare an attachment region in the bottom of the draft. +To compose a multipart message, you should execute this command first." + (interactive) + (if (mew-attach-p) + (message "Attachments region has already been prepared") + (let* ((attachdir (mew-attachdir)) + (cp (expand-file-name mew-draft-coverpage attachdir)) + (dir (file-name-nondirectory attachdir))) + (if (mew-attach-p) + (message "Attachments already exist") + (mew-attach-set) + (mew-check-directory attachdir) + (unless (file-exists-p cp) (write-region "" nil cp 'append 'no-msg)) + (unless mew-encode-syntax + (setq mew-encode-syntax (mew-encode-syntax-initial dir))) + (mew-encode-syntax-print mew-encode-syntax) + (mew-attach-goto-number 'here '(2)) + (if (and (not no-scroll) + (not (pos-visible-in-window-p + (point-max) + (get-buffer-window (current-buffer))))) + (set-window-start (get-buffer-window (current-buffer)) + (mew-attach-begin))) + (setq buffer-undo-list nil))))) + +(defun mew-attach-expand-path (syntax nums) + ;; Ignore the first dir + (let ((path "")) + (while (cdr nums) + (setq syntax (aref syntax (+ mew-syntax-magic (1- (car nums))))) + (setq path (concat path (mew-syntax-get-file syntax))) + (setq nums (cdr nums))) + path)) + +(defun mew-attach-line () + "Return the line number for the cursor from the beginning of the +attachments region. +0 if on the beginning boundary. +-1 if on the ending boundary." + (let (ret max) + (save-excursion + (beginning-of-line) + (setq ret (count-lines (1+ (mew-attach-begin)) (point))) + (goto-char (point-max)) + (beginning-of-line) + (setq max (count-lines (1+ (mew-attach-begin)) (point))) + (if (or (= ret max) (= ret (1- max))) -1 ret)))) + +(defun mew-attach-line-lastp () + (let ((here (point))) + (save-excursion + (goto-char (point-max)) + (beginning-of-line) + (= (count-lines here (point)) 2)))) + +(defun mew-attach-move-onto-file () + (end-of-line) + (re-search-backward " [^ ]" nil t) + (forward-char)) + +(defun mew-attach-move-onto-body () + (goto-char (1+ (mew-attach-begin))) + (forward-char -1)) + +(defun mew-attach-directory-p () + (save-excursion + (mew-attach-move-onto-file) + (looking-at (file-name-as-directory "[^ ]+")))) + +(defun mew-attach-dot-p () + (save-excursion + (mew-attach-move-onto-file) + (looking-at "\\. *$"))) + +;; cursor only +(defun mew-attach-line0-1 () + (when (mew-attach-p) + (let ((line (mew-attach-line))) + (or (= line 0) (= line -1))))) + +;; cursor only +(defun mew-attach-line01-1 () + (when (mew-attach-p) + (let ((line (mew-attach-line))) + (or (= line 0) (= line 1) (= line -1))))) + +;; insert commands +(defun mew-attach-not-line012-1 () + (when (mew-attach-p) + (let ((line (mew-attach-line))) + (not (or (= line 0) (= line 1) (= line 2) (= line -1)))))) + +;; find commands +(defun mew-attach-not-line012-1-dot () + (when (mew-attach-p) + (let ((line (mew-attach-line))) + (not (or (mew-attach-dot-p) + (= line 0) (= line 1) (= line 2) (= line -1)))))) + +;; delete commands +(defun mew-attach-not-line02-1-dot () + (when (mew-attach-p) + (let ((line (mew-attach-line))) + (not (or (mew-attach-dot-p) (= line 0) (= line 2) (= line -1)))))) + + +;; modify commands +(defun mew-attach-not-line0-1-dot () + (when (mew-attach-p) + (let ((line (mew-attach-line))) + (not (or (mew-attach-dot-p) (= line 0) (= line -1)))))) + +;; cursor +(defun mew-attach-line1-dot () + (when (mew-attach-p) + (let ((line (mew-attach-line))) + (or (mew-attach-dot-p) (= line 1))))) + +(defun mew-attach-goto-number (direction nums) + (let (numreg) + (setq nums (nreverse nums)) + (cond + ((eq direction 'next) + (setq nums (cons (1+ (car nums)) (cdr nums)))) + ((eq direction 'prev) + (setq nums (cons (1- (car nums)) (cdr nums)))) + ((eq direction 'up) + (setq nums (cdr nums))) + ((eq direction 'down) + (setq nums (cons 1 nums))) + (t ())) + (if (null nums) + (progn + (goto-char (1- (mew-attach-begin))) + (re-search-forward "^..... " nil t) + (mew-attach-move-onto-file)) + (setq numreg (number-to-string (car nums))) + (setq nums (cdr nums)) + (dolist (num nums) + (setq numreg (concat (number-to-string num) "." numreg))) + (setq numreg (regexp-quote numreg)) + (goto-char (1+ (mew-attach-begin))) + (re-search-forward (concat "^....." numreg " ") nil t) + (mew-attach-move-onto-file)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Dialog +;;; + +(defun mew-substitute-for-attach (msg) + (substitute-command-keys (concat "\\" msg))) + +(defun mew-message-for-attach (msg) + (message "%s" (mew-substitute-for-attach msg))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; commands +;; + +;; +;; cursor commands +;; + +(defun mew-attach-newline () + "Insert RET before the attachments region." + (interactive) + (when (= (point) (1+ (mew-attach-begin))) + (insert "\n") + (mew-draft-attach-keymap))) + +(defun mew-attach-forward () + "Go to the first subdirectory in attachments." + (interactive) + (if (mew-attach-line0-1) + (mew-attach-goto-number 'here nil) + (mew-attach-move-onto-file) + (if (mew-attach-directory-p) + (mew-attach-goto-number 'down (mew-syntax-nums)) + (mew-attach-goto-number 'here (mew-syntax-nums))))) + +(defun mew-attach-backforward () + "Go to the parent directory in attachments." + (interactive) + (if (mew-attach-line0-1) + (mew-attach-move-onto-body) + (let ((nums (mew-syntax-nums))) + (if (= (length nums) 1) + (mew-attach-goto-number 'here nil) + (mew-attach-goto-number 'up (mew-syntax-nums)))))) + +(defun mew-attach-previous () + "Go to the previous file in the current directory in attachments." + (interactive) + (if (mew-attach-line01-1) + (mew-attach-move-onto-body) + (if mew-attach-move-by-line + (progn + (forward-line -1) + (mew-attach-move-onto-file)) + (let* ((nums (mew-syntax-nums)) + (last (nth (1- (length nums)) nums))) + (if (= last 1) + (mew-attach-goto-number 'here (mew-syntax-nums)) + (mew-attach-goto-number 'prev (mew-syntax-nums))))))) + +(defun mew-attach-next () + "Go to the next file in the current directory in attachments." + (interactive) + (if (mew-attach-line0-1) + (mew-attach-goto-number 'here nil) + (if mew-attach-move-by-line + (if (mew-attach-line-lastp) + () + (forward-line) + (mew-attach-move-onto-file)) + (if (mew-attach-line1-dot) + (mew-attach-goto-number 'here (mew-syntax-nums)) + (mew-attach-goto-number 'next (mew-syntax-nums)))))) + +;; +;; delete commands +;; + +(defun mew-attach-delete () + "Delete this file or this directory in attachments." + (interactive) + (if (not (mew-attach-not-line02-1-dot)) + (message "Cannot delete here") + (if (= (mew-attach-line) 1) + (if (not (y-or-n-p "Delete entire attachments? ")) + (message "Attachments were not deleted") + (mew-delete-directory-recursively (mew-attachdir)) + (setq mew-encode-syntax nil) + (mew-attach-clear) + (message "Attachments were deleted")) + (let* ((nums (mew-syntax-nums)) + (subdir (mew-attach-expand-path mew-encode-syntax nums)) + (attachdir (mew-attachdir)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (name (mew-syntax-get-file syntax)) + (ename (if (string= subdir "") name (concat subdir name))) + (fullname (expand-file-name ename attachdir)) + (dirp (string-match (concat mew-path-separator "$") name)) + (msg (if dirp + "Delete %s with contained files? " + "Delete %s? "))) + ;; attachdir / {subdir/} name + (when (y-or-n-p (format msg ename)) + (message "Deleting %s..." ename) + (if (file-exists-p fullname) + (if dirp + (mew-delete-directory-recursively fullname) + (mew-delete-file fullname))) + (message "Deleting %s...done" ename) + (setq mew-encode-syntax + (mew-syntax-remove-entry mew-encode-syntax nums)) + (mew-encode-syntax-print mew-encode-syntax)))))) + +;; +;; insert commands +;; + +(defun mew-attach-multipart () + "Create a subdirectory(i.e. multipart) on '.' in attachments." + (interactive) + (if (not (mew-attach-not-line012-1)) + (message "Cannot create a sub-multipart here") + (let* ((nums (mew-syntax-nums)) + (subdir (mew-attach-expand-path mew-encode-syntax nums)) + (insert-default-directory nil) + (attachdir (mew-attachdir)) + dir dirpath) + ;; attachdir / {subdir/} dir + (unless (string= subdir "") + (setq attachdir (expand-file-name subdir attachdir))) + ;; attachdir / dir + (setq dirpath (mew-random-filename attachdir 1 nil)) + (if (file-exists-p dirpath) + (message "Cannot make a directory, sorry") + (setq dir (file-name-nondirectory dirpath)) + (mew-make-directory dirpath) + (setq mew-encode-syntax + (mew-syntax-insert-entry + mew-encode-syntax + nums + (mew-encode-syntax-multi dir mew-type-mlm))) + (mew-encode-syntax-print mew-encode-syntax))))) + +(defun mew-attach-duplicate (func action setmode &optional from to default) + (if (not (mew-attach-not-line012-1)) + (message "Cannot %s here" action) + (let* ((completion-ignored-extensions nil) + (nums (mew-syntax-nums)) + (subdir (mew-attach-expand-path mew-encode-syntax nums)) + (attachdir (mew-attachdir)) + (frompath from) + (efile (and to (concat subdir to))) + (tofile to) + ct msg FILE) + (while (or (null frompath) + (file-directory-p (file-chase-links frompath)) + (not (file-exists-p (file-chase-links frompath)))) + (setq frompath (mew-draft-input-file-name + (concat (mew-capitalize action) " from: ") default))) + (while (or (null efile) + (file-exists-p (expand-file-name efile attachdir))) + (setq tofile (mew-input-string + (concat (mew-capitalize action) " to %s(%s): ") + subdir + (file-name-nondirectory frompath))) + (setq efile (concat subdir tofile))) + (setq FILE (expand-file-name efile attachdir)) + (funcall func frompath FILE) + (if setmode (mew-set-file-modes FILE)) + (setq ct (mew-ctdb-ct (mew-ctdb-by-file tofile))) + (unless ct + (setq ct (mew-content-type (mew-tinfo-get-case))) + (cond + ((string= ct mew-ct-txt) + (setq msg (mew-substitute-for-attach + "Attached as text. Type '\\[mew-attach-toggle]' to toggle text to binary"))) + ((string= ct mew-ct-apo) + (setq msg (mew-substitute-for-attach + "Attached as binary. Type '\\[mew-attach-toggle]' to toggle binary to text"))))) + (setq mew-encode-syntax + (mew-syntax-insert-entry + mew-encode-syntax + nums + (mew-encode-syntax-single tofile (list ct) nil nil nil 'cdp))) + (mew-encode-syntax-print mew-encode-syntax) + (if mew-attach-move-next-after-copy (mew-attach-next)) + (if msg (message "%s" msg))))) + +(defun mew-attach-link (&optional from to) + "Link a file with a symbolic link on '.' in attachments. +FROM must be absolute path. TO must be a file name." + (interactive) + (mew-attach-duplicate 'mew-symbolic-link "link" nil from to)) + +(defun mew-attach-copy (&optional from to) + "Copy a file (via networks) on '.' in attachments. +FROM must be absolute path. TO must be a file name. +To copy a remote file, use the \"/[user@]hostname:/filepath\" syntax." + (interactive) + (mew-attach-duplicate 'copy-file "copy" t from to)) + +(defun mew-attach-toggle () + "Toggle text/binary in attachments." + (interactive) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot change %s here" mew-ct:) + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (file (mew-syntax-get-file syntax)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + cte) + (if (not (or (string= ct mew-ct-txt) (string= ct mew-ct-apo))) + (message "Cannot toggle %s" ct) + (if (string= ct mew-ct-txt) + (setq ct mew-ct-apo) + (setq ct mew-ct-txt)) + (setq ctl (list ct)) + (mew-syntax-set-ct syntax ctl) + (setq cte (mew-ctdb-cte (mew-ctdb-by-ct ct))) + (mew-syntax-set-cte syntax cte) + (mew-syntax-set-cdp syntax (mew-syntax-cdp-format ct file)) + (mew-encode-syntax-print mew-encode-syntax))))) + +(defun mew-attach-link-message () + "Link the message displayed in Message mode with a symbolic link +on '.' in attachments." + (interactive) + (let* ((fid (mew-frame-id)) + (fld (mew-current-get-fld fid)) + (msg (mew-current-get-msg fid)) + default) + (if fld (setq default (mew-expand-msg fld msg))) + (if mew-use-symbolic-link-for-forwarding + (mew-attach-duplicate 'mew-symbolic-link "link" nil nil nil default) + (mew-attach-duplicate 'copy-file "copy" nil nil nil default)))) + +(defun mew-attach-find-new-file () + "Open a new file into a buffer on '.' in attachments." + (interactive) + (if (not (mew-attach-not-line012-1)) + (message "Cannot find a new file here") + (let* ((nums (mew-syntax-nums)) + (subdir (mew-attach-expand-path mew-encode-syntax nums)) + (attachdir (mew-attachdir)) + file filepath) + ;; attachdir / {subdir/} dir + (unless (string= subdir "") + (setq attachdir (expand-file-name subdir attachdir))) + ;; attachdir / file + (setq filepath (mew-random-filename attachdir 1 nil mew-text-suffix)) + (if (null filepath) + (message "Cannot make a text file, sorry") + (setq file (file-name-nondirectory filepath)) + (setq mew-encode-syntax + (mew-syntax-insert-entry + mew-encode-syntax + nums + (mew-encode-syntax-single file (list mew-ct-txt) ;; for charset + nil nil nil nil))) + (mew-encode-syntax-print mew-encode-syntax) + ;; + (switch-to-buffer (mew-find-file-noselect2 filepath)) + (text-mode) + ;; buffer switched + (local-set-key "\C-c\C-q" 'mew-kill-buffer))))) + +(defun mew-attach-audio () + "Sampling voice and insert as audio file on '.' in attachments" + (interactive) + (if (not (mew-attach-not-line012-1)) + (message "Cannot attach audio data here") + (let* ((nums (mew-syntax-nums)) + (subdir (mew-attach-expand-path mew-encode-syntax nums)) + (attachdir (mew-attachdir)) + file filepath recorded) + ;; attachdir / {subdir/} dir + (unless (string= subdir "") + (setq attachdir (expand-file-name subdir attachdir))) + ;; attachdir / file + (setq filepath (mew-random-filename attachdir 1 nil mew-audio-suffix)) + (if (null filepath) + (message "Cannot make a file for audio, sorry") + (setq file (file-name-nondirectory filepath)) + (with-temp-buffer + (condition-case nil + (progn + (if (not (y-or-n-p "Are you ready to record audio? ")) + (message "Nothing is recoded") + (mew-message-for-attach + "Type '\\[keyboard-quit]' to finish recording...") + (mew-plet + (apply 'call-process + (nth 0 mew-prog-audio2) + nil t nil + (nth 1 mew-prog-audio2))))) + (quit + (mew-message-for-attach + "Type '\\[keyboard-quit]' to finish recording...done") + (setq recorded t) + (mew-flet + (write-region (point-min) (point-max) filepath nil 'no-msg))))) + (if recorded + (setq mew-encode-syntax ;; buffer local + (mew-syntax-insert-entry + mew-encode-syntax + nums + (mew-encode-syntax-single file mew-type-ado + nil nil nil 'cdp)))) + (mew-encode-syntax-print mew-encode-syntax))))) + +;; +;; modify commands +;; + +(defun mew-attach-undo () + "Unmark. The original mark appears." + (interactive) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot undo encoding here") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums))) + (mew-syntax-set-privacy syntax nil) + (mew-syntax-set-decrypters syntax nil) + ;; + (mew-syntax-set-cte syntax + (mew-ctdb-cte + (mew-ctdb-by-ct + (car (mew-syntax-get-ct syntax))))) + (mew-encode-syntax-print mew-encode-syntax)))) + +(defun mew-attach-type () + "Change the data type(Content-Type:) in attachments." + (interactive) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot change %s here" mew-ct:) + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (file (mew-syntax-get-file syntax)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + cte) + (setq ct (mew-input-type "Type for %s (%s): " file ct + (if (mew-syntax-multipart-p syntax) + mew-mime-content-type-multipart-list + mew-mime-content-type-list))) + (setq ctl (list ct)) + (mew-syntax-set-ct syntax ctl) + (setq cte (mew-ctdb-cte (mew-ctdb-by-ct ct))) + (mew-syntax-set-cte syntax cte) + (mew-syntax-set-cdp syntax (mew-syntax-cdp-format ct file)) + (mew-encode-syntax-print mew-encode-syntax)))) + +(defun mew-attach-charset () + "Specify the charset parameter for a Text/* object in attachments." + (interactive) + (mew-attach-charset-base "charset")) + +(defun mew-attach-icharset () + "Specify a input coding-system for a text file in attachments." + (interactive) + (mew-attach-charset-base "icharset")) + +(defun mew-attach-charset-base (param) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot specify character set here") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (file (mew-syntax-get-file syntax)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (params (mew-syntax-get-params ctl)) + (char (mew-syntax-get-param ctl param)) + charset) + (if (not (mew-ct-textp ct)) + (message "Cannot use character set %s" ct) + (unless char (setq char "guess")) + (setq charset (mew-input-type + (if (string= param "charset") + "Output message charset for %s (%s): " + "Input file charset for %s (%s): ") + file char + (cons "guess" mew-charset-list))) + (setq params (mew-delete param params)) + (if (string= charset "guess") + (setq ctl (cons ct params)) + (setq ctl (cons ct (cons (list param charset) params)))) + (mew-syntax-set-ct syntax ctl) + (mew-encode-syntax-print mew-encode-syntax))))) + +(defun mew-attach-description () + "Input a description(Content-Description:) in attachments." + (interactive) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot describe here") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (ocd (or (mew-syntax-get-cd syntax) (mew-syntax-get-file syntax))) + (cd (read-string "Description: " ocd))) + (if (string= cd "") + (mew-syntax-set-cd syntax nil) + (mew-syntax-set-cd syntax cd)) + (mew-encode-syntax-print mew-encode-syntax)))) + +(defun mew-attach-disposition () + "Input Content-Disposition: in attachments." + (interactive) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot set disposition here") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (oldfile (or (mew-syntax-get-param (mew-syntax-get-cdp syntax) + "filename") + (mew-syntax-get-file syntax))) + (file (read-string "Filename: " oldfile))) + (if (string= file "") + (mew-syntax-set-cdp syntax nil) + (mew-syntax-set-cdp syntax (mew-syntax-cdp-format ct file nil 'force-file))) + (mew-encode-syntax-print mew-encode-syntax)))) + +(defun mew-attach-base64 () + "Put the 'B' mark to encode with Base64 in attachments." + (interactive) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot encode with base64 here") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap))) + (if (or (mew-ct-messagep ct) (mew-ct-multipartp ct)) + (message "Cannot encode with base64 here") + (mew-syntax-set-cte syntax mew-b64) + (mew-encode-syntax-print mew-encode-syntax))))) + +(defun mew-attach-quoted-printable () + "Put the 'Q' mark to encode with Quoted-Printable in attachments" + (interactive) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot encode with quoted-printable here") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap))) + (if (or (mew-ct-messagep ct) (mew-ct-multipartp ct)) + (message "Cannot encode with quoted-printable here") + (mew-syntax-set-cte syntax mew-qp) + (mew-encode-syntax-print mew-encode-syntax))))) + +(defun mew-attach-gzip64 () + "Put the 'G' mark to encode with Gzip64 in attachments. This is +applicable only to Text/Plain and Application/Postscript since compression +is not effective other objects. For example, JPEG is already compressed." + (interactive) + (if (not (mew-attach-not-line0-1-dot)) + (message "Cannot apply gzip here") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap))) + (if (or (mew-ct-messagep ct) + (mew-ct-multipartp ct) + (not (mew-ct-linebasep ct))) + ;; never use compress to types other than text/plain or + ;; application/postscript. Indeed, compression is not + ;; effective to compressed data such as jpeg. + (message "Cannot apply gzip to %s" ct) + (mew-syntax-set-cte syntax mew-xg) + (mew-encode-syntax-print mew-encode-syntax))))) + +(defun mew-attach-zip () + "Put the 'Z' mark and encrypt it with \"zip\" in attachments." + (interactive) + (if (not (mew-attach-not-line02-1-dot)) + (message "Cannot encrypt with zip here") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap))) + (if (or (mew-ct-messagep ct) (mew-ct-multipartp ct)) + (message "Cannot encrypt with zip here") + (if (not (mew-which-exec mew-prog-zip)) + (message "\"zip\" not found") + (let ((password (mew-read-passwd "Zip password: ")) + (password1 (mew-read-passwd "Zip password again: "))) + (if (not (string= password password1)) + (message "Password mismatch!") + (let* ((subdir (mew-attach-expand-path mew-encode-syntax nums)) + (attachdir (mew-attachdir)) + (name (mew-syntax-get-file syntax)) + (ename (if (string= subdir "") name (concat subdir name))) + (fullname (expand-file-name ename attachdir)) + (zname (concat name ".zip")) + (zfullname (concat fullname ".zip")) + (zct "application/zip") + (default-directory (file-name-directory fullname))) + ;; must not specify the "-e" option due to + ;; variety of zip versions. + (call-process mew-prog-zip nil nil nil "-P" password zname name) + (if (not (file-exists-p zfullname)) + (if (string= password "") + (message "\"zip\" does not allow zero length password") + (message "\"zip\" does not support encryption")) + (mew-syntax-set-ct syntax (list zct)) + (mew-syntax-set-cte syntax mew-b64) + (mew-syntax-set-file syntax zname) + (mew-syntax-set-cdp syntax (mew-syntax-cdp-format zct zname)) + (mew-encode-syntax-print mew-encode-syntax)))))))))) + +(defun mew-attach-pgp-sign () + "Put the 'PS' mark to sign with PGP in attachments." + (interactive) + (cond + ((not (mew-attach-not-line0-1-dot)) + (message "Cannot PGP sign here")) + ((null mew-pgp-ver) + (message "%s does not exist" mew-prog-pgp)) + (t + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (privacy (mew-syntax-get-privacy syntax)) + (pgp-sign (mew-pcdb-ct (mew-pcdb-by-service 'pgp-signature)))) + (cond + ((>= (length privacy) 2) + (message "Too many marks")) + ((member (car pgp-sign) privacy) ;; xxx hard coding + (message "Already marked")) + (t + (mew-syntax-set-privacy + syntax (append privacy pgp-sign)) + (mew-encode-syntax-print mew-encode-syntax))))))) + +(defun mew-attach-pgp-enc () + "Put the 'PE' mark to encrypt with PGP in attachment. +Input decrypters' addresses." + (interactive) + (cond + ((not (mew-attach-not-line0-1-dot)) + (message "Cannot PGP encrypt here")) + ((null mew-pgp-ver) + (message "%s does not exist" mew-prog-pgp)) + (t + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (privacy (mew-syntax-get-privacy syntax)) + (towhom (mew-header-parse-address-list mew-destination:-list)) + (pgp-enc (mew-pcdb-ct (mew-pcdb-by-service 'pgp-encryption)))) + (cond + ((>= (length privacy) 2) + (message "Too many marks")) + ((member (car pgp-enc) privacy) ;; xxx hard coding + (message "Already marked")) + (t + ;; ask towhom before set privacy for C-g + (if towhom + (setq towhom (mew-input-address "To (%s): " (mew-join "," towhom))) + (setq towhom (mew-input-address "To: "))) + ;; towhom is already canonicalized. + (mew-syntax-set-privacy + syntax (append privacy pgp-enc)) + (mew-syntax-set-decrypters syntax towhom) + (mew-encode-syntax-print mew-encode-syntax))))))) + +(defun mew-attach-smime-sign () + "Put the 'PS' mark to sign with S/MIME in attachments." + (interactive) + (cond + ((not (mew-attach-not-line0-1-dot)) + (message "Cannot S/MIME sign here")) + ((null mew-smime-ver) + (message "%s does not exist" mew-prog-smime)) + (t + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (privacy (mew-syntax-get-privacy syntax)) + (smime-sign (mew-pcdb-ct (mew-pcdb-by-service 'smime-signature)))) + (cond + ((>= (length privacy) 2) + (message "Too many marks")) + ((member (car smime-sign) privacy) ;; xxx hard coding + (message "Already marked")) + (t + (mew-syntax-set-privacy + syntax (append privacy smime-sign)) + (mew-encode-syntax-print mew-encode-syntax))))))) + +(defun mew-attach-smime-enc () + "Put the 'SE' mark to encrypt with S/MIME in attachment. +Input decrypters' addresses." + (interactive) + (cond + ((not (mew-attach-not-line0-1-dot)) + (message "Cannot S/MIME encrypt here")) + ((null mew-smime-ver) + (message "%s does not exist" mew-prog-smime)) + (t + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (privacy (mew-syntax-get-privacy syntax)) + (towhom (mew-header-parse-address-list mew-destination:-list)) + (smime-enc (mew-pcdb-ct (mew-pcdb-by-service 'smime-encryption)))) + (cond + ((>= (length privacy) 2) + (message "Too many marks")) + ((member (car smime-enc) privacy) ;; xxx hard coding + (message "Already marked")) + (t + ;; ask towhom before set privacy for C-g + (if towhom + (setq towhom (mew-input-address "To (%s): " (mew-join "," towhom))) + (setq towhom (mew-input-address "To: "))) + ;; towhom is already canonicalized. + (mew-syntax-set-privacy + syntax (append privacy smime-enc)) + (mew-syntax-set-decrypters syntax towhom) + (mew-encode-syntax-print mew-encode-syntax))))))) +;; +;; find commands +;; + +(defun mew-attach-find-file () + "Open this file into a buffer in attachments." + (interactive) + (if (not (mew-attach-not-line012-1-dot)) + (message "Cannot find a file here") + (let* ((nums (mew-syntax-nums)) + (subdir (mew-attach-expand-path mew-encode-syntax nums)) + (attachdir (mew-attachdir)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums)) + (file (mew-syntax-get-file syntax)) + efile FILE) + (setq efile (if (string= subdir "") file (concat subdir file))) + (setq FILE (expand-file-name efile attachdir)) + (switch-to-buffer (mew-find-file-noselect2 FILE)) + ;; buffer switched + (local-set-key "\C-c\C-q" 'mew-kill-buffer) + (if (file-symlink-p FILE) + (message "This file is a symbolic link. Take care"))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Drag & Drop +;; + +(defun mew-draft-dnd-handle-local-file (uri action) + (let* ((from (dnd-get-local-file-name uri t)) + (to (if from (file-name-nondirectory from) + (error "Can not read %s" uri) nil))) + (when from + (unless (mew-attach-p) + (mew-draft-prepare-attachments)) + (goto-char (point-max)) + (forward-line -2) + (mew-attach-next) + (cond + ((file-directory-p from) + (message "Directory cannot be attached")) + ((or (eq action 'copy) + (eq action 'private) + (eq action 'move)) + (mew-attach-copy from to)) + ((eq action 'link) + (mew-attach-link from to)) + (t + (message "Nothing happened")))))) + +(defun mew-draft-dnd-handle-remote-url (uri _action) + (error "Remote files not supported") nil) + +(defvar mew-draft-dnd-handle-remote-file-function + (if (eq system-type 'windows-nt) + 'mew-draft-dnd-handle-local-file + 'mew-draft-dnd-handle-remote-url)) + +(defun mew-draft-dnd-handle-file (uri action) + (let ((local-file (dnd-get-local-file-uri uri))) + (if local-file + (mew-draft-dnd-handle-local-file local-file action) + (if mew-draft-dnd-handle-remote-file-function + (funcall mew-draft-dnd-handle-remote-file-function uri action) + (error "Remote files not supported") nil)))) + +(provide 'mew-attach) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-attach.el ends here diff --git a/elpa/mew-20150813.2354/mew-auth.el b/elpa/mew-20150813.2354/mew-auth.el new file mode 100644 index 00000000..eaf66773 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-auth.el @@ -0,0 +1,102 @@ +;;; mew-auth.el + +;; Author: Kazu Yamamoto +;; Created: Aug 17, 1999 + +;;; Code: + +(require 'mew) + +(defun mew-auth-select (grt lst) + (mew-auth-select2 (mew-split grt mew-sp) lst)) + +(defun mew-auth-select2 (auths lst) + (let (n preference strongest) + (dolist (auth auths) + (setq n (mew-member-case-equal auth lst)) + (cond + ((null n) ()) + ((null preference) + (setq preference n) + (setq strongest auth)) + ((< n preference) + (setq preference n) + (setq strongest auth)))) + strongest)) + +(defun mew-md5-raw (str) + (let* ((md5str (mew-md5 str)) + (len (length md5str)) + (md5raw (make-string (/ len 2) 0)) + (i 0) (j 0)) + (while (< i len) + (aset md5raw j (+ (* (mew-hexchar-to-int (aref md5str i)) 16) + (mew-hexchar-to-int (aref md5str (1+ i))))) + (setq i (+ i 2)) + (setq j (1+ j))) + md5raw)) + +;; (mew-hmac-md5 "what do ya want for nothing?" "Jefe") +;; -> 0x750c783e6ab0b503eaa86e310a5db738 + +(defun mew-hmac-md5 (message key) + "HMAC-MD5 defined in RFC 2104" + (let* ((keylen (length key)) + (ipad 54) ;; 0x36 + (opad 92) ;; 0x5c + (ikey (make-string 64 0)) + okey digest) + (when (< keylen 64) + (dotimes (i keylen) + (aset ikey i (aref key i)))) + (setq okey (copy-sequence ikey)) + (dotimes (i 64) + (aset ikey i (logxor (aref ikey i) ipad)) + (aset okey i (logxor (aref okey i) opad))) + (setq digest (mew-md5-raw (concat ikey message))) + (mew-md5 (concat okey digest)))) + +(defun mew-cram-md5 (user passwd b64-challenge) + "CRAM-MD5 defined in RFC 2195" + (let* ((challenge (mew-base64-decode-string b64-challenge)) + (response (mew-hmac-md5 challenge passwd))) + (mew-base64-encode-string (format "%s %s" user response)))) + +;; + +(defun mew-keyed-md5 (key passwd) + (mew-md5 (concat key passwd))) + +(provide 'mew-auth) + +;;; Copyright Notice: + +;; Copyright (C) 2000-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-auth.el ends here diff --git a/elpa/mew-20150813.2354/mew-autoloads.el b/elpa/mew-20150813.2354/mew-autoloads.el new file mode 100644 index 00000000..81c2efae --- /dev/null +++ b/elpa/mew-20150813.2354/mew-autoloads.el @@ -0,0 +1,81 @@ +;;; mew-autoloads.el --- automatically extracted autoloads +;; +;;; Code: +(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +;;;### (autoloads nil "mew" "mew.el" (22007 46197 0 0)) +;;; Generated autoloads from mew.el + +(autoload 'mew "mew" "\ +Execute Mew first unless Mew is running. And retrieve arrived +messages or just visit to the default folder. + +'proto' is determined by 'mew-proto' and 'mew-case'. + +If 'proto' is '+' (ie a local folder), a mailbox is determined +according to 'mew-mailbox-type'. Otherwise (ie a remote folder), an +appropriate protocol to retrieve messages is chosen according to +'proto'. + +If 'mew-auto-get' is 't', arrived messages are asynchronously fetched +and listed up in Summary mode. + +'mew-auto-get' is 'nil', just visit to the folder determined by +'proto'. + +When executed with '\\[universal-argument]', 'mew-auto-get' is +considered reversed. + +\(fn &optional ARG)" t nil) + +(autoload 'mew-send "mew" "\ +Execute Mew then prepare a draft. This may be used as library +function. + +\(fn &optional TO CC SUBJECT)" t nil) + +(autoload 'mew-user-agent-compose "mew" "\ +Set up message composition draft with Mew. +This is 'mail-user-agent' entry point to Mew. + +The optional arguments TO and SUBJECT specify recipients and the +initial Subject field, respectively. + +OTHER-HEADERS is an alist specifying additional +header fields. Elements look like (HEADER . VALUE) where both +HEADER and VALUE are strings. + +A Draft buffer is prepared according to SWITCH-FUNCTION. + +CONTINUE, YANK-ACTION and SEND-ACTIONS are ignored. + +\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-FUNCTION YANK-ACTION SEND-ACTIONS &rest DUMMY)" nil nil) + +;;;*** + +;;;### (autoloads nil nil ("mew-addrbook.el" "mew-attach.el" "mew-auth.el" +;;;;;; "mew-blvs.el" "mew-bq.el" "mew-cache.el" "mew-complete.el" +;;;;;; "mew-config.el" "mew-const.el" "mew-darwin.el" "mew-decode.el" +;;;;;; "mew-demo.el" "mew-draft.el" "mew-edit.el" "mew-encode.el" +;;;;;; "mew-env.el" "mew-exec.el" "mew-ext.el" "mew-fib.el" "mew-func.el" +;;;;;; "mew-gemacs.el" "mew-header.el" "mew-highlight.el" "mew-imap.el" +;;;;;; "mew-imap2.el" "mew-key.el" "mew-lang-jp.el" "mew-lang-kr.el" +;;;;;; "mew-lang-latin.el" "mew-local.el" "mew-mark.el" "mew-message.el" +;;;;;; "mew-mime.el" "mew-minibuf.el" "mew-mule.el" "mew-mule3.el" +;;;;;; "mew-net.el" "mew-nntp.el" "mew-nntp2.el" "mew-passwd.el" +;;;;;; "mew-pgp.el" "mew-pick.el" "mew-pkg.el" "mew-pop.el" "mew-refile.el" +;;;;;; "mew-scan.el" "mew-search.el" "mew-smime.el" "mew-smtp.el" +;;;;;; "mew-sort.el" "mew-ssh.el" "mew-ssl.el" "mew-summary.el" +;;;;;; "mew-summary2.el" "mew-summary3.el" "mew-summary4.el" "mew-syntax.el" +;;;;;; "mew-thread.el" "mew-unix.el" "mew-vars.el" "mew-vars2.el" +;;;;;; "mew-vars3.el" "mew-varsx.el" "mew-virtual.el" "mew-win32.el") +;;;;;; (22007 46198 630682 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; End: +;;; mew-autoloads.el ends here diff --git a/elpa/mew-20150813.2354/mew-blvs.el b/elpa/mew-20150813.2354/mew-blvs.el new file mode 100644 index 00000000..e454e03b --- /dev/null +++ b/elpa/mew-20150813.2354/mew-blvs.el @@ -0,0 +1,90 @@ +;;; mew-blvs.el + +;; Author: Kazu Yamamoto +;; Created: Feb 1, 1999 + +;;; Code: + +(require 'mew) + +;;; +;;; Buffer local variables +;;; + +;; All buffer local variables which Mew defines should be here. +;; They are made buffer local by make-variable-buffer-local. +;; They are used internal purpose only (i.e. not user options). +;; When Mew makes a buffer local variable which another package +;; defines, make-local-variable should be used. + +;; Inevitable due to mode-line. +(defvar mew-summary-buffer-process nil) +(defvar mew-summary-buffer-process-status nil) +(defvar mew-summary-buffer-process-error nil) +(defvar mew-summary-buffer-secure-process nil) +(defvar mew-summary-buffer-left-msgs nil) +(defvar mew-summary-buffer-raw nil) + +(defvar mew-decode-syntax nil) ;; just for convenience +(defvar mew-encode-syntax nil) ;; just for convenience + +(defvar mew-ainfo nil) ;; Any buffers +(defvar mew-cinfo nil) ;; Cache +(defvar mew-dinfo nil) ;; Decode +(defvar mew-minfo nil) ;; Message mode +(defvar mew-sinfo nil) ;; Summary mode +(defvar mew-tinfo nil) ;; Draft mode +(defvar mew-vinfo nil) ;; Virtual mode +(defvar mew-xinfo nil) ;; Analyzed + +(mapc 'make-variable-buffer-local + (list 'mew-summary-buffer-process + 'mew-summary-buffer-process-status + 'mew-summary-buffer-process-error + 'mew-summary-buffer-secure-process + 'mew-summary-buffer-left-msgs + 'mew-summary-buffer-raw + 'mew-decode-syntax + 'mew-encode-syntax + 'mew-ainfo + 'mew-cinfo + 'mew-dinfo + 'mew-minfo + 'mew-sinfo + 'mew-tinfo + 'mew-vinfo + 'mew-xinfo)) + +(provide 'mew-blvs) + +;;; Copyright Notice: + +;; Copyright (C) 2000-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-blvs.el ends here diff --git a/elpa/mew-20150813.2354/mew-bq.el b/elpa/mew-20150813.2354/mew-bq.el new file mode 100644 index 00000000..8e2166ee --- /dev/null +++ b/elpa/mew-20150813.2354/mew-bq.el @@ -0,0 +1,1199 @@ +;;; mew-bq.el --- Base64 and Quoted-Printable encoding for Mew + +;; Author: Kazu Yamamoto +;; Created: Aug 20, 1997 + +;;; Code: + +(require 'mew) + +(defvar mew-header-encode-switch + '(("B" . mew-base64-encode-string) + ("Q" . mew-q-encode-string))) + +(defun mew-header-encode-get-func (b-or-q) + (cdr (mew-assoc-case-equal b-or-q mew-header-encode-switch 0))) + + +(defvar mew-header-decode-switch + `(("B" + mew-base64-decode-string + mew-base64-decode-error-string + ,mew-error-invalid-b-encoding) + ("Q" + mew-q-decode-string + nil + ,mew-error-invalid-q-encoding))) + +(defun mew-header-decode-get-func (b-or-q) + (nth 1 (mew-assoc-case-equal b-or-q mew-header-decode-switch 0))) + +(defun mew-header-decode-get-error-func (b-or-q) + (nth 2 (mew-assoc-case-equal b-or-q mew-header-decode-switch 0))) + +(defun mew-header-decode-get-error-str (b-or-q) + (nth 3 (mew-assoc-case-equal b-or-q mew-header-decode-switch 0))) + +(defconst mew-header-decode-regex + "=\\?\\([^? \t]+\\)\\?\\(.\\)\\?\\([^? \t]+\\)\\?=") + +(defconst mew-header-decode-regex2 + "[ \t]*=\\?\\([^? \t]+\\)\\?\\(.\\)\\?\\([^? \t]+\\)\\?=") + +(defconst mew-header-decode-regex3 + "^\\([ \t]+\\)=\\?[^? \t]+\\?.\\?[^? \t]+\\?=") + +(defconst mew-header-param-regex + "^\\([^=*]+\\)\\(\\|\\*[0-9]+\\)\\(\\*?\\)=\\(.*\\)$") + +;;; +;;; +;;; + +(defun mew-header-sanity-check-string (str) + (if (null str) + str + (let ((regex mew-regex-ctls)) + (while (string-match regex str) + (setq str (replace-match "" nil t str))) + str))) + +(defun mew-header-sanity-check-string2 (str key) + (if (null str) + str + (let ((regex mew-regex-ctls-wo-tab)) + (if (not (string-match regex str)) + str + (mew-decode-warning-fields key 'ctl) + (setq str (replace-match "" nil t str)) + (while (string-match regex str) + (setq str (replace-match "" nil t str))) + str)))) + +(defun mew-header-sanity-check-region (beg end &optional key) + (let ((regex mew-regex-ctls-wo-tab-lf)) + ;; meaningless tabs are removed by mew-header-decode-region + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (when (re-search-forward regex nil t) + (if key (mew-decode-warning-fields key 'ctl)) + (replace-match "" nil t) + (while (re-search-forward regex nil t) + (replace-match "" nil t)))))) + +(defun mew-header-encode (charset b-or-q fun hcs str) + ;; sanity check should be done + (let* ((estr (mew-cs-encode-string str hcs))) + (concat "=?" charset "?" b-or-q "?" (funcall fun estr) "?="))) + +(defun mew-header-decode (charset b-or-q estr &optional key) + (let* ((fun (mew-header-decode-get-func b-or-q)) + (cs (mew-charset-to-cs charset)) + str) + (when (and mew-use-autoconv-when-unknown + (not (mew-coding-system-p cs))) + (setq cs mew-cs-autoconv)) + (cond + ((not (mew-coding-system-p cs)) + mew-error-unknown-charset) + (fun ;; if cs is nil, mew-cs-decode-string does not cs-decode. + (setq str (funcall fun estr)) + (unless str (setq str (mew-header-decode-error key b-or-q estr))) + (if (null str) + (mew-header-decode-get-error-str b-or-q) + (when (and mew-decode-broken + (not (eq cs mew-cs-autoconv)) + (or (null charset) + (mew-case-equal charset mew-us-ascii) + (mew-case-equal charset mew-utf-8)) + (string-match mew-regex-singlebyte-nonascii str)) + (setq cs mew-cs-autoconv)) + (if (null cs) + str + (mew-cs-decode-string str cs)))) + (t estr)))) + +(defun mew-header-decode-error (key b-or-q estr) + (let ((func (mew-header-decode-get-error-func b-or-q))) + (if func (funcall func key b-or-q estr)))) + +(defun mew-base64-decode-error-string (key b-or-q estr) + (let ((str estr) strlen r ret) + (when (string-match "^\\([^=]*\\)=*$" str) + (setq str (mew-match-string 1 str))) + (setq strlen (length str)) + (setq r (% strlen 4)) + (cond + ((= r 0) + (setq ret (mew-base64-decode-string str))) + ((= r 1) + ) + ((= r 2) + (setq ret (mew-base64-decode-string (concat str "==")))) + ((= r 3) + (setq ret (mew-base64-decode-string (concat str "="))))) + (if ret (mew-decode-warning-fields key 'padding)) + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Quoted-printable encoding +;;; + +(defun mew-q-encode-string (str &optional prefix) + (let* ((len (length str)) + (ret (mew-make-string (* len 3))) + (j 0) char) + (dotimes (i len) + (setq char (aref str i)) + (cond + ((char-equal char mew-sp) + (aset ret j ?_)) + ((and (> char mew-sp) + (< char 126) + (not (char-equal char ?=)) + (not (char-equal char ??)) + (not (char-equal char ?_)) ;; space + (or (not prefix) (not (memq char '(?# ?@))))) + (aset ret j char)) + (t + (aset ret j (or prefix ?=)) + (setq j (1+ j)) + (aset ret j (aref "0123456789ABCDEF" (lsh char -4))) + (setq j (1+ j)) + (aset ret j (aref "0123456789ABCDEF" (logand char 15))))) + (setq j (1+ j))) + (substring ret 0 j))) + +(defun mew-samba-encoding (str) + (setq str (mew-cs-encode-string str mew-cs-samba)) + (let* ((len (length str)) + (ret (mew-make-string (* len 3))) + (j 0) char type) + (cond + ((eq mew-use-samba-encoding-type 'cap) + (setq type 'cap)) + (t + (setq type 'hex))) + (dotimes (i len) + (setq char (aref str i)) + (if (and (eq type 'cap) (< char 128)) + (aset ret j char) + (aset ret j ?:) + (setq j (1+ j)) + (aset ret j (aref "0123456789abcdef" (lsh char -4))) + (setq j (1+ j)) + (aset ret j (aref "0123456789abcdef" (logand char 15)))) + (setq j (1+ j))) + (substring ret 0 j))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Quoted-printable decoding +;;; + +(defun mew-hexchar-to-int (hex) + ;; would return nil if error + (cond + ((and (<= ?0 hex) (<= hex ?9)) (- hex ?0)) + ((and (<= ?A hex) (<= hex ?F)) (+ (- hex ?A) 10)) + ((and (<= ?a hex) (<= hex ?f)) (+ (- hex ?a) 10)))) + +(defun mew-q-decode-string (qpstr &optional okey) + (condition-case nil + (let* ((len (length qpstr)) + (ret (mew-make-string len)) + (j 0) char key) + (setq key (or okey ?=)) + (dotimes (i len) + (setq char (aref qpstr i)) + (cond + ((and (not okey) (char-equal char ?_)) + (aset ret j mew-sp)) + ((char-equal char key) + (aset ret j (+ (* (mew-hexchar-to-int (aref qpstr (1+ i))) 16) + (mew-hexchar-to-int (aref qpstr (+ i 2))))) + (setq i (+ i 2))) + (t + (aset ret j char))) + (setq j (1+ j))) + (substring ret 0 j)) + (error nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; RFC 2047 encoding +;; + +;; RFC2822 says that each line SHOULD be no more than 78 characters, +;; excluding the CRLF. +;; RFC 2047 says that encoded-word must be less than or equal to 75. +;; RFC 2047 says that each line which includes one or more encoded-words +;; must be less than or equal to 76. + +(defvar mew-encode-word-max-length 75) +(defvar mew-field-max-length 76) + +;; If possible, mew-header-encode-string should expect the length of +;; results and split 'str' before encoding so that every 'encoded-word' +;; fits in 75 length. However, it is very difficult first because +;; it is very difficult to know actual length of 'str' after convention +;; from the internal representation to charset encoding. Second because +;; ISO-2022-JP cannot be simply split. If split, extra escape sequences +;; appear. Moreover, it is not effective to expect the length of results +;; because 'str' is short enough in most cases. So, we measure the length +;; of results. If it is longer than 75, 'str' is split and 'substr1' and +;; 'substr2' are encoded.... Repeat this recursively but not so deeply. + +(defun mew-header-encode-string (str &optional key-len) + (let* ((ecsdb (or (mew-ecsdb-guess-string str) + (mew-charset-to-ecsdb (mew-charset-m17n)))) + (hcs (mew-ecsdb-hcs ecsdb)) + charset b-or-q fun) + (if (not (mew-coding-system-p hcs)) + (mew-encode-error + (format "Unknown coding system %s in the header" (symbol-name hcs))) + (setq charset (mew-cs-to-charset hcs)) + (setq b-or-q (mew-ecsdb-get-b-or-q ecsdb)) + (setq fun (mew-header-encode-get-func b-or-q)) + (if (null fun) + (mew-encode-error + (format "Unknown encoding function for %s" b-or-q)) + (mew-header-encode-string1 charset b-or-q fun hcs str key-len))))) + +(defun mew-header-encode-string1 (charset b-or-q fun hcs str &optional key-len) + (let* ((max mew-encode-word-max-length) + (encoded-word (mew-header-encode charset b-or-q fun hcs str))) + (if key-len + (setq max (- max key-len))) + (if (> (length encoded-word) max) + (let ((med (/ (length str) 2))) + (append + (mew-header-encode-string1 + charset b-or-q fun hcs (substring str 0 med) key-len) + (mew-header-encode-string1 + charset b-or-q fun hcs (substring str med)))) + (list encoded-word)))) + +(defun mew-header-encode-split-string (str) + "Split STR to need-to-encode string and non-encode-string." + (let ((start 0) beg end ret) + (while (string-match "\\(^\\|[ \t]+\\)[\t -~]+\\($\\|[ \t]+\\)" str start) + (setq beg (match-beginning 0)) + (setq end (match-end 0)) + (if (= start beg) + (setq ret (cons (substring str beg end) ret)) + (setq ret (cons (substring str beg end) + (cons (substring str start beg) ret)))) + (setq start end)) + (if (/= start (length str)) + (setq ret (cons (substring str start) ret))) + (nreverse ret))) + +(defun mew-header-encode-comma-text (str) + (let ((str-list (mapcar 'mew-chop (mew-split str ?,)))) + (mew-header-encode-text (car str-list)) + (setq str-list (cdr str-list)) + (dolist (sl str-list) + (insert ", ") ;; must be fold here + (mew-header-encode-text sl)))) + +(defmacro mew-header-encode-cond (c) + `(cond + ((> ,c 127) ;; non-ascii + (when (eq status 'space) + (insert (substring str bound i)) + (setq bound i)) + (setq status 'non-ascii)) + ;; end of non-ascii + (t ;; ascii + (cond + ((eq status 'space) + (insert (substring str bound i)) ;; spaces + (setq bound i) + (setq status 'ascii)) + ((eq status 'ascii) + (setq status 'ascii)) + ((eq status 'non-ascii) + (setq status 'non-ascii)) + ((eq status 'non-ascii-space) + (mew-header-encode-text (substring str bound SBOUND)) + ;; non-ascii + (insert (substring str SBOUND i)) ;; spaces + (setq bound i) + (setq status 'ascii)))) + ;; end of ascii + )) + +(defmacro mew-header-encode-cond2 (opt) + `(cond + ((eq status 'ascii) + (insert (substring str bound i))) + ((eq status 'space) + (insert (substring str bound i))) + ((eq status 'non-ascii) + (mew-header-encode-text (substring str bound i)) ,opt) + ((eq status 'non-ascii-space) + (mew-header-encode-text (substring str bound SBOUND) ,opt) + (insert (substring str SBOUND i))))) + +(defun mew-header-encode-addr (str) + (let* ((len (length str)) + (i 0) (bound 0) (status 'space) + SBOUND open c I) + ;; status space, ascii, non-ascii, non-ascii-space + ;; assumptions: + ;; <> does not contain non-ascii characters. + ;; () does not recurse. + ;; if " " contains non-ascii, cause an error. + (while (< i len) + (setq c (aref str i)) + (cond + ;; quote + ((char-equal c ?\") + (setq I (1+ i)) + (setq open t) + (catch 'quote + (while (< I len) + (setq c (aref str I)) + (cond + ((char-equal c ?\") + (setq open nil) + (throw 'quote nil)) + ((> c 127) + (mew-encode-error + "Only ASCII is allowed in quoted-string in the header"))) + (setq I (1+ I)))) + (if open + (mew-encode-error "Quote string must be closed in the header")) + (mew-header-encode-cond ?a) + (setq i I)) + ;; end of quote + ;; comment + ((char-equal c ?\() + (mew-header-encode-cond2 nil) + (insert "(") + (setq i (1+ i)) + (setq bound i) + (setq status 'ascii) + (setq open t) + (let (qp) + (catch 'comment + (while (< i len) + (setq c (aref str i)) + (cond + ((char-equal c ?\)) + (setq open nil) + (throw 'comment nil)) + ((char-equal c ?\") + (setq qp t)) + ((> c 127) + (setq status 'non-ascii))) + (setq i (1+ i)))) + (if (and qp (eq status 'non-ascii)) + (mew-encode-error + "Only ASCII is allowed in quoted-string in the header"))) + (if open + (mew-encode-error "Comment must be closed in the header")) + (mew-header-encode-cond2 'comment) + (if (= i len) + () + (insert ")") + (setq bound (1+ i))) + (setq status 'space)) + ;; end of () + ;; route + ((char-equal c ?<) + (mew-header-encode-cond2 nil) + (if (or (char-equal (char-before (point)) mew-sp) + (char-equal (char-before (point)) ?\t)) + (insert "<") + (insert " <")) + (setq i (1+ i)) + (setq bound i) + (setq status 'ascii) + (setq open t) + (catch 'route + (while (< i len) + (setq c (aref str i)) + (cond + ((char-equal c ?>) + (setq open nil) + (throw 'route nil)) + ((> c 127) + (mew-encode-error "<> must contain ASCII only")) + (t + (insert c))) + (setq i (1+ i)))) + (if open + (mew-encode-error "<> must be closed in the header")) + (if (= i len) + () + (insert ">") + (setq bound (1+ i))) + (setq status 'space)) + ((char-equal c ?>) + (mew-encode-error "Unbalanced <> in the header")) + ;; end of <> + + ;; group + ;; 'mailbox' between ":" and ";" should be 'addr-spec', + ;; not be 'phrase route-addr' in Mew because they are to be + ;; removed. + ((char-equal c ?:) + (mew-header-encode-cond2 nil) + ;; RFC 2047 says: + ;; An 'encoded-word' that appears within a + ;; 'phrase' MUST be separated from any adjacent 'word', 'text' or + ;; 'special' by 'linear-white-space'. + ;; However, we do not care if an 'encoded-word' is followed by + ;; ":". The spec is believed too strict. 'encoded-word' can be + ;; recognized because of the token rule. + (insert ":") + (setq i (1+ i)) + (unless (char-equal (aref str i) ?\;) + (mew-encode-error ": must be followed by ; in the header")) + (insert ";") + (setq bound (1+ i)) + (setq status 'space)) + ;; end of group + + ;; space + ((or (char-equal c mew-sp) (char-equal c ?\t)) + (cond + ((or (eq status 'ascii) (eq status 'space)) + (insert (substring str bound i)) ;; 'ascii + (setq bound i) + (setq status 'space)) + ((eq status 'non-ascii) + (setq status 'non-ascii-space) + (setq SBOUND i)))) + ;; end of white space + ;; comma + ((char-equal c ?,) + (mew-header-encode-cond2 nil) + (insert ", ") + (setq i (1+ i)) + (catch 'comma + (while (< i len) + (setq c (aref str i)) + (if (or (char-equal c mew-sp) (char-equal c ?\t) (char-equal c ?\n)) + () ;; loop + (throw 'comma nil)) + (setq i (1+ i)))) + ;; get back to the end of white spaces + (setq bound i) + (setq c mew-sp) + (setq i (1- i)) + (setq status 'space)) + ;; end of comma + ;; the others + (t (mew-header-encode-cond c))) + ;; end of outside cond + (setq i (1+ i))) + ;; end of while + (mew-header-encode-cond2 nil))) + +(defun mew-header-encode-text (str &optional comment key-len) + ;; 'comment' means that we are in RFC822 comment "(...)". + (let ((str-list (mew-header-encode-split-string str)) + head-is-e e-list) + (if (string-match "^[\t -~]+$" (car str-list)) + (progn + ;; ascii + (insert (car str-list)) + (setq str-list (cdr str-list))) + (setq head-is-e t)) + (while str-list + ;; encoded-words + (if (and key-len head-is-e) + (progn + (setq e-list (mew-header-encode-string (car str-list) key-len)) + (setq head-is-e nil)) + (setq e-list (mew-header-encode-string (car str-list)))) + (insert (mapconcat 'identity e-list " ")) + ;; ascii + (setq str-list (cdr str-list)) + (when (car str-list) + (insert (car str-list)) + (setq str-list (cdr str-list)))))) + +(defun mew-header-fold-region (beg end med &optional use-tab) + (let ((limit1 med) limit2) + (save-restriction + (narrow-to-region beg end) + (goto-char beg) + (while (not (eobp)) + (while (> (- (setq limit2 (save-excursion (end-of-line) (point))) + (point)) + mew-field-max-length) + (forward-char mew-field-max-length) + (if (re-search-backward "[ \t]" limit1 t) + (progn + (insert "\n") + (if use-tab + (progn + (delete-char 1) + (insert "\t")))) + ;; Ugh! + (if (re-search-forward "[ \t]" limit2 t) ;; hold on anyway + (progn + (backward-char) + (insert "\n") + (if use-tab + (progn + (delete-char 1) + (insert "\t")))) + (forward-line))) ;; give up this line + (setq limit1 (1+ (point)))) + (forward-line) + (setq limit1 (1+ (point))))))) + +(defun mew-header-resent-p (field) + (let ((case-fold-search t)) + (string-match mew-resent-regex field))) + +(defun mew-header-encode-region (beg end &optional resentp) + (let (key med type str start last fast-path) + (save-restriction + (narrow-to-region beg end) + (mew-header-sanity-check-region (point-min) (point-max)) + (mew-charset-sanity-check (point-min) (point-max)) + (goto-char (point-min)) + (while (not (eobp)) + (setq start (point)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq key (mew-match-string 1)) + (setq med (match-end 0)) + (setq type (mew-field-type-for-encoding key)) + (setq fast-path t) + (if (eq type 'mailbox) + (if resentp + (if (mew-header-resent-p key) + (setq fast-path nil)) + (if (not (mew-header-resent-p key)) + (setq fast-path nil)))) + (forward-line) + (mew-header-goto-next) + (setq last (1- (point))) + (unless (= last med) + (if (and (string= (mew-charset-guess-region med last) mew-us-ascii) + fast-path) + () ;; fast path + ;; if us-ascii AND mailbox, need to check syntax + (setq str (mew-buffer-substring med (1- (point)))) + ;; excluding \n + (delete-region med (point)) + (cond + ((eq type 'mailbox) + (mew-header-encode-addr str)) + ((eq type 'mime) + (mew-header-encode-addr str)) + ((eq type 'comma-text) + (mew-header-encode-comma-text str)) + ((eq type 'text) + (mew-header-encode-text str nil (length key))) + ((eq type 'unstruct) + (mew-header-encode-text str nil (length key)))) + (insert "\n")) ;; previously deleted, so insert here + (mew-header-fold-region start (point) med))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; RFC 2047 decoding +;; + +(defun mew-header-unfold-region (type) + (goto-char (point-min)) + (cond + ((eq type 'struct) + ;; If each line does not end with ",", unfold it. + ;; In Page 5 of RFC822 says, "Unfolding is accomplished by + ;; regarding CRLF immediately followed by a LWSP-char as + ;; equivalent to the LWSP-char". However, it also says, + ;; "In structured field bodies, multiple linear space ASCII + ;; characters (namely HTABs and SPACEs) are treated as single + ;; spaces and may freely surround any symbol." So, remove + ;; continuous white spaces. + (when (and mew-decode-broken (looking-at "\n[ \t]+")) + (replace-match "" nil t)) + (goto-char (point-min)) + (while (re-search-forward ",[ \t]+\n" nil t) + (replace-match ",\n" nil t)) + (goto-char (point-min)) + (while (re-search-forward "\\([^,]\\)[ \t]*\n[ \t]+" nil t) + (replace-match "\\1 "))) + ((eq type 'struct2) ;; for Authentication-Results: + (while (re-search-forward "[ \t]*\n[ \t]+" nil t) (replace-match " ")) + (goto-char (point-min)) + (while (search-forward ";" nil t) + (insert "\n") + (if (looking-at "[\t ]+") + (replace-match "\t") + (insert "\t")))) + ((eq type 'text) + ;; In Page 5 of RFC822 says, "Unfolding is accomplished by + ;; regarding CRLF immediately followed by a LWSP-char as + ;; equivalent to the LWSP-char". + (while (re-search-forward "\n\\([ \t]\\)" nil t) + (replace-match "\\1"))) + (t ;; unstruct + ))) + +(defun mew-header-decode-string (key) + (let ((beg (match-beginning 0)) + (end (match-end 0)) + (css (mew-header-decode (mew-match-string 1) + (mew-match-string 2) + (mew-match-string 3) + key))) + (setq css (mew-header-sanity-check-string2 css key)) + (delete-region beg end) + (insert css))) + +(defun mew-header-decode-in-quotedp () + (save-excursion + (beginning-of-line) + (char-equal (following-char) ?\"))) + +(defun mew-header-decode-in-addr-spec () + (eq (get-text-property (match-beginning 0) 'mew-addr-spec) t)) + +(defun mew-decode-warning-body (err msg) + (mew-xinfo-set-warning + (cons + (cond + ((eq err 'unknown-charset) + (format "Charset (%s) for body is not supported.\n" msg)) + ((eq err 'no-charset) + (if msg + (format "Charset (%s) for body is mis-matched.\n" msg) + "Charset for body is not specified.\n")) + ((eq err 'multi) + (format "Invalid encoding (%s) for multipart.\n" msg))) + (mew-xinfo-get-warning)))) + +(defun mew-decode-warning-fields (key err) + (unless (member key mew-no-warning-fields) + (let (wmsg level) + (cond + ((eq err 'spc) + (setq level 1) + (setq wmsg (concat "tab/spc characters on " key " are simplified.\n"))) + ((eq err 'ctl) + (setq level 1) + (setq wmsg (concat "some control code on " key " are removed.\n"))) + ((eq err 'raw) + (setq level 2) + (setq wmsg (concat key " has raw text strings.\n"))) + ((eq err 'padding) + (setq level 2) + (setq wmsg (concat key " has illegal padding in encoded text.\n"))) + ((eq err 'quoted) + (setq level 2) + (setq wmsg (concat key " has encoded-words in quoted text.\n")))) + (if (>= level mew-warning-field-level) + (mew-xinfo-set-warning (cons wmsg (mew-xinfo-get-warning))))))) + +(defun mew-decode-warning-params (param err) + (unless (and param (member (downcase param) mew-no-warning-params)) + (mew-xinfo-set-warning + (cons + (cond + ((eq err 'raw) + (concat "The '" param "' parameter has raw text.\n")) + ((eq err 'ctl) + (concat "The '" param "' has invalid control codes.\n")) + ((eq err 'enc) + (concat "The '" param "' parameter has encoded-word.\n")) + ((eq err 'char) + (concat "The '" param "' has invalid characters.\n"))) + (mew-xinfo-get-warning))))) + +(defun mew-header-decode-region (key rbeg rend &optional draftp) + "RFC 2047 decoding. This is liberal on the one point from RFC 2047. +That is, each line may be more than 75." + (setq key (capitalize key)) + (let* ((type (mew-field-type-for-decoding key)) (nl "\0")) + (save-restriction + (narrow-to-region rbeg rend) + ;; Handling invalid raw text. + (goto-char (point-min)) + (if draftp + (mew-cs-decode-region (point-min) (point-max) mew-cs-m17n) + (when (and mew-decode-broken + (re-search-forward mew-regex-esc-or-nonascii nil t)) + (mew-decode-warning-fields key 'raw) + (mew-cs-decode-region (point-min) (point-max) mew-cs-autoconv))) + ;; + (mew-header-unfold-region type) + ;; + (goto-char (point-min)) + (when (re-search-forward mew-header-decode-regex nil t) + ;; In Page 10 of RFC 2047 says, "When displaying a particular + ;; header field that contains multiple 'encoded-word's, any + ;; 'linear-white-space' that separates a pair of adjacent + ;; 'encoded-word's is ignored". So, use looking-at. + (cond + ((memq type '(text comma-text)) + ;; This is text field. We do not care quote! + ;; make use of the search above + (mew-header-decode-string key) + (while (looking-at mew-header-decode-regex2) + (mew-header-decode-string key)) + ;; + (while (re-search-forward mew-header-decode-regex nil t) + (mew-header-decode-string key) + (while (looking-at mew-header-decode-regex2) + (mew-header-decode-string key)))) + (t + ;; This is structured field. + ;; encoded-word in quoted-string should not be decoded + ;; according to RFC 2047. However, if users wish + ;; (ie mew-decode-broken is *non-nil*), decode it. + ;; Regular expression cannot express a quoted string in + ;; general case. So, canonicalize as follows: + ;; Not quoted line (may be null line) + ;; "quoted line" + ;; Not quoted line + ;; "quoted line" + ;; ... + ;; For this purpose, "\n" is converted to ^\@(\0). + (goto-char (point-min)) + (while (re-search-forward "\n" nil t) + (replace-match nl nil t)) + ;; + (goto-char (point-min)) + (while (re-search-forward mew-regex-id nil t) + (put-text-property (match-beginning 0) (match-end 0) + 'mew-addr-spec t)) + ;; + (goto-char (point-min)) + ;; Perfect regular expression for quoted strings. + ;; See "Mastering Regular Expressions", O'REILLY + (while (re-search-forward "\"\\([^\"\\\\]\\|\\\\.\\)*\"" nil t) + (goto-char (match-beginning 0)) + (insert "\n") + (goto-char (1+ (match-end 0))) + (insert "\n")) + ;; + (goto-char (point-min)) ;; anyway + ;; + (while (re-search-forward mew-header-decode-regex nil t) + (cond + ((mew-header-decode-in-addr-spec) + ) ;; do nothing + ((mew-header-decode-in-quotedp) + (when mew-decode-broken + (mew-decode-warning-fields key 'quoted) + (mew-header-decode-string key) + (while (looking-at mew-header-decode-regex2) + (mew-header-decode-string key)))) + (t + (mew-header-decode-string key) + (while (looking-at mew-header-decode-regex2) + (mew-header-decode-string key))))) + ;; Getting back to the original + (goto-char (point-min)) + (while (re-search-forward "\n" nil t) + (replace-match "" nil t)) + (goto-char (point-min)) + (while (re-search-forward nl nil t) + (replace-match "\n" nil t)) + (remove-text-properties (point-min) (point-max) '(mew-addr-spec t))))) + ;; + (if (and mew-decode-broken (member key mew-decode-ws-fields)) + (let (ws) + ;; We want to warn only in the case of ^\t. + (goto-char (point-min)) + ;; Because lines are already unfolded, we cannot tell + ;; whether or not this TABs locate on the beginning + ;; of a line. But this should be acceptable. + (while (re-search-forward "\t+" nil t) + (or ws (setq ws t)) + (replace-match " " nil t)) + (goto-char (point-min)) + ;; Continuous SPCs are not invalid, just for appearance. + (while (re-search-forward " +" nil t) + (or ws (setq ws t)) + (replace-match " " nil t)) + (if ws (mew-decode-warning-fields key 'spc)))) + ;; + (mew-header-sanity-check-region (point-min) (point-max) key) + (goto-char (point-max))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; RFC 2231 +;; + +(defun mew-param-encode (str) + (let* ((ecsdb (or (mew-ecsdb-guess-string str) + (mew-charset-to-ecsdb (mew-charset-m17n)))) + (hcs (mew-ecsdb-hcs ecsdb)) + (charset (mew-cs-to-charset hcs)) + (estr (mew-cs-encode-string str hcs)) + (len (length estr)) + (ret (mew-make-string (* len 3))) + (j 0) char) + (dotimes (i len) + (setq char (aref estr i)) + (if (or (and (<= ?0 char) (<= char ?9)) + (and (<= ?a char) (<= char ?z)) + (and (<= ?A char) (<= char ?Z))) + (aset ret j char) + (aset ret j ?%) + (setq j (1+ j)) + (aset ret j (aref "0123456789ABCDEF" (lsh char -4))) + (setq j (1+ j)) + (aset ret j (aref "0123456789ABCDEF" (logand char 15)))) + (setq j (1+ j))) + (concat charset "''" (substring ret 0 j)))) + +(defun mew-param-decode (whole-value) + (let* ((value-params (mew-addrstr-parse-value-list whole-value)) + (value (car value-params)) + (params (cdr value-params)) + (max 0) num + ret ext ext-sort entry charset cs + paramname-value paramname paramvalue) + (dolist (param params) + (setq paramname-value (mew-param-analyze param)) + (when paramname-value + (setcar paramname-value (downcase (nth 0 paramname-value))) + (if (= (length paramname-value) 2) + (setq ret (cons paramname-value ret)) + (setq ext (cons paramname-value ext)) + (setq num (nth 2 paramname-value)) + (if (> num max) (setq max num))))) + (if (null ext) + (cons value (nreverse ret)) ;; fast return + (setq max (1+ max)) + (dolist (ea ext) + (mew-set '(paramname paramvalue num) ea) + (if (setq entry (assoc paramname ext-sort)) + (progn + (aset (nth 1 entry) num paramvalue) + (when (= num 0) + (setcar (nthcdr 2 entry) (nth 3 ea)) ;; charset + (setcar (nthcdr 3 entry) (nth 4 ea)))) ;; lang + (setq entry (make-vector max nil)) + (aset entry num paramvalue) + (setq ext-sort + (cons (list paramname entry (nth 3 ea) (nth 4 ea)) + ext-sort)))) + (dolist (ea ext-sort) + (setq paramvalue nil) + (mew-set '(paramname entry charset) ea) + (setq num 0) + (catch 'concat-loop + (while (< num max) + (if (aref entry num) + (setq paramvalue (concat paramvalue (aref entry num))) ;; xxx + (throw 'concat-loop nil)) + (setq num (1+ num)))) + (when charset + (setq cs (mew-charset-to-cs charset)) + (when (and mew-use-autoconv-when-unknown + (not (mew-coding-system-p cs))) + (setq cs mew-cs-autoconv)) + (when (and mew-decode-broken + (not (eq cs mew-cs-autoconv)) + (or (null charset) + (mew-case-equal charset mew-us-ascii) + (mew-case-equal charset mew-utf-8)) + (string-match mew-regex-singlebyte-nonascii paramvalue)) + (setq cs mew-cs-autoconv)) + (if (mew-coding-system-p cs) + (setq paramvalue (mew-cs-decode-string paramvalue cs)) + (setq paramvalue mew-error-unknown-charset))) + (setq ret (cons (list paramname paramvalue) ret))) + (setq ret (mapcar 'mew-param-sanity-check ret)) + (cons value (nreverse ret))))) ;; late return + +(defun mew-param-analyze (param) + "Return (paramname paramvalue) or + (paramname paramvalue section charset lang)." + (let (name section asterisk value charset lang) + (when (string-match mew-header-param-regex param) + (setq name (match-string 1 param)) + (setq section (match-string 2 param)) ;; *21 + (setq asterisk (string= (match-string 3 param) "*")) + (setq value (match-string 4 param)) + (if (string= section "") + (if asterisk + (setq section 0) + (setq section nil)) + (setq section (string-to-number (substring section 1)))) + (if (null asterisk) + ;; delete quote + (progn + (if (and (< 1 (length value)) + (char-equal (aref value 0) 34) + (char-equal (aref value (1- (length value))) 34)) + (setq value (substring value 1 -1))) + (if mew-decode-broken + (setq value (mew-param-analyze-broken value name)))) + (when (and (= section 0) + ;; broken UAs quote extended-value, sigh + (string-match "^\"?\\([^']*\\)'\\([^']*\\)'\\([^\"]*\\)\"?$" value)) + (setq charset (match-string 1 value)) + (setq lang (match-string 2 value)) + (if (string= lang "") (setq lang nil)) + (setq value (match-string 3 value)) + (if (string= value "") (setq value nil))) + ;; broken UAs quote extended-value, sigh + (if (string-match "^\"\\([^\"]*\\)\"$" value) + (setq value (mew-match-string 1 value))) + (setq value (mew-q-decode-string value ?%))) + (if section + (list name value section charset lang) + (list name value))))) + +(defun mew-param-analyze-broken (value name) + ;; broken message handling + (when (and (mew-member-case-equal name mew-broken-parameter-list) + (string-match mew-regex-esc-or-nonascii value)) + (mew-decode-warning-params name 'raw) + (setq value (mew-cs-decode-string value mew-cs-autoconv))) + (when (string-match mew-header-decode-regex value) + (let (pre med pst) + (mew-decode-warning-params name 'enc) + (while (string-match mew-header-decode-regex value) + ;; We cannot ensure that sub-function does not use match functions. + ;; So, pre/pst prevents infinite loop. + (setq pre (substring value 0 (match-beginning 0))) + (setq pst (substring value (match-end 0))) + (setq med (mew-header-decode (match-string 1 value) + (match-string 2 value) + (match-string 3 value))) + (if (string-match mew-header-decode-regex3 pst) + (setq pst (substring pst (match-end 1)))) + (setq value (concat pre med pst))))) + value) + +(defun mew-param-sanity-check (ent) + (let (param value new) + (mew-set '(param value) ent) + (setq new (mew-header-sanity-check-string value)) + (unless (string= value new) (mew-decode-warning-params param 'ctl)) + (list param new))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Punycode:: RFC 3492 +;;; + +(defconst mew-puny-base 36) +(defconst mew-puny-tmin 1) +(defconst mew-puny-tmax 26) +(defconst mew-puny-damp 700) +(defconst mew-puny-skew 38) +(defconst mew-puny-initial-bias 72) +(defconst mew-puny-initial-n 128) +(defconst mew-puny-delimiter ?-) + +(defun mew-puny-adapt (delta numpoints firsttime) + (let ((k 0)) + (if firsttime + (setq delta (/ delta mew-puny-damp)) + (setq delta (/ delta 2))) + (setq delta (+ delta (/ delta numpoints))) + (while (> delta (/ (* (- mew-puny-base mew-puny-tmin) mew-puny-tmax) 2)) + (setq delta (/ delta (- mew-puny-base mew-puny-tmin))) + (setq k (+ k mew-puny-base))) + (+ k (/ (* (1+ (- mew-puny-base mew-puny-tmin)) delta) (+ delta mew-puny-skew))))) + +(defun mew-puny-decode-digit (cp) + (if (< (- cp 48) 10) + (- cp 22) + (if (< (- cp 65) 26) + (- cp 65) + (if (< (- cp 97) 26) + (- cp 97) + mew-puny-base)))) + +(defun mew-puny-encode-digit (d) + (if (< d 26) + (+ d 22 75) ;; a-z + (+ d 22))) ;; 0-9 + +(defun mew-puny-decode (input) + (when mew-cs-utf-16be + (condition-case nil + (mew-cs-decode-string + (mew-puny-decode1 (substring input 4)) ;; xn-- + mew-cs-utf-16be) + (error nil)))) + +(defun mew-puny-decode1 (input) + (let* ((n mew-puny-initial-n) + (bias mew-puny-initial-bias) + (len (length input)) + (in 0) (out 0) + (i 0) (b 0) + digit thr oldi w k output ret) + (dotimes (j len) + (if (= (aref input j) mew-puny-delimiter) (setq b j))) + (dotimes (j b) + (setq output (cons (aref input j) output)) + (setq out (1+ out))) + (setq output (nreverse output)) + (if (> b 0) (setq in (1+ b)) (setq in 0)) + (while (< in len) + (setq oldi i) + (setq w 1) + (setq k mew-puny-base) + (catch 'loop + (while t + (if (>= in len) (error "punycode bad input")) + (setq digit (mew-puny-decode-digit (aref input in))) + (if (>= digit mew-puny-base) (error "punycode bad input")) + (setq in (1+ in)) + (setq i (+ i (* digit w))) + (if (<= k bias) + (setq thr mew-puny-tmin) + (if (>= k (+ bias mew-puny-tmax)) + (setq thr mew-puny-tmax) + (setq thr (- k bias)))) + (if (< digit thr) (throw 'loop nil)) + (setq w (* w (- mew-puny-base thr))) + (setq k (+ k mew-puny-base)))) + (setq out (1+ out)) + (setq bias (mew-puny-adapt (- i oldi) out (= oldi 0))) + (setq n (+ n (/ i out))) + (setq i (% i out)) + (if (= i 0) + (setq output (cons n (nthcdr i output))) + (setcdr (nthcdr (1- i) output) (cons n (nthcdr i output)))) + (setq i (1+ i))) + (setq ret (mew-make-string (* out 2))) + (let ((j 0)) + (dolist (op output) + (aset ret j (/ op 256)) + (setq j (1+ j)) + (aset ret j (% op 256)) + (setq j (1+ j)))) + ret)) + +(defun mew-puny-encode (input) + (when mew-cs-utf-16be + (condition-case nil + (concat "xn--" (mew-puny-encode1 (mew-cs-encode-string input mew-cs-utf-16be))) + (error nil)))) + +(defun mew-puny-encode1 (input) + (let* ((len (length input)) + (h-len (/ len 2)) + (n mew-puny-initial-n) + (bias mew-puny-initial-bias) + (delta 0) (out 0) + (output (mew-make-string (* len 4))) + h b m q k thr uni) + (dotimes (j len) + (setq uni (aref input j)) + (setq j (1+ j)) + (setq uni (+ (* uni 256) (aref input j))) + (when (< uni 128) ;; basic + (aset output out uni) + (setq out (1+ out)))) + (setq h out) + (setq b out) + (when (> b 0) + (aset output out mew-puny-delimiter) + (setq out (1+ out))) + (while (< h h-len) + (setq m 65536) ;; 17bits + (dotimes (j len) + (setq uni (aref input j)) + (setq j (1+ j)) + (setq uni (+ (* uni 256) (aref input j))) + (if (and (>= uni n) (< uni m)) (setq m uni))) + (setq delta (+ delta (* (- m n) (1+ h)))) + (setq n m) + (dotimes (j len) + (setq uni (aref input j)) + (setq j (1+ j)) + (setq uni (+ (* uni 256) (aref input j))) + (when (< uni n) + (setq delta (1+ delta)) + (if (= delta 0) (error "punycode overflow"))) + (when (= uni n) + (setq q delta) + (setq k mew-puny-base) + (catch 'loop + (while t + (if (<= k bias) + (setq thr mew-puny-tmin) + (if (>= k (+ bias mew-puny-tmax)) + (setq thr mew-puny-tmax) + (setq thr (- k bias)))) + (if (< q thr) (throw 'loop nil)) + (aset output out (mew-puny-encode-digit (+ thr (% (- q thr) (- mew-puny-base thr))))) + (setq out (1+ out)) + (setq q (/ (- q thr) (- mew-puny-base thr))) + (setq k (+ k mew-puny-base)))) + (aset output out (mew-puny-encode-digit q)) + (setq out (1+ out)) + (setq bias (mew-puny-adapt delta (1+ h) (= h b))) + (setq delta 0) + (setq h (1+ h)))) + (setq delta (1+ delta)) + (setq n (1+ n))) + (substring output 0 out))) + +(defun mew-puny-encode-url (url) + (let (beg end idn) + (with-temp-buffer + (insert url) + (goto-char (point-min)) + (if (search-forward "://" nil t) + (setq beg (point)) + (setq beg (point-min))) + (if (search-forward "/" nil t) + (setq end (1- (point))) + (setq end (point-max))) + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (while (re-search-forward "[^.]?[^.\000-\177][^.]*" nil t) + (setq idn (mew-match-string 0)) + (delete-region (match-beginning 0) (match-end 0)) + (insert (mew-puny-encode idn)))) + (mew-buffer-substring (point-min) (point-max))))) + +(provide 'mew-bq) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-bq.el ends here diff --git a/elpa/mew-20150813.2354/mew-cache.el b/elpa/mew-20150813.2354/mew-cache.el new file mode 100644 index 00000000..da85f909 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-cache.el @@ -0,0 +1,265 @@ +;;; mew-cache.el --- Cache management for Mew + +;; Author: Kazu Yamamoto +;; Created: Mar 23, 1997 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Cache info +;;; + +(defvar mew-cinfo-list '("fld" "msg" "time" "size" "decode-broken")) + +(mew-blinfo-defun 'mew-cinfo mew-cinfo-list) + +(defun mew-cinfo-set (fld msg time size decode-broken) + (mew-cinfo-set-fld fld) + (mew-cinfo-set-msg msg) + (mew-cinfo-set-time time) + (mew-cinfo-set-size size) + (mew-cinfo-set-decode-broken decode-broken)) + +(defun mew-cinfo-equal (fld msg time size) + (and (string= (mew-cinfo-get-fld) fld) + (string= (mew-cinfo-get-msg) msg) + (equal (mew-cinfo-get-time) time) + (eq (mew-cinfo-get-size) size))) + +(defun mew-cache-dinfo-get-decode-broken (buf) + (when buf + (with-current-buffer buf + (mew-cinfo-get-decode-broken)))) + +(defvar mew-xinfo-list + '("decode-err" "warning" "info" "action" "multi-form" "icon-spec" + "pri-result" "not-decrypted" "text-body")) + +(mew-blinfo-defun 'mew-xinfo mew-xinfo-list) + +(defun mew-xinfo-copy (buf) + (set 'mew-xinfo (with-current-buffer buf (symbol-value 'mew-xinfo)))) + +(defun mew-xinfo-clear () + (set 'mew-xinfo nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Prepare new message --- caching +;; + +(defun mew-cache-decode-syntax (buf) + (with-current-buffer buf mew-decode-syntax)) + +(defvar mew-cache nil + "A list of decoded messages cache. +The (new ... old) order of ((\"+folder\" . \"message\") . cache-buffer)") + +(defun mew-cache-key (fld msg) + (cons fld msg)) + +(defun mew-cache-buffer-get (entry) + (cdr entry)) + +(defun mew-cache-entry-make (fld msg buf) + (cons (mew-cache-key fld msg) buf)) + +(defun mew-cache-get (fld msg) + (assoc (mew-cache-key fld msg) mew-cache)) + +(defun mew-cache-hit (fld msg &optional must-hit) + "Return the buffer associated with FLD and MSG. +If no cache entry is found, nil is returned. +If a cache entry is invalid, the entry is removed and nil is returned. +If MUST-HIT is non-nil and no valid cache entry is found, an error occurs." + (let ((entry (mew-cache-get fld msg)) + cache file time size ok) + (if (null entry) + (if must-hit + (error "Cache not found") + nil) + (setq cache (mew-cache-buffer-get entry)) + (setq file (mew-expand-msg fld msg)) + (unless (file-readable-p file) + (error "%s does not exist" (mew-concat-folder fld msg))) + (setq time (mew-file-get-time file)) + (setq size (mew-file-get-size file)) + (with-current-buffer cache + (setq ok (mew-cinfo-equal fld msg time size))) + (if ok + (progn + (mew-cache-sort entry) + cache) + (if must-hit + (error "Cache not found") + (mew-cache-delete2 fld msg) + nil))))) + +(defun mew-cache-sort (entry) + (setq mew-cache (cons entry (delq entry mew-cache)))) + +(defun mew-cache-add (fld msg) + (let ((len (length mew-cache)) + buf) + (if (< len mew-cache-size) + (setq buf (get-buffer-create (format "%s%d" mew-buffer-cache len))) + (setq buf (mew-cache-buffer-get (nth (1- len) mew-cache))) + (setcdr (nthcdr (- len 2) mew-cache) nil)) + (setq mew-cache (cons (mew-cache-entry-make fld msg buf) mew-cache)) + buf)) + +(defun mew-cache-delete () + "Delete the most recent cache entry." + (let ((buf (mew-cache-buffer-get (car mew-cache)))) + ;; must preserve the buffer itself because the buffer creation + ;; depends on the length of mew-cache. + (setq mew-cache (nconc (cdr mew-cache) + (list (mew-cache-entry-make nil nil buf)))))) + +(defun mew-cache-delete2 (fld msg) + "Delete the specific cache entry." + (let ((entry (mew-cache-get fld msg)) buf) + (if (null entry) + () + (setq buf (mew-cache-buffer-get entry)) + (setq mew-cache (delq entry mew-cache)) + (setq mew-cache (nconc mew-cache + (list (mew-cache-entry-make nil nil buf))))))) + +(defvar mew-fields-xcc + (list mew-fcc: mew-dcc: mew-bcc: + mew-resent-fcc: mew-resent-bcc: mew-resent-dcc:)) + +(defun mew-xinfo-get-xcc (fld msg) + (when (or (mew-folder-queuep fld) (mew-folder-postqp fld)) + (let ((info (concat (mew-expand-msg fld msg) mew-queue-info-suffix)) + (headers mew-fields-xcc) + data addr xinfo) + (when (and (file-readable-p info) + (setq data (aref (mew-lisp-load info) 0))) + (with-temp-buffer + (insert data) + (goto-char (point-min)) + (dolist (header headers) + (when (setq addr (mew-header-get-value header)) + (setq xinfo (cons (format "%s %s\n" header addr) xinfo))))) + (nreverse xinfo))))) + +(defun mew-disable-alternative-check () + (let ((xmailer (mew-header-get-value mew-x-mailer:)) + (regexs mew-disable-alternative-regex-list)) + (if (null xmailer) + t + (catch 'loop + (dolist (regex regexs t) + (if (string-match regex xmailer) + (throw 'loop nil))))))) + +(defun mew-cache-message (fld msg &optional unlimit no-err) + "Cache the message specified by FLD and MSG. +If an invalid message are cached, deletes it and caches the message again. +If UNLIMIT is non-nil, decodes the message to be cached without +the limitations. If NO-ERR is non-nil, an error is caused +if decode fails." + (let* ((cbuf (current-buffer)) + (cache (mew-cache-hit fld msg)) + (use-alternative mew-use-alternative) + tim-siz decode errormsg) + (catch 'return + (if cache + (progn + (set-buffer cache) + ;; Decryption may fail if password is wrong. So, try + ;; to decode this again. + (if (or (and unlimit (mew-xinfo-get-not-decrypted)) + (and unlimit (mew-xinfo-get-decode-err))) + ;; cache is invalid + (setq decode t))) + (setq cache (mew-cache-add fld msg)) + (setq decode t)) + (if (not decode) (throw 'return nil)) + ;; + (set-buffer cache) + ;; in cache buffer + (mew-erase-buffer) + (condition-case errmsg + (setq tim-siz (mew-insert-message fld msg mew-cs-text-for-read nil)) + (error + ;; file not exist + (mew-cache-delete) + (setq errormsg (nth 1 errmsg)) + (throw 'return (setq cache nil)))) + (mew-cinfo-set fld msg (car tim-siz) (cdr tim-siz) mew-decode-broken) + (if (and use-alternative mew-disable-alternative-regex-list) + (setq use-alternative (mew-disable-alternative-check))) + (mew-dinfo-set nil t t use-alternative) + (mew-decode-syntax-clear) + (mew-xinfo-set-text-body mew-use-text-body) + (condition-case nil + (if unlimit + (let ((mew-header-max-length nil) + (mew-header-max-depth nil)) + (mew-decode)) + (mew-decode)) + ;; Don't put error handing here. Because (mew-decode) would + ;; set debug-on-error to t. + (quit + ;; prefetching an encrypted message + (mew-cache-delete) + ;; The following message is not friendly to users. + ;; (message "MIME decoding for %s/%s aborted" fld msg) + (throw 'return (setq cache nil)))) + (mew-ainfo-set-icon msg) + (mew-xinfo-set-info (append (mew-xinfo-get-info) (mew-xinfo-get-xcc fld msg))) + (mew-decode-syntax-set)) + ;; + (set-buffer cbuf) + (if errormsg (if no-err (message "%s" errormsg) (error "%s" errormsg))) + cache)) ;; return value + +(defun mew-cache-clean-up () + "A function to flush all decoded messages in cache list." + (interactive) + (dotimes (n mew-cache-size) + (mew-kill-buffer (format "%s%d" mew-buffer-cache n))) + (mew-summary-reset) + (setq mew-cache nil)) + +(defalias 'mew-cache-flush 'mew-cache-clean-up) + +(provide 'mew-cache) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-cache.el ends here diff --git a/elpa/mew-20150813.2354/mew-complete.el b/elpa/mew-20150813.2354/mew-complete.el new file mode 100644 index 00000000..2f158dd7 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-complete.el @@ -0,0 +1,812 @@ +;;; mew-complete.el --- Completion magic for Mew + +;; Author: Kazu Yamamoto +;; Created: May 30, 1997 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Low level functions +;;; + +(defun mew-draft-on-field-p () + (if (bolp) + (if (bobp) + t + (save-excursion + (forward-line -1) + (if (looking-at ".*,[ \t]?$") nil t))) + (let ((pos (point))) + (save-excursion + (beginning-of-line) + (if (looking-at mew-lwsp) + nil + (if (search-forward ":" pos t) nil t)))))) + +(defun mew-draft-on-value-p (switch) + (save-excursion + (beginning-of-line) + (while (and (< (point-min) (point)) (looking-at mew-lwsp)) + (forward-line -1)) + (if (looking-at "\\([^:]*:\\)") + (mew-field-get-func (match-string 1) switch) + nil))) ;; what a case reaches here? + +;; +;; Window management for completion candidates +;; + +(defvar mew-complete-candidates nil) + +(defun mew-complete-window-delete (&optional force) + (when (mew-ainfo-get-win-cfg) + ;; (mew-ainfo-get-win-cfg) remains when the last completion + ;; finished with multiple candidates. + ;; (e.g. foo when foo and foobar are displayed.) + ;; In this case, this function is called in another + ;; completion thread but setting window configuration is not + ;; desired. If we set window configuration with the old + ;; (mew-ainfo-get-win-cfg), the cursor jumps to mini buffer. + ;; This was a stupid bug of Mew. So, let's see if the complete + ;; buffer is displayed or not. + (if (or force (get-buffer-window mew-buffer-completions)) + (set-window-configuration (mew-ainfo-get-win-cfg))) + (mew-ainfo-set-win-cfg nil)) + (mew-remove-buffer mew-buffer-completions) + (setq mew-complete-candidates nil)) + +(defun mew-complete-insert-folder-function (choice buffer mini-p base-size) + (let ((start (mew-minibuf-point-min)) + (proto (substring choice 0 1)) + (pos (point))) + (while (not (or (= start (point)) + (not (char-before)) + (char-equal (char-before) ?,))) + (forward-char -1)) + (if (and (member proto mew-folder-prefixes) + (looking-at (concat "\\(" + (regexp-opt mew-config-cases t) + ":\\)" + (regexp-quote proto)))) + (progn + (delete-region (match-end 1) pos) + (goto-char (match-end 1))) + (delete-region (point) pos)) + (insert choice) + (remove-text-properties start (point-max) '(mouse-face nil)) + (mew-complete-window-delete 'force) + t)) + +(defun mew-complete-window-show (all) + (unless (mew-ainfo-get-win-cfg) + (mew-ainfo-set-win-cfg (current-window-configuration))) + (if (and (get-buffer-window mew-buffer-completions) + (equal mew-complete-candidates all)) + (let ((win (get-buffer-window mew-buffer-completions))) + (with-current-buffer mew-buffer-completions + (if (pos-visible-in-window-p (point-max) win) + (set-window-start win 1) + (scroll-other-window)))) + (setq mew-complete-candidates all) + (with-output-to-temp-buffer mew-buffer-completions + (when mew-inherit-complete-folder + (make-local-variable 'choose-completion-string-functions) + (add-hook 'choose-completion-string-functions + 'mew-complete-insert-folder-function)) + (display-completion-list all)))) + +(defun mew-complete-backscroll () + "Backscroll the *Completion* buffer." + (interactive) + (let* ((win (get-buffer-window mew-buffer-completions)) + (height (and win (window-height win)))) + (and win (scroll-other-window (- 3 height))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Completion function for a draft only +;;; + +(defun mew-draft-set-completion-ignore-case (case) + ;; Need to set the global variable "completion-ignore-case", + ;; since clicking a candidate on a completion buffer checks + ;; the global variable. + ;; Yes, this has side-effect. + (when (mew-draft-or-header-p) + (setq completion-ignore-case case))) + +(defun mew-draft-header-comp () + "Complete and expand address short names. +First, a short name is completed. When completed solely or the @ character +is inserted before the cursor, the short name is expanded to its address." + (interactive) + (if (mew-draft-on-field-p) + (mew-complete-field) + (let ((func (mew-draft-on-value-p mew-field-completion-switch))) + (if func + (funcall func) + (tab-to-tab-stop))))) ;; default keybinding + +(defun mew-complete-field () + "Field complete function." + (interactive) + (let ((word (mew-delete-key))) ;; capitalized + (if (null word) + (mew-complete-window-show mew-fields) + (mew-complete + word + (mapcar (lambda (x) (list (concat (mew-capitalize x) " "))) mew-fields) + "field" + nil)))) + +(defun mew-complete-newsgroups () + "Newsgroup complete function." + (interactive) + (let ((word (mew-delete-backward-char))) + (if (null word) + (tab-to-tab-stop) + (mew-complete + word + (mew-nntp-folder-alist2 (mew-tinfo-get-case)) + "newsgroup" + nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Completion function for both a draft and the minibuffer +;;; + +(defun mew-complete-address () + "Complete and expand an address short name. +First alias key is completed. When completed solely or the @ character +is inserted before the cursor, the short name is expanded to its address." + (interactive) + (mew-draft-set-completion-ignore-case mew-complete-address-ignore-case) + (let ((word (mew-delete-backward-char)) + (completion-ignore-case mew-complete-address-ignore-case)) + (if (null word) + (tab-to-tab-stop) + (if mew-use-full-alias + (mew-complete + word mew-addrbook-alist "alias" nil nil nil + 'mew-addrbook-alias-get + 'mew-addrbook-alias-hit) + (if (string-match "@." word) + (insert (or (mew-addrbook-alias-next word mew-addrbook-alist) word)) + (mew-complete + word mew-addrbook-alist "alias" ?@ nil nil + 'mew-addrbook-alias-get + 'mew-addrbook-alias-hit)))))) + +(defun mew-draft-addrbook-expand () + (interactive) + (mew-draft-set-completion-ignore-case mew-complete-address-ignore-case) + (let ((word (mew-delete-backward-char)) + (completion-ignore-case mew-complete-address-ignore-case) + try) + (if (null word) + (message "No expand key") + (setq try (try-completion word mew-addrbook-alist)) + (if (or (eq try t) + (and (stringp try) (string= word try))) + (insert (mew-addrbook-alias-get word mew-addrbook-alist)) + (insert word) + (message "'%s' cannot be expanded" word))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Completing folders +;;; + +(defmacro mew-complete-proto-folder (sym &rest body) + ;; (declare (indent 1)) + `(if mew-input-folder-search-direction + (mew-input-folder-search-complete) + (mew-draft-set-completion-ignore-case mew-complete-folder-ignore-case) + (let ((,sym (mew-delete-backward-char)) + (completion-ignore-case mew-complete-folder-ignore-case) + (mew-inherit-complete-folder t)) + ,@body))) + +(put 'mew-complete-proto-folder 'lisp-indent-function 1) + +(defun mew-complete-local-folder () + "Local folder complete function." + (interactive) + (mew-complete-proto-folder word + (if (null word) + (mew-complete-window-show (list "+")) + (if (and (mew-folder-absolutep word) + (not (mew-draft-or-header-p))) + (mew-complete word (mew-complete-directory-alist word) "directory" nil) + (mew-complete word (mew-local-folder-alist) "folder" nil))))) + +;; case is specified by mew-inherit-case. +(defun mew-complete-imap-folder () + "IMAP folder complete function." + (interactive) + (mew-complete-proto-folder word + (if (null word) + (mew-complete-window-show (list "%")) + (mew-complete + word + (mew-imap-folder-alist mew-inherit-case) ;; ie mew-sinfo-get-case + "mailbox" + nil)))) + +(defun mew-complete-fcc-folder () + "Fcc: folder complete function." + (interactive) + (mew-complete-proto-folder word + (if (null word) + (mew-complete-window-show (list "+" "%")) + (cond + ((and (mew-folder-absolutep word) (not (mew-draft-or-header-p))) + (mew-complete word (mew-complete-directory-alist word) "directory" nil)) + ((mew-folder-imapp word) + (mew-complete word (mew-imap-folder-alist (mew-tinfo-get-case)) "mailbox" nil)) + (t + (mew-complete word (mew-local-folder-alist) "folder" nil)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Completion function for the minibuffer only +;;; + +(defun mew-complete-folder () + "Folder complete function." + (interactive) + (if mew-input-folder-search-direction + (mew-input-folder-search-complete) + (mew-complete-folder2))) + +(defun mew-input-folder-search-complete () + (let ((mew-inherit-complete-folder t) + keys) + (with-current-buffer mew-input-folder-search-buf + (save-excursion + (goto-char (point-min)) + (while (search-forward (or mew-input-folder-search-key "\n") nil t) + (setq keys + (cons (buffer-substring (progn (beginning-of-line) (point)) + (progn (end-of-line) (point))) + keys))))) + (mew-complete-window-show (nreverse (delete "" keys))) + (mew-highlight-folder-comp-search-window))) + +(defun mew-complete-folder2 () + (let ((word (mew-delete-backward-char nil ", \t\n")) + (completion-ignore-case mew-complete-folder-ignore-case) + (mew-inherit-complete-folder t) + case folder) + (cond + ((null word) + (mew-complete-window-show mew-config-cases2)) + ((setq case (mew-case:folder-case word)) + (setq folder (mew-case:folder-folder word)) + (cond + ((mew-folder-localp folder) + (mew-complete2 folder (mew-local-folder-alist) case)) + ((mew-folder-popp folder) + (mew-complete2 folder (mew-pop-folder-alist) case)) + ((mew-folder-nntpp folder) + (mew-complete2 folder (mew-nntp-folder-alist case) case)) + ((mew-folder-imapp folder) + (mew-complete2 folder (mew-imap-folder-alist case) case)) + ((mew-folder-virtualp folder) + (mew-complete + word (mew-buffer-list "^\\*" t 'mew-virtual-mode) "folder" nil)) + ((string= folder "") + (insert word) + (mew-complete-window-show + (mapcar (lambda (x) (concat case ":" x)) mew-folder-prefixes))) + (t + (insert word) + (if (window-minibuffer-p (get-buffer-window (current-buffer))) + (mew-temp-minibuffer-message " [No matching folder]") + (message "No matching folder"))))) + (t + (cond + ((mew-folder-localp word) + (mew-complete word (mew-local-folder-alist) "folder" nil)) + ((mew-folder-popp word) + (mew-complete word (mew-pop-folder-alist) "folder" nil)) + ((mew-folder-nntpp word) + (mew-complete word (mew-nntp-folder-alist nil) "newsgroup" nil)) + ((mew-folder-imapp word) + (mew-complete word (mew-imap-folder-alist nil) "mailbox" nil)) + ((mew-folder-virtualp word) + (mew-complete + word (mew-buffer-list "^\\*" t 'mew-virtual-mode) "folder" nil)) + ((mew-folder-absolutep word) + (mew-complete word (mew-complete-directory-alist word) "directory" nil)) + (t + (mew-complete + word + (mapcar (lambda (x) (list (concat x ":"))) mew-config-cases) + "case" + nil))))))) + +(defun mew-complete-case () + "Complete function for cases." + (interactive) + (let ((word (or (mew-delete-backward-char) "")) + (completion-ignore-case mew-complete-case-ignore-case)) + (mew-complete + word + (mapcar 'list mew-config-cases) + "case" + nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Circular completion function for a draft only +;;; + +(defun mew-draft-circular-comp () + "Switch function for circular complete functions." + (interactive) + (let ((func (mew-draft-on-value-p mew-field-circular-completion-switch))) + (if func + (funcall func) + (message "No circular completion here")))) + +(defun mew-circular-complete-domain () + "Circular completion of domains for To:, Cc:, etc. +If the @ character does not exist, the first value of +mew-mail-domain-list is inserted. If exists, the next value of +mew-mail-domain-list concerned with the string between @ and +the cursor is inserted." + (interactive) + (mew-draft-set-completion-ignore-case + mew-circular-complete-domain-ignore-case) + (let ((word (mew-delete-backward-char "@")) + (completion-ignore-case mew-circular-complete-domain-ignore-case)) + (cond + ((eq word nil) ;; @ does not exist. + (if (null mew-mail-domain-list) + (message "For domain circular completion, set mew-mail-domain-list") + (insert "@") + (insert (car mew-mail-domain-list)) + (mew-complete-window-delete))) + ((eq word t) ;; just after @ + (if (null mew-mail-domain-list) + (message "For domain circular completion, set mew-mail-domain-list") + (insert (car mew-mail-domain-list)) + (mew-complete-window-delete))) + (t + ;; cannot use mew-get-next since completion is necessary sometime. + (mew-complete + word + (mew-slide-pair mew-mail-domain-list) + "domain" + t))))) ;; use cdr + +(defun mew-circular-complete (msg sym &optional minibuf) ;; xxx msg + "General circular complete function." + (interactive) + (let ((name (symbol-name sym)) + (val (symbol-value sym)) + str alst match) + (if (null val) + (mew-temp-minibuffer-message (format "[Set '%s']" name)) + (setq str (mew-delete-value nil minibuf)) + (setq alst (mew-slide-pair val)) + (if (or (null str) ;; draft + (and (string= str "") (null (assoc "" alst)))) ;; minibuf + (insert (car val)) + (setq match (assoc str alst)) + (if match + (insert (cdr match)) + (insert str) + (mew-temp-minibuffer-message (format "[No matching %s]" msg))))))) + +(defun mew-circular-complete-from () + "Circular complete function for From:." + (interactive) + (mew-circular-complete "from" 'mew-from-list)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Circular completion function for the minibuffer only +;;; + +(defvar mew-circular-complete-function nil) + +(defun mew-circular-complete-switch () + "A switch function to call a function defined to +'mew-circular-complete-function'." + (interactive) + (if mew-circular-complete-function (funcall mew-circular-complete-function))) + +(defun mew-circular-complete-pick-pattern () + (mew-circular-complete "pick pattern" 'mew-pick-pattern-list 'minibuf)) + +(defun mew-circular-complete-case () + (mew-circular-complete "case" 'mew-config-cases 'minibuf)) + +(defun mew-circular-complete-case: () + (cond + ((eq mew-input-complete-function 'mew-complete-local-folder) + ()) + (mew-input-folder-search-direction + (mew-input-folder-self-insert)) + (t + (let (cases oldcase newcase insert-:) + (save-excursion + (if (search-backward "," nil t) + (forward-char 1) + (beginning-of-line)) + (if (looking-at mew-regex-case2) + (progn + (setq oldcase (mew-match-string 1)) + (delete-region (match-beginning 1) (match-end 1))) + (setq oldcase mew-case-default) + (setq insert-: t)) + (if (setq cases (member oldcase mew-config-cases)) + (if (> (length cases) 1) + (setq newcase (nth 1 cases)) + (setq newcase (car mew-config-cases))) + (setq newcase mew-case-default)) + (if (string= newcase mew-case-default) + (unless insert-: (delete-char 1)) + (insert newcase) + (if insert-: (insert ":")))) + (if (or (= (point) (mew-minibuf-point-min)) + (save-excursion + (forward-char -1) + (looking-at "[:,]"))) + (if (search-forward "," nil t) + (forward-char -1) + (goto-char (point-max)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Expansion for a draft only +;;; + +(defun mew-draft-expand () + "Switch function for expand functions." + (interactive) + (let ((func (mew-draft-on-value-p mew-field-expansion-switch))) + (if func + (funcall func) + (message "No expansion here")))) + +(defun mew-expand-address () + "Address expansion function for To:, Cc:, etc. +'user@domain' will be expands 'name ' if +the name exists." + (interactive) + (let ((word (mew-delete-backward-char)) func name) + (if (null word) + (message "No address here") + (setq func (mew-addrbook-func mew-addrbook-for-address-expansion)) + (if (null func) + (insert word) + (setq name (funcall func word)) + (insert (if name (format "%s <%s>" name word) word)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Other completion stuff +;;; + +;; dummy +(defvar mew-ext-host "") +(defvar mew-ext-user "") + +(defun mew-complete-rfile () + "Complete a remote file." + (interactive) + (let* ((path-file (mew-delete-file-name)) + (path (car path-file)) + (file (cdr path-file)) + rpath) + (setq rpath (format "/%s@%s:%s" mew-ext-user mew-ext-host path)) + (mew-complete + file + rpath + "remote file" + nil + 'mew-ext-file-name-completion + 'mew-ext-file-name-all-completions))) + +(defun mew-complete-pick-pattern () + "Complete pick patterns." + (interactive) + (let* ((pat (mew-delete-pattern)) + (clist (append '("(" "!") + mew-pick-field-list + (mapcar 'car mew-pick-macro-alist)))) + (if (null pat) + (mew-complete-window-show clist) + (mew-complete + pat + (mapcar 'list clist) + "pick pattern" + nil)))) + +(defun mew-complete-sort-key () + "Complete sort keys." + (interactive) + (let* ((word (mew-delete-line)) + field alist) + (if (string-match ":" word) + (progn + ;; If WORD contains ':', change alist for completion. + (setq field (car (mew-split word ?:))) + (setq alist + (mapcar (lambda (str) (list (concat field ":" str))) mew-sort-modes))) + ;; Otherwise, alist is mew-sort-key-alist itself. + (setq alist mew-sort-key-alist)) + (mew-complete word alist "sort key" nil))) + +(defun mew-complete-directory-alist (dir) + "Return alist of directories for completion." + (let ((odir dir) odir1 dirs1 sub dirs2) + (setq dir (mew-file-chase-links (expand-file-name dir))) + (when (file-directory-p dir) + (setq odir1 (file-name-as-directory odir)) + (setq dirs1 (mapcar + (lambda (x) + (when (file-directory-p (expand-file-name x dir)) + (cons (concat odir1 (file-name-as-directory x)) x))) + (directory-files dir nil "[^.]" 'nosort)))) + (setq sub (file-name-nondirectory dir)) + (setq odir (file-name-directory odir)) + (setq dir (file-name-directory dir)) + (when (and dir odir sub (not (string= sub ""))) + (setq odir (file-name-as-directory odir)) + (setq dirs2 (mapcar + (lambda (x) + (when (file-directory-p (expand-file-name x dir)) + (cons (concat odir (file-name-as-directory x)) x))) + (directory-files dir nil + (concat "^" (regexp-quote sub)) + 'nosort)))) + (sort (delq nil (append dirs2 dirs1)) + (lambda (x y) (string< (car x) (car y)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Hart function for completions +;;; + +(defalias 'mew-complete-hit 'assoc) + +(defun mew-complete-get (key alist) + (cdr (mew-complete-hit key alist))) + +(defun mew-complete (WORD ALIST MSG EXPAND-CHAR &optional TRY ALL GET HIT) + (let* ((ftry (or TRY 'try-completion)) + (fall (or ALL 'all-completions)) + (fget (or GET 'mew-complete-get)) + (fhit (or HIT 'mew-complete-hit)) + (cmp (funcall ftry WORD ALIST)) + (all (funcall fall WORD ALIST)) + (len (length WORD)) + subkey) + (cond + ;; already completed + ((eq cmp t) + (if EXPAND-CHAR ;; may be "t" + (insert (funcall fget WORD ALIST)) ;; use cdr + (insert WORD)) ;; use car + (mew-complete-window-delete)) + ;; EXPAND + ((and (mew-characterp EXPAND-CHAR) + (char-equal (aref WORD (1- len)) EXPAND-CHAR) + (setq subkey (substring WORD 0 (1- len))) + (funcall fhit subkey ALIST)) + (insert (funcall fget subkey ALIST)) ;; use cdr + (mew-complete-window-delete)) + ;; just one candidate + ((= 1 (length all)) + (insert cmp) + (if (window-minibuffer-p (get-buffer-window (current-buffer))) + (mew-temp-minibuffer-message " [Sole completion]") + (message "Sole completion")) + (mew-complete-window-delete)) + ;; two or more candidates + ((stringp cmp) ;; (length all) > 1 + (insert cmp) + (mew-complete-window-show all) + (if (and (mew-characterp EXPAND-CHAR) (funcall fhit cmp ALIST)) + (message + "To expand '%s', type '%c' then '%s'" + cmp EXPAND-CHAR + (substitute-command-keys + "\\\\[mew-draft-header-comp]")))) + ;; no candidate + (t + (insert WORD) + ;;(mew-complete-window-delete) + (if (window-minibuffer-p (get-buffer-window (current-buffer))) + (mew-temp-minibuffer-message (format " [No matching %s]" MSG)) + (message "No matching %s" MSG)))))) + +(defun mew-complete2-insert (case word) + (if case + (insert case ":" word) + (insert word))) + +(defun mew-complete2 (word alist case) + (let* ((cmp (try-completion word alist)) + (all (all-completions word alist))) + (cond + ;; already completed + ((eq cmp t) + (mew-complete2-insert case word) ;; use car + (mew-complete-window-delete)) + ;; just one candidate + ((= 1 (length all)) + (mew-complete2-insert case cmp) + (if (window-minibuffer-p (get-buffer-window (current-buffer))) + (mew-temp-minibuffer-message " [Sole completion]") + (message "Sole completion")) + (mew-complete-window-delete)) + ;; two or more candidates + ((stringp cmp) ;; (length all) > 1 + (mew-complete2-insert case cmp) + (mew-complete-window-show all)) + ;; no candidate + (t + (mew-complete2-insert case word) + ;;(mew-complete-window-delete) + (if (window-minibuffer-p (get-buffer-window (current-buffer))) + (mew-temp-minibuffer-message " [No matching folder]") + (message "No matching folder")))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Minibuf magic +;;; + +(defun mew-temp-minibuffer-message (m) + (let ((savemax (point-max))) + (save-excursion + (goto-char (point-max)) + (insert m)) + (let ((inhibit-quit t)) + (mew-let-user-read) + (delete-region savemax (point-max)) + (when quit-flag + (setq quit-flag nil) + (setq unread-command-events (list 7)))))) ;; 7 == C-g + +;; +;; Extracting completion key +;; + +(defun mew-delete-backward-char (&optional here sep) + "Delete appropriate preceding word and return it." + (interactive) + (let ((case-fold-search t) + (start nil) + (end (point)) + (regex (concat "[^" (or sep mew-address-separator) "]"))) + (save-excursion + (while (and (not (bobp)) + (string-match regex (mew-buffer-substring (1- (point)) (point)))) + (forward-char -1)) + (if (and here (not (re-search-forward (regexp-quote here) end t))) + nil ;; "here" does not exist. + (setq start (point)) + (if (= start end) + (if here t nil) ;; just after "here", just after separator + (prog1 + (mew-buffer-substring start end) + (delete-region start end))))))) + +(defun mew-delete-file-name () + (if (search-backward mew-path-separator nil t) + (forward-char 1) + (beginning-of-line)) + (prog1 + (cons (mew-buffer-substring (mew-minibuf-point-min) (point)) + (mew-buffer-substring (point) (point-max))) + (delete-region (point) (point-max)))) + +(defun mew-delete-pattern () + (let ((pos (point))) + (if (re-search-backward " \\|(\\|&\\||\\|!\\|," nil t) + (forward-char 1) + (beginning-of-line)) + (prog1 + (mew-buffer-substring (point) pos) + (delete-region (point) pos)))) + +(defun mew-delete-line () + (let ((pos (point))) + (beginning-of-line) + (prog1 + (mew-buffer-substring (point) pos) + (delete-region (point) pos)))) + +(defun mew-delete-key () + (let ((pos (point))) + (beginning-of-line) + (prog1 + (mew-capitalize (mew-buffer-substring (point) pos)) + (delete-region (point) pos)))) + +(defun mew-delete-value (&optional here minibuf) + (beginning-of-line) + (if minibuf + (let ((start (point)) ret) + (end-of-line) + (setq ret (mew-buffer-substring start (point))) + (delete-region start (point)) + ret) + (when (looking-at "[^:]+:") + (goto-char (match-end 0)) + (if (looking-at "[ \t]") + (forward-char 1) + (insert " ")) + (if (eolp) + nil + (let ((start (point)) ret) + (end-of-line) + (if (and here (re-search-backward (regexp-quote here) start t)) + (progn + (setq start (1+ (point))) + (end-of-line))) + (setq ret (mew-buffer-substring start (point))) + (delete-region start (point)) + ret))))) + +;; +;; Making alist +;; + +(defun mew-slide-pair (x) + (let ((len (length x)) + (ret nil) + (first (car x))) + (cond + ((= len 0) nil) + ((= len 1) (list (cons first first))) + (t + (while (cdr x) + (setq ret (cons (cons (nth 0 x) (nth 1 x)) ret)) + (setq x (cdr x))) + (setq ret (cons (cons (car x) first) ret)) + (nreverse ret))))) + +(provide 'mew-complete) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-complete.el ends here diff --git a/elpa/mew-20150813.2354/mew-config.el b/elpa/mew-20150813.2354/mew-config.el new file mode 100644 index 00000000..7a80b4eb --- /dev/null +++ b/elpa/mew-20150813.2354/mew-config.el @@ -0,0 +1,642 @@ +;;; mew-config.el + +;; Author: Kazu Yamamoto +;; Created: Dec 14, 1999 + +;;; Code: + +(require 'mew) + +(defun mew-case-default-p (case) + (or (null case) (string= case mew-case-default))) + +(defvar mew-generate-mail-address-list nil) +(defvar mew-generate-mail-domain-list nil) +(defvar mew-generate-from-list nil) + +;; +;; +;; + +(defun mew-cfent-value (case key def &optional type) + (let ((cases (and case (mapcar 'mew-chop (mew-split case ?,)))) + ent ret cfent) + (or (member mew-case-default cases) + (setq cases (cons mew-case-default cases))) + (setq cases (nreverse cases)) + (catch 'loop + (dolist (cs cases) + (setq cfent (mew-cfent-by-case cs)) + (setq ent (or (assoc key cfent) ;; old + (assoc (intern key) cfent))) ;; new + (when ent + (setq ret (cdr ent)) ;; old + (cond + ((eq type 'symbol) + (if (consp ret) (setq ret (car ret))) + (setq ret (symbol-value ret))) + ((eq type 'list) + (if (and (consp (car ret)) (null (cdr ret))) ;; new + (setq ret (car ret))) + (if (equal ret '(nil)) + (setq ret nil))) + (t + (if (consp ret) (setq ret (car ret))))) ;; new + (if ent (throw 'loop nil)))) + (setq ret def)) + ret)) + +(defvar mew-config-cases nil) +(defvar mew-config-cases2 nil) +(defvar mew-inbox-folders nil) +(defvar mew-queue-folders nil) +(defvar mew-postq-folders nil) + +(defun mew-config-init () + (if (null mew-mail-address-list) (setq mew-generate-mail-address-list t)) + (if (null mew-mail-domain-list) (setq mew-generate-mail-domain-list t)) + (if (null mew-from-list) (setq mew-generate-from-list t))) + +(defun mew-config-case-name (ent) + (let ((case (car ent))) + (if (symbolp case) + (symbol-name case) + case))) + +(defun mew-config-setup () + (if mew-generate-mail-address-list (setq mew-mail-address-list nil)) + (if mew-generate-mail-domain-list (setq mew-mail-domain-list nil)) + (if mew-generate-from-list (setq mew-from-list nil)) + (setq mew-inbox-folders nil) + (setq mew-queue-folders nil) + (setq mew-postq-folders nil) + (setq mew-config-cases (mapcar 'mew-config-case-name mew-config-alist)) + (or (member mew-case-default mew-config-cases) + (setq mew-config-cases (cons mew-case-default mew-config-cases))) + (setq mew-config-cases2 + (append mew-folder-prefixes + (mapcar (lambda (x) (concat x ":")) mew-config-cases))) + (let ((cases (reverse mew-config-cases)) ;; must copy + val) + (dolist (case cases) + (setq val (mew-inbox-folder case)) + (or (mew-folder-inboxp val) + (setq mew-inbox-folders (cons val mew-inbox-folders))) + (setq val (mew-queue-folder case)) + (or (mew-folder-queuep val) + (setq mew-queue-folders (cons val mew-queue-folders))) + (setq val (mew-postq-folder case)) + (or (mew-folder-postqp val) + (setq mew-postq-folders (cons val mew-postq-folders))) + (when mew-generate-mail-address-list + (setq val (concat "^" (regexp-quote (mew-mail-address case)) "$")) + (or (member val mew-mail-address-list) + (setq mew-mail-address-list (cons val mew-mail-address-list)))) + (when mew-generate-mail-domain-list + (setq val (mew-mail-domain case)) + (or (member val mew-mail-domain-list) + (setq mew-mail-domain-list (cons val mew-mail-domain-list)))) + (when mew-generate-from-list + (setq val (mew-from case)) + (or (member val mew-from-list) + (setq mew-from-list (cons val mew-from-list))))))) + +;;; +;;; +;;; + +(defun mew-name (&optional case) + (mew-cfent-value case "name" mew-name)) + +(defun mew-user (&optional case) + (mew-cfent-value case "user" mew-user)) + +(defun mew-mail-domain (&optional case) + (mew-cfent-value case "mail-domain" mew-mail-domain)) + +(defun mew-mail-address (&optional case) + (concat (mew-user case) "@" (mew-mail-domain case))) + +;; mew-from is really strange to maintain backword compatibility. +(defun mew-from (&optional case) + (or (unless mew-config-alist + (if mew-generate-from-list + mew-from + (car mew-from-list))) + (let ((name (mew-name case)) + (addr (mew-mail-address case))) + (if (and name (string-match "[^ \t]" name)) + (format "%s <%s>" name addr) + addr)))) + +(defun mew-cc (&optional case) + (let ((cc (mew-cfent-value case "cc" mew-cc))) + (if (eq cc 'me) (mew-mail-address case) cc))) + +(defun mew-fcc (&optional case) + (mew-cfent-value case "fcc" mew-fcc)) + +(defun mew-bcc (&optional case) + (mew-cfent-value case "bcc" mew-bcc)) + +(defun mew-dcc (&optional case) + (let ((dcc (mew-cfent-value case "dcc" mew-dcc))) + (if (eq dcc 'me) (mew-mail-address case) dcc))) + +(defun mew-reply-to (&optional case) + (mew-cfent-value case "reply-to" mew-reply-to)) + +(defun mew-organization (&optional case) + (mew-cfent-value case "organization" mew-organization)) + +;; + +(defun mew-ssl-cert-directory (&optional case) + (mew-cfent-value case "ssl-cert-directory" mew-ssl-cert-directory)) + +(defun mew-ssl-verify-level (&optional case) + (mew-cfent-value case "ssl-verify-level" mew-ssl-verify-level)) + +;; + +(defun mew-smtp-server (&optional case) + (mew-cfent-value case "smtp-server" mew-smtp-server)) + +(defun mew-smtp-port (&optional case) + (mew-cfent-value case "smtp-port" mew-smtp-port)) + +(defun mew-smtp-ssh-server (&optional case) + (mew-cfent-value case "smtp-ssh-server" mew-smtp-ssh-server)) + +(defun mew-smtp-ssl (&optional case) + (mew-cfent-value case "smtp-ssl" mew-smtp-ssl)) + +(defun mew-smtp-ssl-port (&optional case) + (mew-cfent-value case "smtp-ssl-port" mew-smtp-ssl-port)) + +(defun mew-smtp-helo-domain (&optional case) + (mew-cfent-value case "smtp-helo-domain" mew-smtp-helo-domain)) + +(defun mew-smtp-user-only (&optional case) + (let ((user-domain (mew-smtp-user case))) + (if (string-match "^\\([^@]+\\)@" user-domain) + (mew-match-string 1 user-domain) + user-domain))) + +(defun mew-smtp-user (&optional case) + (or (mew-cfent-value case "smtp-user" mew-smtp-user) + (mew-mail-address case))) + +(defun mew-smtp-auth-list (&optional case) + (mew-cfent-value case "smtp-auth-list" mew-smtp-auth-list 'list)) + +(defun mew-smtp-mail-from (&optional case) + (mew-cfent-value case "smtp-mail-from" mew-smtp-mail-from)) + +(defun mew-smtp-msgid-user (&optional case) + (or (mew-cfent-value case "smtp-msgid-user" mew-smtp-msgid-user) + (mew-user case))) + +(defun mew-smtp-msgid-domain (&optional case) + (or (mew-cfent-value case "smtp-msgid-domain" mew-smtp-msgid-domain) + (mew-mail-domain case))) + +(defun mew-smtp-message-id (&optional case) + (let* ((random (format "%08d" (mew-random))) + (domain (mew-smtp-msgid-domain case)) + (user (mew-smtp-msgid-user case)) + (time (mew-time-ctz-to-msgid (current-time)))) + (concat "<" time "." random "." user "@" domain ">"))) + +(defun mew-use-smtp-auth (&optional case) + (mew-cfent-value case "use-smtp-auth" mew-use-smtp-auth)) + +(defun mew-smtp-auth-plain-authorize-id (&optional case) + (mew-cfent-value case "smtp-auth-plain-authorize-id" mew-smtp-auth-plain-authorize-id)) + +;; + +(defun mew-mailbox-type (&optional case) + (mew-cfent-value case "mailbox-type" mew-mailbox-type)) + +;; + +(defun mew-mbox-command (&optional case) + (mew-cfent-value case "mbox-command" mew-mbox-command)) + +(defun mew-mbox-command-arg (&optional case) + (mew-cfent-value case "mbox-command-arg" mew-mbox-command-arg)) + +;; + +(defun mew-pop-server (&optional case) + (mew-cfent-value case "pop-server" mew-pop-server)) + +(defun mew-pop-port (&optional case) + (mew-cfent-value case "pop-port" mew-pop-port)) + +(defun mew-pop-auth (&optional case) + (mew-cfent-value case "pop-auth" mew-pop-auth)) + +(defun mew-pop-ssh-server (&optional case) + (mew-cfent-value case "pop-ssh-server" mew-pop-ssh-server)) + +(defun mew-pop-ssl (&optional case) + (mew-cfent-value case "pop-ssl" mew-pop-ssl)) + +(defun mew-pop-ssl-port (&optional case) + (mew-cfent-value case "pop-ssl-port" mew-pop-ssl-port)) + +(defun mew-pop-proxy-server (&optional case) + (mew-cfent-value case "pop-proxy-server" mew-pop-proxy-server)) + +(defun mew-pop-proxy-port (&optional case) + (mew-cfent-value case "pop-proxy-port" mew-pop-proxy-port)) + +(defun mew-pop-user (&optional case) + (mew-cfent-value case "pop-user" mew-pop-user)) + +(defun mew-pop-auth-list (&optional case) + (mew-cfent-value case "pop-auth-list" mew-pop-auth-list 'list)) + +(defun mew-pop-size (&optional case) + (mew-cfent-value case "pop-size" mew-pop-size)) + +(defun mew-pop-body-lines (&optional case) + (mew-cfent-value case "pop-body-lines" mew-pop-body-lines)) + +(defun mew-pop-delete (&optional case) + (mew-cfent-value case "pop-delete" mew-pop-delete)) + +(defun mew-pop-header-only (&optional case) + (mew-cfent-value case "pop-header-only" mew-pop-header-only)) + +;; + +(defun mew-imap-server (&optional case) + (mew-cfent-value case "imap-server" mew-imap-server)) + +(defun mew-imap-port (&optional case) + (mew-cfent-value case "imap-port" mew-imap-port)) + +(defun mew-imap-auth (&optional case) + (mew-cfent-value case "imap-auth" mew-imap-auth)) + +(defun mew-imap-ssh-server (&optional case) + (mew-cfent-value case "imap-ssh-server" mew-imap-ssh-server)) + +(defun mew-imap-ssl (&optional case) + (mew-cfent-value case "imap-ssl" mew-imap-ssl)) + +(defun mew-imap-ssl-port (&optional case) + (mew-cfent-value case "imap-ssl-port" mew-imap-ssl-port)) + +(defun mew-imap-proxy-server (&optional case) + (mew-cfent-value case "imap-proxy-server" mew-imap-proxy-server)) + +(defun mew-imap-proxy-port (&optional case) + (mew-cfent-value case "imap-proxy-port" mew-imap-proxy-port)) + +(defun mew-imap-user (&optional case) + (mew-cfent-value case "imap-user" mew-imap-user)) + +(defun mew-imap-auth-list (&optional case) + (mew-cfent-value case "imap-auth-list" mew-imap-auth-list 'list)) + +(defun mew-imap-size (&optional case) + (mew-cfent-value case "imap-size" mew-imap-size)) + +(defun mew-imap-delete (&optional case) + (mew-cfent-value case "imap-delete" mew-imap-delete)) + +(defun mew-imap-header-only (&optional case) + (mew-cfent-value case "imap-header-only" mew-imap-header-only)) + +(defun mew-imap-prefix-list (&optional case) + (mew-cfent-value case "imap-prefix-list" mew-imap-prefix-list 'list)) + +;; + +(defun mew-nntp-server (&optional case) + (mew-cfent-value case "nntp-server" mew-nntp-server)) + +(defun mew-nntp-port (&optional case) + (mew-cfent-value case "nntp-port" mew-nntp-port)) + +(defun mew-nntp-ssh-server (&optional case) + (mew-cfent-value case "nntp-ssh-server" mew-nntp-ssh-server)) + +(defun mew-nntp-ssl (&optional case) + (mew-cfent-value case "nntp-ssl" mew-nntp-ssl)) + +(defun mew-nntp-ssl-port (&optional case) + (mew-cfent-value case "nntp-ssl-port" mew-nntp-ssl-port)) + +(defun mew-nntp-user (&optional case) + (mew-cfent-value case "nntp-user" mew-nntp-user)) + +(defun mew-nntp-size (&optional case) + (mew-cfent-value case "nntp-size" mew-nntp-size)) + +(defun mew-nntp-header-only (&optional case) + (mew-cfent-value case "nntp-header-only" mew-nntp-header-only)) + +(defun mew-nntp-msgid-user (&optional case) + (or (mew-cfent-value case "nntp-msgid-user" mew-nntp-msgid-user) + (mew-user case))) + +(defun mew-nntp-msgid-domain (&optional case) + (or (mew-cfent-value case "nntp-msgid-domain" mew-nntp-msgid-domain) + (mew-mail-domain case))) + +(defun mew-nntp-message-id (&optional case) + (let* ((random (format "%08d" (mew-random))) + (domain (mew-nntp-msgid-domain case)) + (user (mew-nntp-msgid-user case)) + (time (mew-time-ctz-to-msgid (current-time)))) + (concat "<" time "." random "." user "@" domain ">"))) +;; + +(defun mew-inbox-folder (&optional case) + (mew-cfent-value case "inbox-folder" mew-inbox-folder)) + +(defun mew-imap-inbox-folder (&optional case) + (mew-cfent-value case "imap-inbox-folder" mew-imap-inbox-folder)) + +(defun mew-nntp-newsgroup (&optional case) + (mew-cfent-value case "nntp-newsgroup" mew-nntp-newsgroup)) + +(defun mew-imap-friend-folder (&optional case) + (mew-cfent-value case "imap-friend-folder" mew-imap-friend-folder)) + +(defun mew-queue-folder (&optional case) + (mew-cfent-value case "queue-folder" mew-queue-folder)) + +(defun mew-postq-folder (&optional case) + (mew-cfent-value case "postq-folder" mew-postq-folder)) + +(defun mew-imap-queue-folder (&optional case) + (mew-cfent-value case "imap-queue-folder" mew-imap-queue-folder)) + +(defun mew-imap-trash-folder (&optional case) + (mew-cfent-value case "imap-trash-folder" mew-imap-trash-folder)) + +(defun mew-imap-trash-folder-list (&optional case) + (mew-cfent-value case "imap-trash-folder-list" mew-imap-trash-folder-list 'list)) + +(defun mew-header-alist (&optional case) + (mew-cfent-value case "header-alist" mew-header-alist 'list)) + +(defun mew-signature-file (&optional case) + (mew-cfent-value case "signature-file" mew-signature-file)) + +(defun mew-content-type (&optional case) + (mew-capitalize (mew-cfent-value case "content-type" mew-content-type))) + +(defun mew-imap-spam-field (&optional case) + (mew-cfent-value case "imap-spam-field" mew-imap-spam-field)) + +(defun mew-imap-spam-word (&optional case) + (mew-cfent-value case "imap-spam-word" mew-imap-spam-word)) + +(defun mew-imap-spam-pattern (&optional case) + (mew-cfent-value case "imap-spam-pattern" mew-imap-spam-pattern)) + +(defun mew-imap-spam-folder (&optional case) + (mew-cfent-value case "imap-spam-folder" mew-imap-spam-folder)) + +;; + +(defun mew-warn-addresses (&optional case) + (mew-cfent-value case "warn-addresses" mew-warn-addresses)) + +(defun mew-safe-addresses (&optional case) + (mew-cfent-value case "safe-addresses" mew-safe-addresses)) + +(defun mew-warn-domains (&optional case) + (mew-cfent-value case "warn-domains" mew-warn-domains)) + +(defun mew-safe-domains (&optional case) + (mew-cfent-value case "safe-domains" mew-safe-domains)) + +;; + +(defun mew-proto (&optional case) + (mew-cfent-value case "proto" mew-proto)) + +;; + +(defun mew-ssh-prog (&optional case) + (mew-cfent-value case "ssh-prog" mew-ssh-prog)) + +(defun mew-ssh-prog-args (&optional case) + (mew-cfent-value case "ssh-prog-args" mew-ssh-prog-args)) + +(defun mew-ssh-prog-ver (&optional case) + (mew-cfent-value case "ssh-prog-ver" mew-ssh-prog-ver)) + +(defun mew-spam-prog (&optional case) + (mew-cfent-value case "spam-prog" mew-spam-prog)) + +(defun mew-spam-prog-args (&optional case) + (mew-cfent-value case "spam-prog-args" mew-spam-prog-args)) + +(defun mew-ham-prog (&optional case) + (mew-cfent-value case "ham-prog" mew-ham-prog)) + +(defun mew-ham-prog-args (&optional case) + (mew-cfent-value case "ham-prog-args" mew-ham-prog-args)) + +;; + +(defun mew-refile-guess-alist (&optional case) + (mew-cfent-value case "refile-guess-alist" mew-refile-guess-alist 'symbol)) + +;; + +(defun mew-use-old-pgp (&optional case) + (mew-cfent-value case "use-old-pgp" mew-use-old-pgp)) + +;; + +(defun mew-inbox-action-alist (&optional case) + (mew-cfent-value case "inbox-action-alist" mew-inbox-action-alist 'list)) + +;; + +(defun mew-draft-privacy-method (&optional case) + (mew-cfent-value case "draft-privacy-method" mew-draft-privacy-method)) + +(defun mew-protect-privacy-always (&optional case) + (mew-cfent-value case "protect-privacy-always" mew-protect-privacy-always)) + +(defun mew-protect-privacy-always-type (&optional case) + (mew-cfent-value case "protect-privacy-always-type" mew-protect-privacy-always-type)) + +(defun mew-protect-privacy-encrypted (&optional case) + (mew-cfent-value case "protect-privacy-encrypted" mew-protect-privacy-encrypted)) + +(defun mew-protect-privacy-encrypted-type (&optional case) + (mew-cfent-value case "protect-privacy-encrypted-type" mew-protect-privacy-encrypted-type)) + +(defun mew-protect-privacy-with-old-pgp-signature (&optional case) + (mew-cfent-value case "protect-privacy-with-old-pgp-signature" mew-protect-privacy-with-old-pgp-signature)) + +;; + +(defun mew-pgp-signer (&optional case) + (mew-cfent-value case "pgp-signer" mew-pgp-signer)) + +(defun mew-smime-signer (&optional case) + (mew-cfent-value case "smime-signer" mew-smime-signer)) + +(defun mew-use-x-mailer (&optional case) + (mew-cfent-value case "use-x-mailer" mew-use-x-mailer)) + +(defun mew-use-format-flowed (&optional case) + (mew-cfent-value case "use-format-flowed" mew-use-format-flowed)) + +;;; +;;; Setting case +;;; + +(defvar mew-case nil) + +(defun mew-case-set () + "Set the case both for input and output." + (interactive) + (setq mew-case (mew-input-case mew-case))) + +(defun mew-summary-set-case () + "Set the case." + (interactive) + (let ((case (mew-case-set))) ;; side effect + (save-excursion + (dolist (buf mew-buffers) + (when (get-buffer buf) + (set-buffer buf) + (cond + ((mew-summary-p) + (mew-summary-mode-name mew-mode-name-summary)) + ((mew-virtual-p) + (mew-summary-mode-name mew-mode-name-virtual)))))) + (when mew-visit-inbox-after-setting-case + (let ((inbox (mew-case-folder + case + (mew-proto-inbox-folder (mew-proto case) case)))) + (mew-summary-visit-folder inbox))))) + +(defun mew-draft-set-case (&optional arg) + "Guess case and set the case for output to it. The value is +locally stored in Draft mode. If called with '\\[universal-argument]', +you can modify the locally stored value. Then this command replace +fields in the header according to the new value." + (interactive "P") + (let ((old-case (mew-tinfo-get-case)) new-case) + (if arg + (setq new-case (mew-input-case old-case 'edit)) + (setq new-case (mew-draft-get-case-by-guess)) + (if mew-case-guess-addition + (setq new-case (mew-draft-add-case old-case new-case))) + (setq new-case (mew-input-case (or new-case mew-case)))) + (mew-tinfo-set-case new-case) + (mew-tinfo-set-use-flowed (mew-use-format-flowed new-case)) + (mew-draft-mode-name (mew-tinfo-get-hdr-file)) + (mew-draft-replace-fields old-case) + (mew-highlight-header) + (unless (mew-tinfo-get-hdr-file) (mew-draft-header-keymap)) + (save-buffer))) + +(defun mew-draft-replace-fields (old-case) + (save-excursion + (goto-char (point-min)) + (let ((new-case (mew-tinfo-get-case)) + from fcc dcc eoh) + ;; (mew-header-end) cannot be used here + (mew-header-goto-end) + (setq eoh (point)) + (goto-char (point-min)) + (cond + ((mew-draft-resent-p eoh) + (setq from mew-resent-from:) + ;; (setq cc mew-resent-cc:) + (setq fcc mew-resent-fcc:) + (setq dcc mew-resent-dcc:)) + (t + (setq from mew-from:) + ;; (setq cc mew-cc:) + (setq fcc mew-fcc:) + (setq dcc mew-dcc:))) + (mew-header-replace-value from (mew-from new-case)) + ;; (mew-header-replace-value cc (mew-cc new-case)) + (mew-header-replace-value dcc (mew-dcc new-case)) + (mew-header-replace-value fcc (mew-fcc new-case)) + (mew-header-replace-value mew-reply-to: (mew-reply-to new-case)) + (mew-header-replace-value mew-organization: (mew-organization new-case)) + (mew-header-delete-lines (mapcar 'mew-alist-get-key (mew-header-alist old-case))) + (mew-header-delete-lines (mapcar 'mew-alist-get-key (mew-header-alist new-case))) + (mew-header-delete-lines (list mew-x-face: mew-x-mailer:)) + (mew-header-goto-end) + (mew-draft-header-insert-xface) + (mew-draft-header-insert-alist (mew-header-alist new-case)) + ;; X-Mailer: must be the last + (if (mew-use-x-mailer new-case) + (mew-draft-header-insert mew-x-mailer: mew-x-mailer))))) + +(defun mew-draft-get-case-by-guess (&optional alist) + "Guess case according to 'mew-case-guess-alist'." + (unless alist (setq alist mew-case-guess-alist)) + (let ((cases (mew-refile-guess-by-alist1 alist))) + (if cases + (mew-join "," cases) + nil))) + +(defun mew-draft-set-case-by-guess () + (let ((case (mew-draft-get-case-by-guess))) + (when case + (if mew-case-guess-addition + (setq case (mew-draft-add-case (mew-tinfo-get-case) case))) + (mew-tinfo-set-case case)))) + +(defun mew-draft-add-case (dst src) + (if (mew-case-default-p dst) + src + (if (> (length src) 0) + (mew-join + "," (nreverse + (mew-uniq-list (nreverse (mew-split (concat dst "," src) ?,))))) + dst))) + +(provide 'mew-config) + +;;; Copyright Notice: + +;; Copyright (C) 1999-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-config.el ends here diff --git a/elpa/mew-20150813.2354/mew-const.el b/elpa/mew-20150813.2354/mew-const.el new file mode 100644 index 00000000..1ef563fa --- /dev/null +++ b/elpa/mew-20150813.2354/mew-const.el @@ -0,0 +1,373 @@ +;;; mew-const.el + +;; Author: Kazu Yamamoto +;; Created: Feb 1, 1999 + +;;; Code: + +(require 'mew) + +;; Constants which are used in two or more files must be here. +;; Constants used only in a file should be defined in the file. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Suffix +;;; + +(defconst mew-suffix ".mew") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Readability +;;; + +(defconst mew-sp ?\ ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message fields +;;; + +;; Must be capitalized! + +(defconst mew-subj: "Subject:") +(defconst mew-to: "To:") +(defconst mew-cc: "Cc:") +(defconst mew-from: "From:") +(defconst mew-sender: "Sender:") +(defconst mew-date: "Date:") + +(defconst mew-bcc: "Bcc:") +(defconst mew-dcc: "Dcc:") +(defconst mew-fcc: "Fcc:") + +(defconst mew-message-id: "Message-Id:") +(defconst mew-references: "References:") +(defconst mew-in-reply-to: "In-Reply-To:") + +(defconst mew-resent-to: "Resent-To:") +(defconst mew-resent-cc: "Resent-Cc:") +(defconst mew-resent-from: "Resent-From:") +(defconst mew-resent-sender: "Resent-Sender:") +(defconst mew-resent-date: "Resent-Date:") + +(defconst mew-resent-bcc: "Resent-Bcc:") +(defconst mew-resent-dcc: "Resent-Dcc:") +(defconst mew-resent-fcc: "Resent-Fcc:") + +(defconst mew-resent-regex "^Resent-") + +(defconst mew-resent-message-id: "Resent-Message-Id:") + +(defconst mew-reply-to: "Reply-To:") +(defconst mew-organization: "Organization:") +(defconst mew-newsgroups: "Newsgroups:") +(defconst mew-distribution: "Distribution:") +(defconst mew-followup-to: "Followup-To:") + +(defconst mew-apparently-to: "Apparently-To:") + +;; Must not include Bcc:. +(defconst mew-destination:-list + `(,mew-to: ,mew-cc: ,mew-dcc: ,mew-bcc: ,mew-apparently-to:)) +(defconst mew-resent-dest:-list + `(,mew-resent-to: ,mew-resent-cc: ,mew-resent-bcc: ,mew-resent-dcc:)) + +(defconst mew-received: "Received:") + +(defconst mew-x-mailer: "X-Mailer:") +(defconst mew-x-face: "X-Face:") +(defconst mew-face: "Face:") +(defconst mew-x-mew: "X-Mew:") +(defconst mew-x-mew-uidl: "X-Mew-Uidl:") +(defconst mew-x-mew-ref: "X-Mew-Ref:") + +(defconst mew-keywords: "Keywords:") +(defconst mew-body: "Body:") + +(defconst mew-mv: "Mime-Version:") +(defconst mew-mv:-num "1.0") + +(defconst mew-ct: "Content-Type:") +(defconst mew-cte: "Content-Transfer-Encoding:") +(defconst mew-cd: "Content-Description:") +(defconst mew-cid: "Content-Id:") +(defconst mew-cdp: "Content-Disposition:") + +(defconst mew-ct-txt "Text/Plain") +(defconst mew-ct-htm "Text/Html") +(defconst mew-ct-xml "Text/Xml") +(defconst mew-ct-trh "Text/Rfc822-Headers") +(defconst mew-ct-msg "Message/Rfc822") +(defconst mew-ct-ext "Message/External-Body") +(defconst mew-ct-sts "Message/Delivery-Status") +(defconst mew-ct-mlm "Multipart/Mixed") +(defconst mew-ct-mla "Multipart/Alternative") +(defconst mew-ct-mls "Multipart/Signed") +(defconst mew-ct-mle "Multipart/Encrypted") +(defconst mew-ct-mld "Multipart/Digest") +(defconst mew-ct-ado "Audio/Basic") +(defconst mew-ct-apo "Application/Octet-Stream") +(defconst mew-ct-aps "Application/Postscript") +(defconst mew-ct-apk "Application/Pgp-Keys") +(defconst mew-ct-pgs "application/pgp-signature") ;; due to the RFC 1847 bug +(defconst mew-ct-pge "application/pgp-encrypted") ;; due to the RFC 1847 bug +(defconst mew-ct-smm "Application/Pkcs7-Mime") +(defconst mew-ct-xsmm "Application/X-Pkcs7-Mime") +(defconst mew-ct-smm-enc "enveloped-data") +(defconst mew-ct-smm-sig "signed-data") +(defconst mew-ct-sms "application/pkcs7-signature") ;; due to the RFC 1847 bug +(defconst mew-ct-xsms "application/x-pkcs7-signature") ;; due to the RFC 1847 bug + +(defconst mew-us-ascii "us-ascii") +(defconst mew-utf-8 "utf-8") +(defconst mew-iso-2022-jp-2 "iso-2022-jp-2") +(defconst mew-cs-unknown 'unknown) +(defconst mew-cs-m17n-list `(,mew-utf-8 ,mew-iso-2022-jp-2)) + +(defconst mew-type-txt `(,mew-ct-txt ("charset" ,mew-us-ascii))) +(defconst mew-type-msg `(,mew-ct-msg)) +(defconst mew-type-mlm `(,mew-ct-mlm)) +(defconst mew-type-ado `(,mew-ct-ado)) +(defconst mew-type-apo `(,mew-ct-apo)) +(defconst mew-type-apk `(,mew-ct-apk)) + +(defconst mew-b64 "base64") +(defconst mew-qp "quoted-printable") +(defconst mew-xg "x-gzip64") +(defconst mew-7bit "7bit") +(defconst mew-8bit "8bit") +(defconst mew-bin "binary") +(defconst mew-xuu "x-uuencode") + +(defconst mew-decode-value + `(,mew-b64 ,mew-qp ,mew-xg ,mew-7bit ,mew-8bit ,mew-bin ,mew-xuu)) +(defconst mew-decode-composite-value + `(,mew-7bit ,mew-8bit ,mew-bin)) + +(defun mew-cte-p (cte) + (member (downcase cte) mew-decode-value)) + +(defun mew-cte-composite-p (cte) + (member (downcase cte) mew-decode-composite-value)) + +;; must be list of list. +(defconst mew-mime-fields + `((,mew-ct: 0 analyze) + (,mew-cte: 1 extract) + (,mew-cd: 2 decode) + (,mew-cid: 3 id) + (,mew-cdp: 4 analyze))) + +(defconst mew-syntax-magic + (+ (length [key beg end pri]) (length mew-mime-fields))) + +(defconst mew-x-mailer + (format "%s on Emacs %s / Mule %s" + mew-version + (when (string-match "^\\([.0-9]+\\)\\.[0-9]+$" emacs-version) + (match-string 1 emacs-version)) + mule-version) + "*A value inserted into X-Mailer: field in Draft mode if *non-nil*.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Buffers +;;; + +(defconst mew-buffer-prefix " *Mew* ") +(defconst mew-buffer-regex "^ ?\\*Mew\\* ") + +(defconst mew-buffer-cache " *mew cache*") +(defconst mew-buffer-cache-prefix (concat "^" (regexp-quote mew-buffer-cache))) + +(defconst mew-buffer-message "*Mew message*") +(defconst mew-buffer-completions "*Mew completions*") +(defconst mew-buffer-addrbook "*Mew Addrbook*") +(defconst mew-buffer-debug "*Mew debug*") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Suffix +;;; + +(defconst mew-ext-suffix ".ext") +(defconst mew-text-suffix ".txt") +(defconst mew-audio-suffix ".au") +(defconst mew-pgp-key-suffix ".pka") +(defconst mew-pgp-ascii-suffix ".asc") +(defconst mew-queue-work-suffix ".wrk") +(defconst mew-queue-info-suffix ".mqi") +(defconst mew-draft-info-suffix ".mdi") +(defconst mew-imapq-info-suffix ".iqi") +(defconst mew-backup-suffix ".old") +(defconst mew-backup-prefix "#") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Regular expressions +;;; + +(defconst mew-regex-files "^[^.]\\|^.[^.]") ;; xxx "[^.]" is enough? + +;;; +;;; Sumsyn +;;; + +(defconst mew-regex-mark "^\\([^ \n]\\)") +(defun mew-sumsyn-mark () (string-to-char (mew-match-string 1))) + +;; fld msg +(defconst mew-regex-sumsyn-short "\r \\([^ \n]*\\) \\([^ \n]+\\)") + +;; fld msg my-id par-id uid siz +(defconst mew-regex-sumsyn-long "\r \\([^ \n]*\\) \\([^ \n]+\\) \\([^ \n]*\\) \\([^ \n]*\\) \\([^ \n]*\\) \\([0-9]*\\)") + +;; fld msg +(defun mew-regex-sumsyn-msg (msg) + (format "\r \\([^ \n]*\\) \\(%s\\) " msg)) + +(defun mew-summary-search-msg (msg) + (let ((regex (mew-regex-sumsyn-msg msg))) + (when (or (re-search-forward regex nil t) + (re-search-backward regex nil t)) + (beginning-of-line) + t))) + +(defconst mew-regex-sumsyn-valid "\r \\([^ \n]*\\) \\([^ \n]+\\)") +(defconst mew-regex-sumsyn-invalid "\r [^ \n]* 0[1-9][0-9]*") + +(defun mew-msg-validp (msg) + (and msg (string-match mew-regex-message-files msg))) + +(defun mew-msg-invalidp (msg) + (and msg (string-match "^0" msg))) + +(defun mew-msg-truncatedp (siz) + (and siz (string-match "^0" siz))) + +;; fld msg my-id par-id uid siz +(defun mew-regex-sumsyn-my-id (my-id) + (format "\r [^ \n]* [0-9]+ %s [^ \n]*" (regexp-quote my-id))) +(defun mew-regex-sumsyn-par-id (par-id) + (format "\r [^ \n]* [0-9]+ [^ \n]* %s" (regexp-quote par-id))) + +;;; +;;; +;;; + +(defconst mew-regex-msg-icon "^\\([0-9]+\\) ") +(defconst mew-regex-part "^.... \\([.0-9]+\\) ") +(defconst mew-regex-part-icon "<\\([.0-9]+\\)>") + +(defun mew-regex-jmp-part (part) (format "^.... \\(%s\\) " part)) + +;; [\033\200-\377] does not work due to the multibyte +(defconst mew-regex-esc-or-nonascii "[^\000-\032\034-\177]") ;; \033 = esc +(defconst mew-regex-nonascii "[^\000-\177]") +(defconst mew-regex-singlebyte-nonascii + "\\(\\`\\|[\000-\177]\\)[^\000-\177]\\([\000-\177]\\|\\'\\)") + +;; The followings MUST contain "+" for conversion. +;; \011 = tab, \012 = lf +(defconst mew-regex-ctls "[\000-\037\177]+") +(defconst mew-regex-ctls-wo-tab "[\000-\010\012-\037\177]+") +(defconst mew-regex-ctls-wo-tab-lf "[\000-\010\013-\037\177]+") + +;; Can skip \n. Match the first id. For example: +;; In-Reply-To: Your message of "Mon, 5 Oct 1998 13:33:14 +0900" +;; <19981005133317N.kazu@example.org> +(defconst mew-regex-id "<[^>\n\t]+>") + +(defconst mew-regex-case "^\\([^-+$%*,:][^,:]+\\):\\(.*\\)") +(defconst mew-regex-case1 "^\\([^-+$%*,:][^,:]+\\(,[^,:]+\\)*\\):\\(.*\\)") +(defconst mew-regex-case2 "\\([^-+$%*,:][^,:]+\\(,[^,:]+\\)*\\):") + +(defconst mew-regex-punycode "xn--\\([-0-9a-zA-z]+\\)") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder +;;; + +(defconst mew-folder-local "+") +(defconst mew-folder-pop "$") +(defconst mew-folder-imap "%") +(defconst mew-folder-nntp "-") +(defconst mew-folder-virtual "*") +(defconst mew-folder-prefixes + `(,mew-folder-local ,mew-folder-pop ,mew-folder-imap + ,mew-folder-nntp ,mew-folder-virtual)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Misc +;;; + +(defconst mew-home (file-name-as-directory "~")) + +(defconst mew-case-default "default" + "The default value for case.") + +(defconst mew-draft-coverpage "Cover.txt") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Inherit +;;; + +(defconst mew-inherit-case nil) +(defconst mew-inherit-exec-case nil) +(defconst mew-inherit-alt nil) +(defconst mew-inherit-7bit nil) +(defconst mew-inherit-offline nil) +(defconst mew-inherit-decode-signer nil) +(defconst mew-inherit-encode-pgp-signer nil) +(defconst mew-inherit-encode-smime-signer nil) +(defconst mew-inherit-prefetching nil) +(defconst mew-inherit-refile-case nil) +(defconst mew-inherit-refile-proto nil) +(defconst mew-inherit-grep-cmd nil) +(defconst mew-inherit-after-marking nil) +(defconst mew-inherit-pick-tokens nil) +(defconst mew-inherit-pick-ret nil) +(defconst mew-inherit-pick-mewlp nil) +(defconst mew-inherit-pick-omit-and nil) +(defconst mew-inherit-pick-omit-and2 nil) +(defconst mew-inherit-submission nil) +(defconst mew-inherit-complete-folder nil) + +(provide 'mew-const) + +;;; Copyright Notice: + +;; Copyright (C) 2000-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-const.el ends here diff --git a/elpa/mew-20150813.2354/mew-darwin.el b/elpa/mew-20150813.2354/mew-darwin.el new file mode 100644 index 00000000..593f749b --- /dev/null +++ b/elpa/mew-20150813.2354/mew-darwin.el @@ -0,0 +1,120 @@ +;;; mew-darwin.el --- Settings for Mew on Darwin + +;; Author: Kazu Yamamoto +;; Created: Oct 30, 2002 + +;;; Code: + +;; +;; MIME setting +;; + +(defvar mew-darwin-exec "open") +(defvar mew-default-external-program mew-darwin-exec) + +(defvar mew-prog-plain 'mew-mime-text/plain) +(defvar mew-prog-html '(mew-mime-text/html mew-mime-text/html-ext)) +(defvar mew-prog-xml '(mew-mime-text/xml mew-mime-text/xml-ext)) +(defvar mew-prog-patch '(mew-mime-text/plain mew-mime-text/patch-ext)) +(defvar mew-prog-enriched 'mew-mime-text/enriched) +(defvar mew-prog-text 'mew-mime-text/plain) +(defvar mew-prog-audio mew-darwin-exec) +(defvar mew-prog-audio2 mew-darwin-exec) ;; dummy +(defvar mew-prog-image '(mew-mime-image/* mew-mime-image/*-ext)) +(defvar mew-prog-iges mew-darwin-exec) +(defvar mew-prog-vrml mew-darwin-exec) +(defvar mew-prog-mesh mew-darwin-exec) +(defvar mew-prog-video mew-darwin-exec) +(defvar mew-prog-rfc822 'mew-mime-message/rfc822) +(defvar mew-prog-rfc822-headers 'mew-mime-text/rfc822-headers) +(defvar mew-prog-external-body '(mew-mime-external-body mew-mime-external-body-ext)) +(defvar mew-prog-delivery-status 'mew-mime-text/plain) +(defvar mew-prog-postscript mew-darwin-exec) +(defvar mew-prog-pgp-keys '(mew-mime-pgp-keys mew-mime-pgp-keys-ext)) + +(defvar mew-prog-application/pdf "pdftotext") +(defvar mew-prog-pdf-ext mew-darwin-exec) +(defvar mew-prog-pdf `(mew-mime-application/pdf ,mew-prog-pdf-ext)) + +(defvar mew-prog-xml2 '(mew-mime-application/xml + mew-mime-application/xml-ext)) +(defvar mew-prog-oasys mew-darwin-exec) +(defvar mew-prog-octet-stream mew-darwin-exec) +(defvar mew-prog-msword mew-darwin-exec) +(defvar mew-prog-msexcel mew-darwin-exec) +(defvar mew-prog-mspowerpoint mew-darwin-exec) +(defvar mew-prog-visio mew-darwin-exec) +(defvar mew-prog-ooffice mew-darwin-exec) +(defvar mew-prog-rtf mew-darwin-exec) +(defvar mew-prog-unzip mew-darwin-exec) + +;;; +;;; Text/Html, Application/Xml, Image +;;; + +(defvar mew-format-html "%s.html") +(defvar mew-format-xml "%s.xml") + +(defvar mew-prog-text/html + (if (and (fboundp 'shr-render-region) + (fboundp 'libxml-parse-html-region)) + 'shr-render-region + 'mew-mime-text/html-w3m)) ;; See w3m.el +(defvar mew-prog-text/html-ext mew-darwin-exec) + +(defvar mew-prog-text/xml + (if (and (fboundp 'shr-render-region) + (fboundp 'libxml-parse-html-region)) + 'shr-render-region + 'mew-mime-text/html-w3m)) ;; See w3m.el +(defvar mew-prog-text/xml-ext mew-darwin-exec) + +(defvar mew-prog-application/xml nil) +(defvar mew-prog-application/xml-ext mew-darwin-exec) + +(defvar mew-prog-image/* 'mew-mime-image/*) +(defvar mew-prog-image/*-ext mew-darwin-exec) + +(defvar mew-prog-application/msword nil) +(defvar mew-prog-application/msexcel nil) +(defvar mew-prog-application/mspowerpoint nil) +(defvar mew-prog-application/rtf nil) + +;; + +(setq mew-delete-temp-file nil) +(defvar mew-dir-list-function 'mew-dir-list-with-link-count) + +(provide 'mew-darwin) + +;;; Copyright Notice: + +;; Copyright (C) 2002-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-darwin.el ends here diff --git a/elpa/mew-20150813.2354/mew-decode.el b/elpa/mew-20150813.2354/mew-decode.el new file mode 100644 index 00000000..e04a1eef --- /dev/null +++ b/elpa/mew-20150813.2354/mew-decode.el @@ -0,0 +1,1157 @@ +;;; mew-decode.el --- MIME syntax decoder for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Decode info +;;; + +;; limit: +;; Depth of RFC 822 messages. +;; The cnt starts with 0. +;; Decode if cnt <= limit +;; nil means that limit is 0. +;; +;; decode-text: +;; If t, decode a text MIME body. +;; Otherwise, it is treated as 'no-cs-conv +;; +;; decode-binary: +;; If t, decode a binary (non-text) MIME body. +;; +;; use-alt: +;; If t, one part in Multipart/Alternative is used. +;; Otherwise, it is treated as Multipart/Mixed. + +(defvar mew-dinfo-list '("limit" "decode-text" "decode-binary" "use-alt" "encap-html")) + +(mew-blinfo-defun 'mew-dinfo mew-dinfo-list) + +(defun mew-dinfo-set (lim dt db alt &optional encap) + (mew-dinfo-set-limit lim) + (mew-dinfo-set-decode-text dt) + (mew-dinfo-set-decode-binary db) + (mew-dinfo-set-use-alt alt) + (mew-dinfo-set-encap-html encap)) + +(defun mew-cache-dinfo-get-use-alt (buf) + (when buf + (with-current-buffer buf + (mew-dinfo-get-use-alt)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Decode switch +;;; + +(defvar mew-prog-mime-decode-switch + `((,mew-b64 "-d" "-b") + (,mew-qp "-d" "-q") + (,mew-xg "-d" "-g") + (,mew-xuu "-d" "-u"))) + +(defvar mew-prog-mime-decode-text-switch + `((,mew-b64 "-d" "-b" "-t") + (,mew-qp "-d" "-q") + (,mew-xg "-d" "-g" "-t") + (,mew-xuu "-d" "-u"))) + +(defun mew-prog-mime-decode-get-opt (cte switch) + (cdr (mew-assoc-case-equal cte switch 0))) + +(defvar mew-decode-multipart-encrypted-switch + `((,mew-ct-pge mew-pgp-decrypt mew-pgp-ver mew-prog-pgp))) + +(defvar mew-decode-multipart-signed-switch + `((,mew-ct-pgs mew-pgp-verify mew-pgp-ver mew-prog-pgp) + (,mew-ct-sms mew-smime-detach-verify mew-smime-ver mew-prog-smime) + (,mew-ct-xsms mew-smime-detach-verify mew-smime-ver mew-prog-smime))) + +;; + +(defun mew-decode-get-security-func (proto switch) + (nth 1 (mew-assoc-case-equal proto switch 0))) + +(defun mew-decode-get-security-existence (proto switch) + (symbol-value (nth 2 (mew-assoc-case-equal proto switch 0)))) + +(defun mew-decode-get-security-prog (proto switch) + (symbol-value (nth 3 (mew-assoc-case-equal proto switch 0)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; MIME decoder +;;; + +(defun mew-decode-error (error-msg) + (mew-xinfo-set-decode-err error-msg) + (error error-msg)) + +(defun mew-decode-error2 (error-msg) + (mew-xinfo-set-decode-err error-msg)) + +;;; +;;; Decoding a header +;;; + +(defmacro mew-decode-narrow-to-header (&rest body) + `(progn + (if (re-search-forward mew-eoh nil t) + (beginning-of-line) + (goto-char (point-max)) + (insert "\n")) + (when (and (integerp mew-header-max-length) + (> (count-lines (point-min) (point)) mew-header-max-length)) + (mew-xinfo-set-action + (mew-substitute-for-summary + "Too long header. To see the message, type '\\[mew-summary-analyze-again]'")) + (error "")) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + ,@body))) + +(defun mew-summary-toggle-header-veil () + "If 'mew-use-header-veil' is non-nil, field lines of To: and Cc: +over 'mew-header-veil-count' are covered with invisible veils. +This commands toggles visibility of these lines." + (interactive) + (when (and mew-use-header-veil (get-buffer (mew-buffer-message))) + (mew-summary-msg-or-part + (with-current-buffer (mew-buffer-message) + (when (mew-msghdr-p) + (let* ((win (get-buffer-window (current-buffer))) + (pos (window-start win))) + (mew-toggle-header-veil (mew-minfo-get-veil-to)) + (mew-toggle-header-veil (mew-minfo-get-veil-cc)) + (set-window-start win pos))))))) + +(defun mew-header-veil-put (key ov) + (let ((case-fold-search t) + (regex (concat "^" key))) + (goto-char (point-min)) + (when (re-search-forward regex nil t) + (beginning-of-line) + (let ((start (point)) end) + (forward-line) + (mew-header-goto-next) + (setq end (point)) + (when (> (count-lines start end) mew-header-veil-count) + (goto-char start) + (forward-line mew-header-veil-count) + (move-overlay ov (1- (point)) (1- end))))))) + +(defun mew-header-veil () + (when mew-use-header-veil + (unless (mew-minfo-get-veil-to) + (mew-minfo-set-veil-to (mew-header-veil-make))) + (unless (mew-minfo-get-veil-cc) + (mew-minfo-set-veil-cc (mew-header-veil-make))) + (mew-header-veil-put "To:" (mew-minfo-get-veil-to)) + (mew-header-veil-put "Cc:" (mew-minfo-get-veil-cc)))) + +(defun mew-header-arrange (beg end) + (let (vispos) + (save-restriction + (narrow-to-region beg end) + (mew-elet + (let (ch-beg ch-end vs-beg vs-end contents cbeg) + (setq ch-beg (next-single-property-change (point-min) 'mew-noncontents)) + (when ch-beg + (setq vs-beg (next-single-property-change (point-min) 'mew-visible)) + (cond + (vs-beg + (setq vs-end (next-single-property-change vs-beg 'mew-visible))) + (mew-field-other-visible + (setq vs-beg (next-single-property-change (point-min) 'mew-others)) + (if vs-beg + (setq vs-end (next-single-property-change vs-beg 'mew-others)) + (setq vs-beg ch-beg) + (setq vs-end ch-beg))) + (t + (setq vs-beg ch-beg) + (setq vs-end ch-beg))) + (setq ch-end (point-max)) + (unless vs-end (setq vs-end (point-max))) + (mew-decode-header-property-region ch-beg ch-end) + ;; This must be "buffer-substring". + (setq contents (buffer-substring ch-beg ch-end)) + (delete-region ch-beg ch-end) + (cond + ((mew-nspec-visiblep (mew-nspec-by-key "Content-")) + ;; visible + (goto-char vs-end) + (setq cbeg (point)) + (insert contents) + (put-text-property cbeg (point) 'mew-visible t)) ;; used later + (t + ;; invisible + (goto-char vs-beg) + (setq cbeg (point)) + (insert contents))) + (goto-char (point-max))) + (mew-decode-syntax-insert-privacy) + (mew-decode-syntax-insert-warning) + (save-excursion (mew-highlight-x-face (point-min) (point-max))) + (setq vispos (if (get-text-property (point-min) 'mew-visible) + (point-min) + (or (next-single-property-change (point-min) 'mew-visible) + (point-max))))))) + (mew-header-veil) + (mew-header-goto-end) + (if (eobp) + (mew-header-set "\n") ;; analyzed + (mew-header-set nil)) ;; asis + ;; Emacs 21.3.50 or later need this. + (set-window-start (selected-window) vispos))) + +(defun mew-decode-header-property-region (BEG END) + ;; see also mew-highlight-header + (when mew-use-highlight-header + (mew-elet + (let (key beg med nspec key-face val-face) + (save-restriction + (narrow-to-region BEG END) + (goto-char (point-min)) + (while (not (eobp)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq key (mew-match-string 1)) + (setq beg (match-beginning 0)) + (setq med (match-end 0)) + (forward-line) + (setq nspec (mew-nspec-by-key key)) + (setq key-face (mew-key-face key nspec)) + (setq val-face (mew-val-face key nspec)) + (put-text-property beg med 'face key-face) + (put-text-property med (1- (point)) 'face val-face) + (while (looking-at mew-lwsp+) + (forward-line) + (put-text-property (match-end 0) (1- (point)) + 'face val-face))))))))) + +(defun mew-decode-rfc822-header (&optional cnt) + "A function to handle RFC822 header. +Called on the beginning of the header in the narrowed region. + - Decode and highlight RFC822 fields excluding MIME fields. + - Delete X-Mew: fields. + - Arrange decoded-RFC822-fields, mew-mv:, MIME fields in order. +The cursor moves between mew-mv: and MIME fields. +Return the existence MIME-Version: and the value of Subject:." + (let* ((case-fold-search t) + (visibles (make-list (length mew-field-spec) nil)) + (prop mew-use-highlight-header) + key beg med subj from contents others + key-face val-face N nspec visiblep + mimep mimep2 + size ext ext-str ext-face) + (mew-decode-narrow-to-header + (while (not (eobp)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq key (mew-capitalize (mew-match-string 1))) + (setq beg (match-beginning 0)) + (setq med (match-end 0)) + (forward-line) + (mew-header-goto-next) + (setq nspec (mew-nspec-by-key key)) + (setq N (mew-nspec-n nspec)) + (setq visiblep (mew-nspec-visiblep nspec)) + (if (fboundp visiblep) + (setq visiblep (funcall visiblep (mew-buffer-substring med (1- (point)))))) + (cond + ((string= key mew-x-mew:) + ;; deleting X-Mew: on the RFC822 header + (delete-region beg (point))) + ((string= key mew-x-mew-uidl:) + (setq size (mew-scan-uid-size (mew-buffer-substring med (1- (point))))) + (when (and (eq cnt 1) (mew-msg-truncatedp size)) + (mew-xinfo-set-action + (mew-substitute-for-summary + "Too large, truncated (the 'T' mark). To get the entire message, type '\\[mew-summary-retrieve-message]'")))) + ((string-match "^Content-" key) + ;; Due to PGP/MIME, properties are not put here. + :; This must be "buffer-substring". + (setq mimep2 t) + (setq contents (cons (buffer-substring beg (point)) contents)) + (delete-region beg (point))) + (t + ;; Let's decode the field anyway. + ;; If a user want to preserve this RFC 822 header, he + ;; set the limit, so never reaches here. + ;; Moreover this function may be called with + ;; mew-dinfo-set unset. + (mew-header-decode-region key med (point)) + (cond + ((string= key mew-from:) + (setq from (mew-addrstr-parse-address + (mew-buffer-substring med (1- (point)))))) + ((string= key mew-subj:) + (setq subj (mew-buffer-substring med (1- (point))))) + ((string= key mew-mv:) + ;; MIME-Version: + (setq mimep (string-match + mew-mv:-num + (or (mew-addrstr-parse-value + (mew-buffer-substring med (point))) + ""))))) + (when prop + (setq key-face (mew-key-face key nspec)) + (setq val-face (mew-val-face key nspec)) + (put-text-property beg med 'face key-face) + (goto-char med) + (forward-line) + (put-text-property med (1- (point)) 'face val-face) + (while (looking-at mew-lwsp+) + (forward-line) + (put-text-property (match-end 0) (1- (point)) + 'face val-face)) + (when (setq ext (mew-nspec-extraface nspec)) + (save-restriction + (narrow-to-region med (point)) + (while ext ;; cannot use dolist + (goto-char (point-min)) + (setq ext-str (car ext)) + (setq ext (cdr ext)) + (setq ext-face (car ext)) + (setq ext (cdr ext)) + (while (re-search-forward ext-str nil t) + (put-text-property (match-beginning 0) (match-end 0) 'face ext-face))) + (goto-char (point-max))))) + (cond + ((null nspec) ;; others + ;; This must be "buffer-substring". + (setq others (cons (buffer-substring beg (point)) others)) + (delete-region beg (point))) + (visiblep + ;; This must be "buffer-substring". + (setcar (nthcdr N visibles) + (concat (nth N visibles) + (buffer-substring beg (point)))) + (delete-region beg (point))) + (t ;; invisible + ()))))))) + (put-text-property (point-min) (point) 'mew-invisible t) + (put-text-property (point-min) (point) 'mew-noncontents t) + (unless mew-field-other-visible + (setq beg (point)) + (mapc 'insert (nreverse others)) + (put-text-property beg (point) 'mew-others t) + (put-text-property beg (point) 'mew-noncontents t)) + (setq beg (point)) + (mapc (lambda (x) (and (stringp x) (insert x))) visibles) + ;; for recenter in Message mode + (put-text-property beg (point) 'mew-visible t) + (put-text-property beg (point) 'mew-noncontents t) + (mew-rear-nonsticky beg (point)) + (when mew-field-other-visible + (setq beg (point)) + (mapc 'insert (nreverse others)) + (put-text-property beg (point) 'mew-others t) + (put-text-property beg (point) 'mew-noncontents t) + (mew-rear-nonsticky beg (point))) + ;; the beginning of the content header + (save-excursion (mapc 'insert (nreverse contents))) + ;; 'mew-contents does not work due to PGP/MIME + (if (and (null mimep) mimep2) + (mew-xinfo-set-warning + (cons "No MIME-Version\n" (mew-xinfo-get-warning)))) + (list (or mimep mimep2) subj from))) + +(defun mew-decode-mime-header (&optional dct) + "A function to handle content header. +Called on the beginning of the content header in the narrowed region +Return a part syntax after moving the beginning of the content body." + (let ((case-fold-search t) + (vec (make-vector (length mew-mime-fields) nil)) + key med attr n act value syntax) + (mew-decode-narrow-to-header + (while (not (eobp)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq key (mew-capitalize (mew-match-string 1))) + (setq med (match-end 0)) + (forward-line) + (mew-header-goto-next) + (setq attr (assoc key mew-mime-fields)) + (when attr + (mew-set '(nil n act) attr) + (cond + ((eq act 'analyze) + (setq value (mew-param-decode + (mew-buffer-substring med (1- (point)))))) + ((eq act 'extract) + (setq value (mew-addrstr-parse-value + (mew-buffer-substring med (1- (point)))))) + ((eq act 'decode) + ;; If a user want to preserve this MIME header, he + ;; set the limit, so never reaches here. + (mew-header-decode-region key med (point)) + ;; mew-header-decode-region goes to the max point in + ;; the narrowed region. So, this must be (point). + (setq value (mew-buffer-substring med (1- (point))))) + ((eq act 'id) + (setq value (mew-buffer-substring med (1- (point)))) + (setq value (mew-idstr-get-first-id value)))) + (aset vec n value))))) + (if (eobp) + (insert "\n") + (forward-line)) + ;; the beginning of the content body + (setq syntax (vconcat (list 'single (point) nil nil) vec)) + (or (mew-syntax-get-ct syntax) + (mew-syntax-set-ct syntax (or dct mew-type-txt))) + syntax)) + +;;; +;;; Decoding a message +;;; + +(defun mew-decode () + "Decode a message. Execute mew-dinfo-set before calling this." + ;; in cache buffer + (mew-set-buffer-multibyte t) + ;; + ;; Illegal messages may not have end-of-header. + ;; Truncated messages may not have end-of-header. + ;; + (goto-char (point-min)) ;; just in case + (unless (re-search-forward mew-eoh nil t) + (goto-char (point-max)) + (if (not (bolp)) (insert "\n")) + (insert "\n")) + (goto-char (point-min)) + ;; + (if (mew-debug 'decode) + (let ((debug-on-error t)) + (setq mew-decode-syntax + (mew-decode-message (mew-decode-syntax-rfc822-head) 0))) + (condition-case nil + (setq mew-decode-syntax + (mew-decode-message + ;; Call internalform with VIRTUAL content header + ;; CT: message/rfc822 (virtual) + ;; + ;; Header(RFC822 header + content header) + ;; + ;; Body(content body) + (mew-decode-syntax-rfc822-head) 0)) + (error + (widen) + (mew-header-goto-body) + ;; min, point - 1, point, point-max + (setq mew-decode-syntax (mew-decode-syntax-rfc822)))))) + +(defun mew-decode-message (syntax cnt) + ;; Called on the beginning of the RFC822 header in the narrowed region + ;; hbeg is certainly the beginning of the VIRTUAL content body(i.e. min). + ;; hend will have to set to the end of PHYSICAL content header(i.e. end) + ;; after analyzing the physical content header and body since CD:'s + ;; length in the physical content header will change(no need to say + ;; about the end of the physical content header). + ;; + ;; Content-Type: Message/Rfc822 == virtual content header + ;; + ;;(min)Decoded RFC822 fields == virtual content body + ;; MIME-Version: 1.0 + ;;(cur)MIME fields == physical content header + ;;(end) + ;; Content-Body == physical content body + ;;(max) + (setq cnt (1+ cnt)) + (cond + ((and (mew-dinfo-get-limit) (> cnt (mew-dinfo-get-limit))) + ;; Don't analyze recursively. + ;; We need to analyze the header and the body since a user + ;; may want to save the body only. + ;; the beginning of the meaningless physical content header + (if (re-search-forward mew-eoh nil t) + (forward-line) + (mew-decode-error "No end-of-header(null line) in RFC822 message")) + ;; the beginning of the BODY(i.e. the physical content body) + (mew-syntax-set-key syntax 'message) + (mew-syntax-set-end syntax (1- (point))) + ;; (point-min), (point) - 1, (point), (point-max) + (mew-decode-syntax-rfc822 syntax)) ;; return value + (t + ;; Analyze recursively. + (let* ((msf (mew-decode-rfc822-header cnt)) ;; on the physical + (mimep (nth 0 msf)) + (subj (nth 1 msf)) + (mew-inherit-decode-signer (nth 2 msf)) ;; signature verification + part) + ;; the beginning of the physical content header (cur) + (cond + (mimep ;; MIME + (save-restriction + (narrow-to-region (point) (point-max)) + (setq part (mew-decode-singlepart cnt nil 'message)) + ;; hend is always 1 char smaller than the beginning of + ;; the physical content body. + ;; If multipart/alternative mew-syntax-get-begin2 gets + ;; correct value like other cases. + (mew-syntax-set-key syntax 'message) + (mew-syntax-set-end syntax (1- (mew-syntax-get-begin2 part))) + (or (mew-syntax-get-cd syntax) (mew-syntax-set-cd syntax subj)) + (mew-syntax-cat syntax part))) ;; return value + (t ;; RFC822 + ;; the beginning of the meaningless physical content header + (if (re-search-forward mew-eoh nil t) + (forward-line) + (mew-decode-error "No end-of-header(null line) in RFC822 message")) + ;; the beginning of the BODY(i.e. the physical content body) + (if (eq (mew-dinfo-get-decode-text) t) ;; not 'no-cs-conv + (mew-cs-decode-region (point) (point-max) mew-cs-autoconv)) + (mew-syntax-set-key syntax 'message) + (mew-syntax-set-end syntax (1- (point))) + (or (mew-syntax-get-cd syntax) (mew-syntax-set-cd syntax subj)) + ;; (point-min), (point) - 1, (point), (point-max) + (mew-highlight-body-region (point) (point-max)) + (mew-decode-syntax-rfc822 + syntax (not (mew-xinfo-get-text-body))))))))) ;; return value + +;;; +;;; Decoding singlepart +;;; + +(defun mew-decode-mime-body (textp ct cte &optional charset) + ;; ((point), (point-max)) (not point-min) + (let* ((linebasep (mew-ct-linebasep ct)) + (beg (point)) + opt file decoded switch) + (unless (or (null cte) (mew-cte-composite-p cte)) + (when (and (mew-case-equal cte mew-b64) (fboundp 'base64-decode-region)) + (condition-case nil + (setq decoded (base64-decode-region beg (point-max))) + (error (setq decoded nil))) + (when (and decoded linebasep) + (goto-char beg) + (mew-crlf-to-lf))) + ;; base64-decode-region may fail if garbage exists. + (cond + (decoded + ()) + ((mew-which-exec mew-prog-mime-decode) + (setq switch (if linebasep + mew-prog-mime-decode-text-switch + mew-prog-mime-decode-switch)) + (setq opt (mew-prog-mime-decode-get-opt cte switch)) + (if (null opt) + ;; Treated as Application/Octet-Stream. + ;; Never reach here when decoding. + (mew-decode-error (concat "Unknown CTE: " cte)) + (setq file (mew-make-temp-name)) + (mew-frwlet mew-cs-dummy (if linebasep + mew-cs-text-for-write + mew-cs-text-for-net) + ;; Due to broken MUAs, we need to write CRLF. + ;; NEVER use call-process-region for privacy reasons + (write-region beg (point-max) file nil 'no-msg)) + (delete-region beg (point-max)) + (mew-piolet mew-cs-binary mew-cs-dummy + ;; mew-prog-mime-decode converts CRLF to LF, so + ;; read input as binary. + (apply 'call-process mew-prog-mime-decode file '(t nil) nil opt)) + (mew-delete-file file))) + (t + (mew-decode-error (concat mew-prog-mime-decode " does not exist"))))) + ;; charset conversion + (if (and textp (eq (mew-dinfo-get-decode-text) t)) ;; not 'no-cs-conv + (mew-decode-charset-conv charset beg)))) + +(defun mew-decode-charset-conv (charset beg) + (let* ((fromcs (and charset (mew-charset-to-cs charset)))) + ;; fromcs is nil if charset is "us-ascii" + ;; (mew-coding-system-p nil) returns t. + (unless (mew-coding-system-p fromcs) + (mew-decode-warning-body 'unknown-charset charset)) + (when (and mew-use-autoconv-when-unknown + (not (mew-coding-system-p fromcs))) + (setq fromcs mew-cs-autoconv)) + (when (and mew-decode-broken + (not (eq fromcs mew-cs-autoconv)) + (or (null charset) + (mew-case-equal charset mew-us-ascii))) ;; anyway + (goto-char beg) + (when (re-search-forward mew-regex-esc-or-nonascii nil t) + (mew-decode-warning-body 'no-charset charset) + (setq fromcs mew-cs-autoconv)) + (goto-char beg)) + (when (and mew-decode-broken + (not (eq fromcs mew-cs-autoconv)) + (or (null charset) + (mew-case-equal charset mew-us-ascii) + (mew-case-equal charset mew-utf-8))) + (goto-char beg) + (when (re-search-forward mew-regex-singlebyte-nonascii nil t) + (mew-decode-warning-body 'no-charset charset) + (setq fromcs mew-cs-autoconv)) + (goto-char beg)) + (if (mew-coding-system-p fromcs) + (mew-cs-decode-region beg (point-max) fromcs)))) + +(defun mew-decode-singlepart (cnt &optional dct parent) + ;; Called on the beginning of the content header in the narrowed region + (let* ((case-fold-search t) (begin (point)) + (syntax (mew-decode-mime-header dct)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (textp (mew-ct-textp ct)) + (cte (or (mew-syntax-get-cte syntax) mew-7bit)) + (multi-err t) (encap nil) type hend format delsp) + ;; the beginning of the content body + (cond + ((not (mew-cte-p cte)) + (mew-syntax-set-ct syntax mew-type-apo) + (if (eq parent 'message) (setq encap t))) + ((mew-ct-messagep ct) + (if (not (mew-cte-composite-p cte)) + (mew-syntax-set-ct syntax mew-type-apo) + (cond + ((string= mew-ct-msg ct) + (if (eq parent 'message) (setq encap t)) + (save-restriction + (narrow-to-region (point) (point-max)) + (setq syntax (mew-decode-message syntax cnt)))) + ((string= mew-ct-ext ct) + (let* ((at (mew-syntax-get-param ctl "access-type")) + (func (mew-ext-include-get-func at))) + (when (and func (fboundp func)) + (save-excursion + (goto-char (point-max)) ;; phantom body + (funcall func ctl)) + (delete-region begin (point)) + (setq syntax (mew-decode-singlepart cnt))))) + ((string= mew-ct-sts ct) + ;; do nothing + ) + (t + ;; xxx how about message/partial? + (mew-syntax-set-ct syntax mew-type-apo) + )))) + ((or (string= ct mew-ct-smm) (string= ct mew-ct-xsmm)) + (mew-decode-mime-body nil ct cte) + (mew-syntax-set-end syntax (point-max)) + (setq syntax (mew-decode-smime syntax cnt))) + ;; Multipart, decoding is not required + ((mew-ct-multipartp ct) + (if (mew-cte-composite-p cte) + (setq multi-err nil) + (mew-decode-warning-body 'multi cte) + (if mew-decode-broken (setq multi-err nil))) + (if multi-err + (mew-syntax-set-ct syntax mew-type-apo) + (cond + ((string= mew-ct-mld ct) + ;; semantics into digest + (setq syntax (mew-decode-multipart syntax cnt mew-type-msg))) + ((string= mew-ct-mls ct) + (setq syntax (mew-decode-multipart-signed syntax cnt))) + ((string= mew-ct-mle ct) + ;; xxx making use of password cache? + (if mew-inherit-prefetching + (signal 'quit "") + (setq syntax (mew-decode-multipart-encrypted syntax cnt)))) + (t + (setq syntax (mew-decode-multipart syntax cnt nil)))))) + ;; Others + ((string= mew-ct-trh ct) + (save-restriction + ;; Eliminating the content the header so that Rfc822 header + ;; comes the beginning. + (narrow-to-region (point) (point-max)) + (mew-decode-rfc822-header))) + (t + (if (and (eq parent 'message) + (or (not (mew-xinfo-get-text-body)) + (if (mew-dinfo-get-encap-html) + (not (string= ct mew-ct-txt)) + (not textp)))) + (setq encap t)) + ;; even if cte is nil, call mew-decode-mime-body for charset conversion + (if textp + (if (mew-dinfo-get-decode-text) + (let ((charset (mew-syntax-get-param ctl "charset"))) + (mew-decode-mime-body t ct cte charset))) + (if (mew-dinfo-get-decode-binary) + (mew-decode-mime-body nil ct cte))))) + ;; ct may be changed to apo + ;; or single in multipart/alternative + ;; or single in multipart/security + (setq type (mew-syntax-get-value (mew-syntax-get-ct syntax) 'cap)) + (setq hend (mew-syntax-get-end syntax)) + (unless hend + (mew-syntax-set-end syntax (point-max))) + (when (and (string= type mew-ct-txt) + (setq format (mew-syntax-get-param ctl "format")) + (mew-case-equal format "flowed")) + (setq delsp (mew-syntax-get-param ctl "delsp")) + (if (and delsp (mew-case-equal delsp "yes")) + (setq delsp t) + (setq delsp nil)) + (mew-decode-flowed (mew-syntax-get-begin syntax) (point-max) delsp) + (setq hend nil)) + ;; highlight in the cache buffers only + (when (and (string= type mew-ct-txt) + (string-match mew-buffer-cache-prefix (buffer-name))) + (mew-highlight-body-region (mew-syntax-get-begin syntax) (point-max))) + (unless hend + (mew-syntax-set-end syntax (point-max))) ;; ajusting + (if encap + ;; Mew allows text/plain and multipart/* for body. + ;; If other CT: is embedded under message, it should be + ;; encapsulated in multipart/mixed. + (let ((head (mew-decode-syntax-multi-head))) + ;; begin for multipart syntax is important because + ;; the begin will be used by the parent to set hend + (mew-syntax-set-begin head (mew-syntax-get-begin syntax)) + (mew-syntax-set-end head (point-max)) + (mew-syntax-cat head syntax)) ;; return value + ;; return value + syntax))) + +(defun mew-decode-flowed-level () + (cond + ((looking-at "^$") -1) + ((looking-at "^>*") + (let ((level (- (match-end 0) (match-beginning 0)))) + (goto-char (match-end 0)) + ;; we don't remove space-stuff after > + (if (and (/= level 0) (looking-at " ")) (forward-char)) + level)))) + +(defconst mew-flowed-quoted ?>) +(defconst mew-flowed-stuffed mew-sp) +(defconst mew-flowed-break mew-sp) +(defconst mew-flowed-netnews "-- ") +(defvar mew-flowed-broken-list '("----- Original Message ----- ")) ;; OE + +(defun mew-decode-flowed (beg end delsp) + "Decoding wrapped lines encoded with RFC 3676" + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (let (level prev-level softbreak) + (setq level (mew-decode-flowed-level)) + (if (= level 0) (mew-decode-flowed-remove-stuffed)) + (setq softbreak (mew-decode-flowed-soft-breakp delsp)) + (while (= (forward-line) 0) + (setq prev-level level) + (setq level (mew-decode-flowed-level)) + (cond + ((and (= prev-level level) softbreak) + (mew-decode-flowed-remove-quoted-stuffed softbreak)) + (t + (if (= level 0) (mew-decode-flowed-remove-stuffed)))) + (setq softbreak (mew-decode-flowed-soft-breakp delsp)))))) + +(defun mew-decode-flowed-remove-quoted-stuffed (beg) + (delete-region beg (point))) + +(defun mew-decode-flowed-remove-stuffed () + (if (and (char-after) (char-equal (char-after) mew-flowed-stuffed)) + (delete-char 1))) + +(defun mew-decode-flowed-soft-breakp (delsp) + (let ((beg (point)) line) + (end-of-line) + (setq line (mew-buffer-substring beg (point))) + (if (string= line mew-flowed-netnews) + nil + (if (and mew-decode-broken (member line mew-flowed-broken-list)) + (progn + (mew-xinfo-set-warning + (cons "Illegal flowed lines\n" (mew-xinfo-get-warning))) + nil) + (if (and (char-before) (char-equal (char-before) mew-flowed-break)) + (if delsp (1- (point)) (point)) + nil))))) + +;;; +;;; Decoding multipart +;;; + +(defun mew-decode-multipart-boundary-regex (boundary) + ;; for broken MUAs which uses non-ASCII boundaries + ;; This works only on Emacs 21. + (let ((mboundary (mew-set-string-multibyte boundary))) + ;; Some MUAs use invalid character like "<>". + (when (or (string-match "[!-&*;<>@[-^`{-~]" mboundary) + (not (string= mboundary boundary))) + (if mew-decode-broken + (mew-decode-warning-params "boundary" 'char) + (mew-decode-error "Boundary has invalid character"))) + (concat "^--" (regexp-quote mboundary) "\\(--\\|\\)[ \t]*$"))) + +(defun mew-decode-multipart-end-boundary-regex (boundary) + (let ((mboundary (mew-set-string-multibyte boundary))) + (concat "^--" (regexp-quote mboundary) "--[ \t]*$"))) + +(defun mew-decode-multipart-boundary-cont () + (string= (mew-match-string 1) "")) + +(defun mew-decode-multipart-boundary-end () + (string= (mew-match-string 1) "--")) + +(defun mew-decode-multipart-beginning-of-first-part (bregex ct) + ;; RFC 2046 says, "An exact match of the entire candidate + ;; line is not required; it is sufficient that the boundary + ;; appear in its entirety following the CRLF". + (unless (and (re-search-forward bregex nil t) + (mew-decode-multipart-boundary-cont)) + (mew-decode-error (format "No first boundary for %s" ct))) + (forward-line)) ;; the beginning of the first part + +(defun mew-decode-multipart-beginning-of-part (break) + (if break + () ;; close-delimiter need not be followed by CRLF + (forward-line))) ;; the beginning of the next part + +(defun mew-decode-multipart-end-of-part (break) + (unless break (forward-line -1)) + (beginning-of-line) + (forward-char -1) ;; skip the preceding CRLF + ;; the end of the part + ) + +(defun mew-decode-multipart-singlepart (break start cnt dct) + (save-excursion + (mew-decode-multipart-end-of-part break) + (save-restriction + (narrow-to-region start (point)) + (goto-char (point-min)) + ;; the beginning of the part + (mew-decode-singlepart cnt dct nil)))) + +(defun mew-decode-multipart-duplicate-boundary (start cnt dct err boundary bregex) + (if (not (string-match "^No first boundary" (nth 1 err))) + (error "") + ;; duplicate boundary error recovering, sigh + (widen) ;; breaking save-restriction + (goto-char start) ;; breaking save-excursion + (let ((eregex (mew-decode-multipart-end-boundary-regex boundary)) + break part) + (if (not (and (re-search-forward eregex nil t) + (forward-line) + (re-search-forward bregex nil t))) + (error "") + (mew-xinfo-set-warning + (cons "Duplicate boundary\n" (mew-xinfo-get-warning))) + (mew-xinfo-set-decode-err nil) + (setq break (mew-decode-multipart-boundary-end)) + (mew-decode-multipart-beginning-of-part break) + (setq part (mew-decode-multipart-singlepart break start cnt dct)) + (list part break))))) + +(defun mew-decode-multipart-alternative-choice (part prefpart lastpref lastatpref) + (let ((pref (or (mew-multipart-alternative-preference part) + (length mew-mime-multipart-alternative-list))) + (atpref (mew-mime-external-body-preference part))) + ;; returns '(prefpart lastpref lastatpref) + (cond + ((or (null prefpart) (<= pref lastpref)) + (list part pref atpref)) + ((and (= pref lastpref) atpref + (or (null lastatpref) (<= atpref lastatpref))) + ;; If external-body and internal-body are alternative, + ;; what should we do? + (list part lastpref atpref)) + (t + (list prefpart lastpref lastatpref))))) + +(defun mew-decode-multipart-alternative-part (prefpart syntax) + (let* ((beg (mew-syntax-get-begin prefpart)) + (ctl (mew-syntax-get-ct prefpart)) + (ct (mew-syntax-get-value ctl 'cap)) + (multibeg (mew-syntax-get-begin syntax))) + (mew-syntax-set-begin prefpart (cons beg multibeg)) + (mew-xinfo-set-info + (cons + (format "%s in Multipart/Alternative as a singlepart\n" ct) + (mew-xinfo-get-info))) + prefpart)) + +(defun mew-decode-multipart (syntax cnt &optional dct) + (let* ((case-fold-search nil) ;; boundary is case sensitive + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (boundary (mew-syntax-get-param ctl "boundary")) + (count 0) + (parts []) part + (use-alt (and (mew-dinfo-get-use-alt) (string= ct mew-ct-mla))) + prefpart lastpref lastatpref + bregex start break) + (unless boundary + (mew-decode-error "No boundary parameter for multipart")) + (mew-syntax-set-key syntax 'multi) + (setq bregex (mew-decode-multipart-boundary-regex boundary)) + (mew-decode-multipart-beginning-of-first-part bregex ct) + (setq start (point)) ;; the beginning of the first part + (catch 'multipart + (while (re-search-forward bregex nil t) + (setq break (mew-decode-multipart-boundary-end)) + (mew-decode-multipart-beginning-of-part break) + (condition-case err + (setq part (mew-decode-multipart-singlepart break start cnt dct)) + (error + ;; rescue duplicate boundary + (let ((pb (mew-decode-multipart-duplicate-boundary start cnt dct err boundary bregex))) + (mew-set '(part break) pb)))) + (setq count (1+ count)) + (setq start (point)) ;; the beginning of the part + (if use-alt + (let ((pll (mew-decode-multipart-alternative-choice part prefpart lastpref lastatpref))) + (mew-set '(prefpart lastpref lastatpref) pll)) + (setq parts (vconcat parts (vector part)))) + (when break + (if use-alt + (throw 'multipart (mew-decode-multipart-alternative-part prefpart syntax)) + (throw 'multipart (vconcat syntax parts))))) + ;; Let's try to decode the first part even if boundary is not found. + ;; This should save truncated messages. + (when (= count 0) + (save-restriction + (narrow-to-region start (point-max)) + (goto-char (point-min)) + (mew-decode-singlepart cnt dct nil))) + (mew-decode-error (format "No last boundary for %s" ct))))) + +;;; +;;; Privacy services +;;; + +(mew-defstruct privacy-dinfo ct proto result) + +(defun mew-decode-multipart-encrypted (syntax cnt) + ;; called in narrowed region + ;; + ;; CT: M/E; proto; bound; + ;; + ;;(cur)--bound + ;; (the key part) + ;; --bound + ;; (the encrypted part) + ;; --bound-- + (let* ((case-fold-search nil) ;; boundary is case sensitive + (ctl (mew-syntax-get-ct syntax)) + (boundary (mew-syntax-get-param ctl "boundary")) + (switch mew-decode-multipart-encrypted-switch) + file1 file2 file3 syntax1 syntax3 func unknown existp proto + start result file3result privacy bregex) + (unless boundary + (mew-decode-error "No boundary parameter for multipart")) + (setq bregex (mew-decode-multipart-boundary-regex boundary)) + ;; + (unless (and (re-search-forward bregex nil t) + (mew-decode-multipart-boundary-cont)) + (mew-decode-error "No first boundary for Multipart/Encrypted")) + (forward-line) ;; the beginning of the key part + (setq start (point)) + ;; + (unless (and (re-search-forward bregex nil t) + (mew-decode-multipart-boundary-cont)) + (mew-decode-error "No second boundary for Multipart/Encrypted")) + (beginning-of-line) + (setq syntax1 (mew-decode-security-singlepart start (1- (point)))) + (setq proto (mew-syntax-get-value (mew-syntax-get-ct syntax1) 'cap)) + (setq func (mew-decode-get-security-func proto switch)) + (setq existp (mew-decode-get-security-existence proto switch)) + (if func + (if existp (setq file1 (mew-save-decode-form syntax1))) + (setq unknown t)) + (forward-line) ;; the beginning of the encrypted part + (setq start (point)) + ;; + (unless (and (re-search-forward bregex nil t) + (mew-decode-multipart-boundary-end)) + (mew-decode-error "No third boundary for Multipart/Encrypted")) + (beginning-of-line) + (if (and func existp) + (setq file2 (mew-save-decode-form + (mew-decode-security-singlepart start (1- (point)))))) + ;; + (delete-region (point-min) (point-max)) + ;; + ;; Call protocol function + (cond + (unknown + (setq result (concat "unknown protocol " proto))) + ((not existp) + (setq result (concat (mew-decode-get-security-prog proto switch) + " does not exist"))) + (t + (setq file3result (funcall func file1 file2)) + (mew-set '(file3 result) file3result))) + ;; + (if (and func existp (file-exists-p file3)) + (mew-flet + (mew-insert-file-contents file3) + (put-text-property (point-min) (point-max) 'mew-noncontents nil) + ;; because of RICH functionality of RFC1847... Gee dirty! + (mew-decode-crlf-magic)) + (insert "\n") ;; CT: text/plain; charset=us-ascii + (insert "Multipart/Encrypted could not be decrypted.\n") + (mew-xinfo-set-not-decrypted t)) + ;; Throw away garbage + (mew-delete-file file1) + (mew-delete-file file2) + (mew-delete-file file3) + ;; Analyze the decrypted part + (goto-char (point-min)) + (setq syntax3 (mew-decode-singlepart cnt nil nil)) + (setq privacy (mew-syntax-get-privacy syntax3)) + (if privacy (setq result (concat result "\n\t"))) + (mew-syntax-set-privacy + syntax3 (cons (mew-make-privacy-dinfo :ct mew-ct-mle :proto proto :result result) privacy)) + syntax3)) + +(defun mew-decode-multipart-signed (syntax cnt) + ;; called in narrowed region + ;; + ;; CT: M/S; proto; bound; micalg; + ;; + ;;(cur)--bound + ;; (the signed part) + ;; --bound + ;; (the key part) + ;; --bound-- + (let* ((case-fold-search nil) ;; boundary is case sensitive + (ctl (mew-syntax-get-ct syntax)) + (boundary (mew-syntax-get-param ctl "boundary")) + (switch mew-decode-multipart-signed-switch) + file1 file2 syntax2 syntax3 func unknown existp proto + end1 start2 result privacy bregex) + (unless boundary + (mew-decode-error "No boundary parameter for multipart")) + (setq bregex (mew-decode-multipart-boundary-regex boundary)) + ;; + (unless (and (re-search-forward bregex nil t) + (mew-decode-multipart-boundary-cont)) + (mew-decode-error2 "No first boundary for Multipart/Signed")) + (forward-line) ;; the beginning of the signed part + (delete-region (point-min) (point)) ;; deleting content-header + (goto-char (point-min)) ;; just in case + ;; + (unless (and (re-search-forward bregex nil t) + (mew-decode-multipart-boundary-cont)) + (mew-decode-error2 "No second boundary for Multipart/Signed")) + (beginning-of-line) + (setq end1 (1- (point))) ;; the end of the signed part + (forward-line) ;; the beginning of the key part + (setq start2 (point)) + ;; + (unless (and (re-search-forward bregex nil t) + (mew-decode-multipart-boundary-end)) + (mew-decode-error2 "No third boundary for Multipart/Signed")) + (beginning-of-line) ;; the end of the encrypted part + 1 + (setq syntax2 (mew-decode-security-singlepart start2 (1- (point)))) + (setq proto (mew-syntax-get-value (mew-syntax-get-ct syntax2) 'cap)) + (setq func (mew-decode-get-security-func proto switch)) + (setq existp (mew-decode-get-security-existence proto switch)) + (if func + (when existp + (setq file1 (mew-save-transfer-form (point-min) end1 'retain)) + (setq file2 (mew-save-decode-form syntax2 (concat file1 ".sig")))) + (setq unknown t)) + ;; + (delete-region end1 (point-max)) + ;; Now the signed part only + ;; Call protocol function + (cond + (unknown + (setq result (concat "unknown protocol " proto))) + ((not existp) + (setq result (concat (mew-decode-get-security-prog proto switch) + " does not exist"))) + (t + (setq result (funcall func file1 file2)))) + ;; Throw away garbage + (mew-delete-file file1) + (mew-delete-file file2) + ;; Analyze the signed part + (goto-char (point-min)) + (setq syntax3 (mew-decode-singlepart cnt nil nil)) + (setq privacy (mew-syntax-get-privacy syntax3)) + (if privacy (setq result (concat result "\n\t"))) + (mew-syntax-set-privacy + syntax3 (cons (mew-make-privacy-dinfo :ct mew-ct-mls :proto proto :result result) privacy)) + syntax3)) + +(defun mew-decode-security-singlepart (beg end) + (save-excursion + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (mew-decode-singlepart 0)))) ;; 0 is dummy + +(defun mew-save-decode-form (syntax &optional file) + (mew-flet + (unless file (setq file (mew-make-temp-name))) + (write-region (mew-syntax-get-begin syntax) + (mew-syntax-get-end syntax) + file nil 'no-msg) + file)) + +(defun mew-decode-crlf-magic () + (let ((case-fold-search t) + (cte mew-7bit) + key start match) + (save-excursion + (goto-char (point-min)) + (catch 'header + (while (re-search-forward + "^\r?$\\|^Content-Transfer-Encoding:[ \t]*" nil t) + (setq key (mew-match-string 0)) + (setq start (match-end 0)) + (when (string-match "^\r?$" key) + (save-restriction + (if (string-match mew-bin cte) ;; cte may include \r + (narrow-to-region (point-min) (1+ start)) + (narrow-to-region (point-min) (point-max))) + (goto-char (point-min)) + (mew-crlf-to-lf)) + (throw 'header nil)) + (forward-line) + (mew-header-goto-next) + (setq match (mew-buffer-substring start (1- (point)))) + (setq cte (mew-addrstr-parse-value match))))))) + +(provide 'mew-decode) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-decode.el ends here diff --git a/elpa/mew-20150813.2354/mew-demo.el b/elpa/mew-20150813.2354/mew-demo.el new file mode 100644 index 00000000..c2de2d97 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-demo.el @@ -0,0 +1,145 @@ +;;; mew-demo.el --- Startup demo for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew-vars) + +(defvar mew-logo nil) + +(defconst mew-icon-mew "Mew.png") + +(defconst mew-hello-message +" + +Welcome to Mew world. + +Mew -- Messaging in the Emacs World + +%s + +Copyright (C) 1994-2015 Kazu Yamamoto + +Please send comments to Kazu@Mew.org. + +" +) + +(defconst mew-demo-string +'( + "/\\\\ - \\\\/" + + "-\\\\ - \\\\/" "\\\\\\ - \\\\/" "|\\\\ - \\\\/" "/\\\\ - \\\\/" + "-\\\\ - \\\\/" "\\\\\\ - \\\\/" "|\\\\ - \\\\/" "/\\\\ - \\\\/" + + "/|\\ - \\\\/" "//\\ - \\\\/" "/-\\ - \\\\/" "/\\\\ - \\\\/" + "/|\\ - \\\\/" "//\\ - \\\\/" "/-\\ - \\\\/" "/\\\\ - \\\\/" + + "/\\| - \\\\/" "/\\/ - \\\\/" "/\\- - \\\\/" "/\\\\ - \\\\/" + "/\\| - \\\\/" "/\\/ - \\\\/" "/\\- - \\\\/" "/\\\\ - \\\\/" + + "/\\\\ - |\\/" "/\\\\ - /\\/" "/\\\\ - -\\/" "/\\\\ - \\\\/" + "/\\\\ - |\\/" "/\\\\ - /\\/" "/\\\\ - -\\/" "/\\\\ - \\\\/" + + "/\\\\ - \\|/" "/\\\\ - \\//" "/\\\\ - \\-/" "/\\\\ - \\\\/" + "/\\\\ - \\|/" "/\\\\ - \\//" "/\\\\ - \\-/" "/\\\\ - \\\\/" + + "/\\\\ - \\\\-" "/\\\\ - \\\\\\" "/\\\\ - \\\\|" "/\\\\ - \\\\/" + "/\\\\ - \\\\-" "/\\\\ - \\\\\\" "/\\\\ - \\\\|" "/\\\\ - \\\\/" + ) +) + +(defun mew-hello () + (let ((time mew-demo-sit-for) + (left-margin 0) + (fill-column (window-width)) + indent) + (if (not (integerp time)) (setq time 0)) + (insert (format mew-hello-message mew-version)) + (center-region (point-min) (point-max)) + (if (null mew-demo-picture) + (mew-hello-text time) + (cond + ((and window-system + (fboundp 'image-type-available-p) + (image-type-available-p 'png)) + (goto-char (point-max)) + (setq mew-logo (mew-create-image + (expand-file-name mew-icon-mew mew-icon-directory))) + (setq indent (/ (- (window-width) + (truncate (car (image-size mew-logo)))) 2)) + (setq indent (max 0 indent)) + (insert (make-string indent mew-sp)) + (insert-image mew-logo) + (goto-char (point-min)) + (mew-redraw time)) + (t + (mew-hello-text time))) + (set-buffer-modified-p nil)))) + +(defun mew-hello-text (time) + (insert "/\\\\ - \\\\/") + (center-line) + (end-of-line) + (insert (make-string (1- (- (window-width) (current-column))) mew-sp)) + (end-of-line) + (mew-redraw time) + (if (and mew-demo window-system) (mew-demo))) + +(defun mew-demo (&optional string) + (let* ((strs (or string mew-demo-string)) + (wl (window-width)) + (ul (length (regexp-quote "/\\ - \\/"))) + (pl (/ (- wl ul) 2)) + (pre (make-string pl mew-sp)) + (suf (make-string (1- (- (- wl pl) ul)) mew-sp))) + (save-window-excursion + (dolist (str strs) + (mew-demo-print str pre suf) + (mew-demo-loop))))) + +(defun mew-demo-print (string prefix suffix) + (goto-char (point-max)) + (let ((end (point))) + (beginning-of-line) + (delete-region (point) end)) + (insert prefix string suffix)) + +(defun mew-demo-loop () + (mew-redraw 0.02)) + +(provide 'mew-demo) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-demo.el ends here diff --git a/elpa/mew-20150813.2354/mew-draft.el b/elpa/mew-20150813.2354/mew-draft.el new file mode 100644 index 00000000..75869d96 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-draft.el @@ -0,0 +1,1030 @@ +;;; mew-draft.el --- Draft mode for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Draft info +;;; + +(defvar mew-tinfo-list + '("header-keymap" "attach-keymap" "case" "encrypted-p" "privacy-err" + "encode-err" "privacy-type" "hdr-file" "field-del" "other-frame" + "preserved-header" "src-folder" "flowed" "use-flowed")) + +(mew-blinfo-defun 'mew-tinfo mew-tinfo-list) + + +(defvar mew-draft-mode-syntax-table nil + "*Syntax table used while in Draft mode.") + +(unless mew-draft-mode-syntax-table + (setq mew-draft-mode-syntax-table (make-syntax-table text-mode-syntax-table)) + (modify-syntax-entry ?% "." mew-draft-mode-syntax-table)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Draft mode +;;; + +(defun mew-draft-set-local-variables () + (auto-save-mode mew-draft-mode-auto-save) + (make-local-variable 'completion-ignore-case) + (make-local-variable 'paragraph-start) + (setq paragraph-start (concat mew-eoh "\\|[ \t]*$\\|" page-delimiter)) + (make-local-variable 'paragraph-separate) + (setq paragraph-separate paragraph-start) + (make-local-variable 'mail-header-separator) + (setq mail-header-separator mew-header-separator) + (make-local-variable 'comment-start) + (setq comment-start mew-comment-start) + (make-local-variable 'comment-start-skip) + (setq comment-start-skip mew-comment-start-skip) + (add-hook 'after-change-functions 'mew-draft-dynamic-highlight nil 'local) + (if (boundp 'write-file-functions) + (add-hook 'write-file-functions 'mew-encode-make-backup nil 'local) + (add-hook 'local-write-file-hooks 'mew-encode-make-backup)) + (make-local-variable 'after-save-hook) + (when mew-require-final-newline + (make-local-variable 'require-final-newline) + (setq require-final-newline t)) + (when (featurep 'dnd) + (make-local-variable 'dnd-protocol-alist) + (setq dnd-protocol-alist + (append '(("^file:///" . mew-draft-dnd-handle-local-file) + ("^file://" . mew-draft-dnd-handle-file) + ("^file:" . mew-draft-dnd-handle-local-file)) + dnd-protocol-alist)))) + +(defun mew-draft-mode (&optional encrypted) + "A major mode for composing a MIME message. + +\\{mew-draft-mode-map}" + (interactive) + (setq major-mode 'mew-draft-mode) + (setq mode-line-buffer-identification (mew-mode-line-id)) + (mew-draft-set-local-variables) + (use-local-map mew-draft-mode-map) + (set-syntax-table mew-draft-mode-syntax-table) + (cd (expand-file-name mew-home)) + (mew-draft-setup-decoration) + (mew-ainfo-set-icon (file-name-nondirectory (buffer-file-name))) + (mew-tinfo-set-encrypted-p encrypted) + (mew-tinfo-set-privacy-err nil) + (mew-tinfo-set-privacy-type nil) + (mew-tinfo-set-use-flowed (mew-use-format-flowed (mew-tinfo-get-case))) + (mew-draft-mode-name) ;; must be after (mew-tinfo-set-encrypted-p encrypted) + (mew-run-mode-hooks 'text-mode-hook 'mew-draft-mode-hook) + ;; auto-fill-function is set by mew-draft-mode-hook + (when auto-fill-function + (make-local-variable 'auto-fill-function) + (setq auto-fill-function 'mew-draft-auto-fill)) + (setq buffer-undo-list nil)) + +(defun mew-draft-mode-name (&optional header) + (let ((case (mew-tinfo-get-case)) + pcdb sub) + (cond + ((or (mew-tinfo-get-privacy-type) (mew-tinfo-get-privacy-err)) + ;; If privacy err, don't display mew-protect-privacy-always-type etc. + (setq pcdb (mew-pcdb-by-service (mew-tinfo-get-privacy-type))) + (setq sub (mew-pcdb-mark pcdb))) + ((and (mew-tinfo-get-encrypted-p) (mew-protect-privacy-encrypted case)) + (setq pcdb (mew-pcdb-by-service (mew-protect-privacy-encrypted-type case))) + (setq sub (mew-pcdb-mark pcdb))) + ((mew-protect-privacy-always case) + (setq pcdb (mew-pcdb-by-service (mew-protect-privacy-always-type case))) + (setq sub (mew-pcdb-mark pcdb)))) + (setq mode-name (if header mew-mode-name-header mew-mode-name-draft)) + (if sub (setq mode-name (concat mode-name " " sub))) + (unless (mew-case-default-p (mew-tinfo-get-case)) + (setq mode-name (concat mode-name " " (mew-tinfo-get-case)))) + (if (mew-tinfo-get-use-flowed) + (setq mode-name (concat mode-name " F"))) + (force-mode-line-update))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Draft subfunctions +;;; + +(defun mew-draft-dynamic-highlight (beg end len) + (when (mew-in-header-p) + (save-match-data + (mew-highlight-header) + (when (mew-draft-p) + (mew-draft-header-keymap))))) + +(defun mew-draft-auto-fill () + (let ((ret1 (do-auto-fill)) ret2) + (when (mew-in-header-p) + (save-excursion + (beginning-of-line) + (while (not (or (looking-at "[^ \t\n]+:\\|[ \t]") (bobp))) + (setq ret2 t) + (insert "\t") + (forward-line -1) + (beginning-of-line)))) + (or ret1 ret2))) ;; if modifies, return t. + +(defun mew-draft-find-and-switch (draft-path &optional switch-func) + ;; switch-func = nil :: switch-to-buffer + ;; switch-func = t :: switch-to-buffer-other-window + (let* ((display-buffer-alist nil) + (same-window-buffer-names nil) + (same-window-regexps nil) + (draftname (mew-path-to-folder draft-path))) + (when (get-buffer draftname) + (with-current-buffer draftname + (clear-visited-file-modtime) + (set-buffer-modified-p nil) ;; just in case + (mew-delete-file buffer-auto-save-file-name) + (mew-remove-buffer draftname))) + (cond + (mew-use-other-frame-for-draft + (setq switch-func 'switch-to-buffer-other-frame)) + ((eq switch-func nil) + (setq switch-func 'switch-to-buffer)) + ((eq switch-func t) + (setq switch-func 'switch-to-buffer-other-window))) + (mew-frwlet mew-cs-m17n mew-cs-dummy + (funcall switch-func (mew-find-file-noselect draft-path))) + ;; draft buffer + (mew-set-buffer-cs mew-cs-m17n) + ;; copy config, first + (mew-tinfo-set-case mew-case) + (when mew-use-other-frame-for-draft + (mew-tinfo-set-other-frame t) + ;; to ensure to cite a message from summary frame. + (mew-remove-buffer (mew-buffer-message))) + (rename-buffer draftname))) + +(defun mew-draft-to-attach (draft) + "Converting draft to attach. E.g. +draft/1 -> +attach/1" + (mew-concat-folder mew-attach-folder (file-name-nondirectory draft))) + +(defun mew-attachdir (&optional draft) + (mew-expand-folder (mew-draft-to-attach (or draft (buffer-name))))) + +(defun mew-draft-header-insert-alist (halist) + "Insert field-body: and field-value. Return the value of +the Body: field." + (let ((case-fold-search t) + key val ret) + (dolist (ent halist) + (setq key (mew-alist-get-key ent)) + (setq val (mew-alist-get-value ent)) + (unless (string-match ":$" key) + (setq key (concat key ":"))) + (if (string-match mew-body: key) + (setq ret val) + (mew-draft-header-insert key val))) + ret)) + +(defun mew-insert-address-list (field adrs del force-insert) + (let ((cnt 0) (beg (point)) med) + (dolist (adr adrs) + (unless (mew-is-my-address del adr) + (if (= cnt 0) + (insert adr) + (insert ", " adr)) + (setq del (cons (concat "^" (regexp-quote adr) "$") del)) + (setq cnt (1+ cnt)))) + (when (or force-insert (> cnt 0)) + (beginning-of-line) + (insert field " ") + (setq med (point)) + (end-of-line) + (insert "\n") + (mew-header-fold-region beg (point) med 'use-tab)) + del)) + +(defun mew-insert-address-list2 (field adrs) + (when adrs + (let ((beg (point)) med) + (insert field " ") + (setq med (point)) + (insert (car adrs)) + (setq adrs (cdr adrs)) + (dolist (adr adrs) + (insert ", " adr)) + (insert "\n") + (mew-header-fold-region beg (point) med 'use-tab)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Draft header +;;; + +(defun mew-draft-header (&optional subject nl to cc newsgroups in-reply-to references other-headers fromme) +;; to -- string or list +;; cc -- string or list +;; nl -- one empty line under "----", which is necessary if +;; attachment is prepared + (let ((del (unless fromme mew-regex-my-address-list)) ;; deleting list + case body) + (goto-char (point-min)) + (if newsgroups + (cond + ((stringp newsgroups) + (mew-draft-header-insert mew-newsgroups: newsgroups)) + ((listp newsgroups) + (mew-insert-address-list2 mew-newsgroups: newsgroups))) + ;; Insert To: first. + ;; All addresses inserted on To: are appended to del. + (cond + ((null to) (mew-draft-header-insert mew-to: "")) + ((stringp to) ;; To: specified from the mini-buffer. + ;; do not check to is mine. Cc: is also string + ;; We believe that user never specifies the same address of To: to Cc:. + (mew-draft-header-insert mew-to: to)) + ;; To: collected by reply + ((listp to) + (setq del (mew-insert-address-list mew-to: to del t)))) + (cond + ((null cc) ()) ;; do nothing + ((stringp cc) ;; Cc: specified from the mini-buffer. + (mew-draft-header-insert mew-cc: cc)) + ((listp cc) ;; Cc: collected by reply. + (mew-insert-address-list mew-cc: cc del nil)))) + (if mew-case-guess-when-prepared + (mew-draft-set-case-by-guess)) + (setq case (mew-tinfo-get-case)) + (unless newsgroups + (mew-draft-header-insert mew-cc: (mew-cc case))) + (mew-draft-header-insert mew-subj: (or subject "")) + (mew-draft-header-insert mew-from: (mew-from case)) + (mew-draft-header-insert mew-fcc: (mew-fcc case)) + (unless newsgroups + (mew-draft-header-insert mew-bcc: (mew-bcc case)) + (mew-draft-header-insert mew-dcc: (mew-dcc case))) + (mew-draft-header-insert mew-reply-to: (mew-reply-to case)) + (unless newsgroups + (mew-draft-header-insert mew-in-reply-to: in-reply-to)) + (mew-draft-header-insert mew-references: references) + (mew-draft-header-insert-xface) + (mew-draft-header-insert mew-organization: (mew-organization case)) + (setq body (mew-draft-header-insert-alist other-headers)) + ;; Deleting fields defined in mew-header-alist to replace them. + (mew-header-delete-lines (mapcar 'mew-alist-get-key (mew-header-alist case))) + (mew-header-goto-end) + (mew-draft-header-insert-alist (mew-header-alist case)) + ;; X-Mailer: must be the last + (if (mew-use-x-mailer case) + (mew-draft-header-insert mew-x-mailer: mew-x-mailer)) + ;; (mew-header-set "\n") is enough. But highlighting delayed. + (mew-header-prepared) + ;; on the body + (if nl (insert "\n")) + (if body (save-excursion (insert body))) + ;; move the cursor after "To: " + (goto-char (point-min)) + (search-forward ": " nil t))) + +(defun mew-draft-header-insert-xface () + (if (and mew-x-face-file + (file-exists-p (expand-file-name mew-x-face-file))) + (let (xface) + (with-temp-buffer + (mew-insert-file-contents (expand-file-name mew-x-face-file)) + (setq xface (mew-buffer-substring (point-min) + (max (buffer-size) 1)))) + (mew-draft-header-insert mew-x-face: xface)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Citation +;;; + +(defun mew-draft-auto-set-input-method () + (if (and (fboundp 'activate-input-method) + mew-charset-input-method-alist) + (let* ((charset (mew-charset-guess-region + (mew-header-end) (or (mew-attach-begin) (point-max)))) + (method (mew-charset-to-input-method charset))) + (when (stringp method) + (activate-input-method method) + (message "Set input method to %s" method))))) + +(defun mew-draft-yank (&optional arg force) + "Copy and paste a part of message from Message mode WITHOUT +citation prefix and label. +1. Roughly speaking, it copies the body in Message mode. For example, + if text/plain is displayed, the entire Message mode is copied. + If message/rfc822 is displayed, the body without the header is copied. +2. If called with '\\[universal-argument]', the header is also copied if exists. +3. If an Emacs mark exists, the target is the region between the mark and + the cursor." +;; MUST take care of C-x C-x +;; MUST be able to cancel by C-x u + (interactive "P") + (if (and (not force) (or (mew-in-header-p) (mew-in-attach-p))) + (message "Cannot cite a message here") + (let (cite beg end) + (save-excursion + (cond + ((get-buffer (mew-buffer-message)) + (set-buffer (mew-buffer-message))) + ((get-buffer mew-message-last-buffer) + (set-buffer mew-message-last-buffer))) + (set-buffer (mew-buffer-message)) + (save-restriction + (widen) + (let ((mark-active t)) + (cond + (arg + (setq beg (point-min) end (point-max))) + ((and (not mew-cite-ignore-region) + (mew-mark) + (/= (point) (mew-mark)) + (not (and mew-cite-ignore-mouse-region + (mew-mouse-region-p)))) + (setq beg (region-beginning) end (region-end))) + ((mew-msghdr-p) + ;; header exists in Message mode + (mew-header-goto-body) + (setq beg (point) end (point-max))) + (t + (setq beg (point-min) end (point-max))))) + (setq cite (mew-buffer-substring beg end)))) + (mew-push-mark) + (insert cite) + (mew-draft-auto-set-input-method)))) + +(defvar mew-message-citation-buffer nil + "This value is used by mew-gnus.el to specify a buffer from where +you can cite.") + +(defvar mew-message-citation-frame-id nil) + +(defun mew-draft-cite (&optional arg force) + "Copy and paste a part of message from Message mode with +citation prefix and label. +1. Roughly speaking, it copies the body in Message mode. For example, + if text/plain is displayed, the entire Message mode is copied. + If message/rfc822 is displayed, the body without the header is copied. +2. If called with '\\[universal-argument]', the header is also copied if exists. +3. If an Emacs mark exists, the target is the region between the mark and + the cursor." +;; MUST take care of C-x C-x +;; MUST be able to cancel by C-x u + (interactive "P") + (if (and (not force) (or (mew-in-header-p) (mew-in-attach-p))) + (message "Cannot cite a message here") + (let* ((nonmewbuf mew-message-citation-buffer) ;; may be buffer local + (fid (or mew-message-citation-frame-id (mew-frame-id))) + (fld (mew-current-get-fld fid)) + (msg (mew-current-get-msg fid)) + (msg-buf (mew-buffer-message)) + cite beg end tbuf irt-msgid) + (unless (get-buffer msg-buf) + (setq msg-buf mew-message-last-buffer)) + (save-excursion + ;; + ;; extract the body without header + ;; + (setq tbuf (or nonmewbuf msg-buf)) + (if (get-buffer tbuf) + (set-buffer tbuf) + (error "No buffer to be cited")) + (save-restriction + ;; first prepare "cite" + (widen) + (let ((mark-active t)) + (cond + ;; arg will be effect in mew-cite-original + ((and (not mew-cite-ignore-region) + (mew-mark) + (/= (point) (mew-mark)) + (not (and mew-cite-ignore-mouse-region + (mew-mouse-region-p)))) + (setq beg (region-beginning) end (region-end))) + ((mew-msghdr-p) + ;; header exists in Message mode. Skip the header + ;; because we will concatenate it to cite later. + (mew-header-goto-body) + (setq beg (point) end (point-max))) + (t + (setq beg (point-min) end (point-max))))) + (setq cite (mew-buffer-substring beg end))) + ;; + ;; concat the header + ;; + (setq tbuf (or nonmewbuf + (save-excursion + (when (get-buffer msg-buf) + (set-buffer msg-buf) + (if (mew-msghdr-p) (current-buffer)))) + ;; header exists only in cache if multipart + (mew-cache-hit fld msg))) + (if (get-buffer tbuf) + (set-buffer tbuf) + (error "No buffer to be cited")) + (save-restriction + (widen) + (mew-header-goto-end) + (setq cite (concat (mew-buffer-substring (point-min) (point)) + "\n" cite)) + (setq irt-msgid (mew-idstr-get-first-id + (mew-header-get-value mew-message-id:))))) + ;; + ;; Draft mode, insert the header and the body. + ;; + + ;; Append message-id to In-Reply-To: + (if (and irt-msgid (mew-msghdr-p)) + (save-excursion + (let* ((mew-references-max-count nil) + (irt (mew-header-get-value mew-in-reply-to:)) + (irtl (mew-idstr-to-id-list irt 'rev)) + irtstr) + (mew-addq irtl irt-msgid) + (setq irtl (nreverse irtl)) + (setq irtstr (mew-id-list-to-idstr irtl)) + (mew-header-delete-lines (list mew-in-reply-to:)) + (unless irt (goto-char (mew-header-end))) + (mew-draft-header-insert mew-in-reply-to: irtstr)))) + (save-restriction + ;; this gets complicated due to supercite, please do not care + (narrow-to-region (point) (point)) ;; for (goto-char (point-min)) + (insert cite) + ;; not for C-x C-x. Do not use mew-push-mark. + (push-mark (point) t t) + (goto-char (point-min))) + (cond + (mew-cite-hook + (run-hooks 'mew-cite-hook)) + (t (mew-cite-original arg))) + ;; (mark-marker) indicates the point after label. + ;; Should we include the label too? + (or force (mew-highlight-body-region (mark-marker) (point) 'draft)) + (mew-draft-auto-set-input-method)))) + +(defconst mew-cite-default-prefix "> ") + +(defun mew-cite-original (&optional arg) + (if (< (marker-position (mark-marker)) (point)) + (exchange-point-and-mark)) + (let ((beg (point)) (end (marker-position (mark-marker))) + label prefix) + (save-restriction + (narrow-to-region beg end) + (condition-case nil + (setq label (funcall mew-cite-strings-function)) + (error + (error "Syntax of mew-cite-format was changed. Read explanation of mew-cite-fields"))) + (cond + (mew-cite-prefix-function + (setq prefix (funcall mew-cite-prefix-function))) + (mew-cite-prefix + (setq prefix mew-cite-prefix)) + (t + (setq prefix mew-cite-default-prefix))) + (if (and mew-cite-prefix-confirmp (not mew-use-format-flowed)) + (let ((ask (read-string + (format "Prefix (\"%s\"): " prefix) ""))) + (if (not (string= ask "")) (setq prefix ask)))) + ;; C-u C-c C-y cites body with header. + (if (eq arg nil) + ;; header has been already cited. So, delete it. + (delete-region beg (progn (mew-header-goto-body) (point)))) + (insert label) + (mew-push-mark) + (if (or mew-cite-prefix-function mew-cite-prefix) + (progn + (and (bolp) (insert prefix)) + (while (= 0 (forward-line)) + (or (= (point) (point-max)) + (insert prefix)))) + (if (bolp) (mew-cite-format-flowed)) + (while (= 0 (forward-line)) + (unless (= (point) (point-max)) + (mew-cite-format-flowed))))))) + +(defun mew-cite-format-flowed () + (insert mew-flowed-quoted) + (unless (char-equal (char-after) mew-flowed-quoted) + (insert mew-flowed-stuffed))) + +(defun mew-cite-get-value (field) + (let ((value (mew-header-get-value field)) + repl func) + (when (and (string= mew-from: field) value + (setq func (mew-addrbook-func mew-addrbook-for-cite-label))) + (setq repl (funcall func (mew-addrstr-parse-address value))) + (if repl (setq value repl))) + (or value ""))) + +(defun mew-cite-strings () + "A function to create cite labels according to +'mew-cite-format' and 'mew-cite-fields'." + (if (null mew-cite-fields) + "" + (let* ((vals (mapcar 'mew-cite-get-value mew-cite-fields)) + (label (apply 'format mew-cite-format vals)) + (ellipses (if (stringp mew-draft-cite-ellipses) + mew-draft-cite-ellipses "")) + beg eol) + (if (not (or (eq mew-draft-cite-fill-mode 'truncate) + (eq mew-draft-cite-fill-mode 'wrap))) + label + (with-temp-buffer + (let ((fill-column + (or mew-draft-cite-label-fill-column fill-column))) + (insert label) + (goto-char (point-min)) + (while (not (eobp)) + (cond + ((eq mew-draft-cite-fill-mode 'truncate) + (end-of-line) + (if (>= fill-column (current-column)) + () + (setq eol (point)) + (insert ellipses) + (goto-char eol) + (while (< fill-column (current-column)) + (delete-char -1)))) + ((eq mew-draft-cite-fill-mode 'wrap) + (setq beg (point)) + (end-of-line) + (if (= (current-column) 0) + () + (fill-region beg (point))))) + (forward-line))) + (buffer-string)))))) + +(defun mew-cite-prefix-username () + "A good candidate for mew-cite-prefix-function. +The citation style is 'from_address> ', e.g. 'kazu> '" + (let* ((from (mew-header-parse-address mew-from:)) + (user (mew-addrstr-extract-user from)) + (func (mew-addrbook-func mew-addrbook-for-cite-prefix)) + nickname prefix) + (if func (setq nickname (funcall func from))) + (setq prefix (or nickname user)) + (if mew-ask-cite-prefix + (setq prefix (read-string "Citation prefix: " prefix))) + (concat prefix mew-cite-default-prefix))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; format=flowed +;;; + +(defun mew-draft-encode-flowed (&optional arg) + "Manually encode the body with format=flowed. +If called with '\\[universal-argument]', toggle whether or not +format=flowed is used on composing." + (interactive "P") + (if arg + (progn + (mew-tinfo-set-use-flowed (not (mew-tinfo-get-use-flowed))) + (mew-draft-mode-name)) + (save-excursion + (goto-char (mew-header-end)) + (forward-line) + (if (mew-tinfo-get-flowed) + (progn + (mew-decode-flowed (point) (point-max) + (if (string= (mew-tinfo-get-flowed) "yes") t nil)) + (mew-tinfo-set-flowed nil)) + (let* ((charset (mew-charset-guess-region (point) (point-max))) + (flowed-delsp (mew-encode-flowed (point) (point-max) charset)) + flowed delsp) + (mew-set '(flowed delsp) flowed-delsp) + (if (not flowed) + (message "No line folded") + (mew-tinfo-set-flowed (if delsp "yes" "no"))))) + (mew-draft-rehighlight) + (setq buffer-undo-list nil)))) + +(defun mew-draft-use-format-flowed (&optional arg) + "Toggle the use of format=flowed for the current draft. +If called with '\\[universal-argument]', enable format=flowed if the argument +is positive. You can use `mew-draft-use-format-flowed-hooks' to +enable interesting minor modes according to whether the message is +flowed or not. Here is an example: + +\(add-hook 'mew-draft-use-format-flowed-hooks + '(lambda() + (if mew-use-format-flowed + (progn + (auto-fill-mode 0) + (visual-line-mode 1)) + (progn + (auto-fill-mode 1) + (visual-line-mode 0))) + ))" + (interactive "P") + (set (make-local-variable 'mew-use-format-flowed) + (if (null arg) + (not (mew-use-format-flowed)) + (> (prefix-numeric-value arg) 0))) + (mew-tinfo-set-use-flowed mew-use-format-flowed) + (mew-draft-mode-name) ;; Display "F" if Flowed + (run-hooks 'mew-draft-use-format-flowed-hooks)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Misc +;;; + +(defun mew-draft-save-buffer () + "Save this draft." + (interactive) + (let ((after-change-functions nil)) + (save-excursion + (mew-header-clear 'keep-read-only) + (insert-before-markers "\n") ;; for mew-summary-reply + (save-buffer) + (delete-region (1- (point)) (point)) + (mew-header-prepared) + (set-buffer-modified-p nil)))) + +(defun mew-draft-kill () + "Kill this draft." + (interactive) + (if (not (y-or-n-p "Kill draft message? ")) + (message "Draft was not killed") + (let* ((attachdir (mew-attachdir)) ;; attachdir must be here + (draft (buffer-file-name)) + (buf (current-buffer)) + (mdi (concat draft mew-draft-info-suffix))) + (mew-elet + (mew-overlay-delete-buffer)) + (save-buffer) + (mew-delete-file draft) + (mew-delete-file mdi) + (if (and (mew-tinfo-get-other-frame) (> (length (frame-list)) 1)) + (delete-frame) + (mew-current-get-window-config)) + (mew-delete-directory-recursively attachdir) + (mew-remove-buffer buf) + (message "Draft was killed")))) + +(defun mew-draft-insert-signature (&optional arg) + "Insert the signature file specified by mew-signature-file. +If attachments exist and mew-signature-as-lastpart is *non-nil*, +the file is attached to the last part. Otherwise, the file is +inserted into the body. If mew-signature-insert-last is *non-nil*, +the file is inserted to the end of the body. Otherwise, inserted +the cursor position. If executed with '\\[universal-argument]', +you can set the case." + (interactive "P") + (let (case sigfile) + (cond + ((stringp arg) + (setq case arg)) + (arg + (setq case (mew-input-case (mew-tinfo-get-case) "Signature"))) + (t + (setq case (mew-tinfo-get-case)))) + (setq sigfile (expand-file-name (mew-signature-file case))) + (if (not (file-exists-p sigfile)) + (message "No signature file %s" sigfile) + (if (and (mew-attach-p) mew-signature-as-lastpart) + (progn + (goto-char (point-max)) + (forward-line -2) + (mew-attach-forward) + (mew-attach-copy sigfile "Signature") + (let* ((nums (mew-syntax-nums)) + (syntax (mew-syntax-get-entry mew-encode-syntax nums))) + (mew-syntax-set-cdp syntax nil) + (mew-syntax-set-cd syntax mew-signature-description)) + (mew-encode-syntax-print mew-encode-syntax)) + (when mew-signature-insert-last + (if (null (mew-attach-p)) + (goto-char (point-max)) + (goto-char (1- (mew-attach-begin)))) + (end-of-line) + (unless (bolp) (insert "\n"))) + (mew-insert-file-contents sigfile))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Re-highlight +;;; + +(defun mew-draft-rehighlight-body () + (save-excursion + (let ((beg (progn (goto-char (mew-header-end)) (forward-line) (point))) + (end (or (mew-attach-begin) (point-max)))) + (mew-highlight-body-region beg end 'draft 'rehighlight)))) + +(defun mew-draft-rehighlight () + "Highlight header and body again." + (interactive) + (let ((mod (buffer-modified-p))) + (mew-highlight-header) + (mew-draft-header-keymap) + (mew-draft-rehighlight-body) + (set-buffer-modified-p mod))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Privacy +;;; + +(defun mew-draft-toggle-privacy-always () + "Toggle whether or not all drafts are protected." + (interactive) + (setq mew-protect-privacy-always (not mew-protect-privacy-always)) + (message "Set mew-protect-privacy-always to %s" + mew-protect-privacy-always) + (mew-draft-mode-name)) + +(defun mew-draft-toggle-privacy-encrypted () + "Toggle whether or not drafts replying to encrypted messages are +protected." + (interactive) + (setq mew-protect-privacy-encrypted (not mew-protect-privacy-encrypted)) + (message "Set mew-protect-privacy-encrypted to %s" + mew-protect-privacy-encrypted) + (mew-draft-mode-name)) + +(defun mew-draft-set-privacy-type () + "\\ +Set privacy service which will be effective when \\[mew-draft-make-message]." + (interactive) + (let* ((services (mew-pcdb-services)) + (alist (mapcar (lambda (x) (cons (symbol-name x) x)) services)) + str) + (setq str (completing-read "Input privacy services: " alist nil t)) + (when (stringp str) + (mew-tinfo-set-privacy-type (cdr (assoc str alist))) + (mew-tinfo-set-privacy-err nil))) + (mew-draft-mode-name)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sending and Queuing +;;; + +(defun mew-draft-make-message (&optional privacy signer) + "Compose a MIME message then put it into a queue folder." + (interactive) + (if (string= mode-name "Edit") + (mew-edit-make) + (if (and (mew-called-interactively-p) ;; prevent the loop + mew-use-old-pgp + mew-protect-privacy-with-old-pgp-signature) + (mew-pgp-sign-message) + (mew-draft-process-message 'queue privacy signer)))) + +(defun mew-draft-send-message () + "Compose a MIME message then send it." + (interactive) + (if (string= mode-name "Edit") + (mew-edit-make) + (if (and (mew-called-interactively-p) ;; just in case + mew-use-old-pgp + mew-protect-privacy-with-old-pgp-signature) + (mew-pgp-sign-message) + (mew-draft-process-message 'send)))) + +(defun mew-draft-process-message (action &optional privacy signer) + (if (and (boundp 'visual-line-mode) visual-line-mode) (visual-line-mode -1)) + (run-hooks 'mew-make-message-hook) + (let* ((case (or (mew-tinfo-get-case) mew-case-default)) + (old-case case) + guessed-case) + (when mew-case-guess-when-composed + (setq guessed-case (mew-draft-get-case-by-guess)) + (when guessed-case + (if mew-case-guess-addition + (setq case (mew-draft-add-case case guessed-case)) + (setq case guessed-case)))) + (unless (string= old-case case) + (mew-tinfo-set-case case) + (mew-draft-mode-name (mew-tinfo-get-hdr-file)) + (mew-draft-replace-fields old-case) + (when (eq action 'send) + (mew-highlight-header) + (unless (mew-tinfo-get-hdr-file) (mew-draft-header-keymap))) + (save-buffer)) + (if (mew-header-existp mew-newsgroups:) + (mew-draft-nntp-process-message case action privacy signer) + (mew-draft-smtp-process-message case action privacy signer)))) + +(defun mew-draft-resent-p (end) + (let ((case-fold-search t)) + (save-excursion + (re-search-forward mew-resent-regex end t)))) + +(defun mew-draft-smtp-process-message (case action &optional privacy signer) + (run-hooks 'mew-send-hook) + (let* ((buf (current-buffer)) + (pnm (mew-smtp-info-name case)) + (queue (mew-queue-folder case)) + resentp fcc sendit msg err) + (if (get-process pnm) + (message "Another message is being sent. Try later") + (mew-draft-remove-invalid-fields) + ;; Check resentp + (save-excursion + (goto-char (point-min)) + (setq resentp (mew-draft-resent-p (mew-header-end)))) + ;; Ask Subject: before the query of "Really send". + ;; Typing C-g here gets back to the draft. + (mew-encode-ask-subject) + (setq fcc (mew-encode-ask-fcc resentp)) + (if (eq action 'queue) + (setq sendit t) + (if mew-ask-send + (setq sendit (y-or-n-p "Really send this message? ")) + (setq sendit t))) + (when sendit + ;; password should be asked in Summary mode. + (if (and (mew-tinfo-get-other-frame) (> (length (frame-list)) 1)) + (delete-frame) + (mew-current-get-window-config) + (delete-windows-on buf)) ;; just in case + (save-excursion + (save-window-excursion + (set-buffer buf) + (if (mew-smtp-encode pnm case resentp fcc privacy signer) + (let ((mdi (concat (buffer-file-name) mew-draft-info-suffix))) + (mew-delete-file mdi) + (setq msg (mew-smtp-queue case "from Draft mode")) + (mew-remove-buffer buf) + (if (eq action 'send) + (mew-smtp-send-message case queue (list msg)))) + (setq err t)))) + ;; now +queue/1 exists + (if err + (progn + (mew-current-set-window-config) + (switch-to-buffer buf) + (delete-other-windows)) + (if (and (eq action 'queue) mew-visit-queue-after-sending) + (mew-summary-visit-folder queue)) + (run-hooks 'mew-real-send-hook)))))) + +(defun mew-draft-nntp-process-message (case action &optional privacy signer) + (run-hooks 'mew-post-hook) + (let* ((buf (current-buffer)) + (pnm (mew-nntp2-info-name case)) + (postq (mew-postq-folder case)) + fcc sendit msg err) + (if (get-process pnm) + (message "Another message is being posted. Try later") + (mew-draft-remove-invalid-fields) + ;; Ask Subject: before the query of "Really post". + ;; Typing C-g here gets back to the draft. + (mew-encode-ask-subject) + (setq fcc (mew-encode-ask-fcc nil)) + (if (eq action 'queue) + (setq sendit t) + (if mew-ask-post + (setq sendit (y-or-n-p "Really post this message? ")) + (setq sendit t))) + (when sendit + ;; password should be asked in Summary mode. + (if (and (mew-tinfo-get-other-frame) (> (length (frame-list)) 1)) + (delete-frame) + (mew-current-get-window-config) + (delete-windows-on buf)) ;; just in case + (save-excursion + (save-window-excursion + (set-buffer buf) + (if (mew-nntp2-encode pnm case fcc privacy signer) + (let ((mdi (concat (buffer-file-name) mew-draft-info-suffix))) + (mew-delete-file mdi) + (setq msg (mew-nntp2-queue case "from Draft mode")) + (mew-remove-buffer buf) + (if (eq action 'send) + (mew-nntp2-send-message case postq (list msg)))) + (setq err t)))) + (if err + (progn + (mew-current-set-window-config) + (switch-to-buffer buf) + (delete-other-windows)) + (if (and (eq action 'queue) mew-visit-queue-after-sending) + (mew-summary-visit-folder postq)) + (run-hooks 'mew-real-post-hook)))))) + +(defun mew-draft-remove-invalid-fields () + (when (mew-header-end) + (save-excursion + (save-restriction + (goto-char (mew-header-end)) + (if (not (bolp)) (insert "\n")) + (narrow-to-region (point-min) (mew-header-end)) + (let (beg med str) + (mew-elet + ;; removing null lines + (goto-char (point-min)) + (while (and (re-search-forward "^$" nil t) + (not (eobp))) + (delete-char 1)) + ;; removing fields which do not have value. + (goto-char (point-min)) + (while (not (eobp)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq beg (match-beginning 0)) + (setq med (match-end 0)) + (forward-line) + (mew-header-goto-next) + (setq str (mew-buffer-substring med (1- (point)))) + ;; str may consists of multiple lines + ;; So, "$" does not work. We need to use "[^ ]". + (unless (string-match "[^ \t\n]" str) + (delete-region beg (point))))))))))) + +;; backward-compatibility +(defalias 'mew-draft-send-letter 'mew-draft-send-message) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Privacy +;;; + +(defvar mew-draft-privacy-method-alist '(("pgp" . pgp) ("smime" . smime))) + +(defun mew-draft-set-privacy-method () + "Set mew-draft-privacy-method. 'pgp or 'smime." + (interactive) + (let ((method (completing-read "Privacy method: " mew-draft-privacy-method-alist nil t))) + (setq mew-draft-privacy-method + (cdr (assoc method mew-draft-privacy-method-alist))))) + +(defmacro mew-draft-privacy-switch (&rest form) + `(let ((method (mew-draft-privacy-method (mew-tinfo-get-case)))) + (cond + ,@(mapcar + (lambda (x) + (if (eq (car x) t) + x + `((eq method ',(car x)) ,(car (cdr x))))) + form) + (t (message "'%s' is not supported" method))))) + +(defun mew-draft-sign-message (&optional arg) + "Sign the entire draft. Input your passphrase." + (interactive "P") + (mew-draft-privacy-switch + (pgp (mew-pgp-sign-message arg)) + (smime (mew-smime-sign-message arg)))) + +(defun mew-draft-encrypt-message () + "Encrypt the entire draft with PGP." + (interactive) + (mew-draft-privacy-switch + (pgp (mew-pgp-encrypt-message)) + (smime (mew-smime-encrypt-message)))) + +(defun mew-draft-sign-encrypt-message (&optional arg) + "Sign then encrypt the entire draft. Input your passphrase." + (interactive "P") + (mew-draft-privacy-switch + (pgp (mew-pgp-sign-encrypt-message arg)) + (smime (mew-smime-sign-encrypt-message arg)))) + +(defun mew-draft-encrypt-sign-message (&optional arg) + "Encrypt then sign the entire draft. Input your passphrase." + (interactive "P") + (mew-draft-privacy-switch + (pgp (mew-pgp-encrypt-sign-message arg)) + (smime (mew-smime-encrypt-sign-message arg)))) + +(provide 'mew-draft) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-draft.el ends here diff --git a/elpa/mew-20150813.2354/mew-edit.el b/elpa/mew-20150813.2354/mew-edit.el new file mode 100644 index 00000000..dfd2f377 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-edit.el @@ -0,0 +1,1202 @@ +;;; mew-edit.el + +;; Author: Kazu Yamamoto +;; Created: Nov 9, 1999 + +;;; Code: + +(require 'mew) + +(defun mew-decode-for-edit () + "Decode a message without limitations. +Execute mew-dinfo-set before calling this." + ;; See also mew-decode. + (mew-decode-syntax-clear) + (mew-xinfo-set-text-body t) + (mew-set-buffer-multibyte t) + (let ((mew-header-max-length nil) + (mew-header-max-depth nil)) + (if (mew-debug 'decode) + (let ((debug-on-error t)) + (setq mew-decode-syntax + (mew-decode-message (mew-decode-syntax-rfc822-head) 0))) + (condition-case nil + (setq mew-decode-syntax + (mew-decode-message (mew-decode-syntax-rfc822-head) 0)) + (error + (error "MIME decoding error: %s" (mew-xinfo-get-decode-err))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Header mode +;;; + +(defun mew-header-mode () + "A major mode for composing a MIME message by editing its header only. + +\\{mew-header-mode-map}" + (interactive) + (mew-draft-set-local-variables) + (setq major-mode 'mew-header-mode) + (use-local-map mew-header-mode-map) + (cd (expand-file-name mew-home)) + (mew-header-setup-decoration) + (mew-draft-mode-name 'header) + (force-mode-line-update) + (mew-run-mode-hooks 'mew-header-mode-hook) + ;; auto-fill-function is set by mew-header-mode-hook + (when auto-fill-function + (make-local-variable 'auto-fill-function) + (setq auto-fill-function 'mew-draft-auto-fill))) + +(defmacro mew-summary-header-mode (fields &rest body) + ;; (declare (indent 1)) + `(mew-summary-msg-or-part + (mew-summary-display 'redisplay) + (mew-current-set-window-config) + (let* ((draft (mew-folder-new-message mew-draft-folder)) + (attachdir (mew-attachdir draft)) + (fid (mew-frame-id)) + (fld (mew-current-get-fld fid)) + (msg (mew-current-get-msg fid))) + (mew-summary-prepare-draft + (mew-draft-find-and-switch draft) + (mew-delete-directory-recursively attachdir) + ,@body + (mew-header-mode) + ;; (mew-header-set "\n") is enough. But highlighting delayed. + (mew-header-prepared) + (goto-char (point-min)) + (end-of-line) + (mew-tinfo-set-hdr-file (mew-expand-msg fld msg)) + (mew-tinfo-set-field-del ,fields))))) +(put 'mew-summary-header-mode 'lisp-indent-function 1) + +(defun mew-summary-send-to-others () + "Prepare Header mode so that this message is to be sent +other people by a header re-write." + (interactive) + (mew-summary-header-mode mew-field-delete-for-others + (let ((case (mew-tinfo-get-case))) + (mew-draft-header-insert mew-to: "") + (mew-draft-header-insert mew-cc: (mew-cc case)) + (mew-draft-header-insert mew-from: (mew-from case)) + (mew-draft-header-insert mew-fcc: (mew-fcc case)) + (mew-draft-header-insert mew-bcc: (mew-bcc case)) + (mew-draft-header-insert mew-dcc: (mew-dcc case)) + (mew-draft-header-insert mew-organization: (mew-organization case))))) + +(defun mew-summary-resend () + "Prepare Header mode so that this message is to be forwarded +by a header re-write." + (interactive) + (mew-summary-header-mode mew-field-delete-for-resending + (let ((case (mew-tinfo-get-case))) + (mew-draft-header-insert mew-resent-to: "") + (mew-draft-header-insert mew-resent-cc: (mew-cc case)) + (mew-draft-header-insert mew-resent-from: (mew-from case)) + (mew-draft-header-insert mew-resent-fcc: (mew-fcc case)) + (mew-draft-header-insert mew-resent-bcc: (mew-bcc case)) + (mew-draft-header-insert mew-resent-dcc: (mew-dcc case))))) + +(defun mew-header-process-message (action) + (if (not (file-readable-p (mew-tinfo-get-hdr-file))) + (message "No corresponding message!") + (if (mew-header-existp mew-newsgroups:) + (mew-header-nntp-process-message action) + (mew-header-smtp-process-message action)))) + +(defun mew-header-smtp-process-message (action) + (let* ((buf (current-buffer)) + (case (mew-tinfo-get-case)) + (pnm (mew-smtp-info-name case)) + (queue (mew-queue-folder case)) + sendit resentp fcc msg err) + (if (get-process pnm) + (message "Another message is being sent. Try later") + (mew-draft-remove-invalid-fields) + (goto-char (point-min)) + (setq resentp (mew-draft-resent-p (mew-header-end))) + (setq fcc (mew-encode-ask-fcc resentp)) + (if (and (eq action 'send) mew-ask-send) + (setq sendit (y-or-n-p "Really send this message? ")) + (setq sendit t)) + (when sendit + (mew-current-get-window-config) + (mew-redraw) + (save-excursion + (with-current-buffer buf + (mew-encode-make-backup) + (mew-header-clear) + ;; the end of the header + (save-restriction + (narrow-to-region (point) (point)) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (mew-insert-file-contents (mew-tinfo-get-hdr-file))) + (goto-char (point-min)) + (mew-header-goto-end) + (mew-header-set mew-header-separator) + (mew-header-delete-lines mew-field-delete-common) + (mew-header-delete-lines (mew-tinfo-get-field-del))) + (if (mew-smtp-encode pnm case resentp fcc nil nil 'header) + (let ((mdi (concat (buffer-file-name) mew-draft-info-suffix))) + (mew-delete-file mdi) + (setq msg (mew-smtp-queue case "from Draft mode")) + (mew-remove-buffer buf) + (if (eq action 'send) + (mew-smtp-send-message case queue (list msg)))) + (setq err t)))) + (if err + (progn + (mew-current-set-window-config) + (switch-to-buffer buf) + (delete-other-windows)) + (if (and (eq action 'queue) mew-visit-queue-after-sending) + (mew-summary-visit-folder queue))))))) + +(defun mew-header-nntp-process-message (action) + (let* ((buf (current-buffer)) + (case (mew-tinfo-get-case)) + (pnm (mew-nntp2-info-name case)) + (postq (mew-postq-folder case)) + sendit resentp fcc msg err) + (if (get-process pnm) + (message "Another message is being posted. Try later") + (mew-draft-remove-invalid-fields) + (goto-char (point-min)) + (setq resentp (mew-draft-resent-p (mew-header-end))) + (setq fcc (mew-encode-ask-fcc resentp)) + (if (and (eq action 'send) mew-ask-send) + (setq sendit (y-or-n-p "Really post this message? ")) + (setq sendit t)) + (when sendit + (mew-current-get-window-config) + (mew-redraw) + (save-excursion + (with-current-buffer buf + (mew-encode-make-backup) + (mew-header-clear) + ;; the end of the header + (save-restriction + (narrow-to-region (point) (point)) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (mew-insert-file-contents (mew-tinfo-get-hdr-file))) + (goto-char (point-min)) + (mew-header-goto-end) + (mew-header-set mew-header-separator) + (mew-header-delete-lines mew-field-delete-common) + (mew-header-delete-lines (mew-tinfo-get-field-del))) + (if (mew-nntp2-encode pnm case fcc nil nil 'header) + (let ((mdi (concat (buffer-file-name) mew-draft-info-suffix))) + (mew-delete-file mdi) + (setq msg (mew-nntp2-queue case "from Draft mode")) + (mew-remove-buffer buf) + (if (eq action 'send) + (mew-nntp2-send-message case postq (list msg)))) + (setq err t)))) + (if err + (progn + (mew-current-set-window-config) + (switch-to-buffer buf) + (delete-other-windows)) + (if (and (eq action 'queue) mew-visit-queue-after-sending) + (mew-summary-visit-folder postq))))))) + +(defun mew-header-make-message () + "Compose a MIME message from the header and its body +then put it into a queue folder." + (interactive) + (mew-header-process-message 'queue)) + +(defun mew-header-send-message () + "Compose a MIME message from the header and its body +then send it." + (interactive) + (mew-header-process-message 'send)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Saving +;;; + +(defun mew-summary-save (&optional askcs) + "Save any parts. If the target is a message, you are asked which +you want to save, the entire message or its body. If the target is +a non-message part, the part is saved (with line delimiter conversion +if it is a text object). When executed with '\\[universal-argument]', coding-system for +a text object to be saved can be specified." + (interactive "P") + (mew-summary-msg-or-part + ;; need to make a cache or a message buffer. + (mew-summary-toggle-disp-msg 'on) + (mew-summary-display) + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (num (mew-syntax-number)) + (nums (mew-syntax-number-to-nums num)) + (cbuf (mew-cache-hit fld msg)) + (alt (mew-cache-dinfo-get-use-alt cbuf)) + (cache (or cbuf (mew-buffer-message))) + (syntax (mew-syntax-get-entry (mew-cache-decode-syntax cache) nums)) + (action "Save") + PLUS1P limit have-hdrp bodyp beg end cdpl file ct ctl + doit append-p) + ;; Due to mew-decode-broken, the filename may be changed. + ;; So, save it here. + (and syntax (setq cdpl (mew-syntax-get-cdp syntax))) + (setq ctl (mew-syntax-get-ct syntax)) + (setq file (mew-syntax-get-filename cdpl ctl)) + ;; First of all, we should determine which part the user want to + ;; save due to the ambiguity. + ;; "y" on Message/Rfc822 + ;; - msg/txt the entire msg or its body? + ;; - msg/mul/txt the entire msg or its part 1? + ;; We have to make use of mew-decode-syntax + ;; in the cache buffer due to the PGP/MIME dilemma. + ;; We need the correct LIMIT. + (if (mew-syntax-message-p syntax) + (let ((bodyname "the body") body bct plus1p) + (setq body (mew-syntax-get-part syntax)) + (when (mew-syntax-multipart-p body) + (setq plus1p t) + (setq bodyname "the part 1 text") + (setq body (mew-syntax-get-entry body '(1)))) + (setq bct (mew-syntax-get-value (mew-syntax-get-ct body) 'cap)) + (if (mew-ct-textp bct) + (if (y-or-n-p (format "Save the entire message (y) or %s (n)? " bodyname)) + (setq have-hdrp t) + (if plus1p + (setq nums (nconc nums '(1))) + (setq bodyp t)) + (setq PLUS1P (mew-syntax-get-privacy body))) + (setq have-hdrp t)))) + ;; Now, let's analyze the message in the burst buffer. + ;; This is lengthy, though, avoidable. + (setq limit (length nums)) + (if (or PLUS1P bodyp) ;; VERY important for PGP/MIME + (setq limit (1+ limit))) + ;; + (with-temp-buffer + (mew-insert-message fld msg mew-cs-text-for-read nil) + (mew-dinfo-set limit 'no-cs-conv t alt) + (mew-decode-for-edit) + ;; + (setq syntax (mew-syntax-get-entry mew-decode-syntax nums)) + (if bodyp (setq syntax (mew-syntax-get-part syntax))) + (setq beg (mew-syntax-get-begin syntax)) + (if (mew-syntax-message-p syntax) + (setq end (mew-syntax-get-end (mew-syntax-get-part syntax))) + (setq end (mew-syntax-get-end syntax))) + (setq ctl (mew-syntax-get-ct syntax)) + (setq cdpl (mew-syntax-get-cdp syntax)) + (setq file (mew-syntax-get-filename cdpl ctl)) + ;; + (if (and mew-use-samba-encoding + file + (string-match mew-regex-nonascii file)) + (setq file (mew-samba-encoding file))) + (setq file (mew-summary-input-file-name nil file)) + (if (not (file-exists-p file)) + (setq doit t) + (if (null mew-file-append-p) + (setq action "Overwrite") + (setq action "Append") + (setq append-p t)) + (if (y-or-n-p (format "File exists. %s it to %s? " action file)) + (setq doit t))) + ;; + (if (not doit) + (message "Did not save anything") + (let (linebasep fromcs tocs charset writecs) + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (setq ct (mew-syntax-get-value ctl 'cap)) + ;; Allow Message/Rfc822. It's user's risk. + (setq linebasep (or (mew-ct-textp ct) (mew-ct-linebasep ct))) + (if linebasep + (setq writecs mew-cs-text-for-write) + (setq writecs mew-cs-binary)) + (when (and askcs linebasep) + (setq tocs (read-coding-system "Coding-system: ")) + (if (mew-cs-raw-p tocs) + (setq writecs tocs tocs nil))) + (when have-hdrp + (goto-char (point-min)) + (mew-header-delete-lines mew-field-delete-common) + (mew-header-delete-lines mew-field-delete-for-saving)) + (when tocs + (setq charset (mew-syntax-get-param ctl "charset")) + (if charset (setq fromcs (mew-charset-to-cs charset))) + ;; When saving an entire message or its body, + ;; its charset is unknown since it is not analyzed. + ;; So, we make use of mew-cs-autoconv. + (unless (mew-coding-system-p fromcs) + (error "Unknown coding system %s" (symbol-name fromcs))) + (unless (mew-coding-system-p tocs) + (error "Unknown coding system %s" (symbol-name tocs))) + (mew-cs-decode-region + (point-min) (point-max) (or fromcs mew-cs-autoconv)) + (mew-cs-encode-region (point-min) (point-max) tocs)) + (mew-frwlet mew-cs-dummy writecs + ;; do not specify 'no-msg + (write-region (point-min) (point-max) file append-p))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Local cs +;;; + +(defun mew-summary-convert-local-cs (&optional askcs) + "Convert the character set of body by using autoconv +according to a specified language. +If executed with '\\[universal-argument]', coding-system is asked." + (interactive "P") + (mew-summary-msg-or-part + ;; need to make a cache or a message buffer. + (mew-summary-toggle-disp-msg 'on) + (mew-summary-display) + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (num (mew-syntax-number)) + (nums (mew-syntax-number-to-nums num)) + (cbuf (mew-cache-hit fld msg)) + (alt (mew-cache-dinfo-get-use-alt cbuf)) + (cache (or cbuf (mew-buffer-message))) + (syntax (mew-syntax-get-entry (mew-cache-decode-syntax cache) nums)) + (buf (generate-new-buffer mew-buffer-prefix)) + (win (selected-window)) + (orig-lang current-language-environment) + PLUS1P limit bodyp hbeg hend beg end start + lang prompt tocs cs-env) + (save-excursion + ;; First of all, we should determine which part the user want to + ;; save due to the ambiguity. + ;; "y" on Message/Rfc822 + ;; - msg/txt the entire msg or its body? + ;; - msg/mul/txt the entire msg or its part 1? + ;; We have to make use of mew-decode-syntax + ;; in the cache buffer due to the PGP/MIME dilemma. + ;; We need the correct LIMIT. + (when (mew-syntax-message-p syntax) + (let (body plus1p) + (setq body (mew-syntax-get-part syntax)) + (when (mew-syntax-multipart-p body) + (setq plus1p t) + (setq body (mew-syntax-get-entry body '(1)))) + (if plus1p + (setq nums (nconc nums '(1))) + (setq bodyp t)) + (setq PLUS1P (mew-syntax-get-privacy body)))) + ;; Now, let's analyze the message in the burst buffer. + ;; This is lengthy, though, avoidable. + (setq limit (length nums)) + (if (or PLUS1P bodyp) ;; VERY important for PGP/MIME + (setq limit (1+ limit))) + ;; + (set-buffer buf) + (mew-erase-buffer) + (mew-insert-message fld msg mew-cs-text-for-read nil) + ;; + (cond + (askcs + (setq prompt + (format "Coding-system (autoconv for %s): " orig-lang)) + (setq tocs (or (read-coding-system prompt) mew-cs-autoconv))) + (t + (setq tocs mew-cs-autoconv) + (setq prompt (format "Language (%s): " orig-lang)) + (setq lang (read-language-name nil prompt orig-lang)) + (setq cs-env (mew-set-language-environment-coding-systems lang)))) + (mew-dinfo-set limit 'no-cs-conv t alt) + (mew-decode-for-edit) + ;; + (setq syntax (mew-syntax-get-entry mew-decode-syntax nums)) + (when bodyp + (setq hbeg (mew-syntax-get-begin syntax)) + (setq hend (mew-syntax-get-end syntax)) + (setq syntax (mew-syntax-get-part syntax))) + (setq beg (mew-syntax-get-begin syntax)) + (setq end (mew-syntax-get-end syntax)) + ;; + (set-buffer (mew-buffer-message)) + (select-window (get-buffer-window (current-buffer))) + (widen) + (mew-elet + (delete-region (point-min) (point-max)) + (when bodyp + ;; This must be "insert-buffer-substring". + (insert-buffer-substring buf hbeg hend) + (mew-header-arrange (point-min) (point-max))) + (setq start (point)) + (save-excursion + (mew-insert-buffer-substring buf beg end) + (mew-cs-decode-region start (point-max) tocs) + (mew-highlight-body-region start (point-max))) + ;; Page breaks + (when mew-break-pages + (goto-char (point-min)) + (mew-message-narrow-to-page)) + (when (and (not askcs) cs-env) + (mew-reset-coding-systems (car cs-env) (cdr cs-env)))) + (mew-summary-display-postscript 'no-hook) + (select-window win)) + (mew-remove-buffer buf)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Burst +;;; + +(defvar mew-burst-last-folder nil) + +(defun mew-input-burst-folder () + (let (default) + (if (and mew-use-burst-folder-history mew-burst-last-folder) + (setq default mew-burst-last-folder) + (setq default (mew-inbox-folder))) ;; local folder + (setq mew-burst-last-folder (mew-input-local-folder default)) + mew-burst-last-folder)) + +(defun mew-summary-burst-part (part folder newmsg &optional num) + (let (n len nums entry file) + (setq n 1) + (cond + (num + (setq nums (mew-syntax-number-to-nums num)) + (setq len 1)) + (t + (setq nums (list n)) + (setq len (- (length part) mew-syntax-magic)))) + (while (<= n len) + (setq entry (mew-syntax-get-entry part nums)) + (cond + ((mew-syntax-multipart-p entry) + (setq newmsg (mew-summary-burst-part entry folder newmsg))) + ((string= (mew-syntax-get-value (mew-syntax-get-ct entry) 'cap) + mew-ct-msg) + (setq file (mew-expand-new-msg folder (number-to-string newmsg))) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region + (mew-syntax-get-begin entry) + ;; This is RFC 822 message. + ;; So, body is a single text/plain. + (mew-syntax-get-end (mew-syntax-get-part entry)) + file nil 'no-msg)) + (mew-set-file-modes file) + (setq newmsg (1+ newmsg)))) + (setq n (1+ n)) + (setq nums (list n))) + newmsg)) + +(defun mew-summary-burst-body (fld msg folder &optional num) + (let (ret errmsg mstr m) + (with-temp-buffer + (mew-insert-message fld msg mew-cs-text-for-read nil) + (mew-dinfo-set 1 nil nil nil) + (mew-decode-for-edit) + (cond + ((not (mew-syntax-multipart-p (mew-syntax-get-part mew-decode-syntax))) + (message "Cannot burst")) + ((not (setq mstr (mew-folder-new-message folder 'num-only))) + (setq errmsg (format "Error in %s. Nothing was processed" folder))) + (t + (setq m (mew-summary-burst-part (mew-syntax-get-part mew-decode-syntax) + folder (string-to-number mstr) num)) + (if (= m (string-to-number mstr)) + (message "Nothing was processed") + (mew-touch-folder folder) + (setq ret (list mstr (number-to-string (1- m))))))) + (if errmsg (error "%s" errmsg)) + ret))) + +(defun mew-summary-burst-files (fld msg dir) + (with-temp-buffer + (let (cnt syntax len stx ctl ct) + (mew-insert-message fld msg mew-cs-text-for-read nil) + ;; must be a message, not a part, so limit is nil + (mew-dinfo-set nil 'no-cs-conv t nil) + (mew-decode-for-edit) + (setq syntax (mew-syntax-get-part mew-decode-syntax)) + (if (mew-syntax-singlepart-p syntax) + (progn + (mew-syntax-set-cdp syntax (mew-syntax-cdp-format mew-ct-txt mew-draft-coverpage)) + (mew-d2e-singlepart syntax dir)) + (setq cnt mew-syntax-magic) + (setq len (length syntax)) + (while (< cnt len) + (setq stx (aref syntax cnt)) + (setq ctl (mew-syntax-get-ct stx)) + (setq ct (mew-syntax-get-value ctl 'cap)) + (cond + ((string= mew-ct-msg ct) + (mew-d2e-message stx dir)) + ((mew-ct-multipartp ct) + (mew-d2e-multipart stx (mew-random-filename dir 1 nil))) + (t + (if (= cnt mew-syntax-magic) + (mew-syntax-set-cdp stx (mew-syntax-cdp-format mew-ct-txt mew-draft-coverpage))) + (mew-d2e-singlepart stx dir))) + (setq cnt (1+ cnt))))))) + +(defun mew-summary-burst (&optional arg) + "Decompose messages embedded in this message. +You are asked a folder for the decomposition. + +If executed on a part, only the message part is saved to +a folder which you specify. + +If called with '\\[universal-argument]', any files in this message +are decomposed. You are asked a new directory name for the decomposition." + (interactive "P") + (mew-summary-msg-or-part + (let ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (num (mew-syntax-number)) + folder dir ret) + (cond + (arg ;; file decomposition + (setq dir (read-file-name "New directory: " mew-home)) + (while (file-exists-p dir) + (setq dir (read-file-name (format "\"%s\" exists. New directory: " dir) mew-home))) + (mew-make-directory dir) + (message "Bursting...") + (mew-summary-burst-files fld msg dir) + (message "Bursting...done")) + (t + (setq folder (mew-input-burst-folder)) + (when (and folder (mew-local-folder-check folder 'ask)) + (message "Bursting...") + (setq ret (mew-summary-burst-body fld msg folder num)) + (when ret + (message "Bursting...done") + (when mew-ask-folder-after-burst + (if (y-or-n-p (format "Go to %s? " folder)) + (mew-summary-visit-folder folder 'goend))) + (message "Messages from %s to %s were extracted in %s" + (nth 0 ret) (nth 1 ret) folder)))))))) + +(defun mew-summary-burst-multi () + "Decompose messages embedded in the messages marked with '*'." + (interactive) + (mew-summary-multi-msgs + (let ((folder (mew-input-burst-folder)) + (targets FLD-MSG-LIST)) + (when (and folder (mew-local-folder-check folder 'ask)) + (message "Bursting...") + (dolist (target targets) + (mew-summary-burst-body (car target) (cdr target) folder)) + (message "Bursting...done") + (when mew-ask-folder-after-burst + (if (y-or-n-p (format "Go to %s? " folder)) + (mew-summary-visit-folder folder 'goend))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Old burst +;;; + +(defun mew-summary-old-burst () + "Decompose old-fashioned encapsulated messages." + (interactive) + (mew-summary-msg + (let ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (sep1 (make-string 70 ?-)) + (sep2 (make-string 30 ?-)) + (folder (mew-input-burst-folder)) + start mstr m done) + (with-temp-buffer + (mew-insert-message fld msg mew-cs-text-for-read nil) + (mew-set-buffer-multibyte t) + (if (not (re-search-forward sep1 nil t)) + (message "Cannot burst this message") + (message "Bursting...") + (forward-line 2) + (setq start (point)) + (setq mstr (mew-folder-new-message folder 'num-only)) + (setq m (string-to-number mstr)) + (while (re-search-forward sep2 nil t) + (save-excursion + (beginning-of-line) + (save-restriction + (narrow-to-region start (1- (point))) + (goto-char (point-min)) + (while (re-search-forward "^- " nil t) + (replace-match "" nil t)) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region (point-min) (point-max) + (mew-expand-new-msg folder mstr) + nil 'no-msg)))) + (forward-line 2) + (setq start (point)) + (setq m (1+ m)) + (setq mstr (number-to-string m))) + (message "Bursting...done") + (mew-touch-folder folder) + (setq done t))) + (when mew-ask-folder-after-burst + (if (and done (y-or-n-p (format "Go to %s? " folder))) + (mew-summary-visit-folder folder 'goend)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Re-editing +;;; + +(defun mew-summary-reedit (&optional keep-hdr) + "Edit this message again to retry sending. Or edit this RFC822 part +typically included in a MIME-encapsulated error message. + +1. In +draft, the message is just edited. +2. In +queue or +postq, the message is moved to +draft and is edited. +3. Otherwise, the message is copied to +draft and is edited. + +For the other folders, if mew-case-guess-when-prepared is 't', each +fields of the original header is replaced according to a guessed +sending case. If called with '\\[universal-argument]', the original +header is reserved. + +See also mew-summary-edit-again." + (interactive "P") + (mew-summary-msg-or-part + (let ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (part (mew-syntax-nums)) + draftname) + (cond + ((string= fld mew-draft-folder) + (setq draftname (mew-path-to-folder (mew-expand-msg fld msg))) + (if (get-buffer draftname) + (progn + (mew-current-set-window-config) ;; xxx necessary? + (mew-window-configure 'draft) + (switch-to-buffer draftname)) + (mew-summary-reedit-for-draft fld msg) + (run-hooks 'mew-draft-mode-reedit-draft-hook))) + ((and (or (mew-folder-queuep fld) (mew-folder-postqp fld)) (null part)) + (mew-summary-reedit-for-queue fld msg) + (run-hooks 'mew-draft-mode-reedit-queue-hook)) + (t + (if part + (let* ((cache (mew-cache-hit fld msg 'must-hit)) + (alt nil) + (syntax (mew-cache-decode-syntax cache)) + (stx (mew-syntax-get-entry syntax part)) + (ct (mew-syntax-get-value (mew-syntax-get-ct stx) 'cap))) + (if (not (string= mew-ct-msg ct)) + (message "Cannot reedit here") + (mew-summary-reedit-for-message fld msg part keep-hdr alt) + (run-hooks 'mew-draft-mode-reedit-hook))) + (mew-summary-reedit-for-message fld msg nil keep-hdr nil) + (run-hooks 'mew-draft-mode-reedit-hook))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Header +;;; + +(defun mew-summary-edit-header-common () + (mew-header-delete-lines (list mew-x-mailer:)) + (mew-header-goto-end) + ;; X-Mailer: must be the last + (if (mew-use-x-mailer (mew-tinfo-get-case)) + (mew-draft-header-insert mew-x-mailer: mew-x-mailer)) + (mew-header-clear) ;; erase the old header separator + (mew-header-set "\n")) + +(defun mew-summary-edit-header-for-draft () + (mew-elet + (mew-summary-edit-header-common))) + +(defun mew-summary-edit-header-for-queue (hdr) + (mew-elet + (mew-header-goto-end) + (delete-region (point-min) (point)) + (insert hdr) + (mew-summary-edit-header-common))) + +(defun mew-summary-edit-header-for-message (keep-hdr) + (mew-elet + (mew-header-delete-lines mew-field-delete-common) + (mew-header-delete-lines mew-field-delete-for-reediting) + (mew-header-sort mew-field-order-for-reediting) + (unless keep-hdr + (if mew-case-guess-when-prepared + (mew-draft-set-case-by-guess)) + (mew-draft-replace-fields nil)) + (mew-summary-edit-header-common))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Body +;;; + +(defun mew-summary-reedit-for-draft (fld msg) + "Edit a message in the draft folder. Use the message as draft. +Note that the message is not a valid MIME message." + ;; Message mode will be invalid so hide it. + (mew-mark-kill-line) + (set-buffer-modified-p nil) + ;; Need to delete Message window because the target message will be + ;; modified and its content will be changed. + (mew-window-configure 'summary) + (mew-current-set-window-config) + (mew-window-configure 'draft) + (mew-summary-prepare-draft + ;; mew-cs-m17n + ;; case is copied here + (mew-draft-find-and-switch (mew-expand-new-msg fld msg)) + (mew-summary-edit-header-for-draft) + (mew-draft-mode) + (mew-draft-rehighlight-body) + (save-excursion + (when (and (mew-encode-load-syntax) mew-encode-syntax) + (mew-encode-syntax-delete 'all) + (mew-draft-prepare-attachments t))) + (mew-draft-mode-name))) + +(defun mew-summary-reedit-for-queue (fld msg) + "Edit a message in a folder other than the draft folder. +The message is assumed to be a valid MIME message." + ;; Message mode will be invalid so hide it. + (mew-decode-syntax-delete) + (mew-mark-kill-line) + (set-buffer-modified-p nil) + ;; Need to delete Message window because the target message will be + ;; modified and its content wiil be changed. + (mew-current-set-window-config) + (mew-window-configure 'draft) + ;; main part + (mew-summary-prepare-draft + (mew-summary-edit-message fld msg nil nil) + (let* ((file (mew-expand-msg fld msg)) + (work (concat file mew-queue-work-suffix)) + (info (concat file mew-queue-info-suffix)) + inf hdr) + (when (file-readable-p file) + (rename-file file work 'override) + (setq inf (mew-lisp-load info)) + (cond + ((mew-folder-queuep fld) + (setq hdr (mew-smtp-get-raw-header inf)) + (mew-tinfo-set-case (mew-smtp-get-case inf))) + ((mew-folder-postqp fld) + (setq hdr (mew-nntp2-get-raw-header inf)) + (mew-tinfo-set-case (mew-nntp2-get-case inf)))) + (mew-queue-backup work mew-queue-info-suffix) + (and hdr (mew-summary-edit-header-for-queue hdr)))) + (mew-draft-mode) + (mew-draft-rehighlight-body) + (when mew-encode-syntax + (save-excursion + (mew-draft-prepare-attachments t))) + (mew-draft-mode-name))) + +(defun mew-summary-reedit-for-message (fld msg part keep-hdr alt) + "Edit a message in a folder other than the draft folder. +The message is assumed to be a valid MIME message." + (mew-current-set-window-config) + (mew-window-configure 'draft) + ;; main part + (mew-summary-prepare-draft + ;; case is copied here + (mew-summary-edit-message fld msg part alt) + ;; get info before backup the original + (mew-summary-edit-header-for-message keep-hdr) + (mew-draft-mode) + (mew-draft-rehighlight-body) + (when mew-encode-syntax + (save-excursion + (mew-draft-prepare-attachments t))) + (mew-draft-mode-name))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Edit again +;;; + +(defvar mew-summary-edit-again-regex + "----- Original message follows -----\\|----- Unsent message follows -----\\|--- Undelivered message follows ---\\|--- Below this line is a copy of the message.") + +(defun mew-summary-edit-again () + "Edit an old fashioned error message in which the original message +is encapsulated after strings defined in 'mew-summary-edit-again-regex' +An example is \"----- Original message follows -----\". See also +mew-summary-reedit." + (interactive) + (mew-summary-msg + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (nfld mew-temp-dir) + (nmsg (mew-folder-new-message nfld 'num-only)) + nfile) + (with-temp-buffer + ;; First, let's remove garbage and make a valid message + ;; into a file. + (mew-insert-message fld msg mew-cs-text-for-read nil) + (mew-set-buffer-multibyte t) + (goto-char (point-min)) + (if (not (re-search-forward mew-summary-edit-again-regex nil t)) + (message "Cannot edit this message again") + (forward-line) + ;; skip blank lines + (while (looking-at "^$") (forward-line)) + (delete-region (point-min) (point)) + (setq nfile (mew-expand-new-msg nfld nmsg)) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region (point-min) (point-max) nfile nil 'no-msg)) + ;; A new message is stored in the temporary directory + (mew-summary-reedit-for-message nfld nmsg nil nil nil) + (run-hooks 'mew-draft-mode-edit-again-hook) + (mew-delete-file nfile)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub functions +;;; + +(defun mew-ct-suffix (ct) + "Get an appropriate suffix from content type." + (let* ((base (mew-ctdb-regex (mew-ctdb-by-ct ct))) + (len (length base)) + (ret (mew-make-string len)) + (j 0) char) + (if (not (stringp base)) + nil + (dotimes (i len) + (setq char (aref base i)) + (if (or (char-equal char ?.) + (and (>= char ?a) (<= char ?z))) + (progn + (aset ret j char) + (setq j (1+ j))))) + (setq ret (substring ret 0 j)) + (if (string-match "^\\.[a-z]+$" ret) + ret + nil)))) + +(defun mew-summary-edit-message (fld msg part alt) + "Prepare a header and a body, optionally attachments." + (let* ((draft (mew-folder-new-message mew-draft-folder)) + (attachdir (mew-attachdir draft)) + (buf (generate-new-buffer mew-buffer-prefix)) + syntax hbeg hend beg end len cnt stx ctl ct charset start cs) + ;; prepare draft file + (mew-draft-find-and-switch draft) + (mew-delete-directory-recursively attachdir) + ;; De-compose the message in the burst buffer. + ;; do not decode Message/Rfc822 parts. + ;; They will be just a attachment message. + (with-current-buffer buf + ;; Let's decode the message without limitations + (mew-erase-buffer) + (mew-insert-message fld msg mew-cs-text-for-read nil) + (mew-dinfo-set (1+ (length part)) 'no-cs-conv t alt 'encap-html) + (mew-decode-for-edit) + (setq syntax (mew-syntax-get-entry mew-decode-syntax part)) + ;; syntax is now for the message + (setq hbeg (mew-syntax-get-begin syntax)) + (setq hend (mew-syntax-get-end syntax)) + ;; Outer 'message is not necessary for mew-encoding-syntax + ;; syntax is now for the multipart + (setq syntax (mew-syntax-get-part syntax)) + (if (mew-syntax-singlepart-p syntax) + (progn + (setq beg (mew-syntax-get-begin syntax)) + (setq end (mew-syntax-get-end syntax)) + (setq ctl (mew-syntax-get-ct syntax)) + (setq charset (mew-syntax-get-param ctl "charset")) + (setq syntax nil)) + ;; Let's store each part + (setq cnt mew-syntax-magic) + (unless (string= mew-ct-txt + (mew-syntax-get-value + (mew-syntax-get-ct (aref syntax cnt)) 'cap)) + (setq syntax (mew-syntax-insert-entry + syntax '(1) (mew-encode-syntax-text)))) + (setq len (length syntax)) + (mew-make-directory attachdir) + (while (< cnt len) + (setq stx (aref syntax cnt)) + (setq ctl (mew-syntax-get-ct stx)) + (setq ct (mew-syntax-get-value ctl 'cap)) + (cond + ((string= mew-ct-msg ct) + (mew-d2e-message stx attachdir)) + ((mew-ct-multipartp ct) + (mew-d2e-multipart stx (mew-random-filename attachdir 1 nil))) + (t + (if (/= cnt mew-syntax-magic) + (mew-d2e-singlepart stx attachdir) + (setq beg (mew-syntax-get-begin stx)) + (setq end (mew-syntax-get-end stx)) + (setq charset (mew-syntax-get-param ctl "charset")) + (mew-delete "charset" ctl) + (mew-syntax-set-file stx mew-draft-coverpage) + (mew-syntax-set-decrypters stx nil)))) + (setq cnt (1+ cnt))) + (mew-syntax-set-file + syntax + (file-name-as-directory (file-name-nondirectory attachdir))) + (mew-syntax-set-decrypters syntax nil) + (mew-syntax-set-privacy syntax nil) + (mew-syntax-set-ct syntax mew-type-mlm) + (mew-syntax-set-cte syntax nil) + (mew-syntax-set-cd syntax nil) + (mew-syntax-set-cid syntax nil) + (mew-syntax-set-cdp syntax nil))) + ;; draft buffer + ;; header + (mew-insert-buffer-substring buf hbeg hend) + (insert "\n") + ;; coverpage + (setq start (point)) + ;; The first part may not be Text/Plain. + (if (and beg end) (mew-insert-buffer-substring buf beg end)) + (if (or (null charset) (string= charset mew-us-ascii)) + (setq cs mew-cs-autoconv) ;; for RFC822 + (setq cs (mew-charset-to-cs charset))) + (unless (mew-coding-system-p cs) + (error "Unknown coding system %s" (symbol-name cs))) + (mew-cs-decode-region start (point-max) cs) + (setq mew-encode-syntax syntax) + (mew-remove-buffer buf))) + +(defun mew-d2e-singlepart (syntax dir) + "De-compose singlepart" + (let* ((ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (cdpl (mew-syntax-get-cdp syntax)) + (file (mew-syntax-get-filename cdpl ctl)) + (beg (mew-syntax-get-begin syntax)) + (end (mew-syntax-get-end syntax)) + (linebasep (or (mew-ct-textp ct) (mew-ct-linebasep ct)))) + (if (stringp file) + (setq file (expand-file-name file dir)) + (setq file (mew-random-filename dir 2 nil (mew-ct-suffix ct))) + (mew-syntax-set-cdp syntax nil)) + (mew-frwlet mew-cs-dummy (if linebasep mew-cs-text-for-write mew-cs-binary) + (write-region beg end file nil 'no-msg)) + (if (and (mew-ct-textp ct) (mew-syntax-get-param ctl "charset")) + (mew-delete "charset" ctl)) ;; side effect + (mew-syntax-set-file syntax (file-name-nondirectory file)) + (mew-syntax-set-decrypters syntax nil) + (mew-syntax-set-privacy syntax nil) + (mew-syntax-set-cid syntax nil))) + +(defun mew-d2e-multipart (syntax dir) + "De-compose multipart" + (let ((len (length syntax)) + (cnt mew-syntax-magic) + ct part) + (mew-make-directory dir) + (while (< cnt len) + (setq part (aref syntax cnt)) + (setq ct (mew-syntax-get-value (mew-syntax-get-ct part) 'cap)) + (cond + ((string= mew-ct-msg ct) + (mew-d2e-message part dir)) + ((mew-ct-multipartp ct) + (mew-d2e-multipart part (mew-random-filename dir 1 nil))) + (t + (mew-d2e-singlepart part dir))) + (setq cnt (1+ cnt))) + (mew-syntax-set-file + syntax + (file-name-as-directory (file-name-nondirectory dir))) + (mew-syntax-set-decrypters syntax nil) + (mew-syntax-set-privacy syntax nil) + (mew-syntax-set-ct syntax mew-type-mlm) + (mew-syntax-set-cte syntax nil) + (mew-syntax-set-cd syntax nil) + (mew-syntax-set-cid syntax nil) + (mew-syntax-set-cdp syntax nil))) + +(defun mew-d2e-message (syntax dir) + "De-compose message like singlepart" + (let ((file (mew-random-filename dir 2 t)) + (beg (mew-syntax-get-begin syntax)) + (end (mew-syntax-get-end (mew-syntax-get-part syntax)))) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region beg end file nil 'no-msg)) + (mew-syntax-set-key syntax 'single) + (mew-syntax-set-file syntax (file-name-nondirectory file)) + (mew-syntax-set-decrypters syntax nil) + (mew-syntax-set-privacy syntax nil) + (mew-syntax-set-cid syntax nil) + (mew-syntax-set-cdp syntax nil) + (mew-syntax-set-part syntax nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Edit mode +;;; + +(defun mew-summary-edit () + (interactive) + (mew-summary-not-in-queue + (mew-summary-not-in-draft + (mew-summary-msg-or-part + (let ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (part (mew-syntax-nums))) + (if part + (let* ((cache (mew-cache-hit fld msg 'must-hit)) + (alt nil) + (syntax (mew-cache-decode-syntax cache)) + (stx (mew-syntax-get-entry syntax part)) + (ct (mew-syntax-get-value (mew-syntax-get-ct stx) 'cap))) + (if (not (string= mew-ct-msg ct)) + (message "Cannot edit here") + (mew-summary-edit-for-message fld msg part alt) + (run-hooks 'mew-draft-mode-edit-hook))) + (mew-summary-edit-for-message fld msg nil nil) + (setq mode-name "Edit") + (force-mode-line-update) + (run-hooks 'mew-draft-mode-edit-hook))))))) + +(defun mew-summary-edit-for-message (fld msg part alt) + (mew-current-set-window-config) + (mew-window-configure 'draft) + ;; main part + (mew-summary-prepare-draft + ;; case is copied here + (mew-summary-edit-message fld msg part alt) + ;; get info before backup the original + (mew-summary-edit-header-for-edit) + (let ((fields (mew-summary-edit-obtain-fields-key))) + (mew-tinfo-set-preserved-header (mew-summary-edit-obtain-fields fld msg fields))) + (mew-tinfo-set-src-folder fld) + (mew-draft-mode) + (mew-draft-rehighlight-body) + (when mew-encode-syntax + (save-excursion + (mew-draft-prepare-attachments t))) + (mew-draft-mode-name))) + +(defun mew-summary-edit-header-for-edit () + (mew-elet + (mew-header-delete-lines '("From " ">From")) + (mew-header-delete-lines mew-field-delete-for-editing) + (mew-header-sort mew-field-order-for-editing) + (mew-header-clear) ;; erase the old header separator + (mew-header-set "\n"))) + +(defun mew-summary-edit-obtain-fields-key () + (let ((case-fold-search t) fields) + (save-excursion + (mew-header-goto-end) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + (while (not (eobp)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq fields (cons (mew-match-string 1) fields)) + (forward-line) + (mew-header-goto-next)))) + fields))) + +(defun mew-summary-edit-obtain-fields (fld msg fields) + (with-temp-buffer + (mew-insert-message + fld msg mew-cs-text-for-read mew-header-reasonable-size) + (mew-header-goto-end) + (delete-region (point) (point-max)) + (mew-header-delete-lines fields) + (mew-header-delete-lines (list mew-mv: "Content-" "X-Mew-")) + (mew-buffer-substring (point-min) (point-max)))) + +(defun mew-edit-make-delete-window (buf) + (if (and (mew-tinfo-get-other-frame) (> (length (frame-list)) 1)) + (delete-frame) + (mew-current-get-window-config) + (delete-windows-on buf))) ;; just in case + +(defun mew-edit-make-message (buf) + (let (multip) + (save-excursion + (save-window-excursion + (set-buffer buf) + (mew-set-buffer-multibyte t) + (if (buffer-modified-p) (save-buffer)) ;; to make backup + (widen) + (if (mew-attach-p) + (progn + (setq multip t) + (mew-attach-clear)) + (unless mew-encode-syntax + (setq mew-encode-syntax + (mew-encode-syntax-single "text.txt" (list mew-ct-txt))))) + (goto-char (mew-header-end)) + (forward-line) + (if multip + (mew-encode-make-multi) + (mew-encode-make-single)) + (mew-encode-make-header) + (mew-encode-save-draft) + (mew-overlay-delete-buffer) + (goto-char (point-min)) + (insert (mew-tinfo-get-preserved-header)) + (save-buffer) + (buffer-file-name))))) + +(defun mew-edit-make-refile (case:srcfld srcfile) + (let* ((case:dstfld (car (mew-input-folders case:srcfld))) + (dstfld (mew-case:folder-folder case:dstfld)) + (case (mew-case:folder-case case:dstfld)) + dstfile) + (cond + ((mew-folder-imapp dstfld) + (mew-imap2-copy-message case 'move (list srcfile) dstfld)) + (t + (setq dstfile (mew-folder-new-message dstfld)) + (rename-file srcfile dstfile) + (mew-set-file-modes dstfile) + (mew-touch-folder dstfld) + (message "Saved in %s" dstfld))))) + +(defun mew-edit-make () + (interactive) + (let ((buf (current-buffer)) + (case:srcfld (mew-tinfo-get-src-folder)) + srcfile) + (mew-edit-make-delete-window buf) + (setq srcfile (mew-edit-make-message buf)) + (mew-remove-buffer buf) + (mew-edit-make-refile case:srcfld srcfile))) + +(provide 'mew-edit) + +;;; Copyright Notice: + +;; Copyright (C) 1999-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-edit.el ends here diff --git a/elpa/mew-20150813.2354/mew-encode.el b/elpa/mew-20150813.2354/mew-encode.el new file mode 100644 index 00000000..6dd3ad19 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-encode.el @@ -0,0 +1,1385 @@ +;;; mew-encode.el --- MIME syntax encoder for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +(defvar mew-prog-mime-encode-switch + `((,mew-b64 "-b") + (,mew-qp "-q") + (,mew-xg "-g"))) + +(defvar mew-prog-mime-encode-text-switch + `((,mew-b64 "-b" "-t") + (,mew-qp "-q") + (,mew-xg "-g""-t"))) + +(defun mew-prog-mime-encode-get-opt (cte switch) + (cdr (mew-assoc-case-equal cte switch 0))) + +(defvar mew-encode-multipart-encrypted-switch + `((,mew-ct-pge mew-pgp-encrypt))) + +(defvar mew-encode-multipart-signed-switch + `((,mew-ct-pgs mew-pgp-sign mew-pgp-canonicalize) + (,mew-ct-sms mew-smime-detach-sign))) + +;; + +(defun mew-encode-get-security-func (proto switch) + (nth 1 (mew-assoc-case-equal proto switch 0))) + +(defun mew-encode-get-canonicalize-func (proto switch) + (nth 2 (mew-assoc-case-equal proto switch 0))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; MIME encoder +;;; + +(defun mew-encode-error (error-msg) + (mew-tinfo-set-encode-err error-msg) + (error "")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; RFC 2822 comments +;;; + +;; RFC 2822 defines the limitations of the number of fields. +;; +;; * Overriding +;; Date: (exactly once) +;; Message-Id: +;; +;; * Put multiple fields to a single field +;; From: (exactly once) +;; Reply-To: +;; To: +;; Cc: +;; +;; * Error and undo +;; Sender: (if exist, exactly one address) +;; +;; In-Reply-To: +;; References: +;; Subject: +;; + +(defconst mew-multiple-field-error-list + (list mew-subj: mew-in-reply-to: mew-references:)) + +(defconst mew-multiple-field-combine-list + (list mew-from: mew-reply-to: mew-to: mew-cc:)) + +(defun mew-header-count-field (field) + (let ((case-fold-search t) + (regex (format "^%s" field)) + (i 0)) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (setq i (1+ i)) + (forward-line)) + i)) + +(defun mew-header-combine-field (field) + (let ((case-fold-search t) + (regex (format "^%s" field)) + beg med here value) + (goto-char (point-min)) + (when (re-search-forward regex nil t) + (forward-line) + (mew-header-goto-next) + (setq here (1- (point))) + (while (re-search-forward regex nil t) + (setq beg (match-beginning 0)) + (setq med (match-end 0)) + (forward-line) + (mew-header-goto-next) + (setq value (mew-buffer-substring med (1- (point)))) + (delete-region beg (point)) + (save-excursion + (goto-char here) + (insert ",\n\t" value) + (setq here (point))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Header sanity check +;;; + +(defun mew-encode-remove-invalid-fields () + (when (mew-header-end) + (save-excursion + (save-restriction + (narrow-to-region (point-min) (mew-header-end)) + (dolist (field mew-multiple-field-error-list) + (if (> (mew-header-count-field field) 1) + (mew-encode-error (format "Multiple %s!" field)))) + (mapcar 'mew-header-combine-field mew-multiple-field-combine-list))))) + +(defun mew-encode-ask-subject () + (when (and mew-ask-subject (not (mew-header-existp mew-subj:))) + ;; Subject: does not exist + (let ((subj (read-string (concat mew-subj: " ")))) + (mew-header-replace-value mew-subj: subj)))) + +(defun mew-encode-fcc-folder-check (fld) + (let ((folder (mew-canonicalize-folder fld))) + (when (and mew-ask-fcc + (mew-folder-localp folder) + (not (file-directory-p (mew-expand-folder folder)))) + (if (y-or-n-p (format "%s does not exist. Create it? " folder)) + (mew-local-folder-check folder) + (mew-encode-error "Edit Fcc:"))) + folder)) + +(defun mew-encode-ask-fcc (resentp) + (let* ((target (if resentp mew-resent-fcc: mew-fcc:)) + (folders (mew-header-get-value target))) + (when folders + (mapcar + 'mew-encode-fcc-folder-check + (mew-addrstr-parse-value-list2 folders))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; To:, Cc: +;;; + +(defvar mew-draft-append-domain-p t) + +(defun mew-draft-append-domain (addr) + (if (string-match "@" addr) + addr + (if mew-draft-append-domain-p + (concat addr "@" (mew-mail-domain (mew-tinfo-get-case))) + (throw 'jump addr)))) + +(defun mew-encode-canonicalize-address (resentp) + (catch 'jump + (let ((case-fold-search t) + (regex (mew-make-field-regex + (if resentp mew-resent-dest:-list mew-destination:-list))) + key start vals val addrs addr ret insl ins prefix suffix) + (save-excursion + (save-restriction + (narrow-to-region (point-min) (mew-header-end)) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (setq key (match-string 1)) + (setq start (match-end 0)) + (forward-line) + (while (looking-at mew-lwsp) + (delete-char -1) + (forward-line)) + (setq val (mew-buffer-substring start (1- (point)))) + (delete-region start (1- (point))) + (backward-char 1) + ;; single quote is allowed for local-part + (setq vals (mapcar 'mew-chop (mew-split-quoted val ?, ?: ?\; 'no-single))) + (dolist (val vals) + (setq ins nil addrs nil) + (cond + ;; phrase:addr1,addr2; + ((string-match "[^:]+:[^;]+;" val) + (let ((mew-alias-expand-prefix nil)) + (setq addrs (mew-alias-expand val mew-addrbook-alist 0)) + (setq addrs (mapcar 'mew-draft-append-domain addrs)) + (setq ins (list (concat mew-alias-expand-prefix ":;"))))) + ;; Name + ((and (setq addr (mew-addrstr-parse-address val)) + (string-match (concat "\\(.*<\\)" (regexp-quote addr) "\\(>.*\\)") + val)) + (setq prefix (match-string 1 val)) + (setq suffix (match-string 2 val)) + (setq addr (mew-draft-append-domain addr)) + (setq addrs (list addr)) + (setq ins (list (concat prefix addr suffix)))) + ;; addr + (t + (let ((mew-alias-expand-prefix nil)) + (setq addrs (mew-alias-expand val mew-addrbook-alist 0)) + (setq addrs (mapcar 'mew-draft-append-domain addrs)) + (if mew-alias-expand-prefix + (setq ins (list (concat mew-alias-expand-prefix ":;"))) + (setq ins (copy-sequence addrs)))))) + (setq insl (nconc insl ins)) + (unless (string-match "bcc" key) ;; Removing Bcc: + (setq ret (nconc ret addrs)))) ;; end of dolist + (insert " " (mapconcat 'identity insl ", ")) + (setq insl nil) + (forward-line)))) + ret))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Dcc:, Bcc: +;;; + +(defun mew-encode-delete-dcc (resentp) + (let* ((target (list (if resentp mew-resent-dcc: mew-dcc:))) + (dcc (mew-header-parse-address-list target))) + ;; Dcc: is already contained in recipients. + ;; So, just delete it. + ;; Delete {Resent-,}Dcc: anyway. + (mew-header-delete-lines (list mew-dcc: mew-resent-dcc:)) + dcc)) + +(defun mew-encode-delete-bcc (resentp) + (let* ((target (list (if resentp mew-resent-bcc: mew-bcc:))) + (bcc (mew-header-parse-address-list target))) + (mew-header-delete-lines (list mew-bcc: mew-resent-bcc:)) ;; anyway + bcc)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message-Id:, Date: +;;; + +(defun mew-encode-id-date (pnm msgid &optional resentp) + (let ((time (current-time))) + (cond + (resentp + (mew-header-delete-lines (list mew-resent-date: mew-resent-message-id:)) + (save-excursion + (goto-char (point-min)) + (mew-header-insert mew-resent-date: (mew-time-ctz-to-rfc time)) + (mew-header-insert mew-resent-message-id: msgid))) + (t + (mew-header-delete-lines (list mew-date: mew-message-id:)) + (save-excursion + (goto-char (point-min)) + (mew-header-insert mew-date: (mew-time-ctz-to-rfc time)) + (mew-header-insert mew-message-id: msgid)))) + (list msgid (mew-time-ctz-to-logtime time)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; From:, Sender: +;;; + +(defun mew-encode-check-sender (resentp) + (if (< 1 (length (mew-addrstr-parse-address-list + (mew-header-get-value + (if resentp mew-resent-sender: mew-sender:))))) + (mew-encode-error "Sender: must contain one address!"))) + +(defun mew-encode-from (case resentp) + (unless (mew-header-existp mew-from:) + (let ((from (mew-from case))) + (save-excursion + (goto-char (point-min)) + (if resentp + (mew-header-insert mew-resent-from: from) + (mew-header-insert mew-from: from)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Learning aliases +;;; + +;; xxx Bcc: and/or Dcc:? +(defun mew-encode-learn-aliases (resentp) + (if (and mew-use-auto-alias mew-addrbook-append-domain-p) + ;; If mew-addrbook-append-domain-p is nil, automatic + ;; short names would be conflicted to local users. + (mapcar 'mew-addrbook-alias-add + (mew-header-parse-address-list + (if resentp + (list mew-resent-to: mew-resent-cc:) + (list mew-to: mew-cc:)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Misc +;;; + +(defun mew-encode-set-privacy (pnm privacy case) + (unless (or (mew-syntax-get-privacy mew-encode-syntax) ;; specified + ;; encryption previously failed, so bypass. + (and (null privacy) (mew-tinfo-get-privacy-err))) + (let (type) + (cond + (privacy + (setq type privacy)) + ((mew-tinfo-get-privacy-type) + (setq type (mew-tinfo-get-privacy-type))) + ((and (mew-tinfo-get-encrypted-p) (mew-protect-privacy-encrypted case)) + (setq type (mew-protect-privacy-encrypted-type case))) + ((mew-protect-privacy-always case) + (setq type (mew-protect-privacy-always-type case)))) + (mew-syntax-set-privacy + mew-encode-syntax + (mew-pcdb-ct (mew-pcdb-by-service type))) + ;; recipients are ignored when signing + (mew-syntax-set-decrypters + mew-encode-syntax (mew-smtp-get-recipients pnm))))) + +(defun mew-encode-make-header (&optional addsep resentp) + (unless (mew-header-existp mew-mv:) + (goto-char (mew-header-end)) + (mew-header-insert mew-mv: mew-mv:-num)) + (mew-header-encode-region (point-min) (mew-header-end) resentp) + (cond + (addsep ;; reedit + ;; To: + ;; Content-* + ;; ---- + (mew-header-clear) ;; mew-in-header-p() returns nil + ;; To: + ;; Content-* + (insert "\n")) + (t + ;; To: + ;; ---- + ;; Content-* + (mew-header-clear) ;; mew-in-header-p returns nil + ;; To: + ;; Content-* + )) + (mew-header-goto-end) + (mew-highlight-header-region (point-min) (point))) + +(defun mew-encode-save-draft () + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region (point-min) (point-max) (buffer-file-name) nil 'no-msg) + (clear-visited-file-modtime) + (mew-delete-file buffer-auto-save-file-name) + (set-buffer-modified-p nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Encoding a message +;;; + +(defun mew-smtp-encode (pnm case resentp fcc &optional privacy signer headerp) + (let ((ret t)) + (if (mew-debug 'encode) + (let ((debug-on-error t)) + (mew-smtp-encode-message pnm case resentp fcc privacy signer headerp)) + (condition-case nil + (mew-smtp-encode-message pnm case resentp fcc privacy signer headerp) + (error + (mew-encode-undo) + (message "%s" (mew-tinfo-get-encode-err)) + (setq ret nil)) + (quit + (mew-encode-undo) + (message "quit") + (setq ret nil)))) + ret)) + +(defun mew-smtp-encode-message (pnm case resentp fcc &optional privacy signer headerp) + (mew-set-buffer-multibyte t) + (if (buffer-modified-p) (save-buffer)) ;; to make backup + (widen) + (let (multip recipients msgid logtime) + (mew-smtp-set-raw-header + pnm (mew-buffer-substring (point-min) (mew-header-end))) + (unless headerp + ;; Let's backup + (if (mew-attach-p) + (progn + (setq multip t) + (mew-attach-clear)) + (unless mew-encode-syntax + (setq mew-encode-syntax + (mew-encode-syntax-single "text.txt" (list mew-ct-txt))))) + (mew-encode-make-backup)) + ;; Errors can be caused from here. + (goto-char (point-min)) + (mew-encode-remove-invalid-fields) + ;; Destination check + (setq recipients (mew-encode-canonicalize-address resentp)) + ;; Bcc: is not included. + (mew-smtp-set-recipients pnm recipients) + (mew-smtp-set-orig-recipients pnm recipients) + (cond + ((null recipients) + (mew-encode-error "No recipient!")) + ((stringp recipients) + (mew-encode-error (format "'%s' is not in the right form!" recipients)))) + ;; Header modifications which are not remained. + (mew-header-delete-lines (list mew-fcc: mew-resent-fcc:)) ;; anyway + (mew-encode-delete-dcc resentp) + (mew-smtp-set-bcc pnm (mew-encode-delete-bcc resentp)) + (mew-smtp-set-fcc pnm fcc) + ;; + (mew-encode-check-sender resentp) + (mew-encode-from case resentp) + ;; + (mew-set '(msgid logtime) (mew-encode-id-date pnm (mew-smtp-message-id case) resentp)) + (mew-smtp-set-msgid pnm msgid) + (mew-smtp-set-logtime pnm logtime) + ;; + (goto-char (mew-header-end)) + (forward-line) ;; necessary for PGP + ;; + (message "Making a message...") + ;; save syntax before setting privacy + (unless headerp + (mew-encode-set-privacy pnm privacy case) + (let (mew-inherit-encode-pgp-signer + mew-inherit-encode-smime-signer) + (setq mew-inherit-encode-pgp-signer + (or signer + (mew-pgp-signer (mew-tinfo-get-case)) + (mew-get-my-address))) + (setq mew-inherit-encode-smime-signer + (or signer + (mew-smime-signer (mew-tinfo-get-case)) + (mew-get-my-address))) + (goto-char (mew-header-end)) ;; due to invalid null lines in the header + (forward-line) + (if multip + (mew-encode-make-multi) + (mew-encode-make-single)))) + (mew-encode-make-header headerp resentp) + ;; Learn aliases after no error occurred + (mew-encode-learn-aliases resentp) + (mew-encode-save-draft) + (mew-overlay-delete-buffer) + (message "Making a message...done"))) + +(defun mew-nntp2-encode (pnm case fcc &optional privacy signer headerp) + (let ((ret t)) + (if (mew-debug 'encode) + (let ((debug-on-error t)) + (mew-nntp2-encode-message pnm case fcc privacy signer headerp)) + (condition-case nil + (mew-nntp2-encode-message pnm case fcc privacy signer headerp) + (error + (mew-encode-undo) + (message "%s" (mew-tinfo-get-encode-err)) + (setq ret nil)) + (quit + (mew-encode-undo) + (message "quit") + (setq ret nil)))) + ret)) + +(defun mew-nntp2-encode-message (pnm case fcc &optional privacy signer headerp) + (mew-set-buffer-multibyte t) + (if (buffer-modified-p) (save-buffer)) ;; to make backup + (widen) + (let (multip newsgroups msgid logtime) + (mew-nntp2-set-raw-header + pnm (mew-buffer-substring (point-min) (mew-header-end))) + ;; Let's backup + (unless headerp + (if (mew-attach-p) + (progn + (setq multip t) + (mew-attach-clear)) + (setq mew-encode-syntax + (mew-encode-syntax-single "text.txt" (list mew-ct-txt)))) + (mew-encode-make-backup)) + ;; Errors can be caused from here. + (goto-char (point-min)) + (mew-encode-remove-invalid-fields) + ;; Newsgroups check + (setq newsgroups (mew-header-get-value mew-newsgroups:)) + (mew-nntp2-set-newsgroups pnm newsgroups) + (unless newsgroups (mew-encode-error "No newsgroups!")) + ;; Header modifications which are not remained. + (mew-header-delete-lines (list mew-fcc: mew-resent-fcc:)) ;; anyway + (mew-nntp2-set-fcc pnm fcc) + ;; + (mew-encode-from case nil) + ;; + (mew-set '(msgid logtime) (mew-encode-id-date pnm (mew-nntp-message-id case))) + (mew-nntp2-set-msgid pnm msgid) + (mew-nntp2-set-logtime pnm logtime) + ;; + (goto-char (mew-header-end)) + (forward-line) ;; necessary for PGP + ;; + (message "Making a message...") + ;; save syntax before setting privacy + (unless headerp + (mew-encode-set-privacy pnm privacy case) + (let (mew-inherit-encode-pgp-signer + mew-inherit-encode-smime-signer) + (setq mew-inherit-encode-pgp-signer + (or signer + (mew-pgp-signer (mew-tinfo-get-case)) + (mew-get-my-address))) + (setq mew-inherit-encode-smime-signer + (or signer + (mew-smime-signer (mew-tinfo-get-case)) + (mew-get-my-address))) + (goto-char (mew-header-end)) ;; due to invalid null lines in the header + (forward-line) + (if multip + (mew-encode-make-multi) + (mew-encode-make-single)))) + (mew-encode-make-header nil) + (mew-encode-save-draft) + (mew-overlay-delete-buffer) + (message "Making a message...done"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Encoding singlepart +;;; + +(defun mew-encode-make-single () + ;; Just after the header + ;; Using Multipart/Signed if the body is a single part. + (if (equal (mew-syntax-get-privacy mew-encode-syntax) + `((,mew-ct-smm ,mew-ct-smm-sig))) + (mew-syntax-set-privacy mew-encode-syntax `((,mew-ct-mls ,mew-ct-sms)))) + (mew-encode-singlepart mew-encode-syntax nil nil t 'cover)) + +(defun mew-encode-charset-8bitp (charset) + (let ((case-fold-search t)) + (if (or (mew-case-equal mew-us-ascii charset) + (string-match "^iso-2022" charset)) + nil + t))) + +(defun mew-encode-file-8bitp (file) + (if (and (mew-which-exec mew-prog-8bit) (file-readable-p file)) + (eq (call-process mew-prog-8bit file nil nil "-8") 1))) + +(defun mew-encode-limit-7bitp (privacy) + ;; Only parts to be signed FIRST are limited to 7bit. + (and privacy (mew-case-equal mew-ct-mls (car (car privacy))))) + +(defvar mew-encode-max-line-length 990) +;; RFC 2822 defines 1000 but Sendmail uses 990 + +(defvar mew-ask-encoding t) +(defvar mew-default-encoding mew-b64) + +(defvar mew-draft-keep-text-charset nil) + +(defun mew-encode-mime-body (ctl cte file no-encoding) + ;; If file is 't', target is buffered. + ;; text should be buffered + ;; - specified charset is a rare case + ;; - copy overhead may be small + (let* ((ct (mew-syntax-get-value ctl 'cap)) + (textp (mew-ct-textp ct)) + (charset (if textp (mew-syntax-get-param ctl "charset"))) + (icharset (if textp (mew-syntax-get-param ctl "icharset"))) + (linebasep (or textp (mew-ct-linebasep ct))) + (switch (if linebasep + mew-prog-mime-encode-text-switch + mew-prog-mime-encode-switch)) + (beg (point)) + buffer cs opt last flowed delsp flowed-delsp) + (if (and (stringp file) + (setq buffer (get-file-buffer file)) + (buffer-modified-p buffer)) + (with-current-buffer buffer + (save-buffer))) + (when textp + (when (and (stringp file) (file-readable-p file)) + (when icharset + (setq cs (mew-charset-to-cs icharset)) + (unless (mew-coding-system-p cs) + (mew-encode-error + (format "Unknown coding system %s in the body" + (symbol-name cs))))) + ;; If a user want to keep text charset, + (when (and mew-draft-keep-text-charset (null charset)) + (let ((cs (mew-cs-strip-lineinfo + (mew-file-guess-coding-system file)))) + (if cs (setq charset (mew-cs-to-charset cs))))) + (mew-frwlet (or cs mew-cs-autoconv) mew-cs-dummy + (mew-insert-file-contents file))) + ;; A user may specify charset to convey JIS X 0201 Katakana. + ;; So, we need to avoid the sanity check. + (unless charset + (if mew-use-charset-sanity-check + (mew-charset-sanity-check beg (point-max))) + (setq charset (mew-charset-guess-region beg (point-max)))) + (setq cs (mew-charset-to-cs charset)) + (when (string= mew-ct-txt ct) + (cond + ((mew-tinfo-get-flowed) + (setq flowed t) + (if (string= (mew-tinfo-get-flowed) "yes") + (setq delsp t))) + ((mew-tinfo-get-use-flowed) + (setq flowed-delsp (mew-encode-flowed beg (point-max) charset)) + (mew-set '(flowed delsp) flowed-delsp)))) + (unless (mew-coding-system-p cs) + (mew-encode-error + (format "Unknown coding system %s in the body" (symbol-name cs)))) + (mew-cs-encode-region beg (point-max) cs)) + ;; decide cte + (cond + (textp + (cond + ((and cte (or (mew-case-equal cte mew-b64) (mew-case-equal cte mew-qp))) + ;; user specified and in 7bit domain, so do nothing. + ) + (t + (if (or (null cte) (mew-case-equal cte mew-bin)) + ;; retain the user-specified cte + (setq cte (mew-charset-to-cte charset))) + (if (or (null cte) (mew-case-equal cte mew-bin)) + ;; unknown charset + (setq cte mew-default-encoding)) + (cond + (no-encoding + (if (mew-encode-charset-8bitp charset) + (setq cte mew-8bit) + (setq cte mew-7bit))) + (mew-inherit-7bit + (if (mew-case-equal cte mew-8bit) + (setq cte mew-default-encoding))) + (mew-use-8bit + (if (mew-encode-charset-8bitp charset) + (setq cte mew-8bit)))) + (when (and (not no-encoding) + (or (mew-case-equal cte mew-7bit) + (mew-case-equal cte mew-8bit))) + (save-excursion + (goto-char beg) + (mew-set-buffer-multibyte nil) + (catch 'long-line + (while t + (setq last (point)) + (if (/= (forward-line) 0) (end-of-line)) + (when (>= (- (point) last) mew-encode-max-line-length) ;; including LF + (if (not mew-ask-encoding) + (setq cte mew-default-encoding) + (setq cte (mew-input-encoding))) + (throw 'long-line nil)) + (if (eobp) (throw 'long-line nil)))) + (mew-set-buffer-multibyte t)))))) + ((string= ct mew-ct-msg) + (if (mew-encode-file-8bitp file) + (setq cte mew-8bit) + (setq cte mew-7bit))) + (t + (if (and no-encoding cte (mew-case-equal cte mew-b64)) + (setq cte mew-bin)) + ;; There are 7bit ascii bodies such as + ;; application/pgp-encrypted and message/external-body. + ;; If 7bit or 8bit, it should be linebase. + (if (null cte) (setq cte mew-7bit)))) + (cond + ((mew-case-equal cte mew-bin) + (mew-frwlet mew-cs-binary mew-cs-dummy + (mew-insert-file-contents file))) + ((or (mew-case-equal cte mew-7bit) (mew-case-equal cte mew-8bit)) + ;; Certainly linebase here. + (unless textp + (mew-frwlet mew-cs-text-for-read mew-cs-dummy + (mew-insert-file-contents file))) + (when (and (string= ct mew-ct-msg) + (or mew-inherit-7bit (not mew-use-8bit)) + (mew-case-equal cte mew-8bit)) + (save-restriction + (setq cte mew-7bit) + (narrow-to-region beg (point-max)) + (mew-convert-message)))) + ((and (mew-case-equal cte mew-b64) (fboundp 'base64-encode-region)) + (unless textp + (mew-frwlet (if linebasep mew-cs-text-for-read mew-cs-binary) mew-cs-dummy + (mew-insert-file-contents file))) + (when linebasep + (goto-char beg) + (mew-lf-to-crlf)) + (base64-encode-region beg (point-max)) + (goto-char (point-max)) + (insert "\n")) + ((mew-which-exec mew-prog-mime-encode) + (setq opt (mew-prog-mime-encode-get-opt cte switch)) + (if (null opt) + (mew-encode-error (concat "Unknown CTE: " cte)) + (when textp + (setq file (mew-make-temp-name)) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + ;; NEVER use call-process-region for privacy reasons + (write-region beg (point-max) file nil 'no-msg)) + (delete-region beg (point-max))) + (mew-piolet mew-cs-text-for-read mew-cs-dummy + (apply 'call-process mew-prog-mime-encode file t nil opt)) + (if textp (mew-delete-file file)))) + (t + (mew-encode-error (concat mew-prog-mime-encode " does not exist")))) + (list cte charset flowed delsp))) + +(defun mew-encode-no-mime-encoding (privacy) + (let ((first (car privacy))) + (and (listp first) + (or (string= (car first) mew-ct-mle) + (string= (car first) mew-ct-smm))))) + +(defun mew-broken-name (cdpl) + (let ((mew-encode-word-max-length 1000) ;; xxx + (file (nth 1 (assoc "filename" cdpl))) + name) + (when (and file (string-match mew-regex-nonascii file)) + (setq name (car (mew-header-encode-string file))) + ;; name must not be double-quoted here. + ;; mew-heaer-insert will do this later + (list "name" name)))) + +(defun mew-encode-flowed (beg end charset) + "Encoding lines with RFC 3676" + (let (flowed delsp column) + (save-excursion + (goto-char beg) + (save-restriction + (narrow-to-region beg end) + (when (mew-encode-flowed-check) + (setq flowed t) + (setq delsp (mew-charset-to-delsp charset)) + (setq column mew-flowed-fold-length) + (if delsp (setq column (1- column))) + (while (not (eobp)) + (mew-encode-flowed-line column delsp) + (forward-line))))) + (list flowed delsp))) + +(defun mew-encode-flowed-remove-trailing-sp () + (while (and (not (bobp)) (= (char-before) mew-sp)) + (delete-char -1))) + +(defun mew-encode-flowed-line (column delsp) + (let (prefix beg) + (looking-at "^>*") + (setq prefix (mew-match-string 0)) + (goto-char (match-end 0)) + (if (looking-at " ") + (if (string= prefix "") + (insert mew-flowed-stuffed) + (progn + (setq prefix (format "%s%c" prefix mew-flowed-stuffed)) + (forward-char))) + (when (looking-at "From ") + (insert mew-flowed-stuffed) + (setq prefix (format "%s%c" prefix mew-flowed-stuffed)))) + (setq beg (point)) + (save-excursion + (end-of-line) + (unless (and (= (- (point) beg) 3) + (string= (mew-buffer-substring beg (point)) "-- ")) + (mew-encode-flowed-remove-trailing-sp))) + (move-to-column column) + (catch 'loop + (while (not (eolp)) + (cond + (delsp + (while (> (current-column) column) + (backward-char 1)) + (insert " \n")) + (t + (if (search-backward " " beg t) + (forward-char) + (unless (search-forward " " (save-excursion (end-of-line) (point)) t) + (throw 'loop (end-of-line)))) + (insert "\n"))) + (insert prefix) + (setq beg (point)) + (move-to-column column))))) + +(defun mew-encode-flowed-check () + (catch 'loop + (save-excursion + (save-restriction + (narrow-to-region (point-min) (min (point-max) mew-file-max-size)) + (goto-char (point-min)) + (while (not (eobp)) + (end-of-line) + (if (> (current-column) mew-flowed-fold-threshold) + (throw 'loop t)) + (forward-line)))))) + +(defun mew-encode-singlepart (syntax &optional path depth buffered coverp) + ;; path is nil if called make-single or security multipart + ;; buffered is t if called make-single + (run-hook-with-args 'mew-encode-singlepart-hook + syntax path depth buffered) + (let* ((file (expand-file-name (mew-syntax-get-file syntax) path)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (cte (mew-syntax-get-cte syntax)) + (cd (mew-syntax-get-cd syntax)) + (cdpl (mew-syntax-get-cdp syntax)) + (privacy (mew-syntax-get-privacy syntax)) + (no-encoding (mew-encode-no-mime-encoding privacy)) + (mew-inherit-7bit (mew-encode-limit-7bitp privacy)) + (beg (point)) + mret charset bodybeg cst ask-cst broken-name flowed delsp) + (setq mret (mew-encode-mime-body ctl cte (or buffered file) no-encoding)) + (goto-char beg) + (mew-set '(cte charset flowed delsp) mret) + (setq ctl (mew-delete "icharset" ctl)) + (when charset + (setq ctl (mew-syntax-get-params ctl)) + (setq ctl (mew-delete "charset" ctl)) + (setq ctl (cons ct (cons (list "charset" charset) ctl)))) + (when flowed + (setq ctl (nconc ctl (list (list "format" "flowed")))) + (if delsp (setq ctl (nconc ctl (list (list "delsp" "yes")))))) + ;; + (setq ctl (mew-delete "name" ctl)) + (setq broken-name (mew-broken-name cdpl)) + (if broken-name (setq ctl (nconc ctl (list broken-name)))) + ;; + (mew-header-insert mew-ct: ctl) + (mew-header-insert mew-cte: cte) + (and cd (mew-header-insert mew-cd: cd)) + (and cdpl (mew-header-insert mew-cdp: cdpl)) + (insert "\n") + ;; header "\n" (cur) [text] + (setq bodybeg (point)) + (goto-char (point-max)) + (when (and (string= ct mew-ct-msg) mew-field-delete-for-forwarding) + (save-restriction + (narrow-to-region bodybeg (point-max)) + (mew-header-delete-lines mew-field-delete-common) + (mew-header-delete-lines mew-field-delete-for-forwarding))) + (when privacy + (mew-encode-security-multipart + beg privacy depth (mew-syntax-get-decrypters syntax) cte)) + (goto-char (point-max)) + (when (and coverp (setq cst charset)) + (cond + ((null mew-ask-charset) + ;; not ask + ) + ((eq mew-ask-charset t) + (if (mew-member-case-equal cst mew-cs-m17n-list) + (setq ask-cst t))) + ((listp mew-ask-charset) + (unless (mew-member-case-equal cst mew-ask-charset) + (setq ask-cst t)))) + (if (and ask-cst + (not (y-or-n-p (format "%s is used. OK? " cst)))) + (mew-encode-error "Modify body"))) + (mew-case-equal cte mew-8bit))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Encoding multipart +;;; + +(defun mew-encode-make-multi () + ;; Just after the header + (let (beg path multip buffered privacy decrypters first ct) + (if (mew-encode-syntax-have-one-part) + ;; A user may want to do any MIME stuff to the body + (progn + (setq mew-encode-syntax (mew-syntax-get-part mew-encode-syntax)) + (setq buffered t)) + ;; See if a cover page is empty or not + (setq beg (point)) + (save-excursion + (while (and (looking-at "^$") (not (eobp))) + (forward-line)) + (unless (eobp) + ;; The cover page exists. + (setq buffered t))) + (setq path (mew-expand-folder mew-attach-folder)) + (if buffered + ;; The cover page exists. + (setq multip t) + ;; The cover page does not exist. + (delete-region beg (point-max)) + ;; Remove the cover page entry from the syntax. + (setq mew-encode-syntax + (mew-syntax-remove-entry mew-encode-syntax '(1))) + ;; After removing the over page, see if this message has + ;; only one text part. + (if (not (mew-encode-syntax-have-one-part)) + (setq multip t) + (setq first (mew-syntax-get-part mew-encode-syntax)) + (setq ct (mew-syntax-get-value (mew-syntax-get-ct first) 'cap)) + (if (not (mew-ct-textp ct)) + (setq multip t) + (setq path (expand-file-name + (mew-syntax-get-file mew-encode-syntax) path)) + (setq privacy (mew-syntax-get-privacy mew-encode-syntax)) + (setq decrypters (mew-syntax-get-decrypters mew-encode-syntax)) + (setq mew-encode-syntax (mew-syntax-get-part mew-encode-syntax)) + (mew-syntax-set-privacy mew-encode-syntax privacy) + (mew-syntax-set-decrypters mew-encode-syntax decrypters))))) + (if multip + (mew-encode-multipart mew-encode-syntax path 0 buffered) + (mew-encode-singlepart mew-encode-syntax path nil nil 'cover)))) + +(defvar mew-default-boundary "--%s(%s_%s)--") + +(defun mew-boundary-get (&optional string) + ;; boundary is less than or equal to 70 + (unless string (setq string "Next_Part")) + (format mew-default-boundary + string + (mew-replace-character + (mew-replace-character (current-time-string) mew-sp ?_) ?: ?_) + (mew-random-string 3 t))) + +(defun mew-encode-multipart (syntax path depth &optional buffered cte) + (let* ((boundary + (mew-boundary-get ;; 0 is nil for Next_Part + (if (> depth 0) (format "BOUNDARY%s" (number-to-string depth))))) + (fullname (expand-file-name (mew-syntax-get-file syntax) path)) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (cd (mew-syntax-get-cd syntax)) + (privacy (mew-syntax-get-privacy syntax)) + (mew-inherit-7bit (mew-encode-limit-7bitp privacy)) + (len (length syntax)) + (beg (point)) + (cnt mew-syntax-magic) + (8bit-cnt 0) + 8bitp cte-pos cover) + (mew-header-insert mew-ct: (list ct (list "boundary" boundary))) + (setq cte-pos (point)) + (and cd (mew-header-insert mew-cd: cd)) + (while (< cnt len) + (insert "\n--" boundary "\n") + (if (mew-syntax-multipart-p (aref syntax cnt)) + (setq 8bitp (mew-encode-multipart + (aref syntax cnt) + fullname + (1+ depth))) + (if (and (= depth 0) (= cnt mew-syntax-magic )) + (setq cover t) + (setq cover nil)) + (setq 8bitp (mew-encode-singlepart + (aref syntax cnt) + fullname + (1+ depth) + (if (eq cnt mew-syntax-magic) buffered nil) + cover))) + (if 8bitp (setq 8bit-cnt (1+ 8bit-cnt))) + (setq cnt (1+ cnt))) + (insert "\n--" boundary "--\n") + (save-excursion + (goto-char cte-pos) + (mew-header-insert mew-cte: (if (> 8bit-cnt 0) mew-8bit mew-7bit))) + (when privacy + (mew-encode-security-multipart + beg privacy depth (mew-syntax-get-decrypters syntax) cte)) + (goto-char (point-max)) + (> 8bit-cnt 0))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Privacy services +;;; + +(defun mew-encode-security-multipart (beg privacy depth decrypters cte) + (save-restriction + (narrow-to-region beg (point-max)) + (let (proto ct) + (dolist (ent privacy) + (goto-char (point-min)) + (mew-set '(ct proto) ent) + (setq ct (mew-capitalize ct)) + (cond + ((string= ct mew-ct-mle) + (mew-encode-multipart-encrypted ct proto depth decrypters cte)) + ((string= ct mew-ct-mls) + (mew-encode-multipart-signed ct proto depth)) + ((string= ct mew-ct-smm) + (mew-encode-smime proto cte decrypters))))))) + +(defun mew-security-multipart-boundary (depth) + (if depth + (mew-boundary-get (format "Security_Multipart%s" (number-to-string depth))) + (mew-boundary-get "Security_Multipart"))) + +(defun mew-save-transfer-form (beg end retain &optional cte) + ;; called in the narrowed region + (let ((sbeg beg) (send end) (draft-buf (current-buffer)) + (ocs mew-cs-text-for-net) + tmpbuf file) + (if retain + (progn + (setq tmpbuf (generate-new-buffer mew-buffer-prefix)) + (set-buffer tmpbuf) + (mew-erase-buffer) + (mew-insert-buffer-substring draft-buf beg end) + (setq sbeg (point-min) send (point-max)))) + (goto-char sbeg) ;; just in case + (if (and cte (mew-case-equal cte mew-bin) + (re-search-forward mew-eoh)) + (progn + (setq ocs mew-cs-binary) + (forward-line) + (save-restriction + (narrow-to-region sbeg (point)) + (goto-char sbeg) + (mew-lf-to-crlf))) + (unless mew-cs-text-for-net + (goto-char sbeg) ;; just in case + (mew-lf-to-crlf))) + (setq send (point-max)) + (setq file (mew-make-temp-name)) + (mew-frwlet mew-cs-dummy ocs + (write-region sbeg send file nil 'no-msg)) + (if retain + (mew-remove-buffer tmpbuf) + (delete-region sbeg send)) + (set-buffer draft-buf) + file)) ;; return value + +(defun mew-encode-multipart-encrypted (ct proto depth decrypters cte) + ;; called in the narrowed region + (let* ((boundary (mew-security-multipart-boundary depth)) + (switch mew-encode-multipart-encrypted-switch) ;; save length + (func (mew-encode-get-security-func proto switch)) + file1 file2 file3 cte2 cte3 fc errmsg) + ;; Write the part converting line breaks. + (setq file1 (mew-save-transfer-form (point-min) (point-max) nil cte)) + ;; The narrowed region stores nothing + ;; Call the protocol function + (condition-case nil + (setq fc (funcall func file1 decrypters)) + (error + (mew-delete-file file1) + (mew-encode-error + (format "unknown error for %s. Check %s, anyway" + mew-ct-mle mew-temp-dir)))) + (mew-set '(file2 cte2 file3 cte3 errmsg) fc) + (if errmsg + (progn + (mew-delete-file file1) + (mew-delete-file file2) + (mew-delete-file file3) + (mew-tinfo-set-privacy-err t) + (mew-tinfo-set-privacy-type nil) + (mew-draft-mode-name) + (mew-encode-error errmsg)) + ;; Create multipart content-header + (mew-header-insert mew-ct: (list ct + (list "protocol" proto) + (list "boundary" boundary))) + (mew-header-insert mew-cte: mew-7bit) + (insert (format "\n--%s\n" boundary)) + ;; Insert control keys + (mew-encode-singlepart + (mew-encode-syntax-single file2 (list proto) cte2)) + (insert (format "\n--%s\n" boundary)) + ;; Insert encrypted body + (mew-encode-singlepart + (mew-encode-syntax-single file3 mew-type-apo cte3)) + (insert (format "\n--%s--\n" boundary)) + ;; Throw away the garbage + (mew-delete-file file1) + (mew-delete-file file2) + (mew-delete-file file3)))) + +(defun mew-encode-multipart-signed (ct proto depth) + ;; called in the narrowed region + (let* ((boundary (mew-security-multipart-boundary depth)) + (switch mew-encode-multipart-signed-switch) ;; save length + (func (mew-encode-get-security-func proto switch)) + (canon-func (mew-encode-get-canonicalize-func proto switch)) + file1 file2 micalg cte2 fmc errmsg ct2 cdp2) + (if (fboundp canon-func) (funcall canon-func)) + (setq file1 (mew-save-transfer-form (point-min) (point-max) 'retain)) + ;; The narrowed region still the ORIGINAL part (i.e. line breaks are LF) + ;; Call the protocol function + (condition-case nil + (setq fmc (funcall func file1)) + (error + (mew-delete-file file1) + (mew-encode-error + (format "unknown error for %s. Check %s, anyway" + mew-ct-mls mew-temp-dir)))) + (mew-set '(file2 cte2 micalg errmsg ct2 cdp2) fmc) + (if errmsg + (progn + (mew-delete-file file1) + (mew-delete-file file2) + (mew-tinfo-set-privacy-err t) + (mew-tinfo-set-privacy-type nil) + (mew-draft-mode-name) + (mew-encode-error errmsg)) + (goto-char (point-min)) + ;; Before the signed part + ;; Create multipart content-header + (mew-header-insert mew-ct: (list ct + (list "protocol" proto) + (list "micalg" micalg) + (list "boundary" boundary))) + (mew-header-insert mew-cte: mew-7bit) + (insert (format "\n--%s\n" boundary)) + (goto-char (point-max)) + ;; After the signed part + (insert (format "\n--%s\n" boundary)) + (mew-encode-singlepart + (mew-encode-syntax-single file2 (or ct2 (list proto)) cte2 nil nil cdp2)) + (insert (format "\n--%s--\n" boundary)) + ;; Throw away the garbage + (mew-delete-file file1) + (mew-delete-file file2)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; 8bit to 7bit conversion for Multipart/Security +;;; + +(defun mew-convert-mime-body (beg end cte linebasep) + (let* ((switch (if linebasep + mew-prog-mime-encode-text-switch + mew-prog-mime-encode-switch)) + file opt) + (save-restriction + (narrow-to-region beg end) + (cond + ((and (mew-case-equal cte mew-b64) (fboundp 'base64-encode-region)) + (when linebasep + (goto-char (point-min)) + (mew-lf-to-crlf)) + (base64-encode-region (point-min) (point-max)) + (goto-char (point-max)) + (insert "\n")) + ((mew-which-exec mew-prog-mime-encode) + (setq opt (mew-prog-mime-encode-get-opt cte switch)) + (if (null opt) + (mew-encode-error (concat "Unknown CTE: " cte)) + (setq file (mew-make-temp-name)) + (mew-frwlet mew-cs-dummy (if linebasep mew-cs-text-for-write mew-cs-binary) + ;; NEVER use call-process-region for privacy reasons + (write-region (point-min) (point-max) file nil 'no-msg) + (delete-region (point-min) (point-max))) + (mew-piolet mew-cs-text-for-read mew-cs-dummy + (apply 'call-process mew-prog-mime-encode file t nil opt)) + (mew-delete-file file))) + (t + (mew-encode-error (concat mew-prog-mime-encode " does not exist"))))))) + +(defun mew-convert-message () + ;; called on the beginning of a header + (let ((case-fold-search t) + (buf (current-buffer)) + hd-end mimep charset cte body-beg body-end) + (unless (re-search-forward mew-eoh nil t) + (goto-char (point-max))) + (setq hd-end (point-marker)) + (goto-char (point-min)) + (if (re-search-forward (concat "^" mew-mv:) (marker-position hd-end) t) + (setq mimep t)) + (cond + (mimep + (goto-char (point-min)) + (mew-convert-singlepart) + (mew-header-delete-lines (list mew-mv:)) + (goto-char hd-end) + (mew-header-insert mew-mv: (concat mew-mv:-num " " mew-field-comment))) + (t + (goto-char hd-end) + (forward-line) + (setq body-beg (point)) + (setq body-end (point-max)) + (with-temp-buffer + (mew-insert-buffer-substring buf body-beg body-end) + (mew-cs-decode-region (point-min) (point-max) mew-cs-autoconv) + (setq charset (mew-charset-guess-region (point-min) (point-max)))) + (when (mew-encode-charset-8bitp charset) + (setq cte (mew-charset-to-cte charset)) + (if (null cte) (setq cte mew-b64)) + (mew-convert-mime-body body-beg (point-max) cte 'linebasep) + (goto-char (point-min)) + (mew-header-delete-lines (list "Content-")) + (goto-char hd-end) + (mew-header-insert mew-mv: mew-mv:-num) + (mew-header-insert mew-ct: (list mew-ct-txt (list "charset" charset))) + (mew-header-insert mew-cte: cte)))))) + +(defun mew-convert-singlepart (&optional dctl) + ;; called on the beginning of a content-header + (let ((case-fold-search t) + cthd-end ctbody-beg + ct-val cte-val + ctl ct cte charset) + (unless (re-search-forward mew-eoh nil t) + (goto-char (point-max))) + (setq cthd-end (point-marker)) + (forward-line) + (setq ctbody-beg (point)) + (goto-char (point-min)) + (if (not (re-search-forward (concat "^" mew-cte: "[ \t]*") nil t)) + (setq cte mew-7bit) + (setq cte-val (point-marker)) + (forward-line) + (mew-header-goto-next) + (setq cte (mew-addrstr-parse-value + (mew-buffer-substring cte-val (1- (point)))))) + (when (or (mew-case-equal cte mew-8bit) (mew-case-equal cte mew-bin)) + (goto-char (point-min)) + (if (not (re-search-forward (concat "^" mew-ct: "[ \t]*") nil t)) + (setq ctl (or dctl mew-type-txt)) + (setq ct-val (point)) + (forward-line) + (mew-header-goto-next) + (setq ctl (mew-param-decode + (mew-buffer-substring ct-val (1- (point))))) + (setq ct (mew-syntax-get-value ctl 'cap)) + (cond + ((mew-ct-multipartp ct) + (if (or (string= ct mew-ct-mle) (string= ct mew-ct-mls)) + () + (mew-convert-multipart ctl)) + (setq cte mew-7bit)) + ((mew-ct-messagep ct) + (if (string= ct mew-ct-msg) + (mew-convert-message)) + (setq cte mew-7bit)) + ((mew-ct-textp ct) + (setq charset (mew-syntax-get-param ctl "charset")) + (setq cte (mew-charset-to-cte charset)) + (if (or (null cte) + (mew-case-equal cte mew-8bit) + (mew-case-equal cte mew-bin)) + (setq cte mew-b64)) + (unless (mew-case-equal cte mew-7bit) + (mew-convert-mime-body ctbody-beg (point-max) cte 'linebasep))) + (t + ;; rare case + (setq cte (mew-ctdb-cte (mew-ctdb-by-ct ct))) + (if (or (null cte) + (mew-case-equal cte mew-8bit) + (mew-case-equal cte mew-bin)) + (setq cte mew-b64)) + (unless (mew-case-equal cte mew-7bit) + (mew-convert-mime-body + ctbody-beg (point-max) cte (mew-ct-linebasep ct)))) + (goto-char (point-min))) + (mew-header-delete-lines (list mew-cte:)) + (goto-char cthd-end) + (mew-header-insert mew-cte: (concat cte " " mew-field-comment)))))) + +(defun mew-convert-multipart (ctl) + (let* ((case-fold-search nil) ;; boundary is case sensitive + (ct (mew-syntax-get-value ctl 'cap)) + (dctl (if (string= ct mew-ct-mld) mew-type-msg)) + (boundary (regexp-quote (mew-syntax-get-param ctl "boundary"))) + obound ebound bregex start break) + (unless boundary + (mew-encode-error "No boundary parameter for multipart")) + (setq obound (concat "--" boundary)) + (setq ebound (concat "--" boundary "--")) + (setq bregex (concat "^--" boundary "\\(\\|--\\)$")) + (unless (re-search-forward (concat "^" obound "$") nil t) + (mew-encode-error (format "No first boundary for %s" ct))) + (forward-line) + (setq start (point)) ;; the beginning of the part + (catch 'multipart + (while t + (unless (re-search-forward bregex nil t) + (mew-encode-error (format "No last boundary for %s" ct))) + (setq break (string= (regexp-quote (match-string 0)) ebound)) + (forward-line) ;; the beginning of the next part + (save-excursion + (forward-line -1) + (beginning-of-line) ;; just in case + (forward-char -1) ;; skip the preceding CRLF + ;; the end of the part + (save-restriction + (narrow-to-region start (point)) + (goto-char (point-min)) + ;; the beginning of the part + (mew-convert-singlepart dctl))) + (setq start (point)) ;; the beginning of the part + (if break (throw 'multipart nil)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Backup and undo +;;; + +(defun mew-encode-make-backup () + (let* ((file (buffer-file-name)) + (back (mew-prepend-prefix file mew-backup-prefix)) + (info (concat file mew-draft-info-suffix))) + (mew-frwlet mew-cs-dummy mew-cs-m17n + (write-region (point-min) (point-max) back nil 'no-msg)) + (mew-lisp-save + info + (list + (cons "Syntax:" mew-encode-syntax) + (cons "Case:" (mew-tinfo-get-case)) + (cons "Flowed:" (mew-tinfo-get-flowed)) + (cons "Use-Flowed:" (mew-tinfo-get-use-flowed)) + (cons "Message:" (mew-tinfo-get-hdr-file))) ;; Header mode + 'nobackup) + nil)) ;; to save + +(defun mew-encode-load-syntax () + (let* ((file (buffer-file-name)) + (info (concat file mew-draft-info-suffix)) + syntax) + (when (file-exists-p info) + (setq syntax (mew-lisp-load info)) + (setq mew-encode-syntax (cdr (assoc "Syntax:" syntax))) + (if (and mew-encode-syntax + (mew-syntax-singlepart-p mew-encode-syntax)) + (setq mew-encode-syntax nil)) + (mew-tinfo-set-case (cdr (assoc "Case:" syntax))) + (mew-tinfo-set-flowed (cdr (assoc "Flowed:" syntax))) + (mew-tinfo-set-flowed (cdr (assoc "Use-Flowed:" syntax))) + (mew-tinfo-set-hdr-file (cdr (assoc "Message:" syntax))) ;; Header mode + t))) + +(defun mew-encode-insert-backup () + (let* ((file (buffer-file-name)) + (back (mew-prepend-prefix file mew-backup-prefix))) + (when (file-exists-p back) + (mew-frwlet mew-cs-m17n mew-cs-dummy + (mew-insert-file-contents back))))) + +(defun mew-encode-undo () + "Get back to the draft before making MIME message." + (interactive) + (mew-elet + (if (not (mew-encode-load-syntax)) + (message "Cannot undo") + (mew-erase-buffer) + (if (not (mew-encode-insert-backup)) + (message "Cannot undo") + (mew-header-clear) ;; erase the old header separator + (mew-header-prepared) + (if mew-encode-syntax (mew-draft-prepare-attachments)) + (mew-draft-toolbar-update) + (setq buffer-undo-list nil))))) + +(provide 'mew-encode) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-encode.el ends here diff --git a/elpa/mew-20150813.2354/mew-env.el b/elpa/mew-20150813.2354/mew-env.el new file mode 100644 index 00000000..af8c56ae --- /dev/null +++ b/elpa/mew-20150813.2354/mew-env.el @@ -0,0 +1,359 @@ +;;; mew-env.el --- Environment setup for Mew + +;; Author: Kazu Yamamoto +;; Created: Mar 6, 1997 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Suppressing warnings at compile +;;; + +(defmacro mew-no-warning-defvar (var-name) + `(unless (boundp ',var-name) (defvar ,var-name nil))) + +(defmacro mew-no-warning-defun (func-name) + `(unless (fboundp ',func-name) (defun ,func-name(&rest args) nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; +;;; + +;; to avoid competition with mh-e.el, sigh. +(let ((ent (rassq 'mh-letter-mode auto-mode-alist))) + (and ent (setq auto-mode-alist (delq ent auto-mode-alist)))) + +(defvar mew-connection-type1 nil + "Connection type for many processes. 't' means PTY and 'nil' means PIPE. +PIPE is usually recommended for speed but some OSes such as Linux +requires PTY.") + +(defvar mew-connection-type2 t + "Connection type for processes that requires a password.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Emacsen +;;; + +(if window-system (require 'faces)) + +(defvar mew-icon-p (and (featurep 'tool-bar) window-system)) + +(defvar mew-internal-utf-8p nil) +(if (or (fboundp 'utf-translate-cjk-mode) ;; Emacs 22.1 or later + (coding-system-p 'utf-8-emacs)) + (setq mew-internal-utf-8p t)) + +(require 'mew-key) +(require 'mew-gemacs) +(require 'mew-mule3) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Misc +;;; + +(defun mew-mark () (marker-position (mark-marker))) + +(defun mew-md5 (str) (md5 str nil nil 'binary)) + +(defun mew-timer (sec func) (run-at-time sec sec func)) + +(if (fboundp 'characterp) + (defalias 'mew-characterp 'characterp) + (defalias 'mew-characterp 'integerp)) + +(if (fboundp 'mouse-region-match) + (defalias 'mew-mouse-region-p 'mouse-region-match) + (defmacro mew-mouse-region-p (&rest args) nil)) + +(cond + ((boundp 'auto-hscroll-mode) ;; Emacs 21.3.50 or later + (defun mew-hscroll () + (set (make-local-variable 'auto-hscroll-mode) t))) + ((boundp 'automatic-hscrolling) ;; Emacs 21.3 or earlier + (defun mew-hscroll () + (set (make-local-variable 'automatic-hscrolling) t)))) + +(if (fboundp 'minibuffer-prompt-end) + (defalias 'mew-minibuf-point-min 'minibuffer-prompt-end) + (defalias 'mew-minibuf-point-min 'point-min)) + +(eval-when-compile + (unless (fboundp 'with-no-warnings) + (defmacro with-no-warnings (&rest body) `(progn ,@body)))) + +(if (fboundp 'set-process-query-on-exit-flag) + (defun mew-process-silent-exit (pro) + (set-process-query-on-exit-flag pro nil)) + (with-no-warnings + (defun mew-process-silent-exit (pro) + (process-kill-without-query pro)))) ;; Emacs 21.4 + +(with-no-warnings + (defun mew-set-coding-priority (pri) + (set-coding-priority pri))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sticky +;;; + +(defun mew-front-sticky (beg end) + (put-text-property beg end 'front-sticky t)) + +(defun mew-front-nonsticky (beg end) + (put-text-property beg end 'front-sticky nil)) + +(defun mew-rear-sticky (beg end) + (put-text-property beg end 'rear-nonsticky nil)) + +(defun mew-rear-nonsticky (beg end) + (put-text-property beg end 'rear-nonsticky t)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Overlay +;;; + +(defun mew-overlay-make (beg end) + (let ((ovl (make-overlay beg end))) + (overlay-put ovl 'mew t) + ovl)) + +(defun mew-overlay-delete (ovl) + (and (overlay-get ovl 'mew) (delete-overlay ovl))) + +(defun mew-overlay-delete-region (beg end) + "Delete overlays in the region." + (interactive "r") + (mapc 'mew-overlay-delete (overlays-in beg end)) + (if (fboundp 'remove-images) (remove-images beg end))) ;; xxx + +(defun mew-overlay-delete-buffer () + (save-restriction + (widen) + (mew-overlay-delete-region (point-min) (point-max)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; File operations +;;; + +(cond + ((fboundp 'make-symbolic-link) + (defun mew-symbolic-link (filename newname &optional OK-IF-ALREADY-EXISTS) + (if (file-directory-p (file-chase-links filename)) + (error "Cannot make a symbolic link to directory") + (make-symbolic-link filename newname OK-IF-ALREADY-EXISTS))) + (defun mew-link (filename newname &optional OK-IF-ALREADY-EXISTS) + (if (file-directory-p (file-chase-links filename)) + (error "Cannot make a link to directory") + (condition-case nil + (add-name-to-file filename newname OK-IF-ALREADY-EXISTS) + (file-error + (copy-file filename newname OK-IF-ALREADY-EXISTS 'keepdate)))))) + (t + (defun mew-symbolic-link (filename newname &optional OK-IF-ALREADY-EXISTS) + (if (file-directory-p filename) + (error "Cannot make a copy of directory") + (copy-file filename newname OK-IF-ALREADY-EXISTS 'keepdate))) + (defun mew-link (filename newname &optional OK-IF-ALREADY-EXISTS) + (if (file-directory-p filename) + (error "Cannot make a copy of directory") + (copy-file filename newname OK-IF-ALREADY-EXISTS 'keepdate))))) + +(if (and (fboundp 'set-file-times) + (memq system-type '(darwin windows-nt cygwin))) + (defalias 'mew-set-file-times 'set-file-times) + (defmacro mew-set-file-times (&rest args) nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Property +;;; + +(defalias 'mew-buffer-substring 'buffer-substring-no-properties) + +(if (fboundp 'match-string-no-properties) + (defalias 'mew-match-string 'match-string-no-properties) + (defalias 'mew-match-string 'match-string)) + +(defun mew-insert-buffer-substring (buf beg end) + (insert (with-current-buffer buf (mew-buffer-substring beg end)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Base64 +;;; + +(defun mew-base64-encode-string (str) + (base64-encode-string str 'no-line-break)) + +(defun mew-base64-decode-string (str64) + (condition-case nil + (base64-decode-string str64) + (error nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Language +;;; + +;; to load the thread separator +(cond + ((and (boundp 'current-language-environment) + (string= current-language-environment "Japanese")) + (require 'mew-lang-jp)) + ((and (boundp 'current-language-environment) + (string= current-language-environment "Korean")) + (require 'mew-lang-kr))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Unix and Mac +;;; + +(if (fboundp 'unix-sync) + (defalias 'mew-unix-sync 'unix-sync) + (defmacro mew-unix-sync (&rest args) nil)) + +(if (fboundp 'mac-set-file-type) + (defalias 'mew-mac-set-file-type 'mac-set-file-type) + (defmacro mew-mac-set-file-type (&rest args) nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Face +;;; + +(cond + ((fboundp 'face-all-attributes) ;; Emacs 23 + (defalias 'mew-face-spec-func 'cons) + (defun mew-face-spec-primitive (col bold) + (if col + (if bold + (list :foreground col :weight 'bold) + (list :foreground col :weight 'normal)) + (if bold + (list :weight 'bold) + (list :weight 'normal))))) + (t + (defalias 'mew-face-spec-func 'list) + (defun mew-face-spec-primitive (col bold) + (if col + (if bold + (list :foreground col :bold t) + (list :foreground col)) + (if bold + (list :bold t) + nil))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Misc +;;; + +(if (fboundp 'fill-match-adaptive-prefix) + (defalias 'mew-fill-match-adaptive-prefix 'fill-match-adaptive-prefix) + ;; Emacs 21.4 + (defun mew-fill-match-adaptive-prefix () + (let ((str (or + (and adaptive-fill-function (funcall adaptive-fill-function)) + (and adaptive-fill-regexp (looking-at adaptive-fill-regexp) + (match-string-no-properties 0))))) + (if (>= (+ (current-left-margin) (length str)) (current-fill-column)) + ;; Death to insanely long prefixes. + nil + str)))) + +(if (fboundp 'create-animated-image) + (defalias 'mew-create-image 'create-animated-image) + (defalias 'mew-create-image 'create-image)) + +(if (fboundp 'run-mode-hooks) + (defun mew-run-mode-hooks (&rest funcs) + (apply 'run-mode-hooks funcs)) + (defun mew-run-mode-hooks (&rest funcs) + (apply 'run-hooks funcs))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Unix/Mac/Win +;;; + +(cond + ((memq system-type '(windows-nt cygwin)) + (defun mew-set-file-type (file) ()) + (defvar mew-cs-est 'shift_jis) + (defun mew-focus-frame (frame) + (if (fboundp 'w32-focus-frame) (w32-focus-frame frame)))) + ((eq system-type 'darwin) + (defun mew-set-file-type (file) + (unless mew-use-suffix + (mew-mac-set-file-type file mew-file-type))) + (defvar mew-cs-est 'utf-8) + (defun mew-focus-frame (frame) + (when focus-follows-mouse + (set-mouse-position + (selected-frame) (1- (frame-width)) 0)))) + (t + (defun mew-set-file-type (file) ()) + (defvar mew-cs-est 'utf-8) + (defun mew-focus-frame (frame) + (when focus-follows-mouse + (set-mouse-position + (selected-frame) (1- (frame-width)) 0))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Unix/Mac/Win +;;; + +(cond + ((>= emacs-major-version 24) + ;; this must be macro. If implemented as a function, its behavior + ;; is changed. + (defmacro mew-called-interactively-p () + '(called-interactively-p 'interactive))) + (t + (defalias 'mew-called-interactively-p 'called-interactively-p))) + +(provide 'mew-env) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-env.el ends here diff --git a/elpa/mew-20150813.2354/mew-exec.el b/elpa/mew-20150813.2354/mew-exec.el new file mode 100644 index 00000000..dff3d244 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-exec.el @@ -0,0 +1,692 @@ +;;; mew-exec.el + +;; Author: Kazu Yamamoto +;; Created: Mar 2, 1997 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; exec-func +;;; + +(defun mew-mark-kill-refile (src msg) + (let ((refinfo (mew-refile-get msg)) + myself) + (setq myself (or (null refinfo) (member src refinfo))) + (if myself (mew-summary-refile-remove-body)) + (not myself))) + +(defun mew-mark-exec-refile (src msgs) + "Refile MSGs from the SRC folder." + (let (dsts tmp msg-dsts dsts-msgses) + (dolist (msg msgs) + (setq msg-dsts (mew-refile-get msg)) + (setq dsts (cdr msg-dsts)) + (if dsts ;; sanity check + (if (setq tmp (assoc dsts dsts-msgses)) + (nconc tmp (list msg)) + (setq dsts-msgses (cons (list dsts msg) dsts-msgses)))) + (mew-refile-reset msg)) + ;; refile at once + (dolist (dsts-msgs dsts-msgses) + (mew-summary-mv-msgs src dsts-msgs)))) + +(defun mew-mark-exec-unlink (src dels) + "Unlink DELS from the SRC folder. +DELS represents the messages to be deleted." + (when dels + (mew-summary-unlink-msgs src dels))) + +(defun mew-mark-exec-delete (src dels) + "Delete messages from the SRC folder according to 'mew-trash-folder' +and 'mew-trash-folder-list'. +DELS represents the messages to be deleted." + (when dels + ;; see also mew-summary-exec-remote-get-execinfo. + (cond + ((null mew-trash-folder) + (mew-summary-unlink-msgs src dels)) + (mew-trash-folder-list + (if (or (member src mew-trash-folder-list) + (string= src mew-trash-folder)) + (mew-summary-unlink-msgs src dels) + (mew-summary-totrash-msgs src dels))) + (t + (if (string= src mew-trash-folder) + (mew-summary-unlink-msgs src dels) + (mew-summary-totrash-msgs src dels)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; sanity-func +;;; + +(defun mew-mark-sanity-refile (msgs) + "Check the destination folder for MSGS." + (let (uniq-dsts udst err-dsts dir) + (dolist (msg msgs) + (dolist (dst (cdr (mew-refile-get msg))) + (mew-addq uniq-dsts dst))) + (mew-addq uniq-dsts mew-trash-folder) + (dolist (uniq-dst uniq-dsts) + (setq udst (mew-case-folder mew-inherit-exec-case uniq-dst)) + (setq dir (mew-expand-folder udst)) + (if (file-exists-p dir) + (if (file-directory-p dir) + (unless (file-writable-p dir) + (set-file-modes dir mew-folder-mode)) + (setq err-dsts (cons udst err-dsts))) ;; NG + (mew-make-directory dir))) + err-dsts)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Unlinking, moving, to-trash +;;; + +(defun mew-folder-suffix (folder) + (if (or (mew-folder-queuep folder) (mew-folder-postqp folder)) + mew-queue-info-suffix + (if (mew-folder-draftp folder) + mew-draft-info-suffix))) + +(defun mew-summary-unlink-msgs (src dels) + (let ((suffix (mew-folder-suffix src)) + file infofile) + (dolist (del dels) + (setq file (mew-expand-msg src del)) + ;; if file does not exist, the marked line will be deleted anyway. + (mew-delete-file file) + (when suffix + (setq infofile (concat file suffix)) + (mew-delete-file infofile))))) + +(defun mew-i2s (num cache) + (if cache + (concat "0" (number-to-string num)) ;; "0" is the mark for invalid messages + (number-to-string num))) + +(defun mew-summary-mv-msgs (src dsts-msgs) + (let* ((dsts (car dsts-msgs)) ;; (+foo +bar) + (msgs (cdr dsts-msgs)) ;; (1 2 3) + (srcx (mew-case:folder-folder src)) + (myselfp (member srcx dsts)) + (cache mew-inherit-offline) + (suffix (mew-folder-suffix srcx)) + msgs- srcfile dstfile dst num strnum infofile) + (if myselfp + ;; msg stays in the src folder with the same number + (progn + (setq dsts (delete srcx dsts)) + (dolist (msg msgs) + (if (file-regular-p (mew-expand-msg src msg)) + (setq msgs- (cons msg msgs-)))) + (setq msgs- (nreverse msgs-)) + (setq msgs msgs-)) + (setq dst (mew-case-folder mew-inherit-exec-case (car dsts))) + (setq dsts (cdr dsts)) + (setq num (string-to-number (mew-folder-new-message dst 'num-only cache))) + (dolist (msg msgs) + (setq srcfile (mew-expand-msg src msg)) + (when (and (file-exists-p srcfile) (file-writable-p srcfile)) + (setq strnum (mew-i2s num cache)) + (setq msgs- (cons strnum msgs-)) + (setq dstfile (mew-expand-new-msg dst strnum)) + (setq num (1+ num)) + (rename-file srcfile dstfile 'override) + (mew-set-file-times dstfile) + (when suffix + (setq infofile (concat srcfile suffix)) + (mew-delete-file infofile)))) + (mew-touch-folder dst) + (setq msgs- (nreverse msgs-)) + (setq src dst)) ;; myselfp + (dolist (ent dsts) + (setq dst (mew-case-folder mew-inherit-exec-case ent)) + (setq num (string-to-number (mew-folder-new-message dst 'num-only cache))) + (dolist (msg msgs-) + (setq srcfile (mew-expand-msg src msg)) + (setq strnum (mew-i2s num cache)) + (setq dstfile (mew-expand-new-msg dst strnum)) + (setq num (1+ num)) + (mew-link srcfile dstfile)) + (mew-touch-folder dst)))) + +(defun mew-summary-totrash-msgs (src dels) + (let* ((trash (mew-case-folder mew-inherit-exec-case mew-trash-folder)) + (trashdir (mew-expand-folder trash)) + (cache mew-inherit-offline) + (suffix (mew-folder-suffix src)) + num srcfile dstfile infofile) + (unless (file-directory-p trashdir) (make-directory trashdir)) + (setq num (string-to-number (mew-folder-new-message trash 'num-only cache))) + ;; must be here after ensuring that +trash exists. + (dolist (del dels) + (setq srcfile (mew-expand-msg src del)) ;; xxx + (setq dstfile (mew-expand-new-msg trash (mew-i2s num cache))) + (setq num (1+ num)) + (when (file-regular-p srcfile) + ;; if not, the marked line will be deleted anyway. + (rename-file srcfile dstfile 'override) + (mew-set-file-times dstfile)) + (when suffix + (setq infofile (concat srcfile suffix)) + (mew-delete-file infofile))) + (mew-touch-folder trash))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Commands for mark processing +;;; + +(defun mew-summary-exec (&optional arg) + "\\ Process marked messages. When called with +'\\[universal-argument]', process marked messages in the specified +region. To cancel the '*' mark, use '\\[mew-summary-undo]' or +'\\[mew-summary-undo-all]'." + (interactive "P") + (let (beg end region) + (if (mew-mark-active-p) (setq arg t)) + (cond + (arg + (setq region (mew-summary-get-region)) + (setq beg (car region)) + (setq end (cdr region))) + (t + (setq beg (point-min)) + (setq end (point-max)))) + (mew-summary-exec-region beg end))) + +(defun mew-summary-exec-one (&optional arg) + "Process the current marked message. +When called with '\\[universal-argument]', process +all marked messages before the current message." + (interactive "P") + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (save-window-excursion + (let (beg end) + (save-excursion + (beginning-of-line) + (setq beg (if arg (point-min) (point))) + (end-of-line) + (setq end (1+ (point)))) + (if (> end (point-max)) + (message "No message") + (mew-summary-exec-region beg end))))) + +(defun mew-summary-exec-delete () + "Process messages marked with 'D'." + (interactive) + (let* ((ent (assoc mew-mark-delete mew-mark-spec)) + (mew-mark-spec (list ent))) + (mew-summary-exec-region (point-min) (point-max)))) + +(defun mew-summary-exec-unlink () + "Process messages marked with 'X'." + (interactive) + (let* ((ent (assoc mew-mark-unlink mew-mark-spec)) + (mew-mark-spec (list ent))) + (mew-summary-exec-region (point-min) (point-max)))) + +(defun mew-summary-exec-refile (&optional arg) + "Process messages marked with 'o'. +If called with '\\[universal-argument]', only messages whose +destination is the same as that of the current message are processed." + (interactive "P") + (let* ((ent (assoc mew-mark-refile mew-mark-spec)) + (mew-mark-spec (list ent))) + (if (not arg) + (mew-summary-exec-region (point-min) (point-max)) + (let* ((msg (mew-summary-message-number)) + (dst (cdr (mew-refile-get msg))) + func) + (if (not dst) + (message "No message to be refiled here") + (setq func (lambda (num) (equal dst (cdr (mew-refile-get num))))) + (mew-summary-exec-region (point-min) (point-max) func)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Exec region +;;; + +(defun mew-summary-move-and-display (msg &optional redisplay) + (when (mew-summary-search-msg msg) + (mew-summary-display redisplay))) + +(defun mew-summary-go-back-summary (key) + (let ((msg (mew-summary-message-number)) + (fld (mew-summary-physical-folder))) + (if (not (and fld (get-buffer fld))) + (message "No physical folder") + (mew-summary-visit-folder fld nil 'no-ls) + (if msg + (mew-summary-move-and-display msg) + (goto-char (point-max))) + (message "Now in %s. Type '%s' again" fld key)))) + +(defun mew-summary-exec-region (beg end &optional func) + (let ((folder (mew-sinfo-get-folder))) + (cond + ((mew-folder-nntpp folder) + (message "This command cannot be used in this folder")) + ((mew-folder-remotep folder) + (message "Refiling and deleting...") + (force-mode-line-update) + (mew-summary-exec-remote beg end func)) + ((mew-virtual-p) + (mew-summary-go-back-summary + (mew-substitute-for-summary "\\[mew-summary-exec]"))) + (t + (message "Refiling and deleting...") + (force-mode-line-update) + (mew-summary-exec-local beg end func))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Refile log +;;; + +(defun mew-exec-refile-log (buf) + (when (get-buffer buf) + (with-current-buffer buf + (mew-frwlet mew-cs-dummy mew-cs-m17n + (write-region (point-min) (point-max) + (expand-file-name mew-refile-log-file mew-conf-path) + 'append 'no-msg))) + (mew-remove-buffer buf))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Processing marks for local +;;; + +(defun mew-mark-kill-line () + (let (start) + (beginning-of-line) + (setq start (point)) + (forward-line) + (mew-elet (delete-region start (point))))) + +(defun mew-summary-exec-local (beg end &optional func-decide) + (when (mew-summary-exclusive-p) + (save-excursion + (condition-case nil + (let* ((marks (mew-mark-get-all-marks)) + (src (mew-summary-folder-name 'ext)) + (lbuf (mew-refile-log-buffer src)) + (m (copy-marker end)) + (cnt 0) + (case-fold-search nil) + msg msgs err-folders func-exec func-sanity killp regex) + (dolist (mark marks) + (setq func-exec (mew-markdb-func-exec mark)) + (when func-exec + (setq killp (mew-markdb-killp mark)) + (setq regex (mew-mark-regex mark)) + (setq msgs nil) + (goto-char beg) + (while (re-search-forward regex m t) + (setq msg (mew-summary-message-number)) + (when (or (not func-decide) (funcall func-decide msg)) + (setq msgs (cons msg msgs)) + (cond + ((fboundp killp) + (if (funcall killp src msg) + (mew-mark-kill-line) + (mew-mark-remove))) + ((eq killp t) + (mew-mark-kill-line))))) + (setq msgs (nreverse msgs)) + (when msgs + (when (= cnt 0) + ;; opening... + (mew-summary-lock t "Executing") + (mew-summary-reset)) + (setq cnt (1+ cnt)) + ;; refiling and deleting... + (setq func-sanity (mew-markdb-func-sanity mark)) + (when (and func-sanity + (setq err-folders (funcall func-sanity msgs))) + (mew-summary-unlock) + (mew-warn + "Nothing proceeded. Folder(s) MUST be a file!: %s" + (mew-join "," err-folders))) + (funcall func-exec src msgs)))) + (if (= cnt 0) + (message "No marks") + ;; ending... + (mew-cache-clean-up) + (mew-summary-folder-cache-save) + (set-buffer-modified-p nil) + (mew-summary-unlock) + (when (and (eobp) (not (pos-visible-in-window-p))) + (forward-line -1) + ;; This ensures that some messages are displayed in Summary. + (recenter)) + (run-hooks 'mew-summary-exec-hook) + (mew-exec-refile-log lbuf) + (message "Refiling and deleting...done"))) + (quit + (set-buffer-modified-p nil) + (mew-summary-unlock)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Processing marks for remote +;;; + +(defun mew-mark-invisible-line () + (let (start) + (beginning-of-line) + (setq start (point)) + (forward-line) + (mew-elet + (put-text-property start (point) 'invisible t) + ;; For Emacs only. To make invisible text act as we want + (put-text-property start (point) 'front-sticky t)))) + +(mew-defstruct execinfo remove kill refile move rttl dttl) +(mew-defstruct refileinfo uid size delete folders) + +(defun mew-summary-exec-remote-get-execinfo (beg end modify &optional func-decide) + ;; for POP or IMAP + ;; If modify, marked lines get invisible. They are removed + ;; IMAP's sentinel. + ;; Otherwise, marked lines retain and they are to be processed + ;; by mew-summary-exec-local(). + (let* ((case (mew-sinfo-get-case)) + (folder (mew-sinfo-get-folder)) + (m (copy-marker end)) + (case-fold-search nil) + (rttl 0) (dttl 0) + trash trash-list lomov + siz msg uid ref flds del regex trss rmvs kils refs movs + refinfo refile-back) + (when (mew-folder-imapp folder) + ;; see also mew-mark-exec-delete. + (setq trash (mew-imap-trash-folder case)) + (setq trash-list (mew-imap-trash-folder-list case)) + (setq lomov t) + (cond + ((null trash) + ) + (trash-list + (if (or (member folder trash-list) + (string= folder trash)) + (setq trash nil))) + (t + (if (string= folder trash) + (setq trash nil))))) + (save-excursion + (mew-decode-syntax-delete) + ;; + ;; refile + ;; + (when (mew-markdb-by-mark mew-mark-refile) + (setq regex (mew-mark-regex mew-mark-refile)) + (goto-char beg) + (while (re-search-forward regex m t) + (re-search-forward mew-regex-sumsyn-long) + (setq msg (mew-sumsyn-message-number)) + (setq uid (mew-sumsyn-message-uid)) + (setq siz (mew-sumsyn-message-size)) + (when (or (not func-decide) (funcall func-decide msg)) + (setq refinfo (mew-refile-get msg)) + (setq refile-back (cons refinfo refile-back)) + (setq flds (cdr refinfo)) + ;; + (setq del nil) + (if (member folder flds) + (setq flds (delete folder flds)) ;; destructive + (setq del t) + (when modify + (if lomov + (setq movs (cons msg movs)) + (setq kils (cons msg kils))))) + (when flds + (setq ref (mew-make-refileinfo :uid uid + :size siz + :delete del + :folders flds)) + (setq refs (cons ref refs))) + (if modify + (if del + (mew-mark-invisible-line) + (mew-summary-refile-remove-body) + (mew-mark-remove))))) + (setq refs (nreverse refs)) + (setq rttl (length refs)) + (setq movs (nreverse movs)) + (if modify (mew-sinfo-set-refile-back refile-back)) + (when lomov + (let ((mew-inherit-exec-case case)) + (mew-mark-sanity-refile movs)))) + ;; + ;; delete + ;; + (when (mew-markdb-by-mark mew-mark-delete) + (setq regex (mew-mark-regex mew-mark-delete)) + (goto-char beg) + (while (re-search-forward regex m t) + (re-search-forward mew-regex-sumsyn-long) + (setq msg (mew-sumsyn-message-number)) + (setq uid (mew-sumsyn-message-uid)) + (setq siz (mew-sumsyn-message-size)) + (if trash + (setq trss (cons (mew-make-refileinfo :uid uid + :size siz + :delete t + :folders (list trash)) + trss)) + (setq rmvs (cons uid rmvs))) + (when modify + (setq kils (cons msg kils)) + (mew-mark-invisible-line)) + (setq dttl (1+ dttl)))) + ;; + ;; unlink + ;; + (when (mew-markdb-by-mark mew-mark-unlink) + (setq regex (mew-mark-regex mew-mark-unlink)) + (goto-char beg) + (while (re-search-forward regex m t) + (re-search-forward mew-regex-sumsyn-long) + (setq msg (mew-sumsyn-message-number)) + (setq uid (mew-sumsyn-message-uid)) + (setq siz (mew-sumsyn-message-size)) + (setq rmvs (cons uid rmvs)) + (when modify + (setq kils (cons msg kils)) + (mew-mark-invisible-line)) + (setq dttl (1+ dttl)))) + ;; + (setq rmvs (nreverse rmvs)) + (setq trss (nreverse trss)) + (if trss (setq refs (nconc trss refs))) + ;; + (set-buffer-modified-p nil) + (cond + ((and (null rmvs) (null refs)) nil) + (modify + (force-mode-line-update) ;; xxx + (mew-make-execinfo :remove rmvs + :kill kils + :refile refs + :move movs + :rttl rttl + :dttl dttl)) + (t + (mew-make-execinfo :remove rmvs + :refile refs + :rttl 0 + :dttl 0)))))) + +(defun mew-summary-exec-remote (beg end &optional func-decide) + (if (mew-folder-nntpp (mew-sinfo-get-folder)) + (message "This command cannot be used in this folder") + (when (mew-summary-exclusive-p) + (let* ((case (mew-sinfo-get-case)) + (folder (mew-sinfo-get-folder)) + (bnm (mew-summary-folder-name 'ext)) + (lbuf (mew-refile-log-buffer bnm)) + (execinfo (mew-summary-exec-remote-get-execinfo beg end 'modify func-decide))) + (if (not execinfo) + (message "No messages to be processed") + (mew-summary-reset) + (while (eq (get-text-property (point) 'invisible) t) + (forward-line)) + (cond + ((mew-folder-popp folder) + (mew-pop-retrieve case 'exec bnm execinfo)) + ((mew-folder-imapp folder) + (mew-imap-retrieve case 'exec bnm execinfo))) + (mew-exec-refile-log lbuf)))))) + +(defun mew-mark-kill-invisible () + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (if (get-text-property (point) 'invisible) + (mew-mark-kill-line) + (forward-line))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Processing marks for offline +;;; + +(defun mew-summary-exec-offline (&optional arg) + "\\Process marked messages in an IMAP folder *offline*. Messages to be refiled in +a remote folder are moved to the corresponding folder but they are +marked invalid. Invalid message are marked with '#'. +Invalid messages will be overridden when the remote folder is scanned online. +A job to delete or refile messages, which is created by this command, +is queued in a queue folder (%queue for IMAP). To flush jobs in +the queue, type '\\[mew-summary-send-message]' in the queue online." + (interactive "P") + (cond + ((mew-virtual-p) + (mew-summary-go-back-summary + (mew-substitute-for-summary "\\[mew-summary-exec-offline]"))) + ((not (mew-folder-imapp (mew-sinfo-get-folder))) + (message "This command cannot be used in this folder")) + (t + (if (mew-mark-active-p) (setq arg t)) + (let (beg end region) + (cond + (arg + (setq region (mew-summary-get-region)) + (setq beg (car region)) + (setq end (cdr region))) + (t + (setq beg (point-min)) + (setq end (point-max)))) + (message "Refiling and deleting...") + (force-mode-line-update) + (mew-summary-exec-offline-region beg end))))) + +(mew-defstruct jobinfo mailbox execinfo mark-hist) + +(defun mew-summary-exec-offline-region (beg end) + "Process the current marked message offline." + (interactive) + (let* ((execinfo (mew-summary-exec-remote-get-execinfo beg end nil)) + (rmvs (mew-execinfo-get-remove execinfo)) + (refs (mew-execinfo-get-refile execinfo)) + job) + (if (not execinfo) + (message "No messages to be processed") + (let* ((fld (mew-sinfo-get-folder)) + (case (mew-sinfo-get-case)) + (imapq (mew-case-folder case (mew-imap-queue-folder case))) + (imapq-dir (mew-expand-folder imapq)) + file file-info) + (unless (file-directory-p imapq-dir) (mew-make-directory imapq-dir)) + (setq file (mew-folder-new-message imapq)) + (setq file-info (concat file mew-imapq-info-suffix)) + (setq job (mew-make-jobinfo :mailbox fld + :execinfo execinfo + :mark-hist (mew-sinfo-get-mark-hist))) + (mew-lisp-save file-info job 'nobackup 'unlimit) + (with-temp-buffer + (mew-header-insert mew-subj: (format "IMAP jobs for %s" fld)) + (mew-header-insert mew-date: (mew-time-ctz-to-rfc (current-time))) + (mew-header-insert mew-from: "Mew IMAP manager") + (insert "\n") + (insert "Messages to be refiled:\n") + (dolist (ref refs) + (insert (format (if (mew-refileinfo-get-delete ref) + "\t%s will be copied to %s\n" + "\t%s will be moved to %s\n") + (mew-refileinfo-get-uid ref) + (mew-join "," (mew-refileinfo-get-folders ref))))) + (insert "\n") + (when rmvs + (insert "Messages to be deleted:\n") + (insert "\t" (mew-join "," rmvs) "\n")) + (mew-frwlet mew-cs-dummy nil + (write-region (point-min) (point-max) file nil 'no-msg))) + (mew-touch-folder imapq) + ;; refile log is not necessary since mew-summary-exec-local does it. + (let ((mew-inherit-exec-case case) + (mew-inherit-offline t) + (mew-trash-folder (mew-imap-trash-folder case))) + (mew-summary-exec-local beg end)))))) + +(defun mew-summary-exec-offline-one (&optional arg) + "Process the message on the cursor offline." + (interactive "P") + (if (not (mew-folder-imapp (mew-sinfo-get-folder))) + (message "This command cannot be used in this folder") + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (save-window-excursion + (let (beg end) + (save-excursion + (beginning-of-line) + (setq beg (if arg (point-min) (point))) + (end-of-line) + (setq end (1+ (point)))) + (if (> end (point-max)) + (message "No message") + (force-mode-line-update) ;; xxx + (mew-summary-exec-offline-region beg end)))))) + +(provide 'mew-exec) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-exec.el ends here diff --git a/elpa/mew-20150813.2354/mew-ext.el b/elpa/mew-20150813.2354/mew-ext.el new file mode 100644 index 00000000..5a793da1 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-ext.el @@ -0,0 +1,523 @@ +;;; mew-ext.el --- Message/External-Body support for Mew + +;; Author: Kazu Yamamoto +;; Created: Nov 13, 1996 + +;;; Code: + +(require 'mew) +(eval-when-compile + (cond +;; ((mew-which-el "efs") +;; (require 'efs)) + ((mew-which-el "ange-ftp") + (require 'ange-ftp)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Variables for encoding +;;; + +(defvar mew-ext-default-access-type "anon-ftp") + +(defvar mew-ext-ftp-server-list + '("ftp.example.org" "ftp.example.jp")) + +(defvar mew-ext-encode-switch + '(("ftp" . mew-ext-encode-ftp) +;; ("tftp" . mew-ext-encode-tftp) + ("anon-ftp" . mew-ext-encode-anon-ftp) + ("local-file" . mew-ext-encode-local-file) + ("mail-server" . mew-ext-encode-mail-server) + ("url" . mew-ext-encode-url))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Variables for decoding +;;; + +(defvar mew-ext-switch + '(("ftp" mew-ext-ftp mew-ext-ftp-ext) + ("tftp" mew-ext-tftp nil) + ("anon-ftp" mew-ext-anon-ftp mew-ext-anon-ftp-ext) + ("mail-server" mew-ext-mail-server mew-ext-mail-server-ext) + ("url" mew-ext-url mew-ext-url-ext))) ;; RFC 2017 + +(defun mew-ext-get-func (acc-type) + (nth 1 (mew-assoc-match acc-type mew-ext-switch 0))) + +(defun mew-ext-get-func-ext (acc-type) + (nth 2 (mew-assoc-match acc-type mew-ext-switch 0))) + +(defvar mew-ext-include-switch + '(("local-file" mew-ext-include-local-file))) + +(defun mew-ext-include-get-func (acc-type) + (nth 1 (mew-assoc-case-equal acc-type mew-ext-include-switch 0))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; environment variables +;;; + +(cond +;; ((mew-which-el "efs") +;; (defun mew-ext-file-name-completion (file path) +;; (require 'efs) +;; (let ((efs-tmp-name-template mew-temp-file)) +;; (efs-file-name-completion file path))) +;; (defun mew-ext-file-name-all-completions (file path) +;; (require 'efs) +;; (let ((efs-tmp-name-template mew-temp-file)) +;; (efs-file-name-all-completions file path))) +;; (defun mew-ext-expand-dir (host user dir) +;; (require 'efs) +;; (let ((efs-tmp-name-template mew-temp-file) exp) +;; (setq exp (efs-expand-file-name (format "/%s@%s:%s" user host dir))) +;; (if (string-match ".*:\\(.*\\)$" exp) +;; (match-string 1 exp)))) +;; (defun mew-ext-copy-file-internal (remote local passwd) +;; (require 'efs) +;; (let ((efs-tmp-name-template mew-temp-file) +;; (efs-generate-anonymous-password passwd) +;; (parsed (efs-ftp-path remote))) +;; (efs-copy-file-internal remote parsed local nil +;; nil nil nil nil t 'image)))) + ((mew-which-el "ange-ftp") + (defun mew-ext-file-name-completion (file path) + (require 'ange-ftp) + (let ((ange-ftp-tmp-name-template mew-temp-file)) + (ange-ftp-file-name-completion file path))) + (defun mew-ext-file-name-all-completions (file path) + (require 'ange-ftp) + (let ((ange-ftp-tmp-name-template mew-temp-file)) + (ange-ftp-file-name-all-completions file path))) + (defun mew-ext-expand-dir (host user dir) + (require 'ange-ftp) + (let ((ange-ftp-tmp-name-template mew-temp-file) exp) + (setq exp (ange-ftp-expand-file-name (format "/%s@%s:%s" user host dir))) + (if (string-match ".*:\\(.*\\)$" exp) + (match-string 1 exp)))) + (defun mew-ext-copy-file-internal (remote local passwd) + (require 'ange-ftp) + (let ((ange-ftp-tmp-name-template mew-temp-file) + (ange-ftp-generate-anonymous-password passwd)) + (ange-ftp-copy-file-internal remote local t nil nil nil t))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Encode +;;; + +(defun mew-attach-external-body () + "Specify external body." + (interactive) + (if (not (mew-attach-not-line012-1)) + (message "Cannot insert external-body here") + (let* ((nums (mew-syntax-nums)) + (subdir (mew-attach-expand-path mew-encode-syntax nums)) + (attachdir (mew-attachdir)) + file filepath ct) + ;; attachdir / {subdir/} dir + (if (not (string= subdir "")) + (setq attachdir (expand-file-name subdir attachdir))) + ;; attachdir / file + (setq filepath (mew-random-filename attachdir 1 nil mew-ext-suffix)) + (if (file-exists-p filepath) + (message "Cannot make a file for external-body, sorry") + (setq file (file-name-nondirectory filepath)) + (setq ct (mew-ext-encode filepath)) + (setq mew-encode-syntax + (mew-syntax-insert-entry + mew-encode-syntax + nums + (mew-encode-syntax-single file ct))) + (mew-encode-syntax-print mew-encode-syntax))))) + +(defun mew-create-content-id () + ;; this is not unique if used with very short interval. + ;; but it's ok + (format "<%s.%s.%s@%s>" (nth 0 (current-time)) (nth 1 (current-time)) + (emacs-pid) (system-name))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-encode (filename) + (let (ret access-type ct name) + (with-temp-buffer + ;;content-header + (setq access-type (mew-input-general + "Access type" mew-ext-encode-switch t + mew-ext-default-access-type)) + (setq ret (funcall (cdr (assoc access-type mew-ext-encode-switch)))) + ;;message-header + (cond + ((string= access-type "url") + (setq name "URL") + (setq ct "Text/Html")) + ((string= access-type "mail-server") + (setq name "Mail server's file") + (setq ct mew-ct-apo)) + (t + (setq name (file-name-nondirectory + (mew-chop (mew-syntax-get-param ret "name")))) + ;; name is quoted + (if (string= name "") + (setq ct mew-ct-apo) + (setq ct (or (mew-ctdb-ct (mew-ctdb-by-file name)) + (mew-content-type (mew-tinfo-get-case))))))) + (setq ct (mew-input-type "Type for %s (%s): " name ct + mew-mime-content-type-list)) + (mew-header-insert mew-ct: ct) + (mew-header-insert mew-cid: (mew-create-content-id)) + (insert "\n") + (when (string= access-type "mail-server") + ;;message-body + (insert (read-string "Input message to the mail-server: ")) + (insert "\n")) + (write-file filename)) + (cons mew-ct-ext (cons (list "access-type" access-type) ret)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-encode-ftp () + ;; "name" "site" "directory" "mode" + (let ((mew-ext-host (mew-input-general + "FTP server" + (if mew-ext-ftp-server-list + (mapcar 'list mew-ext-ftp-server-list)) + nil + (car mew-ext-ftp-server-list))) + mew-ext-user path dir file ret) + (setq ret (list (list "site" mew-ext-host))) + (setq mew-ext-user (read-string (format "User name at %s: " mew-ext-host) + (mew-user))) + (setq path (mew-input-rfile "Filename:")) + (setq file (file-name-nondirectory path)) + (setq dir (file-name-directory path)) + (if (and dir (string-match mew-home dir)) + (setq dir (mew-ext-expand-dir mew-ext-host mew-ext-user dir))) + (cond + (dir + (setq ret (cons (list "directory" dir) ret)) + (setq ret (cons (list "name" file) ret))) + (t + (setq ret (cons (list "name" file) ret)))) + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-encode-tftp () + ;; xxx not yet + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-encode-anon-ftp () + ;; "name" "site" "directory" "mode" + (let ((mew-ext-user "anonymous") + (mew-ext-host (mew-input-general + "FTP server" + (if mew-ext-ftp-server-list + (mapcar 'list mew-ext-ftp-server-list)) + nil + (car mew-ext-ftp-server-list))) + path dir file ret) + (setq ret (list (list "site" mew-ext-host))) + (setq path (mew-input-rfile "Filename:")) + (setq file (file-name-nondirectory path)) + (setq dir (file-name-directory path)) + (if (and dir (string-match mew-home dir)) + (setq dir (mew-ext-expand-dir mew-ext-host mew-ext-user dir))) + (cond + (dir + (setq ret (cons (list "directory" dir) ret)) + (setq ret (cons (list "name" file) ret))) + (t + (setq ret (cons (list "name" file) ret)))) + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-encode-local-file () + ;; "name" "site" + (let ((file (mew-draft-input-file-name "File name: "))) + (list (list "name" (expand-file-name file))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-encode-mail-server () + ;; "server" "subject" + (let (server subject) + (setq server (car (mew-input-address "Server address: "))) + (setq subject (read-string (concat mew-subj: " "))) + (list (list "server" server) + (list "subject" subject)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-encode-url () + ;; "url" + (let ((url (read-string "URL: "))) + (list (list "url" url)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Decode +;;; + +;; +;; exclude +;; + +(defun mew-mime-external-body (cache begin end &optional params) + ;; message-buffer + (let* ((access-type (mew-syntax-get-param params "access-type")) + (func (mew-ext-get-func access-type))) + (if (and (symbolp func) (fboundp func)) + (funcall func cache begin end params)))) + +(defun mew-mime-external-body-ext (cache begin end &optional params) + (let* ((access-type (mew-syntax-get-param params "access-type")) + (func (mew-ext-get-func-ext access-type))) + (if (and (symbolp func) (fboundp func)) + (funcall func cache begin end params)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-ftp (cache begin end &optional params) + (mew-elet + (let* ((site (mew-syntax-get-param params "site")) + (directory (mew-syntax-get-param params "directory")) + (name (mew-syntax-get-param params "name")) + (size (mew-syntax-get-param params "size")) + filepath) + (if directory + (setq filepath (mew-concat-folder directory name)) + (setq filepath name)) + (setq filepath (mew-remove-drive-letter filepath)) + (mew-erase-buffer) + (insert " ####### ####### ###### \n" + " # # # # \n" + " # # # # \n" + " ##### # ###### \n" + " # # # \n" + " # # # \n" + " # # # \n" + "\n\n") + (insert "You can get the message content by FTP\n\n") + (mew-insert "Site:\t%s\n" site) + (mew-insert "File:\t%s\n" filepath) + (mew-insert "Size:\t%s bytes\n" size) + (insert "\n") + (mew-insert-manual + "To get this file, type " + "'\\\\[mew-summary-execute-external]'.\n")))) + +(defun mew-ext-ftp-ext (cache begin end &optional params) + (let* ((site (mew-syntax-get-param params "site")) + (directory (mew-syntax-get-param params "directory")) + (name (mew-syntax-get-param params "name")) + (getit t) (username "") + filepath localfile lfname remotefile) + (if directory + (setq filepath (mew-concat-folder directory name)) + (setq filepath name)) + (setq filepath (mew-remove-drive-letter filepath)) + (setq username (read-string (format "User name at %s: " site) (mew-user))) + (setq remotefile (format "/%s@%s:%s" username site filepath)) + (setq localfile (mew-summary-input-file-name "Save to: " name)) + (setq lfname (file-name-nondirectory localfile)) + (if (file-exists-p localfile) + (if (y-or-n-p (format "%s exists. Overwrite? " lfname)) + (mew-delete-file localfile) + (setq getit nil) + (message "The file was not retrieved"))) + (if getit (mew-ext-copy-file-internal remotefile localfile nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-tftp (cache begin end &optional params) + (message "Access-type TFTP is not supported yet")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-anon-ftp (cache begin end &optional params) + (mew-elet + (let* ((site (mew-syntax-get-param params "site")) + (directory (mew-syntax-get-param params "directory")) + (name (mew-syntax-get-param params "name")) + (size (mew-syntax-get-param params "size")) + filepath) + (if directory + (setq filepath (mew-concat-folder directory name)) + (setq filepath name)) + (setq filepath (mew-remove-drive-letter filepath)) + (mew-erase-buffer) + (insert " Anonymous \n" + " ####### ####### ###### \n" + " # # # # \n" + " # # # # \n" + " ##### # ###### \n" + " # # # \n" + " # # # \n" + " # # # \n" + "\n\n") + (insert "You can get the message content by FTP\n\n") + (mew-insert "Site:\t%s\n" site) + (mew-insert "File:\t%s\n" filepath) + (mew-insert "Size:\t%s bytes\n" size) + (insert "\n") + (mew-insert-manual + "To get this file, type " + "'\\\\[mew-summary-execute-external]'.\n")))) + +(defun mew-ext-anon-ftp-ext (cache begin end &optional params) + (let* ((site (mew-syntax-get-param params "site")) + (directory (mew-syntax-get-param params "directory")) + (name (mew-syntax-get-param params "name")) + (getit t) + filepath localfile lfname remotefile) + (if directory + (setq filepath (mew-concat-folder directory name)) + (setq filepath name)) + (setq filepath (mew-remove-drive-letter filepath)) + (setq remotefile (format "/%s@%s:%s" "anonymous" site filepath)) + (setq localfile (mew-summary-input-file-name "Save to: " name)) + (setq lfname (file-name-nondirectory localfile)) + (if (file-exists-p localfile) + (if (y-or-n-p (format "%s exists. Overwrite? " lfname)) + (mew-delete-file localfile) + (setq getit nil) + (message "The file was not retrieved"))) + (if getit (mew-ext-copy-file-internal remotefile localfile (mew-mail-address))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-mail-server (cache begin end &optional params) + (mew-elet + (let* ((server (mew-syntax-get-param params "server")) + (size (mew-syntax-get-param params "size"))) + (mew-erase-buffer) + (insert " # # # ### #\n" + " ## ## # # # #\n" + " # # # # # # # #\n" + " # # # # # # #\n" + " # # ####### # #\n" + " # # # # # #\n" + " # # # # ### #######\n" + "\n\n") + (insert "You can get the message by e-mail\n\n") + (mew-insert "Server:\t\t%s\n" server) + (mew-insert "Size:\t%s bytes\n" size) + (insert "\n") + ;; picked up source from 'mew-send + (mew-insert-manual + "To send this mail, type " + "'\\\\[mew-summary-execute-external]'.\n")))) + +(defun mew-ext-mail-server-ext (cache begin end &optional params) + (let* ((server (mew-syntax-get-param params "server")) + (subject (mew-syntax-get-param params "subject")) + (syntax (mew-ext-decode-message-header cache begin end)) + (start (mew-syntax-get-begin syntax))) + (mew-summary-send server nil subject) + (goto-char (point-max)) + (mew-insert-buffer-substring cache start end) + (mew-draft-make-message))) + +(defun mew-ext-decode-message-header (cache begin end) + (let (syntax start) + (with-current-buffer cache + (save-restriction + (narrow-to-region begin end) + (goto-char (point-min)) + (setq syntax (mew-decode-mime-header)) + (setq start (point))) + (mew-syntax-set-key syntax 'phantom) + (mew-syntax-set-begin syntax start) + (mew-syntax-set-end syntax end) + syntax))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mew-ext-url (cache begin end &optional params) + (mew-elet + (let* ((url (mew-syntax-get-param params "url")) + (size (mew-syntax-get-param params "size")) + (process-connection-type mew-connection-type1) + (syntax (mew-ext-decode-message-header cache begin end)) + (mct (car (mew-syntax-get-ct syntax))) + (spec mew-prog-text/html-ext) + (prog (mew-progspec-get-prog spec))) + (mew-erase-buffer) + (insert "# # ###### #\n" + "# # # # #\n" + "# # # # #\n" + "# # ###### #\n" + "# # # # #\n" + "# # # # #\n" + " ##### # # #######\n" + "\n\n") + (mew-insert "URL:\t\t%s\n" url) + (mew-insert "Content-Type:\t%s\n" mct) + (mew-insert "Size:\t%s bytes\n" size) + (mew-insert "Operation:\t%s\n" (or prog "not defined")) + (insert "\n") + (mew-insert-manual + "To operate this URL, type " + "'\\\\[mew-summary-execute-external]'.\n")))) + +(defun mew-ext-url-ext (cache begin end &optional params) + (let* ((url (mew-syntax-get-param params "url")) + (process-connection-type mew-connection-type1) + (spec mew-prog-text/html-ext) + (prog (mew-progspec-get-prog spec)) + (args (mew-progsec-args-convert (mew-progspec-get-args spec) url))) + (apply 'call-process prog nil nil nil args))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; +;; include +;; + +(defun mew-ext-include-local-file (params) + (mew-flet + (let* ((file (mew-syntax-get-param params "name"))) + (if (file-exists-p file) + (mew-insert-file-contents file))))) + +(provide 'mew-ext) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-ext.el ends here diff --git a/elpa/mew-20150813.2354/mew-fib.el b/elpa/mew-20150813.2354/mew-fib.el new file mode 100644 index 00000000..385f95d6 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-fib.el @@ -0,0 +1,123 @@ +;;; mew-fib.el --- Filling blanks for Mew + +;; Author: Yoshinari NOMURA +;; Created: Nov 29, 1994 + +;;; Code: + +(require 'mew-func) + +(defvar mew-fib-item-alist nil) + +(defun mew-fib-split (str) + (let (ret match) + (while (string-match "[\t \n]*\\([^,]+\\)" str) + (setq match (substring str (match-beginning 1) (match-end 1))) + (setq str (substring str (match-end 0))) + (setq match (if (string-match "[\t \n]+$" match) + (substring match 0 (match-beginning 0)) + match)) + (setq ret (cons match ret))) + (nreverse ret))) + +(defun mew-fib-make-alist () + (let ((fib-file (expand-file-name mew-fib-item-file)) + item val ret tmp-val) + (setq mew-fib-item-alist nil) + (with-temp-buffer + (if (file-exists-p fib-file) + (mew-insert-file-contents fib-file)) + (goto-char (point-min)) + (delete-matching-lines "^[ \t]*[;#%]") + (while (re-search-forward "^\\([^:]+\\):[ \t]*\\(.*\\)$" nil t) + (setq item (mew-buffer-substring (match-beginning 1) (match-end 1)) + tmp-val (mew-buffer-substring (match-beginning 2) (match-end 2)) + val (if (string= tmp-val "") val tmp-val) + ret (append ret (mapcar (lambda (arg) (cons (downcase arg) val)) + (mew-fib-split item)))))) + ret)) + +(defun mew-fib-fill-default () + "Fill |>item<| according to the information from .mew-fib" + (interactive) + (save-excursion + (let (begin end str) + (setq mew-fib-item-alist (mew-fib-make-alist)) + (goto-char (point-min)) + (while (re-search-forward "|>\\([^<]+\\)<|" nil t) + (setq begin (match-beginning 1) + end (match-end 1) + str (mew-buffer-substring begin end)) + (delete-region begin end) + (backward-char 2) + (insert (or (cdr (assoc (downcase str) mew-fib-item-alist)) str)))))) + +(defun mew-fib-delete-frame () + "Delete all quotations, '|>' and '<|'. This is the finishing stroke." + (interactive) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "|>\\|<|" nil t) + (replace-match "" nil t)))) + +(defun mew-fib-flush-input () + "Flush the fib item on the current point." + (interactive) + (save-excursion + (let ((ptr (point))) + (if (and (search-backward "|>" nil t) + (looking-at "|>\\([^<]+\\)<|") + (>= ptr (match-beginning 1)) + (<= ptr (match-end 1))) + (delete-region (match-beginning 1) + (match-end 1)))))) + +(defun mew-fib-next-item () + "Jump to the next fib item." + (interactive) + (if (re-search-forward "|>\\([^<]+\\)<|" nil t) + (backward-char 2) + (goto-char (point-min)) + (re-search-forward "|>\\([^<]+\\)<|" nil t))) + +(defun mew-fib-previous-item () + "Jump to the previous fib item." + (interactive) + (if (re-search-backward "|>\\([^<]+\\)<|" nil t) + (forward-char 2) + (goto-char (point-max)) + (re-search-backward "|>\\([^<]+\\)<|" nil t))) + +(provide 'mew-fib) + +;;; Copyright Notice: + +;; Copyright (C) 1994-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-fib.el ends here diff --git a/elpa/mew-20150813.2354/mew-func.el b/elpa/mew-20150813.2354/mew-func.el new file mode 100644 index 00000000..5e0b1814 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-func.el @@ -0,0 +1,1669 @@ +;;; mew-func.el --- Basic functions for Mew + +;; Author: Kazu Yamamoto +;; Created: Mar 23, 1997 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mode +;;; + +(defun mew-summary-p () + (eq major-mode 'mew-summary-mode)) + +(defun mew-virtual-p () + (eq major-mode 'mew-virtual-mode)) + +(defun mew-message-p () + (eq major-mode 'mew-message-mode)) + +(defun mew-draft-p () + (eq major-mode 'mew-draft-mode)) + +(defun mew-header-p () + (eq major-mode 'mew-header-mode)) + +(defun mew-draft-or-header-p () + (memq major-mode '(mew-draft-mode mew-header-mode))) + +(defun mew-selection-p () + (eq (mew-vinfo-get-mode) 'selection)) + +(defun mew-thread-p () + (eq (mew-vinfo-get-mode) 'thread)) + +(defun mew-summary-or-virtual-p () + (or (mew-summary-p) (mew-virtual-p))) + +(defun mew-virtual-for-one-summary () + (mew-vinfo-get-physical-folder)) + +(defun mew-pickable-p () + (or (mew-summary-p) (mew-virtual-for-one-summary))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; List functions +;;; + +(defun mew-case-equal (str1 str2) + (string= (downcase str1) (downcase str2))) + +(defun mew-folder-recursive-match (key folder) + "Initial substring match for folders. +If FOLDER is a sub-folder of KEY or KEY itself, t is returned." + ;; file-name-as-directory should be first + ;; because the path separator may be regex-non-safe. + (let ((regex (if (string-match "^[-+%$]$" key) + (mew-folder-regex key) + (mew-folder-regex (file-name-as-directory key))))) + (string-match regex (file-name-as-directory folder)))) + +(defun mew-member-case-equal (str list) + "Return the position equal to STR in LIST. Case is ignored." + (let ((n 0) (dstr (downcase str))) + (catch 'member + (dolist (x list) + (if (string= (downcase x) dstr) (throw 'member n)) + (setq n (1+ n)))))) + +(defun mew-member* (x list) + "Member in a nested list." + (catch 'found + (dolist (ent list) + (if (consp ent) + (if (mew-member* x ent) (throw 'found t)) + (if (equal x ent) (throw 'found t)))))) + +(defun mew-member-match (str list &optional ignore-case) + "Return the position matched to STR in LIST. If +IGNORE-CASE is t, matching is performed by ignoring case." + (let ((n 0) (case-fold-search ignore-case)) + (catch 'member + (dolist (x list) + (if (string-match x str) (throw 'member n)) + (setq n (1+ n)))))) + +(defun mew-member-match2 (regex list &optional ignore-case) + (let ((case-fold-search ignore-case)) + (catch 'member + (dolist (x list) + (if (string-match regex x) (throw 'member x)))))) + +(defun mew-uniq-list (lst) + "Destructively uniqfy elements of LST. +This is O(N^2). So, do not use this function with a large LST." + (let ((tmp lst)) + (while tmp (setq tmp (setcdr tmp (delete (car tmp) (cdr tmp)))))) + lst) + +(defun mew-uniq-alist (alist) + "Uniqfy elements of ALIST." + (let ((vec (make-vector 511 0)) ;; hash + str ret) + (dolist (ent alist) + (setq str (car ent)) + (cond + ((not (stringp str)) + (setq ret (cons ent ret))) + ((intern-soft str vec) + ()) + (t + (setq ret (cons ent ret)) + (intern str vec)))) + (nreverse ret))) + +(defun mew-delete (key alist) + "Destructively delete elements whose first member is equal to key" + (if (null key) + alist + (let (ret) + (while (and (listp (nth 0 alist)) (equal (car (nth 0 alist)) key)) + (setq alist (cdr alist))) + (setq ret alist) + (while alist ;; cannot use dolist + (if (and (listp (nth 1 alist)) (equal (car (nth 1 alist)) key)) + (setcdr alist (cdr (cdr alist))) + (setq alist (cdr alist)))) + ret))) + +(defmacro mew-ntake (n lst) + `(if (> (length ,lst) ,n) (setcdr (nthcdr (1- ,n) ,lst) nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Associative list functions +;;; + +(defun mew-assoc-equal (key alist nth &optional equal-func) + (let ((func (or equal-func 'equal)) + n) + (catch 'loop + (dolist (a alist) + (setq n (nth nth a)) + (if (or (funcall func n key) (eq n t)) (throw 'loop a)))))) + +(defun mew-assoc-case-equal (key alist nth) + (let ((skey (downcase key)) n) + (catch 'loop + (dolist (a alist) + (setq n (nth nth a)) + (if (or (and (stringp n) (string= (downcase n) skey)) + (eq n t)) + (throw 'loop a)))))) + +(defun mew-assoc-match (key alist nth) + "Return list in ALIST that KEY regex is matched to its NTH element. +Case is ignored. Note that the NTH element is 't', +the list is always selected." + (let ((case-fold-search t) n) + (catch 'loop + (dolist (a alist) + (setq n (nth nth a)) + (if (or (and (stringp n) (string-match key n)) + (equal n key) (eq n t)) + (throw 'loop a)))))) + +(defun mew-assoc-match2 (key alist nth) + "Return list in ALIST whose NTH regex is matched to KEY. +Case is ignored. Note that the NTH element is 't', +the list is always selected." + (let ((case-fold-search t) n) + (catch 'loop + (dolist (a alist) + (setq n (nth nth a)) + (if (or (and (stringp n) (string-match n key)) + (equal n key) (eq n t)) + (throw 'loop a)))))) + +(defun mew-assoc-match3 (key alist nth) + "Return list in ALIST whose NTH regex is matched to KEY. +Case is ignored. Note that the NTH element is 't', +the list is always selected. The deference from mew-assoc-match2 +is that this returns the position of a selected list in addition +to the list itself." + (let ((case-fold-search t) (i 0) n) + (catch 'loop + (dolist (a alist) + (setq n (nth nth a)) + (if (or (and (stringp n) (string-match n key)) + (equal n key) (eq n t)) + (throw 'loop (cons i a))) + (setq i (1+ i)))))) + +(defun mew-assoc-member (key lol nth) + "Return a list member of LoL whose NTH list contains +a member equal to KEY." + (mew-assoc-member-base key lol nth 'member)) + +(defun mew-assoc-member-case-equal (key lol nth) + "Return a list member of LoL whose NTH list contains +a member equal to KEY ignoring case." + (mew-assoc-member-base key lol nth 'mew-member-case-equal)) + +(defun mew-assoc-member-base (key lol nth func) + "Return a list member of LoL whose NTH list contains KEY +in the context of FUNC." + (catch 'loop + (dolist (l lol) + (if (and (listp (nth nth l)) (funcall func key (nth nth l))) + (throw 'loop l))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; backward compatibility of alist +;;; + +(defalias 'mew-alist-get-key 'car) +(defun mew-alist-get-value (ent) + (let ((value (cdr ent))) + (if (consp value) + (car value) ;; new + value))) ;; old + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; getting next +;;; + +(defun mew-get-next (LIST MEM) + "Return of a member in LIST which is the next member of MEM." + (let (frst next crnt) + (setq frst (car LIST)) + (setq LIST (cdr LIST)) + (setq next (car LIST)) + (if (equal frst MEM) + (if next next frst) + (catch 'loop + (while LIST ;; cannot use dolist + (setq crnt next) + (setq LIST (cdr LIST)) + (setq next (car LIST)) + (if (equal crnt MEM) + (throw 'loop (if next next frst)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Modifying list +;;; + +(defmacro mew-add-first (variable value) + `(setq ,variable (cons ,value ,variable))) + +(defmacro mew-addq (variable value) + `(if (and ,value (not (member ,value ,variable))) + (setq ,variable (cons ,value ,variable)))) + +(defmacro mew-insert-after (variable value key) + `(let ((var ,variable)) + (catch 'loop + (while var ;; cannot use dolist + (if (equal (nth 0 (car var)) ,key) + (throw 'loop (setcdr var (cons ,value (cdr var))))) + (setq var (cdr var)))))) + +(defmacro mew-replace-with (variable value key) + `(let ((var ,variable)) + (catch 'loop + (while var ;; cannot use dolist + (if (equal (nth 0 (car var)) ,key) + (throw 'loop (setcar var ,value))) + (setq var (cdr var)))))) + +(defmacro mew-remove-entry (variable key) + `(let ((crn ,variable) prv) + (if (equal (nth 0 (car crn)) ,key) + (setq ,variable (cdr crn)) + (setq prv crn) + (setq crn (cdr crn)) + (catch 'loop + (while crn ;; cannot use dolist + (if (equal (nth 0 (car crn)) ,key) + (throw 'loop (setcdr prv (cdr crn)))) + (setq prv crn) + (setq crn (cdr crn))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; String +;;; + +(defun mew-make-string (len) + (make-string len ?a)) + +(defun mew-replace-character (string from to) + "Replace characters equal to FROM to TO in STRING." + (dotimes (cnt (length string) string) + (if (char-equal (aref string cnt) from) + (aset string cnt to)))) + +(defun mew-replace-white-space (string) + "Replace white characters to a space." + (while (string-match "[\n\t]+" string) + (setq string (replace-match " " nil t string))) + (while (string-match " +" string) + (setq string (replace-match " " nil t string))) + string) + +(defun mew-replace-white-space2 (string) + "Replace white characters to under score." + (while (string-match "[\n\t\r ]+" string) + (setq string (replace-match "_" nil t string))) + string) + +(defun mew-capitalize (ostr) + "Syntax table independent version of capitalize. +Words are separated by '/' and '-'." + (let* ((len (length ostr)) + (nstr (mew-make-string len)) + (topp t) c) + (dotimes (i len nstr) + (setq c (aref ostr i)) + (cond + (topp + (aset nstr i (upcase c)) + (setq topp nil)) + ((or (char-equal c ?/) (char-equal c ?-)) + (aset nstr i c) + (setq topp t)) + (t + (aset nstr i (downcase c))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Insertion +;;; + +(defun mew-insert (form str) + (when str + (if form + (insert (format form str)) + (insert str)))) + +(defun mew-insert-message (fld msg rcs size) + (let ((file (mew-expand-msg fld msg))) + (cond + ((not (file-readable-p file)) + (error "%s does not exist" (mew-concat-folder fld msg))) + ((= (mew-file-get-size file) 0) + (error "The size of %s is 0" (mew-concat-folder fld msg))) + ((file-readable-p file) + (let ((old-cs (and (boundp 'buffer-file-coding-system) + buffer-file-coding-system))) + (mew-frwlet rcs mew-cs-dummy + (mew-insert-file-contents file nil 0 size)) + (if (boundp 'buffer-file-coding-system) + (setq buffer-file-coding-system old-cs))) + ;; return physical size + (cons (mew-file-get-time file) (mew-file-get-size file)))))) + +(defun mew-insert-manual (&rest args) + (insert (substitute-command-keys (apply 'concat args)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Stolen form Perl +;;; + +(defun mew-join (separator string-list) + (mapconcat 'identity string-list separator)) + +(defun mew-split (str sepchar) + "Return a list of strings splitting STR with SEPCHAR." + (let ((len (length str)) (start 0) ret) + (dotimes (i len) + (when (char-equal (aref str i) sepchar) + (setq ret (cons (substring str start i) ret)) + (setq start (1+ i)))) + (if (/= start len) + (setq ret (cons (substring str start) ret))) + (nreverse ret))) + +(defun mew-remove-single-quote (str) + (let* ((len (length str)) + (ret (mew-make-string len)) + (j 0)) + (dotimes (i len) + (unless (char-equal (aref str i) ?') + (aset ret j (aref str i)) + (setq j (1+ j)))) + (substring ret 0 j))) + +(defun mew-split-quoted (str sepchar &optional qopen qclose no-single) + "Return a list of strings splitting STR with SEPCHAR. +SEPCHARs in double-quoted strings are ignored. +If QUOTEDCHAR is provided, SEPCHARs between QOPEN and QCLOSE are +also ignored." + (let ((qlevel 0) (len (length str)) (start 0) dblq sub ret c) + (if (and qopen (not qclose)) (setq qclose qopen)) + (dotimes (i len) + (setq c (aref str i)) + (cond + ((char-equal ?\\ c) + (setq i (1+ i))) + ((or (char-equal ?\" c) (and (not no-single) (char-equal ?' c))) + (setq dblq (not dblq))) + ((and qopen (char-equal c qopen)) + (setq qlevel (1+ qlevel))) + ((and qclose (char-equal c qclose)) + (setq qlevel (1- qlevel))) + ((char-equal c sepchar) + (unless (or dblq (>= qlevel 1)) + (setq sub (substring str start i)) + (unless no-single + (setq sub (mew-remove-single-quote sub))) + (setq ret (cons sub ret)) + (setq start (1+ i)))))) + (when (/= start len) + (setq sub (substring str start)) + (unless no-single + (setq sub (mew-remove-single-quote sub))) + (setq ret (cons sub ret))) + (nreverse ret))) + +(defun mew-chop (str) + "Split off preceding and following white spaces." + (let ((i 0) (j (length str)) c) + (catch 'loop + (while (< i j) + (setq c (aref str i)) + (if (or (char-equal c mew-sp) (char-equal c ?\t)) + (setq i (1+ i)) + (throw 'loop nil)))) + (setq j (1- j)) + (catch 'loop + (while (< i j) + (setq c (aref str j)) + (if (or (char-equal c mew-sp) (char-equal c ?\t)) + (setq j (1- j)) + (throw 'loop nil)))) + (substring str i (1+ j)))) + +(defun mew-quote-string (str qchar targets) + "If characters in STR is a member of TARGETS, QCHAR is prepended to them." + (let* ((len (length str)) + (ret (mew-make-string (* len 2))) + (j 0) c) + (dotimes (i len) + (setq c (aref str i)) + (when (member c targets) + (aset ret j qchar) + (setq j (1+ j))) + (aset ret j c) + (setq j (1+ j))) + (substring ret 0 j))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder +;;; + +(defun mew-folder-regex (folder) + (concat "^" (regexp-quote folder))) + +;; + +(defun mew-case:folder-case (case:folder) + "Extract case from case:folder. If case does not exist, nil is returned." + ;; "case" must be distinguished from drive + (if (string-match mew-regex-case1 case:folder) + (mew-match-string 1 case:folder))) + +(defun mew-case:folder-folder (case:folder) + "Extract folder from case:folder." + ;; "case" must be distinguished from drive + (if (string-match mew-regex-case1 case:folder) + (mew-match-string 3 case:folder) + case:folder)) + +(defun mew-case-folder (case folder) + "Concat case and folder to produce case:folder. +If case is \"default\", it is not prepended." + (if (and case + (not (string= case mew-case-default)) + (mew-folder-remotep folder)) + (concat case ":" folder) + folder)) + +;; + +(defun mew-folder-absolutep (folder) + (or (string-match mew-regex-file-absolute folder) + (string-match mew-regex-drive-letter folder))) + +(defun mew-folder-localp (folder) + (string-match "^\\+" folder)) + +(defun mew-folder-remotep (folder) + (string-match "^[-%$]" folder)) + +(defun mew-folder-popp (folder) + (string-match "^\\$" folder)) + +(defun mew-folder-nntpp (folder) + (string-match "^-" folder)) + +(defun mew-folder-imapp (folder) + (string-match "^%" folder)) + +;; (concat "^" (regexp-quote mew-folder-virtual)) +(defun mew-folder-virtualp (folder) + (string-match "^\\*" folder)) + +(defun mew-virtual-thread-p (vfolder) + (with-current-buffer vfolder + (mew-thread-p))) + +;; + +(defun mew-folder-prefix (folder) + (substring folder 0 1)) + +(defun mew-folder-string (folder) + (substring folder 1)) + +(defun mew-string-to-local (folder) + (concat mew-folder-local folder)) + +(defun mew-folder-path-to-folder (path &optional has-proto) + (let (case proto) + ;; depends on folder + (mew-set '(case proto) (mew-summary-case-proto)) + (if (mew-folder-localp proto) + (if has-proto + path + (mew-string-to-local path)) + (let* ((base-path (mew-folder-string + (mew-path-to-folder + (mew-expand-folder (mew-case-folder case proto))))) + (path-regex (concat "^" (regexp-quote base-path))) + (no-proto-path path)) + (when has-proto + (setq no-proto-path (mew-case:folder-folder no-proto-path)) + (setq no-proto-path (mew-folder-string no-proto-path))) + (if (string-match path-regex no-proto-path) + (mew-case-folder + case + (concat proto (substring no-proto-path (match-end 0)))) + path))))) + +;; + +(defun mew-folder-to-selection (folder) + (concat mew-folder-virtual (mew-folder-basename folder))) + +(defun mew-folder-to-thread (folder) + (concat mew-folder-virtual (mew-folder-basename folder) mew-folder-virtual)) + +(defun mew-folder-basename (folder) + ;; Upper functions may use string-match. + ;; So, string-match must not be used here. + (if (eq (aref folder 0) ?*) + (if (eq (aref folder (1- (length folder))) ?*) + (substring folder 1 -1) + (substring folder 1)) + folder)) + +;; + +(defun mew-summary-physical-folder () + (cond + ((mew-summary-p) + (mew-summary-folder-name 'ext)) + ((mew-virtual-p) + (mew-vinfo-get-physical-folder)))) + +;; + +(defun mew-local-to-dir (folder) + (if (string-match "^[+]" folder) + (substring folder 1) + folder)) + +;; + +(defun mew-folder-inboxp (folder) + (member folder mew-inbox-folders)) + +(defun mew-folder-queuep (folder) + (member folder mew-queue-folders)) + +(defun mew-folder-postqp (folder) + (member folder mew-postq-folders)) + +(defun mew-folder-draftp (folder) + (equal folder mew-draft-folder)) + +;; + +(defun mew-folder-imap-queuep () + (string= (mew-sinfo-get-folder) + (mew-imap-queue-folder (mew-sinfo-get-case)))) + +;; + +(defun mew-canonicalize-folder (folder) + (cond + ((mew-folder-localp folder) + folder) + ((mew-folder-imapp folder) + folder) + ((file-name-absolute-p folder) + folder) + (t + (mew-string-to-local folder)))) + +(defun mew-path-to-folder (path) + (let ((regex (concat "^" (regexp-quote (file-name-as-directory (expand-file-name mew-mail-path)))))) + (if (string-match regex path) + (mew-string-to-local (substring path (match-end 0))) + path))) + +(defun mew-canonicalize-case-folder (case:folder) + (let ((case (mew-case:folder-case case:folder)) + (folder (mew-case:folder-folder case:folder)) + len) + (cond + ((mew-folder-localp folder) (directory-file-name folder)) + ((mew-folder-absolutep folder)(directory-file-name folder)) + ((mew-folder-virtualp folder) folder) + (t + (if (null case) + (setq folder case:folder) + (if (string= case mew-case-default) + (progn + (setq case nil) + (setq case:folder folder)))) + (cond + ((mew-folder-popp folder) case:folder) + ((mew-folder-imapp folder) + (mew-imap-directory-file-name + case:folder (or case ;; visit + mew-inherit-case))) ;; refile + ((mew-folder-nntpp folder) + (setq len (1- (length case:folder))) + (if (char-equal (aref case:folder len) ?.) + (substring case:folder 0 len) + case:folder))))))) + +;; + +(defun mew-expand-folder2 (case:folder) + "Expanding FOLDER to a relative path to '+'" + (let ((case (mew-case:folder-case case:folder)) + (folder (mew-case:folder-folder case:folder)) + subdir) + ;; The length of "case" must be longer than or equal to 2. + (setq subdir (mew-folder-string folder)) + (cond + ((mew-folder-popp folder) + (mew-concat-folder (mew-pop-folder case) subdir)) + ((mew-folder-nntpp folder) + (mew-concat-folder (mew-nntp-folder case) subdir)) + ((mew-folder-imapp folder) + (mew-concat-folder (mew-imap-folder case) + (mew-imap-expand-folder + case + (mew-imap-utf-7-encode-string subdir)))) + (t folder)))) + +(defun mew-expand-folder (folder) + "Expanding FOLDER to its absolute path" + (when (stringp folder) + (let (dir) + (setq folder (mew-expand-folder2 folder)) + (if (mew-folder-localp folder) + (setq dir (expand-file-name (mew-folder-string folder) mew-mail-path)) + ;; absolute path + ;; "C:/" -> t, "C:" -> nil , "CC:/" -> nil + (setq dir (expand-file-name folder))) + dir))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Suffix support +;;; + +(defvar mew-use-suffix nil) + +(defun mew-msg-new-filename (file) + (if mew-use-suffix + (format "%s%s" file mew-suffix) + file)) + +(defun mew-msg-get-filename (file) + (let ((sfile (format "%s%s" file mew-suffix))) + (if (file-exists-p sfile) + sfile + file))) + +(defun mew-expand-msg (folder message) + (let ((file (expand-file-name message (mew-expand-folder folder)))) + (mew-msg-get-filename file))) + +(defun mew-expand-new-msg (folder message) + (mew-msg-new-filename (expand-file-name message (mew-expand-folder folder)))) + +(defun mew-expand-file (folder file) + (expand-file-name file (mew-expand-folder folder))) + +(defun mew-concat-folder (folder subfolder) + (concat (file-name-as-directory folder) subfolder)) + +(defun mew-concat-folder2 (folder subfolder case) + (if (mew-folder-imapp folder) + (concat (mew-imap-file-name-as-directory folder case) subfolder) + (concat (file-name-as-directory folder) subfolder))) + +(defun mew-dir-messages (dir &optional regex full) + ;; directory_files uses ENCODE_FILE() for DIR and + ;; DECODE_FILE() for results(FILES). + ;; Both ENCODE_FILE() and DECODE_FILE() are quite slow. + ;; Since DECODE_FILE() is used many times, directory_files is + ;; too slow when {default-,}file-name-coding-system are non-nil. + ;; If {default-,}file-name-coding-system are bound to nil, + ;; ENCODE_FILE() and DECODE_FILE() are skipped, resulting speed up. + ;; So, we need to encode DIR by ourselves. + (let ((edir (expand-file-name dir)) + (cs default-file-name-coding-system)) + (setq edir (mew-cs-encode-string edir cs)) + (or regex (setq regex mew-regex-message-files)) + (mew-alet + (directory-files edir full regex 'no-sort)))) + +(defun mew-folder-messages (folder) + (let* ((dir (mew-expand-folder folder)) + msgs nums) + (when (file-directory-p dir) + (setq msgs (mew-dir-messages dir)) + (setq nums (sort (mapcar 'string-to-number msgs) '<)) + (mapcar 'number-to-string nums)))) + +(defun mew-folder-new-message (folder &optional num-only cache) + (let* ((dir (mew-expand-folder folder)) + (regex (if cache mew-regex-message-files3 mew-regex-message-files)) + (max 0) + cur maxfile maxpath) + ;; xxx create if there is no directory? + (when (file-directory-p dir) + (dolist (msg (mew-dir-messages dir regex)) + (setq cur (string-to-number (file-name-sans-extension msg))) + (if (> cur max) (setq max cur))) + (setq max (1+ max)) + (setq maxfile (number-to-string max)) + (setq maxpath (mew-expand-new-msg folder maxfile)) + (while (get-file-buffer maxpath) ;; xxx + ;; file not exist but there is a buffer. + (setq max (1+ max)) + (setq maxfile (number-to-string max)) + (setq maxpath (mew-expand-new-msg folder maxfile))) + (while (file-exists-p maxpath) + (setq maxfile (read-string (format "%s/%s exists. Input a message number: " max folder))) + (while (not (string-match mew-regex-message-files maxfile)) + (setq maxfile (read-string "Input NUMBER: "))) + (setq maxpath (mew-expand-new-msg folder maxfile))) + (if num-only + (mew-msg-new-filename maxfile) + maxpath)))) + +(defun mew-touch-folder (fld) + (when (stringp mew-summary-touch-file) + (let ((file (mew-expand-file fld mew-summary-touch-file))) + (when (file-writable-p file) + (write-region "touched by Mew." nil file nil 'no-msg) + (mew-set-file-modes file))))) + +;; this kind of defmacro can't recurse +;; if +foo exists and we insert +foo/bar, +;; +foo/ should be inserted, too. But +foo/ does not match to +foo... +(defmacro mew-folder-insert (folder lst subdir) + `(unless (mew-assoc-equal ,folder ,lst 0) + (let ((case-fold-search nil) + (max (1- (length ,lst))) + (pair (mew-folder-func ,folder ,subdir)) + (min 0) + mid crr prv) + (while (> (- max min) 20) ;; 20 is enough? + (setq mid (/ (+ min max) 2)) + (if (string< (car (nth mid ,lst)) ,folder) + (setq min mid) + (setq max mid))) + (setq crr (nthcdr min ,lst)) + (while (and crr (string< (car (car crr)) ,folder)) + (setq prv crr) + (setq crr (cdr crr))) + (if prv + (setcdr prv (cons pair crr)) + (setq ,lst (cons pair crr)))))) + +(defmacro mew-folder-delete (folder lst) + `(setq ,lst (delete (assoc ,folder ,lst) ,lst))) + +(defun mew-folder-node-p (folder &optional case) + (cond + ((mew-folder-localp folder) + (let* ((dir (file-name-as-directory folder)) + (regex (concat "^" (regexp-quote dir)))) + (mew-assoc-match regex (mew-local-folder-alist) 0))) + ((mew-folder-imapp folder) + (let* ((dir (mew-imap-file-name-as-directory folder case)) + (regex (concat "^" (regexp-quote dir)))) + (mew-assoc-match regex (mew-imap-folder-alist case) 0))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder spec +;;; + +(defconst mew-folder-spec-type + '((regex . string-match) + (recursive . mew-folder-recursive-match) + (string . string=))) + +(defun mew-folder-spec-func (type) + (or (cdr (assq type mew-folder-spec-type)) 'string=)) + +(defun mew-folder-spec (folder lst str-type lst-type) + (let ((str-func (mew-folder-spec-func str-type)) + (lst-func (mew-folder-spec-func lst-type)) + keys values ret) + (setq folder (mew-case:folder-folder folder)) + (catch 'loop + (dolist (ent lst) + (setq keys (car ent)) + (setq values (cdr ent)) + (cond + ((eq keys t) + (throw 'loop (setq ret values))) + ((stringp keys) + (if (funcall str-func keys folder) + (throw 'loop (setq ret values)))) + ((listp keys) + (dolist (key keys) + (if (funcall lst-func key folder) + (throw 'loop (setq ret values)))))))) + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Directory +;;; + +(defun mew-parent-directory (path) + (directory-file-name (file-name-directory path))) + +(defun mew-rename-directory (src dst) + (let ((parent (mew-parent-directory (directory-file-name dst)))) + (mew-make-directory parent) + (rename-file src dst))) + +(defun mew-make-directory (path) + (let ((parent (mew-parent-directory path))) + (unless (file-directory-p parent) + (mew-make-directory parent)) + (cond + ((file-directory-p path) + ()) ;; do nothing + ((file-exists-p path) + (delete-file path) + (make-directory path)) + (t + (make-directory path))) + (if (/= mew-folder-mode (file-modes path)) + (set-file-modes path mew-folder-mode)))) + +(defun mew-delete-directory-recursively (dir) + (when (file-directory-p dir) + (dolist (file (directory-files dir 'full mew-regex-files 'no-sort)) + (cond + ((file-symlink-p file) + ;; never chase symlink which points a directory + (delete-file file)) + ((file-directory-p file) + (mew-delete-directory-recursively file)) + (t + (delete-file file)))) + (unless (directory-files dir 'full mew-regex-files 'no-sort) + (delete-directory dir)))) + +(defun mew-check-directory (dir) + (unless (file-directory-p dir) + (unless (file-exists-p dir) + (mew-make-directory dir)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; File existence +;;; + +(defun mew-which (file path) + (catch 'loop + (dolist (dir path) + (if (file-exists-p (expand-file-name file dir)) + (throw 'loop (expand-file-name file dir)))))) + +(defun mew-which-el (elfile) + (or (mew-which (concat elfile ".el") load-path) + (mew-which (concat elfile ".elc") load-path))) + +(defvar mew-which-exec-suffixes '("")) + +(defun mew-which-exec (execfile) + (let (file) + (catch 'detect + (dolist (suffix mew-which-exec-suffixes) + (when (setq file (mew-which (concat execfile suffix) exec-path)) + (throw 'detect file)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; File attribute +;;; + +;; Functions to get other attributes are implemented in C level. + +(defun mew-file-get-links (file) + (let ((w32-get-true-file-link-count t)) ;; for Meadow + (nth 1 (file-attributes file)))) + +(defun mew-file-get-time (file) + (nth 5 (file-attributes file))) + +(defun mew-file-get-size (file) + (nth 7 (file-attributes file))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; File +;;; + +(defun mew-file-chase-links (file) + "Chase links in FILENAME until a name that is not a link. +Does not examine containing directories for links." + (let ((ret file) exp) + (while (setq exp (file-symlink-p ret)) + (setq ret (expand-file-name exp (file-name-directory ret)))) + ret)) + +(defun mew-file-from-home (str) + (if (string-match (expand-file-name mew-home) str) + (concat mew-home (substring str (match-end 0))) + str)) + +(defun mew-prepend-prefix (file prefix) + (if (file-name-absolute-p file) + (concat (file-name-directory file) prefix (file-name-nondirectory file)) + (concat prefix file))) + +(defun mew-rotate-log-files (file-name) + (let ((i 8) (file (expand-file-name file-name mew-conf-path))) + (when (and (file-exists-p file) + (>= (mew-file-get-size file) mew-log-max-size)) + (while (>= i 0) + (if (file-exists-p (format "%s.%d" file i)) + (rename-file (format "%s.%d" file i) + (format "%s.%d" file (1+ i)) t)) + (setq i (1- i))) + (rename-file file (format "%s.0" file))))) + +(defun mew-remove-drive-letter (file) + (if (string-match mew-regex-drive-letter file) + (substring file 2) + file)) + +(defun mew-get-file-modes (path) + (let* ((dir (file-name-directory path)) + (dirmode (file-modes dir))) + (logand dirmode mew-file-mode-mask))) + +(defun mew-set-file-modes (path) + (set-file-modes path (mew-get-file-modes path))) + +(defun mew-delete-file (file) + (if (and (stringp file) (file-exists-p file)) (delete-file file))) + +(defun mew-insert-file-contents (&rest args) + "A safe version of insert-file-contents. +This checks -*-coding:ctext;-*- internally when including a file." + (let ((after-insert-file-functions nil)) + ;; preventing after-insert-file-set-buffer-file-coding-system + (apply 'mew-insert-file-contents2 args))) + +(defun mew-insert-file-contents2 (&rest args) + "Mew version of insert-file-contents. +This sets buffer-file-coding-system." + (let ((auto-image-file-mode nil)) + (apply 'insert-file-contents args))) + +(defun mew-find-file-noselect (&rest args) + "A safe version of find-file-noselect. +This checks -*-coding:ctext;-*- internally when including a file. +But this does not set buffer-file-coding-system." + (let ((after-insert-file-functions nil)) + ;; preventing after-insert-file-set-buffer-file-coding-system + (apply 'mew-find-file-noselect2 args))) + +(defun mew-find-file-noselect2 (&rest args) + "A safe version of find-file-noselect. +This checks -*-coding:ctext;-*- internally when including a file +and sets buffer-file-coding-system." + (let ((auto-image-file-mode nil) + (format-alist nil) + (auto-mode-alist nil) + (enable-local-variables nil) + (find-file-hook nil) + (large-file-warning-threshold nil)) + (apply 'find-file-noselect args))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; temp name +;;; + +(defun mew-make-temp-name (&optional fname) + (unless (file-exists-p mew-temp-dir) + (mew-make-directory mew-temp-dir)) ;; just in case + (if fname + (let ((exist (file-exists-p (expand-file-name fname mew-temp-dir)))) + (if (and (not exist) + (or (not (featurep 'meadow)) + (string-match "^[ -~]+$" fname))) + (expand-file-name fname mew-temp-dir) + (if (string-match "\\.[ -~]+$" fname) + (concat (make-temp-name mew-temp-file) (mew-match-string 0 fname)) + (make-temp-name mew-temp-file)))) + (make-temp-name mew-temp-file))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Random +;;; + +(defvar mew-random-base-09 "0123456789") +(defvar mew-random-base-az "abcdefghijklmnopqrstuvwxwz") + +(defun mew-random () + (let* ((vec (recent-keys)) + (ran (+ (random) (emacs-pid))) + c) + (dotimes (i (length vec)) + (setq c (aref vec i)) + (if (integerp c) (setq ran (+ ran c)))) + (abs ran))) + +(defun mew-random-string (len nump) + (let* ((base (if nump mew-random-base-09 mew-random-base-az)) + (baselen (length base)) + (ret (mew-make-string len))) + (dotimes (i len ret) + (aset ret i (aref base (% (mew-random) baselen)))))) + +(defun mew-random-filename (dir len nump &optional suffix) + (let ((cnt 0) (max 20) ;; ad hoc + file filepath) + (setq file (concat (mew-random-string len nump) suffix)) + (setq filepath (expand-file-name file dir)) + (while (and (file-exists-p filepath) (< cnt max)) + (setq file (concat (mew-random-string len nump) suffix)) + (setq filepath (expand-file-name file dir)) + (setq cnt (1+ cnt))) + (if (file-exists-p filepath) + nil + filepath))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Buffer +;;; + +(defun mew-erase-buffer () + (mew-elet + (widen) + (erase-buffer) + (buffer-disable-undo))) + +(defun mew-remove-buffer (buf) + (if (and buf (get-buffer buf)) (kill-buffer buf))) + +(defmacro mew-elet (&rest body) + `(let ((buffer-read-only nil) + (inhibit-read-only t) + (after-change-functions nil) + (mark-active nil)) + ,@body)) + +(defun mew-push-mark () + "Set the mark for \\[exchange-point-and-mark]" + (let ((mark-active nil)) + (push-mark (point) t t))) + +(defun mew-region-bytes (beg end buf) + ;; string-bytes() acts differently on each Emacs. + ;; set-buffer-multibyte is also buggy. + ;; So, use this way. + (with-current-buffer buf + (if (fboundp 'string-as-unibyte) + (length (string-as-unibyte (mew-buffer-substring beg end))) + (- end beg)))) + +(defun mew-count-lines (beg end) + "Return number of lines between BEG and END." + (save-excursion + (goto-char beg) + (beginning-of-line) + (setq beg (point)) + (goto-char end) + (beginning-of-line) + (setq end (point)) + (if (or (not (mew-decode-syntax-p)) + (not (equal (mew-decode-syntax-buffer) (current-buffer)))) + (mew-count-lines1 beg end) + (let ((mbeg (mew-decode-syntax-begin)) + (mend (mew-decode-syntax-end))) + (if (or (<= end mbeg) (>= beg mend)) + (mew-count-lines1 beg end) + (+ (mew-count-lines1 beg mbeg) (mew-count-lines1 mend end))))))) + +(defun mew-count-lines1 (beg end) + (if (>= beg end) + 0 + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (if (not (and (mew-thread-p) mew-use-thread-separator)) + (- (buffer-size) (forward-line (buffer-size))) + (let ((regex mew-regex-thread-separator) + (lines 0)) + (while (not (eobp)) + (unless (looking-at regex) + (setq lines (1+ lines))) + (forward-line)) + lines))))) + +(defun mew-buffer-list (regex &optional listp mode) + (let (ret) + (dolist (buf (mapcar 'buffer-name (buffer-list))) + (when (and (string-match regex buf) + (or (not mode) + (and mode (get-buffer buf) + (with-current-buffer buf + (eq major-mode mode))))) + (if listp + (setq ret (cons (list buf) ret)) + (setq ret (cons buf ret))))) + (nreverse ret))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; process +;;; + +(defmacro mew-filter (&rest body) + `(let ((pbuf (process-buffer process)) ;; MUST use 'process' + (obuf (buffer-name)) + (inhibit-eol-conversion nil)) ;; \r\n as is + (if (and (bufferp pbuf) + (buffer-name pbuf)) ;; check a killed buffer + ;; must use buffer-name instead of current-buffer + ;; so that get-buffer can detect killed buffer. + (unwind-protect + (progn + ;; buffer surely exists. + (set-buffer (process-buffer process)) ;; necessary + ,@body) + (if (get-buffer obuf) + ;; the body sometimes kills obuf. + (set-buffer obuf)))))) + +(defun mew-start-process-disp (name buffer program &rest program-args) + (let ((disp (cdr (assq 'display (frame-parameters)))) + (process-environment (copy-sequence process-environment))) + (if disp (setenv "DISPLAY" disp)) + (apply 'start-process name buffer program program-args))) + +(defun mew-start-process-lang (name buffer program &rest program-args) + (let ((process-environment (copy-sequence process-environment))) + (setenv "LANGUAGE" "C") + (setenv "LC_ALL" "C") + (setenv "LANG" "C") + (apply 'start-process name buffer program program-args))) + +(defun mew-call-process-lang (prog &optional infile buffer display &rest args) + (let ((process-environment (copy-sequence process-environment))) + (setenv "LANGUAGE" "C") + (setenv "LC_ALL" "C") + (setenv "LANG" "C") + (apply 'call-process prog infile buffer display args))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Global info +;;; + +(defun mew-info (name) + (cond + ((vectorp name) name) ;; just for .mqi + ((stringp name) + (if (or (not (intern-soft name)) + (not (boundp (intern name)))) + (if (string-match "^mew-[^-]+-info-" name) + (let* ((sym (intern (concat (mew-match-string 0 name) "list"))) + (lst (symbol-value sym)) + (len (length lst))) + (set (intern name) (make-vector len nil))))) + (symbol-value (intern-soft name))))) + +(defun mew-info-defun (prefix lst) + (let ((i 0)) + (dolist (ent lst) + (fset (intern (concat prefix "get-" ent)) + `(lambda (arg) + (cond + ((stringp arg) (aref (mew-info arg) ,i)) + ((vectorp arg) (aref arg ,i))))) + (fset (intern (concat prefix "set-" ent)) + `(lambda (arg value) + (cond + ((stringp arg) (aset (mew-info arg) ,i value)) + ((vectorp arg) (aset arg ,i value))))) + (setq i (1+ i))))) + +(defun mew-info-clean-up (arg &optional start) + (let ((i (or start 0)) vec len) + (cond + ((stringp arg) (setq vec (mew-info arg))) + ((vectorp arg) (setq vec arg))) + (setq len (length vec)) + (while (< i len) + (aset vec i nil) + (setq i (1+ i))))) + +(defun mew-net-get-ssh-process (pnm) + (aref (mew-info pnm) 3)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Buffer local info +;;; + +(defun mew-blinfo (sym) + (let* ((name (symbol-name sym)) + (lname (concat name "-list")) + (lsym (intern lname)) + (lst (symbol-value lsym)) + (len (length lst))) + (set sym (make-vector len nil)) + (symbol-value sym))) + +(defun mew-blinfo-defun (blv-sym lst) + (let ((i 0)) + (dolist (ent lst) + (fset (intern (concat (symbol-name blv-sym) "-get-" ent)) + `(lambda () + (cond + ((null ,blv-sym) (aref (mew-blinfo (quote ,blv-sym)) ,i)) + ((vectorp ,blv-sym) (aref ,blv-sym ,i))))) + (fset (intern (concat (symbol-name blv-sym) "-set-" ent)) + `(lambda (value) + (cond + ((null ,blv-sym) (aset (mew-blinfo (quote ,blv-sym)) ,i value)) + ((vectorp ,blv-sym) (aset ,blv-sym ,i value))))) + (setq i (1+ i))))) + +(defvar mew-ainfo-list '("icon" "win-cfg")) +(mew-blinfo-defun 'mew-ainfo mew-ainfo-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Address +;;; + +(defun mew-get-my-address () + (or (mew-header-parse-address mew-from:) (mew-mail-address))) + +;; + +(defun mew-get-my-address-regex-list () + "This creates a list of regular expression used to tell +whether or not a given address is mine. The list is created +from (mew-user), (mew-mail-address), and 'mew-mail-address-list'." + (cons (concat "^" (regexp-quote (mew-user)) "$") + (cons (concat "^" (regexp-quote (mew-mail-address)) "$") + mew-mail-address-list))) + +(defun mew-is-my-address (addrs from) + (and from + (let ((case-fold-search t)) + (catch (quote match) + (car (mapcar (lambda (arg) (and (string-match arg from) + (throw (quote match) t))) + addrs)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Lisp load/save +;;; + +(defun mew-lisp-load (filename) + "Load lisp from FILENAME" + (let ((fullname (if (file-name-absolute-p filename) + filename + (expand-file-name filename mew-conf-path)))) + (if (file-readable-p fullname) + (with-temp-buffer + (mew-frwlet mew-cs-m17n mew-cs-dummy + (mew-insert-file-contents fullname)) + (goto-char (point-min)) + (condition-case nil + (read (current-buffer)) + (error ())))))) + +(defun mew-lisp-save (filename lisp &optional nobackup unlimit) + "Save LISP to FILENAME. LISP is truncated to mew-lisp-max-length +by side-effect." + (let* ((fullname (if (file-name-absolute-p filename) + filename + (expand-file-name filename mew-conf-path))) + (backname (concat fullname mew-backup-suffix)) + print-length print-level) ;; for Emacs 21 + (when (file-writable-p fullname) + (if nobackup + (mew-delete-file fullname) + (if (file-exists-p fullname) + (rename-file fullname backname 'override))) + (when (and (not unlimit) (> (length lisp) mew-lisp-max-length)) + (setq lisp (copy-sequence lisp)) ;; no side effect + (mew-ntake mew-lisp-max-length lisp)) + (with-temp-buffer + (if (> (length lisp) mew-lisp-max-length) + (print lisp (current-buffer)) + (pp lisp (current-buffer))) + (mew-frwlet mew-cs-dummy mew-cs-m17n + (write-region (point-min) (point-max) fullname nil 'no-msg))) + (mew-set-file-modes fullname)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Month +;;; + +(defvar mew-time-mon-alist + '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4) + ("May" . 5) ("Jun" . 6) ("Jul" . 7) ("Aug" . 8) + ("Sep" . 9) ("Oct" . 10) ("Nov" . 11) ("Dec" . 12))) + +(defun mew-time-mon-str-to-int (str) + (or (cdr (assoc (capitalize str) mew-time-mon-alist)) 0)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Time Zone +;;; + +;; Define symbol time zone defined in RFC822 only. +(defvar mew-time-tmzn-alist + '(("UT" . 0) ("GMT" . 0) + ("EST" . -5) ("EDT" . -4) + ("CST" . -6) ("CDT" . -5) + ("MST" . -7) ("MDT" . -6) + ("PST" . -8) ("PDT" . -7))) + +(defun mew-time-tmzn-str-to-int (str) + (cdr (assoc (upcase str) mew-time-tmzn-alist))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; RFC 822 +;;; Date: Wed, 26 Jul 2000 21:18:35 +0900 (JST) +;;; + +(defvar mew-time-rfc-regex + "\\([0-9]+\\)[ \t\n\r]+\\([a-zA-Z]+\\)[ \t\n\r]+\\([0-9]+\\)[ \t\n\r]+\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\([ \t\n\r]+\\([-+0-9a-zA-Z]+\\)\\)?") + +(defmacro mew-time-rfc-day () + '(string-to-number (substring s (match-beginning 1) (match-end 1)))) + +(defmacro mew-time-rfc-mon () + '(substring s (match-beginning 2) (match-end 2))) + +(defmacro mew-time-rfc-year () + '(string-to-number (substring s (match-beginning 3) (match-end 3)))) + +(defmacro mew-time-rfc-hour () + '(string-to-number (substring s (match-beginning 4) (match-end 4)))) + +(defmacro mew-time-rfc-min () + '(string-to-number (substring s (match-beginning 5) (match-end 5)))) + +(defmacro mew-time-rfc-sec () + '(if (match-beginning 7) + (string-to-number (substring s (match-beginning 7) (match-end 7))) + 0)) + +;; returns seconds +(defmacro mew-time-rfc-tmzn () + '(if (match-beginning 9) + (let ((tmzn (substring s (match-beginning 9) (match-end 9))) + int) + (cond + ((string-match "^[-+][0-9]+$" tmzn) + (setq int (string-to-number tmzn)) + (+ (* (/ int 100) 3600) (* (% int 100) 60))) + ((setq int (mew-time-tmzn-str-to-int tmzn)) + (* int 3600)) + (t 0))) + 0)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sort key for Date: +;;; + +;; "20000726121835" +(defun mew-time-ctz-to-sortkey (time) + (let ((system-time-locale "C")) + (format-time-string "%Y%m%d%H%M%S" time))) + +(defun mew-time-ctz-to-sortkey-invalid (sec min hour day mon year) + (format "%04d%02d%02d%02d%02d%02d" year mon day hour min sec)) + +;; "20000726121835" +(defun mew-time-rfc-to-sortkey (s &optional tzadj) + (if (string-match mew-time-rfc-regex s) + (let ((year (mew-time-rfc-year)) + (mon (mew-time-mon-str-to-int (mew-time-rfc-mon))) + (day (mew-time-rfc-day)) + (hour (mew-time-rfc-hour)) + (min (mew-time-rfc-min)) + (sec (mew-time-rfc-sec)) + (tmzn (mew-time-rfc-tmzn))) + (cond + ((< year 50) + (setq year (+ year 2000))) + ((< year 150) + (setq year (+ year 1900)))) + (if (or (< year 1970) (>= year 2038)) + ;; invalid data + (mew-time-ctz-to-sortkey-invalid sec min hour day mon year) + (setq sec (- sec tmzn)) + (if tzadj (setq sec (+ sec (car (current-time-zone))))) + (mew-time-ctz-to-sortkey (encode-time sec min hour day mon year)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; User friendly time +;;; + +(defun mew-time-tmzn-int () + (let ((tz (car (current-time-zone)))) + (if (< tz 0) + (format "-%02d%02d" (/ (- tz) 3600) (/ (% (- tz) 3600) 60)) + (format "+%02d%02d" (/ tz 3600) (/ (% tz 3600) 60))))) + +;; Wed, 26 Jul 2000 21:18:35 +0900 (JST) +(defun mew-time-ctz-to-rfc (time) + (let* ((system-time-locale "C") + ;; A bug of Emacs 22.3 on Windows + (time-zone-name (format-time-string "%Z" time)) + (date (format-time-string "%a, %d %b %Y %T %z" time))) + (if (string= time-zone-name "") + date + (concat date (format " (%s)" time-zone-name))))) + +;; 2000/07/12 16:22:30 +(defun mew-time-ctz-to-logtime (time) + (let ((system-time-locale "C")) + (format-time-string "%Y/%m/%d %H:%M:%S" time))) + +;; 20000712.155559 +(defun mew-time-ctz-to-msgid (time) + (let ((system-time-locale "C")) + (format-time-string "%Y%m%d.%H%M%S" time))) + +;; + +(defun mew-time-calc (new old) + (let ((million 1000000) + (sec (+ (* 65536 (- (nth 0 new) (nth 0 old))) + (- (nth 1 new) (nth 1 old)))) + (usec (- (nth 2 new) (nth 2 old)))) + (if (< usec 0) + (setq sec (1- sec) + usec (+ usec million)) + (if (>= usec million) + (setq sec (1+ sec) + usec (- usec million)))) + (+ sec (/ usec (float million))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Multibyte +;;; + +(defun mew-set-buffer-multibyte (arg) + (if (fboundp 'set-buffer-multibyte) + (set-buffer-multibyte arg))) + +(defun mew-set-string-multibyte (str) + (if (fboundp 'string-as-multibyte) + (string-as-multibyte str) + str)) + +(defun mew-multibyte-string-p (str) + (if (fboundp 'multibyte-string-p) + (multibyte-string-p str))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Network +;;; + +(defun mew-dot-insert () + (goto-char (point-min)) + (while (re-search-forward "^\\." nil t) + (insert ".") + (forward-line))) + +(defun mew-dot-delete () + (goto-char (point-max)) + (forward-line -1) + (delete-region (point) (point-max)) + (goto-char (point-min)) + (while (re-search-forward "^\\." nil t) + (delete-char -1) + (forward-line))) + +(defun mew-crlf-to-lf () + (while (search-forward "\r\n" nil t) (replace-match "\n" nil t))) + +(defun mew-lf-to-crlf () + (while (search-forward "\n" nil t) (replace-match "\r\n" nil t))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; sit-for +;;; + +(defun mew-redraw (&optional time) + (sit-for (or time 0))) + +(defmacro mew-rendezvous (who) + ;; Wait for the termination of WHO. + ;; Emacs does not provide synchronize mechanism with + ;; an asynchronous process. So, take this way. + `(while ,who + (sit-for 0.1) + ;; accept-process-output or sleep-for is not enough + (discard-input))) + +(defun mew-let-user-read () + (sit-for 1.5)) + +(defun mew-warn (&rest msg) + (apply 'message msg) + (ding) + (mew-let-user-read)) + +(defun mew-timing () + (sit-for 0.01)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Multiple set +;;; + +(defun mew-set (vars vals) + (dolist (var vars) + (if var (set var (car vals))) ;; var can be nil to skip + (setq vals (cdr vals)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Structure +;;; + +;;; +;;; Some old code uses assoc. So, you cannot put the structure name +;;; into the car. +;;; + +(defun mew-keyword-number-pair (spec) + (let ((len (length spec)) key ret) + (dotimes (i len (nreverse ret)) + (setq key (intern (concat ":" (symbol-name (car spec))))) + (setq ret (cons (cons key i) ret)) + (setq spec (cdr spec))))) + +(defmacro mew-defstruct (type &rest spec) + `(progn + (mew-defstruct-constructor ,type ,@spec) + (mew-defstruct-s/getter ,type ,@spec))) + +(defmacro mew-defstruct-constructor (type &rest spec) + `(defun ,(intern (concat "mew-make-" (symbol-name type))) (&rest args) + (let* ((alist (quote ,(mew-keyword-number-pair spec))) + (struct (make-list (length alist) nil)) + key val key-num) + (while args ;; cannot use dolist + (setq key (car args)) + (setq args (cdr args)) + (setq val (car args)) + (setq args (cdr args)) + (unless (keywordp key) + (error "'%s' is not a keyword" key)) + (setq key-num (assoc key alist)) + (if key-num + (setcar (nthcdr (cdr key-num) struct) val) + (error "'%s' is unknown" key))) + struct))) + +(defmacro mew-defstruct-s/getter (type &rest spec) + `(let* ((type-name (symbol-name ',type)) + (keys ',spec) + (len (length keys)) + member-name setter getter) + (dotimes (i len) + (setq member-name (symbol-name (car keys))) + (setq setter (intern (format "mew-%s-set-%s" type-name member-name))) + (fset setter (list 'lambda '(struct value) (list 'setcar (list 'nthcdr i 'struct) 'value) 'struct)) + (setq getter (intern (format "mew-%s-get-%s" type-name member-name))) + (fset getter (list 'lambda '(struct) (list 'nth i 'struct))) + (setq keys (cdr keys))))) + +(provide 'mew-func) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-func.el ends here diff --git a/elpa/mew-20150813.2354/mew-gemacs.el b/elpa/mew-20150813.2354/mew-gemacs.el new file mode 100644 index 00000000..ebdcbcf7 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-gemacs.el @@ -0,0 +1,465 @@ +;;; mew-gemacs.el --- Environment of Graphical Emacs for Mew + +;; Author: Kazu Yamamoto +;; Created: Jun 22, 2000 + +;;; Code: + +(defvar mew-prog-pamscale (or (executable-find "pamscale") "pnmscale")) +(defvar mew-prog-pamscale-opt + (cond + ((string-match "pamscale" mew-prog-pamscale) "-xyfit") + ((string-match "pnmscale" mew-prog-pamscale) "-xysize"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Menu setting +;;; + +(easy-menu-define + mew-summary-mode-menu + mew-summary-mode-map + "Menu used in Summary mode." + mew-summary-mode-menu-spec) + +(easy-menu-define + mew-message-mode-menu + mew-message-mode-map + "Menu used in Message mode." + mew-message-mode-menu-spec) + +(easy-menu-define + mew-draft-mode-menu + mew-draft-mode-map + "Menu used in Draft mode." + mew-draft-mode-menu-spec) + +(easy-menu-define + mew-header-mode-menu + mew-header-mode-map + "Menu used in Header mode." + mew-header-mode-menu-spec) + +(easy-menu-define + mew-draft-header-menu + mew-draft-header-map + "Menu used in Draft mode." + mew-draft-mode-menu-spec) + +(easy-menu-define + mew-draft-attach-menu + mew-draft-attach-map + "Menu used in Draft mode." + mew-draft-mode-menu-spec) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Toolbar functions +;;; + +(defvar mew-summary-toolbar nil) +(defvar mew-draft-toolbar nil) + +(defun mew-toolbar-make (map alist) + (let ((tool-bar-map (make-sparse-keymap)) ;; for tool-bar-add-item-from-menu + (data-directory mew-icon-directory)) + (dolist (a alist) + (if (fboundp 'tool-bar-local-item-from-menu) + ;; Emacs 21.3.50 or later + (tool-bar-local-item-from-menu (car a) (cdr a) tool-bar-map map) + ;; Emacs 21.3 or earlier + ;; The target map is tool-bar-map + (tool-bar-add-item-from-menu (car a) (cdr a) map))) + tool-bar-map)) + +(defun mew-summary-setup-decoration () + (if mew-icon-p + (set (make-local-variable 'tool-bar-map) + (mew-toolbar-make mew-summary-mode-map mew-summary-toolbar-spec)))) + +(defun mew-message-setup-decoration () + (if mew-icon-p + (set (make-local-variable 'tool-bar-map) + (mew-toolbar-make mew-message-mode-map mew-message-toolbar-spec)))) + +(defun mew-draft-setup-decoration () + (if mew-icon-p + (set (make-local-variable 'tool-bar-map) + (mew-toolbar-make mew-draft-mode-map mew-draft-toolbar-spec)))) + +(defun mew-header-setup-decoration () + (if mew-icon-p + (set (make-local-variable 'tool-bar-map) + (mew-toolbar-make mew-header-mode-map mew-header-toolbar-spec)))) + +(defun mew-summary-toolbar-update ()) +(defun mew-message-toolbar-update ()) +(defun mew-draft-toolbar-update ()) +(defun mew-header-toolbar-update ()) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; End of messages +;;; + +(defun mew-message-set-end-of-message () + (overlay-put (mew-minfo-get-eom) 'before-string mew-end-of-message-string)) + +(defun mew-message-set-end-of-part () + (overlay-put (mew-minfo-get-eom) 'before-string mew-end-of-part-string)) + +(defun mew-message-set-end-of-nil () + (overlay-put (mew-minfo-get-eom) 'before-string nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Veil +;;; + +(defun mew-header-veil-make () + (let ((ov (mew-overlay-make 1 1))) + (overlay-put ov 'invisible t) + (overlay-put ov 'before-string mew-header-veil-string) + (delete-overlay ov) ;; detach from the buffer + ov)) + +(defun mew-toggle-header-veil (ov) + (cond + ((overlay-get ov 'invisible) + (overlay-put ov 'invisible nil) + (overlay-put ov 'before-string nil)) + (t + (overlay-put ov 'invisible t) + (overlay-put ov 'before-string mew-header-veil-string)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Image +;;; + +(defcustom mew-image-display-resize t + "*If non-nil, image will be displayed with fitting to frame size" + :group 'mew-message + :type 'boolean) + +(defcustom mew-image-display-resize-always nil + "*If nil, only a larger image than frame size will be displayed with fitting to frame size" + :group 'mew-message + :type 'boolean) + +(defcustom mew-image-display-resize-care-height t + "*If nil, image will be displayed with fitting to only frame width" + :group 'mew-message + :type 'boolean) + +(defcustom mew-image-width-margin 45 + "*A value for width margin to display image when resizing" + :group 'mew-message + :type 'integer) + +(defcustom mew-image-height-margin 200 + "A value for height margin to display image when resizing" + :group 'mew-message + :type 'integer) + +(defvar mew-image-l-endian ?\x49) +(defvar mew-image-b-endian ?\x4d) + +(defun mew-image-inline-p (format) + ;; display-graphic-p + (or (and window-system (image-type-available-p format)) + (let* ((ent (mew-image-format-ent format)) + (prog (mew-image-get-prog ent))) + (and prog (mew-which-exec prog) t)))) + +(defun mew-img-get-n (op len) + (let* ((size 0)) + (if (eq op ?\x49) ; I(?\x49) or M(?\x4d) + (dotimes (n len) + (setq size (+ size (* (char-after) (expt ?\x100 n)))) + (forward-char)) + (while (< 0 len) + (setq len (- len 1)) + (setq size (+ size (* (char-after) (expt ?\x100 len)))) + (forward-char))) + size)) + +(defun mew-jpeg-size () + (let (c size width height) + (save-excursion + (catch 'loop + (while t + (setq c (char-after)) + (forward-char) + (unless (eq c ?\xff) + (throw 'loop nil)) + (setq c (char-after)) + (forward-char) + (cond + ((or (eq c ?\xd8) ;; SOI + (eq c ?\xd9) ;; EOI + (and (>= c ?\xd0) (<= c ?\xd7)))) ;; RSTm + ((eq c ?\xc0) + (forward-char 3) + (setq height (mew-img-get-n mew-image-b-endian 2)) + (setq width (mew-img-get-n mew-image-b-endian 2)) + (backward-char) + (throw 'loop nil)) + ((and (>= c ?\xc1) (<= c ?\xfe)) + (setq size (mew-img-get-n mew-image-b-endian 2)) + (forward-char (- size 2))) + (t + (throw 'loop nil)))))) + (cons width height))) + +(defun mew-png-size () + (let (width height) + (save-excursion + (forward-char 18) + ;; length is four bytes + ;; but we takes lower two bytes + (setq width (mew-img-get-n mew-image-b-endian 2)) + (forward-char 2) + (setq height (mew-img-get-n mew-image-b-endian 2)) + (cons width height)))) + +(defun mew-gif-size () + (let (width height) + (save-excursion + (forward-char 6) + (setq width (mew-img-get-n mew-image-l-endian 2)) + (setq height (mew-img-get-n mew-image-l-endian 2)) + (cons width height)))) + +(defun mew-tiff-size () + (let (endian size entry tag width height) + (save-excursion + (setq endian (char-after)) + (forward-char 4) + (setq size (mew-img-get-n endian 4)) + (forward-char (- size 8)) ;; jump to IFD + ;; IFD + (setq entry (mew-img-get-n endian 2)) + (catch 'loop + (while t + (setq entry (- entry 1)) + (setq tag (mew-img-get-n endian 2)) + (cond + ((eq tag 256) + (forward-char 6) + (setq width (mew-img-get-n endian 2)) + (forward-char 2)) + ((eq tag 257) + (forward-char 6) + (setq height (mew-img-get-n endian 2)) + (forward-char 2)) + (t + (forward-char 10))) + (unless (< 1 entry) + (throw 'loop nil))))) + (cons width height))) + +(defun mew-bmp-size () + (let (width height) + (save-excursion + (forward-char 18) + ;; length is four bytes + ;; but we takes lower two bytes + (setq width (mew-img-get-n mew-image-l-endian 2)) + (forward-char 2) + (setq height (mew-img-get-n mew-image-l-endian 2)) + (cons width height)))) + +(defun mew-pbm-size () + (let (width height) + (save-excursion + (cond ((looking-at "^P[1-6][\t\n\v\f\r ]*\\(#[^\r\n]*[\r\n][\t\n\v\f\r ]*\\)*\\([0-9]+\\)[\t\n\v\f\r ]*\\(#[^\r\n]*[\r\n][\t\n\v\f\r ]*\\)*\\([0-9]+\\)[\t\n\v\f\r #]") ;; PBM, PGM, PPM, PNM + (setq width (string-to-number (match-string 2))) + (setq height (string-to-number (match-string 4)))) + ((looking-at "^P7$") ;; PAM + (when (re-search-forward "^WIDTH[ \t]+\\([0-9]+\\)[ \t]*$" nil t) + (setq width (string-to-number (match-string 1)))) + (goto-char (point-min)) + (when (re-search-forward "^HEIGHT[ \t]+\\([0-9]+\\)[ \t]*$" nil t) + (setq height (string-to-number (match-string 1)))))) + (cons width height)))) + +(defvar mew-image-alist + '((jpeg mew-jpeg-size "jpegtopnm" "pnmtojpeg") + (png mew-png-size "pngtopam" "pnmtopng") + (gif mew-gif-size "giftopnm" "pamtogif") + (tiff mew-tiff-size "tifftopnm" "pamtotiff") + (xwd nil "xwdtopnm" "pnmtoxwd") + (xbm nil "xbmtopbm" "pbmtoxbm") + (xpm nil "xpmtoppm" "ppmtoxpm") + (bmp mew-bmp-size "bmptopnm" "ppmtobmp") + (PCX nil "pcxtoppm" "ppmtopcx") + (TGA nil "tgatoppm" "pamtotga") + (ICO nil "winicontoppm" "ppmtowinicon") + (pbm mew-pbm-size nil nil) + (PAM mew-pbm-size "pamtopnm" "pamtopam"))) + +(defun mew-image-format-ent (format) + (assoc format mew-image-alist)) + +(defun mew-image-get-func (ent) + (nth 1 ent)) + +(defun mew-image-get-prog (ent) + (nth 2 ent)) + +(defun mew-image-get-prog2 (ent) + (nth 3 ent)) + +(defun mew-mime-image (cache begin end format) + (message "Loading image...") + (set-buffer (mew-buffer-message)) + (let* ((width (- (frame-pixel-width (selected-frame)) mew-image-width-margin)) + (height (- (frame-pixel-height (selected-frame)) mew-image-height-margin)) + (ent (mew-image-format-ent format)) + (prog (mew-image-get-prog ent)) + (func-size (mew-image-get-func ent)) + image-size image-width image-height image) + (with-temp-buffer + (mew-plet + (insert-buffer-substring cache begin end) + (mew-set-buffer-multibyte nil) + (goto-char (point-min)) + (cond ((and mew-image-display-resize + (not mew-image-display-resize-always) + func-size) + (setq image-size (funcall func-size)) + (setq image-width (car image-size)) + (setq image-height (cdr image-size))) + (t + (setq image-width nil) + (setq image-height nil))) + (when (and (not (image-type-available-p format)) + prog (mew-which-exec prog)) + (message "Converting image...") + (call-process-region (point-min) (point-max) prog + t '(t nil) nil) + (setq format 'pbm) + (unless (or image-width image-height) + (goto-char (point-min)) + (setq image-size (mew-pbm-size)) + (setq image-width (car image-size)) + (setq image-height (cdr image-size))) + (message "Converting image...done")) + (when (and mew-image-display-resize + (or mew-image-display-resize-always + (and image-width image-height + (or (< width image-width) + (and mew-image-display-resize-care-height + (< height image-height))))) + (or (eq format 'pbm) (mew-which-exec prog))) + (message "Resizing image...") + (unless (eq format 'pbm) + (call-process-region (point-min) (point-max) prog + t '(t nil) nil) + (setq format 'pbm)) + (if mew-image-display-resize-care-height + (call-process-region (point-min) (point-max) mew-prog-pamscale + t '(t nil) nil + mew-prog-pamscale-opt + (format "%d" width) + (format "%d" height)) + (call-process-region (point-min) (point-max) mew-prog-pamscale + t '(t nil) nil + "-xsize" (format "%d" width))) + (message "Resizing image...done")) + (setq image (mew-buffer-substring (point-min) (point-max))))) + (mew-elet + (condition-case nil + (insert-image (mew-create-image image format t)) + (error ())))) + (goto-char (point-min)) + (message "Loading image...done")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Transient +;;; + +(defun mew-mark-active-p () + (and transient-mark-mode mark-active)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; X Face +;;; + +(defun mew-x-face-create () + (mew-create-image + (string-as-unibyte (mew-buffer-substring (point-min) (point-max))) + nil t)) + +(defun mew-x-face-display (xface) + (save-excursion + (goto-char (point-min)) + (let ((regex2 (concat "^\\(" mew-from: "\\).*"))) + (when (re-search-forward regex2 nil t) + (goto-char (match-end 1)) + (insert-image xface))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SSL/SSH/TLS notification +;;; + +(defvar mew-secure-format nil) + +;; Emacs 21.x has a bug that an image cannot be displayed +;; if it is specified in mode-line-process. + +(defvar mew-secure-format2 + (if (display-graphic-p) + (let ((data-directory mew-icon-directory)) + (concat " " (propertize "Sec" 'display + (find-image '((:type xpm :file "mew-lock.xpm" :ascent center)))))) + " [Sec]")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Click hack +;;; + +(define-key mew-message-mode-map [mouse-2] 'mew-browse-url-at-mouse) +(if (and (featurep 'emacs) ;; preventing XEmacs's byte compiler from hanging + (eq system-type 'darwin)) + ;; for Mac + (define-key mew-message-mode-map [M-down-mouse-1] 'mew-browse-url-at-mouse)) + +(provide 'mew-gemacs) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-gemacs.el ends here diff --git a/elpa/mew-20150813.2354/mew-header.el b/elpa/mew-20150813.2354/mew-header.el new file mode 100644 index 00000000..d832d1b7 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-header.el @@ -0,0 +1,547 @@ +;; mew-header.el --- Mail header stuff for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +(defvar mew-anonymous-recipients ":;") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Header functions +;;; + +(defun mew-header-goto-next () + (while (looking-at mew-lwsp) (forward-line))) + +;; see also mew-header-end +(defun mew-header-goto-end () + (goto-char (point-min)) + (if (re-search-forward mew-eoh nil t) + (beginning-of-line) + (goto-char (point-max)) + (if (eolp) (insert "\n")))) + +(defun mew-header-goto-body () + (mew-header-goto-end) + (forward-line)) + +(defun mew-header-get-value (field &optional as-list) + "currently, when no match, it returns nil." + ;; maybe called in narrowed region. + ;; we cannot widen for citation. + (let ((case-fold-search t) + (regex (format "^%s[ \t]*" field)) + start match ret) + (save-excursion + (mew-header-goto-end) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + (catch 'only-one + (while (re-search-forward regex nil t) + (setq start (match-end 0)) + (forward-line) + (mew-header-goto-next) + (setq match (mew-buffer-substring start (1- (point)))) + (unless (string= "" match) + (if ret + (if as-list + (setq ret (cons match ret)) + (setq ret (concat ret "," match))) + (if as-list + (setq ret (list match)) + (setq ret match)) + (if (string= field mew-from:) (throw 'only-one nil)))))))) + (if as-list + (nreverse ret) + ret))) + +(defalias 'mew-header-existp 'mew-header-get-value) + +(defun mew-header-replace-value (field value) + (let ((case-fold-search t) + (regex (format "^%s[ \t]*" field)) + start) + (save-excursion + (mew-header-goto-end) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + ;; make value with evaluating + (if (and (listp value) + (stringp (car value))) + (setq value (cons 'format value))) + (setq value + (condition-case e + (eval value) + (error + (format "*** ERROR: %s: %s ***" (car e) (car (cdr e)))))) + (unless (or (stringp value) + (null value)) + (setq value (format "%s" value))) + ;; at this time, value is string or nil + (cond + ((re-search-forward regex nil t) + (setq start (match-beginning 0)) + (forward-line) + (mew-header-goto-next) + (delete-region start (point)) + (if value + (mew-draft-header-insert field value))) + (value ;; insert when value is exist + (mew-header-goto-end) + (mew-draft-header-insert field value))))))) + +(defun mew-make-field-regex (fields) + (concat "^\\(" (mapconcat 'identity fields "\\|") "\\)")) + +(defun mew-header-delete-lines (fields) + (when fields + (let ((case-fold-search t) + (regex (mew-make-field-regex fields)) + start) + (mew-header-goto-end) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (setq start (match-beginning 0)) + (forward-line) + (mew-header-goto-next) + (delete-region start (point))))))) + +(defun mew-header-delete-other-lines (fields) + (when fields + (let ((case-fold-search t) + (regex (mew-make-field-regex fields)) + start) + (mew-header-goto-end) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + (while (not (eobp)) + (if start (delete-region start (point))) + (if (looking-at regex) + (setq start nil) + (setq start (point))) + (forward-line) + (mew-header-goto-next)) + (if start (delete-region start (point))))))) + +(defun mew-header-replace-lines (fields prefix) + (when fields + (let ((case-fold-search t) + (regex (mew-make-field-regex fields))) + (mew-header-goto-end) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (beginning-of-line) + (insert prefix) + (forward-line)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Header sort +;;; + +(defun mew-header-sort (order) + (when order + (let* ((case-fold-search t) + (len (length order)) + (vec (make-vector len nil)) + key beg n line other) + (mew-header-goto-end) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + (while (not (eobp)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq key (mew-match-string 1)) + (setq beg (match-beginning 0)) + (forward-line) + (mew-header-goto-next) + (setq line (mew-buffer-substring beg (point))) + (delete-region beg (point)) + (setq n (mew-member-case-equal key order)) + (if n + (aset vec n (concat (aref vec n) line)) + (setq other (concat other line))))) + (dotimes (i len) + (and (aref vec i) (insert (aref vec i)))) + (and other (insert other)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Header insertion +;;; + +(defun mew-draft-header-insert (field value) + "No encoding. Just insert." + (if (and value (stringp field)) (insert field " " value "\n"))) + +(defun mew-draft-header-fill (field value) + (unless (mew-header-existp field) (mew-draft-header-insert field value))) + +(defun mew-header-insert (key value &optional no-fold) + (if (and value (stringp key)) + (let ((beg (point)) params med parname parval) + (when (listp value) + (setq params (cdr value)) + (setq value (car value))) + (insert key) + (insert " ") + (setq med (point)) + (if (string-match "^[\t -~]*$" value) + (insert value) + (mew-header-encode-text value nil (length key))) + (dolist (par params) + (mew-set '(parname parval) par) + (insert ";") + (cond + ((string-match "^[-a-zA-Z0-9]+$" parval) + ) ;; do nothing + ((and (string= (mew-charset-guess-string parval) mew-us-ascii) + (not (string-match "\"" parval))) + (setq parval (concat "\"" parval "\""))) + (t + (setq parval (mew-param-encode parval)) + (setq parname (concat parname "*")))) + (insert " " parname "=" parval)) + (insert "\n") + (unless no-fold + (mew-header-fold-region beg (point) med))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Low-level functions to parse fields +;;; + +;; +;; The purpose of this function is to purse and extract value +;; of address or content header. text is not target! +;; +;; ADDRP is t if STR are addresses. +;; ADDRP is nil if STR is a value of content-*. +;; +;; 'Winnie (The) Pooh <"W. Pooh" (loves "honey") @ (somewhere in) England>' +;; -> +;; '"W. Pooh"@England' +;; +;; For 'destination', SEP is ",". +;; For Content-*, SEP is ";". +;; +;; The special (i.e. SEP) is one of delimiters. +;; 'linear-white-space' is another delimiter. +;; 'quoted-string', 'comment', and 'domain-literal' is self-delimiting. +;; But 'domain-literal' (e.g. [1.2.3.4]) is meaningless. +;; So, the delimiters consists of SEP, SP, TAB, CRLF, "(", ")", and <">. +;; +;; 'qtext' remains. (It will be removed by mew-param-decode.) +;; ## how about 'quoted-pair'? +;; +;; 'comment' must be symmetric. That is, it must have the exact number of +;; ")" against that of ")". The entire 'comment', even if nested, is +;; ignored. +;; +;; 'encoded-word' is meaningless. +;; (1) Remove 'comment' so 'encoded-word' in 'comment' is meaningless. +;; (2) 'phrase' of 'mailbox' will be ignored because 'addr-spec' in +;; 'route-addr' will be extracted. So, 'encoded-word' in 'phrase' is +;; meaningless. + +(defmacro mew-addrstr-parse-syntax-list-check-depth (&optional depth) + `(progn + (setq sep-cnt (1+ sep-cnt)) + (if (and ,depth (>= sep-cnt ,depth)) + (throw 'max nil)) + (when (and (integerp mew-header-max-depth) + (>= sep-cnt mew-header-max-depth)) + (mew-warn "Too many values. Truncate values over mew-header-max-depth") + (throw 'max nil)))) + +(defun mew-addrstr-parse-syntax-list (str sep addrp &optional depth allow-spc) + (if str (mew-addrstr-parse-syntax-list1 str sep addrp depth allow-spc))) + +(defun mew-addrstr-parse-syntax-list1 (str sep addrp depth allow-spc) + (let* ((i 0) (len (length str)) + (par-cnt 0) (tmp-cnt 0) (sep-cnt 0) + ;; Emacs 23 has non-safe aset. + (tmp (mew-set-string-multibyte (mew-make-string len))) + c ret prevc + (do-clear + (lambda () + (setq tmp-cnt 0) + (mew-addrstr-parse-syntax-list-check-depth depth))) + (do-cons-ret + (lambda () + (setq ret (cons (substring tmp 0 tmp-cnt) ret)))) + (do-copy + (lambda () + (aset tmp tmp-cnt c) + (setq tmp-cnt (1+ tmp-cnt)))) + (in-fold-quote + (lambda () + (setq i (1+ i)) + (catch 'fold-quote + (while (< i len) + (setq c (aref str i)) + (cond + ;; ((or (char-equal c ?\t) (char-equal c mew-sp)) + ;; (setq i (1+ i))) + ((char-equal c ?\") + (funcall do-copy) + (throw 'quote nil)) + (t + (funcall do-copy) + (throw 'fold-quote nil))))))) + (in-quote + (lambda () + (funcall do-copy) + (setq i (1+ i)) + (catch 'quote + (while (< i len) + (setq prevc c) + (setq c (aref str i)) + (cond + ((and (char-equal c ?\") (not (char-equal prevc ?\\))) + (funcall do-copy) + (throw 'quote nil)) + ((char-equal c ?\n) + (funcall in-fold-quote)) + (t + (funcall do-copy))) + (setq i (1+ i)))))) + (in-comment + (lambda () + (setq par-cnt 1) + (setq i (1+ i)) + (catch 'comment + (while (< i len) + (setq c (aref str i)) + (cond + ((char-equal c ?\() + (setq par-cnt (1+ par-cnt))) + ((char-equal c ?\)) + (setq par-cnt (1- par-cnt)) + (if (eq par-cnt 0) (throw 'comment nil)))) + (setq i (1+ i)))))) + (do-skip-until + (lambda (target) + (while (and (< i len) (not (char-equal (aref str i) target))) + (setq i (1+ i))))) + (in-addr + (lambda () + (cond + (addrp + (let (rbeg rend) + (setq i (1+ i)) + (setq rbeg i) + (funcall do-skip-until ?>) + (when (> i rbeg) + (setq rend i) + ;; note: to be used for substring, so not 1-. + ;; should not be nested but easy to implement... + (setq ret (cons (car (mew-addrstr-parse-syntax-list (substring str rbeg rend) sep t)) ret)))) + (funcall do-skip-until sep) + (funcall do-clear)) + (t + ;; just ignore + (funcall do-skip-until ?>))))) + (do-sep + (lambda () + ;; broken quoted string cannot be rescued because + ;; the separator cannot be distinguished + (if (> tmp-cnt 0) (funcall do-cons-ret)) + (funcall do-clear))) + (do-rescue + (lambda (var) + (save-match-data + (if (and addrp (string-match "<\\([^>]+\\)>" var)) + (setq ret (cons (mew-match-string 1 var) ret)) + (funcall do-cons-ret)))))) + ;; main + (catch 'max + (while (< i len) + (setq c (aref str i)) + (cond + ((char-equal c ?\") + (funcall in-quote)) + ((char-equal c ?\() + (funcall in-comment)) + ((char-equal c ?<) + (funcall in-addr)) + ((or (char-equal c ?\n) (char-equal c ?\t) + (and (not allow-spc) (char-equal c mew-sp))) + ) ;; do nothing + ((char-equal c sep) + (funcall do-sep)) + (t + (funcall do-copy))) + (setq i (1+ i))) + ;; broken quoted string can be rescued if it appears solely + (cond + ((> par-cnt 0) + (funcall do-rescue str)) + ((> tmp-cnt 0) + (funcall do-rescue tmp)))) + (setq ret (delete nil ret)) + (when allow-spc + (setq ret (mapcar (lambda (str) + (if (string-match "^ +\\(.*\\)" str) + (mew-match-string 1 str) + str)) + ret))) + (nreverse ret))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; High-level functions to parse fields +;;; + +(defun mew-addrstr-parse-value (value) + (car (mew-addrstr-parse-syntax-list value ?\; nil 1))) + +(defun mew-addrstr-parse-value-list (value) + (mew-addrstr-parse-syntax-list value ?\; nil)) + +(defun mew-addrstr-parse-value2 (value) + (car (mew-addrstr-parse-syntax-list value ?, nil 1))) + +(defun mew-addrstr-parse-value-list2 (value) + (mew-addrstr-parse-syntax-list value ?, nil nil t)) + +;; + +(defun mew-addrstr-parse-address (address) + (car (mew-addrstr-parse-syntax-list address ?, t 1))) + +(defun mew-addrstr-parse-address-list (address) + (mew-addrstr-parse-syntax-list address ?, t)) + +(defun mew-header-parse-address (field) + (car + (mew-addrstr-parse-syntax-list + (mapconcat 'mew-header-get-value (list field) ",") + ?, t 1))) + +(defun mew-header-parse-address-list (field-list) + (mew-addrstr-parse-syntax-list + (mapconcat 'mew-header-get-value field-list ",") + ?, t)) + +(defun mew-header-parse-address-list2 (field-list) + "Collect addresses from FIELD-LIST. +Remove anonymous addresses." + (let ((vals (mew-addrstr-parse-syntax-list + (mapconcat 'mew-header-get-value field-list ",") + ?, t)) + ret) + (dolist (val vals) + (unless (string-match mew-anonymous-recipients val) + (setq ret (cons val ret)))) + (nreverse ret))) + +;; + +(defun mew-addrstr-extract-user-list (addr-list) + (mapcar 'mew-addrstr-extract-user addr-list)) + +(defun mew-addrstr-extract-user (addr) + "Extracts username from ADDR" + (if (string-match "@.*:" addr) ;; xxx what's this? + (setq addr (substring addr (match-end 0))) + (setq addr (mew-replace-character addr mew-sp ?_)) + (setq addr (substring addr 0 (string-match "%" addr))) + (setq addr (substring addr 0 (string-match "@" addr))) + ;; just for refile: "To: recipients:;" -> recipients + (setq addr (substring addr 0 (string-match mew-anonymous-recipients addr))) + ;; removing Notes domain + (setq addr (substring addr 0 (string-match "/" addr))))) + +;; + +(defun mew-addrstr-append-domain (addr) + (if mew-addrbook-append-domain-p + (if (string-match "@" addr) + addr + (concat addr "@" (mew-mail-domain))) ;; xxx + addr)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Functions for ID +;;; + +(defun mew-idstr-get-first-id (idstr) + (when (stringp idstr) + (if (string-match mew-regex-id idstr) + (mew-replace-white-space2 (match-string 0 idstr))))) + +(defun mew-idstr-get-last-id (idstr) + (when (stringp idstr) + (let (beg end start) + (while (string-match mew-regex-id idstr start) + (setq beg (match-beginning 0)) + (setq end (match-end 0)) + (setq start (match-end 0))) + (if (and beg end) + (mew-replace-white-space2 (substring idstr beg end)))))) + +(defun mew-idstr-to-id-list (idstr &optional rev) + (when (stringp idstr) + (let (ret start) + (while (string-match mew-regex-id idstr start) + (setq start (match-end 0)) + (setq ret (cons (mew-replace-white-space2 (match-string 0 idstr)) ret))) + (if rev + ret + (nreverse ret))))) + +(defun mew-id-list-to-idstr (id-list) + (let (skip) + (if (integerp mew-references-max-count) + (setq skip (- (length id-list) mew-references-max-count))) + (if (and (integerp skip) (> skip 0)) + (setq id-list (nthcdr skip id-list))) + (mew-join "\n\t" id-list))) + +(provide 'mew-header) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-header.el ends here diff --git a/elpa/mew-20150813.2354/mew-highlight.el b/elpa/mew-20150813.2354/mew-highlight.el new file mode 100644 index 00000000..729283ec --- /dev/null +++ b/elpa/mew-20150813.2354/mew-highlight.el @@ -0,0 +1,385 @@ +;;; mew-highlight.el --- Highlight for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 18, 1997 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Cursor line +;;; + +(defun mew-highlight-cursor-line () + "A function to highlight the cursor line in Summary and Virtual mode." + (when mew-use-highlight-cursor-line + (mew-elet + (if (overlayp (mew-sinfo-get-cursor-line)) + (move-overlay (mew-sinfo-get-cursor-line) + (save-excursion (beginning-of-line) (point)) + (save-excursion (end-of-line) (point))) + (mew-sinfo-set-cursor-line + (mew-overlay-make + (save-excursion (beginning-of-line) (point)) + (save-excursion (end-of-line) (point)))) + (overlay-put + (mew-sinfo-get-cursor-line) 'face mew-highlight-cursor-line-face)))) + (when mew-use-cursor-mark + (unless (markerp overlay-arrow-position) + (make-local-variable 'overlay-arrow-position) + (setq overlay-arrow-position (make-marker))) + (unless (and overlay-arrow-string + (string= overlay-arrow-string mew-cursor-mark)) + (make-local-variable 'overlay-arrow-string) + (setq overlay-arrow-string mew-cursor-mark)) + (set-marker overlay-arrow-position + (save-excursion (beginning-of-line) (point))))) + +(defun mew-unhighlight-cursor-line () + (when (overlayp (mew-sinfo-get-cursor-line)) + (move-overlay (mew-sinfo-get-cursor-line) 1 1) + ;; (goto-char (point-max)) works wrong if underline exists. + ;; Redisplays it so that it works well. + ;; (sit-for 0) + ;; This code rocks Summary mode when typing "x", sigh. + )) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Marks +;;; + +(defun mew-highlight-mark-line (mark) + (when mew-use-highlight-mark + (let ((face (mew-highlight-mark-get-face mark))) + (unless face (setq face 'default)) + (put-text-property + (save-excursion (beginning-of-line) (point)) + (save-excursion (end-of-line) (point)) + 'face face)))) + +(defun mew-highlight-unmark-line () + (remove-text-properties + (save-excursion (beginning-of-line) (point)) + (save-excursion (end-of-line) (point)) + '(face nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Header +;;; + +(defun mew-unhighlight-region (BEG END) + (mew-overlay-delete-region BEG END)) + +(defun mew-unhighlight-header () + (save-restriction + (widen) + (mew-unhighlight-region (point-min) (mew-header-end)))) + +(defun mew-highlight-header-region (BEG END) + "A function to highlight header in Message and Draft mode." + (when mew-use-highlight-header + (let (key beg med nspec overlay key-face val-face start) + (save-excursion + (mew-elet + (mew-unhighlight-region BEG END) + (save-restriction + (narrow-to-region BEG END) + (goto-char (point-min)) + (while (not (eobp)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq start (point)) + (setq key (mew-match-string 1)) + (setq beg (match-beginning 0)) + (setq med (match-end 0)) + (forward-line) + (setq nspec (mew-nspec-by-key key)) + (setq key-face (mew-key-face key nspec)) + (setq val-face (mew-val-face key nspec)) + (setq overlay (mew-overlay-make beg med)) + (overlay-put overlay 'face key-face) + (setq overlay (mew-overlay-make med (1- (point)))) + (overlay-put overlay 'face val-face) + (while (looking-at mew-lwsp+) + (forward-line) + (setq overlay (mew-overlay-make (match-end 0) (1- (point)))) + (overlay-put overlay 'face val-face)) + (if (member (mew-capitalize key) + mew-draft-address-warning-fields) + (mew-highlight-header-address-region start (point))))))))))) + +(defun mew-highlight-header-address-region (beg end) + (let ((case (mew-tinfo-get-case)) + addr domain overlay begovl endovl warnp) + (save-excursion + (goto-char beg) + (while (re-search-forward "[^\n\t, <>:;]+@\\([^\n\t, <>:;]+\\)" end t) + (setq addr (downcase (mew-match-string 0))) + (setq domain (downcase (mew-match-string 1))) + (setq begovl (match-beginning 0)) + (setq endovl (match-end 0)) + (cond + ((member addr (mew-safe-addresses case)) + (setq warnp nil)) + ((member addr (mew-warn-addresses case)) + (setq warnp t)) + ((member domain (mew-safe-domains case)) + (setq warnp nil)) + ((member domain (mew-warn-domains case)) + (setq warnp t)) + ((or (mew-warn-addresses case) (mew-safe-domains case)) + (setq warnp t)) + (t + (setq warnp nil))) + (when warnp + (setq overlay (mew-overlay-make begovl endovl)) + (overlay-put overlay 'face 'mew-face-header-warning) + (overlay-put overlay 'priority 2)))))) ;; a bug of Meadow + +(defun mew-highlight-header () + (save-restriction + (widen) + (mew-highlight-header-region (point-min) (mew-header-end)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Body +;;; + +(defun mew-highlight-body-region (BEG END &optional draft rehighlight) + (when (and (or mew-use-highlight-body mew-use-highlight-url) + (or (= 0 mew-highlight-body-max-size) + (<= BEG mew-highlight-body-max-size))) + (unless (or (= 0 mew-highlight-body-max-size) + (<= END mew-highlight-body-max-size)) + (setq END mew-highlight-body-max-size)) + (let* ((inhibit-point-motion-hooks t) + (cite-regex mew-highlight-body-regex-cite) + (cmt-regex mew-highlight-body-regex-comment) + (url-regex mew-regex-url) + (fancy-num 0) + (fancy-length (length mew-highlight-body-cite-faces)) + beg end face fancy-alst fancy-prefix idn url) + (save-excursion + (mew-elet + (when draft + (mew-rear-nonsticky BEG END) + (if rehighlight + (remove-text-properties BEG END '(face nil mouse-face nil)))) + (when mew-use-highlight-body + (goto-char BEG) + (while (and (<= (point) END) (re-search-forward cite-regex END t)) + (setq beg (match-beginning 0)) + (setq end (match-end 0)) + (if (match-beginning 1) + (setq fancy-prefix (mew-match-string 1)) + (setq fancy-prefix nil)) + (when (and fancy-prefix + (< (string-width fancy-prefix) + mew-highlight-body-prefix-width)) + (if (setq face (cdr (assoc fancy-prefix fancy-alst))) + (put-text-property beg end 'face face) + (setq face (nth fancy-num mew-highlight-body-cite-faces)) + (setq fancy-alst (cons (cons fancy-prefix face) fancy-alst)) + (setq fancy-num (1+ fancy-num)) + (when (= fancy-length fancy-num) + (setq fancy-num 0)) + (put-text-property beg end 'face face))) + (forward-line)) + (goto-char BEG) + (while (and (<= (point) END) (re-search-forward cmt-regex END t)) + (setq beg (match-beginning 0)) + (setq end (match-end 0)) + (put-text-property beg end 'face 'mew-face-body-comment))) + (when mew-use-highlight-url + (goto-char BEG) + (while (and (<= (point) END) (re-search-forward url-regex END t)) + (save-restriction + (setq beg (match-beginning 0)) + (setq end (match-end 0)) + (narrow-to-region beg end) + (goto-char (point-min)) + (setq url (mew-buffer-substring (point-min) (point-max))) + (while (and mew-use-punycode (re-search-forward mew-regex-punycode nil t)) + (setq idn (mew-puny-decode (mew-buffer-substring (match-beginning 0) (match-end 0)))) + (when idn + (delete-region (match-beginning 0) (match-end 0)) + (insert idn))) + (goto-char (point-max)) + (put-text-property (point-min) (point-max) 'mew-url url) + (put-text-property (point-min) (point-max) 'face 'mew-face-body-url) + (put-text-property + (point-min) (point-max) 'mouse-face mew-highlight-url-mouse-face) + (setq END (- END (- end (point-max)))))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; X Face +;;; + +(defun mew-highlight-x-face (beg end) + "Display X-Face." + (if (and mew-use-highlight-x-face + window-system + (fboundp mew-highlight-x-face-function)) + (funcall mew-highlight-x-face-function beg end))) + +(defvar mew-highlight-x-face-function (if mew-icon-p 'mew-highlight-x-face-original) + "*A function to display-Xface") + +(defun mew-highlight-x-face-original (beg end) + (save-excursion + (goto-char beg) + (mew-elet + (let ((regex1 "^X-Face: *\\(.*\\(\n[ \t].*\\)*\\)\n") + (buf (current-buffer)) + overlay xface beg0 end0 xbmp) + (while (re-search-forward regex1 end t) + (setq beg0 (match-beginning 0)) + (setq end0 (match-end 0)) + (with-temp-buffer + (mew-insert-buffer-substring + buf (match-beginning 1) (match-end 1)) + (setq xbmp (mew-x-face-compface-to-xbm)) + (if xbmp (setq xface (mew-x-face-create)))) + (when xface + (setq overlay (mew-overlay-make beg0 end0)) + (overlay-put overlay 'invisible t) + (save-restriction + (narrow-to-region beg end) + (mew-x-face-display xface )))))))) + +(defun mew-x-face-compface-to-xbm () + (when (and (mew-which-exec mew-prog-uncompface) + (mew-which-exec mew-prog-icontopbm) + (mew-which-exec mew-prog-pbmtoxbm)) + (mew-set-buffer-multibyte nil) + (mew-flet + (call-process-region (point-min) (point-max) mew-prog-uncompface t t nil) + (goto-char (point-min)) + (insert "/* Format_version=1, Width=48, Height=48, Depth=1, Valid_bits_per_item=16 */\n") + (call-process-region (point-min) (point-max) mew-prog-icontopbm t t nil) + (if mew-use-highlight-x-face-inversion + (call-process-region (point-min) (point-max) mew-prog-pbminvert t t nil)) + (call-process-region (point-min) (point-max) mew-prog-pbmtoxbm t t nil)) + t)) ;; return value + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Cooking +;;; + +(defun mew-summary-cook-window (&optional WIN BEG) + (let* ((win (or WIN (selected-window))) + (beg (or BEG (window-start win))) + (end (window-end win t)) + (buf (window-buffer win))) + (with-current-buffer buf + (funcall mew-summary-cook-function beg end)))) + +;; See also mew-scan-insert-line +(defun mew-summary-cook-region (beg end &optional interrupt) + (when (and (mew-summary-or-virtual-p) mew-summary-buffer-raw) + (let ((inhibit-point-motion-hooks t) + ret mark face start med) + (catch 'loop + (save-excursion + (mew-elet + (goto-char beg) + (if (mew-in-decode-syntax-p) + (goto-char (mew-decode-syntax-end))) + (if (and (mew-thread-p) + mew-use-thread-separator + (not (mew-summary-message-number))) + (forward-line)) + (setq start (point)) + (while (and (< (point) end) ;; we cannot trust end + (search-forward "\r" end t)) + (if (and interrupt (input-pending-p)) + (throw 'loop (setq ret t))) + (setq med (match-beginning 0)) + (forward-line) + (if (and mew-use-highlight-mouse-line window-system) + (put-text-property + start med 'mouse-face mew-highlight-mouse-line-face)) + (put-text-property med (1- (point)) 'invisible t) + (if (mew-in-decode-syntax-p) + (goto-char (mew-decode-syntax-end))) + (if (and (mew-thread-p) + mew-use-thread-separator + (not (mew-summary-message-number))) + (forward-line)) + (setq start (point))) + (when mew-use-highlight-mark + (goto-char beg) + (while (and (< (point) end) ;; we cannot trust end + (re-search-forward mew-regex-mark end t)) + (if (and interrupt (input-pending-p)) + (throw 'loop (setq ret t))) + (setq mark (mew-sumsyn-mark)) + (setq face (mew-highlight-mark-get-face mark)) + (beginning-of-line) + (setq start (point)) + (forward-line) + (if face (put-text-property start (1- (point)) 'face face))))))) + (set-buffer-modified-p nil) + ret))) + +(defun mew-summary-cook-folders () + (save-excursion + (dolist (buf mew-buffers) + (when (and (get-buffer buf) (not (input-pending-p))) + (set-buffer buf) + (setq mew-summary-buffer-raw + (mew-summary-cook-region + (point-min) (point-max) 'interrupt)))))) + +(defvar mew-highlight-timer-id nil) + +(defun mew-highlight-timer-setup () + (if mew-highlight-timer-id (cancel-timer mew-highlight-timer-id)) + (setq mew-highlight-timer-id + (run-with-idle-timer mew-highlight-timer-interval + t 'mew-summary-cook-folders))) + +(defun mew-highlight-timer-clean-up () + (if mew-highlight-timer-id (cancel-timer mew-highlight-timer-id)) + (setq mew-highlight-timer-id nil)) + +(provide 'mew-highlight) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-highlight.el ends here diff --git a/elpa/mew-20150813.2354/mew-imap.el b/elpa/mew-20150813.2354/mew-imap.el new file mode 100644 index 00000000..26f8e1d6 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-imap.el @@ -0,0 +1,1878 @@ +;;; mew-imap.el for reading + +;; Author: Kazu Yamamoto +;; Created: Feb 21, 2002 + +;;; Code: + +(require 'mew) + +(defvar mew-imap-msgid-file ".mew-msgid") +(defvar mew-imap-folder-alist-file ".mew-folder-alist") +(defvar mew-imap-folder-alist nil) +(defvar mew-imap-friend-folder-list-file ".mew-friend-folder-list") +(defvar mew-imap-friend-folder-list nil) + +(defconst mew-imap-inbox-string "inbox") +(defun mew-imap-inbox-str-p (mailbox) + (mew-case-equal mailbox mew-imap-inbox-string)) + +(defvar mew-imap-skip-uidl t) + +(defvar mew-imap-marks-to-clean + (list mew-mark-read mew-mark-unread mew-mark-escape mew-mark-review)) +(defvar mew-imap-marks-to-sync + (list mew-mark-read mew-mark-unread mew-mark-review)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; IMAP info +;;; + +(defvar mew-imap-info-list + '("server" "port" "process" "ssh-process" "ssl-process" "status" + "directive" "bnm" "mdb" + "rmvs" "kils" "refs" "movs" + "rtrs" "dels" "uidl" "range" + "rttl" "rcnt" "dttl" "rgttl" "rgcnt" "dgttl" "dgcnt" "jcnt" "rfl" "hlds" + "user" "auth" "auth-list" "passwd" "account" + "size" "truncated" "get-body" + "flush" "no-msg" "msgdb" "done" "dispatched" "error" + "delete" + "case" "mailbox" "msgid" "max" "tag" + "wrk" "jobs" "namespace" "authl" + "spam" "spam-field" "spam-word" "spam-pattern" + "new-mailbox" "my-prefix" "specials" "bytes" + "virtual-info" "disp-info" "status-buf" "mark-hist")) + +(mew-info-defun "mew-imap-" mew-imap-info-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; FSM +;;; + +(defvar mew-imap-fsm + '(("greeting" ("OK" . "capability")) + ("capability" ("OK" . "post-capability")) + ("auth-cram-md5" ("OK" . "pwd-cram-md5") ("NO" . "wpwd")) + ("pwd-cram-md5" ("OK" . "next") ("NO" . "wpwd")) + ("auth-login" ("OK" . "user-login") ("NO" . "wpwd")) + ("user-login" ("OK" . "pwd-login") ("NO" . "wpwd")) + ("pwd-login" ("OK" . "next") ("NO" . "wpwd")) + ("login" ("OK" . "next") ("NO" . "wpwd")) + ("select" ("OK" . "post-select")) + ("flags" ("OK" . "flags")) ;; xxx NG but loop + ("uid" ("OK" . "umsg")) + ("copy" ("OK" . "copy") ("NO \\[TRYCREATE\\]" . "create") ("NO" . "wmbx")) + ("create" ("OK" . "copy") ("NO" . "wmbx")) + ("dels" ("OK" . "dels")) ;; xxx NG but loop + ("expunge" ("OK" . "post-expunge")) + ;; + ("search" ("OK" . "post-search")) + ;; + ("fetch" ("OK" . "post-fetch")) + ;; + ("namespace" ("OK" . "post-namespace") ("NO\\|BAD" . "list")) + ("list" ("OK" . "post-list")) + ;; + ("delete" ("OK" . "logout") ("NO" . "logout3")) + ("rename" ("OK" . "logout") ("NO" . "logout3")) + ;; + ("logout" ("OK" . "noop")) + ("logout2" ("OK" . "noop")) + ("logout3" ("OK" . "noop")))) + +(defun mew-imap-fsm-by-status (status) + (assoc status mew-imap-fsm)) + +(defun mew-imap-fsm-next (status code) + (cdr (mew-assoc-match2 code (nthcdr 1 (mew-imap-fsm-by-status status)) 0))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Structure +;;; + +;; 'get, 'exec and 'jobs +(mew-defstruct copyinfo dst uid) ;; uid = "uid1,uid2" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filters +;;; + +(defun mew-imap-secure-p (pnm) + (or (mew-imap-get-ssh-process pnm) (mew-imap-get-ssl-process pnm))) + +(defun mew-imap-command-capability (pro pnm) + (mew-net-status (mew-imap-get-status-buf pnm) + "Auth'ing" + nil + (mew-imap-secure-p pnm)) + (mew-imap-process-send-string pro pnm "CAPABILITY")) + +(defun mew-imap-command-post-capability (pro pnm) + (let ((case-fold-search t) + authl) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "AUTH=\\([^ \r\n]+\\)" nil t) + (setq authl (cons (mew-match-string 1) authl))) + (goto-char (point-min)) + (mew-imap-set-authl pnm authl) + (mew-imap-set-status pnm "authentication") + (mew-imap-command-authentication pro pnm)))) + +(defun mew-imap-command-authentication (pro pnm) + (cond + ((eq (mew-imap-get-auth pnm) t) ;; t means SASL + (let* ((auth-list (mew-imap-get-auth-list pnm)) + (authl (mew-imap-get-authl pnm)) + auth func) + (if (and authl + (setq auth (mew-auth-select2 authl auth-list)) + (setq func (mew-imap-auth-get-func auth)) + (fboundp func)) + (progn + (mew-imap-set-auth pnm auth) + (funcall func pro pnm)) + (mew-imap-debug "" "No preferred IMAP AUTH.\n") + (mew-imap-set-status pnm "login") + (mew-imap-command-login pro pnm)))) + (t + (mew-imap-set-status pnm "login") + (mew-imap-command-login pro pnm)))) + +(defun mew-imap-command-login (pro pnm) + (let* ((user (mew-imap-get-user pnm)) + (prompt (format "IMAP password (%s): " (mew-imap-get-account pnm))) + (pass (mew-input-passwd prompt (mew-imap-passtag pnm)))) + (setq user (mew-quote-string user ?\\ '(?\\ ?\"))) + (setq pass (mew-quote-string pass ?\\ '(?\\ ?\"))) + (mew-imap-process-send-string pro pnm "LOGIN \"%s\" \"%s\"" user pass))) + +(defun mew-imap-command-wpwd (pro pnm) + (mew-imap-set-error pnm "IMAP password is wrong!") + (mew-passwd-set-passwd (mew-imap-passtag pnm) nil) + (mew-imap-set-status pnm "logout2") + (mew-imap-command-logout2 pro pnm)) + +(defun mew-imap-command-next (pro pnm) + (let ((directive (mew-imap-get-directive pnm)) + (jobs (mew-imap-get-jobs pnm))) + (when (and (eq directive 'jobs) jobs) + (let* ((case (mew-imap-get-case pnm)) + (bnm (mew-imap-get-bnm pnm)) + (file (mew-expand-msg bnm (car jobs))) + (work (concat file mew-queue-work-suffix)) + (data (concat file mew-imapq-info-suffix)) + (data-work (concat data mew-queue-work-suffix)) + jobinfo execinfo mailbox) + (rename-file file work 'override) + (setq jobinfo (mew-lisp-load data)) + (rename-file data data-work 'override) + (setq mailbox (mew-jobinfo-get-mailbox jobinfo)) + (setq mailbox (mew-imap-utf-7-encode-string mailbox)) + (setq mailbox (mew-imap-expand-mailbox case mailbox)) + (mew-imap-set-mailbox pnm mailbox) + (setq execinfo (mew-jobinfo-get-execinfo jobinfo)) + (mew-imap-set-rmvs pnm (mew-execinfo-get-remove execinfo)) + (mew-imap-set-kils pnm (mew-execinfo-get-kill execinfo)) + (mew-imap-set-refs pnm (mew-execinfo-get-refile execinfo)) + (mew-imap-set-movs pnm (mew-execinfo-get-move execinfo)) + (mew-imap-set-rttl pnm (mew-execinfo-get-rttl execinfo)) + (mew-imap-set-dttl pnm (mew-execinfo-get-dttl execinfo)) + (mew-imap-set-mark-hist pnm (mew-imap-make-mark-hist (mew-jobinfo-get-mark-hist jobinfo))) + (mew-imap-set-rcnt pnm 1) + (mew-imap-set-rgcnt pnm 1) + (mew-imap-set-dgcnt pnm 1) + (mew-imap-set-wrk pnm work) + (mew-imap-set-jobs pnm (cdr jobs)))) + (mew-imap-set-status pnm "select") + (mew-imap-command-select pro pnm))) + +(defun mew-imap-command-select (pro pnm) + (let ((directive (mew-imap-get-directive pnm)) + (mailbox (mew-imap-get-mailbox pnm))) + (cond + ((eq directive 'list) + (mew-imap-set-status pnm "namespace") + (mew-imap-command-namespace pro pnm)) + ((eq directive 'delete) + (mew-imap-set-status pnm "delete") + (mew-imap-command-delete pro pnm)) + ((eq directive 'rename) + (mew-imap-set-status pnm "rename") + (mew-imap-command-rename pro pnm)) + (t + (mew-imap-process-send-string pro pnm "SELECT \"%s\"" mailbox))))) + +(defun mew-imap-command-post-select (pro pnm) + (let ((mark-hist (mew-imap-get-mark-hist pnm))) + (cond + (mark-hist + (mew-imap-set-status pnm "flags") ;; come back + (mew-imap-command-flags pro pnm)) + ((mew-imap-get-spam pnm) + (mew-imap-set-status pnm "search") ;; goto "uid" + (mew-imap-command-search pro pnm)) + (t + (mew-imap-set-status pnm "uid") + (mew-imap-command-uid pro pnm))))) + +(defun mew-imap-command-flags (pro pnm) + (let ((mark-hist (mew-imap-get-mark-hist pnm)) + ent msg mark flag) + (cond + (mark-hist + (setq ent (car mark-hist)) + (setq msg (mew-mark-hist-get-msg ent)) + (setq mark (mew-mark-hist-get-mark ent)) + (mew-imap-set-mark-hist pnm (cdr mark-hist)) + (cond + ((char-equal mark mew-mark-review) + (setq flag "+FLAGS (\\Seen \\Flagged)")) + ((char-equal mark mew-mark-read) + (mew-imap-set-mark-hist + pnm (cons (mew-make-mark-hist :msg msg :mark mew-mark-tmp) (cdr mark-hist))) + (setq flag "+FLAGS (\\Seen)")) + ((char-equal mark mew-mark-unread) + (setq flag "-FLAGS (\\Seen)")) + ((char-equal mark mew-mark-tmp) + (setq flag "-FLAGS (\\Flagged)"))) + (mew-imap-process-send-string + pro pnm "UID STORE %s %s" msg flag)) + (t + (mew-imap-set-status pnm "post-select") + (mew-imap-command-post-select pro pnm))))) + +(defun mew-imap-command-uid (pro pnm) + (let ((directive (mew-imap-get-directive pnm)) + (refs (mew-imap-get-refs pnm)) + (rmvs (mew-imap-get-rmvs pnm)) + (bnm (mew-imap-get-bnm pnm)) + (range (mew-imap-get-range pnm)) + max) + (if (and mew-imap-skip-uidl + (or (eq directive 'exec) (eq directive 'jobs))) + (mew-imap-command-dispatch pro pnm directive refs rmvs nil) + (mew-net-status (mew-imap-get-status-buf pnm) + "Checking" nil (mew-imap-secure-p pnm)) + (if (eq directive 'get) + (mew-imap-process-send-string + pro pnm "UID FETCH %s:%s (UID RFC822.SIZE FLAGS)" + (mew-refileinfo-get-uid (car refs)) + (mew-refileinfo-get-uid (nth (1- (length refs)) refs))) + (cond + ((eq directive 'biff) + (setq max (mew-lisp-load (mew-expand-file bnm mew-imap-msgid-file)))) + ((eq directive 'scan) + (if (eq range nil) ;; update + (setq max (mew-lisp-load + (mew-expand-file bnm mew-imap-msgid-file)))))) + (if max + (setq max (string-to-number max)) + (setq max 0)) + (mew-imap-set-max pnm max) + (mew-imap-process-send-string + pro pnm "UID FETCH %d:* (UID RFC822.SIZE FLAGS)" (1+ max)))))) + +(defun mew-imap-command-umsg (pro pnm) + (let* ((directive (mew-imap-get-directive pnm)) + (max (mew-imap-get-max pnm)) + (refs (mew-imap-get-refs pnm)) + (rmvs (mew-imap-get-rmvs pnm)) + (del-time (mew-imap-get-delete pnm)) + (range (mew-imap-get-range pnm)) + (ctime (current-time)) + rtr rtrs dels uid siz uidl old-uidl uid-time hlds flags mdb) + (if (eq directive 'inc) + (setq old-uidl (mew-net-uidl-db-get (mew-imap-passtag pnm)))) + (goto-char (point-min)) + (while (re-search-forward "^\\* [0-9]+ FETCH (" nil t) + (when (looking-at ".*UID \\([0-9]+\\)") + (setq uid (mew-match-string 1))) + (when (looking-at ".*RFC822.SIZE \\([0-9]+\\)") + (setq siz (mew-match-string 1))) + (when (looking-at ".*FLAGS (\\([^)]*\\)") ;; MUST be a list of flags + (setq flags (mew-match-string 1)) + (if (string-match "Flagged" flags) ;; \\\\ is urgly + (setq mdb (cons (list uid mew-mark-review) mdb)) + (if (string-match "Seen" flags) + (setq mdb (cons (list uid mew-mark-read) mdb))))) + (cond + ((or (eq directive 'exec) (eq directive 'jobs) (eq directive 'get)) + (cond + ((setq rtr (assoc uid refs)) + (setq rtrs (cons rtr rtrs))) + ((member uid rmvs) + (setq dels (cons uid dels))))) + ((eq directive 'biff) + (if (and uid (> (string-to-number uid) max)) + (setq rtrs (cons (mew-make-refileinfo :uid uid :size siz) rtrs)))) + ((eq directive 'scan) + (if (and uid (or range ;; all, last:n + (> (string-to-number uid) max))) ;; update + (setq rtrs (cons (mew-make-refileinfo :uid uid :size siz) rtrs)))) + ((eq directive 'sync) + (if uid (setq hlds (cons uid hlds)))) + ((eq directive 'inc) + (if uid (setq uid-time (cdr (assoc uid old-uidl)))) + (cond + (uid-time + (setq uidl (cons (cons uid uid-time) uidl)) + (if (mew-expired-p uid-time del-time) + (setq dels (cons uid dels)))) + (t + (setq uidl (cons (cons uid ctime) uidl)) + (if (eq del-time t) + (setq dels (cons uid dels))) + (setq rtr (mew-make-refileinfo :uid uid :size siz)) + (setq rtrs (cons rtr rtrs))))))) + (mew-imap-set-msgid pnm (or (mew-refileinfo-get-uid (car rtrs)) max)) ;; 'scan + (mew-imap-set-uidl pnm uidl) ;; 'inc + ;; last:n + (when (and (eq directive 'scan) (integerp range)) + (mew-ntake range rtrs)) + (setq rtrs (nreverse rtrs)) + (setq dels (nreverse dels)) + (setq hlds (nreverse hlds)) + (mew-imap-set-mdb pnm (nreverse mdb)) + (mew-imap-command-dispatch pro pnm directive rtrs dels hlds))) + +(defun mew-imap-command-dispatch (pro pnm directive rtrs dels hlds) + (cond + ((or (eq directive 'exec) (eq directive 'jobs)) + ;; '((uid1 siz1 t (dst1 dst2)) + ;; (uid2 siz2 t (dst1)) + ;; (uid3 siz3 nil (dst1 dst2)) + ;; (uid4 siz4 nil (dst3))) + ;; => + ;; '((dst1 uid1 uid2) + ;; (dst2 uid1 uid2 uid3) + ;; (dst3 uid4)) + ;; dels2 = (uid1 uid2) + ;; => + ;; '((dst1 uid1,uid2) + ;; (dst2 uid1,uid2) + ;; (dst2 uid3) + ;; (dst3 uid4)) + (let (uid del fld flds ents dels2 fld-uids uids) + (setq ents rtrs) + (setq rtrs nil) + (dolist (ent ents) + (setq uid (mew-refileinfo-get-uid ent)) + (setq del (mew-refileinfo-get-delete ent)) + (setq flds (mew-refileinfo-get-folders ent)) + (if del (setq dels2 (cons uid dels2))) + (dolist (fld flds) + (if (setq fld-uids (assoc fld rtrs)) + (nconc fld-uids (list uid)) + (setq rtrs (cons (list fld uid) rtrs))))) + ;; + (setq ents rtrs) + (setq rtrs nil) + (dolist (ent ents) + (setq fld (car ent)) + (setq uids (cdr ent)) + (setq uids (mew-net-msg-group uids)) + (setq uids (mapcar (lambda (arg) (mew-make-copyinfo :dst fld :uid arg)) uids)) + (setq rtrs (nconc rtrs uids))) + ;; + (mew-imap-set-rtrs pnm rtrs) + (mew-imap-set-rgttl pnm (length rtrs)) + ;; + (setq dels (mew-net-msg-group dels)) + (setq dels2 (nreverse dels2)) + (setq dels2 (mew-net-msg-group dels2)) + (setq dels (nconc dels dels2)))) + (t + (mew-imap-set-rttl pnm (length rtrs)) + (mew-imap-set-rtrs pnm rtrs) + (mew-imap-set-dttl pnm (length dels)) + ;; We can't use mew-net-msg-group since a member will be + ;; deleted from dels. + ;; (setq dels (mew-net-msg-group dels)) + )) + ;; + (mew-imap-set-dels pnm dels) + (mew-imap-set-dgttl pnm (length dels)) + (mew-imap-set-hlds pnm hlds) + (mew-imap-set-dispatched pnm t) + (cond + ((or (eq directive 'sync) (eq directive 'biff)) + (mew-imap-set-status pnm "logout") + (mew-imap-command-logout pro pnm)) + ((or (eq directive 'exec) (eq directive 'jobs)) + (if rtrs + (mew-imap-command-pre-copy pro pnm) + (mew-imap-command-pre-dels pro pnm))) + (t ;; 'get and 'inc + (mew-imap-command-pre-fetch pro pnm)))) + +(defun mew-imap-command-pre-copy (pro pnm) + (let ((rtt (length (mew-imap-get-rtrs pnm))) + (rttl (mew-imap-get-rttl pnm)) + (dttl (mew-imap-get-dttl pnm)) + (jcnt (mew-imap-get-jcnt pnm))) + (cond + ((= rtt 0) ;; should not occur + (mew-imap-set-status pnm "dels") ;; logout + (mew-imap-command-dels pro pnm)) + (t + (cond + (jcnt + (cond + ((= jcnt 1) + (mew-imap-message pnm "Processing 1 job in background...")) + (t + (mew-imap-message pnm "Processing %d jobs in background..." jcnt)))) + ((= rttl 0) + (cond + ((= dttl 1) + (mew-imap-message pnm "Deleting 1 message in background...")) + (t + (mew-imap-message pnm "Deleting %d messages in background..." dttl)))) + ((= rttl 1) + (mew-imap-message pnm "Refiling 1 message in background...")) + (t + (mew-imap-message pnm "Refiling %d messages in background..." rttl))) + (mew-imap-set-status pnm "copy") + (mew-imap-command-copy pro pnm))))) + +(defun mew-imap-command-copy (pro pnm) + (mew-net-status1 + (mew-imap-get-status-buf pnm) "Refiling" + (mew-imap-get-rgttl pnm) (mew-imap-get-rgcnt pnm) (mew-imap-secure-p pnm)) + (let* ((case (mew-imap-get-case pnm)) + (spam (mew-imap-get-spam pnm)) + (rtrs (mew-imap-get-rtrs pnm)) + (rtr (car rtrs)) + (dst (mew-copyinfo-get-dst rtr)) + (uid (mew-copyinfo-get-uid rtr))) + (if (null rtr) + (cond + ((mew-imap-get-dels pnm) + (mew-imap-set-status pnm "dels") + (mew-imap-command-dels pro pnm)) + (t + (mew-imap-set-status pnm "logout") + (mew-imap-command-logout pro pnm))) + (mew-imap-set-rgcnt pnm (1+ (mew-imap-get-rgcnt pnm))) + (mew-imap-set-rtrs pnm (cdr rtrs)) + (setq dst (mew-imap-expand-mailbox + case (mew-imap-utf-7-encode-string dst))) + (mew-imap-set-rfl pnm rtr) + (if spam + (mew-imap-process-send-string pro pnm "COPY %s \"%s\"" uid dst) + (mew-imap-process-send-string pro pnm "UID COPY %s \"%s\"" uid dst))))) + +(defun mew-imap-command-create (pro pnm) + (let* ((case (mew-imap-get-case pnm)) + (rtrs (mew-imap-get-rtrs pnm)) + (rtr (mew-imap-get-rfl pnm)) + (dst (mew-copyinfo-get-dst rtr))) ;; 'exec or 'jobs + (mew-imap-set-rgcnt pnm (1- (mew-imap-get-rgcnt pnm))) + (mew-imap-set-rtrs pnm (cons rtr rtrs)) + (setq dst (mew-imap-expand-mailbox + case (mew-imap-utf-7-encode-string dst))) + (mew-imap-process-send-string pro pnm "CREATE \"%s\"" dst))) + +(defun mew-imap-escape-format (str) + (if (mew-folder-imapp str) (concat "%" str) str)) + +(defun mew-imap-command-wmbx (pro pnm) + (let* ((rtr (mew-imap-get-rfl pnm)) + (dst (mew-copyinfo-get-dst rtr))) + (mew-imap-set-error pnm (format "Cannot create '%s' or the messages do not exist" (mew-imap-escape-format dst))) + (mew-imap-set-status pnm "logout2") + (mew-imap-command-logout2 pro pnm))) + +(defun mew-imap-command-pre-dels (pro pnm) + (let ((dtt (length (mew-imap-get-dels pnm))) + (dttl (mew-imap-get-dttl pnm)) + (jcnt (mew-imap-get-jcnt pnm))) + (cond + ((= dtt 0) ;; should not occur + (mew-imap-set-status pnm "logout") + (mew-imap-command-logout pro pnm)) + (t + (cond + (jcnt + (cond + ((= jcnt 1) + (mew-imap-message pnm "Processing 1 job in background...")) + (t + (mew-imap-message pnm "Processing %d jobs in background..." jcnt)))) + ((= dttl -1) + (mew-imap-message pnm "Deleting all messages in background...")) + ((= dttl 1) + (mew-imap-message pnm "Deleting 1 message in background...")) + (t + (mew-imap-message pnm "Deleting %d messages in background..." dttl))) + (mew-imap-set-status pnm "dels") + (mew-imap-command-dels pro pnm))))) + +(defun mew-imap-command-dels (pro pnm) + (mew-net-status1 + (mew-imap-get-status-buf pnm) "Deleting" + (mew-imap-get-dgttl pnm) (mew-imap-get-dgcnt pnm) (mew-imap-secure-p pnm)) + (let ((dels (mew-imap-get-dels pnm)) + (spam (mew-imap-get-spam pnm)) + num) + (cond + (dels + (mew-imap-set-dgcnt pnm (1+ (mew-imap-get-dgcnt pnm))) + (setq num (car dels)) + (mew-imap-set-dels pnm (cdr dels)) + (if spam + (mew-imap-process-send-string + pro pnm "STORE %s +FLAGS (\\Deleted)" num) + (mew-imap-process-send-string + pro pnm "UID STORE %s +FLAGS (\\Deleted)" num))) + (t + (mew-imap-set-status pnm "expunge") + (mew-imap-command-expunge pro pnm))))) + +;; + +(defun mew-imap-command-search (pro pnm) + (mew-net-status + (mew-imap-get-status-buf pnm) "Filtering" nil (mew-imap-secure-p pnm)) + (let ((pattern (mew-imap-get-spam-pattern pnm))) + (if pattern + (mew-imap-process-send-string pro pnm "SEARCH %s" pattern) + (mew-imap-process-send-string + pro pnm "SEARCH HEADER %s %s" + (mew-imap-get-spam-field pnm) + (mew-imap-get-spam-word pnm))))) + +(defun mew-imap-command-post-search (pro pnm) + (let* ((case (mew-imap-get-case pnm)) + (trash (or (mew-imap-spam-folder case) (mew-imap-trash-folder case))) + dels rtrs beg) + (goto-char (point-min)) + (mew-crlf-to-lf) + (goto-char (point-min)) + (when (looking-at "^\\* SEARCH ") + (setq beg (match-end 0)) + (goto-char (point-max)) + (forward-line -1) + (if (bolp) (forward-char -1)) + (setq dels (mew-split (mew-buffer-substring beg (point)) mew-sp)) + (when trash + (setq rtrs (copy-sequence dels)) + (mew-imap-set-rttl pnm (length rtrs)) + (setq rtrs (mew-net-msg-group rtrs)) + (setq rtrs (mapcar (lambda (arg) (mew-make-copyinfo :dst trash :uid arg)) rtrs)) + (mew-imap-set-rtrs pnm rtrs) + (mew-imap-set-rgttl pnm (length rtrs))) + (mew-imap-set-dttl pnm (length dels)) + (setq dels (mew-net-msg-group dels)) + (mew-imap-set-dels pnm dels) + (mew-imap-set-dgttl pnm (length dels))) + (cond + (rtrs + (mew-imap-command-pre-copy pro pnm)) + (dels + (mew-imap-command-pre-dels pro pnm)) + (t + (mew-imap-set-status pnm "uid") + (mew-imap-command-uid pro pnm))))) + +;; + +(defun mew-imap-command-pre-fetch (pro pnm) + (let* ((rtt (length (mew-imap-get-rtrs pnm)))) + (cond + ((= rtt 0) + (mew-imap-message pnm "No new messages") + (mew-imap-command-logout pro pnm)) + ((= rtt 1) + (mew-imap-message pnm "Retrieving 1 message in background...") + (mew-imap-set-status pnm "fetch") + (mew-imap-command-fetch pro pnm)) + (t + (mew-imap-message pnm "Retrieving %d messages in background..." rtt) + (mew-imap-set-status pnm "fetch") + (mew-imap-command-fetch pro pnm))))) + +(defun mew-imap-command-fetch (pro pnm) + (mew-net-status2 (mew-imap-get-status-buf pnm) + (mew-imap-get-rttl pnm) + (mew-imap-get-rcnt pnm) + (mew-refileinfo-get-size (car (mew-imap-get-rtrs pnm))) + 'zero + (mew-imap-secure-p pnm)) + (let* ((directive (mew-imap-get-directive pnm)) + (rtrs (mew-imap-get-rtrs pnm)) + (dels (mew-imap-get-dels pnm)) + (rtr (car rtrs)) + (uid (mew-refileinfo-get-uid rtr)) + (siz (mew-refileinfo-get-size rtr)) + (lim (mew-imap-get-size pnm)) + (get-body (mew-imap-get-get-body pnm))) + (cond + ((or (null rtr) (eq directive 'biff)) + (mew-imap-set-truncated pnm nil) + (if dels + (progn + (mew-imap-set-status pnm "dels") + (mew-imap-command-dels pro pnm)) + (mew-imap-set-status pnm "logout") + (mew-imap-command-logout pro pnm))) + ((or (eq directive 'exec) (eq directive 'jobs) (eq directive 'get)) + (mew-imap-set-truncated pnm nil) + ;; RFC822 turns the Seen flag "on" + ;; BODY.PEEK[] keeps the Seen flag "off" + (mew-imap-process-send-string pro pnm "UID FETCH %s BODY.PEEK[]" uid)) + ((and (eq directive 'scan) (not get-body)) + (mew-imap-set-truncated pnm t) + (mew-imap-process-send-string pro pnm "UID FETCH %s BODY.PEEK[HEADER]" uid)) + ((or (= lim 0) (< (string-to-number siz) lim)) + (mew-imap-set-truncated pnm nil) + (mew-imap-process-send-string pro pnm "UID FETCH %s BODY.PEEK[]" uid)) + (t + (mew-imap-set-truncated pnm t) + (mew-imap-process-send-string + pro pnm "UID FETCH %s BODY.PEEK[HEADER]" uid))))) + +(defun mew-imap-command-post-fetch (pro pnm) + (let* ((directive (mew-imap-get-directive pnm)) + (width (1- (mew-scan-width))) + (rtrs (mew-imap-get-rtrs pnm)) + (rtr (car rtrs)) + (uid (mew-refileinfo-get-uid rtr)) + (siz (mew-refileinfo-get-size rtr)) + (del (mew-refileinfo-get-delete rtr)) + (union (mew-refileinfo-get-folders rtr)) ;; 'exec, 'jobs, 'scan, ... + (truncated (mew-imap-get-truncated pnm)) + (case (mew-imap-get-case pnm)) + fld msg vec file msg-file lmsg mark folder) + (cond + ((or (eq directive 'exec) (eq directive 'jobs)) + (setq fld (car union))) + ((eq directive 'get) + (mew-set '(fld msg) union) + (setq lmsg msg)) + (t ;; 'biff, 'scan, 'sync + (setq fld (mew-imap-get-bnm pnm)))) + (setq folder (mew-case:folder-folder fld)) + ;; line delimiters + (goto-char (point-min)) + (mew-crlf-to-lf) + (cond + ((eq directive 'scan) + (setq msg uid) + (setq file (mew-expand-new-msg fld msg))) + (t + (setq msg-file (mew-net-get-new-message + pnm fld msg 'mew-imap-get-msgdb 'mew-imap-set-msgdb)) + (setq msg (car msg-file) file (cdr msg-file)))) + (goto-char (point-min)) + (cond + (truncated + (mew-header-insert-xmu uid siz t (and (eq directive 'inc) + (or (mew-imap-get-case pnm) + mew-case-default)))) + ((eq directive 'scan) + (mew-header-insert-xmu uid siz nil)) + ((and (eq directive 'get) (mew-folder-imapp folder)) + (mew-header-insert-xmu uid siz nil))) + (catch 'write-error + (condition-case nil + (let ((write-region-inhibit-fsync mew-use-async-write)) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region (point-min) (point-max) file nil 'no-msg))) + (error + (mew-imap-set-status pnm "logout") + (mew-imap-command-logout pro pnm) + (throw 'write-error nil))) + (mew-imap-set-rcnt pnm (1+ (mew-imap-get-rcnt pnm))) + (when (file-exists-p file) + (mew-set-file-modes file) + (unless (string= folder (mew-imap-trash-folder case)) + (mew-set-file-type file)) + ;; + (mew-set-buffer-multibyte t) + (setq vec (mew-scan-header)) + (mew-scan-set-folder vec fld) + (mew-scan-set-message vec msg) + (if (and (eq directive 'scan) + (string= folder mew-imap-inbox-folder)) + (setq mark (mew-scan-inbox-action vec case))) + (mew-scan-body vec) + (mew-set-buffer-multibyte nil) + (mew-scan-insert-line fld vec width lmsg mark)) + (mew-imap-set-rtrs pnm (cdr rtrs)) + (cond + ((eq directive 'inc) + (if truncated + (mew-imap-set-dels pnm (delete uid (mew-imap-get-dels pnm))))) + ((eq directive 'get) + (if del (mew-imap-set-dels pnm (cons uid (mew-imap-get-dels pnm)))))) + (mew-imap-set-status pnm "fetch") + (mew-imap-set-bytes pnm nil) + (mew-imap-command-fetch pro pnm)))) + +(defun mew-imap-command-expunge (pro pnm) + (mew-imap-process-send-string pro pnm "EXPUNGE")) + +(defun mew-imap-command-post-expunge (pro pnm) + (if (mew-imap-get-spam pnm) + (progn + (mew-imap-set-status pnm "uid") + (mew-imap-command-uid pro pnm )) + (mew-imap-set-status pnm "logout") + (mew-imap-command-logout pro pnm))) + +(defun mew-imap-command-namespace (pro pnm) + (mew-imap-process-send-string pro pnm "NAMESPACE")) + +(defun mew-imap-read-sexp () + (condition-case nil + (read (current-buffer)) + (error ()))) + +(defun mew-imap-command-post-namespace (pro pnm) + (when (looking-at "^\\* NAMESPACE ") + (let* ((beg (match-end 0)) + (case (mew-imap-get-case pnm)) + (prefix-list (mew-imap-prefix-list case)) + (my-prefix "") + user-prefix sexp sep sharp namespace ent my sp specials) + (goto-char (point-max)) + (forward-line -1) + (save-restriction + (narrow-to-region beg (point)) ;; xxx (1- (point))? + (goto-char (point-min)) + (while (search-forward "NIL" nil t) + (replace-match "nil" t t)) + (goto-char (point-min)) + (setq sexp (mew-imap-read-sexp)) + (cond + ((null prefix-list) + (setq ent (car sexp)) + (setq my-prefix (nth 0 ent)) + (setq sep (nth 1 ent))) + (t + (dolist (ent sexp) + (mew-set '(my sp) ent) + (when (member my prefix-list) + (cond + (sp + (setq my-prefix my) + (setq sep sp)) + (t + (setq specials (cons (cons (concat mew-folder-imap my) my) specials)))))))) + (mew-imap-set-my-prefix pnm my-prefix) + (mew-imap-set-specials pnm specials) + (setq sexp (mew-imap-read-sexp)) + (setq user-prefix (or (nth 0 (car sexp)) "")) + (setq sexp (mew-imap-read-sexp)) + (setq sharp (mew-assoc-match "^#" sexp 0))) + (setq namespace (mew-imap-namespace-create sep my-prefix user-prefix sharp)) + (mew-imap-set-namespace pnm namespace))) + (mew-imap-set-status pnm "list") + (mew-imap-command-list pro pnm)) + +(defun mew-imap-command-list (pro pnm) + (mew-net-status (mew-imap-get-status-buf pnm) + "Listing" + nil + (mew-imap-secure-p pnm)) + (let* ((my-prefix (mew-imap-get-my-prefix pnm)) + (case (mew-imap-get-case pnm)) + (prefix-list (mew-imap-prefix-list case))) + (mew-imap-message pnm "Collecting mailbox list...") + (mew-imap-process-send-string pro pnm "LIST \"%s\" *" (or (and prefix-list my-prefix) "")))) + +(defun mew-imap-command-post-list (pro pnm) + (let* ((case (mew-imap-get-case pnm)) + (queue (mew-imap-queue-folder case)) + (namespace (mew-imap-get-namespace pnm)) + (specials (mew-imap-get-specials pnm)) + ret mailboxes friends) + (unless namespace + (setq namespace (mew-imap-namespace-create nil "" "" nil)) ;; xxx separator? + (mew-imap-set-namespace pnm namespace)) + (setq ret (mew-imap-command-post-list-tree namespace case)) + (mew-set '(mailboxes friends) ret) + (unless case (setq case mew-case-default)) + (if specials (setq mailboxes (nconc specials mailboxes))) + (if queue (mew-folder-insert queue mailboxes nil)) + (mew-imap-folder-set case mailboxes friends) + (mew-imap-set-status pnm "logout") + (mew-imap-command-logout pro pnm))) + +(defun mew-imap-command-post-list-tree (namespace case) + (let* ((case-fold-search t) + (my (format "^%s" (regexp-quote + (or (mew-imap-namespace-my-prefix namespace) "")))) + (user (format "^%s" (regexp-quote + (or (mew-imap-namespace-user-prefix namespace) "")))) + (sep (mew-imap-namespace-sep namespace)) + subfolder friendp mbx mailbox mailboxes subnm friends) + (goto-char (point-min)) + (mew-crlf-to-lf) + (goto-char (point-min)) + (when sep + (setq subfolder (format "\\([^%s\n\r]+\\)$" sep)) + (setq friendp (mew-imap-friend-regex sep case))) + (while (not (eobp)) + (catch 'break + (when (looking-at "^\\* LIST ([^)\n]*) \"?\\([^\"\n]*\\)\"? \"?\\([^\"\n]*\\)\"?") + (unless sep + ;; NAMESPACE may return NIL NIL NIL + (setq sep (mew-match-string 1)) + (mew-imap-namespace-change-sep namespace sep) + (setq subfolder (format "\\([^%s\n\r]+\\)$" sep)) + (setq friendp (mew-imap-friend-regex sep case))) + (setq mbx (mew-match-string 2)) + (setq mbx (mew-imap-utf-7-decode-string mbx)) + (cond + ((mew-imap-inbox-str-p mbx) + (throw 'break nil)) + ((string-match my mbx) + (setq mbx (substring mbx (match-end 0))) + (setq mailbox (concat mew-folder-imap mbx)) + (cond + ((string-match friendp mailbox) + (setq friends (cons mailbox friends)) + (setq mailboxes (cons (mew-folder-func mailbox) mailboxes))) + ((string-match subfolder mbx) + (setq subnm (match-string 1 mbx)) + (setq mailboxes (cons (mew-folder-func mailbox subnm) mailboxes))))) + ((string-match user mbx) + (setq mbx (substring mbx (match-end 0))) + (setq mailbox (concat mew-folder-imap "~" mbx)) + (when (string-match subfolder mbx) + (setq subnm (match-string 1 mbx)) + (setq mailboxes (cons (mew-folder-func mailbox subnm) mailboxes)))) + (t + (setq mailbox (concat mew-folder-imap "#" mbx)) + (when (string-match subfolder mbx) + (setq subnm (match-string 1 mbx)) + (setq mailboxes (cons (mew-folder-func mailbox subnm) mailboxes))))))) + (forward-line)) + (setq mailboxes (sort mailboxes (lambda (x y) (string< (car x) (car y))))) + (setq mailboxes (cons namespace mailboxes)) + (mew-imap-mailbox-arrange mailboxes sep) + (setq friends (sort friends 'string<)) + (list mailboxes friends))) + +(defun mew-imap-mailbox-arrange (lst sep) + (let ((sep-char (string-to-char sep)) + prv fst nxt len1 len2) + (setq prv lst) + (setq fst (car (car lst))) + (setq len1 (length fst)) + (setq lst (cdr lst)) + (while lst + (setq nxt (car (car lst))) + (setq len2 (length nxt)) + (when (and (< len1 len2) + (char-equal (aref nxt len1) sep-char) + (string= fst (substring nxt 0 len1))) + (setcar (car prv) (concat fst sep))) + (setq fst nxt) + (setq prv lst) + (setq lst (cdr lst)) + (setq len1 len2)))) + +(defun mew-imap-command-delete (pro pnm) + (mew-net-status (mew-imap-get-status-buf pnm) + "Deleting" + nil + (mew-imap-secure-p pnm)) + (mew-imap-message pnm "Deleting this folder...") + (let ((mailbox (mew-imap-get-mailbox pnm))) + (mew-imap-process-send-string pro pnm "DELETE \"%s\"" mailbox))) + +(defun mew-imap-command-rename (pro pnm) + (mew-net-status (mew-imap-get-status-buf pnm) + "Renaming" + nil + (mew-imap-secure-p pnm)) + (mew-imap-message pnm "Deleting this folder...") + (mew-imap-message pnm "Renaming this folder...") + (let ((old (mew-imap-get-mailbox pnm)) + (new (mew-imap-get-new-mailbox pnm))) + (mew-imap-process-send-string pro pnm "RENAME \"%s\" \"%s\"" old new))) + +(defun mew-imap-command-logout (pro pnm) + (let ((directive (mew-imap-get-directive pnm))) + (cond + ((eq directive 'jobs) + (mew-queue-backup (mew-imap-get-wrk pnm) mew-imapq-info-suffix) + (if (mew-imap-get-jobs pnm) + (progn + (mew-imap-set-status pnm "next") + (mew-imap-command-next pro pnm)) + (mew-imap-set-done pnm t) + (mew-imap-process-send-string pro pnm "LOGOUT"))) + (t + (mew-imap-set-done pnm t) + (mew-imap-process-send-string pro pnm "LOGOUT"))))) + +(defun mew-imap-command-logout2 (pro pnm) + (let ((wrk (mew-imap-get-wrk pnm))) + (if wrk (mew-queue-enqueue2 wrk))) + (mew-imap-process-send-string pro pnm "LOGOUT")) + +(defun mew-imap-command-logout3 (pro pnm) + (mew-imap-process-send-string pro pnm "LOGOUT")) + +(defun mew-imap-command-noop (pro pnm) + ()) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; AUTH +;;; + +(defvar mew-imap-auth-alist + '(("CRAM-MD5" mew-imap-command-auth-cram-md5) + ("LOGIN" mew-imap-command-auth-login))) + +(defun mew-imap-auth-get-func (auth) + (nth 1 (mew-assoc-case-equal auth mew-imap-auth-alist 0))) + +(defun mew-imap-command-auth-cram-md5 (pro pnm) + (mew-imap-process-send-string pro pnm "AUTHENTICATE CRAM-MD5") + (mew-imap-set-status pnm "auth-cram-md5")) + +(defun mew-imap-command-pwd-cram-md5 (pro pnm) + (let ((user (mew-imap-get-user pnm)) + (prompt (format "IMAP CRAM-MD5 password (%s): " + (mew-imap-get-account pnm))) + challenge passwd cram-md5) + (save-excursion + (goto-char (point-min)) + (if (re-search-forward " \\([a-zA-Z0-9+/]+=*\\)" nil t) + (setq challenge (mew-match-string 1)))) + (setq passwd (mew-imap-input-passwd prompt pnm)) + (setq cram-md5 (mew-cram-md5 user passwd challenge)) + (mew-imap-process-send-string2 pro cram-md5))) + +(defun mew-imap-command-auth-login (pro pnm) + (mew-imap-process-send-string pro pnm "AUTHENTICATE LOGIN") + (mew-imap-set-status pnm "auth-login")) + +(defun mew-imap-command-user-login (pro pnm) + (let* ((user (mew-imap-get-user pnm)) + (euser (mew-base64-encode-string user))) + (mew-imap-process-send-string2 pro euser))) + +(defun mew-imap-command-pwd-login (pro pnm) + (let* ((prompt (format "IMAP LOGIN password (%s): " + (mew-imap-get-account pnm))) + (passwd (mew-imap-input-passwd prompt pnm)) + (epasswd (mew-base64-encode-string passwd))) + (mew-imap-process-send-string2 pro epasswd))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub functions +;;; + +(defconst mew-imap-info-prefix "mew-imap-info-") + +(defun mew-imap-info-name (case mailbox) + (let ((server (mew-imap-server case)) + (port (mew-*-to-string (mew-imap-port case))) + (sshsrv (mew-imap-ssh-server case)) + (name mew-imap-info-prefix)) + (setq name (concat name server "/" mailbox)) + (unless (mew-port-equal port mew-imap-port) + (setq name (concat name ":" port))) + (if sshsrv + (concat name "%" sshsrv) + name))) + +(defun mew-imap-buffer-name (pnm) + (concat mew-buffer-prefix pnm)) + +(defun mew-imap-process-send-string (pro pnm &rest args) + (let ((str (apply 'format args)) + (tag (mew-imap-tag))) + (mew-imap-debug "=SEND=" (concat tag " " str)) + (mew-imap-set-tag pnm tag) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-string pro (concat tag " " str mew-cs-eol)) + (message "IMAP time out")))) + +(defun mew-imap-process-send-string2 (pro &rest args) + (let ((str (apply 'format args))) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-string pro (concat str mew-cs-eol)) + (message "IMAP time out")))) + +(defun mew-imap-message (pnm &rest args) + (or (mew-imap-get-no-msg pnm) (apply 'message args))) + +(defun mew-imap-tag () + (format "%s%04d" (mew-random-string 4 nil) (% (mew-random) 10000))) + +(defun mew-imap-passtag (pnm) + (let ((server (mew-imap-get-server pnm)) + (port (mew-imap-get-port pnm)) + (user (mew-imap-get-user pnm))) + (concat user "@" server ":" port))) + +(defun mew-imap-passtag2 (case) + (let ((server (mew-imap-server case)) + (port (mew-imap-port case)) + (user (mew-imap-user case))) + (concat user "@" server ":" port))) + +(defun mew-imap-input-passwd (prompt pnm) + (let ((directive (mew-imap-get-directive pnm)) + (pro (mew-imap-get-process pnm)) + (tag (mew-imap-passtag pnm)) + pass) + (if (eq directive 'biff) + (or (mew-imap-get-passwd pnm) ;; mew-imap-biff + (mew-input-passwd prompt tag)) ;; mew-imap-check + (setq pass (mew-input-passwd prompt tag)) + (unless (and (processp pro) (eq (process-status pro) 'open)) + (mew-passwd-set-passwd tag nil)) + pass))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Namespace +;;; + +(defvar mew-imap-namespace-length 5) + +(defun mew-imap-namespace-create (sep my-prefix user-prefix sharp) + (mew-folder-func mew-imap-inbox-folder (list sep my-prefix user-prefix sharp))) + +(defun mew-imap-namespace (case) + (let* ((alist (mew-imap-folder-alist case)) + (namespace (assoc mew-imap-inbox-folder alist))) + (if (= (length namespace) mew-imap-namespace-length) + namespace + (error (mew-substitute-for-summary "Type '\\[universal-argument]\\[mew-status-update]' to collect IMAP folders!"))))) + +(defun mew-imap-namespace-sep (namespace) + (nth 1 namespace)) + +(defun mew-imap-namespace-change-sep (namespace sep) + (setcar (nthcdr 1 namespace) sep)) + +(defun mew-imap-namespace-my-prefix (namespace) + (nth 2 namespace)) + +(defun mew-imap-namespace-user-prefix (namespace) + (nth 3 namespace)) + +(defun mew-imap-namespace-sharp (namespace) + (nth 4 namespace)) + +(defun mew-imap-separator (case) + (mew-imap-namespace-sep (mew-imap-namespace case))) + +(defun mew-imap-directory-file-name (dir case) + ;; inbox.foo. => inbox.foo + (let* ((sep (mew-imap-separator case)) + (sep-char (string-to-char sep)) + (len (1- (length dir)))) + (if (char-equal sep-char (aref dir len)) + (substring dir 0 len) + dir))) + +(defun mew-imap-file-name-as-directory (dir case) + ;; inbox.foo => inbox.foo. + (let* ((sep (mew-imap-separator case)) + (sep-char (string-to-char sep)) + (len (1- (length dir)))) + (if (char-equal sep-char (aref dir len)) + dir + (concat dir sep)))) + +;;; + +(defun mew-imap-bnm-to-mailbox (bnm) + " + case:%inbox -> inbox + case:%foo -> inbox.foo + case:%~foo -> user.foo + case:%#foo -> foo" + (let ((case (mew-case:folder-case bnm)) + (folder (mew-case:folder-folder bnm))) + (mew-imap-expand-mailbox case folder))) + +(defun mew-imap-expand-mailbox (case folder) + "%inbox -> inbox + %foo -> inbox.foo + %~foo -> user.foo + %#foo -> foo" + (when (stringp folder) + (setq folder (mew-imap-directory-file-name folder case)) + (let* ((str (mew-folder-string folder)) + (c (aref str 0)) + (substr (substring str 1)) + (namespace (mew-imap-namespace case)) + (my-prefix (mew-imap-namespace-my-prefix namespace)) + (user-prefix (mew-imap-namespace-user-prefix namespace)) + (sharp (mew-imap-namespace-sharp namespace))) + (cond + ((char-equal c ?~) + (if user-prefix (concat user-prefix substr) substr)) + ((char-equal c ?#) + (if sharp str substr)) + ((string= str mew-imap-inbox-string) + mew-imap-inbox-string) + (t + (if my-prefix (concat my-prefix str) str)))))) + +(defun mew-imap-expand-folder (case str) + " + foo -> foo + ~foo -> user.foo + #foo -> #foo +" + (when (and (stringp str) (not (string= str ""))) + (if (char-equal (aref str 0) ?~) + (let* ((namespace (mew-imap-namespace case)) + (user-prefix (mew-imap-namespace-user-prefix namespace))) + (concat "#" user-prefix (substring str 1))) + str))) + +;; Mew cache IMAP +;; folder directory mailbox +;; +;; WU +;; %foo foo foo +;; %foo/bar foo/bar foo/bar +;; %~alice/foo #~alice/foo ~alice/foo "~" -> "~" +;; %#shared.foo #shared.foo #shared.foo +;; +;; Cyrus +;; %foo foo inbox.foo +;; %foo.bar foo.bar inbox.foo.bar +;; %~alice.foo #user.alice.foo user.alice.foo +;; %#shared.foo #shared.foo shared.foo +;; +;; Courier +;; %foo foo inbox.foo +;; %foo.bar foo.bar inbox.foo.bar +;; %~alice.foo N/A N/A +;; %#shared.foo #shared.foo shared.foo + +(defun mew-imap-local-to-imap (case str) + (let* ((sep (mew-imap-separator case)) + (fld (copy-sequence str))) + (aset fld 0 ?%) + (unless (string= sep mew-path-separator) + (mew-replace-character fld ?/ (string-to-char sep))) + fld)) + +(defun mew-imap-fcc-to-mailbox (case fld) + (let* ((namespace (mew-imap-namespace case)) + (my-prefix (mew-imap-namespace-my-prefix namespace)) + (ret (substring fld (1+ (length mew-folder-imap-fcc-prefix))))) + (if (string= ret mew-imap-inbox-string) + mew-imap-inbox-string + (if my-prefix (concat my-prefix ret) ret)))) + +(defun mew-imap-friend-regex (sep case) + (format "^%s%s" + (regexp-quote (mew-imap-friend-folder case)) + (regexp-quote sep))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Opening IMAP +;;; + +(defun mew-imap-open (pnm server port no-msg) + (let ((sprt (mew-*-to-port port)) + pro tm) + (condition-case emsg + (progn + (setq tm (run-at-time mew-imap-timeout-time nil 'mew-imap-timeout)) + (or no-msg (message "Connecting to the IMAP server...")) + (setq pro (open-network-stream pnm nil server sprt)) + (mew-process-silent-exit pro) + (mew-set-process-cs pro mew-cs-binary mew-cs-text-for-net) + (or no-msg (message "Connecting to the IMAP server...done"))) + (quit + (or no-msg (message "Cannot connect to the IMAP server")) + (setq pro nil)) + (error + (or no-msg (message "%s, %s" (nth 1 emsg) (nth 2 emsg))) + (setq pro nil))) + (if tm (cancel-timer tm)) + pro)) + +(defun mew-imap-timeout () + (signal 'quit nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Launcher +;;; + +(defun mew-imap-make-mark-hist (ents) + (let (ret) + (dolist (ent ents) + (let ((mark (mew-mark-hist-get-mark ent)) + (msg (mew-mark-hist-get-msg ent))) + (cond + ((memq mark mew-imap-marks-to-sync) + (setq ret (cons ent ret))) + ;; xxx the refile mark overrides the read mark. + ;; If we refile a message, we cannot distinguish + ;; read or unread... + ((char-equal mark mew-mark-refile) + (setq ret (cons (mew-make-mark-hist :msg msg :mark mew-mark-read) ret)))))) + (nreverse ret))) + +(defun mew-imap-retrieve (case directive bnm &rest args) + (let* ((server (mew-imap-server case)) + (user (mew-imap-user case)) + (port (mew-*-to-string (mew-imap-port case))) + (sshsrv (mew-imap-ssh-server case)) + (sslp (mew-imap-ssl case)) + (sslport (mew-imap-ssl-port case)) + (proxysrv (mew-imap-proxy-server case)) + (proxyport (mew-imap-proxy-port case)) + ;; dirty but necessary for migration + (mailbox (unless (eq directive 'list) + (mew-imap-utf-7-encode-string + (mew-imap-bnm-to-mailbox bnm)))) + (pnm (mew-imap-info-name case mailbox)) + (buf (get-buffer-create (mew-imap-buffer-name pnm))) + (no-msg (eq directive 'biff)) + process sshname sshpro sslname sslpro lport info jobs tls + virtual-info disp-info virtual) + (if (mew-imap-get-process pnm) + (message "Another IMAP process is running. Try later") + (cond + (sshsrv + (setq sshpro (mew-open-ssh-stream case server port sshsrv)) + (when sshpro + (setq sshname (process-name sshpro)) + (setq lport (mew-ssh-pnm-to-lport sshname)) + (when lport + (setq process (mew-imap-open pnm "localhost" lport no-msg))))) + (sslp + (if (mew-port-equal port sslport) (setq tls mew-tls-imap)) + (setq sslpro (mew-open-ssl-stream case server sslport tls)) + (when sslpro + (setq sslname (process-name sslpro)) + (setq lport (mew-ssl-pnm-to-lport sslname)) + (when lport + (setq process (mew-imap-open pnm mew-ssl-localhost lport no-msg))))) + (proxysrv + (setq process (mew-imap-open pnm proxysrv proxyport no-msg))) + (t + (setq process (mew-imap-open pnm server port no-msg)))) + (if (null process) + (when (eq directive 'exec) + (mew-imap-exec-recover bnm)) + (mew-summary-lock process "IMAPing" (or sshpro sslpro)) + (mew-sinfo-set-summary-form (mew-get-summary-form bnm)) + (mew-sinfo-set-summary-column (mew-get-summary-column bnm)) + (mew-sinfo-set-unread-mark nil) + (mew-sinfo-set-scan-id nil) + (mew-sinfo-set-scan-md5 nil) + (mew-info-clean-up pnm) + (mew-imap-set-no-msg pnm no-msg) ;; must come here + (mew-imap-message pnm "Communicating with the IMAP server...") + (mew-imap-set-process pnm process) + (mew-imap-set-ssh-process pnm sshpro) + (mew-imap-set-ssl-process pnm sslpro) + (mew-imap-set-server pnm server) + (mew-imap-set-port pnm port) + (mew-imap-set-user pnm user) + (mew-imap-set-account pnm (format "%s@%s" user server)) + (mew-imap-set-auth pnm (mew-imap-auth case)) + (mew-imap-set-auth-list pnm (mew-imap-auth-list case)) + (mew-imap-set-status pnm "greeting") + (mew-imap-set-directive pnm directive) + (mew-imap-set-bnm pnm bnm) + (mew-imap-set-status-buf pnm bnm) + (mew-imap-set-rcnt pnm 1) + (mew-imap-set-rgcnt pnm 1) + (mew-imap-set-dgcnt pnm 1) + (mew-imap-set-jcnt pnm nil) + (mew-imap-set-rttl pnm 0) + (mew-imap-set-dttl pnm 0) + (mew-imap-set-size pnm (mew-imap-size case)) + (mew-imap-set-mailbox pnm mailbox) + (mew-imap-set-case pnm case) + (mew-imap-set-bytes pnm nil) + (mew-imap-set-mark-hist pnm (mew-imap-make-mark-hist (mew-sinfo-get-mark-hist))) + (cond + ((eq directive 'biff) + (mew-imap-set-passwd pnm (nth 0 args))) ;; password + ((eq directive 'inc) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)) + (mew-imap-set-flush pnm (nth 0 args)) ;; no-flush + (mew-imap-set-delete pnm (mew-imap-delete case))) + ((eq directive 'get) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)) + (mew-imap-set-refs pnm (nth 0 args)) + (setq virtual-info (nth 1 args)) + (mew-imap-set-virtual-info pnm virtual-info) + (setq disp-info (nth 2 args)) + (mew-imap-set-disp-info pnm disp-info) + (setq virtual (mew-net-virtual-info-get-virtual virtual-info)) + (when virtual + (mew-imap-set-status-buf pnm virtual) + (with-current-buffer virtual + (mew-summary-lock process "IMAPing" (or sshpro sslpro))))) + ((eq directive 'scan) + (mew-imap-set-range pnm (nth 0 args)) + (mew-imap-set-get-body pnm (nth 1 args)) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)) + (if (mew-imap-get-range pnm) + (progn +;; (mew-imap-set-mdb pnm (mew-summary-mark-collect4)) + (mew-net-folder-clean)) +;; (mew-imap-set-mdb pnm (mew-summary-mark-collect5)) + (mew-net-invalid-cache-invisible)) + (when (and (string= mailbox mew-imap-inbox-string) + (or (mew-imap-spam-pattern case) + (and (mew-imap-spam-field case) + (mew-imap-spam-word case)))) + (mew-imap-set-spam pnm t) + (mew-imap-set-spam-field pnm (mew-imap-spam-field case)) + (mew-imap-set-spam-word pnm (mew-imap-spam-word case)) + (mew-imap-set-spam-pattern pnm (mew-imap-spam-pattern case)))) + ((eq directive 'sync) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm))) + ((eq directive 'exec) + (setq info (nth 0 args)) + (mew-imap-set-rmvs pnm (mew-execinfo-get-remove info)) + (mew-imap-set-kils pnm (mew-execinfo-get-kill info)) + (mew-imap-set-refs pnm (mew-execinfo-get-refile info)) + (mew-imap-set-movs pnm (mew-execinfo-get-move info)) + (mew-imap-set-rttl pnm (mew-execinfo-get-rttl info)) + (mew-imap-set-dttl pnm (mew-execinfo-get-dttl info))) + ((eq directive 'jobs) + (mew-imap-set-jcnt pnm 0) + (setq jobs (nth 0 args)) + (mew-imap-set-jobs pnm jobs) + (mew-imap-set-jcnt pnm (length jobs))) + ((eq directive 'delete) + ) + ((eq directive 'rename) + (mew-imap-set-new-mailbox pnm (mew-imap-bnm-to-mailbox (nth 0 args))))) + (mew-sinfo-set-start-point (point)) ;; after erase-buffer + ;; + (set-process-sentinel process 'mew-imap-sentinel) + (set-process-filter process 'mew-imap-filter) + (set-process-buffer process buf))))) + +(defun mew-imap-exec-recover (bnm) + (mew-summary-visible-buffer bnm) + (mew-sinfo-set-refile + (nconc (mew-sinfo-get-refile) (mew-sinfo-get-refile-back))) + (mew-sinfo-set-refile-back nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defun mew-imap-debug (label string) + (when (mew-debug 'net) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (let ((start (point))) + (insert (format "\n<%s>\n%s\n" label string)) + (goto-char start) + (mew-crlf-to-lf)) + (goto-char (point-max))))) + +(defun mew-imap-filter (process string) + (let* ((pnm (process-name process)) + (status (mew-imap-get-status pnm)) + (tag (mew-imap-get-tag pnm)) + (eos (format "^%s \\(OK\\|NO \\[TRYCREATE\\]\\|NO\\|BAD\\)" tag)) + (bytes (mew-imap-get-bytes pnm)) + stay next func code) + (mew-imap-debug (upcase status) string) + (mew-filter + ;; Process's buffer + (goto-char (point-max)) + (mew-set-buffer-multibyte nil) + (insert string) + (cond + ((string= status "fetch") + (mew-net-status2 (mew-imap-get-status-buf pnm) + (mew-imap-get-rttl pnm) + (mew-imap-get-rcnt pnm) + (mew-refileinfo-get-size (car (mew-imap-get-rtrs pnm))) + nil + (mew-imap-secure-p pnm)) + (goto-char (point-min)) + (when (and (null bytes) + (looking-at "^\\*[^{]*{\\([0-9]+\\)}")) + (setq bytes (string-to-number (mew-match-string 1))) + (mew-imap-set-bytes pnm bytes)) + (when bytes + (goto-char (point-min)) + (while (and (looking-at "^\\*") (= (forward-line) 0)) + (delete-region (point-min) (point)))) + (if (or (null bytes) (< (point-max) bytes) + (save-excursion (goto-char (point-max)) (not (bolp)))) + (setq stay t) + (goto-char (point-max)) + (forward-line -1) + (while (looking-at "^\\*") (forward-line -1)) + (if (not (looking-at eos)) + (setq stay t) + (delete-region (1+ bytes) (point-max)) + (setq next (mew-imap-fsm-next status "OK"))))) + ((and (goto-char (point-max)) (= (forward-line -1) 0) (looking-at "^\\*")) + ;; untagged message + (if (string= status "greeting") + (setq next (mew-imap-fsm-next "greeting" "OK")) + (setq stay t))) + ((and (goto-char (point-min)) (looking-at "\\+")) + (setq next (mew-imap-fsm-next status "OK"))) + ((and (goto-char (point-max)) (= (forward-line -1) 0) (looking-at eos)) + (mew-imap-set-tag pnm nil) + (setq code (mew-match-string 1)) + (setq next (mew-imap-fsm-next status code))) + (t + ;; xxx what about in this case? + ;; * untag + ;; * untag + ;; tag + ;; * untag + (setq stay t))) + (unless stay + (unless next (setq next "logout")) + (mew-imap-set-status pnm next) + (setq func (intern-soft (concat "mew-imap-command-" next))) + (goto-char (point-min)) + (if (fboundp func) + (funcall func process pnm) + (error "No function called %s" (symbol-name func))) + (if (and process (equal (process-buffer process) (current-buffer))) + (mew-erase-buffer)))))) + +(defun mew-imap-mark-clean (mark) + (let* ((regex (mew-mark-list-regex mew-imap-marks-to-clean))) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (mew-mark-put mark) + (forward-line))))) + +;; see also mew-summary-mark-recover +(defun mew-imap-mark-recover (mdb) + (let ((opos (point)) + (case-fold-search nil) + msg mrk omrk) + (goto-char (point-min)) + (dolist (ent mdb) + (mew-set '(msg mrk) ent) + (when (re-search-forward (mew-regex-sumsyn-msg msg) nil t) + (setq omrk (mew-summary-get-mark)) + (unless (and omrk (or (char-equal omrk mew-mark-refile) + (char-equal omrk mew-mark-delete) + (char-equal omrk mew-mark-unlink))) + (mew-mark-put mrk)) ;; hist will be reset + (forward-line))) + (goto-char opos))) + +(defun mew-imap-sentinel (process event) + (let* ((pnm (process-name process)) + (directive (mew-imap-get-directive pnm)) + (case (mew-imap-get-case pnm)) + (mdb (mew-imap-get-mdb pnm)) + (sshpro (mew-imap-get-ssh-process pnm)) + (sslpro (mew-imap-get-ssl-process pnm)) + (rttl (mew-imap-get-rttl pnm)) + (dttl (mew-imap-get-dttl pnm)) + (jcnt (mew-imap-get-jcnt pnm)) + (bnm (or (mew-imap-get-bnm pnm) (current-buffer))) ;; C-c C-k + (flush (mew-imap-get-flush pnm)) + (kils (mew-imap-get-kils pnm)) + (movs (mew-imap-get-movs pnm)) + (hlds (mew-imap-get-hlds pnm)) + (uidl (mew-imap-get-uidl pnm)) + (msgid (mew-imap-get-msgid pnm)) + (done (mew-imap-get-done pnm)) + (error (mew-imap-get-error pnm)) + (file (mew-expand-file bnm mew-imap-msgid-file)) + (buf (process-buffer process)) + (virtual-info (mew-imap-get-virtual-info pnm)) + (disp-info (mew-imap-get-disp-info pnm))) + (save-excursion + (mew-imap-debug "IMAP SENTINEL" event) + (set-process-buffer process nil) + (set-buffer bnm) + (when (eq directive 'sync) + (if (mew-sinfo-get-unread-mark) + (mew-imap-mark-clean mew-mark-unread) + (mew-imap-mark-clean mew-mark-read))) + (mew-imap-mark-recover mdb) + (mew-sinfo-set-mark-hist nil) ;; xxx + (mew-remove-buffer buf) + (if (not done) + (let* ((rtrs (mew-imap-get-rtrs pnm)) + (lefts (length rtrs)) + (msgid (mew-refileinfo-get-uid (car rtrs))) + leftp) + (if error + (mew-imap-message pnm error) + (mew-imap-message pnm "IMAP connection is lost")) + (cond + ((eq directive 'exec) + (mew-imap-exec-recover bnm)) + ((eq directive 'scan) + (mew-summary-visible-buffer bnm)) + ((or (eq directive 'delete) (eq directive 'rename)) + (setq mew-summary-buffer-process-error t))) + (when (mew-imap-get-dispatched pnm) + (cond + ((eq directive 'scan) + (when msgid + (setq msgid (number-to-string (1- (string-to-number msgid)))) + (mew-lisp-save file msgid nil 'unlimit)) + (setq leftp t)) + ((eq directive 'inc) + ;; uidl is reversed. + (setq msgid (assoc msgid uidl)) + (setq uidl (cdr (member msgid uidl))) + (mew-net-uidl-db-set (mew-imap-passtag pnm) uidl) + (setq leftp t))) + (when leftp + (mew-imap-message + pnm + "%d messages retrieved. %d messages are left due to an error" + (- rttl lefts) lefts) + (mew-summary-folder-cache-save)))) + (if virtual-info (mew-summary-retrieve-message-for-virtual virtual-info)) + (cond + ((eq directive 'list) + (mew-imap-message pnm "Collecting mailbox list...done")) + ((eq directive 'delete) + (mew-imap-message pnm "Deleting this folder...done")) + ((eq directive 'rename) + (mew-imap-message pnm "Renaming this folder...done")) + ((eq directive 'biff) + (and (functionp mew-biff-function) + (funcall mew-biff-function rttl))) + ((eq directive 'sync) + (mew-imap-message pnm "Synchronizing messages...") + (mew-net-folder-sync bnm hlds) + (mew-imap-message pnm "Synchronizing messages...done") + (mew-summary-folder-cache-save)) + ((eq directive 'inc) + (mew-biff-clear) + (mew-net-uidl-db-set (mew-imap-passtag pnm) uidl) + (cond + ((= rttl 0) + (mew-imap-message pnm "No new messages")) + ((= rttl 1) + (mew-imap-message pnm "1 message retrieved") + (mew-summary-folder-cache-save)) + (t + (mew-imap-message pnm "%s messages retrieved" rttl) + (mew-summary-folder-cache-save)))) + ((eq directive 'get) + (cond + ((= rttl 0) + (mew-imap-message pnm "The message does not exist")) + ((= rttl 1) + (mew-imap-message pnm "1 message retrieved") + (mew-summary-folder-cache-save)) + (t + (mew-imap-message pnm "%s messages retrieved" rttl) + (mew-summary-folder-cache-save)))) + ((eq directive 'scan) + (mew-biff-clear) + (cond + ((or (= rttl 0) (null msgid)) + (mew-imap-message pnm "No new messages")) + ((= rttl 1) + (mew-imap-message pnm "1 message retrieved") + (mew-lisp-save file msgid nil 'unlimit) + (mew-net-invalid-cache-clean)) + (t + (mew-imap-message pnm "%s messages retrieved" rttl) + (mew-lisp-save file msgid nil 'unlimit) + (mew-net-invalid-cache-clean)))) + ((eq directive 'exec) + (if kils (mew-mark-exec-unlink bnm kils)) + (when movs + (let ((mew-inherit-exec-case case) + (mew-inherit-offline t)) + (mew-mark-exec-refile bnm movs))) + (when (or kils movs) + (mew-mark-kill-invisible) + (mew-summary-folder-cache-save)) + (cond + ((= rttl 1) + (mew-imap-message pnm "1 message refiled")) + ((> rttl 1) + (mew-imap-message pnm "%d messages refiled" rttl)) + ((= dttl -1) + (mew-imap-message pnm "All messages deleted")) + ((= dttl 1) + (mew-imap-message pnm "1 message deleted")) + (t + (mew-imap-message pnm "%d messages deleted" dttl)))) + ((eq directive 'jobs) + (if (= jcnt 1) + (mew-imap-message pnm "1 job processed") + (mew-imap-message pnm "%d jobs processed" jcnt))))) + ;; + (and mew-use-async-write (mew-unix-sync)) + (mew-net-status-clear (mew-imap-get-status-buf pnm)) + (mew-info-clean-up pnm) + (set-buffer-modified-p nil) + (mew-summary-unlock) + (if (and (processp sshpro) (not mew-ssh-keep-connection)) + (process-send-string sshpro "exit\n")) + (if (and (processp sslpro) (not mew-ssl-keep-connection)) + (delete-process sslpro)) + (mew-net-disp-info-display disp-info) + (unless (eq directive 'biff) + (run-hooks 'mew-imap-sentinel-non-biff-hook)) + (run-hooks 'mew-imap-sentinel-hook) + (when (and mew-auto-flush-queue flush) + (mew-smtp-flush-queue mew-case))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Biff +;;; + +(defun mew-imap-biff () + (let* ((case mew-case) + (inbox (mew-proto-inbox-folder nil case)) + (case:inbox (mew-case-folder case inbox)) + (tag (mew-imap-passtag2 case)) + passwd) + (when (get-buffer case:inbox) + (with-current-buffer case:inbox + (when (and (mew-summary-exclusive-p 'no-msg) + (and (or mew-use-cached-passwd mew-use-master-passwd) + (setq passwd (mew-passwd-get-passwd tag)))) + (mew-imap-retrieve case 'biff case:inbox passwd)))))) + +(defun mew-imap-check () + "See if messages are arrived by IMAP." + (interactive) + (let* ((case mew-case) + (inbox (mew-proto-inbox-folder nil case)) + (case:inbox (mew-case-folder case inbox))) + (when (get-buffer case:inbox) + (with-current-buffer case:inbox + (when (mew-summary-exclusive-p) + (mew-imap-retrieve case 'biff case:inbox)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mailbox alist +;;; + +(defun mew-imap-folder-clean-up () + (setq mew-imap-folder-alist nil) + (setq mew-imap-friend-folder-list nil)) + +(defun mew-imap-folder-alist (&optional case no-load) + (unless case (setq case mew-case-default)) + (let* ((ent (assoc case mew-imap-folder-alist)) + (t2 (nth 1 ent)) ;; may be nil + (alist (nth 2 ent)) + (fld (mew-imap-folder case)) + (file (mew-expand-file fld mew-imap-folder-alist-file)) + (t1 (mew-file-get-time file))) + (if (or no-load (and t1 (not (mew-compare-times t1 t2)))) + alist + (mew-imap-folder-load case) + (setq ent (assoc case mew-imap-folder-alist)) + (setcar (nthcdr 1 ent) t1) + (setq alist (nth 2 ent)) + (if alist + alist + (delete nil + (list + (mew-folder-func mew-imap-inbox-folder) + (mew-folder-func (mew-imap-trash-folder case)) + (mew-folder-func (mew-imap-queue-folder case)))))))) + +(defun mew-imap-friend-folder-list (&optional case no-load) + (unless case (setq case mew-case-default)) + (unless no-load (mew-imap-folder-alist case)) ;; do update + (cdr (assoc case mew-imap-friend-folder-list))) + +(defun mew-imap-folder-load (case) + (let* ((fld (mew-imap-folder case)) + (file (mew-expand-file fld mew-imap-folder-alist-file)) + (mailboxes (mew-lisp-load file)) + (file2 (mew-expand-file fld mew-imap-friend-folder-list-file)) + (friends (mew-lisp-load file2))) + (mew-imap-folder-set case mailboxes friends 'no-save))) + +(defun mew-imap-folder-save (case) + (let* ((fld (mew-imap-folder case)) + (dir (mew-expand-folder fld)) + (file (expand-file-name mew-imap-folder-alist-file dir)) + (file2 (expand-file-name mew-imap-friend-folder-list-file dir)) + (mailboxes (mew-imap-folder-alist case 'no-load)) + (friends (mew-imap-friend-folder-list case 'no-load))) + (mew-check-directory dir) + (mew-lisp-save file mailboxes 'nobackup 'unlimit) + (mew-lisp-save file2 friends 'nobackup 'unlimit) + (mew-file-get-time file))) + +(defun mew-imap-folder-set (case mailboxes friends &optional no-save) + (unless case (setq case mew-case-default)) + (setq mew-imap-folder-alist + (cons (list case nil mailboxes) + (delete (assoc case mew-imap-folder-alist) + mew-imap-folder-alist))) + (setq mew-imap-friend-folder-list + (cons (cons case friends) + (delete (assoc case mew-imap-friend-folder-list) + mew-imap-friend-folder-list))) + (unless no-save + (let ((t1 (mew-imap-folder-save case)) + (ent (assoc case mew-imap-folder-alist))) + (setcar (nthcdr 1 ent) t1)))) + +(defun mew-imap-update (case) + (let ((bnm (mew-summary-folder-name 'ext))) + (mew-imap-retrieve case 'list bnm))) + +(defun mew-imap-folder-insert (case folder) + (let* ((sep (mew-imap-separator case)) + (regex (format "\\([^%s%s\n\r]+\\)$" sep mew-folder-imap)) + (mailboxes (mew-imap-folder-alist case)) + (friends (mew-imap-friend-folder-list case)) + (friendp (mew-imap-friend-regex sep case)) + sub) + (when (string-match regex folder) + (cond + ((string-match friendp folder) + (mew-folder-insert folder mailboxes nil) + (setq friends (cons folder friends))) + (t + (setq sub (match-string 1 folder)) + (mew-folder-insert folder mailboxes sub))) + (mew-imap-folder-set case mailboxes friends) + t))) + +(defun mew-imap-folder-delete (case folder) + (let ((mailboxes (mew-imap-folder-alist case)) + (friends (mew-imap-friend-folder-list case))) + (mew-folder-delete folder mailboxes) + (setq friends (delete folder friends)) + (mew-imap-folder-set case mailboxes friends))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Flush the job queue +;;; + +(defun mew-imap-flush-queue () + (let* ((case (mew-sinfo-get-case)) + (qfld (mew-summary-folder-name 'ext)) + (jobs (mew-folder-messages qfld))) + (if (null jobs) + (message "No IMAP jobs") + (mew-summary-folder-cache-clean qfld) + (mew-imap-retrieve case 'jobs qfld jobs)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; UTF-7 IMAP +;;; + +(defun mew-imap-utf-7-decode-string (str) + (if (or (null mew-cs-utf-16be) (not (string-match "&" str))) + str ;; fast path + (let ((regex "&[A-Za-z0-9+,]+-") + padn) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (insert str) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (narrow-to-region (match-beginning 0) (match-end 0)) + (goto-char (point-min)) + (delete-char 1) + (while (search-forward "," nil t) + (replace-match "/" nil t)) + (goto-char (point-max)) + (delete-char -1) + (setq padn (- 4 (% (- (point-max) (point-min)) 4))) + (unless (= padn 4) + (insert (make-string padn ?=))) + (base64-decode-region (point-min) (point-max)) + (decode-coding-region (point-min) (point-max) mew-cs-utf-16be) + (goto-char (point-max)) + (widen)) + (buffer-substring-no-properties (point-min) (point-max)))))) + +(defun mew-imap-utf-7-encode-string (str) + (if (or (null mew-cs-utf-16be) (string-match "^[ -%'-~]+$" str)) + str ;; fast path + (let ((regex "[^ -%'-~]+")) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (insert str) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (narrow-to-region (match-beginning 0) (match-end 0)) + (encode-coding-region (point-min) (point-max) mew-cs-utf-16be) + (base64-encode-region (point-min) (point-max)) + (goto-char (point-min)) + (insert "&") + (when (re-search-forward "=+" nil t) + (delete-region (match-beginning 0) (match-end 0))) + (goto-char (point-min)) + (while (search-forward "/" nil t) + (replace-match "," nil t)) + (goto-char (point-max)) + (insert "-") + (widen)) + (buffer-substring-no-properties (point-min) (point-max)))))) + +(provide 'mew-imap) + +;;; Copyright Notice: + +;; Copyright (C) 2002-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-imap.el ends here diff --git a/elpa/mew-20150813.2354/mew-imap2.el b/elpa/mew-20150813.2354/mew-imap2.el new file mode 100644 index 00000000..1450f0ce --- /dev/null +++ b/elpa/mew-20150813.2354/mew-imap2.el @@ -0,0 +1,659 @@ +;;; mew-imap2.el for appending + +;; Author: Kazu Yamamoto +;; Created: May 22, 2003 + +;;; Code: + +(require 'mew) + +(defvar mew-imap2-literal+ t) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; IMAP2 info +;;; + +(defvar mew-imap2-info-list + '("case" "directive" "mailbox" + ;; + "src" "messages" "src-list" "src-list-orig" + "server" "port" "ssh-server" + "user" "auth" "auth-list" "account" + "status" "process" "ssh-process" "ssl-process" + "cnt" "ttl" "literal+" + ;; parameters used internally and should be initialized + "tag" "string" "error" "auth-selected" "authl" "aux" "done")) + +(defvar mew-imap2-info-list-clean-length 20) + +(mew-info-defun "mew-imap2-" mew-imap2-info-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; FSM +;;; + +(defvar mew-imap2-fsm + '(("greeting" ("OK" . "capability")) + ("capability" ("OK" . "post-capability")) + ("auth-cram-md5" ("OK" . "pwd-cram-md5") ("NO" . "wpwd")) + ("pwd-cram-md5" ("OK" . "next") ("NO" . "wpwd")) + ("auth-login" ("OK" . "user-login") ("NO" . "wpwd")) + ("user-login" ("OK" . "pwd-login") ("NO" . "wpwd")) + ("pwd-login" ("OK" . "next") ("NO" . "wpwd")) + ("login" ("OK" . "next") ("NO" . "wpwd")) + ("append" ("OK" . "post-append") ("\\[TRYCREATE\\]" . "create")) + ("create" ("OK" . "append") ("NO" . "wmbx")) + ("post-append" ("OK" . "done") ("\\[TRYCREATE\\]" . "create")) + ("logout" ("OK" . "noop")))) + +(defun mew-imap2-fsm-by-status (status) + (assoc status mew-imap2-fsm)) + +(defun mew-imap2-fsm-next (status code) + (cdr (mew-assoc-match2 code (nthcdr 1 (mew-imap2-fsm-by-status status)) 0))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filters 2 +;;; + +(defun mew-imap2-command-capability (pro pnm) + (mew-imap2-process-send-string pro pnm "CAPABILITY")) + +(defun mew-imap2-command-post-capability (pro pnm) + (let ((case-fold-search t) + (aux (mew-imap2-get-aux pnm)) + (start 0) + authl literal+) + (while (string-match "AUTH=\\([^ \r\n]+\\)" aux start) + (setq authl (cons (mew-match-string 1 aux) authl)) + (setq start (match-end 0))) + (if (and mew-imap2-literal+ + (string-match "\\bliteral\\+\\b" aux)) + (setq literal+ t)) + (mew-imap2-set-authl pnm authl) + (mew-imap2-set-literal+ pnm literal+) + (mew-imap2-set-status pnm "authentication") + (mew-imap2-command-authentication pro pnm))) + +(defun mew-imap2-command-authentication (pro pnm) + (cond + ((eq (mew-imap2-get-auth pnm) t) ;; t means SASL + (let ((auth-list (mew-imap2-get-auth-list pnm)) + (authl (mew-imap2-get-authl pnm)) + auth func) + (if (and authl + (setq auth (mew-auth-select2 authl auth-list)) + (setq func (mew-imap2-auth-get-func auth)) + (fboundp func)) + (progn + (mew-imap2-set-auth-selected pnm auth) + (funcall func pro pnm)) + (mew-imap2-debug "" "No preferred IMAP AUTH.\n") + (mew-imap2-set-status pnm "login") + (mew-imap2-command-login pro pnm)))) + (t + (mew-imap2-set-status pnm "login") + (mew-imap2-command-login pro pnm)))) + +(defun mew-imap2-command-login (pro pnm) + (let* ((user (mew-imap2-get-user pnm)) + (prompt (format "IMAP password (%s): " + (mew-imap2-get-account pnm))) + (pass (mew-input-passwd prompt (mew-imap2-passtag pnm)))) + (setq user (mew-quote-string user ?\\ '(?\\ ?\"))) + (setq pass (mew-quote-string pass ?\\ '(?\\ ?\"))) + (mew-imap2-process-send-string pro pnm "LOGIN \"%s\" \"%s\"" user pass))) + +(defun mew-imap2-command-wpwd (pro pnm) + (let ((auth (mew-imap2-get-auth-selected pnm))) + (mew-passwd-set-passwd (mew-imap2-passtag pnm) nil) + (mew-imap2-set-error pnm (format "IMAP %s password is wrong!" auth)) + (mew-imap2-command-logout2 pro pnm))) + +(defun mew-imap2-command-next (pro pnm) + (let ((directive (mew-imap2-get-directive pnm)) + (case (mew-imap2-get-case pnm)) + (src-list (mew-imap2-get-src-list pnm)) + (msgs (mew-imap2-get-messages pnm)) + src dst mailbox msg src-file) + (if msgs + (setq src (mew-imap2-get-src pnm)) + (if (or (eq directive 'copy) (eq directive 'move)) + (progn + (setq msgs src-list) + (mew-imap2-set-src-list pnm nil) + (mew-imap2-set-ttl pnm (length msgs)) + (mew-imap2-set-cnt pnm 0) + (setq dst (mew-imap2-get-mailbox pnm)) + (setq mailbox (mew-imap-expand-mailbox case dst)) + (setq mailbox (mew-imap-utf-7-encode-string mailbox)) + (mew-imap2-set-mailbox pnm mailbox)) + (catch 'break + (while src-list ;; cannot use dolist + (setq src (car src-list)) + (setq src-list (cdr src-list)) + (mew-imap2-set-src pnm src) + (mew-imap2-set-src-list pnm src-list) + (setq msgs (mew-folder-messages (mew-case-folder case src))) + (when msgs + (mew-imap2-set-ttl pnm (length msgs)) + (mew-imap2-set-cnt pnm 0) + (cond + ((eq directive 'cp-r) + (setq dst (mew-imap-local-to-imap case src)) + (unless (assoc dst (mew-imap-folder-alist case)) + (mew-imap-folder-insert case dst)) + (setq mailbox (mew-imap-expand-mailbox case dst))) + ((eq directive 'fcc) + (setq mailbox (mew-imap-fcc-to-mailbox case src)))) + (setq mailbox (mew-imap-utf-7-encode-string mailbox)) + (mew-imap2-set-mailbox pnm mailbox) + (throw 'break nil)))))) + (if msgs + (progn + (setq msg (car msgs)) + (setq msgs (cdr msgs)) + (cond + ((or (eq directive 'copy) (eq directive 'move)) + (setq src-file msg)) + (t + (setq src-file (mew-expand-msg (mew-case-folder case src) msg)))) + (mew-frwlet mew-cs-text-for-read mew-cs-dummy + (set-buffer (mew-find-file-noselect src-file))) + (mew-set-buffer-multibyte nil) + (mew-info-clean-up pnm mew-imap2-info-list-clean-length) + (mew-imap2-set-messages pnm msgs) + (set-process-buffer pro (current-buffer)) + (mew-imap2-set-status pnm "append") + (mew-imap2-command-append pro pnm)) + (mew-imap2-set-status pnm "logout") + (mew-imap2-command-logout pro pnm)))) + +(defun mew-imap2-command-append (pro pnm) + (let ((mailbox (mew-imap2-get-mailbox pnm)) + (cnt (mew-imap2-get-cnt pnm)) + (ttl (mew-imap2-get-ttl pnm)) + (mbx (mew-imap2-get-mailbox pnm)) + (literal+ (mew-imap2-get-literal+ pnm)) + bytes) + (setq cnt (1+ cnt)) + (mew-imap2-set-cnt pnm cnt) + (message "Copying to %s %d/%d (%02d%%)" mbx cnt ttl (/ (* cnt 100) ttl)) + (goto-char (point-max)) + (unless (bolp) (insert "\n")) + (if (mew-eol-fix-for-write) + (setq bytes (- (point-max) (point-min))) + (setq bytes (- (point-max) (point-min))) + (setq bytes (+ bytes (count-lines (point-min) (point-max))))) + (set-buffer-modified-p nil) + (if (not literal+) + (mew-imap2-process-send-string + pro pnm "APPEND \"%s\" {%d}" mailbox bytes) + (mew-imap2-process-send-string + pro pnm "APPEND \"%s\" {%d+}" mailbox bytes) + (mew-imap2-set-status pnm "post-append") + (mew-imap2-command-post-append pro pnm)))) + +(defun mew-imap2-command-post-append (pro pnm) + (process-send-region pro (point-min) (point-max)) + (process-send-string pro mew-cs-eol)) ;; APPEND command ends + +(defun mew-imap2-command-create (pro pnm) + (let ((mailbox (mew-imap2-get-mailbox pnm)) + (cnt (mew-imap2-get-cnt pnm))) + (setq cnt (1- cnt)) + (mew-imap2-set-cnt pnm cnt) + (mew-imap2-process-send-string pro pnm "CREATE \"%s\"" mailbox))) + +(defun mew-imap2-command-wmbx (pro pnm) + (mew-imap2-set-error pnm "mailbox is wrong!") + (mew-imap2-set-status pnm "logout") + (mew-imap2-command-logout pro pnm)) + +(defun mew-imap2-command-done (pro pnm) + (let ((buf (process-buffer pro))) + (set-process-buffer pro nil) + (mew-remove-buffer buf) + (mew-imap2-set-status pro "next") + (mew-imap2-command-next pro pnm))) + +(defun mew-imap2-command-logout (pro pnm) + (mew-imap2-set-done pnm t) + (mew-imap2-process-send-string pro pnm "LOGOUT")) + +(defun mew-imap2-command-logout2 (pro pnm) + ;; error is set + (mew-imap2-set-done pnm t) + (when (and (processp pro) (eq (process-status pro) 'open)) + (mew-imap2-set-status pnm "logout") + (mew-imap2-process-send-string pro pnm "LOGOUT"))) + +(defun mew-imap2-command-noop (pro pnm) + ()) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; AUTH +;;; + +(defvar mew-imap2-auth-alist + '(("CRAM-MD5" mew-imap2-command-auth-cram-md5) + ("LOGIN" mew-imap2-command-auth-login))) + +(defun mew-imap2-auth-get-func (auth) + (nth 1 (mew-assoc-case-equal auth mew-imap2-auth-alist 0))) + +(defun mew-imap2-command-auth-cram-md5 (pro pnm) + (mew-imap2-process-send-string pro pnm "AUTHENTICATE CRAM-MD5") + (mew-imap2-set-status pnm "auth-cram-md5")) + +(defun mew-imap2-command-pwd-cram-md5 (pro pnm) + (let ((user (mew-imap2-get-user pnm)) + (prompt (format "IMAP CRAM-MD5 password (%s): " + (mew-imap2-get-account pnm))) + (aux (mew-imap2-get-aux pnm)) + challenge passwd cram-md5) + (if (string-match " \\([a-zA-Z0-9+/]+=*\\)" aux) + (setq challenge (mew-match-string 1 aux))) + (setq passwd (mew-imap2-input-passwd prompt pnm)) + (setq cram-md5 (mew-cram-md5 user passwd challenge)) + (mew-imap2-process-send-string2 pro cram-md5))) + +(defun mew-imap2-command-auth-login (pro pnm) + (mew-imap2-process-send-string pro pnm "AUTHENTICATE LOGIN") + (mew-imap2-set-status pnm "auth-login")) + +(defun mew-imap2-command-user-login (pro pnm) + (let* ((user (mew-imap2-get-user pnm)) + (euser (mew-base64-encode-string user))) + (mew-imap2-process-send-string2 pro euser))) + +(defun mew-imap2-command-pwd-login (pro pnm) + (let* ((prompt (format "IMAP LOGIN password (%s): " + (mew-imap2-get-account pnm))) + (passwd (mew-imap2-input-passwd prompt pnm)) + (epasswd (mew-base64-encode-string passwd))) + (mew-imap2-process-send-string2 pro epasswd))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub functions +;;; + +(defconst mew-imap2-info-prefix "mew-imap2-info-") + +(defun mew-imap2-info-name (case) + (let ((server (mew-imap-server case)) + (port (mew-*-to-string (mew-imap-port case))) + (sshsrv (mew-imap-ssh-server case)) + (name mew-imap2-info-prefix)) + (setq name (concat name server)) + (unless (mew-port-equal port mew-imap-port) + (setq name (concat name ":" port))) + (if sshsrv + (concat name "%" sshsrv) + name))) + +(defun mew-imap2-buffer-name (pnm) + (concat mew-buffer-prefix pnm)) + +(defun mew-imap2-process-send-string (pro pnm &rest args) + (let ((str (apply 'format args)) + (tag (mew-imap2-tag))) + (mew-imap2-debug "=SEND=" (concat tag " " str)) + (mew-imap2-set-tag pnm tag) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-string pro (concat tag " " str mew-cs-eol)) + (message "IMAP time out")))) + +(defun mew-imap2-process-send-string2 (pro &rest args) + (let ((str (apply 'format args))) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-string pro (concat str mew-cs-eol)) + (message "IMAP time out")))) + +(defun mew-imap2-tag () + (format "%s%04d" (mew-random-string 4 nil) (% (mew-random) 10000))) + +(defun mew-imap2-passtag (pnm) + (let ((server (mew-imap2-get-server pnm)) + (port (mew-imap2-get-port pnm)) + (user (mew-imap2-get-user pnm))) + (concat user "@" server ":" port))) + +(defun mew-imap2-passtag2 (case) + (let ((server (mew-imap-server case)) + (port (mew-imap-port case)) + (user (mew-imap-user case))) + (concat user "@" server ":" port))) + +(defun mew-imap2-input-passwd (prompt pnm) + (let* ((tag (mew-imap2-passtag pnm)) + (pro (mew-imap2-get-process pnm)) + (pass (mew-input-passwd prompt tag))) + (unless (and (processp pro) (eq (process-status pro) 'open)) + (mew-passwd-set-passwd tag nil)) + pass)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Namespace +;;; + + +(defvar mew-folder-imap-fcc-prefix "%.fcc") + +(defun mew-folder-imap-to-fcc (case folder) + (concat + (file-name-as-directory + (mew-case-folder case mew-folder-imap-fcc-prefix)) + (mew-folder-string folder))) + +(defun mew-folder-imap-fcc-dir (case) + (mew-expand-folder (mew-case-folder case mew-folder-imap-fcc-prefix))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Opening IMAP +;;; + +(defun mew-imap2-open (pnm server port) + (let ((sprt (mew-*-to-port port)) + pro tm) + (condition-case emsg + (progn + (setq tm (run-at-time mew-imap-timeout-time nil 'mew-imap2-timeout)) + (message "Connecting to the IMAP server...") + (setq pro (open-network-stream pnm nil server sprt)) + (mew-process-silent-exit pro) + (mew-set-process-cs pro mew-cs-text-for-net mew-cs-text-for-net) + (message "Connecting to the IMAP server...done")) + (quit + (setq pro nil) + (message "Cannot connect to the IMAP server")) + (error + (setq pro nil) + (message "%s, %s" (nth 1 emsg) (nth 2 emsg)))) + (if tm (cancel-timer tm)) + pro)) + +(defun mew-imap2-timeout () + (signal 'quit nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Launcher +;;; + +(defun mew-imap2-copy-message (case directive src-list &optional dst) + (let* ((server (mew-imap-server case)) + (user (mew-imap-user case)) + (port (mew-*-to-string (mew-imap-port case))) + (pnm (mew-imap2-info-name case)) + (sshsrv (mew-imap-ssh-server case)) + (sslp (mew-imap-ssl case)) + (sslport (mew-imap-ssl-port case)) + (proxysrv (mew-imap-proxy-server case)) + (proxyport (mew-imap-proxy-port case)) + process sshname sshpro sslname sslpro lport tls) + (cond + (sshsrv + (setq sshpro (mew-open-ssh-stream case server port sshsrv)) + (when sshpro + (setq sshname (process-name sshpro)) + (setq lport (mew-ssh-pnm-to-lport sshname)) + (when lport + (setq process (mew-imap2-open pnm "localhost" lport))))) + (sslp + (if (mew-port-equal port sslport) (setq tls mew-tls-imap)) + (setq sslpro (mew-open-ssl-stream case server sslport tls)) + (when sslpro + (setq sslname (process-name sslpro)) + (setq lport (mew-ssl-pnm-to-lport sslname)) + (when lport + (setq process (mew-imap2-open pnm mew-ssl-localhost lport))))) + (proxysrv + (setq process (mew-imap2-open pnm proxysrv proxyport))) + (t + (setq process (mew-imap2-open pnm server port)))) + (if (null process) + (cond + ((and sshsrv (null sshpro)) + (message "Cannot create to the SSH connection")) + ((and sslp (null sslpro)) + (message "Cannot create to the SSL/TLS connection")) + (t + (message "Cannot connect to the IMAP server"))) + (mew-info-clean-up pnm) + (mew-imap2-set-case pnm case) + (mew-imap2-set-directive pnm directive) + (mew-imap2-set-server pnm server) + (mew-imap2-set-port pnm port) + (mew-imap2-set-process pnm process) + (mew-imap2-set-ssh-server pnm sshsrv) + (mew-imap2-set-ssh-process pnm sshpro) + (mew-imap2-set-ssl-process pnm sslpro) + (mew-imap2-set-user pnm user) + (mew-imap2-set-account pnm (format "%s@%s" user server)) + (mew-imap2-set-auth pnm (mew-imap-auth case)) + (mew-imap2-set-auth-list pnm (mew-imap-auth-list case)) + (mew-imap2-set-status pnm "greeting") + (mew-imap2-set-src-list pnm src-list) + (mew-imap2-set-src-list-orig pnm src-list) + (mew-imap2-set-mailbox pnm dst) + ;; + (set-process-buffer process nil) + (set-process-sentinel process 'mew-imap2-sentinel) + (set-process-filter process 'mew-imap2-filter) + (message "Copying in background...")))) + +(defun mew-summary-from-local-to-imap () + "Copy messages in local folders under specified folder prefix +to a IMAP server decided by specified case. This may take very long +time (even several days) if there are many local messages." + (interactive) + (let* ((prefix (mew-input-local-folder mew-folder-local)) + (case (mew-input-case mew-case-default "IMAP")) + (alist (mew-local-folder-alist)) + regex src-list fld) + (unless prefix (setq prefix mew-folder-local)) + (setq regex (concat "^" (regexp-quote prefix))) + (dolist (ent alist) + (setq fld (car ent)) + (if (string-match regex fld) + (setq src-list (cons fld src-list)))) + (setq src-list (nreverse src-list)) + (mew-imap2-copy-message case 'cp-r src-list))) + +(defun mew-imap2-fcc (case) + (let* ((prefix mew-folder-imap-fcc-prefix) + (fcc-dir (mew-folder-imap-fcc-dir case)) + (fcc-dirs (mew-dir-list fcc-dir)) + (src-list (mew-local-folder-make-alist fcc-dirs prefix 'make-list))) + ;; src-list + (mew-imap2-copy-message case 'fcc src-list))) + +(defun mew-summary-imap-copy () + "Copy a message to the server side of IMAP." + (interactive) + (mew-summary-not-in-draft + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (fld/msg (mew-expand-msg fld msg)) + (src-list (list fld/msg)) + (case:dst (mew-input-folder mew-case mew-imap-inbox-folder)) + (case (mew-case:folder-case case:dst)) + (dst (mew-case:folder-folder case:dst))) + (when (mew-folder-imapp dst) + (mew-imap2-copy-message case 'copy src-list dst))))) + +(defun mew-summary-mark-imap-copy (&optional arg) + "Copy messages marked with '*' to the server side of IMAP. +If called with '\\[universal-argument]', only messages marked +with '*' in the region are handled." + (interactive "P") + (mew-summary-not-in-draft + (let* ((fld (mew-summary-folder-name)) + (case:dst (mew-input-folder mew-case mew-imap-inbox-folder)) + (case (mew-case:folder-case case:dst)) + (dst (mew-case:folder-folder case:dst)) + msgs beg end region src-list) + (if (mew-mark-active-p) (setq arg t)) + (cond + (arg + (setq region (mew-summary-get-region)) + (setq beg (car region)) + (setq end (cdr region))) + (t + (setq beg (point-min)) + (setq end (point-max)))) + (setq msgs (mew-summary-mark-collect mew-mark-review beg end)) + (if (null msgs) + (message "No mark") + (when (mew-folder-imapp dst) + (setq src-list (mapcar (lambda (x) (mew-expand-msg fld x)) msgs)) + (mew-imap2-copy-message case 'copy src-list dst)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defun mew-imap2-debug (label string) + (when (mew-debug 'net) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +(defun mew-imap2-filter (process string) + (let* ((pnm (process-name process)) + (status (mew-imap2-get-status pnm)) + (tag (mew-imap2-get-tag pnm)) + (eos (format "^%s \\(OK\\|NO\\|BAD\\)\\(.*\\)" tag)) + (str (concat (mew-imap2-get-string pnm) string)) + (buf (process-buffer process)) + aux stay next func code resp) + (save-excursion + (mew-imap2-debug (upcase status) string) + (if (and buf (get-buffer buf)) (set-buffer buf)) + (while (string-match "^\\*[^\n]*\n" str) + (setq aux (substring str 0 (match-end 0))) + (setq str (substring str (match-end 0))) + (cond + ((string= status "greeting") + (setq next (mew-imap2-fsm-next "greeting" "OK"))) + ((string= status "capability") + (mew-imap2-set-aux pnm (concat (mew-imap2-get-aux pnm) aux))))) + (mew-imap2-set-string pnm str) + (cond + (next + nil) + ((string-match "^\\+" str) + (mew-imap2-set-aux pnm str) + (setq next (mew-imap2-fsm-next status "OK"))) + ((string-match eos str) + (mew-imap2-set-tag pnm nil) + (setq code (mew-match-string 1 str)) + (setq resp (mew-match-string 2 str)) + (setq next (mew-imap2-fsm-next status code)) + (unless next (setq next (mew-imap2-fsm-next status resp)))) + (t + (setq stay t))) + (unless stay + (unless next (setq next "logout")) + (mew-imap2-set-status pnm next) + (setq func (intern-soft (concat "mew-imap2-command-" next))) + (if (fboundp func) + (funcall func process pnm) + (error "No function called %s" (symbol-name func))) + (mew-imap2-set-string pnm nil))))) + +(defun mew-imap2-sentinel (process event) + (let* ((pnm (process-name process)) + (directive (mew-imap2-get-directive pnm)) + (case (mew-imap2-get-case pnm)) + (done (mew-imap2-get-done pnm)) + (error (mew-imap2-get-error pnm)) + (sshpro (mew-imap2-get-ssh-process pnm)) + (sslpro (mew-imap2-get-ssl-process pnm)) + (srcflds (mew-imap2-get-src-list-orig pnm))) + (save-excursion + (mew-imap2-debug "IMAP SENTINEL" event) + (cond + (error + (message "%s" error)) + (done + (cond + ((eq directive 'fcc) + (dolist (srcfld srcflds) + (mew-imap2-copy-fcc-cache case srcfld)) + (mew-delete-directory-recursively + (mew-folder-imap-fcc-dir case))) + ((eq directive 'move) + (let ((file (car (mew-imap2-get-src-list-orig pnm)))) + (if (file-exists-p file) (delete-file file))))) + (message "Copying in background...done")) + (t + (message "IMAP connection is lost"))) + (mew-info-clean-up pnm) + (if (and (processp sshpro) (not mew-ssh-keep-connection)) + (process-send-string sshpro "exit\n")) + (if (and (processp sslpro) (not mew-ssl-keep-connection)) + (delete-process sslpro)) + (run-hooks 'mew-imap2-sentinel-hook)))) + +(defun mew-imap2-copy-fcc-cache (case srcfld) + (let* ((case:srcfld (mew-case-folder case srcfld)) + (srcs (mew-folder-messages case:srcfld)) + (prefix (file-name-as-directory mew-folder-imap-fcc-prefix)) + (regex (concat "^" (regexp-quote prefix))) + dst dstfld case:dstfld i) + (string-match regex srcfld) + (setq dstfld (concat mew-folder-imap (substring srcfld (match-end 0)))) + (setq case:dstfld (mew-case-folder case dstfld)) + (mew-local-folder-check case:dstfld) + (setq i (string-to-number (mew-folder-new-message case:dstfld 'num 'cache))) + ;; to make code simple, we just copy the file. + (dolist (src srcs) + (setq dst (mew-i2s i 'cache)) + (copy-file (mew-expand-msg case:srcfld src) + (mew-expand-new-msg case:dstfld dst)) + (setq i (1+ i))) + (mew-touch-folder case:dstfld))) + +(provide 'mew-imap2) + +;;; Copyright Notice: + +;; Copyright (C) 2003-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-imap2.el ends here diff --git a/elpa/mew-20150813.2354/mew-key.el b/elpa/mew-20150813.2354/mew-key.el new file mode 100644 index 00000000..4b753f6a --- /dev/null +++ b/elpa/mew-20150813.2354/mew-key.el @@ -0,0 +1,690 @@ +;;; mew-key.el + +;; Author: Kazu Yamamoto +;; Created: Feb 1, 1999 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mode map +;;; + +(defvar mew-summary-mode-map nil) +(defvar mew-message-mode-map nil) +(defvar mew-draft-mode-map nil) +(defvar mew-draft-header-map nil) +(defvar mew-draft-body-map nil) +(defvar mew-draft-attach-map nil) +(defvar mew-header-mode-map nil) +(defvar mew-addrbook-mode-map nil) +(defvar mew-input-map nil) +(defvar mew-input-folder-map nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Summary mode +;;; + +(unless mew-summary-mode-map + (setq mew-summary-mode-map (make-sparse-keymap)) + (define-key mew-summary-mode-map "0" 'digit-argument) + (define-key mew-summary-mode-map "1" 'digit-argument) + (define-key mew-summary-mode-map "2" 'digit-argument) + (define-key mew-summary-mode-map "3" 'digit-argument) + (define-key mew-summary-mode-map "4" 'digit-argument) + (define-key mew-summary-mode-map "5" 'digit-argument) + (define-key mew-summary-mode-map "6" 'digit-argument) + (define-key mew-summary-mode-map "7" 'digit-argument) + (define-key mew-summary-mode-map "8" 'digit-argument) + (define-key mew-summary-mode-map "9" 'digit-argument) + (define-key mew-summary-mode-map " " 'mew-summary-display) + (define-key mew-summary-mode-map "." 'mew-summary-analyze-again) + (define-key mew-summary-mode-map ":" + 'mew-summary-analyze-again-alternative) + (define-key mew-summary-mode-map "," 'mew-summary-display-asis) + (define-key mew-summary-mode-map ";" 'mew-summary-trace-path) +;; (define-key mew-summary-mode-map "\e<" 'mew-summary-jump-top) +;; (define-key mew-summary-mode-map "\e>" 'mew-summary-jump-bottom) + (define-key mew-summary-mode-map "<" 'mew-summary-scroll-right) + (define-key mew-summary-mode-map ">" 'mew-summary-scroll-left) + (define-key mew-summary-mode-map "\d" 'mew-summary-prev-page) + (define-key mew-summary-mode-map "\r" 'mew-summary-scroll-up) + (define-key mew-summary-mode-map "-" 'mew-summary-scroll-down) + (define-key mew-summary-mode-map "\e\r" 'mew-summary-scroll-down) + (define-key mew-summary-mode-map "g" 'mew-summary-goto-folder) + (define-key mew-summary-mode-map "j" 'mew-summary-goto-line) + (define-key mew-summary-mode-map "i" 'mew-summary-retrieve) + (define-key mew-summary-mode-map "I" 'mew-summary-retrieve-message) + (define-key mew-summary-mode-map "a" 'mew-summary-reply) + (define-key mew-summary-mode-map "A" 'mew-summary-reply-with-citation) + (define-key mew-summary-mode-map "D" 'mew-summary-clean-trash) + (define-key mew-summary-mode-map "E" 'mew-summary-reedit) + (define-key mew-summary-mode-map "\ei" 'mew-summary-edit-again) + (define-key mew-summary-mode-map "\ee" 'mew-summary-edit) + (define-key mew-summary-mode-map "f" 'mew-summary-forward) + (define-key mew-summary-mode-map "F" 'mew-summary-multi-forward) + (define-key mew-summary-mode-map "r" 'mew-summary-resend) + (define-key mew-summary-mode-map "$" 'mew-summary-escape) + (define-key mew-summary-mode-map "*" 'mew-summary-review) + (define-key mew-summary-mode-map "\eu" 'mew-summary-unread) + (define-key mew-summary-mode-map "y" 'mew-summary-save) + (define-key mew-summary-mode-map "b" 'mew-summary-store) + (define-key mew-summary-mode-map "Y" 'mew-summary-cite) + (define-key mew-summary-mode-map "u" 'mew-summary-undo) + (define-key mew-summary-mode-map "U" 'mew-summary-undo-all) + (define-key mew-summary-mode-map "n" 'mew-summary-display-down) + (define-key mew-summary-mode-map "p" 'mew-summary-display-up) + (define-key mew-summary-mode-map "\C-n" 'mew-summary-next-line) + (define-key mew-summary-mode-map "\C-p" 'mew-summary-previous-line) + (define-key mew-summary-mode-map "e" 'mew-summary-exchange-marks) + (define-key mew-summary-mode-map "M" (make-sparse-keymap)) + (define-key mew-summary-mode-map "Md" 'mew-summary-mark-duplicated) + (define-key mew-summary-mode-map "M*" 'mew-summary-redo) + (define-key mew-summary-mode-map "N" 'mew-summary-display-review-down) + (define-key mew-summary-mode-map "P" 'mew-summary-display-review-up) + (define-key mew-summary-mode-map "\en" 'mew-summary-find-keyword-down) + (define-key mew-summary-mode-map "\ep" 'mew-summary-find-keyword-up) + (define-key mew-summary-mode-map "w" 'mew-summary-write) + (define-key mew-summary-mode-map "W" 'mew-summary-send-to-others) + (define-key mew-summary-mode-map "B" 'mew-summary-burst) + (define-key mew-summary-mode-map "K" 'mew-summary-old-burst) + (define-key mew-summary-mode-map "J" 'mew-summary-join) + (define-key mew-summary-mode-map "Z" 'mew-status-update) + (define-key mew-summary-mode-map "#" 'mew-summary-print) + (define-key mew-summary-mode-map "|" 'mew-summary-pipe-message) + (define-key mew-summary-mode-map "\\" 'mew-summary-cmd-msg) + (define-key mew-summary-mode-map "q" 'mew-summary-suspend) + (define-key mew-summary-mode-map "Q" 'mew-summary-quit) + (define-key mew-summary-mode-map "C" 'mew-summary-set-case) + (define-key mew-summary-mode-map "h" 'mew-summary-goto-msg-mode) + (define-key mew-summary-mode-map "\C-c\C-a" 'mew-summary-addrbook-add) + (define-key mew-summary-mode-map "\C-c\C-c" 'mew-summary-send-message) + (define-key mew-summary-mode-map "\C-c\C-e" 'mew-summary-execute-external) + (define-key mew-summary-mode-map "\C-c\t" 'mew-summary-find-file) + (define-key mew-summary-mode-map "\C-c\C-f" 'mew-pgp-fetch-key) + (define-key mew-summary-mode-map "\C-c\C-v" 'mew-pgp-select) + (define-key mew-summary-mode-map "\C-c\C-m" 'mew-passwd-change) + (define-key mew-summary-mode-map "\C-c\C-s" 'mew-summary-isearch-forward) + (define-key mew-summary-mode-map "\C-c\C-r" 'mew-summary-isearch-backward) + (define-key mew-summary-mode-map "\C-c\C-o" + 'mew-summary-jump-to-draft-buffer) + (define-key mew-summary-mode-map "\ea" 'mew-summary-alias-edit) + (define-key mew-summary-mode-map "\el" 'mew-summary-recenter) + (define-key mew-summary-mode-map "\et" 'mew-summary-uudecode) + (define-key mew-summary-mode-map "\es" 'mew-summary-sort) + (define-key mew-summary-mode-map "\eb" 'mew-summary-burst-multi) + (define-key mew-summary-mode-map "\e\\" 'mew-summary-cmd-msgs) + (define-key mew-summary-mode-map "v" 'mew-summary-toggle-disp-msg) + (define-key mew-summary-mode-map "V" 'mew-summary-selection-by-msgid) + (define-key mew-summary-mode-map "\C-c\C-l" 'mew-summary-convert-local-cs) + (define-key mew-summary-mode-map "\C-c\C-z" 'mew-summary-decode-old-pgp) + (define-key mew-summary-mode-map "\C-c\C-q" 'mew-summary-kill) + (define-key mew-summary-mode-map "\C-c\C-x" 'mew-summary-x-face) + (define-key mew-summary-mode-map "\C-c\C-k" 'mew-summary-kill-subprocess) + (define-key mew-summary-mode-map "^" 'mew-summary-parent) + (define-key mew-summary-mode-map "&" 'mew-summary-child) + (define-key mew-summary-mode-map "(" 'mew-summary-thread-sibling-up) + (define-key mew-summary-mode-map ")" 'mew-summary-thread-sibling-down) + (define-key mew-summary-mode-map "m" (make-sparse-keymap)) + (define-key mew-summary-mode-map "md" 'mew-summary-mark-delete) + (define-key mew-summary-mode-map "m\ed" 'mew-summary-mark-unlink) + (define-key mew-summary-mode-map "m$" 'mew-summary-mark-escape) + (define-key mew-summary-mode-map "m*" 'mew-summary-mark-review) + (define-key mew-summary-mode-map "m\eu" 'mew-summary-mark-unread) + (define-key mew-summary-mode-map "ms" 'mew-summary-mark-swap) + (define-key mew-summary-mode-map "mo" 'mew-summary-mark-refile) + (define-key mew-summary-mode-map "mc" 'mew-summary-mark-copy) + (define-key mew-summary-mode-map "mr" 'mew-summary-mark-regexp) + (define-key mew-summary-mode-map "ma" 'mew-summary-mark-all) + (define-key mew-summary-mode-map "mu" 'mew-summary-mark-undo-all) + (define-key mew-summary-mode-map "mI" 'mew-summary-mark-retrieve-message) + (define-key mew-summary-mode-map "ml" (make-sparse-keymap)) + (define-key mew-summary-mode-map "mlc" 'mew-summary-mark-local-copy) + (define-key mew-summary-mode-map "mli" 'mew-summary-mark-imap-copy) + (define-key mew-summary-mode-map "/" 'mew-summary-selection-by-pick) + (define-key mew-summary-mode-map "?" 'mew-summary-pick) + (define-key mew-summary-mode-map "'" 'mew-summary-grep-old) + (define-key mew-summary-mode-map "m/" 'mew-summary-selection-by-mark) + (define-key mew-summary-mode-map "mt" 'mew-summary-mark-thread) + (define-key mew-summary-mode-map "t" (make-sparse-keymap)) + (define-key mew-summary-mode-map "tt" 'mew-summary-make-thread) + (define-key mew-summary-mode-map "tn" 'mew-thread-down) + (define-key mew-summary-mode-map "tp" 'mew-thread-up) + (define-key mew-summary-mode-map "t " 'mew-thread-toggle) + (define-key mew-summary-mode-map "ta" 'mew-thread-toggle-all) + (define-key mew-summary-mode-map "t(" 'mew-thread-all-graft) + (define-key mew-summary-mode-map "t)" 'mew-thread-all-prune) + (define-key mew-summary-mode-map "t*" 'mew-thread-mark-review) + (define-key mew-summary-mode-map "t$" 'mew-thread-mark-escape) + (define-key mew-summary-mode-map "td" 'mew-thread-mark-delete) + (define-key mew-summary-mode-map "to" 'mew-thread-mark-refile) + (define-key mew-summary-mode-map "tc" 'mew-thread-mark-copy) + (define-key mew-summary-mode-map "t\ed" 'mew-thread-mark-unlink) + (define-key mew-summary-mode-map "tu" 'mew-thread-unmark) + (define-key mew-summary-mode-map "tg" 'mew-thread-glue) + (define-key mew-summary-mode-map "tr" 'mew-summary-regexp-make-thread) + (define-key mew-summary-mode-map "z" (make-sparse-keymap)) + (define-key mew-summary-mode-map "z8" 'mew-summary-toggle-8bit) + (define-key mew-summary-mode-map "zc" 'mew-summary-cache-clean-up) + (define-key mew-summary-mode-map "zd" 'mew-summary-toggle-debug) + (define-key mew-summary-mode-map "zp" 'mew-summary-toggle-policy) + (define-key mew-summary-mode-map "zo" 'mew-summary-toggle-pgp) + (define-key mew-summary-mode-map "zv" 'mew-summary-toggle-header-veil) + (define-key mew-summary-mode-map "zw" 'mew-summary-toggle-warning) + (define-key mew-summary-mode-map "zi" 'mew-summary-toggle-invisible) + (define-key mew-summary-mode-map "z " 'mew-summary-toggle-mark-regex) + (define-key mew-summary-mode-map "zz" 'mew-summary-unzip) + (define-key mew-summary-mode-map "l" (make-sparse-keymap)) + (define-key mew-summary-mode-map "lc" 'mew-summary-local-copy) + (define-key mew-summary-mode-map "li" 'mew-summary-imap-copy) + (define-key mew-summary-mode-map "lh" 'mew-summary-learn-ham) + (define-key mew-summary-mode-map "ls" 'mew-summary-learn-spam) + (define-key mew-summary-mode-map "=" 'mew-summary-info) + (define-key mew-summary-mode-map "_" 'mew-summary-line) + (define-key mew-summary-mode-map "k" (make-sparse-keymap)) + (define-key mew-summary-mode-map "kc" 'mew-summary-search-change-method) + (define-key mew-summary-mode-map "k?" 'mew-summary-search) + (define-key mew-summary-mode-map "k/" 'mew-summary-selection-by-search) + (define-key mew-summary-mode-map "km" 'mew-summary-make-index-folder) + (define-key mew-summary-mode-map "kM" 'mew-summary-make-index-all) + (define-key mew-summary-mode-map "ki" 'mew-summary-make-id-index-folder) + (define-key mew-summary-mode-map "kI" 'mew-summary-make-id-index-all) + (define-key mew-summary-mode-map "kj" 'mew-summary-goto-original-message) + ;; + ;; not provided in Virtual mode + ;; + (define-key mew-summary-mode-map "!" 'mew-summary-refile-again) + (define-key mew-summary-mode-map "o" 'mew-summary-refile) + (define-key mew-summary-mode-map "c" 'mew-summary-copy) + (define-key mew-summary-mode-map "d" 'mew-summary-delete) + (define-key mew-summary-mode-map "\ed" 'mew-summary-unlink) + (define-key mew-summary-mode-map "x" 'mew-summary-exec) + (define-key mew-summary-mode-map "X" 'mew-summary-exec-one) + (define-key mew-summary-mode-map "lx" 'mew-summary-exec-offline) + (define-key mew-summary-mode-map "lX" 'mew-summary-exec-offline-one) + (define-key mew-summary-mode-map "mxd" 'mew-summary-exec-delete) + (define-key mew-summary-mode-map "mx\ed" 'mew-summary-exec-unlink) + (define-key mew-summary-mode-map "mxo" 'mew-summary-exec-refile) + (define-key mew-summary-mode-map "s" 'mew-summary-ls) + (define-key mew-summary-mode-map "O" 'mew-summary-pack) + (define-key mew-summary-mode-map "S" 'mew-summary-selection-by-sort) + (define-key mew-summary-mode-map "\C-c\C-b" 'mew-summary-exchange-point) + (define-key mew-summary-mode-map "\eo" 'mew-summary-auto-refile) + (define-key mew-summary-mode-map "R" (make-sparse-keymap)) + (define-key mew-summary-mode-map "Rd" 'mew-summary-delete-folder) + (define-key mew-summary-mode-map "Rr" 'mew-summary-rename-folder) + ;; + (define-key mew-summary-mode-map [mouse-2] 'mew-summary-mouse-show)) + +(defvar mew-summary-mode-menu-spec + '("Mew" + ["Show" mew-summary-display t] + ["Next" mew-summary-display-down t] + ["Previous" mew-summary-display-up t] + ["Top" mew-summary-jump-top t] + ["Bottom" mew-summary-jump-bottom t] + "----" + ["Delete" mew-summary-delete (mew-summary-p)] + ["Refile" mew-summary-refile (mew-summary-case1)] + ["Refile again" mew-summary-refile-again (mew-summary-case1)] + ["Mark review" mew-summary-mark-review t] + ["Mark escape" mew-summary-mark-escape t] + ["Undo" mew-summary-undo t] + ["Undo all" mew-summary-undo-all t] + ["Execute" mew-summary-exec (mew-summary-p)] + ["Suspend" mew-summary-suspend t] + ["Quit" mew-summary-quit t] + "----" + ("Manipulate folder" + ["Retrieve" mew-summary-retrieve t] + ["List" mew-summary-ls (mew-summary-p)] + ["Sort" mew-summary-sort (mew-summary-case2)] + ["Burst" mew-summary-burst t] + ["Go to folder" mew-summary-goto-folder t] + ) + ("Manipulate file" + ["Save" mew-summary-save t] + ["Convert body's character set" mew-summary-convert-local-cs t] + ["Display X-Face" mew-summary-x-face t] + ) + ("Write/Reply/Forward" + ["Write" mew-summary-send t] + ["Reedit" mew-summary-reedit t] + ["Reply" mew-summary-reply (mew-summary-case1)] + ["Reply with citation" mew-summary-reply-with-citation (mew-summary-case1)] + ["Forward" mew-summary-forward (mew-summary-case1)] + ["Multi forward" mew-summary-multi-forward (mew-summary-case1)] + ) + ("Select" + ["Pick then mark" mew-summary-pick (mew-pickable-p)] + ["Selection" mew-summary-selection-by-pick (mew-pickable-p)] + ) + ("Misc" + ["Clean +trash" mew-summary-clean-trash t] + ["Recenter" mew-summary-recenter t] + ["Uudecode" mew-summary-uudecode t] + ["Unshar" mew-summary-unshar t] + ["Multi burst" mew-summary-burst-multi t] + ["Print" mew-summary-print t] + ["Pipe message" mew-summary-pipe-message t] + ["Isearch forward" mew-summary-isearch-forward t] + ["Isearch backward" mew-summary-isearch-backward t] + ["Toggle disp msg" mew-summary-toggle-disp-msg t] + ["Set cases" mew-summary-set-case t] + ["PGP public key fetch" mew-pgp-fetch-key t] + ["Kill Sub-Process" mew-summary-kill-subprocess (mew-summary-case3)] + ))) + +(defvar mew-summary-mode-toolbar-menu + '("Mew Part Commands" + ["Save" mew-summary-save t] + ["Reply" mew-summary-reply t])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message mode +;;; + +(unless mew-message-mode-map + (setq mew-message-mode-map (make-sparse-keymap)) + (define-key mew-message-mode-map " " 'mew-message-next-page) + (define-key mew-message-mode-map "\d" 'mew-message-prev-page) + (define-key mew-message-mode-map "n" 'mew-message-next-msg) + (define-key mew-message-mode-map "p" 'mew-message-prev-msg) + (define-key mew-message-mode-map "h" 'mew-message-goto-summary) + (define-key mew-message-mode-map "a" 'mew-message-reply) + (define-key mew-message-mode-map "A" 'mew-message-reply-with-citation) + (define-key mew-message-mode-map "f" 'mew-message-forward) + (define-key mew-message-mode-map "r" 'mew-message-resend) + (define-key mew-message-mode-map "<" 'mew-message-scroll-right) + (define-key mew-message-mode-map ">" 'mew-message-scroll-left) + (define-key mew-message-mode-map "_" 'mew-message-line) + (define-key mew-message-mode-map "g" 'mew-browse-url-at-point) + (define-key mew-message-mode-map "\C-i" 'mew-message-goto-next-url)) + +(defvar mew-message-mode-menu-spec + '("Mew" + ["Next part" mew-message-next-msg t] + ["Prev part" mew-message-prev-msg t] + ["Next page" mew-message-next-page t] + ["Prev page" mew-message-prev-page t] + ["Goto summary" mew-message-goto-summary t])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Draft mode +;;; + +(defun mew-draft-share-keymap (symmap) + (if (featurep 'meadow) + (define-key (symbol-value symmap) [drag-n-drop] 'mew-draft-dnd-for-meadow)) + (define-key (symbol-value symmap) "\C-x\C-s" 'mew-draft-save-buffer) + (define-key (symbol-value symmap) "\C-c\C-m" 'mew-draft-make-message) + (define-key (symbol-value symmap) "\C-c\C-c" 'mew-draft-send-message) + (define-key (symbol-value symmap) "\C-c\C-o" 'mew-draft-set-case) + (define-key (symbol-value symmap) "\C-c\C-a" 'mew-draft-prepare-attachments) + (define-key (symbol-value symmap) "\C-c\C-l" 'mew-draft-rehighlight) + (define-key (symbol-value symmap) "\C-c\C-q" 'mew-draft-kill) + (define-key (symbol-value symmap) "\C-c\C-s" 'mew-draft-sign-message) + (define-key (symbol-value symmap) "\C-c\C-e" 'mew-draft-encrypt-message) + (define-key (symbol-value symmap) "\C-c\C-b" 'mew-draft-sign-encrypt-message) + (define-key (symbol-value symmap) "\C-c\C-r" 'mew-draft-encrypt-sign-message) + (define-key (symbol-value symmap) "\C-c\C-p\C-m" + 'mew-draft-set-privacy-method) + (define-key (symbol-value symmap) "\C-c\C-p\C-a" + 'mew-draft-toggle-privacy-always) + (define-key (symbol-value symmap) "\C-c\C-p\C-e" + 'mew-draft-toggle-privacy-encrypted) + (define-key (symbol-value symmap) "\C-c\C-p\C-d" + 'mew-draft-set-privacy-type) + (define-key (symbol-value symmap) "\C-c\C-p\C-f" + 'mew-draft-use-format-flowed)) + +(unless mew-draft-header-map + (setq mew-draft-header-map (make-sparse-keymap)) + (define-key mew-draft-header-map "\t" 'mew-draft-header-comp) + (define-key mew-draft-header-map "\C-c\t" 'mew-draft-circular-comp) + (define-key mew-draft-header-map "\e\t" 'mew-draft-expand) + (define-key mew-draft-header-map "\e\C-e" 'mew-draft-addrbook-expand) + (mew-draft-share-keymap 'mew-draft-header-map)) + +(unless mew-draft-body-map + (setq mew-draft-body-map (make-sparse-keymap)) + (set-keymap-parent mew-draft-body-map text-mode-map) + (define-key mew-draft-body-map "\C-c\t" 'mew-draft-insert-signature) + (define-key mew-draft-body-map "\C-c\C-y" 'mew-draft-cite) + (define-key mew-draft-body-map "\C-c\C-t" 'mew-draft-yank) + (define-key mew-draft-body-map "\C-c\C-f" 'mew-draft-encode-flowed) + (define-key mew-draft-body-map "\C-c\C-n\C-f" 'mew-fib-fill-default) + (define-key mew-draft-body-map "\C-c\C-n\C-k" 'mew-fib-delete-frame) + (define-key mew-draft-body-map "\C-c\C-n\C-n" 'mew-fib-next-item) + (define-key mew-draft-body-map "\C-c\C-n\C-p" 'mew-fib-previous-item) + (define-key mew-draft-body-map "\C-c\C-n\C-z" 'mew-fib-flush-input) + (mew-draft-share-keymap 'mew-draft-body-map)) + +(unless mew-draft-mode-map + (setq mew-draft-mode-map (make-sparse-keymap)) + (set-keymap-parent mew-draft-mode-map mew-draft-body-map)) + +(defvar mew-draft-mode-toolbar-menu + '("Attachment Commands" + ["Insert a File by Linking" + mew-attach-link + (mew-attach-not-line012-1)] + ["Insert a File by Copying" + mew-attach-copy + (mew-attach-not-line012-1)] + ["Insert Audio" + mew-attach-audio + (mew-attach-not-line012-1)] + ["Insert an External Reference" + mew-attach-external-body + (mew-attach-not-line012-1)] + ["Insert a Sub-Multipart" + mew-attach-multipart + (mew-attach-not-line012-1)] + ["Read a New File into a Buffer" + mew-attach-find-new-file + (mew-attach-not-line012-1)] + ["Insert PGP public keys" + mew-attach-pgp-public-key + (mew-attach-not-line012-1)] + "----" + ["Delete This Part" + mew-attach-delete + (mew-attach-not-line012-1-dot)] + "----" + ["Describe This Part" + mew-attach-description + (mew-attach-not-line0-1-dot)] + ["Specify A File Name" + mew-attach-disposition + (mew-attach-not-line012-1-dot)] + ["Change the Type" + mew-attach-type + (mew-attach-not-line0-1-dot)] + ["Encode with Gzip64" + mew-attach-gzip64 + (mew-attach-not-line0-1-dot)] + ["Encode with Base64" + mew-attach-base64 + (mew-attach-not-line0-1-dot)] + ["Encode with Quoted-Printable" + mew-attach-quoted-printable + (mew-attach-not-line0-1-dot)] + ["Sign with PGP" + mew-attach-pgp-sign + (mew-attach-not-line0-1-dot)] + ["Encrypt with PGP" + mew-attach-pgp-enc + (mew-attach-not-line0-1-dot)] + "----" + ["Read This File into a Buffer" + mew-attach-find-file + (mew-attach-not-line012-1-dot)])) + +(defvar mew-draft-mode-menu-spec + (list ;; need to eval mew-draft-mode-toolbar-menu + "Mew" + ["Cite" mew-draft-cite t] + ["Cite without Label" mew-draft-yank t] + ["Flowed" mew-draft-use-format-flowed :style toggle + :selected mew-use-format-flowed] + mew-draft-mode-toolbar-menu + ["Queue Message" mew-draft-make-message t] + ["Send Message" mew-draft-send-message t] + ["Prepare Attachments" mew-draft-prepare-attachments (not (mew-attach-p))] + ["Set cases" mew-draft-set-case t] + ["Insert Signature" mew-draft-insert-signature t] + ["Kill Draft" mew-draft-kill t] + "----" + '("PGP" + ["PGP Sign" mew-pgp-sign-message t] + ["PGP Encrypt" mew-pgp-encrypt-message t] + ["PGP Sign then Encrypt" mew-pgp-sign-encrypt-message t] + ["PGP Encrypt then Sign" mew-pgp-encrypt-sign-message t]) + '("Privacy" + ["All messages" mew-draft-toggle-privacy-always t] + ["Msgs replying to encrypted" mew-draft-toggle-privacy-encrypted t] + ["This message" mew-draft-set-privacy-type t]) + '("FIB" + ["FIB next item" mew-fib-next-item (not (mew-attach-p))] + ["FIB previous item" mew-fib-previous-item (not (mew-attach-p))] + ["FIB flush input" mew-fib-flush-input (not (mew-attach-p))] + ["FIB fill default" mew-fib-fill-default (not (mew-attach-p))] + ["FIB delete frame" mew-fib-delete-frame (not (mew-attach-p))]))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Header mode +;;; + +(unless mew-header-mode-map + (setq mew-header-mode-map (make-sparse-keymap)) + (define-key mew-header-mode-map "\C-x\C-s" 'mew-draft-save-buffer) + (define-key mew-header-mode-map "\t" 'mew-draft-header-comp) + (define-key mew-header-mode-map "\C-c\t" 'mew-draft-circular-comp) + (define-key mew-header-mode-map "\e\t" 'mew-draft-expand) + (define-key mew-header-mode-map "\C-c\C-m" 'mew-header-make-message) + (define-key mew-header-mode-map "\C-c\C-c" 'mew-header-send-message) + (define-key mew-header-mode-map "\C-c\C-q" 'mew-draft-kill) + (define-key mew-header-mode-map "\C-c\C-o" 'mew-draft-set-case)) + +(defvar mew-header-mode-menu-spec + '("Mew" + ["Queue Message" mew-header-make-message t] + ["Send Message" mew-header-send-message t] + ["Set cases" mew-draft-set-case t] + ["Kill Draft" mew-draft-kill t])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Attach mode +;;; + +(unless mew-draft-attach-map + (setq mew-draft-attach-map (make-keymap)) + (define-key mew-draft-attach-map "\C-m" 'mew-attach-newline) + (define-key mew-draft-attach-map "\C-f" 'mew-attach-forward) + (define-key mew-draft-attach-map "\C-b" 'mew-attach-backforward) + (define-key mew-draft-attach-map "\C-n" 'mew-attach-next) + (define-key mew-draft-attach-map "\C-p" 'mew-attach-previous) + (define-key mew-draft-attach-map "a" 'mew-attach-audio) + (define-key mew-draft-attach-map "c" 'mew-attach-copy) + (define-key mew-draft-attach-map "C" 'mew-attach-charset) + (define-key mew-draft-attach-map "I" 'mew-attach-icharset) + (define-key mew-draft-attach-map "d" 'mew-attach-delete) + (define-key mew-draft-attach-map "y" 'mew-attach-link-message) + (define-key mew-draft-attach-map "D" 'mew-attach-description) + (define-key mew-draft-attach-map "P" 'mew-attach-disposition) + (define-key mew-draft-attach-map "e" 'mew-attach-external-body) + (define-key mew-draft-attach-map "f" 'mew-attach-find-file) + (define-key mew-draft-attach-map "F" 'mew-attach-find-new-file) + (define-key mew-draft-attach-map "l" 'mew-attach-link) + (define-key mew-draft-attach-map "m" 'mew-attach-multipart) + (define-key mew-draft-attach-map "T" 'mew-attach-type) + (define-key mew-draft-attach-map "t" 'mew-attach-toggle) + (define-key mew-draft-attach-map "G" 'mew-attach-gzip64) + (define-key mew-draft-attach-map "B" 'mew-attach-base64) + (define-key mew-draft-attach-map "Q" 'mew-attach-quoted-printable) + (define-key mew-draft-attach-map "Z" 'mew-attach-zip) + (define-key mew-draft-attach-map "S" 'mew-attach-pgp-sign) + (define-key mew-draft-attach-map "E" 'mew-attach-pgp-enc) + (define-key mew-draft-attach-map "\es" 'mew-attach-smime-sign) + (define-key mew-draft-attach-map "\ee" 'mew-attach-smime-enc) + (define-key mew-draft-attach-map "p" 'mew-attach-pgp-public-key) + (define-key mew-draft-attach-map "U" 'mew-attach-undo) + (define-key mew-draft-attach-map "\C-c\t" 'mew-draft-insert-signature) + (mew-draft-share-keymap 'mew-draft-attach-map)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Addrbook mode +;;; + +(unless mew-addrbook-mode-map + (setq mew-addrbook-mode-map (make-sparse-keymap)) + (set-keymap-parent mew-addrbook-mode-map text-mode-map) + (define-key mew-addrbook-mode-map "\C-c\C-c" 'mew-addrbook-register) + (define-key mew-addrbook-mode-map "\C-c\C-q" 'mew-addrbook-kill)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Minibuffer +;;; + +(unless mew-input-map + (setq mew-input-map + (if (boundp 'minibuffer-local-map) + (copy-keymap minibuffer-local-map) + (make-sparse-keymap))) + (define-key mew-input-map "\r" 'mew-input-exit-minibuffer) + (define-key mew-input-map "\n" 'mew-input-exit-minibuffer) + (define-key mew-input-map "," 'mew-input-comma) + (define-key mew-input-map " " 'mew-input-complete) + (define-key mew-input-map "\t" 'mew-input-complete) + (define-key mew-input-map "?" 'mew-input-complete) + (define-key mew-input-map "\C-c\t" 'mew-circular-complete-switch) + (define-key mew-input-map [menu-bar minibuf] + (cons "Mew" (make-sparse-keymap "Mew"))) + (define-key mew-input-map [menu-bar minibuf quit] + (list 'menu-item "Quit" 'keyboard-escape-quit + :help "Abort input and exit minibuffer")) + (define-key mew-input-map [menu-bar minibuf return] + (list 'menu-item "Enter" 'exit-minibuffer + :help "Terminate input and exit minibuffer"))) + +(unless mew-input-folder-map + (setq mew-input-folder-map (copy-keymap mew-input-map)) + (let ((c 33)) ;; excluding SPC + (while (<= c 128) ;; including delete + (define-key mew-input-folder-map (char-to-string c) + 'mew-input-folder-self-insert) + (setq c (1+ c)))) + (define-key mew-input-folder-map "\d" 'mew-input-folder-self-insert) + (define-key mew-input-folder-map "\C-g" 'mew-input-folder-abort-minibuffer) + (define-key mew-input-folder-map "\r" 'mew-input-folder-exit-minibuffer) + (define-key mew-input-folder-map "\n" 'mew-input-folder-exit-minibuffer) + (define-key mew-input-folder-map "+" 'mew-input-folder-prefix) + (define-key mew-input-folder-map "%" 'mew-input-folder-prefix) + (define-key mew-input-folder-map "$" 'mew-input-folder-prefix) + (define-key mew-input-folder-map "-" 'mew-input-folder-prefix) + (define-key mew-input-folder-map "*" 'mew-input-folder-prefix) + (define-key mew-input-folder-map "," 'mew-input-folder-comma) + (define-key mew-input-folder-map "\C-s" 'mew-input-folder-search-forward) + (define-key mew-input-folder-map "\C-r" 'mew-input-folder-search-backward) + (define-key mew-input-folder-map "\C-n" 'mew-input-folder-search-forward) + (define-key mew-input-folder-map "\C-p" 'mew-input-folder-search-backward)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Toolbar +;;; + +(defvar mew-summary-toolbar-spec + '((mew-summary-display . "mew-show") + (mew-summary-display-down . "mew-next") + (mew-summary-display-up . "mew-prev") + (mew-summary-retrieve . "mew-inc") + (mew-summary-send . "mew-write") + (mew-summary-reply . "mew-reply") + (mew-summary-forward . "mew-forward") + (mew-summary-refile . "mew-refile"))) + +(defvar mew-message-toolbar-spec + '((mew-message-next-msg . "mew-next") + (mew-message-prev-msg . "mew-prev") + (mew-massage-reply . "mew-reply") + (mew-message-forward . "mew-forward"))) + +(defvar mew-draft-toolbar-spec + '((mew-draft-make-message . "mew-queue") + (mew-draft-send-message . "mew-send") + (mew-draft-cite . "mew-cite") + (mew-draft-yank . "mew-yank") + (mew-draft-prepare-attachments . "mew-attach") + (mew-pgp-sign-message . "mew-pgp-sign") + (mew-pgp-encrypt-message . "mew-pgp-enc") + (mew-pgp-sign-encrypt-message . "mew-pgp-sigenc"))) + +(defvar mew-header-toolbar-spec + '((mew-header-make-message . "mew-queue") + (mew-header-send-message . "mew-send"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Icons +;;; + +(defun mew-which-mew-etc () + (let ((file "mew.el")) + (catch 'loop + (dolist (path load-path) + (if (file-exists-p (expand-file-name file path)) + (throw 'loop (expand-file-name "etc" path))))))) + +(defvar mew-icon-directory (mew-which-mew-etc)) + +(defvar mew-icon-separate nil) +(defvar mew-icon-blank nil) +(defvar mew-icon-audio nil) +(defvar mew-icon-image nil) +(defvar mew-icon-video nil) +(defvar mew-icon-application/postscript nil) +(defvar mew-icon-application/octet-stream nil) +(defvar mew-icon-message/rfc822 nil) +(defvar mew-icon-message/external-body nil) +(defvar mew-icon-text nil) +(defvar mew-icon-multipart nil) +(defvar mew-icon-unknown nil) + +(defvar mew-icon-spec + '((separate . "mew-sep") + (text . "mew-Text") + (multipart . "mew-Folder") + (blank . "mew-Blank") + (audio . "mew-Audio") + (image . "mew-Image") + (video . "mew-Video") + (application/postscript . "mew-Postscript") + (application/octet-stream . "mew-Octet-Stream") + (message/rfc822 . "mew-Rfc822") + (message/external-body . "mew-External") + (unknown . "mew-Unknown"))) + +(provide 'mew-key) + +;;; Copyright Notice: + +;; Copyright (C) 2000-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-key.el ends here diff --git a/elpa/mew-20150813.2354/mew-lang-jp.el b/elpa/mew-20150813.2354/mew-lang-jp.el new file mode 100644 index 00000000..cfc63a86 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-lang-jp.el @@ -0,0 +1,219 @@ +;;-*-coding:iso-2022-7bit;-*- +;;; mew-lang-jp.el --- Japanese specific stuff for Mew + +;; Author: Mito +;; Kazu Yamamoto +;; Created: Sep 08, 1997 + +;;; Code: + +;; from jisx0201.el +(defvar mew-katakana-alist + '(( 161 . "(I'(B" ) + ( 162 . "(I1(B" ) + ( 163 . "(I((B" ) + ( 164 . "(I2(B" ) + ( 165 . "(I)(B" ) + ( 166 . "(I3(B" ) + ( 167 . "(I*(B" ) + ( 168 . "(I4(B" ) + ( 169 . "(I+(B" ) + ( 170 . "(I5(B" ) + ( 171 . "(I6(B" ) + ( 172 . "(I6^(B" ) + ( 173 . "(I7(B" ) + ( 174 . "(I7^(B" ) + ( 175 . "(I8(B" ) + ( 176 . "(I8^(B" ) + ( 177 . "(I9(B" ) + ( 178 . "(I9^(B" ) + ( 179 . "(I:(B" ) + ( 180 . "(I:^(B" ) + ( 181 . "(I;(B" ) + ( 182 . "(I;^(B" ) + ( 183 . "(I<(B" ) + ( 184 . "(I<^(B" ) + ( 185 . "(I=(B" ) + ( 186 . "(I=^(B" ) + ( 187 . "(I>(B" ) + ( 188 . "(I>^(B" ) + ( 189 . "(I?(B" ) + ( 190 . "(I?^(B" ) + ( 191 . "(I@(B" ) + ( 192 . "(I@^(B" ) + ( 193 . "(IA(B" ) + ( 194 . "(IA^(B" ) + ( 195 . "(I/(B" ) + ( 196 . "(IB(B" ) + ( 197 . "(IB^(B" ) + ( 198 . "(IC(B" ) + ( 199 . "(IC^(B" ) + ( 200 . "(ID(B" ) + ( 201 . "(ID^(B" ) + ( 202 . "(IE(B" ) + ( 203 . "(IF(B" ) + ( 204 . "(IG(B" ) + ( 205 . "(IH(B" ) + ( 206 . "(II(B" ) + ( 207 . "(IJ(B" ) + ( 208 . "(IJ^(B" ) + ( 209 . "(IJ_(B" ) + ( 210 . "(IK(B" ) + ( 211 . "(IK^(B" ) + ( 212 . "(IK_(B" ) + ( 213 . "(IL(B" ) + ( 214 . "(IL^(B" ) + ( 215 . "(IL_(B" ) + ( 216 . "(IM(B" ) + ( 217 . "(IM^(B" ) + ( 218 . "(IM_(B" ) + ( 219 . "(IN(B" ) + ( 220 . "(IN^(B" ) + ( 221 . "(IN_(B" ) + ( 222 . "(IO(B" ) + ( 223 . "(IP(B" ) + ( 224 . "(IQ(B" ) + ( 225 . "(IR(B" ) + ( 226 . "(IS(B" ) + ( 227 . "(I,(B" ) + ( 228 . "(IT(B" ) + ( 229 . "(I-(B" ) + ( 230 . "(IU(B" ) + ( 231 . "(I.(B" ) + ( 232 . "(IV(B" ) + ( 233 . "(IW(B" ) + ( 234 . "(IX(B" ) + ( 235 . "(IY(B" ) + ( 236 . "(IZ(B" ) + ( 237 . "(I[(B" ) + ( 239 . "(I\(B" ) ; (I\(B -> $B%o(B $B$KJQ49$9$k$h$&$K(B + ( 238 . "(I\(B" ) ; $B%o$H%n$N=gHV$,8r49$7$F$"$k!#(B + ( 240 . "(I((B" ) + ( 241 . "(I*(B" ) + ( 242 . "(I&(B" ) + ( 243 . "(I](B" ) + ( 244 . "(I3^(B" ) + ( 245 . "(I6(B" ) + ( 246 . "(I9(B" ))) + +(defvar mew-katakana-kigou-alist + '(( 162 . "(I$(B" ) + ( 163 . "(I!(B" ) + ( 166 . "(I%(B" ) + ( 171 . "(I^(B" ) + ( 172 . "(I_(B" ) + ( 188 . "(I0(B" ) + ( 214 . "(I"(B" ) + ( 215 . "(I#(B" ))) + +(defvar mew-dakuon-list + '( ?$B%+(B ?$B%-(B ?$B%/(B ?$B%1(B ?$B%3(B + ?$B%5(B ?$B%7(B ?$B%9(B ?$B%;(B ?$B%=(B + ?$B%?(B ?$B%A(B ?$B%D(B ?$B%F(B ?$B%H(B + ?$B%O(B ?$B%R(B ?$B%U(B ?$B%X(B ?$B%[(B)) + +(defvar mew-handakuon-list (memq ?$B%O(B mew-dakuon-list)) + +(defun mew-hankaku-code (ch) + (let* ((str (char-to-string ch)) + (ent (rassoc str mew-katakana-alist))) + (if ent (car ent)))) + +(defun mew-hankaku-kigou-code (ch) + (let* ((str (char-to-string ch)) + (ent (rassoc str mew-katakana-kigou-alist))) + (if ent (car ent)))) + +(defun mew-zenkaku-katakana-region (beg end) + (let (ch wk) + (save-restriction + (narrow-to-region beg end) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\\ck" nil t) + (setq ch (preceding-char)) + (setq wk nil) + (cond + ((= ch ?(I^(B) + (save-excursion + (backward-char 1) + (setq wk (preceding-char))) + (cond + ((= wk ?$B%&(B) + (delete-char -2) + (insert "$B%t(B")) + ((setq wk (memq wk mew-dakuon-list)) + (delete-char -2) + (insert (1+ (car wk)))) + (t + (delete-char -1) + (insert "$B!+(B")))) + ((= ch ?(I_(B) + (save-excursion + (backward-char 1) + (setq wk (preceding-char))) + (if (setq wk (memq wk mew-handakuon-list)) + (progn + (delete-char -2) + (insert (+ 2 (car wk)))) + (delete-char -1) + (insert "$B!,(B"))) + ((setq wk (mew-hankaku-code ch)) + (delete-char -1) + (insert (make-char mew-lc-jp ?\245 wk))) + ((setq wk (mew-hankaku-kigou-code ch)) + (delete-char -1) + (insert (make-char mew-lc-jp ?\241 wk))))))))) + +;; + +(defvar mew-thread-indent-strings ["$B(2(B" "$B(1(B" "$B(-(B" "$B!!(B"]) + +(defvar mew-highlight-body-regex-cite + "^\\(\\([ \t]\\{,7\\}\\([>:|$B!S!d!U"d!'!C(B]\\|\\w+\\([._-]+\\w+\\)*>+\\)\\)+\\).*") + +;; mew-regex-url is defined in mew-vars.el. This duplication is intentional. +;; This definition includes full-width space characters. +(defvar mew-regex-url + (concat + "\\b\\(" + "\\(\\(file\\|news\\|mailto\\):\\)" + "\\|" + "\\(\\(s?https?\\|ftp\\|gopher\\|telnet\\|wais\\)://\\)" + "\\)" + "[^ $B!!(B\t\n>)\"]*" + "[^] $B!!(B\t\n>.,:)\"]+")) + +(provide 'mew-lang-jp) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-lang-jp.el ends here diff --git a/elpa/mew-20150813.2354/mew-lang-kr.el b/elpa/mew-20150813.2354/mew-lang-kr.el new file mode 100644 index 00000000..d7c3a35c --- /dev/null +++ b/elpa/mew-20150813.2354/mew-lang-kr.el @@ -0,0 +1,43 @@ +;;-*-coding:euc-kr;-*- +;;; mew-lang-kr.el --- Korean specific stuff for Mew + +;; Author: CHOI Junho +;; Created: Mar 31, 2003 + +;;; Code: + +(defvar mew-thread-indent-strings ["¦§" "¦¦" "¦¢" "¡¡"]) + +(provide 'mew-lang-kr) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-lang-kr.el ends here diff --git a/elpa/mew-20150813.2354/mew-lang-latin.el b/elpa/mew-20150813.2354/mew-lang-latin.el new file mode 100644 index 00000000..233ef996 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-lang-latin.el @@ -0,0 +1,88 @@ +;;; mew-lang-latin.el --- Latin specific stuff for Mew + +;; Author: Kazu Yamamoto +;; Created: Dec 11, 2002 + +;;; Code: + +(require 'mew) + +(defvar mew-latin01-list '(36 38 40 52 56 60 61 62)) + +(defvar mew-charset-latin-alist + '(("iso-8859-1" latin-iso8859-1 latin-iso8859-15) + ("iso-8859-15" latin-iso8859-15 latin-iso8859-1))) + +(defun mew-latin-make-regex (lc lst) + (mapconcat (lambda (x) (char-to-string (make-char lc x))) lst "\\|")) + +(defvar mew-latin0-regex + (mew-latin-make-regex 'latin-iso8859-15 mew-latin01-list)) + +(defvar mew-latin1-regex + (mew-latin-make-regex 'latin-iso8859-1 mew-latin01-list)) + +(defun mew-latin0-region (beg end) + (let* (charset ent to from ch lc conflict0 conflict1) + (save-restriction + (narrow-to-region beg end) + (setq conflict0 + (save-excursion + (goto-char (point-min)) + (re-search-forward mew-latin0-regex nil t))) + (setq conflict1 + (save-excursion + (goto-char (point-min)) + (re-search-forward mew-latin1-regex nil t))) + (unless (and conflict0 conflict1) ;; mew-charset-m17n + (cond + (conflict0 + (setq charset "iso-8859-15")) + (conflict1 + (setq charset "iso-8859-1")) + (t + (setq charset mew-charset-latin))) + (setq ent (assoc charset mew-charset-latin-alist)) + (mew-set '(nil to from) ent) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\\cl" nil t) + (setq ch (split-char (preceding-char))) + (setq lc (car ch)) + (when (eq lc from) + (delete-char -1) + (insert (make-char to (nth 1 ch)))))))))) + +(provide 'mew-lang-latin) + +;;; Copyright Notice: + +;; Copyright (C) 2002-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-lang-latin.el ends here diff --git a/elpa/mew-20150813.2354/mew-local.el b/elpa/mew-20150813.2354/mew-local.el new file mode 100644 index 00000000..7257b31d --- /dev/null +++ b/elpa/mew-20150813.2354/mew-local.el @@ -0,0 +1,426 @@ +;;; mew-local.el + +;; Author: Kazu Yamamoto +;; Created: Dec 12, 2001 + +(defvar mew-local-folder-alist-file ".mew-folder-alist") +(defvar mew-local-folder-alist nil) +(defvar mew-local-folder-alist-time nil) + +(defvar mew-local-friend-folder-list-file ".mew-friend-folder-list") +(defvar mew-local-friend-folder-list nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Listing directories +;;; + +(defun mew-dir-list (dir) + (if (file-directory-p (expand-file-name dir)) + (funcall mew-dir-list-function dir) + ())) + +(defun mew-dir-list-with-link-count (dir) + "Collecting a directory list under DIR. +Subdirectories are expressed by a list. +This function uses two techniques for speed up. + +One is to gather candidates of directory by matching +'mew-regex-folder-candidate'. The default is +\"^[^.0-9]\\|^[0-9].*[^0-9]\". So, typical messages whose name is +numeric are not gathered. This makes it faster to check whether or not +each candidate is a directory in 'while' loop. + +The other is to see if the link count of a directory is 2. If so, the +directory does not have subdirectories. So, it is not necessary to +trace down. This technique can be used on UNIX variants." + (let* ((default-directory (expand-file-name dir default-directory)) + (dirent (directory-files "." nil mew-regex-folder-candidate)) ;; MUST sort + dirs ent subdirs) + (dolist (file dirent) + (setq ent (mew-file-chase-links file)) + (when (file-directory-p ent) + (setq dirs (cons file dirs)) + (when (and (mew-file-get-links ent) ;; necessary + (/= (mew-file-get-links ent) 2)) + (setq subdirs (mew-dir-list-with-link-count file)) + (if subdirs (setq dirs (cons subdirs dirs)))))) + (nreverse dirs))) + +(defun mew-dir-list-without-link-count (dir) + "Collecting a directory list under DIR. +Subdirectories are expressed by a list. +This function uses one technique for speed up. + +It is to gather candidates of directory by matching +'mew-regex-folder-candidate'. The default is +\"^[^.0-9]\\|^[0-9].*[^0-9]\". So, typical messages whose name is +numeric are not gathered. This makes it faster to check whether or not +each candidate is a directory in 'while' loop." + (let* ((default-directory (expand-file-name dir default-directory)) + (dirent (directory-files "." nil mew-regex-folder-candidate)) ;; MUST sort + dirs ent subdirs) + (dolist (file dirent) + (setq ent (mew-file-chase-links file)) + (when (file-directory-p ent) + (setq dirs (cons file dirs)) + (setq subdirs (mew-dir-list-without-link-count file)) + (if subdirs (setq dirs (cons subdirs dirs))))) + (nreverse dirs))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder list +;;; + +(defun mew-local-folder-entry (ent1 ent2 make-list) + (if make-list + ent1 + (mew-folder-func ent1 ent2))) + +(defun mew-local-folder-make-alist (dirs prefix &optional make-list) + (let (fldpfx dir ret ent) + (if (= (length prefix) 1) + (setq fldpfx prefix) + (setq fldpfx (file-name-as-directory prefix))) + (while dirs + (setq dir (car dirs)) + (setq dirs (cdr dirs)) + (setq ent (concat fldpfx dir)) + (cond + ((consp (car dirs)) ;; not listp because nil is a list. + (cond + ((or (equal mew-attach-folder ent) (equal mew-draft-folder ent)) + (setq ret (cons (mew-local-folder-entry ent nil make-list) ret)) + (setq dirs (cdr dirs))) ;; skip subfolder + (t + (setq ret (cons (mew-local-folder-entry (file-name-as-directory ent) dir make-list) ret)) + (setq ret (nconc (mew-local-folder-make-alist (car dirs) ent make-list) ret)) + (setq dirs (cdr dirs))))) + (t + (if (string-match mew-regex-ignore-folders ent) + (setq ret (cons (mew-local-folder-entry ent nil make-list) ret)) + (setq ret (cons (mew-local-folder-entry ent dir make-list) ret)))))) + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folders +;;; + +(defun mew-local-folder-clean-up () + (setq mew-local-folder-alist nil) + (setq mew-local-friend-folder-list nil)) + +(defun mew-local-folder-alist () + (let* ((file (expand-file-name mew-local-folder-alist-file mew-conf-path)) + (t1 (mew-file-get-time file)) + (t2 mew-local-folder-alist-time)) + (if (mew-compare-times t1 t2) + (mew-local-folder-load)) + mew-local-folder-alist)) + +(defun mew-local-friend-folder-list () + mew-local-friend-folder-list) + +(defun mew-local-folder-load () + (let ((file (expand-file-name mew-local-folder-alist-file mew-conf-path))) + (setq mew-local-folder-alist + (mew-lisp-load mew-local-folder-alist-file)) + (setq mew-local-folder-alist-time (mew-file-get-time file)) + (setq mew-local-friend-folder-list + (mew-lisp-load mew-local-friend-folder-list-file)))) + +(defun mew-local-folder-save () + (let ((file (expand-file-name mew-local-folder-alist-file mew-conf-path))) + (mew-lisp-save mew-local-folder-alist-file + mew-local-folder-alist) + (setq mew-local-folder-alist-time (mew-file-get-time file)) + (mew-lisp-save mew-local-friend-folder-list-file + mew-local-friend-folder-list))) + +(defun mew-local-folder-set (folders friends) + (setq mew-local-folder-alist folders) + (setq mew-local-friend-folder-list friends) + (mew-local-folder-save)) + +(defun mew-local-update (&optional interactivep) + "Update the list of local folders." + (interactive) + (unless interactivep + (add-hook 'kill-emacs-hook 'mew-folder-clean-up) + (mew-local-folder-load)) + ;; + (when (or interactivep (null mew-local-folder-alist)) + (message "Collecting local folders...") + (let* ((mail-dirs (mew-dir-list mew-mail-path)) + (from-dirs (mew-dir-list (mew-expand-folder mew-friend-folder))) + (folders (mew-local-folder-make-alist mail-dirs mew-folder-local)) + (friends (mew-local-folder-make-alist from-dirs mew-friend-folder t))) + (setq folders (nreverse folders)) + (setq friends (nreverse friends)) + (mew-local-folder-set folders friends)) + (message "Collecting local folders...done"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder sub function +;;; + +(defun mew-local-folder-insert (folder) + "Insert FOLDER to 'mew-local-folder-alist'. +Binary search is used for speed reasons." + (let (dir subdir) + (unless (string-match mew-regex-ignore-folders folder) + (setq dir (directory-file-name (mew-folder-string folder))) + ;; foo/bar -> foo/bar + ;; foo/bar/ -> foo/bar + (setq subdir (file-name-nondirectory dir)) + ;; foo/bar -> bar + ;; foo -> foo + ) + (mew-folder-insert folder mew-local-folder-alist subdir) + (if (and (string-match (concat "^" (regexp-quote mew-friend-folder)) folder) + (not (member folder mew-local-friend-folder-list))) + (setq mew-local-friend-folder-list + (cons folder mew-local-friend-folder-list))) + (mew-local-folder-save))) + +(defun mew-local-folder-delete (folder) + (mew-folder-delete folder mew-local-folder-alist) + (setq mew-local-friend-folder-list + (delete folder mew-local-friend-folder-list)) + (mew-local-folder-save)) + +(defun mew-local-folder-check (folder &optional ask) + (let ((absdir (mew-expand-folder folder))) + (if (file-directory-p absdir) + t + (if (or (not ask) + (y-or-n-p (format "%s does not exist. Create it? " folder))) + (progn + (mew-make-directory absdir) + ;; may be called by IMAP... + (if (mew-folder-localp folder) + (mew-local-folder-insert folder)) + folder) + nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Process name +;;; + +(defvar mew-local-info-list + '("directive" "buf" "bnm" "mdb" "flush" "rcnt" "rttl" "first" "case")) + +(mew-info-defun "mew-local-" mew-local-info-list) + +(defconst mew-local-info-prefix "mew-local-info-") + +(defun mew-local-info-name (bnm) + (format "%s<%s>" mew-local-info-prefix bnm)) + +(defun mew-local-buffer-name (folder) + (concat mew-buffer-prefix folder)) + +(defun mew-local-debug (label string) + (when (mew-debug 'ls) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Scan +;;; + +(defun mew-scan-mewl-folder (folder) + (mew-replace-character folder mew-sp ?\007)) + +(defun mew-scan-mewl-src (folder &optional range) + (setq folder (mew-scan-mewl-folder (mew-expand-folder2 folder))) + (if range + (list "-s" (format "%s %s" folder range)) + (list "-s" folder))) + +(defun mew-local-retrieve (directive &rest args) + ;; 'inc folder opts + ;; 'scan folder range + ;; 'vir opts func lra erase + (mew-summary-with-mewl + (let* ((process-connection-type mew-connection-type1) + (bnm (mew-summary-folder-name 'ext)) + (pnm (mew-local-info-name bnm)) + (buf (get-buffer-create (mew-local-buffer-name bnm))) + range pro opts) + (message "Scanning %s..." bnm) + (mew-sinfo-set-summary-form (mew-get-summary-form bnm)) + (mew-sinfo-set-summary-column (mew-get-summary-column bnm)) + (mew-sinfo-set-unread-mark nil) + (mew-sinfo-set-scan-id nil) + (mew-sinfo-set-scan-md5 nil) + (mew-info-clean-up pnm) + (mew-local-set-directive pnm directive) + (mew-local-set-bnm pnm bnm) + (mew-local-set-buf pnm buf) + (mew-local-set-case pnm mew-case) ;; xxx specfy to mew-local-retrieve? + (cond + ((eq directive 'inc) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)) + (mew-local-set-flush pnm (nth 1 args)) + (setq opts (append (nth 2 args) (mew-scan-mewl-src (nth 0 args))))) + ((eq directive 'scan) + (setq range (nth 1 args)) + (if (nth 2 args) + (progn + (mew-local-set-mdb pnm (mew-summary-mark-collect4)) + (mew-erase-buffer) + (setq mew-summary-buffer-raw nil) + (mew-summary-folder-cache-save)) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm))) + (setq opts (mew-scan-mewl-src (nth 0 args) range))) + ((eq directive 'vir) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)) + (setq opts (nth 0 args)) + (mew-vinfo-set-func (nth 1 args)) + (mew-vinfo-set-lra (nth 2 args)) + (unless (nth 3 args) (mew-erase-buffer)) + (mew-local-set-rttl pnm (nth 4 args)))) + (mew-sinfo-set-start-point (point)) ;; after erase-buffer + (mew-local-set-rcnt pnm 1) + (with-current-buffer buf + (mew-erase-buffer)) + (setq opts (append (list "-b" mew-mail-path + "-l" (number-to-string mew-scan-max-field-length) + "-c" (number-to-string mew-scan-max-body-length) + "-w" + "-x" mew-suffix + "-f" (mapconcat 'identity + (nthcdr 2 mew-scan-fields) + ",")) + opts)) + (setq pro (apply 'start-process pnm buf mew-prog-mewl opts)) + (mew-summary-lock pro "Scanning") + (mew-set-process-cs pro mew-cs-text-for-net mew-cs-text-for-write) + ;; text may be broken, so undecided is very dangerous! + (set-process-filter pro 'mew-local-filter) + (set-process-sentinel pro 'mew-local-sentinel) + (mew-process-silent-exit pro)))) + +(defun mew-local-filter (process string) + (let* ((width (1- (mew-scan-width))) + (pnm (process-name process)) + (bnm (mew-local-get-bnm pnm)) + (first (mew-local-get-first pnm)) + (draftp (mew-folder-draftp bnm)) + (directive (mew-local-get-directive pnm)) + (case (mew-local-get-case pnm)) + vec rttl mark) + (mew-local-debug "FILTER" string) + (mew-filter + (mew-set-buffer-multibyte nil) + (goto-char (point-max)) + (mew-elet (insert string)) + (goto-char (point-max)) + (forward-line -1) + (when (looking-at "^\\.$") + (mew-dot-delete) + (goto-char (point-min)) + (unless first + (when (looking-at "NumOfMsg: \\([0-9]+\\)") + (setq rttl (string-to-number (match-string 1))) + (mew-local-set-rttl pnm rttl) + (forward-line) + (delete-region (point-min) (point))) + (mew-local-set-first pnm t)) + (mew-net-status3 bnm (mew-local-get-rttl pnm) (mew-local-get-rcnt pnm)) + (mew-local-set-rcnt pnm (1+ (mew-local-get-rcnt pnm))) + (mew-set-buffer-multibyte t) + (setq vec (mew-scan-header draftp)) + (if (eq directive 'inc) (setq mark (mew-scan-inbox-action vec case))) + (mew-scan-body vec draftp) + (mew-scan-insert-line bnm vec width nil mark) + (delete-region (point-min) (point-max)) + (process-send-string process "\n"))))) + +(defun mew-local-sentinel (process event) + (let* ((pnm (process-name process)) + (bnm (mew-local-get-bnm pnm)) + (buf (mew-local-get-buf pnm)) + (virtualp (mew-folder-virtualp bnm)) + (mdb (mew-local-get-mdb pnm)) + (flush (mew-local-get-flush pnm))) + (save-excursion + (mew-local-debug "SENTINEL" event) + (mew-filter + (mew-set-buffer-multibyte t) + (set-buffer bnm) + (mew-summary-mark-recover mdb) + (if (and virtualp (mew-vinfo-get-func)) + (funcall (mew-vinfo-get-func))) + (mew-vinfo-set-func nil) + (mew-info-clean-up pnm) + (if virtualp + (progn + (mew-summary-set-count-line) + (mew-virtual-set-cache-time)) + (mew-summary-folder-cache-save)) + (set-buffer-modified-p nil) + (mew-summary-unlock) + (if (and (mew-folder-imapp bnm) + (not (mew-folder-imap-queuep))) + (if (mew-local-get-rttl pnm) + (message "Type '\\[mew-summary-ls]' to override invalid messages") + ;; This folder has been just created. + ;; Ideally scan should not be called. But there is no way + ;; to avoid the call. + (message "")) + (message "Scanning %s...done" bnm)) + (run-hooks 'mew-scan-sentinel-hook) + (when (and mew-auto-flush-queue flush) + (mew-smtp-flush-queue mew-case)) + (mew-remove-buffer buf))))) + +(defun mew-virtual-set-cache-time () + (let* ((ctime (current-time)) + (cache-time (list (nth 0 ctime) (nth 1 ctime)))) + (mew-sinfo-set-cache-time cache-time))) + +;;; Code: + +(require 'mew) + +(provide 'mew-local) + +;;; Copyright Notice: + +;; Copyright (C) 2001-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-local.el ends here diff --git a/elpa/mew-20150813.2354/mew-mark.el b/elpa/mew-20150813.2354/mew-mark.el new file mode 100644 index 00000000..477fa6e1 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-mark.el @@ -0,0 +1,931 @@ +;;; mew-mark.el --- Marking for Mew Summary and Virtual mode + +;; Author: Kazu Yamamoto +;; Created: Mar 2, 1997 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; undo-func +;;; + +(defun mew-mark-unrefile (fld msg) + "Delete refile state and delete the mark." + (mew-summary-refile-remove-body) + (unless (mew-virtual-p) + (mew-refile-reset msg) + (mew-summary-refile-unlog fld))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Undo +;;; + +(defun mew-mark-unmark () + (save-excursion + (mew-summary-goto-mark) + (when (looking-at mew-regex-mark) + (mew-mark-remove)))) + +(defun mew-summary-undo (&optional count) + "Cancel the mark in COUNT times." + (interactive "P") + (mew-mark-put-mark-loop 'mew-summary-undo-one count 'stayp)) + +(defun mew-summary-undo-one (&optional no-msg) + "Cancel the mark on this message." + (if (eobp) + (or no-msg (message "No message")) + (let (mark func fld msg) + (save-excursion + (mew-summary-goto-message) + (setq mark (mew-summary-get-mark)) + (if (null mark) + (or no-msg (message "No mark")) + (setq func (mew-markdb-func-undo mark)) + (or (fboundp func) (setq func nil)) + (setq fld (mew-summary-folder-name)) + (setq msg (mew-summary-message-number)) + (mew-mark-unmark) + (if func (funcall func fld msg)) + (if (mew-virtual-for-one-summary) + (mew-summary-unmark-in-physical fld msg func))))))) + +;; + +(defun mew-summary-undo-all () + "Cancel all marks according to what you input." + (interactive) + (let ((char (mew-input-mark))) + (if char (mew-mark-undo-mark char)))) + +(defun mew-mark-undo-mark (mark &optional no-msg virtual-only) + "Undo MARK on the entire buffer. +If optional argument NO-MSG is non-nil, no message is displayed." + (or no-msg (message "Unmarking...")) + (mew-decode-syntax-delete) + (let* ((regex (mew-mark-regex mark)) + (func (mew-markdb-func-undo mark)) + (case-fold-search nil) + (reviewp (char-equal mark mew-mark-review)) + (one-summary (and (not virtual-only) (mew-virtual-for-one-summary))) + alist fld msg reviews) + (or (fboundp func) (setq func nil)) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (setq fld (mew-summary-folder-name)) + (setq msg (mew-summary-message-number)) + (mew-mark-remove) + (if one-summary (mew-mark-alist-set alist fld msg)) + (when reviewp (setq reviews (cons msg reviews))) + (if func (funcall func fld msg)) + (forward-line)) + (set-buffer-modified-p nil) + (mew-sinfo-set-mark-review (nreverse reviews)) + (if one-summary (mew-summary-unmark-in-physical-alist alist func)))) + (or no-msg (message "Unmarking...done"))) + +;; + +(defun mew-summary-mark-undo-all () + "Unmark all message marked with 'o' or 'D' or 'X'." + (interactive) + (message "Unmarking...") + (dolist (mark mew-summary-mark-undo-marks) + (mew-mark-undo-mark mark 'no-msg)) + (message "Unmarking...done")) + +;; + +(defun mew-summary-redo () + "\\Recover the `*' marks which are canceled by the last `\\[mew-summary-undo-all]*'." + (interactive) + (let ((mark mew-mark-review) + (reviews (mew-sinfo-get-mark-review))) + (save-excursion + (mew-mark-undo-mark mark 'no-msg) + (goto-char (point-min)) + (dolist (msg reviews) + (when (re-search-forward (mew-regex-sumsyn-msg msg) nil t) + (mew-mark-put mark) + (forward-line)))) + (set-buffer-modified-p nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Basic functions and macros for mark +;;; + +(defun mew-summary-get-mark () + "Get a mark on the current message." + (save-excursion + (mew-summary-goto-mark) + (when (looking-at mew-regex-mark) + (mew-sumsyn-mark)))) ;; return char + +(defun mew-summary-markable () + (let ((mark (mew-summary-get-mark)) + (case-fold-search nil)) + (or (null mark) (char-equal mark mew-mark-unread)))) + +(defun mew-summary-mark-as (mark) + "Mark this message with MARK if possible." + (when (mew-summary-markable) + (mew-mark-put mark))) + +(defun mew-mark-put (mark) + (save-excursion + (mew-summary-goto-mark) + (let* ((beg (point)) (end (1+ beg))) + (mew-elet + ;; This code is awkward but for invisible. + (forward-char 1) + (insert-and-inherit (char-to-string mark)) ;; inherit highlight + (forward-char -2) + (delete-char 1) + (mew-front-nonsticky beg end) + (mew-highlight-mark-line mark)) + (mew-mark-hist-set (mew-summary-message-number) mark)))) + +(defun mew-mark-remove () + (save-excursion + (mew-summary-goto-mark) + (let* ((mark mew-mark-read) + (beg (point)) (end (1+ beg))) + (mew-elet + ;; This code is awkward but for invisible. + (forward-char 1) + (insert-and-inherit (char-to-string mark)) ;; inherit highlight + (forward-char -2) + (delete-char 1) + (mew-front-nonsticky beg end) + (mew-highlight-unmark-line)) + (mew-mark-hist-set (mew-summary-message-number) mark)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Entire buffer +;;; + +(defun mew-summary-mark-exist-p (mark-list) + "See if this Summary mode has one or more marked messages." + (let ((regex (mew-mark-list-regex mark-list))) + (save-excursion + (goto-char (point-min)) + (re-search-forward regex nil t)))) + +(defun mew-summary-mark-collect (mark &optional begin end) + "This function returns a list of message number." + (save-excursion + (let ((regex (mew-mark-regex mark)) + (msglist nil) + (case-fold-search nil)) + (goto-char (if begin begin (point-min))) + (while (re-search-forward regex end t) + (setq msglist (cons (mew-summary-message-number) msglist))) + (nreverse msglist)))) + +(defun mew-summary-mark-collect2 (mark) + "For Virtual mode, this function returns a list of +cons pairs of folder name and message number." + (save-excursion + (let ((regex (mew-mark-regex mark)) + (msglist nil) + (case-fold-search nil)) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (setq msglist (cons + (cons + (mew-summary-folder-name) + (mew-summary-message-number)) + msglist))) + (nreverse msglist)))) + +(defun mew-summary-mark-collect4 () + (save-excursion + (let (ret mrk msg) + (goto-char (point-min)) + (while (re-search-forward mew-regex-mark nil t) + (setq mrk (mew-sumsyn-mark)) + (setq msg (mew-summary-message-number)) + (setq ret (cons (list msg mrk) ret)) + (forward-line)) + (nreverse ret)))) + +(defun mew-summary-mark-collect5 () + (save-excursion + (let ((beg (mew-net-invalid-cache-start)) + ret mrk msg) + (when beg + (goto-char beg) + (while (re-search-forward mew-regex-mark nil t) + (setq mrk (mew-sumsyn-mark)) + (setq msg (mew-summary-message-number)) + (setq msg (number-to-string (string-to-number msg))) + (setq ret (cons (list msg mrk) ret)) + (forward-line)) + (nreverse ret))))) + +(defun mew-summary-mark-recover (mdb &optional refdb refs) + (let ((opos (point)) + (case-fold-search nil) + msg mrk new-ref ref-ent) + (goto-char (point-min)) + (dolist (ent mdb) + (mew-set '(msg mrk) ent) + (when (re-search-forward (mew-regex-sumsyn-msg msg) nil t) + (if (or (not (char-equal mrk mew-mark-refile)) (null refdb)) + (mew-mark-put mrk) + (when (setq ref-ent (assoc msg refdb)) + (mew-mark-put mrk) + (setq new-ref (cons ref-ent new-ref)))) + (forward-line))) + (dolist (ref refs) + (when (setq ref-ent (assoc ref refdb)) + (setq new-ref (cons ref-ent new-ref)))) + (goto-char opos) + (nreverse new-ref))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Base function +;;; + +(defun mew-mark-afterstep (mark case) + "Move the cursor after marking according to MARK's CASE. +See also mew-mark-afterstep-spec." + (let ((action (mew-markas-nth mark case))) + (cond + ((eq action 0) + ()) ;; stay + ((eq action 1) + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (cond + ((eq mew-summary-mark-direction 'up) + (forward-line -1)) + ((eq mew-summary-mark-direction 'down) + (forward-line)) + ((eq mew-summary-mark-direction 'next) + (if (eq (mew-sinfo-get-direction) 'up) + (forward-line -1) + (forward-line))))) + ((eq action 2) + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (beginning-of-line) + (mew-push-mark) + (let ((mew-inherit-after-marking t)) + (mew-summary-display-after mew-summary-mark-direction)))))) + +(mew-defstruct mark-hist msg mark) + +(defun mew-mark-hist-set (msg mark) + (let* ((hist (mew-sinfo-get-mark-hist)) + (ent (assoc msg hist)) + (num (string-to-number msg)) + curr prev) + (cond + (ent + (if mark (setcar (nthcdr 1 ent) mark))) + (t + (setq ent (mew-make-mark-hist :msg msg :mark mark)) + (setq curr hist) + (catch 'loop + (while curr + (if (> (string-to-number (nth 0 (car curr))) num) + (progn + (if (null prev) + (setq hist (cons ent hist)) + (setcdr prev (cons ent (cdr prev)))) + (throw 'loop nil))) + (setq prev curr) + (setq curr (cdr curr))) + (setq hist (nconc hist (list ent)))) + (mew-sinfo-set-mark-hist hist))))) + +(defun mew-mark-put-mark (newmark &optional no-msg valid-only) + "Put the NEWMARK on the current line if possible. +If NO-MSG is non-nil, no message is displayed. +NO-MSG also means that this function is being called in loop." + (mew-summary-msg-or-part + (let (oldmark oldlevel oldname newlevel newname case msg fld marked validp) + (save-excursion + (mew-summary-goto-message) + (when (mew-sumsyn-match mew-regex-sumsyn-short) + (setq msg (mew-sumsyn-message-number)) + (setq fld (mew-sumsyn-folder-name)) + (setq validp (or (not valid-only) (mew-msg-validp msg)))) + (if (not validp) + (unless no-msg (message "Cannot mark this invalid message with '%c'" newmark)) + (setq oldmark (mew-summary-get-mark)) + (setq oldlevel (mew-markdb-level oldmark)) + (setq oldname (mew-markdb-name oldmark)) + (setq newlevel (mew-markdb-level newmark)) + (setq newname (mew-markdb-name newmark)) + (cond + ((null oldmark);; no mark + (setq case 1) + (mew-mark-put newmark) + (setq marked t)) + ((eq oldmark newmark) + (setq case 2) + (or no-msg + (mew-markdb-statefullp oldmark) + (message "Already marked as '%s'" oldname))) + ((< oldlevel newlevel) + (setq case 3) + (mew-summary-undo-one no-msg) + (mew-mark-put newmark) + (setq marked t)) + ((= oldlevel newlevel) + (cond + ((mew-markdb-statefullp oldmark) + (if (or no-msg + (y-or-n-p (format "Already marked as '%s'. %s it? " + oldname (mew-capitalize newname)))) + (progn + (setq case 4) + (mew-summary-undo-one no-msg) + (mew-mark-put newmark) + (setq marked t)) + (setq case 5))) + (t + (setq case 6) + (mew-summary-undo-one no-msg) + (mew-mark-put newmark) + (setq marked t)))) + (t ;; > oldlevel newlevel + (setq case 7) + (message "Cannot mark here because '%s' is stronger than '%s'" + oldname newname))))) + (when validp + (if (and marked (mew-virtual-for-one-summary)) + (mew-summary-mark-in-physical fld msg newmark)) + (or no-msg (mew-mark-afterstep newmark case)) + (set-buffer-modified-p nil))))) + +(defun mew-mark-put-mark-loop (func count stayp) + "Unless COUNT is numeric, just call FUNC once. +The cursor moves forward. STAYP has no effect. +If COUNT is positive, call FUNC in COUNT times moving the cursor forward. +If COUNT is negative, call FUNC in COUNT times moving the cursor backward. +If COUNT is numeric and STAYP is non-nil, the cursor stays in the +original position." + (if (and (not (integerp count)) (mew-mark-active-p)) + (let ((begend (mew-summary-get-region))) + (goto-char (car begend)) + (setq stayp nil) + (setq count (count-lines (point) (cdr begend))) + (mew-mark-put-mark-loop1 func count stayp)) + (mew-mark-put-mark-loop1 func count stayp))) + +(defun mew-mark-put-mark-loop1 (func count stayp) + (when (and func (fboundp func)) + (mew-summary-msg-or-part + (if (integerp count) + (let ((start (point))) + (mew-decode-syntax-delete) + ;; positive loop + (while (and (> count 0) (not (eobp))) + (setq count (1- count)) + (funcall func 'no-msg) + (forward-line)) + ;; negative loop + (while (< count 0) + (if (bobp) + ;; need to call the func + (setq count 0) + (setq count (1+ count))) + (funcall func 'no-msg) + (forward-line -1)) + (and stayp (goto-char start))) + ;; just one + (funcall func)) + (set-buffer-modified-p nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Physical +;;; + +(defun mew-summary-mark-in-physical (fld msg new-mark) + (save-excursion + (when (get-buffer fld) + (set-buffer fld) + (save-excursion + (when (mew-summary-search-msg msg) + (mew-mark-put new-mark) + (set-buffer-modified-p nil)))))) + +(defun mew-summary-unmark-in-physical (fld msg &optional func) + (save-excursion + (when (get-buffer fld) + (set-buffer fld) + (save-excursion + (when (mew-summary-search-msg msg) + (mew-mark-remove) + (if func (funcall func fld msg)) + (set-buffer-modified-p nil)))))) + +(defmacro mew-mark-alist-set (alist fld msg) + `(let ((imsg (string-to-number ,msg)) + (fld-msgs (assoc ,fld ,alist))) + (if fld-msgs + (nconc fld-msgs (list imsg)) + (setq ,alist (cons (list ,fld imsg) ,alist))))) + +(defun mew-summary-mark-in-physical-alist (alist mark &optional func) + (save-excursion + (let (fld msg msgs) + (dolist (ent alist) + (setq fld (car ent)) + (setq msgs (sort (copy-sequence (cdr ent)) '<)) ;; sort has side effect + (when (get-buffer fld) + (set-buffer fld) + (save-excursion + (goto-char (point-min)) + (dolist (m msgs) + (setq msg (number-to-string m)) + (when (re-search-forward (mew-regex-sumsyn-msg msg) nil t) + (if func (funcall func)) + (mew-mark-put mark) + (forward-line))) + (set-buffer-modified-p nil))))))) + +(defun mew-summary-unmark-in-physical-alist (alist func) + (save-excursion + (let (fld msg msgs) + (dolist (ent alist) + (setq fld (car ent)) + (setq msgs (sort (copy-sequence (cdr ent)) '<)) ;; sort has side effect + (when (get-buffer fld) + (set-buffer fld) + (save-excursion + (goto-char (point-min)) + (dolist (m msgs) + (setq msg (number-to-string m)) + (when (re-search-forward (mew-regex-sumsyn-msg msg) nil t) + (mew-mark-remove) + (if func (funcall func fld msg)) + (forward-line))) + (set-buffer-modified-p nil))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Review: "*" in Summary mode +;;; + +(defun mew-summary-review (&optional count) + "\\ +Put the review mark (default is '*') in COUNT times. +Use '\\[mew-summary-display-review-down]' or '\\[mew-summary-display-review-up]' to jump to a message marked with '*'. +See also '\\[mew-summary-mark-refile]', '\\[mew-summary-mark-delete]', '\\[mew-summary-mark-regexp]', and '\\[mew-summary-mark-all]'." + (interactive "P") + (mew-mark-put-mark-loop 'mew-summary-review-one count nil)) + +(defun mew-summary-review-one (&optional no-msg) + "Put the review mark (default is '*') on this message." + (mew-mark-put-mark mew-mark-review no-msg)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Escape: "$" in Summary mode +;;; + +(defun mew-summary-escape (&optional count) + "\\ +Put the escape mark (default is '$') in COUNT times." + (interactive "P") + (mew-mark-put-mark-loop 'mew-summary-escape-one count nil)) + +(defun mew-summary-escape-one (&optional no-msg) + "Put the escape mark (default is '$') on this message." + (mew-mark-put-mark mew-mark-escape no-msg)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Delete: "D" in Summary mode +;;; + +(defun mew-summary-delete (&optional count) + "Put the delete mark (default is 'D') in COUNT times." + (interactive "P") + (mew-summary-not-in-nntp + (mew-mark-put-mark-loop 'mew-summary-delete-one count nil))) + +(defun mew-summary-delete-one (&optional no-msg) + "Put the delete mark (default is 'D') on this message." + (mew-mark-put-mark mew-mark-delete no-msg 'valid-only)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Unlink: "X" in Summary mode +;;; + +(defun mew-summary-unlink (&optional count) + "Put the unlink mark (default is 'X') in COUNT times." + (interactive "P") + (mew-summary-not-in-nntp + (mew-mark-put-mark-loop 'mew-summary-unlink-one count nil))) + +(defun mew-summary-unlink-one (&optional no-msg) + "Put the unlink mark (default is 'X') on this message." + (mew-mark-put-mark mew-mark-unlink no-msg 'valid-only)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Unread: "U" in Summary mode +;;; + +(defun mew-summary-unread (&optional count) + "\\ +Put the unread mark (default is 'U') in COUNT times." + (interactive "P") + (mew-mark-put-mark-loop 'mew-summary-unread-one count nil)) + +(defun mew-summary-unread-one (&optional no-msg) + "Put the unread mark (default is 'U') on this message." + (mew-mark-put-mark mew-mark-unread no-msg)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; All messages +;;; + +(defun mew-summary-mark-all (&optional arg) + "Put the '*' mark onto all messages which are not marked." + (interactive "P") + (mew-decode-syntax-delete) + (if (mew-mark-active-p) (setq arg t)) + (if arg + (let ((begend (mew-summary-get-region))) + (mew-summary-mark-all-region (car begend) (cdr begend))) + (mew-summary-mark-all-region (point-min) (point-max)))) + +(defun mew-summary-mark-all-region (beg end) + "Put the '*' mark onto all messages which are not marked between +BEG and END." + (interactive "r") + (let ((regex (mew-mark-regex mew-sp)) ;; not marked + (mark mew-mark-review) ;; someday ... + (one-summary (mew-virtual-for-one-summary)) + fld msg alist) + (save-excursion + (goto-char beg) + (while (re-search-forward regex end t) + (mew-summary-mark-as mark) + (when one-summary + (setq fld (mew-summary-folder-name)) + (setq msg (mew-summary-message-number)) + (mew-mark-alist-set alist fld msg)) + (forward-line)) + (set-buffer-modified-p nil)) + (if one-summary (mew-summary-mark-in-physical-alist alist mark)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Regex +;;; + +(defun mew-summary-search-regexp-visible (regex) + (catch 'loop + (while (re-search-forward regex nil t) + (beginning-of-line) + (unless (search-forward "\r" (match-end 0) t) + (throw 'loop t)) + (forward-line)))) + +(defun mew-summary-mark-regexp (&optional args) + "Put the '*' mark onto all messages matched to a regular expression." + (interactive "P") + (mew-decode-syntax-delete) + (let ((regex (read-string "Regexp: ")) + (mark mew-mark-review) ;; someday ... + (one-summary (mew-virtual-for-one-summary)) + (n 0) + fld msg alist) + (while (string= regex "") + (setq regex (read-string "Regexp: "))) + (save-excursion + (goto-char (point-min)) + (while (if args + (re-search-forward regex nil t) + (mew-summary-search-regexp-visible regex)) + (when (and (mew-summary-markable) + (mew-sumsyn-match mew-regex-sumsyn-short)) + (when one-summary + (setq fld (mew-sumsyn-folder-name)) + (setq msg (mew-sumsyn-message-number)) + (mew-mark-alist-set alist fld msg)) + (mew-mark-put mark) + (setq n (1+ n))) + (forward-line)) + (set-buffer-modified-p nil)) + (if one-summary (mew-summary-mark-in-physical-alist alist mark)) + (cond + ((= n 1) + (message "1 message marked")) + ((> n 1) + (message "%d messages marked" n)) + (t + (message "No message to be marked"))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Exchange +;;; + +(defun mew-summary-exchange-mark (oldmark newmark &optional valid-only) + (let ((regex (mew-mark-regex oldmark)) + (case-fold-search nil) + (one-summary (mew-virtual-for-one-summary)) + (i 0) + fld msg alist) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (when (mew-sumsyn-match mew-regex-sumsyn-short) + (setq fld (mew-sumsyn-folder-name)) + (setq msg (mew-sumsyn-message-number)) + (when (or (not valid-only) (mew-msg-validp msg)) + (mew-mark-put newmark) + (if one-summary (mew-mark-alist-set alist fld msg)))) + (forward-line) + (setq i (1+ i)))) + (if (= i 0) + (message "No marked messages") + (set-buffer-modified-p nil) + (if one-summary (mew-summary-mark-in-physical-alist alist newmark))))) + +(defun mew-summary-mark-delete () ;; * -> D + "Put the delete mark onto all messages marked with '*'." + (interactive) + (mew-summary-not-in-nntp + (mew-summary-exchange-mark mew-mark-review mew-mark-delete 'valid-only))) + +(defun mew-summary-mark-unlink () ;; * -> X + "Put the delete mark onto all messages marked with '*'." + (interactive) + (mew-summary-exchange-mark mew-mark-review mew-mark-unlink 'valid-only)) + +(defun mew-summary-mark-escape () ;; * -> $ + "Change the '*' mark into the '$' mark." + (interactive) + (mew-summary-exchange-mark mew-mark-review mew-mark-escape)) + +(defun mew-summary-mark-review () ;; $ -> * + "Change the '$' mark into the '*' mark." + (interactive) + (mew-summary-exchange-mark mew-mark-escape mew-mark-review)) + +(defun mew-summary-mark-unread () ;; * -> U + "Change the '*' mark into the 'U' mark." + (interactive) + (mew-summary-exchange-mark mew-mark-review mew-mark-unread)) + +(defun mew-summary-mark-swap () ;; $ <-> * + "Swap the '$' mark and the '*' mark." + (interactive) + (mew-summary-exchange-mark mew-mark-escape mew-mark-tmp) + (mew-summary-exchange-mark mew-mark-review mew-mark-escape) + (mew-summary-exchange-mark mew-mark-tmp mew-mark-review)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Marking duplicated messages +;;; + +(defun mew-summary-mark-duplicated (&optional arg) + "Put the mark specified by 'mew-mark-duplicated' on duplicated +messages. If called with '\\[universal-argument]', process in the +region." + (interactive "P") + (mew-summary-not-in-queue + (mew-summary-not-in-draft + (if (and (or (eq mew-mark-duplicated mew-mark-delete) + (eq mew-mark-duplicated mew-mark-unlink)) + (eq mew-summary-mark-duplicated-skip nil)) + (message "Cannot mark because messages may lost by this setting") + (let ((reversep (eq mew-summary-mark-duplicated-skip 'last)) + (count 0) my-id dup-id size ids beg end region) + (if (mew-mark-active-p) (setq arg t)) + (cond + (arg + (setq region (mew-summary-get-region)) + (setq beg (car region)) + (setq end (cdr region))) + (t + (setq beg (point-min)) + (setq end (point-max)))) + (message "Marking duplications...") + (save-excursion + ;; from mew-summary-thread-region in mew-threaed.el + (setq size (count-lines beg end)) + (cond + ((<= size 211) + (setq size 211)) + ((<= size 1511) + (setq size 1511)) + ((<= size 7211) + (setq size 7211)) + (t + (setq size 18211))) + (setq ids (make-vector size 0)) ;; hash + (save-restriction + (narrow-to-region beg end) + (goto-char (if reversep (point-max) (point-min))) + (catch 'loop + (while t + (when (and (mew-summary-message-number) + (mew-summary-markable)) + (setq my-id (mew-summary-my-id)) + (when (> (length my-id) 0) + (setq dup-id (intern-soft my-id ids)) + (if (null dup-id) + ;; first time (no duplication) + (set (intern my-id ids) t) + (when (symbol-value dup-id) + ;; second time (first duplication) + (unless mew-summary-mark-duplicated-skip + (save-excursion + (when (re-search-backward + (mew-regex-sumsyn-my-id my-id) nil t) + (mew-mark-put-mark mew-mark-duplicated 'no-msg) + (setq count (1+ count)))) + (set (intern my-id ids) nil))) + (mew-mark-put-mark mew-mark-duplicated 'no-msg) + (setq count (1+ count))))) + (cond + (reversep + (beginning-of-line) + (if (bobp) + (throw 'loop t) + (forward-line -1))) + (t + (forward-line 1) + (if (eobp) + (throw 'loop t)))))))) + (cond + ((= count 0) + (message "Marking duplications...done (no duplication)")) + ((= count 1) + (message "Marking duplications...done (1 msg is marked)")) + (t + (message "Marking duplications...done (%d msgs are marked)" count)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Reviewing +;;; + +(defun mew-summary-set-walk-mark () + (let* ((msg (format "Input mark(%c): " mew-mark-default-walk)) + (mew-mark-spec (cons (list 13) mew-mark-spec)) ;; adding \r + (char (mew-input-mark msg))) + (cond + ((null char) + ;; mew-input-mark displays a message. + ) + ((char-equal char ?\r) + (setq mew-mark-walk mew-mark-default-walk) + (message "Target mark was set to '%c'" mew-mark-walk)) + (char + (setq mew-mark-walk char) + (message "Target mark was set to '%c'" mew-mark-walk))))) + +(defun mew-summary-down-mark (mark) + (let ((case-fold-search nil)) + (forward-line) + (cond + ((re-search-forward (mew-mark-regex mark) nil t) + (beginning-of-line) + t) + (t + (forward-line -1) + (message "No more marked messages") + nil)))) + +(defun mew-summary-display-review-down (&optional arg) + "Jump to the message marked with '*' below. +If called with '\\[universal-argument]', you can change the target mark. +After that, this command jumps to the message marked with +the specified mark." + (interactive "P") + (if arg + (mew-summary-set-walk-mark) + (if (mew-summary-down-mark mew-mark-walk) + (mew-summary-display)))) + +(defun mew-summary-up-mark (mark) + (let ((case-fold-search nil)) + (cond + ((re-search-backward (mew-mark-regex mark) nil t) + t) + (t + (message "No more marked messages") + nil)))) + +(defun mew-summary-display-review-up (&optional arg) + "Jump to the message marked with '*' above. +If called with '\\[universal-argument]', you can change the target mark. +After that, this command jumps to the message marked with +the specified mark." + (interactive "P") + (if arg + (mew-summary-set-walk-mark) + (if (mew-summary-up-mark mew-mark-walk) + (mew-summary-display)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mark exchange +;;; + +(defun mew-summary-input-exchangeable-mark (msg) + (let (mark) + (catch 'loop + (while t + (setq mark (mew-input-mark msg)) + (cond + ((null mark) + (message "That is not a mark") + (mew-let-user-read)) + ((mew-markdb-statefullp mark) + (message "'%c' cannot be exchanged" mark) + (mew-let-user-read)) + (t + (throw 'loop mark))))))) + +(defun mew-summary-exchange-marks () + "Exchange the first input mark to the second one. +The 'o' mark is not exchangeable." + (interactive) + (let* ((from (mew-summary-input-exchangeable-mark "Input mark from: ")) + (to (mew-summary-input-exchangeable-mark "Input mark to: ")) + (regex (mew-mark-regex from)) + (case-fold-search nil)) + (unless (char-equal from to) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (mew-summary-undo-one 'nomsg) + (mew-mark-put-mark to 'nomsg)) + (forward-line))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Clean up marks! +;;; + +(defun mew-mark-init () + (add-hook 'kill-emacs-hook 'mew-sinfo-clean-up)) + +(defun mew-sinfo-clean-up () + "Saving marks. Typically called by kill-emacs-hook." + (remove-hook 'kill-emacs-hook 'mew-sinfo-clean-up) + (mew-decode-syntax-delete) + (save-excursion + (dolist (buf mew-buffers) + (when (bufferp (get-buffer buf)) + (set-buffer buf) + (when (mew-summary-p) + (mew-sinfo-save)))))) + +(provide 'mew-mark) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-mark.el ends here diff --git a/elpa/mew-20150813.2354/mew-message.el b/elpa/mew-20150813.2354/mew-message.el new file mode 100644 index 00000000..91c5b35d --- /dev/null +++ b/elpa/mew-20150813.2354/mew-message.el @@ -0,0 +1,341 @@ +;;; mew-message.el --- Message mode for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message info +;;; + +(defvar mew-minfo-list '("summary" "eom" "veil-to" "veil-cc" "reob")) + +(mew-blinfo-defun 'mew-minfo mew-minfo-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message mode +;;; + +(defun mew-message-mode () + "A major mode for display a message. + +\\{mew-message-mode-map}" + (interactive) + (setq major-mode 'mew-message-mode) + (setq mode-name mew-mode-name-message) + (setq mode-line-buffer-identification (mew-mode-line-id)) + (use-local-map mew-message-mode-map) + (setq buffer-read-only t) + (make-local-variable 'page-delimiter) + (setq page-delimiter mew-page-delimiter) + (mew-message-setup-decoration) + (mew-message-toolbar-update) + (mew-run-mode-hooks 'mew-message-mode-hook)) + +(defun mew-message-mode-line (fld message) + (let* ((msg (or message + (mew-current-get-msg (mew-frame-id)))) + (status (mew-message-line-status)) + (flag (nth status '("N" "W" "L")))) + (when msg + (setq mode-line-process (format " %s %s/%s" flag fld msg))))) + +(defun mew-message-next-page (&optional lines) + "Scroll up this message. Return 'nil' if more pages. Otherwise, return 't'." + (interactive) + (if (save-excursion + (goto-char (window-end)) + (and (pos-visible-in-window-p) (eobp))) + ;; Nothing in this page. + (if (or (null mew-break-pages) + (save-excursion + (goto-char (window-end)) + (save-restriction + (widen) (forward-line) (eobp)))) ;; Real end of buffer? + (if mew-summary-show-pause + (prog1 + (mew-minfo-get-reob) + (unless (mew-minfo-get-reob) + (message "End of buffer") + (mew-minfo-set-reob t))) + t) + ;; Go to the next page. + (mew-message-narrow-to-page 1) + nil) + ;; More in this page. + (condition-case nil + (scroll-up lines) + (end-of-buffer + (goto-char (point-max)) + (message "End of buffer"))) + nil)) + +(defun mew-message-prev-page (&optional lines) + "Back-scroll this message. Return 'nil' if more pages. +Otherwise, return 't'." + (interactive) + (move-to-window-line 0) + (if (save-excursion + (beginning-of-line) + (and (pos-visible-in-window-p) (bobp))) + ;; Nothing in this page. + (if (or (null mew-break-pages) + (save-restriction + (widen) (bobp))) ;; Real beginning of buffer? + t + ;; Go to the previous page. + (mew-message-narrow-to-page -1) + nil) + ;; More in this page. + (condition-case nil + (scroll-down lines) + (beginning-of-buffer + (goto-char (point-min)) + (message "Beginning of buffer"))) + nil)) + +(defun mew-message-narrow-to-page (&optional arg) + (setq arg (if arg (prefix-numeric-value arg) 0)) + (save-excursion + (condition-case nil + (forward-page -1) ;; Beginning of the current page. + (beginning-of-buffer ())) + (widen) + (cond + ((> arg 0) (forward-page arg)) + ((< arg 0) (forward-page (1- arg)))) + (forward-page) + (let* ((end (point))) + (forward-page -1) + (if (and (eolp) (not (bobp))) + (forward-line)) + (narrow-to-region (point) end)))) + +(defun mew-message-goto-summary () + "Get back to Summary mode." + (interactive) + (let* ((fld (mew-minfo-get-summary)) + (fid (mew-frame-id)) + (msg (mew-current-get-msg fid)) + (part (mew-current-get-part fid))) + (if (not (get-buffer fld)) + (message "No Summary mode for %s" fld) + (if (get-buffer-window fld) + (select-window (get-buffer-window fld)) + (mew-summary-switch-to-folder fld)) + (cond + ((and msg part (mew-decode-syntax-p)) + (setq part (concat "^.. +" + (regexp-quote (mapconcat 'number-to-string part ".")) + " ")) + (goto-char (mew-decode-syntax-begin)) + (re-search-forward part (mew-decode-syntax-end) t) + (beginning-of-line) + (mew-summary-display)) + (msg + (mew-summary-move-and-display msg)))))) + +(defun mew-message-reply () + "Answer to this message. A new draft is prepared in Draft mode. +Mew automatically decides To: and Cc:." + (interactive) + (mew-message-goto-summary) + (call-interactively 'mew-summary-reply)) + +(defun mew-message-reply-with-citation () + "Answer to this message. A new draft is prepared in Draft mode. +Mew automatically decides To: and Cc: and cites the body." + (interactive) + (mew-message-goto-summary) + (call-interactively 'mew-summary-reply-with-citation)) + +(defun mew-message-forward () + "Forward this message to a third person. A new draft is prepared in +Draft mode and this message is automatically attached." + (interactive) + (mew-message-goto-summary) + (call-interactively 'mew-summary-forward)) + +(defun mew-message-resend () + "\\ +Resend this message with Resent-To:. It is strongly +discouraged to use this command since beginners are always +confused. Please use '\\[mew-message-forward]' instead." + (interactive) + (mew-message-goto-summary) + (call-interactively 'mew-summary-resend)) + +(defun mew-message-next-msg (&optional arg) + "Display a message or a part below." + (interactive "p") + (let* ((swin (previous-window)) + (mbuf (current-buffer))) + (select-window swin) ;; for the next forward-line + (when (mew-summary-or-virtual-p) + (forward-line arg) ;; minus arg results in prev + (mew-summary-display)) + ;; for window config + (select-window (get-buffer-window mbuf)))) + +(defun mew-message-prev-msg (&optional arg) + "Display a message or a part above." + (interactive "p") + (mew-message-next-msg (- arg))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; URLs +;;; + +(defun mew-message-goto-next-url (&optional arg) + (interactive "P") + (let ((next (if arg + 'previous-single-property-change + 'next-single-property-change)) + pos) + (setq pos (funcall next (point) 'mew-url)) + (if pos + (if (not (get-text-property pos 'mew-url)) + (setq pos (funcall next pos 'mew-url)))) + (when pos + (goto-char pos)))) + +(defun mew-browse-url-at-mouse (event) + (interactive "e") + (let ((buf (current-buffer)) url) + (mouse-set-point event) + (setq url (or (get-text-property (point) 'mew-url) + (get-text-property (point) 'w3m-href-anchor) + (get-text-property (point) 'shr-url))) + (if (and url (string-match mew-regex-nonascii url)) + (setq url (mew-puny-encode-url url))) + (if url (browse-url url)) + (pop-to-buffer buf))) + +(defun mew-browse-url-at-point () + (interactive) + (let (url) + (setq url (or (get-text-property (point) 'mew-url) + (get-text-property (point) 'w3m-href-anchor) + (get-text-property (point) 'shr-url))) + (if (and url (string-match mew-regex-nonascii url)) + (setq url (mew-puny-encode-url url))) + (if url (browse-url url)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; lines +;;; + +(defun mew-message-line-status () + (cond + ((not (eq buffer-undo-list t)) 1) ;; wrapped + (truncate-lines 2) ;; long + (t 0))) ;; normal + +(defun mew-message-line () + "Toggle normal lines, wrapped lines and long lines." + (interactive) + (let* ((N 3) + (status (% (1+ (mew-message-line-status)) N))) + (mew-elet + (cond + ((= status 0) + (setq truncate-lines nil) + (message "Normal lines")) + ((= status 1) + (setq buffer-undo-list nil) + (mew-wrap-lines (if (mew-header-end) (1+ (mew-header-end)) (point-min)) (point-max)) + (message "Wrapped lines")) + ((= status 2) + (save-excursion + (primitive-undo (length buffer-undo-list) buffer-undo-list)) + (buffer-disable-undo) + (setq truncate-lines t) + (message "Long lines"))) + (set-window-hscroll (selected-window) 0) + (set-buffer-modified-p nil)))) + +(defun mew-normal-line () + (setq truncate-lines nil)) + +(defcustom mew-wrap-lines-column fill-column + "*Number of fill column to wrap line." + :group 'mew-message + :type 'integer) + +(defun mew-wrap-lines (beg end) + (save-restriction + (narrow-to-region beg end) + (save-excursion + (goto-char (point-min)) + (let ((adaptive-fill-mode nil) + (winwidth (- (window-width) 2)) + (fill-column mew-wrap-lines-column) + width start fill-prefix) + (while (not (eobp)) + (setq start (point)) + (setq fill-prefix (mew-fill-match-adaptive-prefix)) + (end-of-line) + (setq width (current-column)) + (forward-line) + (if fill-prefix + (setq fill-column (+ mew-wrap-lines-column (string-width fill-prefix))) + (setq fill-column mew-wrap-lines-column)) + (setq fill-column (min fill-column winwidth)) + (when (> width fill-column) + (fill-region-as-paragraph start (1- (point))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Horizontal Scrolling +;;; + +(defun mew-message-scroll-left () + "Scroll the Message window to the right." + (interactive) + (call-interactively 'scroll-left)) + +(defun mew-message-scroll-right () + "Scroll the Message window to the left." + (interactive) + (call-interactively 'scroll-right)) + +(provide 'mew-message) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-message.el ends here diff --git a/elpa/mew-20150813.2354/mew-mime.el b/elpa/mew-20150813.2354/mew-mime.el new file mode 100644 index 00000000..3d4495f5 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-mime.el @@ -0,0 +1,989 @@ +;;; mew-mime.el --- MIME launcher for Mew + +;; Author: Kazu Yamamoto +;; Created: Mar 23, 1997 + +;;; Code: + +(require 'mew) +(eval-when-compile + (cond + ((memq system-type '(windows-nt cygwin)) + (require 'mew-win32)) + ((eq system-type 'darwin) + (require 'mew-darwin)) + (t + (require 'mew-unix))) + (mew-no-warning-defun w3m-region) + (mew-no-warning-defun w3m-expand-file-name-as-url)) + +(defvar mew-process-file-alist nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Configuration subroutines +;;; + +(defun mew-progspec-get-prog (def) + (cond + ((stringp def) def) + ((and (listp def) (stringp (car def))) (car def)))) + +(defun mew-progspec-get-args (def) + (if (listp def) (nth 1 def))) + +(defun mew-progspec-get-async (def) + (cond + ((stringp def) t) + ((listp def) (nth 2 def)))) + +(defun mew-progsec-args-convert (args arg) + (let (converted ret) + (setq ret (mapcar (lambda (x) + (if (not (string-match "%s" x)) + x + (setq converted t) + (format x arg))) + args)) + (unless converted (setq ret (append ret (list arg)))) + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Start and call process +;;; + +(defun mew-mime-start-process (program options file) + (let ((process-connection-type mew-connection-type1) pro) + (message "Starting %s..." program) + (setq pro (apply 'mew-start-process-disp + (format "*mew %s*" program) + nil + program + (append options (list file)))) + (set-process-sentinel pro 'mew-mime-start-process-sentinel) + (message "Starting %s...done" program) + (setq mew-process-file-alist (cons (cons pro file) mew-process-file-alist)) + t)) ;; to next part + +(defun mew-mime-start-process-sentinel (process event) + (let* ((al (assoc process mew-process-file-alist)) + (file (cdr al))) + (save-excursion + ;; A launcher program may be executed. + ;; The launcher program executes an application according to + ;; file's suffix or something. + ;; The time when the launcher is finished is not the time when + ;; the application is finished. So, we can't delete the temporary + ;; file here. Hoping that the file will be deleted when Mew is + ;; finished. + (if mew-delete-temp-file (mew-delete-file file)) + (setq mew-process-file-alist (delq al mew-process-file-alist))))) + +(defun mew-mime-call-process (program options file) + (message "Calling %s..." program) + (apply 'call-process program file nil nil options) + (mew-delete-file file) + (message "Calling %s...done" program) + t) ;; to next part + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Part handler +;;; + +;; see also mew-summary-execute-external(). + +(defun mew-mime-part (cache fullpart nums) + ;; called in Message buffer + ;; if nums is nil, it means singlepart. + (let* ((syntax (mew-syntax-get-entry fullpart nums)) + (begin (mew-syntax-get-begin syntax)) + (end (mew-syntax-get-end syntax)) + (ctl (mew-syntax-get-ct syntax)) + (cte (mew-syntax-get-cte syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (cdpl (mew-syntax-get-cdp syntax)) + (fname (mew-syntax-get-filename cdpl ctl)) + (cd (mew-syntax-get-cd syntax)) + (params (mew-syntax-get-params ctl)) + (program (mew-ctdb-prog (mew-ctdb-by-ct ct))) + func2) + (when (listp program) + (setq func2 (nth 1 program)) + (setq program (nth 0 program))) + (cond + ((null program) + (mew-mime-function func2 cache begin end ct cte cd fname)) + ((symbolp program) + (when (fboundp program) + (cond + ((eq program 'mew-mime-message/rfc822) + (funcall program cache syntax)) ;; for recursive MIME + ((eq program 'mew-mime-application/octet-stream) + (funcall program cache begin end params ct cte cd fname)) + ((mew-ct-imagep ct) + (funcall program cache begin end params fname ct cte)) + (t + (funcall program cache begin end params))))) + (t ;; string + (insert " ###### ###### ####### ##### ###### # # #\n" + " # # # # # # # # # # # # ## ##\n" + " # # # # # # # # # # # # # # #\n" + " ###### ###### # # # #### ###### # # # # #\n" + " # # # # # # # # # ####### # #\n" + " # # # # # # # # # # # # #\n" + " # # # ####### ##### # # # # # #\n" + "\n\n") + (mew-insert "Content-Type:\t%s\n" ct) + (mew-insert "Encoding:\t%s\n" cte) + (mew-insert "Size:\t\t%d bytes\n" (mew-region-bytes begin end cache)) + (mew-insert "Filename:\t%s\n" fname) + (mew-insert "Description:\t%s\n" cd) + (mew-insert "Program:\t%s\n" program) + (insert "\n") + (mew-mime-part-messages t))))) + +(defun mew-mime-function (func cache begin end &optional ct cte cd fname) + (insert " ####### # # # # ##### ####### ### ####### # #\n" + " # # # ## # # # # # # # ## #\n" + " # # # # # # # # # # # # # #\n" + " ##### # # # # # # # # # # # # #\n" + " # # # # # # # # # # # # # #\n" + " # # # # ## # # # # # # # ##\n" + " # ##### # # ##### # ### ####### # #\n" + "\n\n") + (mew-insert "Content-Type:\t%s\n" ct) + (mew-insert "Encoding:\t%s\n" cte) + (mew-insert "Size:\t\t%d bytes\n" (mew-region-bytes begin end cache)) + (mew-insert "Filename:\t%s\n" fname) + (mew-insert "Description:\t%s\n" cd) + (mew-insert "Function:\t%s\n" func) + (insert "\n") + (mew-mime-part-messages func)) + +(defun mew-mime-part-messages (prog) + (cond + ((and prog (fboundp prog)) + (mew-insert-manual + "To execute an external function, type " + "'\\\\[mew-summary-execute-external]'.\n" + "\n")) + (prog + (mew-insert-manual + "To execute an external command, type " + "'\\\\[mew-summary-execute-external]'.\n" + "\n"))) + (mew-insert-manual + "To save this part, type " + "'\\\\[mew-summary-save]'.\n" + "To insert this part in Message mode, type " + "'\\\\[mew-summary-display-asis]'.\n")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Text/Plain +;;; + +(defvar mew-flowed-auto-wrap t) + +(defun mew-mime-text/plain (cache begin end &optional params) + ;; called in Message buffer + (when (> end begin) + (save-excursion + ;; We need to keep properties (e.g. citation color) + ;; in a message cache. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring cache begin end) + (when mew-insert-final-newline + (save-excursion + (goto-char (point-max)) + (if (not (bolp)) (insert "\n")))) + (if (and mew-flowed-auto-wrap + (mew-syntax-get-param params "format") + (string= (downcase (mew-syntax-get-param params "format")) + "flowed")) + (mew-message-line)) + ;; Page breaks + (when mew-break-pages + (goto-char (point-min)) + (mew-message-narrow-to-page))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Text/Enriched +;;; + +(defun mew-mime-text/enriched (cache begin end &optional params) + ;; called in Message buffer + (when (> end begin) + (save-excursion + (let ((start (point))) + ;; We need to keep composite properties of charset. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring cache begin end) + ;; Highlight + (when mew-use-text/enriched + (condition-case nil + ;; format.el is buggy. + (format-decode-region start (point-max) 'text/enriched) + (args-out-of-range (message nil))) ;; just clear + (enriched-mode 0))) + ;; Page breaks + (when mew-break-pages + (goto-char (point-min)) + (mew-message-narrow-to-page))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Text/Html +;;; + +(defun mew-mime-text/html (cache begin end &optional params) + ;; called in Message buffer + (if (and (symbolp mew-prog-text/html) (fboundp mew-prog-text/html)) + (save-excursion + (let ((start (point)) + folder) + ;; We need to keep composite properties of charset. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring cache begin end) + (with-current-buffer cache + (setq folder (mew-cinfo-get-fld))) + (if (or mew-use-text/html + (and mew-use-text/html-list + (mew-folder-spec folder + mew-use-text/html-list + mew-use-text/html-string-type + mew-use-text/html-list-type))) + (progn + (funcall mew-prog-text/html start (point-max)) + (delete-trailing-whitespace start (point-max)) + (mew-highlight-body-region start (point-max))) + (mew-message-for-summary "To parse HTML, type '\\[mew-summary-analyze-again]'")))) + (insert " # # ####### # # #\n" + " # # # ## ## #\n" + " # # # # # # # #\n" + " ####### # # # # #\n" + " # # # # # #\n" + " # # # # # #\n" + " # # # # # #######\n" + "\n\n") + (mew-insert "Size:\t\t%d bytes\n" (mew-region-bytes begin end cache)) + (mew-insert "Browser:\t%s\n" (or (mew-progspec-get-prog mew-prog-text/html-ext) "none")) + (insert "\n") + (mew-mime-part-messages t))) + +(defun mew-text/html-detect-cs (begin end) + (let ((case-fold-search t)) + (save-excursion + (goto-char begin) + (when (or (re-search-forward + (concat "") + (min end (+ begin 1024)) t) + (re-search-forward + (concat "") + (min end (+ begin 1024)) t) + (re-search-forward + "<\\?xml.*encoding=['\"]\\([^'\"]+\\)['\"] *\\?>" + (min end (+ begin 1024)) t)) + (mew-charset-to-cs (mew-match-string 1)))))) + +(defun mew-mime-text/html-ext (cache begin end &optional params) + (mew-mime-markup-language-ext + mew-prog-text/html-ext cache begin end params "HTML" mew-format-html)) + +(defun mew-mime-markup-language-ext (program cache begin end params tag form) + ;; called in Message buffer + (when (> end begin) + (let* ((file (format form (mew-make-temp-name))) + (prog (mew-progspec-get-prog program)) + (args (mew-progsec-args-convert (mew-progspec-get-args program) file)) + wcs) + (with-current-buffer cache + (message "Displaying %s..." tag) + ;; charset check + (setq wcs (mew-text/html-detect-cs begin end)) + ;; note that application/xml may have the charset parameter + (unless (mew-coding-system-p wcs) + (setq wcs (mew-charset-to-cs + (mew-syntax-get-param params "charset")))) + (unless (mew-coding-system-p wcs) + (setq wcs mew-cs-text-for-write)) + (mew-frwlet mew-cs-dummy wcs + (write-region begin end file nil 'no-msg) + (apply 'mew-start-process-disp prog nil prog args)) + (message "Displaying %s...done" tag))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Text/XML +;;; + +(defun mew-mime-text/xml (cache begin end &optional params) + ;; called in Message buffer + (if (and (symbolp mew-prog-text/xml) (fboundp mew-prog-text/xml)) + (save-excursion + (let ((start (point))) + ;; We need to keep composite properties of charset. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring cache begin end) + (if mew-use-text/xml + (funcall mew-prog-text/xml start (point-max)) + (mew-message-for-summary "To parse XML, type '\\[mew-summary-analyze-again]'")))) + (insert " # # # # #\n" + " # # ## ## #\n" + " # # # # # # #\n" + " # # # # #\n" + " # # # # #\n" + " # # # # #\n" + " # # # # #######\n" + "\n\n") + (mew-insert "Size:\t\t%d bytes\n" (mew-region-bytes begin end cache)) + (mew-insert "Browser:\t%s\n" (or (mew-progspec-get-prog mew-prog-text/xml-ext) "none")) + (insert "\n") + (mew-mime-part-messages t))) + +(defun mew-mime-text/xml-ext (cache begin end &optional params) + (mew-mime-markup-language-ext + mew-prog-text/xml-ext cache begin end params "XML" mew-format-xml)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Application/Xml +;;; + +(defun mew-mime-application/xml (cache begin end &optional params) + ;; called in Message buffer + (if (and (symbolp mew-prog-application/xml) + (fboundp mew-prog-application/xml)) + (save-excursion + (let ((start (point))) + ;; We need to keep composite properties of charset. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring cache begin end) + (funcall mew-prog-application/xml start (point-max)))) + (insert " # # # # #\n" + " # # ## ## #\n" + " # # # # # # #\n" + " # # # # #\n" + " # # # # #\n" + " # # # # #\n" + " # # # # #######\n" + "\n\n") + (mew-insert "Size:\t\t%d bytes\n" (mew-region-bytes begin end cache)) + (mew-insert "Browser:\t%s\n" (or (mew-progspec-get-prog mew-prog-application/xml-ext) "none")) + (insert "\n") + (mew-mime-part-messages t))) + +(defun mew-mime-application/xml-ext (cache begin end &optional params) + (mew-mime-markup-language-ext + mew-prog-application/xml-ext cache begin end params "XML" mew-format-xml)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Text/X-Patch +;;; + +(defun mew-mime-text/patch-ext (cache begin end &optional params) + (when (> end begin) + (save-excursion + (switch-to-buffer-other-frame "*Mew Patch*") + (delete-other-windows) + (erase-buffer) + (insert-buffer-substring cache begin end) + (diff-mode)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Image/* +;;; + +(defun mew-mime-image/* (cache begin end &optional params fname ct cte) + (let* ((format (mew-mime-image-format-name ct))) + (if (mew-image-inline-p format) + (mew-mime-image cache begin end format) + (insert " ##### # # # ##### #######\n" + " # ## ## # # # # # \n" + " # # # # # # # # # \n" + " # # # # # # # #### #######\n" + " # # # ####### # # # \n" + " # # # # # # # # \n" + " ##### # # # # ##### #######\n" + "\n\n") + (mew-insert "Content-Type:\t%s\n" ct) + (mew-insert "Encoding:\t%s\n" cte) + (mew-insert "Size:\t\t%d bytes\n" (mew-region-bytes begin end cache)) + (mew-insert "Filename:\t%s\n" fname) + (mew-insert "Program:\t%s\n" mew-prog-image/*-ext) + (insert "\n") + (mew-mime-part-messages t)))) + +(defun mew-mime-image/*-ext (cache begin end &optional params fname ct cte) + (let ((file (mew-make-temp-name fname))) + (with-current-buffer cache + (mew-flet + (write-region begin end file nil 'no-msg))) + (mew-mime-image-ext file))) + +(defun mew-mime-image-ext (file) + (let* ((spec mew-prog-image/*-ext) + (prog (mew-progspec-get-prog spec)) + (args (mew-progspec-get-args spec))) + (mew-mime-start-process prog args file))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message/Rfc822 +;;; + +(defun mew-mime-text/rfc822-headers (cache begin end &optional params) + ;; called in Message buffer + (when (> end begin) + (save-excursion + ;; We need to keep properties of a header. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring cache begin end) + (mew-header-arrange (point-min) (point-max))))) + +(defun mew-mime-message/rfc822 (cache part) + ;; called in Message buffer + (let* ((hbeg (mew-syntax-get-begin part)) + (hend (mew-syntax-get-end part)) + (body (mew-syntax-get-part part))) + ;; We need to keep properties of a header. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring cache hbeg hend) + (mew-header-arrange (point-min) (point-max)) + (cond + ;; Displaying the text/plain body or the first part of + ;; top level multipart if it is text/plain. + ;; see also mew-syntax-singlepart + ((mew-syntax-singlepart-p body) + (mew-mime-part cache body nil)) ;; nil is single + ((mew-syntax-multipart-p body) + (let* ((first (mew-syntax-get-part body)) + (ct (mew-syntax-get-value (mew-syntax-get-ct first) 'cap))) + (when (and (mew-xinfo-get-text-body) (mew-ct-textp ct)) + (mew-mime-part cache first nil))))))) ;; nil is single + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Application/Octet-Stream +;;; + +(defun mew-mime-application/octet-stream (cache begin end &optional params ct cte cd fl) + (insert " ###### ### # # # ###### # #\n" + " # # # ## # # # # # # #\n" + " # # # # # # # # # # # #\n" + " ###### # # # # # # ###### #\n" + " # # # # # # ####### # # #\n" + " # # # # ## # # # # #\n" + " ###### ### # # # # # # #\n" + "\n\n") + (mew-insert "Content-Type:\t%s\n" ct) + (mew-insert "Encoding:\t%s\n" cte) + (when params + (mew-insert + "Parameters:\t%s\n" + (mapconcat (lambda (x) (concat (nth 0 x) "=" (nth 1 x))) params ", "))) + (mew-insert "Size:\t\t%d bytes\n" (mew-region-bytes begin end cache)) + (mew-insert "Filename:\t%s\n" fl) + (mew-insert "Description:\t%s\n" cd) + (mew-insert-manual + "\nTo specify appropriate Content-Type: \n" + "and execute an internal/external function/command, " + "type \\\\[mew-summary-execute-external]'.\n") + (insert "\n") + (mew-mime-part-messages nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Application/Msoffice +;;; + +(defun mew-mime-application/msword (cache begin end &optional parameter) + (mew-mime-application/msoffice + mew-prog-application/msword cache begin end parameter)) + +(defun mew-mime-application/msexcel (cache begin end &optional parameter) + (mew-mime-application/msoffice + mew-prog-application/msexcel cache begin end parameter)) + +(defun mew-mime-application/mspowerpoint (cache begin end &optional parameter) + (mew-mime-application/msoffice + mew-prog-application/mspowerpoint cache begin end parameter)) + +(defun mew-mime-application/rtf (cache begin end &optional parameter) + (mew-mime-application/msoffice + mew-prog-application/rtf cache begin end parameter)) + +(defun mew-mime-application/rtf-ext (cache begin end &optional parameter) + (save-excursion + (mew-mime-application/rtf cache begin end parameter))) + +(defun mew-mime-application/msoffice (prog cache begin end &optional parameter) + (let ((doit t) file1 file2) + (unless mew-internal-utf-8p + (condition-case nil + (require 'un-define) + (file-error + (setq doit nil) + (insert "To display this, install Mule-UCS for UTF-8.\n")))) + (unless (mew-which-exec prog) + (setq doit nil) + (insert "To display this, install \"" prog "\".\n")) + (condition-case nil + (require 'mew-w3m) + (file-error + (setq doit nil) + (insert "To display this, install \"w3m.el\".\n"))) + (if (not doit) + (progn + (insert "\n") + (mew-mime-part-messages nil)) + (message "Displaying an MS document...") + (mew-erase-buffer) + (setq file1 (mew-make-temp-name)) + (with-current-buffer cache + (mew-flet + (write-region begin end file1 nil 'no-msg))) + (setq file2 (mew-make-temp-name)) + (if (eq prog mew-prog-application/msword) + (mew-frwlet 'utf-8 mew-cs-dummy + (if mew-use-old-wvhtml + (call-process prog nil nil nil file1 file2) + (call-process prog nil nil nil + "--charset=utf-8" + (concat "--targetdir=" (file-name-directory file2)) + file1 + (file-name-nondirectory file2))) + (let ((buffer-file-coding-system)) ;; to prevent the side effect + (mew-insert-file-contents file2))) + (if (eq prog mew-prog-application/rtf) + (mew-frwlet 'shift_jis mew-cs-dummy + (call-process prog nil (current-buffer) nil file1)) + (mew-frwlet 'utf-8 mew-cs-dummy + (call-process prog nil (current-buffer) nil file1)))) + (mew-delete-file file1) + (mew-delete-file file2) + (save-excursion + (w3m-region (point-min) (point-max) + (w3m-expand-file-name-as-url (file-name-directory file2)))) + (message "Displaying an MS document...done")))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PDF +;;; + +(defun mew-mime-application/pdf (cache begin end &optional parameter) + (message "Displaying a PDF document...") + (mew-erase-buffer) + (let ((doit t) (prog mew-prog-application/pdf) + file1 file2) + (unless (mew-which-exec prog) + (setq doit nil) + (mew-elet (insert "To display this, install \"" prog "\".\n"))) + (if (not doit) + (progn + (mew-elet (insert "\n")) + (mew-mime-part-messages t) + (message "Displaying a PDF document...failed")) + (setq file1 (mew-make-temp-name)) + (with-current-buffer cache + (mew-flet + (write-region begin end file1 nil 'no-msg))) + (setq file2 (mew-make-temp-name)) + (call-process prog nil nil nil "-layout" "-enc" "UTF-8" file1 file2) + (when (file-exists-p file2) + (mew-frwlet 'utf-8 mew-cs-dummy + (insert-file-contents file2))) + (if (file-exists-p file1) (delete-file file1)) + (if (file-exists-p file2) (delete-file file2)) + (message "Displaying a PDF document...done")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Application/Ms-Tnef +;;; + +(defun mew-mime-application-ms-tnef (cache begin end &optional parameter) + (insert " ####### # # ####### ########\n" + " # ## # # #\n" + " # # # # # #\n" + " # # # # ####### ######\n" + " # # # # # #\n" + " # # ## # #\n" + " # # # ####### #\n" + "\n\n") + (mew-insert-manual + "To extract files, type " + "'\\\\[mew-summary-execute-external]'.\n")) + +(defvar mew-prog-tnef "tnef") + +(defun mew-mime-application-ms-tnef-ext (cache begin end &optional parameter) + ;; called in Message buffer + (let ((file (mew-make-temp-name)) + (dir (mew-input-directory-name mew-home))) + (if (not (mew-which-exec mew-prog-tnef)) + (message "'%s' not found" mew-prog-tnef) + (with-current-buffer cache + (mew-plet + (write-region begin end file nil 'no-msg))) + (mew-erase-buffer) + (insert "Extracted: \n\n") + (call-process mew-prog-tnef file t nil "--verbose" "-C" dir) + (mew-delete-file file)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Executing external commands +;;; + +(defun mew-summary-ask-ct (ct fname) + (let (pt fl) + (cond + (fname + (setq ct (or (mew-ctdb-ct (mew-ctdb-by-file fname)) + (mew-content-type (mew-sinfo-get-case)))) + (setq pt "Type for %s (%s): ") + (setq fl fname)) + (t + (setq pt "Type %s(%s): ") + (setq fl ""))) + (mew-input-type pt fl ct mew-mime-content-type-list))) + +(defun mew-summary-execute-external (&optional ask-command) + "Execute an external command according to Content-Type:. +If this command is executed on the entire message, the first part +is chosen as a target. + +If Content-Type of the target part is Application/Octet-Stream, +Content-Type is automatically asked. And if it has both +internal and external visualization mechanisms, you are asked +which you want to use. + +If executed with '\\[universal-argument]', you can specify a +command to be executed. + +See 'mew-mime-content-type' to know how actions can be defined." + (interactive "P") + (mew-summary-msg-or-part + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (nums (mew-syntax-nums)) + (cache (mew-cache-hit fld msg 'must-hit)) + (syntax (mew-cache-decode-syntax cache)) + (stx (mew-syntax-get-entry syntax nums)) + (ctl (mew-syntax-get-ct stx)) + (ct (mew-syntax-get-value ctl 'cap)) + (win (selected-window)) + begin end params cdpl fname program options async was-apo erase-p + pro-opt ent1 ent2) + (when (and (string= ct mew-ct-msg) + (or (not ask-command) + (not (y-or-n-p "Save the entire message (y) or the first part (n)? ")))) + (setq stx (mew-syntax-get-part stx)) + (if (mew-syntax-multipart-p stx) + (setq stx (mew-syntax-get-part stx))) + (setq ctl (mew-syntax-get-ct stx)) + (setq ct (mew-syntax-get-value ctl 'cap))) + (setq begin (mew-syntax-get-begin stx)) + (setq end (mew-syntax-get-end stx)) + (setq params (mew-syntax-get-params ctl)) + (setq cdpl (mew-syntax-get-cdp stx)) + (setq fname (mew-syntax-get-filename cdpl ctl)) + (when (or (string= ct mew-ct-apo) + (eq (mew-ctdb-prog (mew-ctdb-by-ct ct)) + 'mew-mime-application/octet-stream)) + (setq ct (mew-summary-ask-ct ct fname)) + (setq was-apo t)) + (if (not ask-command) + (setq program (mew-ctdb-prog (mew-ctdb-by-ct ct))) + (setq pro-opt (mew-input-command mew-default-external-program)) + (setq program (car pro-opt)) + (setq options (cdr pro-opt))) + ;; prog + ;; func => called for both + ;; (prog ...) + ;; (nil prog) == prog + ;; (nil (prog...)) == (prog...) + ;; (nil func) != func + ;; (func func) => need to select + ;; (func prog) => need to select + ;; (func (prog ...)) => need to select + (cond + ((stringp program) + (setq async t)) + ((symbolp program) + (setq erase-p t)) + ((listp program) + (setq ent1 (nth 0 program)) + (setq ent2 (nth 1 program)) + (cond + ((stringp ent1) + (mew-set '(program options async) program)) + ((null ent1) + (cond + ((stringp ent2) + (setq program ent2) + (setq async t)) + ((listp ent2) + (mew-set '(program options async) ent2)) + (t ;; symbol + (setq program ent2)))) + (t ;; symbol + (if (and was-apo + (y-or-n-p "Internal (y) or External (n)? ")) + (progn + (setq erase-p t) + (setq program ent1)) + (setq program ent2)) + (cond + ((stringp program) + (setq async t)) + ((listp program) + (mew-set '(program options async) program))))))) + (mew-summary-toggle-disp-msg 'on) + (mew-window-configure 'message) + (if erase-p (mew-erase-buffer)) + ;; message buffer + (unwind-protect + (mew-elet + (cond + ((stringp program) + (mew-summary-execute-program + program ct ctl cache begin end params fname options async)) + ((symbolp program) + (mew-summary-execute-symbol + program ct ctl cache begin end params fname was-apo))) + (mew-summary-display-postscript 'no-hook)) + (select-window win))))) + +(defun mew-summary-execute-symbol (program ct ctl cache begin end params fname was-apo) + (cond + ((not (fboundp program)) + (message "%s is not implemented" (symbol-name program))) + ((eq program mew-prog-rfc822) + (message "%s cannot be executed" mew-prog-rfc822)) + ((or (mew-ct-imagep ct) (mew-ct-modelp ct)) + (funcall program cache begin end params fname ct)) + (t + (let ((mew-use-text/html t) + (mbuf (current-buffer)) + tbuf) + (if (and was-apo (mew-ct-textp ct)) ;; decode-broken? + (with-temp-buffer + (insert-buffer-substring cache begin end) + (mew-cs-decode-region (point-min) (point-max) mew-cs-autoconv) + (setq tbuf (current-buffer)) + (setq begin (point-min)) + (setq end (point-max)) + (set-buffer mbuf) + (funcall program tbuf begin end params)) + (funcall program cache begin end params)))))) + +;;; external +(defun mew-summary-execute-program (program ct ctl cache begin end params fname options async) + (if (not (mew-which-exec program)) + (message "%s does not exist" program) + (let ((file (mew-make-temp-name fname)) + wcs) + (with-current-buffer cache + ;; NEVER use call-process-region for privacy reasons + (cond + ((not (mew-ct-linebasep ct)) + (setq wcs mew-cs-binary)) + ((not (mew-ct-textp ct)) + (setq wcs mew-cs-text-for-write)) + (t + (cond + ((or (string= mew-ct-htm ct) (string= mew-ct-xml ct)) + (setq wcs (mew-text/html-detect-cs begin end)) + (unless (mew-coding-system-p wcs) + (setq wcs (mew-charset-to-cs + (mew-syntax-get-param ctl "charset"))))) + (t + (setq wcs (mew-charset-to-cs + (mew-syntax-get-param ctl "charset"))))) + (unless (mew-coding-system-p wcs) + (setq wcs (if mew-decode-broken + (mew-charset-to-cs + (mew-charset-guess-region + begin end)) + mew-cs-text-for-write))))) + (mew-frwlet mew-cs-dummy wcs + (write-region begin end file nil 'no-msg)) + (if async + (mew-mime-start-process program options file) + (mew-mime-call-process program options file)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; unzip +;;; + +(defvar mew-ct-zip-list '("Application/Zip" + "Application/X-Zip-Compressed" + "Application/Octet-Stream")) + +(defun mew-ct-zip-p (ct) + (member ct mew-ct-zip-list)) + +(defun mew-summary-unzip () + (interactive) + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (nums (mew-syntax-nums)) + (cache (mew-cache-hit fld msg 'must-hit)) + (syntax (mew-cache-decode-syntax cache)) + (stx (mew-syntax-get-entry syntax nums)) + (ct (mew-syntax-get-value (mew-syntax-get-ct stx) 'cap)) + (file0 (mew-syntax-get-param (mew-syntax-get-cdp stx) "filename")) + (beg (mew-syntax-get-begin stx)) + (end (mew-syntax-get-end stx)) + (size (- end beg)) + (dir mew-temp-dir) + file size1 end1) + (if (not (mew-ct-zip-p ct)) + (message "Cannot unzip")) + (setq file (mew-unzip-file cache beg end dir file0)) + (if (not file) + (message "unzip failed") + (let ((ct (mew-ctdb-ct (mew-ctdb-by-file file))) + cs) + (unless ct + (let ((txtp (mew-ct-textp (mew-content-type "default"))) + (file- (file-name-nondirectory file))) + (setq ct (if txtp + (if (y-or-n-p (format "\"%s\" as text? " file-)) + mew-ct-txt mew-ct-apo) + (if (y-or-n-p (format "\"%s\" as binary? " file-)) + mew-ct-apo mew-ct-txt))))) + (setq cs (if (mew-ct-textp ct) mew-cs-autoconv mew-cs-binary)) + (with-current-buffer cache + (delete-region beg end) + (goto-char beg) + (save-restriction + (narrow-to-region beg beg) + (mew-frwlet cs mew-cs-dummy + (insert-file-contents (expand-file-name file dir))) + (mew-syntax-set-ct stx (list ct)) + (setq end1 (point-max)) + (mew-syntax-set-end stx end1) + (setq size1 (- end1 beg)) + (mew-syntax-set-cdp stx (mew-syntax-cdp-format ct file))) + (mew-decode-syntax-adjust-message mew-decode-syntax beg (- size1 size)) + (mew-xinfo-set-multi-form nil) + (mew-decode-syntax-set)) + (let ((current (point)) + (start (mew-decode-syntax-begin))) + (mew-decode-syntax-delete) + (mew-decode-syntax-copy cache) + (goto-char start) + (forward-line -1) + (mew-decode-syntax-print (current-buffer) + mew-decode-syntax + (mew-xinfo-get-multi-form) + (mew-xinfo-get-icon-spec)) + (goto-char current) + (mew-summary-display 'redisplay)))))) + +(defun mew-decode-syntax-adjust (val threshold inc) + (if (> val threshold) (+ val inc) val)) + +(defun mew-decode-syntax-adjust-single (syntax threshold inc) + (unless (= (mew-syntax-get-begin syntax) threshold) + (mew-syntax-set-begin + syntax (mew-decode-syntax-adjust + (mew-syntax-get-begin syntax) threshold inc)) + (mew-syntax-set-end + syntax (mew-decode-syntax-adjust + (mew-syntax-get-end syntax) threshold inc)))) + +(defun mew-decode-syntax-adjust-message (syntax threshold inc) + (mew-decode-syntax-adjust-single syntax threshold inc) + (let ((body (mew-syntax-get-part syntax))) + (if (mew-syntax-multipart-p body) + (mew-decode-syntax-adjust-multi body threshold inc) + (mew-decode-syntax-adjust-single body threshold inc)))) + +(defun mew-decode-syntax-adjust-multi (syntax threshold inc) + (mew-decode-syntax-adjust-single syntax threshold inc) + (let ((i mew-syntax-magic) + (len (length syntax)) + part) + (while (< i len) + (setq part (aref syntax i)) + (cond + ((mew-syntax-singlepart-p part) + (mew-decode-syntax-adjust-single part threshold inc)) + ((mew-syntax-multipart-p part) + (mew-decode-syntax-adjust-multi part threshold inc)) + ((mew-syntax-message-p part) + (mew-decode-syntax-adjust-message part threshold inc))) + (setq i (1+ i))))) + +(defun mew-unzip-file (buf beg end dir file) + (let* ((zipfile (expand-file-name file dir)) + (encrypted (mew-zip-encrypted-p buf beg)) + (password (if encrypted (read-passwd "Zip password: "))) + (args0 (list "-o" "-d" dir zipfile)) + (args (if password (cons "-P" (cons password args0)) args0))) + (with-current-buffer buf + (mew-frwlet mew-cs-dummy mew-cs-binary + (write-region beg end zipfile nil 'no-msg))) + (with-temp-buffer + (apply 'call-process "unzip" nil t nil args) + (goto-char (point-max)) + (forward-line -1) + (beginning-of-line) + (when (looking-at "^ *[a-z]+: \\([^ ]+\\)") + (mew-match-string 1))))) + +(defun mew-zip-encrypted-p (buf beg) + (with-current-buffer buf + (goto-char beg) + (forward-char 6) + (= (% (char-after) 2) 1))) + +(provide 'mew-mime) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-mime.el ends here diff --git a/elpa/mew-20150813.2354/mew-minibuf.el b/elpa/mew-20150813.2354/mew-minibuf.el new file mode 100644 index 00000000..705bde01 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-minibuf.el @@ -0,0 +1,1058 @@ +;;; mew-minibuf.el --- Minibuffer input methods for Mew + +;; Author: Kazu Yamamoto +;; Created: Mar 23, 1997 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Completion switch +;;; + +(defvar mew-input-complete-function nil + "A function to be called when TAB is typed in minibuffer. +This is used in 'mew-input-complete'.") + +(defun mew-input-complete () + "Do completion according to the global variable +\"mew-input-complete-function\"." + (interactive) + (if (and mew-input-complete-function (fboundp mew-input-complete-function)) + (funcall mew-input-complete-function))) + +(defvar mew-input-exit-minibuffer-function nil + "A function to be called when RET is typed in minibuffer. +This function are used to check validity of 'case' and sort key.") + +(defun mew-input-exit-minibuffer () + "Ensure the input meets a condition." + (interactive) + (if (or (not (and mew-input-exit-minibuffer-function + (fboundp mew-input-exit-minibuffer-function))) + (funcall mew-input-exit-minibuffer-function)) + (exit-minibuffer))) + +(defvar mew-input-comma-function nil + "A function to be called when ',' is typed in minibuffer. +This function can be used to check validity of 'case'.") + +(defun mew-input-comma () + "Ensure the input meets a condition." + (interactive) + (when (or (not (and mew-input-comma-function + (fboundp mew-input-comma-function))) + (funcall mew-input-comma-function)) + (insert ","))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Clean up side effects +;;; + +(defun mew-input-clear () + "A function to clean up side effects of window configuration +at completions." + (with-current-buffer (window-buffer (minibuffer-window)) + ;; (mew-ainfo-get-win-cfg) is shared by many functions + ;; because minibuffer is just one! + (mew-ainfo-set-win-cfg nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder +;;; + +(defvar mew-input-folder-search-buf " *Mew* folder search") + +(defvar mew-input-folder-hist nil) + +(defvar mew-input-folder-refile nil) + +(defvar mew-input-folder-search-direction nil) +(defvar mew-input-folder-search-key nil) +(defvar mew-input-folder-search-match nil) +(defvar mew-input-folder-search-original nil) +(defvar mew-input-folder-search-point nil) +(defvar mew-input-folder-search-multi nil) + +(defun mew-input-folder-clean-up () + (setq mew-input-folder-search-direction nil) + (setq mew-input-folder-search-key nil) + (setq mew-input-folder-search-match nil) + (setq mew-input-folder-search-original nil) + (setq mew-input-folder-search-point nil)) + +(defun mew-highlight-folder-comp-search-window () + (let* ((win (get-buffer-window mew-buffer-completions)) + (match mew-input-folder-search-match) + face) + (when (and win + mew-input-folder-search-key + mew-input-folder-search-match) + (with-current-buffer mew-buffer-completions + (mew-elet + (goto-char (point-min)) + (when (looking-at "^Key: ") + (delete-region (point-min) (progn (forward-line) (point)))) + (insert "Key: " mew-input-folder-search-key ", " + "Match: " mew-input-folder-search-match "\n") + (put-text-property (point-min) (point-max) 'face nil) + (when (re-search-forward + (format "\\(%s\\)\\([ \t]\\|$\\)" (regexp-quote match)) nil t) + (goto-char (match-beginning 1)) + (setq face (if (not window-system) + 'mew-face-header-from + (if (facep 'isearch) 'isearch 'region))) + (put-text-property (point) (match-end 1) 'face face) + (unless (pos-visible-in-window-p (point) win) + (set-window-start win (progn (forward-line -2) (point)))))))))) + +(defun mew-input-folder-display (&optional msg) + (mew-highlight-folder-comp-search-window) + (mew-elet + (delete-region (mew-minibuf-point-min) (point-max)) + (insert "(" (or mew-input-folder-search-match "") ") ") + (insert (or mew-input-folder-search-key "")) + (if msg (save-excursion (insert " [" msg "]"))) + (put-text-property (mew-minibuf-point-min) (point-max) 'read-only t))) + +(defun mew-input-folder-search-setup (&optional min) + (if mew-input-folder-refile + (mew-input-folder-search-setup2 min) + (mew-input-folder-search-setup1 min))) + +(defun mew-input-folder-search-setup-buffer (alist min) + (with-current-buffer (get-buffer-create mew-input-folder-search-buf) + (setq buffer-read-only t) + (mew-elet + (mew-erase-buffer) + (mapc (lambda (x) (if (stringp (car x)) (insert (car x) "\n"))) alist)) + (if min (goto-char (point-min))))) + +(defun mew-input-folder-search-setup1 (&optional min) + (let (case:folder case folder alist) + (save-excursion + (goto-char (point-max)) + (if (search-backward "," nil t) + (setq mew-input-folder-search-point + (- (match-end 0) (mew-minibuf-point-min))))) + (setq mew-input-folder-search-original + (mew-buffer-substring (mew-minibuf-point-min) (point-max))) + (setq case:folder mew-input-folder-search-original) + (if mew-input-folder-search-point + (setq case:folder (substring case:folder mew-input-folder-search-point))) + (setq case (mew-case:folder-case case:folder)) + (setq folder (mew-case:folder-folder case:folder)) + (when case + (setq mew-input-folder-search-point + (+ (or mew-input-folder-search-point 0) (length case) 1))) ;; ":" + (mew-input-folder-display) + (if (or (null folder) (string= folder "")) + (setq folder (mew-proto case))) + (cond + ((mew-folder-popp folder) + (setq alist (mew-pop-folder-alist))) + ((mew-folder-nntpp folder) + (setq alist (mew-nntp-folder-alist case))) + ((mew-folder-imapp folder) + (setq alist (mew-imap-folder-alist case))) + (t + (setq alist (mew-local-folder-alist)))) + (mew-input-folder-search-setup-buffer alist min))) + +(defun mew-input-folder-search-setup2 (&optional min) + (let (do-search alist) + (save-excursion + (goto-char (point-max)) + (if (search-backward "," (minibuffer-prompt-end) t) + (progn + (goto-char (match-end 0)) + (unless (looking-at mew-regex-case2) + (setq do-search t) + (setq mew-input-folder-search-point + (- (point) (mew-minibuf-point-min))))) + (goto-char (mew-minibuf-point-min)) + (unless (looking-at mew-regex-case2) + (setq do-search t)))) + (if (not do-search) + (progn + (mew-temp-minibuffer-message "Remove case!") + (mew-input-folder-clean-up)) + (setq mew-input-folder-search-original + (mew-buffer-substring (mew-minibuf-point-min) (point-max))) + (mew-input-folder-display) + (cond + ((eq mew-input-complete-function 'mew-complete-local-folder) + (setq alist (mew-local-folder-alist))) + ((eq mew-input-complete-function 'mew-complete-imap-folder) + (setq alist (mew-imap-folder-alist mew-inherit-case)))) + (mew-input-folder-search-setup-buffer alist min)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder search forward +;;; + +(defun mew-input-folder-search-forward-1 (&optional again) + (let (no-match pos) + (with-current-buffer mew-input-folder-search-buf + (setq pos (point)) + (if again + (forward-line) + (beginning-of-line)) + (if (search-forward mew-input-folder-search-key nil t) + (progn + (goto-char (match-beginning 0)) + (setq mew-input-folder-search-match + (mew-buffer-substring + (save-excursion (beginning-of-line) (point)) + (save-excursion (end-of-line) (point))))) + (setq no-match t) + (goto-char pos))) + (if no-match + (mew-input-folder-display "no match") + (mew-input-folder-display)))) + +(defun mew-input-folder-search-forward () + "Search a folder forward." + (interactive) + (cond + ((and mew-input-folder-search-direction (null mew-input-folder-search-key)) + (mew-input-folder-display "no match")) + ((eq mew-input-folder-search-direction 'forward) + (mew-input-folder-search-forward-1 'again)) + ((eq mew-input-folder-search-direction 'backward) + (setq mew-input-folder-search-direction 'forward) + (mew-input-folder-search-forward-1 'again)) + (t + (setq mew-input-folder-search-direction 'forward) + (mew-input-folder-search-setup 'min)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder search backward +;;; + +(defun mew-input-folder-search-backward-1 (&optional again) + (let (no-match pos) + (with-current-buffer mew-input-folder-search-buf + (setq pos (point)) + (if again + (progn (forward-line -1) (end-of-line)) + (end-of-line)) + (if (search-backward mew-input-folder-search-key nil t) + (progn + (goto-char (match-end 0)) + (setq mew-input-folder-search-match + (mew-buffer-substring + (save-excursion (beginning-of-line) (point)) + (save-excursion (end-of-line) (point))))) + (setq no-match t) + (goto-char pos))) + (if no-match + (mew-input-folder-display "no match") + (mew-input-folder-display)))) + +(defun mew-input-folder-search-backward () + "Search a folder backward." + (interactive) + (cond + ((and mew-input-folder-search-direction (null mew-input-folder-search-key)) + (mew-input-folder-display "no match")) + ((eq mew-input-folder-search-direction 'forward) + (setq mew-input-folder-search-direction 'backward) + (mew-input-folder-search-backward-1 'again)) + ((eq mew-input-folder-search-direction 'backward) + (mew-input-folder-search-backward-1 'again)) + (t + (setq mew-input-folder-search-direction 'backward) + (mew-input-folder-search-setup)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder commands +;;; + +(defun mew-input-folder-exit-minibuffer () + "If called in folder search, this gets back to minibuffer to input +folders. If called in minibuffer to input folders, this +gets out of minibuffer." + (interactive) + (if mew-input-folder-search-direction + (mew-elet + (delete-region (mew-minibuf-point-min) (point-max)) + (cond + (mew-input-folder-search-match + (when mew-input-folder-search-point + (insert (substring mew-input-folder-search-original + 0 mew-input-folder-search-point))) + (insert mew-input-folder-search-match)) + (mew-input-folder-search-original + (insert mew-input-folder-search-original))) + (mew-input-folder-clean-up) + (mew-complete-window-delete)) + (exit-minibuffer))) + +(defun mew-input-folder-abort-minibuffer () + "This function exits folder search mode if in folder search mode. +Otherwise, it exits minibuffer." + (interactive) + (if mew-input-folder-search-direction + (mew-elet + (delete-region (mew-minibuf-point-min) (point-max)) + (when mew-input-folder-search-original + (insert mew-input-folder-search-original)) + (mew-input-folder-clean-up) + (mew-complete-window-delete)) + (abort-recursive-edit))) + +(defun mew-input-folder-comma () + "This function inserts ',' on multiple folder input +and does not insert anything on single folder input." + (interactive) + (unless mew-input-folder-search-direction + (insert ","))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Self insert +;;; + +(defun mew-input-folder-self-insert () + "This function normally inserts its bound key to minibuffer. +When in folder search mode, this function searches a candidate +folder and displays it in addition to its bound key." + (interactive) + (let ((key (this-command-keys)) + last-str gfunc) + (cond + ((stringp key) + (setq last-str key) + (setq gfunc (lookup-key (current-global-map) key))) + ((vectorp key) + (setq gfunc (lookup-key (current-global-map) key)) + (unless gfunc + (setq key (lookup-key function-key-map key)) + (cond + ((vectorp key) ;; normal Emacs + (setq gfunc (lookup-key (current-global-map) key))) + ((stringp key) ;; Meadow + (setq last-str key) + (setq gfunc (lookup-key (current-global-map) key))))))) + (if mew-input-folder-search-direction + (cond + ((or (equal key "\177") (equal key [127]) + (equal key 'delete) (equal key 'backspace)) + (if (null mew-input-folder-search-key) + (mew-input-folder-display "not allowed") + (setq mew-input-folder-search-key + (substring mew-input-folder-search-key 0 -1)) + (when (string= mew-input-folder-search-key "") + (setq mew-input-folder-search-key nil) + (setq mew-input-folder-search-match nil) + (with-current-buffer mew-input-folder-search-buf + (cond + ((eq mew-input-folder-search-direction 'forward) + (goto-char (point-min))) + ((eq mew-input-folder-search-direction 'backward) + (goto-char (point-max)))))) + (mew-input-folder-display))) + ((and (symbolp gfunc) + (not (string-match "self-insert-command" (symbol-name gfunc)))) + (mew-input-folder-display "not allowed")) + ((eq mew-input-folder-search-direction 'forward) + (setq mew-input-folder-search-key + (concat mew-input-folder-search-key last-str)) + (mew-input-folder-search-forward-1)) + ((eq mew-input-folder-search-direction 'backward) + (setq mew-input-folder-search-key + (concat mew-input-folder-search-key last-str)) + (mew-input-folder-search-backward-1))) + (cond + ((or (null gfunc) + (and (symbolp gfunc) (not (fboundp gfunc)))) + ()) + ((and (symbolp gfunc) + (string-match "self-insert-command" (symbol-name gfunc))) + (insert last-command-event)) + ((commandp gfunc) + (call-interactively gfunc)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Prefix hack +;;; + +(defun mew-input-folder-complete-case (prefix-char) + (when (and mew-use-case-completion + (eq mew-input-complete-function 'mew-complete-folder) + (mew-folder-remotep (char-to-string prefix-char)) + (and mew-case (not (string= mew-case mew-case-default)))) + (insert mew-case ":"))) + +(defun mew-input-folder-prefix () + "A function to insert a folder prefix in minibuffer. +If the previous character is another folder prefix, +it is deleted automatically." + (interactive) + (cond + (mew-input-folder-search-direction + (mew-input-folder-self-insert)) + ;; + ((or (eq mew-input-complete-function 'mew-complete-local-folder) + (eq mew-input-complete-function 'mew-complete-imap-folder)) + ;; no case, not allow other prefixes. + (let* ((pos (- (point) (mew-minibuf-point-min))) + (prefix (if (eq mew-input-complete-function + 'mew-complete-local-folder) + mew-folder-local mew-folder-imap)) + (insert-ok (string= (char-to-string last-command-event) prefix))) + (cond + ((or (= pos 0) + (save-excursion (forward-char -1) (looking-at ","))) + (if insert-ok (insert prefix))) + ((or (and (= pos 1) + (save-excursion (forward-char -1) (looking-at "[-+%$]"))) + ;; excluding * + (save-excursion (forward-char -2) (looking-at ",[-+%$]"))) + ;; A wrong prefix might accidentally be here. + ;; So, replace it just in case + (when insert-ok + (forward-char -1) + (delete-char 1) + (insert prefix))) + (t + (insert last-command-event))))) + (t + (let ((pos (- (point) (mew-minibuf-point-min)))) + (cond + ((or (= pos 0) + (save-excursion (forward-char -1) (looking-at ","))) + (mew-input-folder-complete-case last-command-event) + (insert last-command-event)) + ;; + ((or (and (= pos 1) + (save-excursion (forward-char -1) (looking-at "[-+%$]"))) + ;; excluding * + (save-excursion (forward-char -2) (looking-at ",[-+%$]"))) + (forward-char -1) + (delete-char 1) + (mew-input-folder-complete-case last-command-event) + (insert last-command-event)) + ;; + ((save-excursion + (forward-char -2) + (looking-at ":[-+%$*]")) + (forward-char -1) + (delete-char 1) + (when (memq last-command-event '(?+ ?*)) + ;; delete case: + (delete-region (save-excursion (or (and (search-backward "," nil t) + (match-end 0)) + (mew-minibuf-point-min))) + (point))) + (insert last-command-event)) + ;; + (t + (insert last-command-event))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder +;;; + +(defun mew-input-folder-check (folders) + (let (folder ret) + (dolist (case:folder folders) + (catch 'continue + (if (string-match mew-regex-case case:folder) + (progn + (setq folder (mew-match-string 2 case:folder)) + (if (= (length folder) 0) (throw 'continue nil))) ;; "case:" only + (setq folder case:folder)) + (if (and (= (length folder) 1) + (member folder mew-folder-prefixes)) ;; "prefix" only + (throw 'continue nil)) + (if (and (mew-folder-popp folder) ;; not $inbox + (not (string= mew-pop-inbox-folder folder))) + (throw 'continue nil)) + (setq case:folder (mew-canonicalize-case-folder case:folder)) + (setq ret (cons case:folder ret)))) + (setq ret (delete nil ret)) + (nreverse ret))) + +(defun mew-input-local-folder (folder) + "Input a local folder from the minibuffer." + (mew-input-clear) + (mew-input-folder-clean-up) + (let* ((default folder) + (init (mew-folder-prefix folder)) + (mew-input-complete-function 'mew-complete-local-folder) + (mew-circular-complete-function 'mew-circular-complete-case:) + (ret (read-from-minibuffer (format "Folder name (%s): " default) + init mew-input-folder-map nil + 'mew-input-folder-hist))) + (when (or (string= ret "") (string= ret init)) + (setq ret default)) + (car (mew-input-folder-check (list ret))))) + +(defun mew-input-folder (case folder) + "Input a folder from the minibuffer." + (mew-input-clear) + (mew-input-folder-clean-up) + (let* ((default (mew-case-folder case folder)) + (init (mew-case-folder case (mew-folder-prefix folder))) + (mew-input-complete-function 'mew-complete-folder) + (mew-circular-complete-function 'mew-circular-complete-case:) + ;; mew-inherit-case must be nil + (ret (read-from-minibuffer (format "Folder name (%s): " default) + init mew-input-folder-map nil + 'mew-input-folder-hist)) + (new-folder)) + (when (or (string= ret "") (string= ret init)) + (setq ret default)) + ;; mew-input-folder-check requires an IMAP separator, + ;; which requires C-uZ. C-uZ needs "g". So, chicken and egg. + ;; Skip the check for inbox to avoid the problem. + (setq new-folder (mew-case:folder-folder ret)) + (if (member new-folder (list mew-inbox-folder + mew-pop-inbox-folder + mew-imap-inbox-folder + mew-nntp-newsgroup)) + ret + (car (mew-input-folder-check (list ret)))))) + +(defun mew-input-folders (case:folder) + "Input a folder from the minibuffer." + (mew-input-clear) + (mew-input-folder-clean-up) + (let* ((init (mew-canonicalize-case-folder case:folder)) + (mew-input-complete-function 'mew-complete-folder) + (mew-circular-complete-function 'mew-circular-complete-case:) + (mew-input-folder-search-multi t) + ;; mew-inherit-case must be nil + (ret (read-from-minibuffer "Folder name: " + init mew-input-folder-map nil + 'mew-input-folder-hist))) + (when (string= ret "") + (setq ret init)) + (setq ret (mapcar 'mew-chop (mew-split ret ?,))) + (mew-input-folder-check ret))) + +(defun mew-input-refile-folder-check (folders proto) + (let (folder ret) + (dolist (case:folder folders) + (catch 'continue + ;; If case is specified, just remove it at this moment... + (if (string-match mew-regex-case case:folder) + (progn + (setq folder (mew-match-string 2 case:folder)) + (if (= (length folder) 0) (throw 'continue nil))) ;; "case:" only + (setq folder case:folder)) + (cond + ((eq proto 'imap) + (unless (mew-folder-imapp folder) + (throw 'continue nil))) + ((eq proto 'local) + (unless (mew-folder-localp folder) + (throw 'continue nil)))) + (if (and (= (length folder) 1) + (member folder mew-folder-prefixes)) ;; "prefix" only + (throw 'continue nil)) + (setq folder (mew-canonicalize-case-folder folder)) + (setq ret (cons folder ret)))) + (nreverse ret))) + +(defun mew-input-refile-folders (folder-list singlep case proto) + "Input refile folders from the minibuffer." + (mew-input-clear) + (mew-input-folder-clean-up) + (let ((mew-input-complete-function (if (mew-folder-imapp proto) + 'mew-complete-imap-folder + 'mew-complete-local-folder)) + (mew-inherit-case case) + (mew-input-folder-search-multi t) + (mew-input-folder-refile t) + ;; Emacs 21.1, 21.2 and 21.3 has a bug of inhibit-quit. + ;; Set inhibit-quit to nil so that C-g can be used + (inhibit-quit nil) + default prompt init ret) + (cond + (singlep + (setq default (car folder-list)) + (setq init (mew-folder-prefix default)) + (if case + (setq prompt (format "Folder name <%s:> (%s): " case default)) + (setq prompt (format "Folder name (%s): " default)))) + (t + (if case + (setq prompt (format "Folder name <%s:>: " case)) + (setq prompt "Folder name: ")) + (setq init (mew-join "," folder-list)))) + (setq ret (read-from-minibuffer prompt + init mew-input-folder-map nil + 'mew-input-folder-hist)) + (when (and singlep (string= ret init)) + (setq ret default)) + (setq ret (mapcar 'mew-chop (mew-split ret ?,))) + (mew-input-refile-folder-check + ret (if (mew-folder-imapp proto) 'imap 'local)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Address +;;; + +(defvar mew-input-address-hist nil) + +(defun mew-input-address (prompt &optional default) + (mew-input-clear) + (let ((mew-input-complete-function 'mew-complete-address) + val vals addrs ret) + (setq val (read-from-minibuffer + (if default (format prompt default) prompt) + "" + mew-input-map + nil + 'mew-input-address-hist)) + (if (and default (string= val "")) + (setq val default)) + (setq vals (mapcar 'mew-chop (mew-split-quoted val ?,))) + (dolist (val vals) + (setq addrs (mew-alias-expand val mew-addrbook-alist 0)) + (setq addrs (mapcar 'mew-addrstr-append-domain addrs)) + (setq ret (nconc ret addrs))) + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Pick pattern +;;; + +(defvar mew-input-pick-pattern-hist nil) + +(defun mew-input-pick-pattern (prompt) + (mew-input-clear) + (let ((mew-input-complete-function 'mew-complete-pick-pattern) + (mew-circular-complete-function 'mew-circular-complete-pick-pattern) + (keymap (copy-keymap mew-input-map))) + (define-key keymap " " nil) + (mew-pick-macro-expand-string + (read-from-minibuffer (concat prompt " pattern: ") + (car mew-pick-pattern-list) + keymap + nil + 'mew-input-pick-pattern-hist)))) + +(defvar mew-input-pick-command-hist nil) + +(defun mew-input-pick-command (prog opts) + (mew-input-clear) + (let ((init (mapconcat 'identity (cons prog opts) " ")) + (prompt "Cmd opts pattern: ") + input lst cmd opts len pat) + (unless (string-match " $" init) + (setq init (concat init " "))) + (setq input (read-string prompt init 'mew-input-pick-command-hist)) + (setq mew-input-pick-command-hist + (mew-uniq-list mew-input-pick-command-hist)) + (setq lst (mew-split-quoted input mew-sp)) + (setq cmd (car lst)) + (setq opts (cdr lst)) + (setq len (length opts)) + (cond + ((= len 0) + ) + ((= len 1) + (setq pat (car opts)) + (setq opts nil)) + (t + (setq pat (nth (1- len) opts)) + (setcdr (nthcdr (- len 2) opts) nil))) + (list cmd opts pat))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sort key +;;; +;;; mew-sort-default-key-alist + +(defvar mew-input-sort-key-hist nil) + +(defun mew-input-sort-key-check () + (let* ((field:mode (mew-buffer-substring (mew-minibuf-point-min) (point-max))) + (mode (car (cdr (mew-split field:mode ?:)))) + err) + (if mode + (unless (member mode mew-sort-modes) + (setq err mode))) + (if err + (progn + (mew-temp-minibuffer-message (format " [No match: %s]" err)) + nil) + t))) + +(defun mew-input-sort-key (key) + (mew-input-clear) + (let* ((mew-input-complete-function 'mew-complete-sort-key) + (mew-input-exit-minibuffer-function 'mew-input-sort-key-check) + (field:mode (read-from-minibuffer + (format "Sort by (%s)?: " key) + "" + mew-input-map + nil + 'mew-input-sort-key-hist)) + field mode) + (if (or (null field:mode) (string= field:mode "")) + (setq field:mode key)) + (setq field (car (mew-split field:mode ?:))) + (setq mode (or (car (cdr (mew-split field:mode ?:))) + (mew-alist-get-value (assoc field mew-sort-key-alist)) + "text")) + (list field mode))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Remote file +;;; + +(defvar mew-input-rfile-hist nil) + +(defun mew-input-rfile (prompt) ;; prompt="To:" + (mew-input-clear) + (let ((mew-input-complete-function 'mew-complete-rfile)) + (read-from-minibuffer + (concat prompt " ") + "" + mew-input-map + nil + 'mew-input-rfile-hist))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Range +;;; + +(defun mew-range-update (folder) + (when (get-buffer folder) + (with-current-buffer folder + (goto-char (point-max)) + (if (bobp) + mew-range-all ;; buffer is empty. + (forward-line -1) + (mew-summary-goto-message) + (concat (number-to-string + (1+ (string-to-number (mew-summary-message-number)))) + "-"))))) + +(defun mew-input-range (folder askp) + (let* ((default (or (car (mew-folder-spec folder mew-range-list + mew-range-list-string-type + mew-range-list-list-type)) + mew-range-str-update)) + (range default) + comp ret) + (when askp + (setq comp (mapcar 'list mew-input-range-list)) + (setq range (completing-read (format "Range (%s): " default) comp + nil nil nil nil default))) + (cond + ((string= range mew-range-str-all) + (setq ret (list mew-range-all 'erase))) + ((string= range mew-range-str-update) + (setq ret (list (mew-range-update folder) nil))) + ((string-match "^last:" range) + (setq ret (list range 'erase))) + ((or (string-match "^[0-9]+$" range) + (string-match "^[0-9]+-$" range) + (string-match "^-[0-9]+$" range) + (string-match "^[0-9]+-[0-9]+$" range)) + (setq ret (list range 'erase))) + (t + (setq ret nil))) ;; a wrong range + ret)) + +(defun mew-input-range-remote (folder) + ;; t all + ;; nil update + ;; n last: + ;; 'sync + (let* ((default (or (car (mew-folder-spec folder mew-range-list + mew-range-list-string-type + mew-range-list-list-type)))) + (comp (mapcar 'list mew-input-range-remote-list)) + (range (completing-read (format "Range (%s): " default) comp + nil nil nil nil default))) + (cond + ((string= range mew-range-str-sync) 'sync) + ((string= range mew-range-str-all) t) + ((string= range mew-range-str-update) nil) + ((string-match "^last:\\([0-9]+\\)$" range) + (string-to-number (match-string 1 range))) + (t nil)))) ;; update just in case + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Buffer +;;; + +(defun mew-input-draft-buffer (default) + (let* ((regex (mew-folder-regex (file-name-as-directory mew-draft-folder))) + (comp (mew-buffer-list regex t))) + (if (and (= (length comp) 1) + (string= default (car (car comp)))) + default + (completing-read (format "Buffer (%s): " default) comp + nil nil nil nil default)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; File +;;; + +(defun mew-input-file-name (&optional prompt default) + (let ((msg (or prompt "File: ")) + (use-dialog-box nil) + file) + (cond + ((null default) + (setq file mew-save-dir)) + ((mew-folder-absolutep default) + (setq file default)) + (t + (setq file (concat mew-save-dir default)))) + (expand-file-name (read-file-name msg file file)))) + +(defun mew-input-directory-name (&optional default) + (let ((dir (expand-file-name + (read-file-name "Directory: " default default t)))) + (if (file-directory-p dir) + dir + (mew-warn "%s is not directory" dir) + (mew-input-directory-name default)))) + +(defun mew-convert-to-home-dir (dir) + (let* ((chome (file-name-as-directory mew-home)) + (ehome (concat "^" (regexp-quote (expand-file-name chome))))) + (if (string-match ehome dir) + (concat chome (substring dir (match-end 0))) + dir))) + +(defvar mew-summary-previous-directory nil) +(defvar mew-draft-previous-directory nil) + +(defmacro mew-mode-input-file-name (prompt file preservep previous modedir) + `(let (dir ret def) + (if (and ,file (file-name-absolute-p ,file)) + (setq def (mew-convert-to-home-dir ,file)) + (if ,preservep + (setq dir (or ,previous ,modedir)) + (setq dir , modedir)) + (setq dir (and dir (file-name-as-directory dir))) + (setq def (concat dir ,file))) + (setq ret (mew-input-file-name ,prompt def)) + (if ,preservep + (setq ,previous (file-name-directory + (mew-convert-to-home-dir + (if (file-directory-p ret) + (file-name-as-directory ret) + ret))))) + (if (and ,file (file-directory-p ret)) + (setq ret (expand-file-name (file-name-nondirectory ,file) ret))) + ret)) + +(defun mew-summary-input-file-name (&optional prompt file) + (mew-mode-input-file-name prompt file mew-summary-preserve-dir + mew-summary-previous-directory mew-save-dir)) + +(defun mew-draft-input-file-name (&optional prompt file) + (mew-mode-input-file-name prompt file mew-draft-preserve-dir + mew-draft-previous-directory mew-copy-dir)) + +(defmacro mew-mode-input-directory-name (preservep previous modedir) + `(if ,preservep + (let (dir ret) + (setq dir (file-name-as-directory (or ,previous ,modedir))) + (setq ret (mew-input-directory-name dir)) + (setq ,previous (mew-convert-to-home-dir ret)) + ret) + (mew-input-directory-name default-directory))) + +(defun mew-summary-input-directory-name () + (mew-mode-input-directory-name + mew-summary-preserve-dir mew-summary-previous-directory mew-save-dir)) + +(defun mew-draft-input-directory-name () + (mew-mode-input-directory-name + mew-draft-preserve-dir mew-draft-previous-directory mew-copy-dir)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; String +;;; + +(defun mew-input-string (prompt subdir default) + (let ((input (read-string (format prompt subdir default) ""))) + (if (string= input "") default input))) + +(defun mew-input-general (prompt alist &optional require-match initial) + (let* ((completion-ignore-case t) + (question (if initial (format "%s (%s): " prompt initial) + (format "(%s): " prompt)))) + (completing-read question alist nil require-match nil nil initial))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Type +;;; + +(defun mew-input-type (prompt filename default type-list) + (let ((completion-ignore-case t)) + (completing-read (format prompt filename default) + (mapcar 'list type-list) + nil + t + "" + nil + default))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Case +;;; + +(defun mew-input-case-check () + (let ((case (mew-buffer-substring (mew-minibuf-point-min) (point-max))) + err) + (catch 'nomatch + (dolist (cs (mew-split case ?,)) + (unless (member cs mew-config-cases) + (throw 'nomatch (setq err cs))))) + (if err + (progn + (mew-temp-minibuffer-message (format " [No match: %s]" err)) + nil) + t))) + +(defvar mew-input-case-hist nil) + +(defun mew-input-case (default &optional edit) + (mew-input-clear) + (unless default (setq default mew-case-default)) + (let ((mew-input-complete-function 'mew-complete-case) + (mew-circular-complete-function 'mew-circular-complete-case) + (mew-input-exit-minibuffer-function 'mew-input-case-check) + (mew-input-comma-function 'mew-input-case-check) + case ret) + (if edit + (setq case (read-from-minibuffer + "Case value: " + default + mew-input-map + nil + 'mew-input-case-hist)) + (setq case (read-from-minibuffer + (format "Case value (%s): " default) + "" + mew-input-map + nil + 'mew-input-case-hist))) + (if (string= case "") + default + (dolist (cs (mew-split case ?,)) + (if (member cs mew-config-cases) + (setq ret (cons cs ret)))) + (mapconcat 'identity (nreverse ret) ",")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mark +;;; + +(defun mew-input-mark (&optional msg) + (let ((ociea cursor-in-echo-area) char) + (unwind-protect + (progn + (message (or msg "Input mark: ")) + (setq cursor-in-echo-area t) + (setq char (read-char)) + (unless (char-equal char ?\r) + (message "%s%c" (or msg "Input mark: ") char))) + (setq cursor-in-echo-area ociea)) + (cond + ((mew-markdb-by-mark char) char) + (t (message "Mark %c is not supported" char) + nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Encoding +;;; + +(defun mew-input-encoding () + (let* ((encoding-list (list mew-b64 mew-qp)) + (encoding-alist (mapcar (lambda (x) (list x)) encoding-list)) + (prompt (format "Lines are too long. Input encoding (%s): " + mew-default-encoding)) + (cte (completing-read prompt encoding-alist nil nil nil nil + mew-default-encoding))) + (setq cte (downcase cte)) + (while (not (member cte encoding-list)) + (setq prompt (format "'%s' is unknown. Input encoding (%s): " + cte mew-default-encoding)) + (setq cte (completing-read prompt encoding-alist nil nil nil nil + mew-default-encoding)) + (setq cte (downcase cte))) + cte)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Command +;;; + +(defun mew-input-command (&optional default) + (let ((program (read-string "Command args: " default))) + (setq program (mew-split-quoted program mew-sp)) + (setq program (delete "" program)) + (while (not (mew-which-exec (car program))) + (setq program (read-string "Command args: " default)) + (setq program (mew-split-quoted program mew-sp)) + (setq program (delete "" program))) + program)) + +(provide 'mew-minibuf) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-minibuf.el ends here diff --git a/elpa/mew-20150813.2354/mew-mule.el b/elpa/mew-20150813.2354/mew-mule.el new file mode 100644 index 00000000..aabebf38 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-mule.el @@ -0,0 +1,170 @@ +;;; mew-mule.el --- Environment of Mule common for Mew + +;; Author: Kazu Yamamoto +;; Created: Jul 15, 1998 + +;;; Code: + +;; +;; Charset +;; + +(defun mew-charset-m17n () + (if (string= mew-charset-m17n mew-utf-8) + (if mew-internal-utf-8p + mew-utf-8 + (if (condition-case nil (require 'un-define) (file-error nil)) + mew-utf-8 + mew-iso-2022-jp-2)) + mew-iso-2022-jp-2)) + +(defun mew-charset-guess-string (str) + (let ((ecsdb (mew-ecsdb-guess-string str))) + (if ecsdb + (mew-cs-to-charset (mew-ecsdb-get-cs ecsdb)) ;; not hcs, take care + (mew-charset-m17n)))) + +(defun mew-ecsdb-guess-string (str) + (with-temp-buffer + (insert str) + (mew-ecsdb-guess-region (point-min) (point-max)))) + +(defun mew-charset-guess-region (beg end) + "Guess charset for the region." + (interactive "r") + (let ((ecsdb (mew-ecsdb-guess-region beg end)) + ret) + (if (null ecsdb) + (setq ret (mew-charset-m17n)) + (setq ret (mew-cs-to-charset (mew-ecsdb-get-cs ecsdb)))) ;; not hcs + (if (mew-called-interactively-p) (message "%s" ret)) ;; for debug + ret)) + +(defun mew-ecsdb-guess-region (beg end) + (let* ((tcsl (mew-find-cs-region beg end)) + (N (length tcsl)) + (alst mew-cs-database-for-encoding) + acsl csl ret) + (dolist (ecsdb alst) + (setq acsl (mew-ecsdb-get-lcs ecsdb)) + (catch 'loop + (dotimes (i N) + (unless (member (nth i tcsl) acsl) + (setq ecsdb nil) + (setq acsl nil) + (throw 'loop nil)))) + (if (null ret) + (setq ret ecsdb) + (if (and acsl (< (length acsl) (length csl))) + (setq ret ecsdb csl acsl)))) + ret)) + +(autoload 'mew-zenkaku-katakana-region "mew-lang-jp" nil) +(autoload 'mew-latin0-region "mew-lang-latin" nil) + +(defun mew-charset-sanity-check (beg end) + "Eliminate invalid characters" + (interactive "r") + (let ((lcs (mew-find-cs-region beg end))) + (cond + ((member mew-lc-kana lcs) + (mew-zenkaku-katakana-region beg end)) + ((and (not (fboundp 'set-charset-priority)) + (memq 'latin-iso8859-1 lcs) (memq 'latin-iso8859-15 lcs)) ;; xxx + (mew-latin0-region beg end))))) + +;;; +;;; +;;; + +(defun mew-file-guess-coding-system (file) + (with-temp-buffer + (kill-local-variable 'find-file-literally) + (set-buffer-multibyte t) + (insert-file-contents file nil 0 1024) + buffer-file-coding-system)) + +(defun mew-cs-strip-lineinfo (cs) + (let ((str (symbol-name cs))) + (if (string-match "-\\(unix\\|mac\\|dos\\)$" str) + (intern (substring str 0 (match-beginning 0))) + cs))) + +;;; +;;; +;;; + +(defun mew-coding-system-equal (cs1 cs2) + ;; Emacs 22 causes an error if cs is not defined. + (condition-case nil + (coding-system-equal cs1 cs2) + (error nil))) + +(defun mew-cs-to-charset (cs) + (let ((dcsdb (mew-assoc-equal cs mew-cs-database-for-decoding 1 'mew-coding-system-equal))) + (if (null dcsdb) + (mew-charset-m17n) + (mew-dcsdb-get-charset dcsdb)))) + +(defun mew-charset-to-cs (charset) + (when charset + (let ((dcsdb (assoc (downcase charset) mew-cs-database-for-decoding))) + (if (null dcsdb) + mew-cs-unknown + (mew-dcsdb-get-cs dcsdb))))) + +(defun mew-charset-to-ecsdb (charset) + (mew-assoc-equal (mew-charset-to-cs charset) mew-cs-database-for-encoding 1)) + +(defun mew-charset-to-cte (charset) + (mew-ecsdb-get-cte (mew-charset-to-ecsdb charset))) + +(defun mew-charset-to-delsp (charset) + (mew-ecsdb-get-delsp (mew-charset-to-ecsdb charset))) + +;; + +(defvar mew-charset-list + (mapcar 'mew-dcsdb-get-charset mew-cs-database-for-decoding)) + +;; + +(defun mew-cs-encode-arg (arg) + (let ((cs (mew-ecsdb-cs-for-arg (mew-ecsdb-guess-string arg)))) + (if (mew-coding-system-p cs) + (mew-cs-encode-string arg cs) + arg))) + +(provide 'mew-mule) + +;;; Copyright Notice: + +;; Copyright (C) 1998-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-mule.el ends here diff --git a/elpa/mew-20150813.2354/mew-mule3.el b/elpa/mew-20150813.2354/mew-mule3.el new file mode 100644 index 00000000..528c5b37 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-mule3.el @@ -0,0 +1,422 @@ +;;; mew-mule3.el --- Environment of Mule version 3 for Mew + +;; Author: Kazu Yamamoto +;; Created: Mar 20, 1997 + +;;; Code: + +(eval-when-compile + (mew-no-warning-defun charset-priority-list)) + +;; must be here +(if (fboundp 'find-coding-system) + (defun mew-coding-system-p (cs) + (if (null cs) t (find-coding-system cs))) + (defun mew-coding-system-p (cs) + (if (null cs) t (coding-system-p cs)))) + +;; In the context of Mew, 'charset' means MIME charset. +;; 'cs' means the internal representation of Emacs (was known as Mule). + +;; +;; User CS definitions +;; + +;; iso-2022-7bit-ss2 is iso-2022-jp-2 + +(define-coding-system-alias 'mew-cs-text 'raw-text) +(define-coding-system-alias 'mew-cs-text-lf 'raw-text-unix) +(define-coding-system-alias 'mew-cs-text-crlf 'raw-text-dos) +(define-coding-system-alias 'mew-cs-text-cr 'raw-text-mac) +(define-coding-system-alias 'mew-cs-text-net 'raw-text-dos) +(defun mew-cs-raw-p (cs) + (memq cs '(raw-text raw-text-unix raw-text-dos raw-text-mac))) + +(defvar mew-cs-dummy 'binary) +(defvar mew-cs-binary 'binary) +(defvar mew-cs-text-for-read 'mew-cs-text) +(defvar mew-cs-text-for-write 'mew-cs-text-lf) +(defvar mew-cs-text-for-net 'mew-cs-text-net) +(defvar mew-cs-autoconv 'undecided) +;; xxx should be utf-8-unix someday. +(defvar mew-cs-m17n (if (mew-coding-system-p 'ctext-unix) 'ctext-unix 'ctext)) +(defvar mew-cs-utf-16be + (cond + ((mew-coding-system-p 'utf-16-be-no-signature) 'utf-16-be-no-signature) + ((mew-coding-system-p 'utf-16be) 'utf-16be) + (t nil))) + +(defvar mew-cs-eol "\n") +(defun mew-eol-fix-for-read () ()) +(defun mew-eol-fix-for-write () ()) + +;; Latin 0 -- Nickname of Latin 9 +;; Latin 1 -- ISO-8859-1 West European +;; Latin 2 -- ISO-8859-2 East European +;; Latin 3 -- ISO-8859-3 South European +;; Latin 4 -- ISO-8859-4 North European +;; Latin 5 -- ISO-8859-9 Turkish +;; Latin 6 -- ISO-8859-10 Nordic +;; Latin 7 -- ISO-8859-13 Baltic Rim +;; Latin 8 -- ISO-8859-14 Celtic +;; Latin 9 -- ISO-5589-15 New West European + +;; ISO-8859-1 -- Latin 1 West European +;; ISO-8859-2 -- Latin 2 East European +;; ISO-8859-3 -- Latin 3 South European +;; ISO-8859-4 -- Latin 4 North European +;; ISO-8859-5 -- Cyrillic +;; ISO-8859-6 -- Arabic +;; ISO-8859-7 -- Greek +;; ISO-8859-8 -- Hebrew +;; ISO-8859-9 -- Latin 5 Turkish +;; ISO-8859-10 -- Latin 6 Nordic +;; ISO-8859-11 -- Thai +;; ISO-8859-12 -- +;; ISO-8859-13 -- Latin 7 Baltic Rim +;; ISO-8859-14 -- Latin 8 Celtic +;; ISO-8859-15 -- Latin 9 New West European (or Latin 0) + +(defvar mew-charset-utf-8-encoding "base64") +(defvar mew-charset-utf-8-header-encoding "B") + +(mew-defstruct ecsdb lcs cs cte b-or-q delsp) + +(defun mew-ecsdb-hcs (ecsdb) + (mew-ecsdb-get-cs ecsdb)) + +(defvar mew-cs-database-for-encoding + `(((ascii) nil "7bit" "7bit" nil) + ;; West European (Latin 1) + ((ascii latin-iso8859-1) iso-8859-1 "quoted-printable" "Q" nil) + ;; East European (Latin 2) + ((ascii latin-iso8859-2) iso-8859-2 "quoted-printable" "Q" nil) + ;; South European (Latin 3) + ((ascii latin-iso8859-3) iso-8859-3 "quoted-printable" "Q" nil) + ;; North European (Latin 4) + ((ascii latin-iso8859-4) iso-8859-4 "quoted-printable" "Q" nil) + ;; Cyrillic + ((ascii cyrillic-iso8859-5) koi8-r "quoted-printable" "Q" nil) + ;; Arabic + ((ascii arabic-iso8859-6) iso-8859-6 "base64" "B" t) + ;; Greek + ((ascii greek-iso8859-7) iso-8859-7 "base64" "B" t) + ;; Hebrew + ((ascii hebrew-iso8859-8) iso-8859-8 "base64" "B" t) + ;; Turkish (Latin 5) + ((ascii latin-iso8859-9) iso-8859-9 "quoted-printable" "Q" nil) + ;; Celtic (Latin 8) + ((ascii latin-iso8859-14) iso-8859-14 "quoted-printable" "Q" nil) ;; xxx + ;; New West European (Latin 9 or Latin 0) + ((ascii latin-iso8859-15) iso-8859-15 "quoted-printable" "Q" nil) + ((ascii thai-tis620) tis-620 "base64" "B" t) + ((ascii latin-jisx0201 japanese-jisx0208 japanese-jisx0208-1978) + iso-2022-jp "7bit" "B" t) + ((ascii korean-ksc5601) euc-kr "8bit" "B" t) + ((ascii chinese-gbk) gbk "base64" "B" t) + ((ascii chinese-gb2312) cn-gb-2312 "base64" "B" t) + ((ascii chinese-big5-1 chinese-big5-2) + chinese-big5 "base64" "B" t) +;; ((ascii japanese-jisx0208 japanese-jisx0213-1 japanese-jisx0213-2) +;; iso-2022-jp-3 "7bit" "B" t) + (nil utf-7 "7bit" "Q" t) ;; xxx + (nil utf-8 ,mew-charset-utf-8-encoding ,mew-charset-utf-8-header-encoding t) + (nil iso-2022-jp-2 "7bit" "B" t))) + +(defvar mew-cs-database-for-arg + '((iso-2022-jp . euc-jp) + (iso-2022-kr . euc-kr))) + +(defun mew-ecsdb-cs-for-arg (ecsdb) + (let* ((cs (mew-ecsdb-get-cs ecsdb)) + (acs (cdr (assoc cs mew-cs-database-for-arg)))) + (or acs cs))) + +(if (and (not (mew-coding-system-p 'chinese-big5)) + (mew-coding-system-p 'big5)) + (define-coding-system-alias 'chinese-big5 'big5)) + +(mew-defstruct dcsdb charset cs) + +(defvar mew-cs-database-for-decoding + `(("us-ascii" nil) + ("iso-8859-1" iso-8859-1) + ("iso-8859-2" iso-8859-2) + ("iso-8859-3" iso-8859-3) + ("iso-8859-4" iso-8859-4) + ("iso-8859-5" iso-8859-5) + ("iso-8859-6" iso-8859-6) + ("iso-8859-7" iso-8859-7) + ("iso-8859-8" iso-8859-8) + ("iso-8859-8-i" iso-8859-8) ;; temporary solution + ("iso-8859-9" iso-8859-9) + ("iso-8859-15" iso-8859-15) + ("iso-2022-cn" iso-2022-cn) + ("iso-2022-cn-ext" iso-2022-cn-ext) + ("gbk" gbk) + ("gb2312" cn-gb-2312) ;; should be before cn-gb + ("cn-gb" cn-gb-2312) + ("hz-gb-2312" hz-gb-2312) + ("big5" chinese-big5) + ("cn-big5" chinese-big5) + ("iso-2022-kr" iso-2022-kr) + ("euc-kr" euc-kr) + ("ks_c_5601-1987" euc-kr) + ("iso-2022-jp" iso-2022-jp) + ("iso-2022-jp-2" iso-2022-jp-2) + ("iso-2022-jp-3" iso-2022-jp-3) + ("euc-jp" euc-japan) + ("shift_jis" shift_jis) + ("windows-31j" cp932) + ("tis-620" tis-620) + ("koi8-r" koi8-r) + ("iso-2022-int-1" iso-2022-int-1) + ("utf-7" utf-7) + ("unicode-1-1-utf-7" utf-7) ;; the old UTF-7 name, RFC 1642 + ("utf-8" utf-8) + ,@(if (mew-coding-system-p 'windows-1251) + '(("windows-1250" windows-1250) + ("windows-1251" windows-1251) + ("windows-1252" windows-1252) + ("windows-1253" windows-1253) + ("windows-1254" windows-1254) + ("windows-1255" windows-1255) + ("windows-1256" windows-1256) + ("windows-1257" windows-1257) + ("windows-1258" windows-1258)) + '(("windows-1250" cp1250) + ("windows-1251" cp1251) + ("windows-1252" cp1252) + ("windows-1253" cp1253) + ("windows-1254" cp1254) + ("windows-1255" cp1255) + ("windows-1256" cp1256) + ("windows-1257" cp1257) + ("windows-1258" cp1258))))) + +;; +;; CS +;; + +(defvar mew-charset-priority-list '(japanese-jisx0208 + korean-ksc5601 + latin-iso8859-2 + latin-iso8859-3 + latin-iso8859-4 + hebrew-iso8859-8 + latin-iso8859-9 + ;; for accent characters + cyrillic-iso8859-5 + greek-iso8859-7 + latin-iso8859-14 + thai-tis620 + latin-jisx0201 + japanese-jisx0208-1978 + japanese-jisx0213-1 + japanese-jisx0213-2 + katakana-jisx0201 + unicode)) + +(if (fboundp 'set-charset-priority) + (defun mew-find-cs-region (beg end) + (let ((charset-list (charset-priority-list)) + ret) + (catch 'find + (set-charset-priority 'latin-iso8859-1) + (setq ret (find-charset-region beg end)) + (if (equal ret '(ascii latin-iso8859-1)) + (throw 'find nil)) + ;; + (set-charset-priority 'latin-iso8859-15) + (setq ret (find-charset-region beg end)) + (if (equal ret '(ascii latin-iso8859-15)) + (throw 'find nil)) + ;; + (set-charset-priority 'cyrillic-iso8859-5) + (setq ret (find-charset-region beg end)) + (if (equal ret '(ascii cyrillic-iso8859-5)) + (throw 'find nil)) + ;; + (set-charset-priority 'greek-iso8859-7) + (setq ret (find-charset-region beg end)) + (if (equal ret '(ascii greek-iso8859-7)) + (throw 'find nil)) + ;; + (apply 'set-charset-priority mew-charset-priority-list) + (setq ret (find-charset-region beg end))) + (apply 'set-charset-priority charset-list) + ret)) + (defalias 'mew-find-cs-region 'find-charset-region)) + +;; to internal +(defun mew-cs-decode-region (beg end cs) + (if cs (decode-coding-region beg end cs))) + +;; to external +(defun mew-cs-encode-region (beg end cs) + (if cs (encode-coding-region beg end cs))) + +;; to internal +(defun mew-cs-decode-string (str cs) + (if cs (decode-coding-string str cs) str)) + +;; to external +(defun mew-cs-encode-string (str cs) + (if cs (encode-coding-string str cs) str)) + +;; +;; Process environment +;; + +(defun mew-set-process-cs (process read write) + (set-process-coding-system process read write)) + +(defun mew-set-buffer-cs (write) + (setq buffer-file-coding-system write)) + +(defmacro mew-plet (&rest body) + `(let ((coding-system-for-read 'binary) + (coding-system-for-write 'binary)) + ,@body)) + +(defmacro mew-piolet (read write &rest body) + ;; (declare (indent 2)) + `(let ((coding-system-for-read ,read) + (coding-system-for-write ,write)) + ,@body)) +(put 'mew-piolet 'lisp-indent-function 2) + +(defmacro mew-flet (&rest body) + `(let ((coding-system-for-read 'binary) + (coding-system-for-write 'binary) + (format-alist nil) + (auto-image-file-mode nil) + (jka-compr-inhibit t)) + ,@body)) + +(defmacro mew-frwlet (read write &rest body) + ;; (declare (indent 2)) + `(let ((coding-system-for-read ,read) + (coding-system-for-write ,write) + (format-alist nil) + (auto-image-file-mode nil) + (jka-compr-inhibit t)) + ,@body)) +(put 'mew-frwlet 'lisp-indent-function 2) + +(defmacro mew-alet (&rest body) + `(let ((default-file-name-coding-system nil) + (file-name-coding-system nil)) + ,@body)) + +;; +;; +;; + +(defun mew-substring (str width &optional cnt nopad) + (let ((sw (if (null str) 0 (string-width str))) + (i 0) (w 0) cw wid) + (condition-case nil + (cond + ((= sw width) + str) + ((< sw width) + (if nopad + str + (concat str (make-string (- width sw) mew-sp)))) + (t + (if cnt (setq width (- width 2))) + (catch 'loop + (while t + (setq cw (char-width (aref str i))) + (if (get-text-property i 'composition str) ;; for Emacs 21 + (setq i (1+ i))) + (if (> (+ w cw) width) + (throw 'loop t)) + (setq w (+ w cw)) + (setq i (+ i 1)))) + (cond + ((= w width) + (if cnt + (concat (substring str 0 i) "..") + (substring str 0 i))) + (t + (setq wid (- width w)) + (if cnt + (concat (substring str 0 i) (make-string wid mew-sp) "..") + (concat (substring str 0 i) (make-string wid mew-sp))))))) + (error + (if (> (length mew-error-broken-string) width) + (substring mew-error-broken-string 0 width) + mew-error-broken-string))))) + +;; +;; Language specific +;; + +(defvar mew-lc-kana 'katakana-jisx0201) +(defvar mew-lc-jp 'japanese-jisx0208) + +;; +;; Stolen from mule-cmd.el +;; + +(defun mew-coding-category-list () coding-category-list) +(defun mew-coding-category-system (cat) (eval cat)) + +(defun mew-reset-coding-systems (priority categories) + (let ((rest-ctgs categories)) + (dolist (pri priority) + (set (car rest-ctgs) pri) + (setq rest-ctgs (cdr rest-ctgs))) + (if (fboundp 'update-coding-systems-internal) + (update-coding-systems-internal)) + (mew-set-coding-priority categories))) + +(defun mew-set-language-environment-coding-systems (language-name) + (let ((priority (get-language-info language-name 'coding-priority))) + (when priority + (let* ((categories (mapcar 'coding-system-category priority)) + (orig-ctg (mew-coding-category-list)) + (orig-pri (mapcar 'mew-coding-category-system orig-ctg))) + (mew-reset-coding-systems priority categories) + (cons orig-pri orig-ctg))))) + +;; +;; +;; + +(require 'mew-mule) +(provide 'mew-mule3) + +;;; Copyright Notice: + +;; Copyright (C) 1997-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-mule3.el ends here diff --git a/elpa/mew-20150813.2354/mew-net.el b/elpa/mew-20150813.2354/mew-net.el new file mode 100644 index 00000000..03d2464f --- /dev/null +++ b/elpa/mew-20150813.2354/mew-net.el @@ -0,0 +1,911 @@ +;;; mew-net.el + +;; Author: Kazu Yamamoto +;; Created: Feb 27, 2002 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Port DB +;;; + +(defvar mew-port-db + '(("smtp" 25) + ;; This is officially assigned to another service (urd) by IANA. + ;; IESG will never assign a port number to SMTP over SSL... + ("smtps" 465) + ("pop3" 110) + ("pop3s" 995) + ("nntp" 119) + ("nntps" 563) + ("imap" 143) + ("imaps" 993) + ("submission" 587))) + +(defun mew-serv-to-port (serv) + (cond + ((integerp serv) serv) + ((string-match "^[0-9]+$" serv) + (string-to-number serv)) + (t + (or (mew-alist-get-value (assoc serv mew-port-db)) 0)))) + +(defun mew-*-to-port (port) + (cond + ((integerp port) port) + ((string-match "^[0-9]+$" port) + (string-to-number port)) + (t port))) + +(defun mew-*-to-string (any) + (cond + ((integerp any) + (number-to-string any)) + (t any))) + +(defun mew-port-equal (port1 port2) + (string= (mew-*-to-string port1) (mew-*-to-string port2))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Net folders +;;; + +(defvar mew-pop-folder "+#pop/%s@%s#%s") +(defvar mew-imap-folder "+#imap/%s@%s#%s") +(defvar mew-nntp-folder "+#nntp/%s@%s#%s") + +(defun mew-pop-folder (&optional case) + (format mew-pop-folder + (mew-pop-user case) (mew-pop-server case) (mew-pop-port case))) + +(defun mew-imap-folder (&optional case) + (format mew-imap-folder + (mew-imap-user case) (mew-imap-server case) (mew-imap-port case))) + +(defun mew-nntp-folder (&optional case) + (format mew-nntp-folder + (or (mew-nntp-user case) "") ;; a user may be nil + (mew-nntp-server case) (mew-nntp-port case))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Net status +;;; + +(defun mew-summary-lock (key status &optional secure) + (setq mew-summary-buffer-process key) + (setq mew-summary-buffer-process-status (format " %s" status)) + (setq mew-summary-buffer-secure-process secure)) + + +(defun mew-summary-unlock () + (setq mew-summary-buffer-process nil) + (setq mew-summary-buffer-process-status nil) + (setq mew-summary-buffer-secure-process nil) + (force-mode-line-update)) + +(defun mew-net-status-clear (buf) + (when (and mew-use-net-status buf (get-buffer buf)) + (with-current-buffer buf + (setq mew-summary-buffer-process-status nil) + (setq mew-summary-buffer-secure-process nil)))) + +(defun mew-net-status (buf status &optional substatus secure) + (when mew-use-net-status + (with-current-buffer buf + (if substatus + (setq mew-summary-buffer-process-status + (format " %s:%s" status substatus)) + (setq mew-summary-buffer-process-status (format " %s" status))) + (setq mew-summary-buffer-secure-process secure)))) + +(defun mew-net-status1 (buf msg ttl cnt &optional secure) + (when mew-use-net-status + (when (<= cnt ttl) + (let ((substatus (format "%02d%%" (/ (* cnt 100) ttl)))) + (mew-net-status buf msg substatus secure))))) + +(defvar mew-net-status-percent-size 51200) + +(defun mew-net-status2 (buf rttl rcnt siz &optional zero secure) + (when mew-use-net-status + (when (<= rcnt rttl) + (let ((msiz (string-to-number siz)) + (bsiz (if zero 0 (buffer-size))) + percent substatus) + (if (and (integerp mew-net-status-percent-size) + (< msiz mew-net-status-percent-size)) + (progn + (setq substatus (format "%d/%d" rcnt rttl)) + (mew-net-status buf "Retrieving" substatus secure)) + (if (= msiz 0) (setq msiz 1)) + (if (< 10000 msiz) + (setq percent (/ bsiz (/ msiz 100))) + (setq percent (/ (* bsiz 100) msiz))) + (setq substatus (format "%d/%d:%02d%%" rcnt rttl percent)) + (mew-net-status buf "Retrieving" substatus secure)))))) + +(defvar mew-local-status-unit 10) +(defvar mew-local-status-threshold 100) + +(defun mew-net-status3 (buf rttl rcnt) + (when mew-use-net-status + (if rttl + (if (or (not (integerp mew-local-status-unit)) + (not (integerp mew-local-status-threshold)) + (< (- rttl rcnt) mew-local-status-threshold) + (= 0 (% rcnt mew-local-status-unit))) + (mew-net-status buf "Scanning" (format "%d/%d" rcnt rttl))) + (mew-net-status buf "Scanning" (format "%d" rcnt))))) + +(defun mew-summary-visible-buffer (buf) + (with-current-buffer buf + (mew-elet (put-text-property (point-min) (point-max) 'invisible nil)) + (setq mew-summary-buffer-raw t) + (if (eq (get-buffer-window buf) (selected-window)) + (mew-summary-cook-window)) + (set-buffer-modified-p nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Biff +;;; + +(defvar mew-biff-string nil) +(defvar mew-biff-timer-id nil) + +(defun mew-biff-bark (n) + (if (= n 0) + (setq mew-biff-string nil) + (if (and mew-use-biff-bell (eq mew-biff-string nil)) + (beep)) + (setq mew-biff-string (format "Mail(%d)" n)))) + +(defun mew-biff-clear () + (setq mew-biff-string nil)) + +(defun mew-biff-setup () + (let ((inbox (mew-proto-inbox-folder nil mew-case)) + func) + (if (not mew-use-biff) + (mew-biff-clean-up) + (if mew-biff-timer-id (cancel-timer mew-biff-timer-id)) + (cond + ((mew-folder-localp inbox) + (setq func 'mew-pop-biff)) + ((mew-folder-popp inbox) + (setq func 'mew-pop-biff)) + ((mew-folder-imapp inbox) + (setq func 'mew-imap-biff))) + (if func + (setq mew-biff-timer-id (mew-timer (* 60 mew-biff-interval) func))))) + (let ((ent '(mew-biff-string mew-biff-string))) + (unless (member ent global-mode-string) + (if global-mode-string + (setq global-mode-string + (append global-mode-string (list "" ent))) + (setq global-mode-string (list ent)))))) + +(defun mew-biff-clean-up () + (if mew-biff-timer-id (cancel-timer mew-biff-timer-id)) + (setq mew-biff-timer-id nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Keep time +;;; + +(defun mew-time-diff (t1 t2) + (/ (+ (* (- (nth 0 t2) (nth 0 t1)) 65536) + (- (nth 1 t2) (nth 1 t1))) + 86400.0)) ;; one day (* 60 60 24) + +(defun mew-expired-p (time keep) + (cond + ((and (consp keep) + (stringp (nth 0 keep)) (file-exists-p (nth 0 keep)) + (integerp (nth 1 keep))) + (if (>= (mew-time-diff time (mew-file-get-time (nth 0 keep))) (nth 1 keep)) + t)) + ((integerp keep) + (if (>= (mew-time-diff time (current-time)) keep) t)) + ;; ((eq keep t) t) + ;; This case MUST not be included because messages marked with 'T' + ;; will be deleted. + (t nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; UIDL +;;; + +(defvar mew-net-uidl-file ".mew-uidl") +(defvar mew-net-uidl-db nil) + +(defun mew-net-uidl-db-get (tag) + (cdr (assoc tag mew-net-uidl-db))) + +(defun mew-net-uidl-db-set (tag uidl) + (let* ((ent (assoc tag mew-net-uidl-db))) + (if ent + (setcdr ent uidl) + (setq mew-net-uidl-db (cons (cons tag uidl) mew-net-uidl-db))) + (mew-lisp-save mew-net-uidl-file mew-net-uidl-db nil 'unlimit))) + +(defun mew-net-setup () + (setq mew-net-uidl-db (mew-lisp-load mew-net-uidl-file)) + (add-hook 'kill-emacs-hook 'mew-net-clean-up)) + +(defun mew-net-clean-up () + (remove-hook 'kill-emacs-hook 'mew-net-clean-up) + (mew-lisp-save mew-net-uidl-file mew-net-uidl-db nil 'unlimit)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; New message +;;; + +(defun mew-net-get-new-message (pnm bnm msg get set) + (if msg + (cons msg (mew-expand-msg bnm msg)) ;; 'get + (let ((msg (funcall get pnm)) + file nxt) + (cond + (msg + (setq nxt (number-to-string (1+ (string-to-number msg)))) + (funcall set pnm nxt) + (setq file (mew-expand-new-msg bnm msg))) + (t + (setq file (mew-folder-new-message bnm)) + ;; 1.eml => 1 + (setq msg (file-name-sans-extension (file-name-nondirectory file))) + (setq nxt (number-to-string (1+ (string-to-number msg)))) + (funcall set pnm nxt))) + (cons msg file)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Queue +;;; + +(defun mew-queue-check-new-message (file) + (if (not (file-exists-p (concat file mew-queue-work-suffix))) + file + (let* ((dir (file-name-directory file)) + ;; 1.eml => 1 + (num (file-name-sans-extension (file-name-nondirectory file))) + (n (1+ (string-to-number num)))) + (while (or (file-exists-p (format "%s%d" dir n)) + (file-exists-p (format "%s%d%s" dir n mew-queue-work-suffix))) + (setq n (1+ n))) + (format "%s%d" dir n)))) + +(defun mew-queue-enqueue (work qfld) ;; 1.wrk or draft/1 + (let (orig info iwrk) + (if (not (string-match (concat mew-queue-work-suffix "$") work)) + ;; draft/1 + (setq orig (mew-queue-check-new-message (mew-folder-new-message qfld))) + ;; 1.wrk + (setq orig (file-name-sans-extension work)) ;; 1 + (setq iwrk (concat orig mew-queue-info-suffix mew-queue-work-suffix)) + (mew-delete-file iwrk) ;; 1.mqi.wrk + (if (file-exists-p orig) + (setq orig (mew-queue-check-new-message (mew-folder-new-message qfld))))) + (rename-file work orig) ;; An error is signaled if orig exists. + (unless mew-use-nfs-hack + ;; This cause an error when using NFS. + (mew-set-file-modes orig)) + (setq info (concat orig mew-queue-info-suffix)) + (list orig info))) + +(defun mew-queue-enqueue2 (work) ;; 1.wrk + (let* ((dir (file-name-directory work)) + (orig (file-name-sans-extension work)) ;; 1 + (info (concat orig mew-imapq-info-suffix)) ;; 1.iqi + (iwrk (concat info mew-queue-work-suffix))) ;; 1.iqi.wrk + (when (file-exists-p orig) + (setq orig (mew-queue-check-new-message (mew-folder-new-message dir))) + (setq info (concat orig mew-imapq-info-suffix))) + (rename-file work orig) ;; An error is signaled if orig exists. + (rename-file iwrk info 'override))) + +(defun mew-queue-insert-file (pnm n qfld msg) ;; 1 + (let* ((file (mew-expand-new-msg qfld msg)) + (work (concat file mew-queue-work-suffix)) ;; 1.wrk + (info (concat file mew-queue-info-suffix)) ;; 1.mqi + (iwrk (concat info mew-queue-work-suffix)) ;; 1.mqi.wrk + buf data) + (when (and (file-readable-p file) (file-readable-p info)) + (rename-file file work 'override) + ;; If an old buffer exists by accident, we MUST remove the buffer. + (if (setq buf (get-file-buffer work)) (mew-remove-buffer buf)) + (mew-frwlet mew-cs-text-for-read mew-cs-dummy + (set-buffer (mew-find-file-noselect work))) + (setq data (mew-lisp-load info)) + (dotimes (i n) + (aset (mew-info pnm) i (aref data i))) + (rename-file info iwrk 'override) + t))) + +(defun mew-queue-get-next (pnm qfld msgs n func) + (let (flushp) + (catch 'loop + (dolist (msg msgs) + (if (mew-queue-insert-file pnm n qfld msg) + (throw 'loop (setq flushp t))))) + (if (fboundp func) (funcall func pnm msgs)) ;; set-messages + flushp)) + +(defun mew-queue-backup (work info-suffix) ;; 1.wrk + (let* ((orig (file-name-sans-extension work)) ;; 1 + (back (mew-prepend-prefix orig mew-backup-prefix)) ;; #1 + (info (concat orig info-suffix)) ;; 1.sfx + (iwrk (concat info mew-queue-work-suffix)) ;; 1.sfx.wrk + (ibck (mew-prepend-prefix info mew-backup-prefix))) ;; #1.sfx + (if (file-exists-p work) (rename-file work back 'override)) + (if (file-exists-p iwrk) (rename-file iwrk ibck 'override)) + back)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Fcc: +;;; + +(defun mew-net-fcc-message (case fcc file) + (let (flds fcc-file link fld imapp) + (dolist (fc fcc) + (if (mew-folder-imapp fc) + (progn + (setq flds (cons (mew-folder-imap-to-fcc case fc) flds)) + (setq imapp t)) + (setq flds (cons fc flds)))) + (catch 'loop + (while flds ;; cannot use dolist + (setq fld (car flds)) + (mew-local-folder-check fld) + (setq flds (cdr flds)) + (setq fcc-file (mew-folder-new-message fld)) + (when fcc-file + (copy-file file fcc-file) + (mew-set-file-modes fcc-file) + (mew-touch-folder fld) + (throw 'loop nil)))) + (dolist (fld flds) + (mew-local-folder-check fld) + (setq link (mew-folder-new-message fld)) + (when link + (mew-link fcc-file link) + (mew-touch-folder fld))) + imapp)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Syncing +;;; + +(defun mew-net-folder-sync (bnm hlds) + (let (uid msg ulks new-hlds) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (setq uid (mew-summary-message-uid)) + (if (setq new-hlds (member uid hlds)) + (progn + (setq hlds (cdr new-hlds)) + (forward-line)) + (setq msg (mew-summary-message-number)) + (setq ulks (cons msg ulks)) + (mew-mark-kill-line)))) + (when ulks + (setq ulks (nreverse ulks)) + (let ((mew-trash-folder nil)) + (mew-mark-exec-delete bnm ulks)) + (mew-summary-folder-cache-save)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Cleaning +;;; + +;; See also mew-summary-folder-cache-clean. +(defun mew-net-folder-clean () + (let* ((bnm (mew-summary-folder-name 'ext)) + (dir (mew-expand-folder bnm)) + (msgs (mew-dir-messages dir mew-regex-message-files3))) + (mew-summary-unlink-msgs bnm msgs) + (mew-erase-buffer) + (setq mew-summary-buffer-raw nil) + (mew-summary-folder-cache-save))) + +(defun mew-net-invalid-cache-start () + (save-excursion + (goto-char (point-min)) + (when (re-search-forward mew-regex-sumsyn-invalid nil t) + (beginning-of-line) + (point)))) + +(defun mew-net-invalid-cache-invisible () + (let ((beg (mew-net-invalid-cache-start))) + (when beg + (mew-elet + (put-text-property beg (point-max) 'invisible t))))) + +(defun mew-net-invalid-cache-clean () + (let* ((bnm (mew-summary-folder-name 'ext)) + (dir (mew-expand-folder bnm)) + (msgs (mew-dir-messages dir mew-regex-message-files4))) + (mew-summary-unlink-msgs bnm msgs) + (mew-mark-kill-invisible) + (mew-summary-folder-cache-save))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Retrieving messages +;;; + +(defun mew-summary-retrieve-gap (folder) + (when (mew-summary-folder-dir-newp) + (goto-char (point-max)) + (let ((range (mew-range-update folder))) + (mew-local-retrieve 'scan folder range) + (mew-rendezvous mew-summary-buffer-process)))) + +(defun mew-summary-case-proto () + (let (case:folder case proto) + (cond + ((mew-virtual-for-one-summary) + (setq case:folder (mew-summary-physical-folder)) + (setq case (or (mew-case:folder-case case:folder) + mew-case)) + (setq proto (mew-folder-prefix (mew-case:folder-folder case:folder)))) + ((mew-virtual-p) + (setq case (or mew-case mew-case-default)) + (setq proto (mew-proto case))) + (t ;; Summary + (setq case (or (mew-sinfo-get-case) ;; remote + mew-case)) ;; local + (setq proto (mew-folder-prefix (mew-sinfo-get-folder))))) + (list case proto))) + +(defun mew-summary-retrieve (&optional no-flush) + "In local folders, retrieve messages to +inbox asynchronously +according to 'mew-mailbox-type' and 'mew-case'. +If 'mew-auto-flush-queue' is non-nil, +queue is flushed. +If called with '\\[universal-argument]', +queue is not flushed. + +In remote folders, visit an inbox folder and scan with 'update." + (interactive "P") + (let (case proto inbox case:inbox mailbox) + (mew-set '(case proto) (mew-summary-case-proto)) + (setq inbox (mew-proto-inbox-folder proto case)) + (cond + ((mew-folder-remotep proto) + (setq case:inbox (mew-case-folder case inbox))) + (t ;; local + (setq case:inbox inbox))) + ;; for mew-summary-exchange-point. + (mew-sinfo-set-ret-pos (point)) + (mew-summary-visit-folder case:inbox) + ;; in the inbox + (when (mew-summary-exclusive-p) + (cond + ((mew-folder-remotep inbox) + (mew-summary-ls nil 'goend 'update)) + (t ;; local + ;; + (mew-summary-reset) + (mew-summary-retrieve-gap inbox) + ;; + (goto-char (point-max)) + (mew-sinfo-set-start-point (point)) + (mew-sinfo-set-direction 'down) + (setq mailbox (mew-mailbox-type case)) + (cond + ((eq mailbox 'pop) + (mew-pop-retrieve case 'inc inbox (not no-flush))) + ((eq mailbox 'imap) + (mew-imap-retrieve case 'inc inbox (not no-flush))) + ((eq mailbox 'mbox) + (mew-mbox-retrieve case 'inc inbox (not no-flush))))))))) + +(defun mew-summary-scan-boot (proto case) + ;; called by mew() + (let* ((inbox (mew-proto-inbox-folder proto case)) + (case:inbox (mew-case-folder case inbox)) + (dir (mew-expand-folder case:inbox)) + mailbox) + (unless (file-directory-p dir) + (mew-make-directory dir)) + (mew-summary-switch-to-folder case:inbox) + ;; in the inbox + ;; for mew-summary-exchange-point. + (mew-sinfo-set-ret-pos (point)) + (when (mew-summary-exclusive-p) + (mew-summary-reset) + ;; + (if (mew-folder-localp inbox) (mew-summary-retrieve-gap case:inbox)) + ;; + (goto-char (point-max)) + (mew-sinfo-set-start-point (point)) + (mew-sinfo-set-direction 'down) + (cond + ((mew-folder-localp inbox) + (setq mailbox (mew-mailbox-type case)) + (cond + ((eq mailbox 'pop) + (mew-pop-retrieve case 'inc inbox)) + ((eq mailbox 'imap) + (mew-imap-retrieve case 'inc inbox)) + ((eq mailbox 'mbox) + (mew-mbox-retrieve case 'inc inbox)))) + ((mew-folder-popp inbox) + (let ((get-body (if (mew-pop-header-only case) nil t))) + (mew-pop-retrieve case 'scan case:inbox nil get-body))) + ((mew-folder-imapp inbox) + (let ((get-body (if (mew-imap-header-only case) nil t))) + (mew-imap-retrieve case 'scan case:inbox nil get-body))) + ((mew-folder-nntpp inbox) + (let ((get-body (if (mew-nntp-header-only case) nil t))) + (mew-nntp-retrieve case 'scan case:inbox nil get-body))))))) + +(defun mew-mbox-retrieve (case directive inbox &optional flush) + ;; directive is 'inc + (let* ((mbox-command (mew-mbox-command case)) + (mbox-command-arg (mew-mbox-command-arg case)) + dir mode opts) + (if (not (mew-which-exec mbox-command)) + (message "'%s' not found!" mbox-command) + (if mbox-command-arg + (if (not (string= mbox-command "incm")) + (setq opts (list "-e" mbox-command "-m" mbox-command-arg)) + (setq dir (mew-expand-folder inbox)) + (setq mode (mew-get-file-modes dir)) + (if mew-use-suffix + (setq opts (list "-e" mbox-command + "-m" (format "%s -o -p %d" mbox-command-arg mode))) + (setq opts (list "-e" mbox-command + "-m" (format "%s -p %d" mbox-command-arg mode))))) + (setq opts (list "-e" mbox-command))) + (mew-local-retrieve 'inc inbox flush opts)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Retrieving truncated messages +;;; + +(defun mew-summary-get-inherit-case (fld msg) + (let ((buf (mew-cache-hit fld msg)) + uid) + (if buf + (with-current-buffer buf + (setq uid (mew-header-get-value mew-x-mew-uidl:))) + (with-temp-buffer + (mew-insert-message fld msg mew-cs-text-for-read mew-header-reasonable-size) + (setq uid (mew-header-get-value mew-x-mew-uidl:)))) + (mew-scan-uid-case uid))) + +(mew-defstruct net-virtual-info virtual summary msgs threadp) + +(defun mew-net-virtual-info (msgs) + (mew-make-net-virtual-info :virtual (mew-summary-folder-name 'ext) + :summary (mew-summary-folder-name) + :msgs msgs + :threadp (mew-thread-p))) + +(mew-defstruct net-disp-info list fid buf fld msg) + +(defun mew-net-disp-info () + (let* ((fid (mew-frame-id)) + (buf (current-buffer)) + (fld (mew-current-get-fld fid)) + (msg (mew-current-get-msg fid)) + (disp (mew-sinfo-get-disp-msg))) + (if disp (mew-make-net-disp-info :fid fid :buf buf :fld fld :msg msg)))) + +(defun mew-net-disp-info-display (disp-info) + (when disp-info + (let ((fid (mew-net-disp-info-get-fid disp-info)) + (buf (mew-net-disp-info-get-buf disp-info)) + (fld (mew-net-disp-info-get-fld disp-info)) + (msg (mew-net-disp-info-get-msg disp-info)) + (nfid (mew-frame-id)) + m) + (when (and (equal fid nfid) + (equal fld (mew-current-get-fld nfid))) + (with-current-buffer buf + (setq m (point-marker)) + (set-marker-insertion-type m t) + (when (and (mew-sinfo-get-disp-msg) + (equal msg (mew-current-get-msg nfid)) + (mew-summary-search-msg msg)) + ;; The message was truncated probaby because it's too large. + (mew-summary-analyze-again)) + (goto-char m)))))) + +(defun mew-summary-retrieve-message (&optional rev-del) + "Retrieve the rest of a truncated('T') message. + +In a LOCAL folder: a method to retrieve the message is determined +by 'mew-case' and 'mew-mailbox-type'. +If 'mew-pop-delete'/'mew-imap-delete' is non-nil, delete the message +from the mailbox. When executed with '\\[universal-argument]', +'mew-pop-delete'/'mew-imap-delete' is considered reversed. + +In a REMOTE folder: case and protocol are determined by the folder. +The message in the server side is always retained." + (interactive "P") + (mew-pickable + (mew-summary-msg + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (let* ((msg (mew-sumsyn-message-number)) + (uid (mew-sumsyn-message-uid)) + (siz (mew-sumsyn-message-size)) + (bnm (mew-summary-folder-name)) + (disp-info (mew-net-disp-info)) + (virtual-info (if (mew-virtual-for-one-summary) + (mew-net-virtual-info (list msg)))) + folder case del rtr rtrs mailbox) + (with-current-buffer bnm + (when (mew-summary-exclusive-p) + (setq folder (mew-sinfo-get-folder)) + (setq case (mew-sinfo-get-case)) + (when (mew-folder-localp folder) + (setq case (or (mew-summary-get-inherit-case folder msg) mew-case)) + (setq mailbox (mew-mailbox-type case)) + (cond + ((eq mailbox 'pop) + (setq del (eq (mew-pop-delete case) t))) ;; delete may be number + ((eq mailbox 'imap) + (setq del (eq (mew-imap-delete case) t)))) ;; delete may be number + (if rev-del (setq del (not del)))) + (when (and uid (not (string= uid ""))) + (setq rtr (mew-make-refileinfo :uid uid + :size siz + :delete del + :folders (list bnm msg))) + (setq rtrs (list rtr))) + (cond + ((not rtrs) + (message "No message to be retrieved")) + ((not (mew-msg-validp msg)) + (message "No valid message to be retrieved")) + ((mew-folder-localp folder) + (cond + ((eq mailbox 'pop) + (mew-pop-retrieve case 'get bnm rtrs virtual-info disp-info)) + ((eq mailbox 'imap) + (mew-imap-retrieve case 'get bnm rtrs virtual-info disp-info)))) + ((mew-folder-popp folder) + (mew-pop-retrieve case 'get bnm rtrs virtual-info disp-info)) + ((mew-folder-imapp folder) + (mew-imap-retrieve case 'get bnm rtrs virtual-info disp-info)) + ((mew-folder-nntpp folder) + (mew-nntp-retrieve case 'get bnm rtrs virtual-info disp-info)))))))))) + +(defun mew-summary-retrieve-message-for-virtual-summary (msg) + (save-excursion + (when (mew-summary-search-msg msg) + (let ((start (point))) + (forward-line) + (buffer-substring start (point)))))) + +(defun mew-summary-retrieve-message-for-virtual-selection (msg str) + (save-excursion + (when (mew-summary-search-msg msg) + (let ((start (point))) + (forward-line) + (mew-elet + (delete-region start (point)) + (insert str)))))) + +(defun mew-summary-retrieve-message-for-virtual-thread (msg str) + (save-excursion + (when (mew-summary-search-msg msg) + (let* ((start (point)) + (beg (mew-thread-next-property start)) + (level (mew-thread-get-property beg)) + (length (* mew-thread-indent-length level)) + (end (+ beg length)) + (idt-str (buffer-substring beg end))) + (forward-line) + (mew-elet + (delete-region start (point)) + (insert str) + (goto-char beg) + (if (= level 0) (setq end (1+ end))) + (insert idt-str) + (mew-thread-put-property beg end level)))))) + +(defun mew-summary-retrieve-message-for-virtual (virtual-info) + (let ((virtual (mew-net-virtual-info-get-virtual virtual-info)) + (summary (mew-net-virtual-info-get-summary virtual-info)) + (msgs (mew-net-virtual-info-get-msgs virtual-info)) + (func (if (mew-net-virtual-info-get-threadp virtual-info) + 'mew-summary-retrieve-message-for-virtual-thread + 'mew-summary-retrieve-message-for-virtual-selection)) + str) + (save-excursion + (dolist (msg msgs) + (set-buffer summary) + ;; Summary + (setq str (mew-summary-retrieve-message-for-virtual-summary msg)) + (set-buffer virtual) + ;; Virtual + (funcall func msg str)) + (mew-summary-unlock)))) + +(defun mew-summary-mark-retrieve-message (&optional rev-del) + "Retrieve the rest of truncated('T') messages marked with '*'. + +In a LOCAL folder: a method to retrieve the messages is determined by +'mew-case' and 'mew-mailbox-type'. +If 'mew-pop-delete'/'mew-imap-delete' is non-nil, delete the messages +from the mailbox. When executed with '\\[universal-argument]', +'mew-pop-delete'/'mew-imap-delete' is considered reversed. + +In a REMOTE folder: case and protocol are determined by the folder. +The messages in the server side is always retained." + (interactive "P") + (mew-summary-only + (let* ((bnm (mew-summary-folder-name 'ext)) + (folder (mew-sinfo-get-folder)) + (case (mew-sinfo-get-case)) + msg uid siz del rtr rtrs case-rtrs mailbox) + (save-excursion + (goto-char (point-min)) + (if (mew-folder-localp folder) + (let (tmp) + (while (re-search-forward mew-regex-msg-review nil t) + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (setq uid (mew-sumsyn-message-uid)) + (setq msg (mew-sumsyn-message-number)) + (setq siz (mew-sumsyn-message-size)) + (setq case (or (mew-summary-get-inherit-case folder msg) mew-case)) + (setq mailbox (mew-mailbox-type case)) + (when (and (mew-msg-validp msg) (mew-msg-truncatedp siz)) + (cond + ((eq mailbox 'pop) + (setq del (eq (mew-pop-delete case) t))) ;; delete may be number + ((eq mailbox 'imap) + (setq del (eq (mew-imap-delete case) t)))) ;; delete may be number + (if rev-del (setq del (not del))) + (setq rtr (mew-make-refileinfo :uid uid + :size siz + :delete del + :folders (list bnm msg))) + (if (setq tmp (nth 2 (assoc case case-rtrs))) + (nconc tmp (list rtr)) + (setq case-rtrs (cons (list case mailbox (list rtr)) case-rtrs)))) + (forward-line))) + (setq case-rtrs (nreverse case-rtrs))) + (while (re-search-forward mew-regex-msg-review nil t) + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (setq uid (mew-sumsyn-message-uid)) + (setq msg (mew-sumsyn-message-number)) + (setq siz (mew-sumsyn-message-size)) + (when (and (mew-msg-validp msg) (mew-msg-truncatedp siz)) + (setq rtr (mew-make-refileinfo :uid uid + :size siz + :delete del + :folders (list bnm msg))) + (setq rtrs (cons rtr rtrs)))) + (forward-line)) + (setq rtrs (nreverse rtrs)))) + (if (and (not rtrs) (not case-rtrs)) + (message "No message to be retrieved") + (cond + ((mew-folder-localp folder) + (while case-rtrs ;; cannot use dolist + (setq case (nth 0 (car case-rtrs))) + (setq mailbox (nth 1 (car case-rtrs))) + (setq rtrs (nth 2 (car case-rtrs))) + (setq case-rtrs (cdr case-rtrs)) + (cond + ((eq mailbox 'pop) + (mew-pop-retrieve case 'get bnm rtrs)) + ((eq mailbox 'imap) + (mew-imap-retrieve case 'get bnm rtrs))) + (when case-rtrs + (mew-rendezvous mew-summary-buffer-process)))) + ((mew-folder-popp folder) + (mew-pop-retrieve case 'get bnm rtrs)) + ((mew-folder-imapp folder) + (mew-imap-retrieve case 'get bnm rtrs)) + ((mew-folder-nntpp folder) + (mew-nntp-retrieve case 'get bnm rtrs))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folder clean up +;;; + +(defun mew-folder-clean-up () + (remove-hook 'kill-emacs-hook 'mew-folder-clean-up) + (mew-local-folder-clean-up) + (mew-imap-folder-clean-up) + (mew-nntp-folder-clean-up)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message packing +;;; + +(defun mew-net-msg-pack (msgs) + ;; (mew-net-msg-pack '("1" "3" "4" "5" "7" "8" "10")) + ;; => ("1" "3:5" "7:8" "10") + (let (pack a b s) + (when (setq a (car msgs)) + (setq a (string-to-number a)) + (setq msgs (cdr msgs)) + (while (setq b (car msgs)) + (setq b (string-to-number b)) + (setq msgs (cdr msgs)) + (if (= (1+ a) b) + (if (null s) + (setq s a)) + (if (null s) + (setq pack (cons (format "%d" a) pack)) + (setq pack (cons (format "%d:%d" s a) pack)) + (setq s nil))) + (setq a b)) + (if s + (setq pack (cons (format "%d:%d" s a) pack)) + (setq pack (cons (format "%d" a) pack))) + (nreverse pack)))) + +(defvar mew-imap-message-cat-size 10) + +(defun mew-net-msg-cat (lst) + (let ((N (1- mew-imap-message-cat-size)) + (crn lst) + prv nxt ret) + (while (setq prv (nthcdr N crn)) + (setq nxt (cdr prv)) + (setcdr prv nil) + (setq ret (cons (mew-join "," crn) ret)) + (setq crn nxt)) + (if crn (setq ret (cons (mew-join "," crn) ret))) + (nreverse ret))) + +(defun mew-net-msg-group (lst) + (if (= (length lst) 1) + lst ;; "1:*" + (mew-net-msg-cat (mew-net-msg-pack lst)))) + +(provide 'mew-net) + +;;; Copyright Notice: + +;; Copyright (C) 2002-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-net.el ends here diff --git a/elpa/mew-20150813.2354/mew-nntp.el b/elpa/mew-20150813.2354/mew-nntp.el new file mode 100644 index 00000000..951425bd --- /dev/null +++ b/elpa/mew-20150813.2354/mew-nntp.el @@ -0,0 +1,744 @@ +;;; mew-nntp.el for reading + +;; Author: Kazu Yamamoto +;; Created: Feb 1, 1999 + +;;; Code: + +(require 'mew) + +(defvar mew-nntp-msgid-file ".mew-msgid") +(defvar mew-nntp-folder-alist-file ".mew-folder-alist") +(defvar mew-nntp-folder-alist nil) +;; without mew-folder-nntp +(defvar mew-nntp-folder-alist2-file ".mew-folder-alist2") +(defvar mew-nntp-folder-alist2 nil) + +(defvar mew-nntp-skip-uidl t) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; NNTP info +;;; + +(defvar mew-nntp-info-list + '("server" "port" "process" "ssh-process" "ssl-process" "status" + "directive" "bnm" "mdb" + "rtrs" "refs" "range" + "rttl" "rcnt" "hlds" + "user" "account" + "size" "get-body" "no-msg" "case" "msgdb" "done" "dispatched" "error" + "max" + "newsgroup" "msgid" "truncated" + "virtual-info" "disp-info" "status-buf")) + +(mew-info-defun "mew-nntp-" mew-nntp-info-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; FSM +;;; + +(defvar mew-nntp-fsm + '(("greeting" nil ("20[01]" . "mode-reader")) + ("mode-reader" nil (t . "authinfo")) + ("authinfo" nil ("381" . "authpass")) + ("authpass" nil ("281" . "group") (t . "wpwd")) + ("group" nil ("211" . "xover")) + ("xover" t ("224" . "pre-article")) + ("article" t ("22[01]" . "post-article") (t . "next-article")) + ("list" t ("215" . "post-list")) + ("pre-quit" nil (t . "quit2")) + ("quit" nil ("205" . "noop")))) + +(defun mew-nntp-fsm-by-status (status) + (assoc status mew-nntp-fsm)) + +(defun mew-nntp-fsm-next (status code) + (cdr (mew-assoc-match2 code (nthcdr 2 (mew-nntp-fsm-by-status status)) 0))) + +(defun mew-nntp-fsm-reply (status) + (nth 1 (mew-nntp-fsm-by-status status))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filters +;;; + +(defun mew-nntp-secure-p (pnm) + (or (mew-nntp-get-ssh-process pnm) (mew-nntp-get-ssl-process pnm))) + +(defun mew-nntp-command-mode-reader (pro pnm) + (mew-net-status (mew-nntp-get-status-buf pnm) + "Connecting" + nil + (mew-nntp-secure-p pnm)) + (mew-nntp-process-send-string pro "MODE READER")) + +(defun mew-nntp-command-authinfo (pro pnm) + (let ((user (mew-nntp-get-user pnm))) + (if user + (mew-nntp-process-send-string pro "AUTHINFO USER %s" user) + (mew-nntp-set-status pnm "group") + (mew-nntp-command-group pro pnm)))) + +(defun mew-nntp-command-authpass (pro pnm) + (let* ((prompt (format "NNTP password (%s): " (mew-nntp-get-account pnm))) + (pass (mew-nntp-input-passwd prompt pnm))) + (mew-nntp-process-send-string pro "AUTHINFO PASS %s" pass))) + +(defun mew-nntp-command-wpwd (pro pnm) + (mew-nntp-message pnm "NNTP password is wrong!") + (mew-passwd-set-passwd (mew-nntp-passtag pnm) nil) + (mew-nntp-set-status pnm "pre-quit")) + +(defun mew-nntp-command-group (pro pnm) + (let ((directive (mew-nntp-get-directive pnm)) + (newsgroup (mew-nntp-get-newsgroup pnm))) + (cond + ((eq directive 'list) + (mew-nntp-set-status pnm "list") + (mew-nntp-command-list pro pnm)) + (t + (mew-nntp-process-send-string pro "GROUP %s" newsgroup))))) + +(defun mew-nntp-command-xover (pro pnm) + (let ((directive (mew-nntp-get-directive pnm)) + (refs (mew-nntp-get-refs pnm)) ;; (uid siz del (+fld msg)) + (bnm (mew-nntp-get-bnm pnm)) + (range (mew-nntp-get-range pnm)) + max first last) + (if (and mew-nntp-skip-uidl (eq directive 'get)) + (mew-nntp-command-dispatch pro pnm directive refs nil) + (mew-net-status (mew-nntp-get-status-buf pnm) + "Checking" nil (mew-nntp-secure-p pnm)) + (cond + ((eq directive 'scan) + (if (eq range nil) ;; update + (setq max (mew-lisp-load + (mew-expand-file bnm mew-nntp-msgid-file)))))) + ;; 221 total first last newsgroup (xxx) + (if (re-search-forward "^[0-9]+ +[0-9]+ +\\([0-9]+\\) +\\([0-9]+\\) +[-.a-zA-Z0-9]+" nil t) + (progn + (setq first (string-to-number (mew-match-string 1))) + (setq last (string-to-number (mew-match-string 2))) + (cond + ((stringp max) + (setq max (string-to-number max))) + (max ;; backward compatibility + ;; reversed + (setq max (car max)) + (setq max (string-to-number max))) + ((and (eq directive 'scan) (integerp range)) + (setq max (- last range)) + (if (< max first) (setq max (1- first)))) + (t + (setq max (1- first)))) + (mew-nntp-set-max pnm max) + (mew-nntp-process-send-string pro "XOVER %d-" (1+ max))) + (mew-nntp-set-status pnm "quit") + (mew-nntp-command-quit pro pnm))))) + +(defun mew-nntp-command-pre-article (pro pnm) + (let* ((directive (mew-nntp-get-directive pnm)) + (max (mew-nntp-get-max pnm)) + (refs (mew-nntp-get-refs pnm)) + ;; (uid siz del (+fld msg)) + (range (mew-nntp-get-range pnm)) + uid siz rtr rtrs hlds) + (goto-char (point-min)) + ;; num subj from date msg-id ref siz lines + (while (re-search-forward "^\\([0-9]+\\)\t[^\t\n]*\t[^\t\n]*\t[^\t\n]*\t<[^>\t\n]+>\t[^\t\n]*\t\\([0-9]*\\)" nil t) + (setq uid (mew-match-string 1)) + (setq siz (mew-match-string 2)) + (if (string= uid "") (setq uid nil)) + (cond + ((eq directive 'get) + (setq rtr (assoc uid refs)) + (if rtr (setq rtrs (cons rtr rtrs)))) + ((eq directive 'scan) + (if (and uid (or range ;; all, last:n + (> (string-to-number uid) max))) ;; update + (setq rtrs (cons (mew-make-refileinfo :uid uid :size siz) rtrs)))) + ((eq directive 'sync) + (if uid (setq hlds (cons uid hlds)))))) + (mew-nntp-set-msgid pnm (mew-refileinfo-get-uid (car rtrs))) ;; 'scan + ;; last:n xxx + ;; (when (and (eq directive 'scan) (integerp range)) + ;; (mew-ntake range rtrs)) + (setq rtrs (nreverse rtrs)) + (setq hlds (nreverse hlds)) + (mew-nntp-command-dispatch pro pnm directive rtrs hlds))) + +(defun mew-nntp-command-dispatch (pro pnm directive rtrs hlds) + (let ((rttl (length rtrs))) + (mew-nntp-set-rtrs pnm rtrs) + (mew-nntp-set-rttl pnm rttl) + (mew-nntp-set-hlds pnm hlds) + (mew-nntp-set-dispatched pnm t) + (cond + ((eq directive 'sync) + (mew-nntp-set-status pnm "quit") + (mew-nntp-command-quit pro pnm)) + ((= rttl 0) + (mew-nntp-message pnm "No new messages") + (mew-nntp-set-status pnm "quit") + (mew-nntp-command-quit pro pnm)) + ((= rttl 1) + (mew-nntp-message pnm "Retrieving 1 message in background...") + (mew-nntp-set-status pnm "article") + (mew-nntp-command-article pro pnm)) + (t + (mew-nntp-message pnm "Retrieving %d messages in background..." rttl) + (mew-nntp-set-status pnm "article") + (mew-nntp-command-article pro pnm))))) + +(defun mew-nntp-command-article (pro pnm) + (mew-net-status2 (mew-nntp-get-status-buf pnm) + (mew-nntp-get-rttl pnm) + (mew-nntp-get-rcnt pnm) + (mew-refileinfo-get-size (car (mew-nntp-get-rtrs pnm))) + 'zero + (mew-nntp-secure-p pnm)) + (let* ((directive (mew-nntp-get-directive pnm)) + (rtrs (mew-nntp-get-rtrs pnm)) + (rtr (car rtrs)) + (uid (mew-refileinfo-get-uid rtr)) + (siz (mew-refileinfo-get-size rtr)) + (lim (mew-nntp-get-size pnm)) + (get-body (mew-nntp-get-get-body pnm))) + (cond + ((or (null rtr) (eq directive 'biff)) + (mew-nntp-set-truncated pnm nil) + (mew-nntp-set-status pnm "quit") + (mew-nntp-command-quit pro pnm)) + ((eq directive 'get) + (mew-nntp-set-truncated pnm nil) + (mew-nntp-process-send-string pro "ARTICLE %s" uid)) + ((and (eq directive 'scan) (not get-body)) + (mew-nntp-set-truncated pnm t) + (mew-nntp-process-send-string pro "HEAD %s" uid)) + ((or (= lim 0) (<= (string-to-number siz) lim)) + (mew-nntp-set-truncated pnm nil) + (mew-nntp-process-send-string pro "ARTICLE %s" uid)) + (t + (mew-nntp-set-truncated pnm t) + (mew-nntp-process-send-string pro "HEAD %s" uid))))) + +(defun mew-nntp-command-post-article (pro pnm) + (let* ((directive (mew-nntp-get-directive pnm)) + (width (1- (mew-scan-width))) + (rtrs (mew-nntp-get-rtrs pnm)) + (rtr (car rtrs)) + (uid (mew-refileinfo-get-uid rtr)) + (siz (mew-refileinfo-get-size rtr)) + (fld-msg (mew-refileinfo-get-folders rtr)) + (truncated (mew-nntp-get-truncated pnm)) + fld msg vec file msg-file lmsg) + (cond + ((null fld-msg) + (setq fld (mew-nntp-get-bnm pnm))) + ((stringp fld-msg) + (setq fld fld-msg)) + ((listp fld-msg) + (mew-set '(fld msg) fld-msg) + (setq lmsg msg))) + (goto-char (point-min)) + (forward-line) + (delete-region (point-min) (point)) + ;; line delimiters + (mew-eol-fix-for-read) + (mew-dot-delete) + (cond + ((eq directive 'scan) + (setq msg uid) + (setq file (mew-expand-new-msg fld msg))) + (t + (setq msg-file (mew-net-get-new-message + pnm fld msg 'mew-nntp-get-msgdb 'mew-nntp-set-msgdb)) + (setq msg (car msg-file) file (cdr msg-file)))) + (goto-char (point-min)) + (if truncated + (mew-header-insert-xmu uid siz t) + (mew-header-insert-xmu uid siz nil)) + (catch 'write-error + (condition-case nil + (let ((write-region-inhibit-fsync mew-use-async-write)) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region (point-min) (point-max) file nil 'no-msg))) + (error + (mew-nntp-set-status pnm "quit") + (mew-nntp-command-quit pro pnm) + (throw 'write-error nil))) + (when (file-exists-p file) + (mew-set-file-modes file) + (mew-set-file-type file) + (mew-set-buffer-multibyte t) + (setq vec (mew-scan-header)) + (mew-scan-set-folder vec fld) + (mew-scan-set-message vec msg) + (mew-scan-body vec) + (mew-set-buffer-multibyte nil) + (mew-scan-insert-line fld vec width lmsg)) + (mew-nntp-command-next-article pro pnm)))) + +(defun mew-nntp-command-next-article (pro pnm) + (let* ((rtrs (mew-nntp-get-rtrs pnm))) + (mew-nntp-set-rcnt pnm (1+ (mew-nntp-get-rcnt pnm))) + (mew-nntp-set-rtrs pnm (cdr rtrs)) + (mew-nntp-set-status pnm "article") + (mew-nntp-command-article pro pnm))) + +(defun mew-nntp-command-list (pro pnm) + (mew-net-status (mew-nntp-get-status-buf pnm) + "Listing" + nil + (mew-nntp-secure-p pnm)) + (mew-nntp-message pnm "Collecting newsgroup list...") + (mew-nntp-process-send-string pro "LIST")) + +(defun mew-nntp-command-post-list (pro pnm) + (let ((case (mew-nntp-get-case pnm)) + group group2 groups groups2) + (goto-char (point-min)) + (forward-line) + (delete-region (point-min) (point)) + ;; line delimiters + (mew-eol-fix-for-read) + (mew-dot-delete) + (while (not (eobp)) + (when (looking-at "\\([a-z][^ \t\n]+\\)") + (setq group2 (mew-match-string 1)) + (setq group (concat mew-folder-nntp group2)) + (setq groups (cons (mew-folder-func group) groups)) + (setq groups2 (cons (mew-folder-func group2) groups2))) + (forward-line)) + (if (null case) (setq case mew-case-default)) + (setq groups (nreverse groups)) + (mew-nntp-folder-save case groups groups2) + (mew-nntp-folder-alist-set case groups) + (mew-nntp-folder-alist2-set case groups2) + (mew-nntp-set-status pnm "quit") + (mew-nntp-command-quit pro pnm))) + +(defun mew-nntp-command-quit (pro pnm) + (mew-nntp-set-done pnm t) + (mew-nntp-process-send-string pro "QUIT")) + +(defun mew-nntp-command-quit2 (pro pnm) + (mew-nntp-set-done pnm t) + (mew-nntp-set-error pnm t) + (mew-nntp-set-status pnm "quit") + (mew-nntp-process-send-string pro "QUIT")) + +(defun mew-nntp-command-noop (pro pnm) + ()) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub functions +;;; + +(defconst mew-nntp-info-prefix "mew-nntp-info-") + +(defun mew-nntp-info-name (case newsgroup) + (let ((server (mew-nntp-server case)) + (port (mew-*-to-string (mew-nntp-port case))) + (sshsrv (mew-nntp-ssh-server case)) + (name mew-nntp-info-prefix)) + (setq name (concat name server "/" newsgroup)) + (unless (mew-port-equal port mew-nntp-port) + (setq name (concat name ":" port))) + (if sshsrv + (concat name "%" sshsrv) + name))) + +(defun mew-nntp-buffer-name (pnm) + (concat mew-buffer-prefix pnm)) + +(defun mew-nntp-process-send-string (pro &rest args) + (let ((str (apply 'format args))) + (mew-nntp-debug "=SEND=" str) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-string pro (concat str mew-cs-eol)) + (message "NNTP time out")))) + +(defun mew-nntp-passtag (pnm) + (let ((server (mew-nntp-get-server pnm)) + (port (mew-nntp-get-port pnm)) + (user (mew-nntp-get-user pnm))) + (concat user "@" server ":" port))) + +(defun mew-nntp-message (pnm &rest args) + (or (mew-nntp-get-no-msg pnm) (apply 'message args))) + +(defun mew-bnm-to-newsgroup (bnm) + (mew-folder-string (mew-case:folder-folder bnm))) + +(defun mew-nntp-input-passwd (prompt pnm) + (let* ((tag (mew-nntp-passtag pnm)) + (pro (mew-nntp-get-process pnm)) + (pass (mew-input-passwd prompt tag))) + (unless (and (processp pro) (eq (process-status pro) 'open)) + (mew-passwd-set-passwd tag nil)) + pass)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Opening NNTP +;;; + +(defun mew-nntp-open (pnm server port no-msg) + (let ((sprt (mew-*-to-port port)) + pro tm) + (condition-case emsg + (progn + (setq tm (run-at-time mew-nntp-timeout-time nil 'mew-nntp-timeout)) + (or no-msg (message "Connecting to the NNTP server...")) + (setq pro (open-network-stream pnm nil server sprt)) + (mew-process-silent-exit pro) + (mew-set-process-cs pro mew-cs-text-for-net mew-cs-text-for-net) + (or no-msg (message "Connecting to the NNTP server...done"))) + (quit + (or no-msg (message "Cannot connect to the NNTP server")) + (setq pro nil)) + (error + (or no-msg (message "%s, %s" (nth 1 emsg) (nth 2 emsg))) + (setq pro nil))) + (if tm (cancel-timer tm)) + pro)) + +(defun mew-nntp-timeout () + (signal 'quit nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Launcher +;;; + +(defun mew-nntp-retrieve (case directive bnm &rest args) + (let* ((server (mew-nntp-server case)) + (user (mew-nntp-user case)) + (port (mew-*-to-string (mew-nntp-port case))) + (sshsrv (mew-nntp-ssh-server case)) + (sslp (mew-nntp-ssl case)) + (sslport (mew-nntp-ssl-port case)) + (newsgroup (mew-bnm-to-newsgroup bnm)) + (pnm (mew-nntp-info-name case newsgroup)) + (buf (get-buffer-create (mew-nntp-buffer-name pnm))) + (no-msg (eq directive 'biff)) + process sshname sshpro sslname sslpro lport tls + virtual-info disp-info virtual) + (if (mew-nntp-get-process pnm) + (message "Another NNTP process is running. Try later") + (cond + (sshsrv + (setq sshpro (mew-open-ssh-stream case server port sshsrv)) + (when sshpro + (setq sshname (process-name sshpro)) + (setq lport (mew-ssh-pnm-to-lport sshname)) + (when lport + (setq process (mew-nntp-open pnm "localhost" lport no-msg))))) + (sslp + (if (mew-port-equal port sslport) (setq tls mew-tls-nntp)) + (setq sslpro (mew-open-ssl-stream case server sslport tls)) + (when sslpro + (setq sslname (process-name sslpro)) + (setq lport (mew-ssl-pnm-to-lport sslname)) + (when lport + (setq process (mew-nntp-open pnm mew-ssl-localhost lport no-msg))))) + (t + (setq process (mew-nntp-open pnm server port no-msg)))) + (when process + (mew-summary-lock process "NNTPing" (or sshpro sslpro)) + (mew-sinfo-set-summary-form (mew-get-summary-form bnm)) + (mew-sinfo-set-summary-column (mew-get-summary-column bnm)) + (mew-sinfo-set-unread-mark nil) + (mew-sinfo-set-scan-id nil) + (mew-sinfo-set-scan-md5 nil) + (mew-info-clean-up pnm) + (mew-nntp-set-no-msg pnm no-msg) ;; must come here + (mew-nntp-message pnm "Communicating with the NNTP server...") + (mew-nntp-set-process pnm process) + (mew-nntp-set-ssh-process pnm sshpro) + (mew-nntp-set-ssl-process pnm sslpro) + (mew-nntp-set-server pnm server) + (mew-nntp-set-port pnm port) + (mew-nntp-set-user pnm user) + (mew-nntp-set-account pnm (format "%s@%s" user server)) + (mew-nntp-set-status pnm "greeting") + (mew-nntp-set-directive pnm directive) + (mew-nntp-set-bnm pnm bnm) + (mew-nntp-set-status-buf pnm bnm) + (mew-nntp-set-rcnt pnm 1) + (mew-nntp-set-rttl pnm 0) + (mew-nntp-set-size pnm (mew-nntp-size case)) + (mew-nntp-set-newsgroup pnm newsgroup) + (mew-nntp-set-case pnm case) + ;; + (cond + ((eq directive 'get) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)) + (mew-nntp-set-refs pnm (nth 0 args)) + (setq virtual-info (nth 1 args)) + (mew-nntp-set-virtual-info pnm virtual-info) + (setq disp-info (nth 1 args)) + (mew-nntp-set-disp-info pnm disp-info) + (setq virtual (mew-net-virtual-info-get-virtual virtual-info)) + (when virtual + (mew-nntp-set-status-buf pnm virtual) + (with-current-buffer virtual + (mew-summary-lock process "NNTPing" (or sshpro sslpro))))) + ((eq directive 'scan) + (mew-nntp-set-range pnm (nth 0 args)) + (mew-nntp-set-get-body pnm (nth 1 args)) + (if (mew-nntp-get-range pnm) + (progn + (mew-nntp-set-mdb pnm (mew-summary-mark-collect4)) + (mew-net-folder-clean)) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)))) + ((eq directive 'sync) + )) + (mew-sinfo-set-start-point (point)) ;; after erase-buffer + (set-process-sentinel process 'mew-nntp-sentinel) + (set-process-filter process 'mew-nntp-filter) + (set-process-buffer process buf))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defun mew-nntp-debug (label string) + (when (mew-debug 'net) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +(defun mew-nntp-filter (process string) + (let* ((pnm (process-name process)) + (status (mew-nntp-get-status pnm)) + (mulrep (mew-nntp-fsm-reply status)) + stay next func code) + (mew-nntp-debug (upcase status) string) + (mew-filter + ;; Process's buffer + (goto-char (point-max)) + (mew-set-buffer-multibyte nil) + (insert string) + (when (string= status "article") + (mew-net-status2 (mew-nntp-get-status-buf pnm) + (mew-nntp-get-rttl pnm) + (mew-nntp-get-rcnt pnm) + (mew-refileinfo-get-size (car (mew-nntp-get-rtrs pnm))) + nil + (mew-nntp-secure-p pnm))) + (cond + ((and (and (goto-char (1- (point-max))) (looking-at "\n$")) + (and (goto-char (point-min)) (looking-at "^\\([45][0-9][0-9]\\)"))) + ;; this is an error code. this cannot be a multiple-line reply. + (setq code (mew-match-string 1)) + (setq next (mew-nntp-fsm-next status code))) + ((and (or (and mulrep + (goto-char (point-max)) + (= (forward-line -1) 0) + (looking-at "^\\.\r?$")) + (and (not mulrep) + (goto-char (1- (point-max))) + (looking-at "\n$"))) + (and (goto-char (point-min)) (looking-at "^\\([0-9][0-9][0-9]\\)"))) + (setq code (mew-match-string 1)) + (setq next (mew-nntp-fsm-next status code))) + (t + (setq stay t))) + (unless stay + (unless next (setq next "quit")) + (mew-nntp-set-status pnm next) + (setq func (intern-soft (concat "mew-nntp-command-" next))) + (goto-char (point-min)) + (if (fboundp func) + (funcall func process pnm) + (error "No function called %s" (symbol-name func))) + (if (and process (equal (process-buffer process) (current-buffer))) + (mew-erase-buffer)))))) + +(defun mew-nntp-sentinel (process event) + (let* ((pnm (process-name process)) + (directive (mew-nntp-get-directive pnm)) + (mdb (mew-nntp-get-mdb pnm)) + (sshpro (mew-nntp-get-ssh-process pnm)) + (sslpro (mew-nntp-get-ssl-process pnm)) + (rttl (mew-nntp-get-rttl pnm)) + (bnm (or (mew-nntp-get-bnm pnm) (current-buffer))) + (hlds (mew-nntp-get-hlds pnm)) + (msgid (mew-nntp-get-msgid pnm)) + (done (mew-nntp-get-done pnm)) + (error (mew-nntp-get-error pnm)) + (file (mew-expand-file bnm mew-nntp-msgid-file)) + (buf (process-buffer process)) + (virtual-info (mew-nntp-get-virtual-info pnm)) + (disp-info (mew-nntp-get-disp-info pnm))) + (save-excursion + (mew-nntp-debug "NNTP SENTINEL" event) + (set-process-buffer process nil) + (set-buffer bnm) + (mew-summary-mark-recover mdb) + (mew-remove-buffer buf) + (if (not done) + (let* ((rtrs (mew-nntp-get-rtrs pnm)) + (lefts (length rtrs)) + (msgid (mew-refileinfo-get-uid (car rtrs))) + recovered) + (mew-nntp-message pnm "NNTP connection is lost") + (when (mew-nntp-get-dispatched pnm) + (cond + ((eq directive 'scan) + (setq msgid (number-to-string (1- (string-to-number msgid)))) + (mew-lisp-save file msgid nil 'unlimit) + (setq recovered t))) + (when recovered + (mew-nntp-message + pnm + "%d message retrieved. %d messages are left due to an error" + (- rttl lefts) lefts) + (mew-summary-folder-cache-save)))) + (if virtual-info (mew-summary-retrieve-message-for-virtual virtual-info)) + (cond + (error + ;; retain the error message + ) + ((eq directive 'list) + (mew-nntp-message pnm "Collecting newsgroup list...done")) + ((eq directive 'sync) + (mew-nntp-message pnm "Synchronizing messages...") + (mew-net-folder-sync bnm hlds) + (mew-nntp-message pnm "Synchronizing messages...done") + (mew-summary-folder-cache-save)) + ((eq directive 'get) + (cond + ((= rttl 0) + (mew-nntp-message pnm "No new messages")) + ((= rttl 1) + (mew-nntp-message pnm "1 message retrieved") + (mew-summary-folder-cache-save)) + (t + (mew-nntp-message pnm "%d messages retrieved" rttl) + (mew-summary-folder-cache-save)))) + ((eq directive 'scan) + (cond + ((or (= rttl 0) (null msgid)) + (mew-nntp-message pnm "No messages scanned")) + ((= rttl 1) + (mew-nntp-message pnm "1 message scanned") + (mew-lisp-save file msgid nil 'unlimit) + (mew-summary-folder-cache-save)) + (t + (mew-nntp-message pnm "%d messages scanned" rttl) + (mew-lisp-save file msgid nil 'unlimit) + (mew-summary-folder-cache-save)))))) + ;; + (and mew-use-async-write (mew-unix-sync)) + (mew-net-status-clear (mew-nntp-get-status-buf pnm)) + (mew-info-clean-up pnm) + (set-buffer-modified-p nil) + (mew-summary-unlock) + (if (and (processp sshpro) (not mew-ssh-keep-connection)) + (process-send-string sshpro "exit\n")) + (if (and (processp sslpro) (not mew-ssl-keep-connection)) + (delete-process sslpro)) + (mew-net-disp-info-display disp-info) + (run-hooks 'mew-nntp-sentinel-hook)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Newsgroup alist +;;; + +(defun mew-nntp-folder-clean-up () + (setq mew-nntp-folder-alist nil) + (setq mew-nntp-folder-alist2 nil)) + +(defun mew-nntp-folder-alist (&optional case) + (let ((ent (assoc (or case mew-case-default) mew-nntp-folder-alist)) + alist) + (if (and ent (cdr ent)) + (cdr ent) + (setq alist (mew-nntp-folder-load case)) + (if alist + alist + (list (mew-folder-func (mew-nntp-newsgroup case))))))) + +(defun mew-nntp-folder-alist2 (&optional case) + (let ((ent (assoc (or case mew-case-default) mew-nntp-folder-alist2))) + (if ent + (cdr ent) + (mew-nntp-folder-load case 'two)))) + +(defun mew-nntp-folder-load (case &optional two) + (let* ((fld (mew-nntp-folder case)) + (file (mew-expand-file fld mew-nntp-folder-alist-file)) + (groups (mew-lisp-load file)) + (file2 (mew-expand-file fld mew-nntp-folder-alist2-file)) + (groups2 (mew-lisp-load file2))) + (mew-nntp-folder-alist-set case groups) + (mew-nntp-folder-alist2-set case groups2) + (if two groups2 groups))) + +(defun mew-nntp-folder-save (case groups groups2) + (let* ((fld (mew-nntp-folder case)) + (dir (mew-expand-folder fld)) + (file (expand-file-name mew-nntp-folder-alist-file dir)) + (file2 (expand-file-name mew-nntp-folder-alist2-file dir))) + (mew-check-directory dir) + (mew-lisp-save file groups 'nobackup 'unlimit) + (mew-lisp-save file2 groups2 'nobackup 'unlimit))) + +(defun mew-nntp-folder-alist-set (case groups) + (setq mew-nntp-folder-alist + (cons (cons (or case mew-case-default) groups) + (delete (assoc (or case mew-case-default) mew-nntp-folder-alist) + mew-nntp-folder-alist)))) + +(defun mew-nntp-folder-alist2-set (case groups) + (setq mew-nntp-folder-alist2 + (cons (cons (or case mew-case-default) groups) + (delete (assoc (or case mew-case-default) mew-nntp-folder-alist2) + mew-nntp-folder-alist2)))) + +(defun mew-nntp-update (case) + (let ((bnm (mew-summary-folder-name 'ext))) + (mew-nntp-retrieve case 'list bnm))) + +(provide 'mew-nntp) + +;;; Copyright Notice: + +;; Copyright (C) 1999-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-nntp.el ends here diff --git a/elpa/mew-20150813.2354/mew-nntp2.el b/elpa/mew-20150813.2354/mew-nntp2.el new file mode 100644 index 00000000..4bd3c71c --- /dev/null +++ b/elpa/mew-20150813.2354/mew-nntp2.el @@ -0,0 +1,446 @@ +;;; mew-nntp2.el for posting + +;; Author: Kazu Yamamoto +;; Created: Nov 19, 1999 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; NNTP2 info +;;; + +(defvar mew-nntp2-info-list + '(;; parameters to be saved + "raw-header" "newsgroups" "fcc" "msgid" "logtime" + "case" ;; save for re-edit, not for sending + ;; parameters used internally + "server" "port" "ssh-server" "user" "account" + "status" "process" "ssh-process" "ssl-process" + "qfld" "messages" + ;; parameters used internally and should be initialized + "string" "error" "done" "imapp")) + +(mew-info-defun "mew-nntp2-" mew-nntp2-info-list) + +(defvar mew-nntp2-info-list-save-length 6) +(defvar mew-nntp2-info-list-clean-length 16) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; FSM +;;; + +(defvar mew-nntp2-fsm + '(("greeting" ("20[01]" . "mode-reader")) ;; a broken server returns 200 even if post is allowed + ("mode-reader" (t . "authinfo")) + ("authinfo" ("381" . "authpass")) + ("authpass" ("281" . "next") (t . "wpwd")) + ("post" ("340" . "post-post")) + ("post-post" ("240" . "done")) + ("quit" (t . "noop")))) + +(defun mew-nntp2-fsm-by-status (status) + (assoc status mew-nntp2-fsm)) + +(defun mew-nntp2-fsm-next (status code) + (cdr (mew-assoc-match2 code (nthcdr 1 (mew-nntp2-fsm-by-status status)) 0))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filters 2 +;;; + +(defun mew-nntp2-command-mode-reader (pro pnm) + (mew-nntp2-process-send-string pro "MODE READER")) + +(defun mew-nntp2-command-authinfo (pro pnm) + (let ((user (mew-nntp2-get-user pnm))) + (if user + (mew-nntp2-process-send-string pro "AUTHINFO USER %s" user) + (mew-nntp2-set-status pnm "next") + (mew-nntp2-command-next pro pnm)))) + +(defun mew-nntp2-command-authpass (pro pnm) + (let* ((prompt (format "NNTP password (%s): " (mew-nntp2-get-account pnm))) + (pass (mew-nntp2-input-passwd prompt pnm))) + (mew-nntp2-process-send-string pro "AUTHINFO PASS %s" pass))) + +(defun mew-nntp2-command-wpwd (pro pnm) + (mew-passwd-set-passwd (mew-nntp2-passtag pnm) nil) + (mew-nntp2-set-error pnm "NNTP password is wrong!") + (mew-nntp2-command-quit2 pro pnm)) + +(defun mew-nntp2-command-next (pro pnm) + (let ((msgs (mew-nntp2-get-messages pnm)) + (qfld (mew-nntp2-get-qfld pnm)) + (case (mew-nntp2-get-case pnm)) + msg) + (if msgs + (progn + (setq msg (car msgs)) + (setq msgs (cdr msgs)) + (mew-queue-insert-file pnm mew-nntp2-info-list-save-length qfld msg) + (mew-set-buffer-multibyte nil) + (mew-info-clean-up pnm mew-nntp2-info-list-clean-length) + (mew-nntp2-set-case pnm case) ;; override + (mew-nntp2-set-messages pnm msgs) + (set-process-buffer pro (current-buffer)) + (mew-nntp2-set-status pnm "post") + (mew-nntp2-command-post pro pnm)) + (mew-nntp2-set-status pnm "quit") + (mew-nntp2-command-quit pro pnm)))) + +(defun mew-nntp2-command-post (pro pnm) + (mew-nntp2-process-send-string pro "POST")) + +(defun mew-nntp2-command-post-post (pro pnm) + (goto-char (point-max)) + (unless (bolp) (insert "\n")) + (mew-dot-insert) + (mew-eol-fix-for-write) + (set-buffer-modified-p nil) + (process-send-region pro (point-min) (point-max)) + (mew-nntp2-process-send-string pro ".")) + +(defun mew-nntp2-command-done (pro pnm) + (let ((fcc (mew-nntp2-get-fcc pnm)) + (case (mew-nntp2-get-case pnm)) + (back (mew-queue-backup (buffer-file-name) mew-queue-info-suffix)) + imapp) + ;; mew-folder-new-message may be slow if the folder contains + ;; a lot of messages. So, let's Fcc in background. + (setq imapp (mew-net-fcc-message case fcc back)) + (mew-nntp2-set-imapp pnm imapp) + (mew-nntp2-log pnm) + (mew-nntp2-set-status pro "next") + (mew-nntp2-command-next pro pnm))) + +(defun mew-nntp2-command-quit (pro pnm) + (mew-nntp2-set-done pnm t) + (mew-nntp2-process-send-string pro "QUIT")) + +(defun mew-nntp2-command-quit2 (pro pnm) + ;; error is set + (mew-nntp2-set-done pnm t) + (when (and (processp pro) (eq (process-status pro) 'open)) + (mew-nntp2-set-status pnm "quit") + (mew-nntp2-process-send-string pro "QUIT"))) + +(defun mew-nntp2-command-noop (pro pnm) + ()) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub functions +;;; + +(defconst mew-nntp2-info-prefix "mew-nntp2-info-") + +(defun mew-nntp2-info-name (case) + (let ((server (mew-nntp-server case)) + (port (mew-*-to-string (mew-nntp-port case))) + (sshsrv (mew-nntp-ssh-server case)) + (name mew-nntp2-info-prefix)) + (setq name (concat name server)) + (unless (mew-port-equal port mew-nntp-port) + (setq name (concat name ":" port))) + (if sshsrv + (concat name "%" sshsrv) + name))) + +(defun mew-nntp2-process-send-string (pro &rest args) + (let ((str (apply 'format args))) + (mew-nntp2-debug "=SEND=" str) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-string pro (concat str mew-cs-eol)) + (message "NNTP time out")))) + +(defun mew-nntp2-passtag (pnm) + (let ((server (mew-nntp2-get-server pnm)) + (port (mew-nntp2-get-port pnm)) + (user (mew-nntp2-get-user pnm))) + (concat user "@" server ":" port))) + +(defun mew-nntp2-input-passwd (prompt pnm) + (let* ((tag (mew-nntp2-passtag pnm)) + (pro (mew-nntp2-get-process pnm)) + (pass (mew-input-passwd prompt tag))) + (unless (and (processp pro) (eq (process-status pro) 'open)) + (mew-passwd-set-passwd tag nil)) + pass)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Opening NNTP +;;; + +(defun mew-nntp2-open (pnm server port) + (let ((sprt (mew-*-to-port port)) + pro tm) + (condition-case emsg + (progn + (setq tm (run-at-time mew-nntp-timeout-time nil 'mew-nntp2-timeout)) + (message "Connecting to the NNTP server...") + (setq pro (open-network-stream pnm nil server sprt)) + (mew-process-silent-exit pro) + (mew-set-process-cs pro mew-cs-text-for-net mew-cs-text-for-net) + (message "Connecting to the NNTP server...done")) + (quit + (setq pro nil) + (message "Cannot connect to the NNTP server")) + (error + (setq pro nil) + (message "%s, %s" (nth 1 emsg) (nth 2 emsg)))) + (if tm (cancel-timer tm)) + pro)) + +(defun mew-nntp2-timeout () + (signal 'quit nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Launcher +;;; + +(defun mew-nntp2-send-message (case qfld msgs) + (let ((server (mew-nntp-server case)) + (user (mew-nntp-user case)) + (port (mew-*-to-string (mew-nntp-port case))) + (pnm (mew-nntp2-info-name case)) + (sshsrv (mew-nntp-ssh-server case)) + (sslp (mew-nntp-ssl case)) + (sslport (mew-nntp-ssl-port case)) + process sshname sshpro sslname sslpro lport tls) + (cond + (sshsrv + (setq sshpro (mew-open-ssh-stream case server port sshsrv)) + (when sshpro + (setq sshname (process-name sshpro)) + (setq lport (mew-ssh-pnm-to-lport sshname)) + (when lport + (setq process (mew-nntp2-open pnm "localhost" lport))))) + (sslp + (if (mew-port-equal port sslport) (setq tls mew-tls-nntp)) + (setq sslpro (mew-open-ssl-stream case server sslport tls)) + (when sslpro + (setq sslname (process-name sslpro)) + (setq lport (mew-ssl-pnm-to-lport sslname)) + (when lport + (setq process (mew-nntp2-open pnm mew-ssl-localhost lport))))) + (t + (setq process (mew-nntp2-open pnm server port)))) + (if (null process) + (cond + ((and sshsrv (null sshpro)) + (message "Cannot create to the SSH connection")) + ((and sslp (null sslpro)) + (message "Cannot create to the SSL/TLS connection")) + (t + (message "Cannot connect to the NNTP server"))) + (mew-info-clean-up pnm mew-nntp2-info-list-clean-length) + (mew-nntp2-set-case pnm case) + (mew-nntp2-set-qfld pnm qfld) + (mew-nntp2-set-messages pnm msgs) + (mew-nntp2-set-server pnm server) + (mew-nntp2-set-port pnm port) + (mew-nntp2-set-ssh-server pnm sshsrv) + (mew-nntp2-set-ssh-process pnm sshpro) + (mew-nntp2-set-ssl-process pnm sslpro) + (mew-nntp2-set-user pnm user) + (mew-nntp2-set-account pnm (format "%s@%s" user server)) + (mew-nntp2-set-status pnm "greeting") + ;; + (set-process-buffer process nil) + (set-process-sentinel process 'mew-nntp2-sentinel) + (set-process-filter process 'mew-nntp2-filter) + (message "Posting in background...")))) + +(defun mew-nntp2-flush-queue (case &optional qfld) + (let (msgs) + (unless qfld (setq qfld (mew-postq-folder case))) + (if (mew-nntp2-get-server (mew-nntp2-info-name case)) ;; lock + (message "%s is locked" qfld) + (setq msgs (mew-folder-messages qfld)) + (when msgs + (mew-summary-folder-cache-clean qfld) + (run-hooks 'mew-nntp2-flush-hook) + (message "Flushing %s..." qfld) + (mew-nntp2-send-message case qfld msgs))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel 2 +;;; + +(defun mew-nntp2-debug (label string) + (when (mew-debug 'net) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +(defun mew-nntp2-filter (process string) + (let* ((pnm (process-name process)) + (status (mew-nntp2-get-status pnm)) + (str (concat (mew-nntp2-get-string pnm) string)) + (buf (process-buffer process)) + next func code) + (save-excursion + (mew-nntp2-debug (upcase status) string) + (if (and buf (get-buffer buf)) (set-buffer buf)) + ;; NNTP server's strings should be short enough. + (mew-nntp2-set-string pnm str) + (cond + ((and (string-match "\n$" str) + (string-match "^\\([0-9][0-9][0-9]\\) " str)) + (setq code (match-string 1 str)) + (setq next (mew-nntp2-fsm-next status code)) + (cond + (next + (mew-nntp2-set-status pnm next) + (setq func (intern-soft (concat "mew-nntp2-command-" next))) + (and func (funcall func process pnm)) + (mew-nntp2-set-string pnm nil)) + (t + (if (string-match "^pwd-" status) + (mew-nntp2-set-error pnm "NNTP password is wrong!") + (if (string-match "\n$" str) + (setq str (substring str 0 -1))) + (unless (string-match "[.!]$" str) + (setq str (concat str ".")))) + (mew-nntp2-set-error pnm str) + (mew-nntp2-command-quit2 process pnm)))) + (t ()))))) ;; stay + +(defun mew-nntp2-sentinel (process event) + (let* ((pnm (process-name process)) + (buf (process-buffer process)) + (qfld (mew-nntp2-get-qfld pnm)) + (case (mew-nntp2-get-case pnm)) + (done (mew-nntp2-get-done pnm)) + (imapp (mew-nntp2-get-imapp pnm)) + (error (mew-nntp2-get-error pnm)) + (sshpro (mew-nntp2-get-ssh-process pnm)) + (sslpro (mew-nntp2-get-ssl-process pnm))) + (save-excursion + (mew-nntp2-debug "NNTP SENTINEL" event) + (cond + (error + (when buf + ;; A message file is not inserted at the beginning of the NNTP + ;; session. + (set-buffer buf) + (mew-nntp2-queue case error)) + (mew-nntp2-log pnm error) + (message-box (format "%s This mail has been queued to %s" error qfld))) + (done + (message "Posting in background...done")) + (t + (if (null buf) + (message "NNTP connection is lost") + (set-buffer buf) + (mew-nntp2-queue case "NNTP connection is lost")))) + (mew-info-clean-up pnm) + (if (and (processp sshpro) (not mew-ssh-keep-connection)) + (process-send-string sshpro "exit\n")) + (if (and (processp sslpro) (not mew-ssl-keep-connection)) + (delete-process sslpro)) + (run-hooks 'mew-nntp2-sentinel-hook) + (if imapp (mew-imap2-fcc case)) + (when buf (mew-remove-buffer buf))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Queuing +;;; + +(defun mew-nntp2-queue (case err) + ;; Must be in a buffer where a message is contained. + (let* ((pnm (mew-nntp2-info-name case)) + (qfld (mew-postq-folder case)) + (oname (buffer-name)) + (work (buffer-file-name)) + file-info file info nname) + (mew-local-folder-check qfld) + (setq file-info (mew-queue-enqueue work qfld)) + (mew-set '(file info) file-info) + (setq file (file-name-nondirectory file)) + (setq nname (mew-concat-folder qfld file)) + (if (mew-draft-p) + (mew-nntp2-set-case pnm (mew-tinfo-get-case))) + ;; + (let* ((n mew-nntp2-info-list-save-length) + (data (make-vector n nil))) + (dotimes (i n) + (aset data i (aref (mew-info pnm) i))) + (mew-lisp-save info data)) + ;; + (mew-remove-buffer (current-buffer)) + (message "%s has been queued to %s (%s)" oname nname err) + (mew-touch-folder qfld) + (file-name-sans-extension file))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Logging +;;; + +(defun mew-nntp2-log (pnm &optional err) + (let ((logtime (mew-nntp2-get-logtime pnm)) + (msgid (mew-nntp2-get-msgid pnm)) + (newsgroups (mew-nntp2-get-newsgroups pnm)) + (server (mew-nntp2-get-server pnm)) + (sshsrv (mew-nntp2-get-ssh-server pnm)) + (sslp (mew-nntp2-get-ssl-process pnm))) + (with-temp-buffer + (and logtime (insert logtime)) + (and msgid (insert " id=" msgid)) + (and server (insert " server=" server)) + (and sshsrv (insert " sshsrv=" sshsrv)) + (and sslp (insert " SSL/TLS")) + (and newsgroups (insert " newsgroups=" newsgroups)) + (if err + (insert " status=" "(" + (substring err 0 (string-match "\n+$" err)) + ")") + (insert " status=sent")) + (insert "\n") + (write-region (point-min) (point-max) + (expand-file-name mew-nntp-log-file mew-conf-path) + 'append 'no-msg)))) + +(provide 'mew-nntp2) + +;;; Copyright Notice: + +;; Copyright (C) 1999-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-nntp2.el ends here diff --git a/elpa/mew-20150813.2354/mew-passwd.el b/elpa/mew-20150813.2354/mew-passwd.el new file mode 100644 index 00000000..80d39c9e --- /dev/null +++ b/elpa/mew-20150813.2354/mew-passwd.el @@ -0,0 +1,354 @@ +;;; mew-passwd.el + +;; Author: Kazu Yamamoto +;; Created: May 23, 2006 + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Variables +;;; + +(defvar mew-prog-passwd "gpg") +(defvar mew-passwd-file ".mew-passwd.gpg") +(defvar mew-passwd-cipher "AES") +(defvar mew-passwd-repeat 3) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Internal variables +;;; + +(defvar mew-passwd-encryption-name "GPG Encryption") +(defvar mew-passwd-decryption-name "GPG Decryption") + +(defvar mew-passwd-master nil) +(defvar mew-passwd-alist nil) +(defvar mew-passwd-timer-id nil) +(defvar mew-passwd-rendezvous nil) +(defvar mew-passwd-agent-hack nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; External functions +;;; + +(defun mew-passwd-get-passwd (key) + (nth 1 (assoc key mew-passwd-alist))) + +(defun mew-passwd-set-passwd (key val) + (if (assoc key mew-passwd-alist) + (setcar (nthcdr 1 (assoc key mew-passwd-alist)) val) + (setq mew-passwd-alist (cons (list key val 0) mew-passwd-alist)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Functions +;;; + +(defun mew-passwd-get-counter (key) + (nth 2 (assoc key mew-passwd-alist))) + +(defun mew-passwd-set-counter (key val) + (if (assoc key mew-passwd-alist) + (setcar (nthcdr 2 (assoc key mew-passwd-alist)) val))) + +(defun mew-passwd-get-keys () + (mapcar 'car mew-passwd-alist)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; GPG version +;;; + +(defun mew-passwd-gpg-version () + (when (mew-which mew-prog-passwd exec-path) + (with-temp-buffer + (call-process mew-prog-passwd nil t nil "--version") + (goto-char (point-min)) + (re-search-forward "(GnuPG) " nil t) + (if (looking-at "\\([0-9]+\\)\\.\\([0-9]+\\)") + (list + (string-to-number (match-string 1)) + (string-to-number (match-string 2))))))) + +(defun mew-passwd-check-agent-hack () + (let ((ver (mew-passwd-gpg-version))) + (when ver + (let ((major (nth 0 ver)) + (minor (nth 1 ver))) + (cond + ((= major 1) nil) + ((= major 2) (>= minor 1)) + (t t)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Setup and cleanup +;;; + +(defun mew-passwd-setup () + (when (and mew-use-cached-passwd (not mew-use-master-passwd)) + (if mew-passwd-timer-id (cancel-timer mew-passwd-timer-id)) + (setq mew-passwd-timer-id + (mew-timer (* mew-passwd-timer-unit 60) 'mew-passwd-timer)))) + +(defun mew-passwd-setup-master () + (when (and (not mew-passwd-master) mew-use-master-passwd) + (setq mew-passwd-agent-hack (mew-passwd-check-agent-hack)) + (let ((file (expand-file-name mew-passwd-file mew-conf-path))) + (if (file-exists-p file) + (setq mew-passwd-alist (mew-passwd-load)) + ;; save nil and ask master twice + (mew-passwd-save))) + (add-hook 'kill-emacs-hook 'mew-passwd-clean-up))) + +(defun mew-passwd-clean-up () + (remove-hook 'kill-emacs-hook 'mew-passwd-clean-up) + (when mew-passwd-master + (mew-passwd-save)) + (setq mew-passwd-master nil) + (when (and mew-use-cached-passwd (not mew-use-master-passwd)) + (setq mew-passwd-alist nil) + (if mew-passwd-timer-id (cancel-timer mew-passwd-timer-id)) + (setq mew-passwd-timer-id nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Timer +;;; + +(defun mew-passwd-timer () + (let ((keys (mew-passwd-get-keys))) + (dolist (key keys) + (if (< (mew-passwd-get-counter key) mew-passwd-lifetime) + (mew-passwd-set-counter key (1+ (mew-passwd-get-counter key))) + ;; time out + (mew-passwd-set-passwd key nil) + (mew-passwd-set-counter key 0))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Input +;;; + +(defun mew-input-passwd (prompt key) + (if (and key (or mew-use-cached-passwd mew-use-master-passwd)) + (progn + (mew-passwd-setup-master) + (if (mew-passwd-get-passwd key) + (progn + (mew-timing) + (if mew-passwd-reset-timer (mew-passwd-set-counter key 0)) + (mew-passwd-get-passwd key)) + (let ((pass (mew-read-passwd prompt))) + (mew-passwd-set-passwd key pass) + (mew-passwd-set-counter key 0) + pass))) + (mew-read-passwd prompt))) + +(defun mew-read-passwd (prompt) + (let ((inhibit-input-event-recording t) + ;; A process filter sets inhibit-quit to t to prevent quitting. + ;; Set inhibit-quit to nil so that C-g can be used + (inhibit-quit nil)) + (condition-case nil + (read-passwd prompt) + ;; If read-passwd causes an error, let's return "" so that + ;; the password process will safely fail. + (quit "") + (error "")))) + +(defun mew-passwd-read-passwd (prompt &optional encrypt-p) + (if mew-passwd-master + (progn + (mew-timing) + mew-passwd-master) + (let ((pass (mew-read-passwd prompt))) + (unless encrypt-p (setq mew-passwd-master pass)) + pass))) + +(defun mew-passwd-change () + "Change the master password." + (interactive) + (setq mew-passwd-master nil) + (mew-passwd-save)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Load and save +;;; + +(defmacro mew-passwd-rendezvous (pro) + `(condition-case nil + (let ((inhibit-quit nil)) + (setq mew-passwd-rendezvous t) + (while mew-passwd-rendezvous + (accept-process-output ,pro 0.1 nil t))) + (quit + (setq mew-passwd-rendezvous nil)))) + +(defun mew-passwd-load () + (let* ((process-connection-type mew-connection-type2) + (file (expand-file-name mew-passwd-file mew-conf-path)) + (tfile (mew-make-temp-name "gpg-load")) + (args (mew-passwd-adjust-args (list "-d" "--yes" "--output" tfile file))) + (N mew-passwd-repeat) + pwds pro) + (unwind-protect + (with-temp-buffer + (catch 'loop + (dotimes (i N) + (when mew-passwd-agent-hack (mew-passwd-clear-passphrase file)) + (setq pro (apply 'mew-start-process-lang + mew-passwd-decryption-name + (current-buffer) + mew-prog-passwd + args)) + (set-process-filter pro 'mew-passwd-filter) + (set-process-sentinel pro 'mew-passwd-sentinel) + (mew-passwd-rendezvous pro) + (unless (file-exists-p tfile) + (setq mew-passwd-master nil)) + (when mew-passwd-master + (let ((coding-system-for-read 'undecided)) + (insert-file-contents tfile)) + (condition-case nil + (setq pwds (read (current-buffer))) + (error ())) + (throw 'loop nil))) + (message "Master password is wrong!") + (mew-let-user-read))) + (mew-passwd-delete-file tfile)) + pwds)) + +(defun mew-passwd-save () + (let* ((process-connection-type mew-connection-type2) + (file (expand-file-name mew-passwd-file mew-conf-path)) + (tfile (mew-make-temp-name "gpg-save")) + (args (mew-passwd-adjust-args (list "-c" + "--cipher-algo" mew-passwd-cipher + "--yes" "--output" file tfile))) + (N mew-passwd-repeat) + pro) + (if (file-exists-p file) + (rename-file file (concat file mew-backup-suffix) 'override)) + (unwind-protect + (with-temp-buffer + (pp mew-passwd-alist (current-buffer)) + (write-region (point-min) (point-max) tfile nil 'no-msg) + (catch 'loop + (dotimes (i N) + (setq pro (apply + 'mew-start-process-lang + mew-passwd-encryption-name + (current-buffer) + mew-prog-passwd + args)) + (set-process-filter pro 'mew-passwd-filter) + (set-process-sentinel pro 'mew-passwd-sentinel) + (mew-passwd-rendezvous pro) + (if (file-exists-p file) (throw 'loop nil))) + (message "Master password is wrong! Passwords not saved") + (mew-let-user-read))) + (unless (file-exists-p file) + (rename-file (concat file mew-backup-suffix) file)) + (mew-passwd-delete-file tfile)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defun mew-passwd-filter (process string) + (let* ((name (process-name process)) + (regex (concat "^" (regexp-quote mew-passwd-encryption-name))) + (encrypt-p (string-match regex name))) + (with-current-buffer (process-buffer process) + (cond + ((string-match "invalid passphrase" string) + (mew-warn "Master password mismatch!") + (setq mew-passwd-master nil)) + ((string-match "[bB]ad \\(?:session \\)?key" string) + (mew-warn "Master password is wrong!") + (setq mew-passwd-master nil)) + ((string-match "Enter passphrase:" string) + (process-send-string process (mew-passwd-read-passwd (if encrypt-p "New master password: " "Master password: ") encrypt-p)) + (process-send-string process "\n")) + ((string-match "Repeat passphrase:" string) + (process-send-string process (mew-passwd-read-passwd "New master password again: ")) + (process-send-string process "\n")) + ((string-match "exiting" string) + (setq mew-passwd-rendezvous nil)))))) + +(defun mew-passwd-sentinel (process event) + (setq mew-passwd-rendezvous nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub functions +;;; + +(defun mew-passwd-delete-file (file) + (when (file-exists-p file) + (with-temp-buffer + (let ((coding-system-for-write 'binary) + (size (mew-file-get-size file))) + (dotimes (i size) + (insert 0)) + (write-region (point-min) (point-max) file nil 'no-msg))) + (delete-file file))) + +(defun mew-passwd-get-cache-id (file) + (with-temp-buffer + (call-process mew-prog-passwd nil t nil "--list-packets" file) + (goto-char (point-min)) + (when (re-search-forward "salt \\([^ ,]+\\)," nil t) + (concat "S" (match-string 1))))) + +(defun mew-passwd-clear-passphrase (file) + (when (file-exists-p file) + (let ((cache-id (mew-passwd-get-cache-id file))) + (with-temp-buffer + (insert "CLEAR_PASSPHRASE " cache-id "\n") + (call-process-region (point-min) (point-max) "gpg-connect-agent"))))) + +(defun mew-passwd-adjust-args (args) + (if mew-passwd-agent-hack + (cons "--pinentry-mode" (cons "loopback" args)) + args)) + +(provide 'mew-passwd) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-passwd.el ends here diff --git a/elpa/mew-20150813.2354/mew-pgp.el b/elpa/mew-20150813.2354/mew-pgp.el new file mode 100644 index 00000000..46a8f33f --- /dev/null +++ b/elpa/mew-20150813.2354/mew-pgp.el @@ -0,0 +1,1267 @@ +;;; mew-pgp.el --- PGP/MIME for Mew + +;; Author: Kazu Yamamoto +;; Created: Aug 17, 1994 + +;;; Code: + +(require 'mew) + +;;; +;;; PGP 2.6.x is supported. +;;; PGP 5.x is supported. But very ad-hoc. +;;; GNUPG 1.0.2 or later is supported. +;;; PGP 6.x is supported. But very ad-hoc. +;;; + +(defvar mew-pgp-ver nil + "Automatically set 0 if PGP version is 2. +Set 1 if 5. Set 2 if 6. Set 3 if GNUPG.") + +(defconst mew-pgp-ver2 0) +(defconst mew-pgp-ver5 1) +(defconst mew-pgp-ver6 2) +(defconst mew-pgp-verg 3) +(defconst mew-pgp-list '("PGPv2" "PGPv5" "PGPv6" "GNUPG")) +(defconst mew-pgp-keys '(pgpv2 pgpv5 pgpv6 gnupg)) ;; use symbols, cases are string + +;; mew-prog-pgp is used only for version check +(defvar mew-prog-pgp2 "pgp") ;; "pgp263i", PGP selection +(defvar mew-prog-pgp5 "pgp") ;; PGP selection +(defvar mew-prog-pgp5e "pgpe") +(defvar mew-prog-pgp5s "pgps") +(defvar mew-prog-pgp5v "pgpv") +(defvar mew-prog-pgp5k "pgpk") +(defvar mew-prog-pgp6 "pgp") ;; "pgp651i", PGP selection +(defvar mew-prog-gpg "gpg") ;; PGP selection + +(defvar mew-prog-pgpe + `(,mew-prog-pgp2 ,mew-prog-pgp5e ,mew-prog-pgp6 ,mew-prog-gpg)) +(defvar mew-prog-pgps + `(,mew-prog-pgp2 ,mew-prog-pgp5s ,mew-prog-pgp6 ,mew-prog-gpg)) +(defvar mew-prog-pgpv + `(,mew-prog-pgp2 ,mew-prog-pgp5v ,mew-prog-pgp6 ,mew-prog-gpg)) +(defvar mew-prog-pgpd + `(,mew-prog-pgp2 ,mew-prog-pgp5v ,mew-prog-pgp6 ,mew-prog-gpg)) +(defvar mew-prog-pgpk + `(,mew-prog-pgp2 ,mew-prog-pgp5k ,mew-prog-pgp6 ,mew-prog-gpg)) + +(defconst mew-prog-pgpe-arg + '(("-ea" "+language=en" "+batchmode=on" "+armorlines=0") + ("-a" "+language=en" "+batchmode=on" "+armorlines=0") + ("-ea" "+language=en" "+batchmode=on" "+armorlines=0") + ("--encrypt" "--armor" "--batch"))) + +(defconst mew-prog-pgpd-arg + '(("+language=en" "+batchmode=off") + ("+language=en" "+batchmode=off") + ("+language=en" "+batchmode=off") + ("--decrypt"))) + +(defvar mew-prog-pgps-arg ;; local binding + '(("-sba" "+language=en" "+batchmode=off") + ("-ba" "+language=en" "+batchmode=off") + ("-sba" "+language=en" "+batchmode=off") + ("--detach-sign" "--armor" "--status-fd" "1"))) + +(defconst mew-prog-pgpv-arg + '(("+batchmode=on" "+language=en") + ("+batchmode=on" "+language=en" "+force=on") + ("+batchmode=on" "+language=en") + ("--verify" "--batch"))) + +(defconst mew-prog-old-pgpv-arg + '(("+batchmode=on" "+language=en") + ("+batchmode=on" "+language=en" "+force=on") + ("+batchmode=on" "+language=en") + ("--decrypt" "--batch"))) ;; --verify does not extract original data + +(defconst mew-prog-pgp-arg-output '("-o" "-o" "-o" "--output")) +(defconst mew-prog-pgp-arg-input '(nil "-o" nil nil)) +(defconst mew-prog-pgp-arg-luserid '("-u" "-u" "-u" "--local-user")) +(defconst mew-prog-pgp-arg-ruserid '(nil "-r" nil "--remote-user")) + +(defconst mew-prog-pgpk-add-arg + '(("-ka" "+batchmode=on") + ("-a" "+batchmode=on") + ("-ka" "+batchmode=on") + ("--import" "--batch"))) + +(defconst mew-prog-pgpk-ext-arg + '(("-kxfa") ("-xa") ("+force" "-kxfa") ("--export" "--armor" "--batch"))) + +(defconst mew-pgp-msg-signature + '("\n\\(.*\\) signature from user \\(.*\\)\\." + "\n\\(.*\\) signature made" + "\\([a-zA-Z0-9]*\\) signature from user \\(.*\\)\\." + " \\(.*\\) signature from \"\\(.*\\)\"")) + +(defconst mew-pgp-msg-key-id + '("Key ID \\([a-zA-Z0-9]+\\) not found" + ": 0x\\([a-zA-Z0-9]+\\)" + ": 0x\\([a-zA-Z0-9]+\\)" + "key ID \\([a-zA-Z0-9]+\\)")) + +(defconst mew-pgp-msg-bad-pass + '("No passphrase" + "Cannot unlock private key\\|It can only be decrypted" + "Bad pass phrase" + "bad passphrase")) + +(defconst mew-pgp-msg-enter + '("Enter" "Enter" "Enter" "xxx")) + +(defconst mew-pgp-msg-overwrite + '("Overwrite (y/N)\\? " + "Overwrite (y/N)\\? " + "Overwrite (y/N)\\? " + "Overwrite (y/N)\\? ")) + +(defconst mew-pgp-msg-enter-pass + '("Enter pass phrase: " + "Enter pass phrase: " + "Enter pass phrase: " + "Enter passphrase: ")) + +(defconst mew-pgp-msg-reenter-pass + '("Enter pass phrase: " + "Enter pass phrase: " + "Enter pass phrase: " + "Enter passphrase: ")) + +(defconst mew-pgp-msg-no-enckey + '("Key matching" + "No encryption keys" + "public key matching" + "public key not found")) + +(defconst mew-pgp-msg-no-validkey + '("DUMMY" + "^WARNING:[ -9;-~\n]+belongs? to:" + "^WARNING:[ -9;-~\n]+belongs? to:" + "There is no indication that this key really belongs to the owner")) + +(defconst mew-pgp-msg-pubkey-expired + '("xxx" + "xxx" + "xxx" + "encryption failed: unusable public key")) + +(defconst mew-pgp-msg-no-vrfkey + '("Key matching" "unknown keyid" "key does not meet" "public key not found")) + +(defconst mew-pgp-msg-no-keyring + '("Keyring file" "Keyring file" "NO MESSAGE" "public key not found")) + +(defconst mew-pgp-msg-no-seckey-or-secring + '("You do not have the secret key" + "Cannot find a private key" + "Signature error\\|You do not have the secret key" + "failed: secret key not available")) + +(defconst mew-pgp-msg-unsupported + '("Unsupported packet format" ;; including algorithms and packets + "Unsupported packet format\\|None of the signatures were understood" + "Unsupported packet format" ;; including algorithms and packets + "xxx")) + +(defconst mew-pgp-msg-nocross + '("xxx" + "xxx" + "xxx" + "is not cross-certified")) + +(defconst mew-pgp-verify-addr + '(".* \\(signature from user\\) " + "\\( \\)" + ".* \\(signature from user\\) " + "gpg: .* \\(from\\|aka\\) ")) + +;; 2: ASCII armor corrupted +;; 3: +;; 5: + +;; 2: ERROR: or Error: + +(defconst mew-pgp-msg-no-export-key + '("Key not found" "No keys" "Key not found" "nothing exported")) + +(defvar mew-pgp-micalg '("pgp-md5" "pgp-sha1" "pgp-sha1" "pgp-sha1")) + +(defvar mew-pgp-hash-alist + '(("1" . "pgp-md5") + ("2" . "pgp-sha1") + ("3" . "pgp-ripemd160") + ("5" . "pgp-md2") + ("6" . "pgp-tiger192") + ("7" . "pgp-haval-5-160") + ("8" . "pgp-sha256") + ("9" . "pgp-sha384") + ("10" . "pgp-sha512"))) + +;; +;; + +(defvar mew-pgp-string nil) +(defvar mew-pgp-running nil) +(defvar mew-pgp-failure nil) + +(defvar mew-pgp-decrypt-msg nil) +(defvar mew-pgp-sign-msg nil) + +(defconst mew-pgp-encryption-begin "-----BEGIN PGP MESSAGE-----") +(defconst mew-pgp-signature-begin "-----BEGIN PGP SIGNED MESSAGE-----") +(defconst mew-pgp-key-begin "-----BEGIN PGP PUBLIC KEY BLOCK-----") +(defconst mew-pgp-key-end "-----END PGP PUBLIC KEY BLOCK-----") + +(defconst mew-pgp-err-pass 'mew-err-pass) +(defconst mew-pgp-err-pubring 'mew-err-pubring) +(defconst mew-pgp-err-secring 'mew-err-secring) +(defconst mew-pgp-err-pubkey 'mew-err-pubkey) +(defconst mew-pgp-err-seckey 'mew-err-seckey) +(defconst mew-pgp-err-seckey-or-secring 'mew-err-seckey-or-secring) +(defconst mew-pgp-err-other 'mew-err-other) + +(defvar mew-pgp-result-pass "Pass phrase is wrong") +(defvar mew-pgp-result-pubring "No public keyring") +(defvar mew-pgp-result-secring "No secret keyring") +(defvar mew-pgp-result-pubkey "No his/her public key") +(defvar mew-pgp-result-expired "His/her public key is expired or not signed by yourself") +(defvar mew-pgp-result-invalid + "His/her public key is invalid. Sign the key by yourself, first") +(defvar mew-pgp-result-seckey "No your secret key") +(defvar mew-pgp-result-seckey-or-secring + "No secret keyring or no your secret key") +(defvar mew-pgp-result-other "PGP failed for some reasons") +(defvar mew-pgp-result-sec-succ "PGP decrypted") +(defvar mew-pgp-result-dec-fail "PGP NOT decrypted for some reasons") +(defvar mew-pgp-result-unsup "PGP unsupported signature") +(defvar mew-pgp-result-nocross "His/her Public key is not cross-certified") + +(defvar mew-pgp-prompt-enter-pass "Enter pass phrase (%s): ") +(defvar mew-pgp-prompt-reenter-pass "Re-enter pass phrase (%s): ") + +(defun mew-pgp-get (list-or-vec) + (elt list-or-vec mew-pgp-ver)) + +(defun mew-pgp-set (vec val) + (aset vec mew-pgp-ver val)) + + +(defun mew-pgp-debug (label string) + (when (mew-debug 'pgp) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PGP version check +;;; + +(defun mew-pgp-setup () + (cond + ((mew-which-exec mew-prog-pgp) + (with-temp-buffer + (mew-call-process-lang mew-prog-pgp nil t nil) + (goto-char (point-min)) + (if (search-forward "PGP is now invoked" nil t) + (setq mew-pgp-ver mew-pgp-ver5) + (goto-char (point-min)) + (if (search-forward "Pretty Good Privacy(tm) 2" nil t) + (setq mew-pgp-ver mew-pgp-ver2) + (goto-char (point-min)) + (if (search-forward "gpg" nil t) + (setq mew-pgp-ver mew-pgp-verg) + (goto-char (point-min)) + (if (search-forward "Pretty Good Privacy(tm) Version 6" nil t) + (setq mew-pgp-ver mew-pgp-ver6) + (setq mew-pgp-ver nil))))))) + (t (setq mew-pgp-ver nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PGP selection +;;; + +(defun mew-pgp-select () + "Select PGP version and set up environment for selected PGP." + (interactive) + (setq mew-prog-pgp + (completing-read + "PGP name: " + (mapcar 'list (list mew-prog-pgp2 mew-prog-pgp5 mew-prog-gpg)) + nil t)) + (mew-pgp-setup)) + +;; xxx how about multiple users on local machine? +(defun mew-pgp-passtag () + (mew-pgp-get mew-pgp-list)) + +(defun mew-pgp-passphrase (&optional again) + (let ((prompt (if again + mew-pgp-prompt-reenter-pass + mew-pgp-prompt-enter-pass)) + (msg (mew-pgp-passtag))) + (setq prompt (format prompt msg)) + (mew-input-passwd prompt msg))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PGP verifying +;;; + +(defun mew-pgp-verify-check () + (let (ret keyid) + (goto-char (point-min)) + (if (not (re-search-forward (mew-pgp-get mew-pgp-msg-signature) nil t)) + ;; this is verification, so the error is about public key + (progn + (goto-char (point-min)) + (if (search-forward (mew-pgp-get mew-pgp-msg-no-vrfkey) nil t) + (progn + (goto-char (point-min)) + (if (not (re-search-forward (mew-pgp-get mew-pgp-msg-key-id) nil t)) + (setq keyid "not found") + (setq keyid (format "0x%s"(mew-match-string 1)))) + (setq ret (concat mew-pgp-result-pubkey ": ID = " keyid))) + (if (search-forward (mew-pgp-get mew-pgp-msg-no-keyring) nil t) + (setq ret mew-pgp-result-pubring) + (if (re-search-forward (mew-pgp-get mew-pgp-msg-unsupported) nil t) + (setq ret mew-pgp-result-unsup) + (if (re-search-forward (mew-pgp-get mew-pgp-msg-nocross) nil t) + (setq ret mew-pgp-result-nocross) + ;; this line must be nil since this function is used + ;; by the decryption function, too, for signed-then-encrypted + ;; messages. We cannot tell whether or not signatures exist + ;; from the outside of the cipher. + ))))) + ;; Signature result is found. + (setq ret (concat (mew-match-string 1) " PGP sign ")) + (goto-char (point-max)) + (if (and mew-inherit-decode-signer + (re-search-backward (concat (mew-pgp-get mew-pgp-verify-addr) ".*" mew-inherit-decode-signer) nil t)) + (progn + (beginning-of-line) + (looking-at (concat (mew-pgp-get mew-pgp-verify-addr) "\\(.*\\)")) + (setq ret (concat ret (mew-match-string 2)))) + (goto-char (point-max)) + (re-search-backward (concat (mew-pgp-get mew-pgp-verify-addr) "\\(.*\\)") nil t) + (setq ret (concat ret (mew-match-string 2)))) + ;; xxx + (goto-char (point-min)) + (if (re-search-forward "not certified with \\(enough\\|sufficiently\\)" nil t) + (setq ret (concat ret " MARGINAL")) + (goto-char (point-min)) + (if (search-forward "not trusted" nil t) + (setq ret (concat ret " UNTRUSTED")) + (goto-char (point-min)) + (if (search-forward "not certified with a" nil t) + ;; PGP uses "unknown" for validity internally, but + ;; prints "undefined" instead of "unknown". + (setq ret (concat ret " UNDEFINED")) + (goto-char (point-min)) + (if (search-forward "expired" nil t) + (setq ret (concat ret " EXPIRED")) + (setq ret (concat ret " COMPLETE"))))))) + ret)) + +(defun mew-pgp-verify (file1 file2) + (message "PGP verifying...") + (let ((ioption (mew-pgp-get mew-prog-pgp-arg-input)) ;; detached signature + (voptions (mew-pgp-get mew-prog-pgpv-arg)) + (pgpv (mew-pgp-get mew-prog-pgpv)) + files ret) + (with-temp-buffer + (if ioption + (setq files (list ioption file1 file2)) + (setq files (list file2 file1))) + (apply 'mew-call-process-lang pgpv nil t nil (append voptions files)) + (setq ret (mew-pgp-verify-check))) + (message "PGP verifying...done") + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PGP encrypting +;;; + +(defun mew-pgp-encrypt-check () + (let (ret) ;; this should be nil + (goto-char (point-min)) + (if (re-search-forward (mew-pgp-get mew-pgp-msg-no-validkey) nil t) + (setq ret mew-pgp-result-invalid) + (goto-char (point-min)) + (if (search-forward (mew-pgp-get mew-pgp-msg-no-enckey) nil t) + (setq ret mew-pgp-result-pubkey) + (goto-char (point-min)) + (if (search-forward (mew-pgp-get mew-pgp-msg-no-keyring) nil t) + (setq ret mew-pgp-result-pubring) + (goto-char (point-min)) + (if (search-forward (mew-pgp-get mew-pgp-msg-pubkey-expired) nil t) + (setq ret mew-pgp-result-expired))))) + ret)) + +(defun mew-pgp-encrypt (file1 decrypters) + (message "PGP encrypting...") + (let ((roption (mew-pgp-get mew-prog-pgp-arg-ruserid)) + (ooption (mew-pgp-get mew-prog-pgp-arg-output)) + (eoptions (mew-pgp-get mew-prog-pgpe-arg)) + (pgpe (mew-pgp-get mew-prog-pgpe)) + (file2 (mew-make-temp-name)) + check file3 decs args) ;; not unique if file3 is made here + (with-temp-buffer + (insert "Version: 1\n") + (write-region (point-min) (point-max) file2 nil 'no-msg)) + (setq file3 (concat (mew-make-temp-name) mew-pgp-ascii-suffix)) + (if (and mew-encrypt-to-myself + (not (member mew-inherit-encode-pgp-signer decrypters))) + (setq decrypters (cons mew-inherit-encode-pgp-signer decrypters))) + (setq decrypters + (mapcar (lambda (x) + (if (string-match "^[^<].*@" x) (concat "<" x ">") x)) + decrypters)) + (if (not roption) + (setq args (append (list ooption file3 file1) eoptions decrypters)) + (mapc + (lambda (x) (setq decs (cons roption (cons x decs)))) + decrypters) + (setq args (append eoptions decs (list ooption file3 file1)))) + (with-temp-buffer + (apply 'mew-call-process-lang pgpe nil t nil args) + (setq check (mew-pgp-encrypt-check))) + (message "PGP encrypting...done") + (list file2 mew-7bit file3 mew-7bit check))) ;; both ctes are 7bit + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PGP decrypting +;;; + +(defun mew-pgp-decrypt (file1 file2) + ;; file1 is a key file. just ignore. + ;; file2 is an encrypted file with PGP. + (message "PGP decrypting...") + (setq mew-pgp-running 'decrypting) + (setq mew-pgp-string nil) + (setq mew-pgp-decrypt-msg nil) + (setq mew-pgp-failure nil) + (let ((process-connection-type mew-connection-type2) + (ooption (mew-pgp-get mew-prog-pgp-arg-output)) + (doptions (mew-pgp-get mew-prog-pgpd-arg)) + (pgpd (mew-pgp-get mew-prog-pgpd)) + file3 process verify) + (setq file3 (mew-make-temp-name)) + (setq process + (apply 'mew-start-process-lang + "PGP decrypt" + (current-buffer) + pgpd + (append doptions (list ooption file3 file2)))) + (mew-set-process-cs process mew-cs-autoconv mew-cs-dummy) + (set-process-filter process 'mew-pgp-process-filter1) + (set-process-sentinel process 'mew-pgp-process-sentinel) + (mew-rendezvous mew-pgp-running) + (message "PGP decrypting...done") + (if (file-exists-p file3) + (progn + (with-temp-buffer + (insert mew-pgp-string) + (setq verify (mew-pgp-verify-check))) + (when verify + (setq mew-pgp-decrypt-msg (concat mew-pgp-decrypt-msg "\n\t" verify)))) + ;; unpredictable error + (mew-passwd-set-passwd (mew-pgp-passtag) nil) + (if (string= mew-pgp-decrypt-msg mew-pgp-result-sec-succ) + (setq mew-pgp-decrypt-msg mew-pgp-result-dec-fail))) + (list file3 mew-pgp-decrypt-msg))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PGP signing +;;; + +(defun mew-pgp-canonicalize () + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "[ \t]+$" nil t) + (replace-match "" nil t) + (forward-line)))) + +(defun mew-pgp-get-micalg () + (let ((micalg (mew-pgp-get mew-pgp-micalg)) alg) + (if (/= mew-pgp-ver mew-pgp-verg) + micalg + (with-temp-buffer + (insert mew-pgp-string) + (goto-char (point-min)) + (if (re-search-forward "SIG_CREATED [A-Z] [0-9]+ \\([0-9]+\\)" nil t) + (setq alg (cdr (assoc (mew-match-string 1) mew-pgp-hash-alist))))) + (or alg micalg)))) + +(defun mew-pgp-sign (file1) + (message "PGP signing...") + (setq mew-pgp-running 'signing) + (setq mew-pgp-string nil) + (setq mew-pgp-sign-msg nil) + (setq mew-pgp-failure nil) + (let ((process-connection-type mew-connection-type2) + (loption (mew-pgp-get mew-prog-pgp-arg-luserid)) + (ooption (mew-pgp-get mew-prog-pgp-arg-output)) + (soptions (mew-pgp-get mew-prog-pgps-arg)) + (pgps (mew-pgp-get mew-prog-pgps)) + file2 process) + (setq file2 (concat (mew-make-temp-name) mew-pgp-ascii-suffix)) + ;; not perfectly unique but OK + (setq process + (apply 'mew-start-process-lang + "PGP sign" + (current-buffer) ;; xxx nil? + pgps + (append soptions (list loption mew-inherit-encode-pgp-signer ooption file2 file1)))) + (mew-set-process-cs process mew-cs-autoconv mew-cs-dummy) + (set-process-filter process 'mew-pgp-process-filter1) + (set-process-sentinel process 'mew-pgp-process-sentinel) + (mew-rendezvous mew-pgp-running) + (message "PGP signing...done") + (unless (file-exists-p file2) ;; for unpredictable error + (mew-passwd-set-passwd (mew-pgp-passtag) nil)) + (list file2 nil (mew-pgp-get-micalg) mew-pgp-sign-msg))) ;; return + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PGP process functions +;;; + +(defun mew-pgp-process-sentinel (process event) + (save-excursion + (let ((decrypted mew-pgp-result-sec-succ) + (msg "")) + (if (not mew-pgp-failure) + (cond + ((eq mew-pgp-running 'decrypting) + (setq mew-pgp-decrypt-msg decrypted)) + ((eq mew-pgp-running 'signing) + (setq mew-pgp-sign-msg nil))) + (cond + ;; sign or decrypt + ((eq mew-pgp-failure mew-pgp-err-pass) + (setq msg mew-pgp-result-pass)) + ;; decrypt-then-verify + ((eq mew-pgp-failure mew-pgp-err-pubring) + (setq msg decrypted)) + ;; decrypt-then-verify + ((eq mew-pgp-failure mew-pgp-err-pubkey) + (setq msg decrypted)) + ;; sign + ((eq mew-pgp-failure mew-pgp-err-secring) + (setq msg mew-pgp-result-secring)) + ;; sign + ((eq mew-pgp-failure mew-pgp-err-seckey) + (setq msg mew-pgp-result-seckey)) + ;; decrypt + ((eq mew-pgp-failure mew-pgp-err-seckey-or-secring) + (setq msg mew-pgp-result-seckey-or-secring)) + ;; other + (t ;; mew-pgp-err-other or nil + (setq msg mew-pgp-result-other))) + (cond + ((eq mew-pgp-running 'decrypting) + (setq mew-pgp-decrypt-msg msg)) + ((eq mew-pgp-running 'signing) + (setq mew-pgp-sign-msg msg)))) + (setq mew-pgp-running nil)))) + +(defun mew-pgp-process-filter1 (process string) + (save-excursion + ;; sign or decrypt, not verify + (mew-pgp-debug "PGP filter1" string) + (setq mew-pgp-string (concat mew-pgp-string string)) + (cond + ;; no secret key or no secring for decrypt + ((string-match (mew-pgp-get mew-pgp-msg-no-seckey-or-secring) string) + (setq mew-pgp-failure mew-pgp-err-seckey-or-secring) + (set-process-filter process 'mew-pgp-process-filter3)) + + ;; no secring for sign + ((string-match (mew-pgp-get mew-pgp-msg-no-keyring) string) + (setq mew-pgp-failure mew-pgp-err-secring) + ;; Enter secret key filename: + (process-send-string process "\n") + (set-process-filter process 'mew-pgp-process-filter3)) + + ;; no secret key for sign + ((string-match (mew-pgp-get mew-pgp-msg-no-enckey) string) + (setq mew-pgp-failure mew-pgp-err-seckey) + ;; Enter secret key filename: + (process-send-string process "\n") + (set-process-filter process 'mew-pgp-process-filter3)) + + ;; pass phrase for sign or decrypt + ((string-match (mew-pgp-get mew-pgp-msg-enter-pass) string) + (process-send-string process (format "%s\n" (mew-pgp-passphrase))) + (set-process-filter process 'mew-pgp-process-filter2)) + + ;; overwrite a previous data with a new data. (multiple data is unsupported) + ((string-match (mew-pgp-get mew-pgp-msg-overwrite) string) + (process-send-string process "y\n") + (set-process-filter process 'mew-pgp-process-filter1)) + + ;; just in case + ((string-match (mew-pgp-get mew-pgp-msg-enter) string) + (setq mew-pgp-failure mew-pgp-err-other) + ;; Enter PSWD: + (process-send-string process "\n") + (set-process-filter process 'mew-pgp-process-filter3))))) + +(defun mew-pgp-process-filter2 (process string) + (save-excursion + (mew-pgp-debug "PGP filter2" string) + (setq mew-pgp-string (concat mew-pgp-string string)) + (cond + ;; re-enter pass phrase + ((string-match (mew-pgp-get mew-pgp-msg-reenter-pass) string) + (setq mew-pgp-string nil) + (mew-passwd-set-passwd (mew-pgp-passtag) nil) ;; cancel anyway + (process-send-string process (format "%s\n" (mew-pgp-passphrase 'again))) + (set-process-filter process 'mew-pgp-process-filter2)) + + ;; pass phrases were wrong three times + ((string-match (mew-pgp-get mew-pgp-msg-bad-pass) string) + (setq mew-pgp-failure mew-pgp-err-pass) + (mew-passwd-set-passwd (mew-pgp-passtag) nil) ;; cancel anyway + (set-process-filter process 'mew-pgp-process-filter3)) + + ;; no pubring for verify + ((string-match (mew-pgp-get mew-pgp-msg-no-keyring) string) + (setq mew-pgp-failure mew-pgp-err-pubring) + ;; Enter public key filename: + (process-send-string process "\n") + (set-process-filter process 'mew-pgp-process-filter3)) + + ;; no public key for verify + ((string-match (mew-pgp-get mew-pgp-msg-no-vrfkey) string) + (setq mew-pgp-failure mew-pgp-err-pubkey) + ;; Enter public key filename: + (process-send-string process "\n") + (set-process-filter process 'mew-pgp-process-filter3)) + + ;; after decrypted secret key, symmetric key is not unknown... + ;; gpg: unknown cipher algorithm + ;; no secret key or no secring for decrypt + ((string-match (mew-pgp-get mew-pgp-msg-no-seckey-or-secring) string) + (setq mew-pgp-failure mew-pgp-err-seckey-or-secring) + (set-process-filter process 'mew-pgp-process-filter3)) + + ;; overwrite a previous data with a new data. (multiple data is unsupported) + ((string-match (mew-pgp-get mew-pgp-msg-overwrite) string) + (process-send-string process "y\n") + (set-process-filter process 'mew-pgp-process-filter2)) + + ;; just in case + ((string-match (mew-pgp-get mew-pgp-msg-enter) string) + (setq mew-pgp-failure mew-pgp-err-other) + ;; Enter PSWD: + (process-send-string process "\n") + (set-process-filter process 'mew-pgp-process-filter3))))) + +(defun mew-pgp-process-filter3 (process string) + (save-excursion + (mew-pgp-debug "PGP filter3" string) + ;; ending or error + (setq mew-pgp-string (concat mew-pgp-string string)) + ;; string may contain old "Enter" + (cond + ;; just in case + ((string-match (mew-pgp-get mew-pgp-msg-enter) string) + ;; (setq mew-pgp-failure mew-pgp-err-other) ;; this is wrong + ;; Enter PSWD: + (process-send-string process "\n") + (set-process-filter process 'mew-pgp-process-filter3))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; shortcut methods +;;; + +(defun mew-pgp-sign-message (&optional arg) + "Sign the entire draft with PGP. Input your passphrase." + (interactive "P") + (mew-pgp-encode-message 'pgp-signature arg)) + +(defun mew-pgp-encrypt-message () + "Encrypt the entire draft with PGP." + (interactive) + (mew-pgp-encode-message 'pgp-encryption)) + +(defun mew-pgp-sign-encrypt-message (&optional arg) + "Sign then encrypt the entire draft with PGP. Input your passphrase." + (interactive "P") + (mew-pgp-encode-message 'pgp-signature-encryption)) + +(defun mew-pgp-encrypt-sign-message (&optional arg) + "Encrypt then sign the entire draft with PGP. Input your passphrase." + (interactive "P") + (mew-pgp-encode-message 'pgp-encryption-signature)) + +(defun mew-pgp-encode-message (type &optional ask-signer) + (if (null mew-pgp-ver) + (message "%s does not exist" mew-prog-pgp) + (let ((func 'mew-draft-make-message)) + (if (mew-use-old-pgp (mew-tinfo-get-case)) + (setq func 'mew-old-pgp-encode)) + (if (and ask-signer (string-match "signature" (symbol-name type))) + (funcall func type (car (mew-input-address "Who's key?: "))) + (funcall func type))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; old PGP encoding +;;; + +(defconst mew-prog-old-pgps-arg + '(("-sat" "+clearsig=on" "+language=en" "+batchmode=off") + ("-at" "+clearsig=on" "+language=en" "+batchmode=off") + ("-sat" "+clearsig=on" "+language=en" "+batchmode=off") + ("--clearsign" "--armor" "--textmode"))) + +(defconst mew-prog-old-pgpse-arg + '(("-seat" "+language=en" "+batchmode=off") + ("-eat" "+language=en" "+batchmode=off") + ("-seat" "+language=en" "+batchmode=off") + ("--sign" "--encrypt" "--armor" "--textmode"))) + +(defconst mew-prog-old-pgpe-arg + '(("-eat" "+language=en" "+batchmode=on" "+armorlines=0") + ("-at" "+language=en" "+batchmode=on" "+armorlines=0") + ("-eat" "+language=en" "+batchmode=on" "+armorlines=0") + ("--encrypt" "--armor" "--textmode" "--batch"))) + +(defun mew-old-pgp-encode (type &optional signer) + (let (mew-inherit-encode-pgp-signer doit syntax ctl ct charset cs) + (if (mew-attach-p) + (if (mew-encode-syntax-have-one-part) + (progn + (setq syntax (mew-syntax-get-part mew-encode-syntax)) + (setq ctl (mew-syntax-get-ct syntax)) + (setq ct (mew-syntax-get-value ctl 'cap)) + (if (string= ct mew-ct-txt) + (progn + (setq charset (mew-syntax-get-param ctl "charset")) + (setq cs (mew-charset-to-cs charset)) + (setq doit t) + (mew-attach-clear)) + (message "Old PGP cannot be used for non-text"))) + (message "Old PGP cannot be used if multipart exists")) + (setq doit t)) + (when doit + (setq mew-inherit-encode-pgp-signer (or signer + (mew-pgp-signer (mew-tinfo-get-case)) + (mew-get-my-address))) + (cond + ((eq type 'pgp-signature) + (mew-old-pgp-sign cs syntax)) + ((eq type 'pgp-encryption) + (mew-old-pgp-encrypt cs)) + ((eq type 'pgp-signature-encryption) + (mew-pgp-old-sign-encrypt cs)) + (t + (message "Not supported")))))) + +(defun mew-old-pgp-sign (cs &optional syntax) + (let ((file1 (mew-make-temp-name)) + (mew-prog-pgps-arg mew-prog-old-pgps-arg) + file2 fmc errmsg charset) + (goto-char (mew-header-end)) + (forward-line) + (unless cs + (setq charset (mew-charset-guess-region (point) (point-max))) + (setq cs (mew-charset-to-cs charset))) + (mew-frwlet mew-cs-dummy cs + (write-region (point) (point-max) file1 nil 'no-msg)) + (condition-case nil + (setq fmc (mew-pgp-sign file1)) + (error + (mew-delete-file file1) + (mew-encode-error + (format "unknown error for %s. Check %s, anyway" + mew-ct-mls mew-temp-dir)))) + (mew-set '(file2 nil nil errmsg) fmc) + (if errmsg + (progn + (mew-delete-file file1) + (mew-delete-file file2) + (error errmsg)) + (delete-region (point) (point-max)) + (mew-frwlet cs mew-cs-dummy + (insert-file-contents file2)) + (mew-delete-file file1) + (mew-delete-file file2) + (setq mew-encode-syntax syntax) + (mew-draft-make-message)))) + +(defun mew-old-pgp-encrypt (cs) + (let ((file1 (mew-make-temp-name)) + (mew-prog-pgps-arg mew-prog-old-pgps-arg) + (decrypters (mew-header-parse-address-list mew-destination:-list)) + file2 file3 fc errmsg charset) + (goto-char (mew-header-end)) + (forward-line) + (unless cs + (setq charset (mew-charset-guess-region (point) (point-max))) + (setq cs (mew-charset-to-cs charset))) + (mew-frwlet mew-cs-dummy cs + (write-region (point) (point-max) file1 nil 'no-msg)) + (condition-case nil + (setq fc (mew-pgp-encrypt file1 decrypters)) + (error + (mew-delete-file file1) + (mew-encode-error + (format "unknown error for %s. Check %s, anyway" + mew-ct-mle mew-temp-dir)))) + (mew-set '(file2 nil file3 nil errmsg) fc) + (if errmsg + (progn + (mew-delete-file file1) + (mew-delete-file file2) + (mew-delete-file file3) + (error errmsg)) + ;; Create multipart content-header + (delete-region (point) (point-max)) + (mew-frwlet cs mew-cs-dummy + (insert-file-contents file3)) + (mew-delete-file file1) + (mew-delete-file file2) + (mew-delete-file file3) + (setq mew-encode-syntax nil) + (mew-draft-make-message)))) + +(defun mew-pgp-old-sign-encrypt (cs) + (message "PGP signing then encrypting...") + (let ((decrypters (mew-header-parse-address-list mew-destination:-list)) + (roption (mew-pgp-get mew-prog-pgp-arg-ruserid)) + (loption (mew-pgp-get mew-prog-pgp-arg-luserid)) + (ooption (mew-pgp-get mew-prog-pgp-arg-output)) + (eoptions (mew-pgp-get mew-prog-old-pgpse-arg)) ;; xxx + (pgpe (mew-pgp-get mew-prog-pgpe)) ;; xxx + (file1 (mew-make-temp-name)) + file2 check decs args process charset) + (goto-char (mew-header-end)) + (forward-line) + (unless cs + (setq charset (mew-charset-guess-region (point) (point-max))) + (setq cs (mew-charset-to-cs charset))) + (mew-frwlet mew-cs-dummy cs + (write-region (point) (point-max) file1 nil 'no-msg)) + (if (and mew-encrypt-to-myself + (not (member mew-inherit-encode-pgp-signer decrypters))) + (setq decrypters (cons mew-inherit-encode-pgp-signer decrypters))) + (setq decrypters + (mapcar (lambda (x) + (if (string-match "^[^<].*@" x) (concat "<" x ">") x)) + decrypters)) + (setq file2 (mew-make-temp-name)) + (setq args (list loption mew-inherit-encode-pgp-signer ooption file2 file1)) + (if (not roption) + (setq args (append args eoptions decrypters)) + (dolist (decrypter decrypters) + ;; nreverse later, take care. + (setq decs (cons decrypter (cons roption decs)))) + (setq decrypters (nreverse decs)) + (setq args (append eoptions decrypters args))) + (setq mew-pgp-running 'signing) + (setq mew-pgp-string nil) + (setq mew-pgp-sign-msg nil) + (setq mew-pgp-failure nil) + (with-temp-buffer + (setq process (apply 'mew-start-process-lang + "PGP sign" + (current-buffer) + pgpe args)) + (mew-set-process-cs process mew-cs-autoconv mew-cs-dummy) + (set-process-filter process 'mew-pgp-process-filter1) + (set-process-sentinel process 'mew-pgp-process-sentinel) + (mew-rendezvous mew-pgp-running) + (message "PGP signing then encrypting...done") + (setq check (mew-pgp-encrypt-check))) + (unless (file-exists-p file2) ;; for unpredictable error + (mew-passwd-set-passwd (mew-pgp-passtag) nil)) + (if (or mew-pgp-sign-msg check) + (progn + (mew-delete-file file1) + (mew-delete-file file2) + (error (or mew-pgp-sign-msg check))) + (delete-region (point) (point-max)) + (mew-frwlet cs mew-cs-dummy + (insert-file-contents file2)) + (mew-delete-file file1) + (mew-delete-file file2) + (setq mew-encode-syntax nil) + (mew-draft-make-message)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; old PGP decoding +;;; + +(defun mew-old-pgp-check () + (goto-char (point-min)) + (if (re-search-forward (concat "^" mew-pgp-encryption-begin) nil t) + ;; this may be 'pgp-signature, but we hope clearsig is used... + 'pgp-encryption + (goto-char (point-min)) + (if (re-search-forward (concat "^" mew-pgp-signature-begin) nil t) + 'pgp-signature + nil))) + +(defun mew-old-pgp-verify (file) + (message "PGP verifying...") + (let ((voptions (mew-pgp-get mew-prog-old-pgpv-arg)) + (ooption (mew-pgp-get mew-prog-pgp-arg-output)) + (pgpv (mew-pgp-get mew-prog-pgpv)) + (file1 (mew-make-temp-name)) + verify) + (with-temp-buffer + (apply 'mew-call-process-lang + pgpv nil t nil (append voptions (list ooption file1 file))) + (setq verify (mew-pgp-verify-check))) + (message "PGP verifying...done") + (list file1 verify))) + +(defun mew-summary-decode-old-pgp () + "Decrypting/verifying old-fashioned PGP messages." + (interactive) + (if (null mew-pgp-ver) + (message "%s does not exist" mew-prog-pgp) + (mew-summary-msg + (let ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + type) + (with-current-buffer (mew-buffer-message) + ;; We need MIME-decoded buffer to check PGP boundaries. + (setq type (mew-old-pgp-check)) + (if type + (mew-old-pgp-decode fld msg type) + (message "No PGP data found"))))))) + +(defun mew-old-pgp-decode (fld msg type) + ;; in Message buffer + (let* ((cache (mew-cache-hit fld msg 'must-hit)) + (syntax (mew-cache-decode-syntax cache)) + (file (mew-expand-msg fld msg)) + mew-inherit-decode-signer + file1 file2 result xmew win start cte) + (with-temp-buffer + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (mew-insert-file-contents file) + (re-search-forward mew-eoh nil t) + (forward-line) + (delete-region (point-min) (point)) + (when (eq type 'pgp-signature) + (setq cte (mew-syntax-get-cte (mew-syntax-get-part syntax))) + (mew-decode-mime-body nil mew-ct-txt cte)) + (setq file1 (mew-make-temp-name)) + (write-region (point-min) (point-max) file1 nil 'no-msg))) + (mew-elet + (widen) + (setq win (get-buffer-window (current-buffer))) + (setq start (window-start win)) + (setq mew-inherit-decode-signer + (mew-addrstr-parse-address + (mew-header-get-value mew-from:))) + (goto-char (mew-header-end)) + (forward-line) + (delete-region (point) (point-max)) + (cond + ((eq type 'pgp-encryption) + (setq result (mew-pgp-decrypt 'dummy file1))) + ((eq type 'pgp-signature) + (setq result (mew-old-pgp-verify file1)))) + (mew-set '(file2 xmew) result) + (unless xmew (setq xmew "CRC error")) ;; xxx + (mew-xinfo-set-pri-result + (concat mew-x-mew: " " xmew "\n")) + (save-excursion + (mew-header-delete-lines (list mew-x-mew:)) + (goto-char (mew-header-end)) + (mew-decode-syntax-insert-privacy)) + (when (and file1 (file-exists-p file1)) + (mew-delete-file file1)) + (when (and file2 (file-exists-p file2)) + (mew-frwlet mew-cs-text-for-read mew-cs-dummy + (mew-insert-file-contents file2)) + (mew-delete-file file2)) + (mew-cs-decode-region + (point) (point-max) + ;; This is valid for PGP signature only. + ;; Since cipher text is encoded with Radix 64, charset should + ;; be "US-ASCII". I don't know this code is valid for + ;; cipher text in the case that a wrong charset is specified. + (or (mew-charset-to-cs + (mew-syntax-get-param + (mew-syntax-get-ct (mew-syntax-get-part syntax)) "charset")) + mew-cs-autoconv)) + (mew-highlight-body-region (point) (point-max)) + (mew-message-set-end-of) + (set-window-start win start) + (set-buffer-modified-p nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Key distribution +;;; + +(defun mew-attach-pgp-public-key () + "Extract the PGP key for the specified user on '.'. in attachments" + (interactive) + (if (not (mew-attach-not-line012-1)) + (message "Cannot link here") + (let* ((error nil) + (nums (mew-syntax-nums)) + (subdir (mew-attach-expand-path mew-encode-syntax nums)) + (attachdir (mew-attachdir)) + user file filepath begin end) + ;; attachdir / {subdir/} dir + (unless (string= subdir "") + (setq attachdir (expand-file-name subdir attachdir))) + ;; attachdir / file + (setq filepath (mew-random-filename attachdir 1 nil mew-pgp-key-suffix)) + (if (null filepath) + (message "Cannot make a file for pgp key, sorry") + (setq file (file-name-nondirectory filepath)) + (setq user (car (mew-input-address + "Who's key? (%s): " (mew-get-my-address)))) + (with-temp-buffer + (apply 'mew-call-process-lang + (mew-pgp-get mew-prog-pgpk) + nil t nil + (append + (mew-pgp-get mew-prog-pgpk-ext-arg) + (list user))) + (goto-char (point-min)) + (if (search-forward (mew-pgp-get mew-pgp-msg-no-export-key) nil t) + (setq error t) + (goto-char (point-min)) + (if (not (search-forward mew-pgp-key-begin nil t)) + (setq error t) + (beginning-of-line) + (setq begin (point)) + (if (not (search-forward mew-pgp-key-end nil t)) + (setq error t) + (beginning-of-line) + (forward-line) + (setq end (point))) + (write-region begin end filepath nil 'no-msg)))) + (if error + (message "Cannot extract pgp key for %s" user) + (setq mew-encode-syntax + (mew-syntax-insert-entry + mew-encode-syntax + nums + (mew-encode-syntax-single file mew-type-apk nil user))) + (mew-encode-syntax-print mew-encode-syntax)))))) + +(defvar mew-pgp-tmp-file nil) + +(defun mew-mime-pgp-keys (cache begin end &optional params) + "A function to add PGP keys in Application/PGP-Keys to your +public keyring." + (mew-elet + (insert " ###### ##### ###### # # ####### # #\n" + " # # # # # # # # # # #\n" + " # # # # # # # # # #\n" + " ###### # #### ###### #### ####### #\n" + " # # # # # # # #\n" + " # # # # # # # #\n" + " # ##### # # # ####### #\n" + "\n\n") + (mew-insert-manual + "To add this key to your pubring, type " + "'\\\\[mew-summary-execute-external]'.\n"))) + +(defun mew-mime-pgp-keys-ext (cache begin end &optional params) + "A function to add PGP keys to your public keyring." + (if (not mew-pgp-ver) + (message "PGP not found") + (when (y-or-n-p "Add this PGP key onto your public keyring? ") + (setq mew-pgp-tmp-file (mew-make-temp-name)) + (with-current-buffer cache + (mew-frwlet mew-cs-dummy mew-cs-autoconv + (write-region begin end mew-pgp-tmp-file nil 'no-msg)) + (set-buffer (mew-buffer-message)) + (mew-elet + (message "Adding PGP keys...") + (apply 'mew-call-process-lang + (mew-pgp-get mew-prog-pgpk) + nil t nil + (append (mew-pgp-get mew-prog-pgpk-add-arg) + (list mew-pgp-tmp-file))) + (message "Adding PGP keys...done") + (insert "\n\n" + "**************** IMPORTANT NOTE ****************\n" + "When Mew adds PGP keys onto your public keyring,\n" + "it is careless about both TRUST and VALIDITY.\n" + "It is YOU who set these values. Please use\n") + (cond + ((eq mew-pgp-ver mew-pgp-ver2) + (insert "\"pgp -ke\" and \"pgp -ks\" to change them.\n")) + ((eq mew-pgp-ver mew-pgp-ver5) + (insert "\"pgpk -e\" and \"pgpk -s\" to change them.\n")) + ((eq mew-pgp-ver mew-pgp-ver6) + (insert "\"pgp -ke\" and \"pgp -ks\" to change them.\n")) + ((eq mew-pgp-ver mew-pgp-verg) + (insert "\"gpg --edit-key\" to change them.\n"))) + (insert "If you do not know what TRUST and VALIDITY is,\n" + "you should learn the web of trust system BEFORE\n" + "using PGP to protect your privacy.\n" + "**************** IMPORTANT NOTE ****************\n"))) + (mew-delete-file mew-pgp-tmp-file)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; key fetch +;;; + +(defun mew-pgp-fetch-key-by-xuri () + (let (val uri) + (with-current-buffer (mew-buffer-message) + (catch 'loop + (dolist (key mew-x-pgp-key-list) + (setq val (mew-header-get-value key)) + (when (and val (string-match "http:[^ \t\n]*" val)) + (setq val (mew-match-string 0 val)) + (if (y-or-n-p (format "Fetch a PGP public key from %s? " val)) + (throw 'loop (setq uri val))))))) + (if uri + (mew-pgp-fetch uri) + (message "A PGP key is not fetched")))) + +(defun mew-pgp-fetch-key (arg) + "Fetch a PGP public key. + +A PGP public key is fetch from one of the PGP PKS servers with a +key ID which is extracted from the X-Mew: field. The list of the +PGP PKS servers is specified by 'mew-pgp-pks-servers'. + +If called with \\[universal-argument], a PGP public key is fetched +according to a URL in a field specified by 'mew-x-pgp-key-list'." + (interactive "P") + (if arg + (mew-pgp-fetch-key-by-xuri) + (let (keyid userid xmew) + (with-current-buffer (mew-buffer-message) + (setq userid (mew-header-parse-address mew-from:)) + (setq xmew (mew-header-get-value mew-x-mew:))) + (cond + ((and xmew + (string-match " ID = \\(0x[0-9a-fA-F]+\\)" xmew nil) + (setq keyid (mew-match-string 1 xmew))) + (if (y-or-n-p (format "Fetch the PGP public key for %s? " keyid)) + (mew-pgp-fetch-key-from-pks keyid))) + (userid + (if (y-or-n-p (format "Fetch the PGP public key for %s? " userid)) + (mew-pgp-fetch-key-from-pks userid))) + (t + (message "A PGP key is not fetched")))))) + +(defun mew-pgp-fetch-key-from-pks (&optional id) + (let* ((alist mew-pgp-pks-servers) + (server (car (car alist))) + uri) + (unless id + (setq id (read-string "PGP key id or e-mail address: "))) + (setq server (mew-input-general "PGP key server" alist nil server)) + (unless (mew-pgp-pks-http-port-p server alist) + (setq server (concat server ":" (mew-*-to-string mew-pgp-pks-port)))) + (setq uri (concat "http://" server mew-pgp-pks-lang id)) + (mew-pgp-fetch uri))) + +(defun mew-pgp-fetch (uri) + (message "PGP key fetching...") + (let (pro) + (mew-piolet mew-cs-autoconv mew-cs-autoconv + (setq pro (apply 'start-process + "Mew PGP fetch" + (generate-new-buffer mew-buffer-prefix) + mew-prog-pgpkey + (append mew-prog-pgpkey-args (list uri))))) + (set-process-sentinel pro 'mew-pgp-fetch-process-sentinel))) + +(defun mew-pgp-fetch-process-sentinel (process event) + (message "PGP key fetching...done") + (let ((buf (process-buffer process))) + (with-current-buffer buf + (goto-char (point-min)) + (if (and (search-forward mew-pgp-key-begin nil t) + (search-forward mew-pgp-key-end nil t)) + (mew-mime-pgp-keys-ext (current-buffer) (point-min) (point-max)) + (message "PGP key fetch failed"))) + (mew-remove-buffer buf))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; or +;; +;; no seckey no secring:: <1> +;; You do not have the secret key needed to decrypt this file. +;; +;; <2> +;; Keyring file 'pubring.pgp' does not exist. +;; Enter public key filename: +;; +;; Key matching expected Key ID 1B8BF431 not found in file 'pubring.pgp'. +;; Enter public key filename: +;; +;; <1> +;; +;; A secret key is required to make a signature. +;; Keyring file 'secring.pgp' does not exist. +;; Enter secret key filename: +;; +;; A secret key is required to make a signature. +;; Key matching userid 'foo' not found in file 'secring.pgp'. +;; Enter secret key filename: +;; +;; +;; +;; Keyring file 'pubring.pgp' does not exist. +;; +;; Key matching userid 'foo' not found in file 'pubring.pgp'. +;; +;; +;; Keyring file 'pubring.pgp' does not exist. +;; +;; Key matching expected Key ID 1B8BF431 not found in file 'pubring.pgp'. + +(provide 'mew-pgp) + +;;; Copyright Notice: + +;; Copyright (C) 1994-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-pgp.el ends here diff --git a/elpa/mew-20150813.2354/mew-pick.el b/elpa/mew-20150813.2354/mew-pick.el new file mode 100644 index 00000000..6aecea09 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-pick.el @@ -0,0 +1,853 @@ +;;; mew-pick.el --- Picking up messages for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Pick commands +;;; + +(defun mew-summary-pick-msgs (folder regionp) + (let* ((dir (mew-expand-folder folder)) + (default-directory dir) ;; buffer local + beg end region msg msgs) + (if (mew-mark-active-p) (setq regionp t)) + (cond + (regionp + (setq region (mew-summary-get-region)) + (setq beg (car region)) + (setq end (cdr region)) + (save-excursion + (goto-char beg) + (while (re-search-forward mew-regex-msg-or-part end t) ;; for thread + (setq msg (mew-summary-message-number)) + (setq msg (mew-msg-get-filename msg)) + (setq msgs (cons msg msgs)) + (forward-line))) + (setq msgs (delq nil msgs)) + (setq msgs (nreverse msgs))) + (t + (setq msgs (mew-dir-messages ".")) ;; all messages + (setq msgs (delq nil msgs)))))) + +(defun mew-summary-pick (&optional regionp) + "Pick messages according to a specified pick pattern. +Then put the '*' mark onto them. 'mewl' or 'grep' is called as a +picking command. If called with '\\[universal-argument]', the +target is the region." + (interactive "P") + (mew-pickable + (mew-summary-with-mewl + (let* ((folder (mew-summary-physical-folder)) + (msgs (mew-summary-pick-msgs folder regionp)) + (prompt (format "%s/%s pick" mew-prog-mewl mew-prog-grep)) + (prog mew-prog-grep) + (opts mew-prog-grep-opts) + mew-inherit-pick-mewlp + grepp pattern prog-opts-pat) + (if (not msgs) + (message "No message") + (setq pattern (mew-input-pick-pattern prompt)) + (cond + ((string= pattern "") + (setq prog-opts-pat (mew-input-pick-command prog opts)) + (mew-set '(prog opts pattern) prog-opts-pat) + (setq grepp t)) + (t + (setq pattern (mew-pick-canonicalize-pattern pattern)) + (unless mew-inherit-pick-mewlp (setq grepp t)))) + (if (and grepp (not (mew-which-exec prog))) + (message "'%s' not found" prog) + (cond + (grepp + (mew-sinfo-set-find-key pattern) + (message "Picking messages in %s..." folder) + (setq msgs (mew-summary-pick-with-grep prog opts pattern folder msgs)) + (message "Picking messages in %s...done" folder)) + (t + (mew-sinfo-set-find-key nil) ;; force to ask a user + (message "Picking messages in %s..." folder) + (setq msgs (mew-summary-pick-with-mewl pattern folder msgs)) + (message "Picking messages in %s...done" folder))) + (mew-summary-pick-ls folder msgs))))))) + +(defmacro mew-dolist-eob (spec &rest body) + ;; (declare (indent 1)) + `(let ((--mew-temp-- ,(nth 1 spec)) ,(nth 0 spec)) + (while (and --mew-temp-- (not (eobp))) + (setq ,(nth 0 spec) (car --mew-temp--)) + (setq --mew-temp-- (cdr --mew-temp--)) + ,@body))) +(put 'mew-dolist-eob 'lisp-indent-function 1) + +(defun mew-summary-pick-ls-thread (msgs) + (let* ((preline 0) + (threadmsgs (mew-summary-thread-get-msglst + (mew-vinfo-get-top) 'separator)) + (total (length threadmsgs)) + (msgs2 msgs) + linenum) + (goto-char (point-min)) + (mew-dolist-eob (msg msgs) + (setq linenum (member msg threadmsgs)) + (if (null linenum) + (setq msgs2 (delete (car msgs) msgs2)) + (setq linenum (- total (length linenum))) + (forward-line (- linenum preline)) + (setq preline linenum) + (mew-summary-mark-as mew-mark-review))) + (set-buffer-modified-p nil) + msgs2)) + +(defun mew-summary-pick-ls-selection (msgs) + ;; messages are not displayed in order + (goto-char (point-min)) + (let (msgs2) + (mew-dolist-eob (msg msgs) + (when (mew-summary-search-msg msg) + (setq msgs2 (cons (car msgs) msgs2)) + (mew-summary-mark-as mew-mark-review)) + (forward-line)) + (set-buffer-modified-p nil) + (nreverse msgs2))) + +(defun mew-summary-pick-ls-summary (folder msgs) + (when (get-buffer folder) + (set-buffer folder) + (save-excursion + (goto-char (point-min)) + (mew-dolist-eob (msg msgs) + (when (re-search-forward (mew-regex-sumsyn-msg msg) nil t) + (mew-summary-mark-as mew-mark-review) + (forward-line)))) + (set-buffer-modified-p nil))) + +(defun mew-summary-pick-ls (folder msgs) + (if (null msgs) + (message "No message to be marked") + (let ((n (length msgs)) msgs2) + (if (= n 1) + (message "Marking 1 message...") + (message "Marking %d messages..." n)) + (save-excursion + (cond + ((mew-thread-p) + (setq msgs2 (mew-summary-pick-ls-thread msgs))) + ((mew-selection-p) + (setq msgs2 (mew-summary-pick-ls-selection msgs))) + (t ;; Summary mode + (setq msgs2 msgs))) + (mew-summary-pick-ls-summary folder msgs2)) + (if (= n 1) + (message "Marking 1 message...done") + (message "Marking %d messages...done" n))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Pick internal +;;; + +(defun mew-summary-pick-range (src-msgs) + (when src-msgs + (let* ((min (string-to-number (car src-msgs))) + (max min) + i) + (setq src-msgs (cdr src-msgs)) + (dolist (src-msg src-msgs) + (setq i (string-to-number src-msg)) + (if (< i min) (setq min i)) + (if (> i max) (setq max i))) + (format "%d-%d" min max)))) + +(defun mew-summary-pick-with-mewl (pattern folder src-msgs) + "A function to pick messages matching PATTERN with 'mewl'" + (let ((pfolder (mew-scan-mewl-folder (mew-expand-folder2 folder))) + (range (mew-summary-pick-range src-msgs)) + (opts (list "-b" mew-mail-path + "-l" (number-to-string mew-scan-max-field-length) + "-x" mew-suffix + "-p" pattern)) + msgs) + (if range + (setq opts (nconc opts (list pfolder range))) + (setq opts (nconc opts (list pfolder)))) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (mew-piolet mew-cs-text-for-read mew-cs-text-for-write + (apply 'call-process mew-prog-mewl nil t nil opts)) + (goto-char (point-min)) + (while (re-search-forward mew-regex-message-files2 nil t) + (setq msgs (cons (mew-match-string 1) msgs)) + (forward-line))) + (nreverse msgs))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Grep +;;; + +(defun mew-summary-pick-with-grep (prog opts pattern folder src-msgs) + "A function to pick messages matching PATTERN." + (let* ((dir (mew-expand-folder folder)) + (default-directory dir) ;; buffer local + msgs nxt) + ;; no sort here + (if (= (length src-msgs) 1) (setq src-msgs (cons null-device src-msgs))) + (if pattern (setq pattern (mew-cs-encode-arg pattern))) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (cd dir) + (mew-piolet mew-cs-text-for-read mew-cs-text-for-write + (while src-msgs + (goto-char (point-max)) + (setq nxt (nthcdr mew-prog-grep-max-msgs src-msgs)) + (if nxt (mew-ntake mew-prog-grep-max-msgs src-msgs)) + (apply 'call-process prog nil t nil + (append opts (and pattern (list pattern)) src-msgs)) + (setq src-msgs nxt))) + (goto-char (point-min)) + (while (re-search-forward mew-regex-message-files2 nil t) + (setq msgs (cons (mew-match-string 1) msgs)) + (forward-line))) + (setq msgs (mew-uniq-list msgs)) + (setq msgs (mapcar 'string-to-number msgs)) + (setq msgs (sort msgs '<)) + (mapcar 'number-to-string msgs))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Displaying keyword +;;; + +(defun mew-summary-find-keyword-down (&optional arg) + "Display a message in the forward direction, find a keyword +and highlight it. +In Summary mode, the target is messages marked with '*'. +In Virtual mode, the target is all messages in a Virtual folder. +The keyword is stored in a buffer local variable in Summary mode. +If no keyword is set to the variable, this command first asks you +for a keyword. +If you want to change the stored keyword, execute this command with '\\[universal-argument]'." + (interactive "P") + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (fid (mew-frame-id)) + (ofld (mew-current-get-fld fid)) + (omsg (mew-current-get-msg fid)) + (cwin (get-buffer-window (current-buffer))) + (mbuf (mew-buffer-message)) + (mwin (get-buffer-window mbuf)) + (key (mew-sinfo-get-find-key)) + (mark (mew-summary-get-mark)) + (virtualp (mew-virtual-p)) + (search t) + end top) + (when (or arg (not (stringp key))) + (setq key (read-string + "Keyword: " (or (car mew-input-pick-pattern-hist) key))) + (mew-sinfo-set-find-key key)) + (cond + ((and (or virtualp (equal mew-mark-review mark)) ;; MUST be equal + (or (not (string= fld ofld)) (not (string= msg omsg)))) + (mew-summary-display-asis) + (setq top t)) + ((or (null mwin) + (not (or virtualp (equal mew-mark-review mark))) ;; MUST be equal + (or (not (string= fld ofld)) (not (string= msg omsg))) + (with-current-buffer mbuf (eobp))) + (cond + (virtualp + (forward-line) + (mew-summary-display-asis) + (setq top t)) + ((mew-summary-down-mark mew-mark-review) + (mew-summary-display-asis) + (setq top t)) + (t + (setq search nil))))) + (setq mwin (get-buffer-window mbuf)) + (if (not search) + (message "No more marked messages") + (select-window mwin) + (unwind-protect + (progn + (if top (goto-char (point-min))) + (if (setq end (re-search-forward key nil t)) + (progn + (isearch-highlight (- end (length key)) end) + (recenter (/ (window-height) 2))) + (goto-char (point-max)) + (message "Keyword '%s' is not found" key) + (recenter -1))) + (select-window cwin))))) + +(defun mew-summary-find-keyword-up (&optional arg) + "Display a message in the backward direction, find a keyword +and highlight it. +In Summary mode, the target is messages marked with '*'. +In Virtual mode, the target is all messages in a Virtual folder. +The keyword is stored in a buffer local variable in Summary mode. +If no keyword is set to the variable, this command first asks you +for a keyword. +If you want to change the stored keyword, execute this command with '\\[universal-argument]'." + (interactive "P") + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (fid (mew-frame-id)) + (ofld (mew-current-get-fld fid)) + (omsg (mew-current-get-msg fid)) + (cwin (get-buffer-window (current-buffer))) + (mbuf (mew-buffer-message)) + (mwin (get-buffer-window mbuf)) + (key (mew-sinfo-get-find-key)) + (mark (mew-summary-get-mark)) + (virtualp (mew-virtual-p)) + (search t) + beg bottom) + (when (or arg (not (stringp key))) + (setq key (read-string + "Keyword: " (or (car mew-input-pick-pattern-hist) key))) + (mew-sinfo-set-find-key key)) + (cond + ((and (or virtualp (equal mew-mark-review mark)) ;; MUST be equal + (or (not (string= fld ofld)) (not (string= msg omsg)))) + (mew-summary-display-asis) + (setq bottom t)) + ((or (null mwin) + (not (or virtualp (equal mew-mark-review mark))) ;; MUST be equal + (or (not (string= fld ofld)) (not (string= msg omsg))) + (with-current-buffer mbuf (bobp))) + (cond + (virtualp + (forward-line -1) + (mew-summary-display-asis) + (setq bottom t)) + ((mew-summary-up-mark mew-mark-review) + (mew-summary-display-asis) + (setq bottom t)) + (t + (setq search nil))))) + (setq mwin (get-buffer-window mbuf)) + (if (not search) + (message "No more marked messages") + (select-window mwin) + (unwind-protect + (progn + (if bottom (goto-char (point-max))) + (if (setq beg (re-search-backward key nil t)) + (progn + (isearch-highlight beg (+ beg (length key))) + (recenter (/ (window-height) 2))) + (goto-char (point-min)) + (message "Keyword '%s' is not found" key) + (recenter 0))) + (select-window cwin))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Pick macro +;;; + +(defvar mew-pick-macro-alist nil) + +(defun mew-pick-define-macro (str1 str2) + "Define pick macro." + (interactive (list (read-string "Pick pattern: ") + (read-string "Macro body: "))) + ;; macro-pattern is a string including no #, or + ;; a string in a form FIELD=#1 #2 #3...#n. + ;; #1 can be replaced by #. + (let (args body asc value) + (while (string-match "\\(#[0-9]*\\)[, ]*" str1) + (setq args (cons (intern (match-string 1 str1)) args)) + (setq str1 (replace-match "" nil t str1))) + (while (string-match "#[0-9]*" str2) + (setq body (cons (substring str2 0 (match-beginning 0)) body)) + (setq body (cons (intern (match-string 0 str2)) body)) + (setq str2 (substring str2 (match-end 0)))) + (setq body (cons str2 body)) + (setq asc (assoc str1 mew-pick-macro-alist)) + (setq value (cons (nreverse args) (nreverse body))) + (if asc + (setcdr asc value) + (setq mew-pick-macro-alist + (cons (cons str1 value) mew-pick-macro-alist))))) + +(defun mew-pick-macro-expand (name args) + (let ((asc (assoc name mew-pick-macro-alist)) + alist args2 body body-copy assq) + (if (not asc) + name + (setq args2 (nth 1 asc)) + (setq body (nthcdr 2 asc)) + (while (and args args2) + (setq alist (cons (cons (car args2) (car args)) alist)) + (setq args (cdr args)) + (setq args2 (cdr args2))) + (dolist (bd body) + (if (stringp bd) + (setq body-copy (cons bd body-copy)) + (setq assq (assq bd alist)) + (if assq (setq body-copy (cons (cdr assq) body-copy))))) + (concat "(" + (mew-pick-macro-expand-string + (apply 'concat (nreverse body-copy))) + ")")))) + +(defun mew-pick-macro-expand-string (str) + (if (string= str "") + "" + (let ((first (string-to-char str)) + asc key rest eq-flag val args) + (if (memq first (list ?\( ?\! ?\& ?\| ?= mew-sp ?\))) + (concat (char-to-string first) + (mew-pick-macro-expand-string (substring str 1))) + (if (string-match "=\\| \\|)\\|&\\||" str) + (if (string= (match-string 0 str) "=") + (progn + (setq eq-flag t) + (setq key (substring str 0 (match-end 0))) + (setq rest (substring str (match-end 0)))) + (setq key (substring str 0 (match-beginning 0))) + (setq rest (substring str (match-beginning 0)))) + (setq key str) + (setq rest "")) + (setq asc (assoc key mew-pick-macro-alist)) + (cond + (asc + (setq args (nth 1 asc)) + (while args + (if (string-match ",\\| \\|)\\|&\\||" rest) + (progn + (setq val (cons (substring rest 0 (match-beginning 0)) val)) + (setq rest (substring rest (match-beginning 0)))) + (setq val (cons rest val)) + (setq rest "")) + (setq args (cdr args))) + (concat + (mew-pick-macro-expand key (nreverse val)) + (mew-pick-macro-expand-string rest))) + (eq-flag + (if (string-match " \\|)\\|&\\||" rest) + (progn + (setq val (substring rest 0 (match-beginning 0))) + (setq rest (substring rest (match-beginning 0)))) + (setq val rest) + (setq rest "")) + (concat key val (mew-pick-macro-expand-string rest))) + (t + (concat key (mew-pick-macro-expand-string rest)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Lex and Parser +;;; + +(defmacro mew-pick-lex-cut () + `(when (and start (< start i)) + (let ((word (substring pattern start i)) key op val) + ;; Allowing "to,cc" + (if (string-match "^\\([-a-z0-9,]+\\)\\(!?==?\\)\\(.+\\)$" word) + (progn + (setq key (mew-match-string 1 word)) + (setq op (mew-match-string 2 word)) + (setq val (mew-match-string 3 word)) + (setq val (mew-remove-single-quote val)) + (setq ret (cons (list op key val) ret))) + (setq word (mew-remove-single-quote word)) + (setq ret (cons word ret))) + (setq start nil)))) + +(defun mew-pick-lex (pattern) + (let ((len (length pattern)) + (i 0) ret start c dq) + (while (< i len) ;; cannot use dotimes + (setq c (aref pattern i)) + (cond + (dq + (if (or (char-equal c ?\") (char-equal c ?')) (setq dq nil))) + ((or (char-equal c ?\") (char-equal c ?')) + (unless start (setq start i)) + (setq dq t)) + ((char-equal c ?\() + (mew-pick-lex-cut) + (setq ret (cons 'open ret))) + ((char-equal c ?\)) + (mew-pick-lex-cut) + (setq ret (cons 'close ret))) + ((char-equal c ?&) + (mew-pick-lex-cut) + (setq ret (cons 'and ret))) + ((char-equal c ?|) + (mew-pick-lex-cut) + (setq ret (cons 'or ret))) + ((and (char-equal c ?!) + (not (char-equal (aref pattern (1+ i)) ?=))) + (mew-pick-lex-cut) + (setq ret (cons 'not ret))) + ((char-equal c mew-sp) + (mew-pick-lex-cut)) + (t + (unless start (setq start i)))) + (setq i (1+ i))) + (mew-pick-lex-cut) + (nreverse ret))) + +(defun mew-pick-parse (mew-inherit-pick-tokens) + (let (mew-inherit-pick-ret) + (mew-pick-parse1) + (nreverse mew-inherit-pick-ret))) + +(defun mew-pick-parse1 () + (when mew-inherit-pick-tokens + (mew-pick-parse-elements) + (while mew-inherit-pick-tokens + (mew-pick-parse-and/or)))) + +(defun mew-pick-parse-elements () + (let ((cur (car mew-inherit-pick-tokens))) + (setq mew-inherit-pick-tokens (cdr mew-inherit-pick-tokens)) + (setq mew-inherit-pick-mewlp t) + (cond + ((stringp cur) + (setq mew-inherit-pick-mewlp nil) + (setq mew-inherit-pick-ret (cons cur mew-inherit-pick-ret))) + ((listp cur) + (setq mew-inherit-pick-ret (cons cur mew-inherit-pick-ret))) + ((eq cur 'open) + (mew-pick-parse-open/close)) + ((eq cur 'close) + (error "')' alone")) + ((eq cur 'not) + (mew-pick-parse-not)) + ((eq cur 'and) + (error "'&' alone")) + ((eq cur 'or) + (error "'|' alone"))))) + +(defun mew-pick-parse-and/or () + (setq mew-inherit-pick-mewlp t) + (let ((cur (car mew-inherit-pick-tokens))) + (cond + ((or (stringp cur) (listp cur)) + (unless mew-inherit-pick-omit-and + (setq mew-inherit-pick-ret (cons 'and mew-inherit-pick-ret))) + (mew-pick-parse-elements)) + ((eq cur 'open) + (unless mew-inherit-pick-omit-and + (setq mew-inherit-pick-ret (cons 'and mew-inherit-pick-ret))) + (setq mew-inherit-pick-tokens (cdr mew-inherit-pick-tokens)) + (mew-pick-parse-open/close)) + ((eq cur 'close) + (error "')' alone")) + ((eq cur 'not) + (unless (or mew-inherit-pick-omit-and2 mew-inherit-pick-omit-and) + (setq mew-inherit-pick-ret (cons 'and mew-inherit-pick-ret))) + (setq mew-inherit-pick-tokens (cdr mew-inherit-pick-tokens)) + (mew-pick-parse-not)) + ((eq cur 'and) + (unless mew-inherit-pick-omit-and + (setq mew-inherit-pick-ret (cons 'and mew-inherit-pick-ret))) + + (setq mew-inherit-pick-tokens (cdr mew-inherit-pick-tokens)) + (mew-pick-parse-elements)) + ((eq cur 'or) + (setq mew-inherit-pick-ret (cons 'or mew-inherit-pick-ret)) + (setq mew-inherit-pick-tokens (cdr mew-inherit-pick-tokens)) + (mew-pick-parse-elements))))) + +(defun mew-pick-parse-not () + (if (eq (car mew-inherit-pick-ret) 'not) + (setq mew-inherit-pick-ret (cdr mew-inherit-pick-ret)) + (setq mew-inherit-pick-ret (cons 'not mew-inherit-pick-ret))) + (mew-pick-parse-elements)) + +(defun mew-pick-parse-open/close () + (let ((sub mew-inherit-pick-tokens) + (level 0) + cur prv pprv found) + (catch 'loop + (while mew-inherit-pick-tokens + (setq pprv prv) + (setq prv mew-inherit-pick-tokens) + (setq cur (car mew-inherit-pick-tokens)) + (setq mew-inherit-pick-tokens (cdr mew-inherit-pick-tokens)) + (cond + ((eq cur 'open) + (setq level (1+ level))) + ((eq cur 'close) + (if (/= level 0) + (setq level (1- level)) + (if (not pprv) (error "'( )' is empty")) + (setcdr pprv nil) + (let ((mew-inherit-pick-tokens sub)) + (setq mew-inherit-pick-ret (cons 'open mew-inherit-pick-ret)) + (mew-pick-parse1) + (setq mew-inherit-pick-ret (cons 'close mew-inherit-pick-ret))) + (throw 'loop (setq found t))))))) + (unless found (error "')' alone")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Canonicalizer +;;; + +(defun mew-pick-native-text (prefix token) + (let (suffix func) + (cond + ((eq token 'and) + (setq suffix "and")) + ((eq token 'or) + (setq suffix "or")) + ((eq token 'open) + (setq suffix "open")) + ((eq token 'close) + (setq suffix "close")) + ((eq token 'not) + (setq suffix "not")) + ((stringp token) + (setq suffix "key")) + ((listp token) + (setq suffix "kyvl"))) + (when suffix + (setq func (intern (concat prefix suffix))) + (if (fboundp func) (funcall func token))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; mewl/grep +;;; + +(defun mew-pick-canonicalize-pattern (pattern) + (mapconcat + 'mew-pick-native-text-mewl + (mew-pick-parse (mew-pick-lex pattern)) + " ")) + +(defun mew-pick-native-text-mewl (token) + (mew-pick-native-text "mew-pick-pattern-mewl-" token)) + +(defun mew-pick-pattern-mewl-and (sym) "&") +(defun mew-pick-pattern-mewl-or (sym) "|") +(defun mew-pick-pattern-mewl-open (sym) "(") +(defun mew-pick-pattern-mewl-close (sym) ")") +(defun mew-pick-pattern-mewl-not (sym) "!") +(defun mew-pick-pattern-mewl-key (key) key) +(defun mew-pick-pattern-mewl-kyvl (kyvl) + (format "%s%s%s" (nth 1 kyvl) (nth 0 kyvl) (nth 2 kyvl))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Hyper Estraier +;;; + +(defun mew-pick-canonicalize-pattern-est (pattern) + (let ((mew-inherit-pick-omit-and2 t)) + (mapconcat + 'mew-pick-native-text-est + (mew-pick-parse (mew-pick-lex pattern)) + " "))) + +(defun mew-pick-native-text-est (token) + (mew-pick-native-text "mew-pick-pattern-est-" token)) + +(defun mew-pick-pattern-est-and (sym) "AND") +(defun mew-pick-pattern-est-or (sym) "OR") +(defun mew-pick-pattern-est-open (sym) (error "'(' is not supported")) +(defun mew-pick-pattern-est-close (sym) (error "')' is not supported")) +(defun mew-pick-pattern-est-not (sym) "ANDNOT") +(defun mew-pick-pattern-est-key (key) key) +(defun mew-pick-pattern-est-kyvl (kyvl) + (error "'%s' is not supported" kyvl)) + +(defvar mew-pick-filter-est-head-fields "date,subject,from,to,cc,resent-from,resent-to,resent-cc,reply-to,mail-followup-to,x-mail-count,x-ml-count,x-ml-name,x-seqno,x-sequence,mailinglist-id,message-id,in-reply-to,references,newsgroups,followup-to") + +(defun mew-pick-filter-est-kyvl (kyvl) + (unless (and (listp kyvl) (= (length kyvl) 3)) + (error "Filter %s is invalid" kyvl)) + (let ((op (nth 0 kyvl)) + (ky (nth 1 kyvl)) + (vl (nth 2 kyvl))) + (if (string= ky "head") + (setq ky mew-pick-filter-est-head-fields)) + (cond + ((string= op "=") + (setq op "ISTRINC")) + ((string= op "==") + (setq op "STRINC")) + ((string= op "!=") + (setq op "!ISTRINC")) + ((string= op "!==") + (setq op "!STRINC")) + (t + (error "'%s' is not supported" op))) + (format "%s %s %s" ky op vl))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Google +;;; + +(defun mew-pick-canonicalize-pattern-google (pattern) + (let ((mew-inherit-pick-omit-and t) + (tokens (mew-pick-parse (mew-pick-lex pattern))) + ret) + (dolist (token tokens) + (if (eq token 'not) + (if (stringp (car tokens)) + (progn + (setq ret (cons (concat "-" (car tokens)) ret)) + (setq tokens (cdr tokens))) + nil) ;; xxx + (setq ret (cons token ret)))) + (mapconcat + 'mew-pick-native-text-google + (nreverse ret) + " "))) + +(defun mew-pick-native-text-google (token) + (mew-pick-native-text "mew-pick-pattern-google-" token)) + +(defun mew-pick-pattern-google-and (sym) "and") +(defun mew-pick-pattern-google-or (sym) "or") +(defun mew-pick-pattern-google-open (sym) (error "'(' is not supported")) +(defun mew-pick-pattern-google-close (sym) (error "')' is not supported")) +(defun mew-pick-pattern-google-not (sym) "-") +(defun mew-pick-pattern-google-key (key) key) +(defun mew-pick-pattern-google-kyvl (kyvl) + (let ((op (nth 0 kyvl))) + (error "'%s' is not supported" op))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; WDS +;;; + +(defun mew-pick-canonicalize-pattern-wds (pattern) + (let ((mew-inherit-pick-omit-and t) + (tokens (mew-pick-parse (mew-pick-lex pattern))) + ret) + (dolist (token tokens) + (if (eq token 'not) + (if (stringp (car tokens)) + (progn + (setq ret (cons (concat "-" (car tokens)) ret)) + (setq tokens (cdr tokens))) + nil) ;; xxx + (setq ret (cons token ret)))) + (mapconcat + 'mew-pick-native-text-wds + (nreverse ret) + " "))) + +(defun mew-pick-native-text-wds (token) + (mew-pick-native-text "mew-pick-pattern-wds-" token)) + +(defun mew-pick-pattern-wds-and (sym) "") +(defun mew-pick-pattern-wds-or (sym) "OR") +(defun mew-pick-pattern-wds-open (sym) "(") +(defun mew-pick-pattern-wds-close (sym) ")") +(defun mew-pick-pattern-wds-not (sym) "-") +(defun mew-pick-pattern-wds-key (key) key) +(defun mew-pick-pattern-wds-kyvl (kyvl) + (let ((op (nth 0 kyvl))) + (error "'%s' is not supported" op))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Spotlight +;;; + +(defun mew-pick-canonicalize-pattern-spotlight (pattern) + (let* ((tokens (mew-pick-parse (mew-pick-lex pattern))) + (str (mapconcat + 'mew-pick-native-text-spotlight + tokens + " "))) + (concat "kMDItemContentType == \"mew\"w && " str))) + +(defun mew-pick-native-text-spotlight (token) + (mew-pick-native-text "mew-pick-pattern-spotlight-" token)) + +(defun mew-pick-pattern-spotlight-and (sym) "&&") +(defun mew-pick-pattern-spotlight-or (sym) "||") +(defun mew-pick-pattern-spotlight-open (sym) "(") +(defun mew-pick-pattern-spotlight-close (sym) ")") +(defun mew-pick-pattern-spotlight-not (sym) (error "'!' is not supported")) +(defun mew-pick-pattern-spotlight-key (key) + (format "kMDItemTextContent == \"%s\"wc" key)) +(defun mew-pick-pattern-spotlight-kyvl (kyvl) + (let ((op (nth 0 kyvl)) + (ky (nth 1 kyvl)) + (vl (nth 2 kyvl)) + kmd) + (cond + ((string= ky "subject") + (setq kmd "kMDItemTitle")) + ((string= ky "from") + (setq kmd "kMDItemAuthors")) + ((string= ky "body") + (setq kmd "kMDItemTextContent")) + (t + (error "'%s' is not supported" ky))) + (cond + ((string= op "=") + (format "%s == \"%s\"wc" kmd vl)) + ((string= op "==") + (format "%s == \"%s\"w" kmd vl)) +;; ((string= op "!=") +;; (format "%s != \"%s\"wc" kmd vl)) +;; ((string= op "!==") +;; (format "%s != \"%s\"c" kmd vl)) + (t + (error "'%s' is not supported" op))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Old +;;; + +(defun mew-summary-grep-old () + "Obsoleted command." + (interactive) + (mew-message-for-summary "This command was obsoleted. Use '\\[mew-summary-pick]'")) + + +(provide 'mew-pick) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-pick.el ends here diff --git a/elpa/mew-20150813.2354/mew-pkg.el b/elpa/mew-20150813.2354/mew-pkg.el new file mode 100644 index 00000000..61c16b4a --- /dev/null +++ b/elpa/mew-20150813.2354/mew-pkg.el @@ -0,0 +1,4 @@ +(define-package "mew" "20150813.2354" "Messaging in the Emacs World" 'nil) +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/mew-20150813.2354/mew-pop.el b/elpa/mew-20150813.2354/mew-pop.el new file mode 100644 index 00000000..025a0d74 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-pop.el @@ -0,0 +1,991 @@ +;;; mew-pop.el + +;; Author: Kazu Yamamoto +;; Created: Jun 28, 2000 + +;;; Code: + +(require 'mew) + +(defvar mew-pop-msgid-file ".mew-msgid") +(defvar mew-pop-folder-alist (list (mew-folder-func mew-pop-inbox-folder))) +(defun mew-pop-folder-alist () + mew-pop-folder-alist) + +;; It is impossible to implement mew-pop-skip-uidl since +;; messages cannot be gained access by UID. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; POP info +;;; + +(defvar mew-pop-info-list + '("server" "port" "process" "ssh-process" "ssl-process" "status" + "directive" "bnm" "mdb" + "rtrs" "dels" "refs" "rmvs" "kils" "left" "uidl" "range" + "rttl" "rcnt" "dttl" "dcnt" "hlds" + "user" "auth" "auth-list" "key" "passwd" "account" + "size" "truncated" "get-body" + "flush" "no-msg" "msgdb" "done" "dispatched" "error" + "body-lines" "delete" "case" + "virtual-info" "disp-info" "status-buf")) + +(mew-info-defun "mew-pop-" mew-pop-info-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; FSM +;;; + +(defvar mew-pop-fsm + '(("greeting" nil ("\\+OK" . "capa")) + ("capa" t ("\\+OK" . "auth") ("-ERR" . "pswd")) + ("auth-cram-md5" nil ("\\+OK" . "pwd-cram-md5") ("-ERR" . "wpwd")) + ("pwd-cram-md5" nil ("\\+OK" . "list") ("-ERR" . "wpwd")) + ("auth-plain" nil ("\\+OK" . "pwd-plain") ("-ERR" . "wpwd")) + ("pwd-plain" nil ("\\+OK" . "list") ("-ERR" . "wpwd")) + ("apop" nil ("\\+OK" . "list") ("-ERR" . "wpwd")) + ("user" nil ("\\+OK" . "pass") ("-ERR" . "wpwd2")) + ("pass" nil ("\\+OK" . "list") ("-ERR" . "wpwd")) + ("list" t ("\\+OK" . "uidl")) + ("uidl" t ("\\+OK" . "umsg") ("-ERR" . "nouidl")) + ("dels" nil ("\\+OK" . "dels")) + ("retr" t ("\\+OK" . "dele")) + ("dele" nil ("\\+OK" . "retr")) + ("quit" nil ("\\+OK" . "noop")))) + +(defun mew-pop-fsm-by-status (status) + (assoc status mew-pop-fsm)) + +(defun mew-pop-fsm-next (status code) + (cdr (mew-assoc-match code (nthcdr 2 (mew-pop-fsm-by-status status)) 0))) + +(defun mew-pop-fsm-reply (status) + (nth 1 (mew-pop-fsm-by-status status))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Structure +;;; + +(mew-defstruct popinfo num uid size delete fldmsg) + +(defun mew-pop-refileinfo-to-popinfo (refileinfo num) + (cons num refileinfo)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filters +;;; + +(defun mew-pop-secure-p (pnm) + (or (mew-pop-get-ssh-process pnm) (mew-pop-get-ssl-process pnm))) + +(defun mew-pop-command-capa (pro pnm) + (mew-net-status (mew-pop-get-status-buf pnm) + "Auth'ing" + nil + (mew-pop-secure-p pnm)) + (if (re-search-forward "<[=!-;?-~]+@[=!-;?-~]+>" nil t) + (mew-pop-set-key pnm (mew-match-string 0))) + (mew-pop-process-send-string pro "CAPA")) + +(defun mew-pop-command-auth (pro pnm) + (cond + ((eq (mew-pop-get-auth pnm) t) ;; t means SASL + (let ((auth-list (mew-pop-get-auth-list pnm)) + auth func) + (save-excursion + (goto-char (point-min)) + (if (re-search-forward "SASL \\([^\r\n]+\\)" nil t) + (setq auth (mew-auth-select (mew-match-string 1) auth-list)))) + (if (and auth + (setq func (mew-pop-auth-get-func auth)) + (fboundp func)) + (progn + (mew-pop-set-auth pnm auth) + (funcall func pro pnm)) + (mew-pop-debug "" "No preferred POP AUTH.\n") + (mew-pop-command-wpwd2 pro pnm)))) + (t + (mew-pop-command-pswd pro pnm)))) + +(defun mew-pop-command-pswd (pro pnm) + (let ((auth (mew-pop-get-auth pnm))) + (cond + ((or (eq auth 'pass) (eq auth 'user)) + (mew-pop-set-status pnm "user") + (mew-pop-command-user pro pnm)) + (t + (mew-pop-set-status pnm "apop") + (mew-pop-command-apop pro pnm))))) + +(defun mew-pop-command-user (pro pnm) + (let ((user (mew-pop-get-user pnm))) + (mew-pop-process-send-string pro "USER %s" user))) + +(defun mew-pop-command-pass (pro pnm) + (let* ((prompt (format "POP password (%s): " + (mew-pop-get-account pnm))) + (passwd (mew-pop-input-passwd prompt pnm))) + (mew-pop-message pnm "Sending your POP password to the POP server...") + (mew-pop-process-send-string pro "PASS %s" passwd))) + +(defun mew-pop-command-apop (pro pnm) + (let ((user (mew-pop-get-user pnm)) + (prompt (format "APOP password (%s): " (mew-pop-get-account pnm))) + (key (mew-pop-get-key pnm)) + passwd kmd5) + (cond + (key + (setq passwd (mew-pop-input-passwd prompt pnm)) + (setq kmd5 (mew-keyed-md5 key passwd)) + (mew-pop-message pnm "Sending your APOP password to the POP server...") + (mew-pop-process-send-string pro "APOP %s %s" user kmd5)) + (t + (mew-passwd-set-passwd (mew-pop-passtag pnm) nil) + (mew-pop-message pnm "APOP password is not supported by this server") + (mew-pop-command-quit2 pro pnm))))) + +(defun mew-pop-command-wpwd (pro pnm) + (let ((directive (mew-pop-get-directive pnm)) + (bnm (mew-pop-get-bnm pnm)) + (auth (mew-pop-get-auth pnm)) + (clear-pass t)) + (goto-char (point-min)) + (cond + ((or (looking-at "-ERR \\[IN-USE\\]") ;; RFC2449 + (re-search-forward " lock" nil t)) ;; for old servers: very ad hoc + (mew-pop-message pnm "The mailbox is locked!") + (setq clear-pass nil)) + ((or (eq auth 'pass) (eq auth 'user)) + (mew-pop-message pnm "POP password is wrong!")) + ((eq auth 'apop) + (mew-pop-message pnm "APOP password is wrong!")) + ((stringp auth) + (mew-pop-message pnm "%s password is wrong!" (upcase auth))) + (t + ;; pnm may be cleared already + (mew-pop-message pnm "POP password is wrong!"))) + (if clear-pass (mew-passwd-set-passwd (mew-pop-passtag pnm) nil)) + (if (eq directive 'exec) + (mew-summary-visible-buffer bnm)) + (mew-pop-command-quit2 pro pnm))) + +(defun mew-pop-command-wpwd2 (pro pnm) + (let ((directive (mew-pop-get-directive pnm)) + (status (mew-pop-get-status pnm)) + (bnm (mew-pop-get-bnm pnm))) + (if (string= status "auth") + (mew-pop-message pnm "No POP AUTH available!") + (mew-pop-message pnm "Stronger password scheme should be used!")) + (mew-passwd-set-passwd (mew-pop-passtag pnm) nil) + (if (eq directive 'exec) + (mew-summary-visible-buffer bnm)) + (mew-pop-command-quit2 pro pnm))) + +(defun mew-pop-command-list (pro pnm) + (mew-net-status (mew-pop-get-status-buf pnm) + "Checking" + nil + (mew-pop-secure-p pnm)) + (let ((directive (mew-pop-get-directive pnm))) + (cond + ((or (eq directive 'get) (eq directive 'exec) (eq directive 'sync)) + (mew-pop-set-status pnm "uidl") + (mew-pop-process-send-string pro "UIDL")) + (t + (mew-pop-process-send-string pro "LIST"))))) + +(defun mew-pop-command-uidl (pro pnm) + (let (msgs num siz) + (while (re-search-forward "^\\([0-9]+\\) +\\([0-9]+\\)" nil t) + (setq num (mew-match-string 1)) + (setq siz (mew-match-string 2)) + (setq msgs (cons (mew-make-popinfo :num num :size siz) msgs))) + (if msgs + (progn + (setq msgs (nreverse msgs)) + (mew-pop-set-rtrs pnm msgs) + (mew-pop-set-left pnm (length msgs)) + (mew-pop-process-send-string pro "UIDL")) + (mew-pop-set-status pnm "quit") + (mew-pop-command-quit pro pnm)))) + +;; The POP server does not support UIDL. +(defun mew-pop-command-nouidl (pro pnm) + (let ((directive (mew-pop-get-directive pnm))) + (if (or (eq directive 'scan) (eq directive 'exec) (eq directive 'sync)) + (progn + (mew-pop-message pnm "POP server does not support this command") + (mew-pop-command-quit2 pro pnm)) + (mew-pop-set-size pnm 0) ;; To get the entire message + (mew-pop-set-rttl pnm (mew-pop-get-left pnm)) + (when (mew-pop-get-delete pnm) + (dolist (rtr (mew-pop-get-rtrs pnm)) + (mew-popinfo-set-delete rtr t))) + (mew-pop-command-pre-retr pro pnm)))) + +(defun mew-pop-command-umsg (pro pnm) + (let* ((directive (mew-pop-get-directive pnm)) + (popinfos (mew-pop-get-rtrs pnm)) ;; popinfo + (refs (mew-pop-get-refs pnm)) ;; refileinfo + (rmvs (mew-pop-get-rmvs pnm)) + (del-time (mew-pop-get-delete pnm)) + (bnm (mew-pop-get-bnm pnm)) + (range (mew-pop-get-range pnm)) + (ctime (current-time)) + (left 0) + rtr rtrs dels num uid uidl old-uidl uid-time hlds) + (cond + ((eq directive 'inc) + (setq old-uidl (mew-net-uidl-db-get (mew-pop-passtag pnm)))) + ((eq directive 'biff) + (setq old-uidl (mew-net-uidl-db-get (mew-pop-passtag pnm)))) + ((eq directive 'scan) + (if (eq range nil) ;; update + (setq old-uidl (mew-lisp-load + (mew-expand-file bnm mew-pop-msgid-file)))))) + (while (re-search-forward "^\\([0-9]+\\) +\\([!-~]*\\)" nil t) + (setq left (1+ left)) + (setq num (mew-match-string 1)) + (setq uid (mew-match-string 2)) + (setq uid-time nil) + ;; A broken POP server may return a null UID. + (if (string= uid "") (setq uid nil)) + (cond + ((eq directive 'get) + (cond + ((setq rtr (assoc uid refs)) + (setq rtr (mew-pop-refileinfo-to-popinfo rtr num)) + (setq rtrs (cons rtr rtrs))) + ((member uid rmvs) + (setq dels (cons num dels))))) + ((eq directive 'exec) + (if (member uid rmvs) + (setq dels (cons num dels)))) + ((eq directive 'biff) + (when (and uid (not (assoc uid old-uidl))) + (setq rtr (mew-make-popinfo :num num)) + (setq rtrs (cons rtr rtrs)))) + ((eq directive 'scan) + (when uid + (setq uidl (cons uid uidl)) + (when (or range ;; all, last:n + (not (member uid old-uidl))) ;; update + (setq rtr (assoc num popinfos)) + (mew-popinfo-set-uid rtr uid) + (setq rtrs (cons rtr rtrs))))) + ((eq directive 'sync) + (when uid + (setq hlds (cons uid hlds)))) + ((eq directive 'inc) + (if uid (setq uid-time (cdr (assoc uid old-uidl)))) + (cond + (uid-time + (setq uidl (cons (cons uid uid-time) uidl)) + (if (mew-expired-p uid-time del-time) + (setq dels (cons num dels)))) + (t + (setq uidl (cons (cons uid ctime) uidl)) + (setq rtr (assoc num popinfos)) + (mew-popinfo-set-uid rtr uid) + (if (eq del-time t) (mew-popinfo-set-delete rtr t)) + (setq rtrs (cons rtr rtrs))))))) + (mew-pop-set-uidl pnm uidl) + ;; last:n + (when (and (eq directive 'scan) (integerp range)) + (mew-ntake range rtrs)) + (setq rtrs (nreverse rtrs)) + (setq dels (nreverse dels)) + (setq hlds (nreverse hlds)) + (mew-pop-set-rtrs pnm rtrs) + (mew-pop-set-dels pnm dels) + (mew-pop-set-hlds pnm hlds) + (mew-pop-set-rttl pnm (length rtrs)) + (mew-pop-set-dttl pnm (length dels)) + (mew-pop-set-left pnm left) + (mew-pop-set-dispatched pnm t) + (cond + ((or (eq directive 'sync) (eq directive 'biff)) + (mew-pop-set-status pnm "quit") + (mew-pop-command-quit pro pnm)) + (dels + (mew-pop-command-pre-dels pro pnm)) + ((eq directive 'exec) ;; no dels + (mew-pop-set-status pnm "quit") + (mew-pop-command-quit pro pnm)) + (t + (mew-pop-command-pre-retr pro pnm))))) + +(defun mew-pop-command-pre-dels (pro pnm) + (let* ((directive (mew-pop-get-directive pnm)) + (dttl (mew-pop-get-dttl pnm))) + (cond + ((= dttl 0) ;; should not occur + (mew-pop-command-pre-retr pro pnm)) + ((= dttl 1) + (if (eq directive 'exec) + (mew-pop-message pnm "Deleting 1 message in background...")) + (mew-pop-set-status pnm "dels") + (mew-pop-command-dels pro pnm)) + (t + (if (eq directive 'exec) + (mew-pop-message pnm "Deleting %d messages in background..." dttl)) + (mew-pop-set-status pnm "dels") + (mew-pop-command-dels pro pnm))))) + +(defun mew-pop-command-dels (pro pnm) + (mew-net-status1 + (mew-pop-get-status-buf pnm) "Deleting" + (mew-pop-get-dttl pnm) (mew-pop-get-dcnt pnm) (mew-pop-secure-p pnm)) + (let ((directive (mew-pop-get-directive pnm)) + (dels (mew-pop-get-dels pnm)) + (left (mew-pop-get-left pnm)) + num) + (if (null dels) + (if (eq directive 'exec) + (progn + (mew-pop-set-status pnm "quit") + (mew-pop-command-quit pro pnm)) + (mew-pop-command-pre-retr pro pnm)) + (mew-pop-set-dcnt pnm (1+ (mew-pop-get-dcnt pnm))) + (setq num (car dels)) + (mew-pop-set-dels pnm (cdr dels)) + (mew-pop-set-left pnm (1- left)) + (mew-pop-process-send-string pro "DELE %s" num)))) + +(defun mew-pop-command-pre-retr (pro pnm) + (let* ((rttl (mew-pop-get-rttl pnm))) + (cond + ((= rttl 0) + (mew-pop-message pnm "No new messages") + (mew-pop-set-status pnm "quit") + (mew-pop-command-quit pro pnm)) + ((= rttl 1) + (mew-pop-message pnm "Retrieving 1 message in background...") + (mew-pop-set-status pnm "retr") + (mew-pop-command-retr pro pnm)) + (t + (mew-pop-message pnm "Retrieving %d messages in background..." rttl) + (mew-pop-set-status pnm "retr") + (mew-pop-command-retr pro pnm))))) + +(defun mew-pop-command-retr (pro pnm) + (mew-net-status2 (mew-pop-get-status-buf pnm) + (mew-pop-get-rttl pnm) + (mew-pop-get-rcnt pnm) + (mew-popinfo-get-size (car (mew-pop-get-rtrs pnm))) + 'zero + (mew-pop-secure-p pnm)) + (let* ((directive (mew-pop-get-directive pnm)) + (rtrs (mew-pop-get-rtrs pnm)) + (rtr (car rtrs)) + (num (mew-popinfo-get-num rtr)) + (siz (mew-popinfo-get-size rtr)) + (lim (mew-pop-get-size pnm)) + (lines (mew-pop-get-body-lines pnm)) + (get-body (mew-pop-get-get-body pnm))) + (cond + ((or (null rtr) (eq directive 'biff)) + (mew-pop-set-truncated pnm nil) + (mew-pop-set-status pnm "quit") + (mew-pop-command-quit pro pnm)) + ((eq directive 'get) + (mew-pop-set-truncated pnm nil) + (mew-pop-process-send-string pro "RETR %s" num)) + ((and (eq directive 'scan) (not get-body)) + (mew-pop-set-truncated pnm t) + (mew-pop-process-send-string pro "TOP %s 0" num)) + ((or (= lim 0) (< (string-to-number siz) lim)) + (mew-pop-set-truncated pnm nil) + (mew-pop-process-send-string pro "RETR %s" num)) + (t + (mew-pop-set-truncated pnm t) + (mew-pop-process-send-string pro "TOP %s %d" num lines))))) + +(defun mew-pop-command-dele (pro pnm) + (let* ((directive (mew-pop-get-directive pnm)) + (width (1- (mew-scan-width))) + (left (mew-pop-get-left pnm)) + (rtrs (mew-pop-get-rtrs pnm)) + (rtr (car rtrs)) + (num (mew-popinfo-get-num rtr)) + (uid (mew-popinfo-get-uid rtr)) + (siz (mew-popinfo-get-size rtr)) + (del (mew-popinfo-get-delete rtr)) + (fld-msg (mew-popinfo-get-fldmsg rtr)) + (truncated (mew-pop-get-truncated pnm)) + (case (mew-pop-get-case pnm)) + fld msg vec file msg-file lmsg mark folder) + (cond + ((null fld-msg) + (setq fld (mew-pop-get-bnm pnm))) + ((stringp fld-msg) + (setq fld fld-msg)) + ((listp fld-msg) + (mew-set '(fld msg) fld-msg) + (setq lmsg msg))) + (setq folder (mew-case:folder-folder fld)) + ;; deleting +OK + (goto-char (point-min)) + (forward-line) + (delete-region (point-min) (point)) + ;; line delimiters + (mew-eol-fix-for-read) + (mew-dot-delete) + (setq msg-file (mew-net-get-new-message + pnm fld msg 'mew-pop-get-msgdb 'mew-pop-set-msgdb)) + (setq msg (car msg-file) file (cdr msg-file)) + (goto-char (point-min)) + (cond + (truncated + (mew-header-insert-xmu uid siz t (and (eq directive 'inc) + (or (mew-pop-get-case pnm) + mew-case-default)))) + ((eq directive 'scan) + (mew-header-insert-xmu uid siz nil)) + ((and (eq directive 'get) (mew-folder-popp folder)) + (mew-header-insert-xmu uid siz nil))) + (catch 'write-error + (condition-case nil + (let ((write-region-inhibit-fsync mew-use-async-write)) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region (point-min) (point-max) file nil 'no-msg))) + (error + (mew-pop-set-status pnm "quit") + (mew-pop-command-quit pro pnm) + (throw 'write-error nil))) + (mew-pop-set-rcnt pnm (1+ (mew-pop-get-rcnt pnm))) + (when (file-exists-p file) + (mew-set-file-modes file) + (mew-set-file-type file) + ;; + (mew-set-buffer-multibyte t) + (setq vec (mew-scan-header)) + (mew-scan-set-folder vec fld) + (mew-scan-set-message vec msg) + (if (or (eq directive 'inc) (eq directive 'scan)) + (setq mark (mew-scan-inbox-action vec case))) + (if (and mark + (eq directive 'scan) + (stringp mark)) ;; in the case of refiling + (setq mark nil)) + (mew-scan-body vec) + (mew-set-buffer-multibyte nil) + (mew-scan-insert-line fld vec width lmsg mark)) + (mew-pop-set-rtrs pnm (cdr rtrs)) + (if (and del (not truncated)) + (progn + (mew-pop-set-left pnm (1- left)) + (mew-pop-process-send-string pro "DELE %s" num)) + (mew-pop-set-status pnm "retr") + (mew-pop-command-retr pro pnm))))) + +(defun mew-pop-command-quit (pro pnm) + (mew-pop-set-done pnm t) + (mew-pop-process-send-string pro "QUIT")) + +(defun mew-pop-command-quit2 (pro pnm) + (mew-pop-set-done pnm t) + (mew-pop-set-error pnm t) + (mew-pop-set-status pnm "quit") + (mew-pop-process-send-string pro "QUIT")) + +(defun mew-pop-command-noop (pro pnm) + ()) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; AUTH +;;; + +(defvar mew-pop-auth-alist + '(("CRAM-MD5" mew-pop-command-auth-cram-md5) + ("PLAIN" mew-pop-command-auth-plain))) + +(defun mew-pop-auth-get-func (auth) + (nth 1 (mew-assoc-case-equal auth mew-pop-auth-alist 0))) + +(defun mew-pop-command-auth-cram-md5 (pro pnm) + (mew-pop-process-send-string pro "AUTH CRAM-MD5") + (mew-pop-set-status pnm "auth-cram-md5")) + +(defun mew-pop-command-pwd-cram-md5 (pro pnm) + (let ((user (mew-pop-get-user pnm)) + challenge passwd cram-md5) + (save-excursion + (goto-char (point-min)) + (if (re-search-forward" \\([a-zA-Z0-9+/]+=*\\)" nil t) + (setq challenge (mew-match-string 1)))) + (setq passwd (mew-pop-input-passwd "POP CRAM-MD5: " pnm)) + (setq cram-md5 (mew-cram-md5 user passwd challenge)) + (mew-pop-process-send-string pro cram-md5))) + +(defun mew-pop-command-auth-plain (pro pnm) + (mew-pop-process-send-string pro "AUTH PLAIN") + (mew-pop-set-status pnm "auth-plain")) + +(defun mew-pop-command-pwd-plain (pro pnm) + (let* ((prompt (format "POP PLAIN password (%s): " + (mew-pop-get-account pnm))) + (passwd (mew-pop-input-passwd prompt pnm)) + (user (mew-pop-get-user pnm)) + (plain (mew-base64-encode-string (format "\0%s\0%s" user passwd)))) + (mew-pop-process-send-string pro "%s" plain))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub functions +;;; + +(defconst mew-pop-info-prefix "mew-pop-info-") + +(defun mew-pop-info-name (case) + (let ((server (mew-pop-server case)) + (port (mew-*-to-string (mew-pop-port case))) + (user (mew-pop-user case)) + (sshsrv (mew-pop-ssh-server case)) + (name mew-pop-info-prefix)) + (setq name (concat name user "@" server)) + (unless (mew-port-equal port mew-pop-port) + (setq name (concat name ":" port))) + (if sshsrv + (concat name "%" sshsrv) + name))) + +(defun mew-pop-buffer-name (pnm) + (concat mew-buffer-prefix pnm)) + +(defun mew-pop-process-send-string (pro &rest args) + (let ((str (apply 'format args))) + (mew-pop-debug "=SEND=" str) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-string pro (concat str mew-cs-eol)) + (message "POP time out")))) ;; not mew-pop-message + +(defun mew-pop-message (pnm &rest args) + (or (mew-pop-get-no-msg pnm) (apply 'message args))) + +(defun mew-pop-message2 (pnm msg left) + (let (msg2) + (cond + ((or (null left) (= left 0)) + ) + ((= left 1) + (setq msg2 " (1 message left)")) + (t + (setq msg2 (format " (%d messages left)" left)))) + (if msg2 (setq msg (concat msg msg2))) + (mew-pop-message pnm msg))) + +(defun mew-pop-passtag (pnm) + (let ((server (mew-pop-get-server pnm)) + (port (mew-pop-get-port pnm)) + (user (mew-pop-get-user pnm))) + (concat user "@" server ":" port))) + +(defun mew-pop-passtag2 (case) + (let ((server (mew-pop-server case)) + (port (mew-pop-port case)) + (user (mew-pop-user case))) + (concat user "@" server ":" port))) + +(defun mew-pop-input-passwd (prompt pnm) + (let ((directive (mew-pop-get-directive pnm)) + (pro (mew-pop-get-process pnm)) + (tag (mew-pop-passtag pnm)) + pass) + (if (eq directive 'biff) + (or (mew-pop-get-passwd pnm) ;; mew-pop-biff + (mew-input-passwd prompt tag)) ;; mew-pop-check + (setq pass (mew-input-passwd prompt tag)) + (unless (and (processp pro) (eq (process-status pro) 'open)) + (mew-passwd-set-passwd tag nil)) + pass))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Opening POP +;;; + +(defun mew-pop-open (pnm server port no-msg) + (let ((sprt (mew-*-to-port port)) + pro tm) + (condition-case emsg + (progn + (setq tm (run-at-time mew-pop-timeout-time nil 'mew-pop-timeout)) + (or no-msg (message "Connecting to the POP server...")) + (setq pro (open-network-stream pnm nil server sprt)) + (mew-process-silent-exit pro) + (mew-set-process-cs pro mew-cs-text-for-net mew-cs-text-for-net) + (or no-msg (message "Connecting to the POP server...done"))) + (quit + (or no-msg (message "Cannot connect to the POP server")) + (setq pro nil)) + (error + (or no-msg (message "%s, %s" (nth 1 emsg) (nth 2 emsg))) + (setq pro nil))) + (if tm (cancel-timer tm)) + pro)) + +(defun mew-pop-timeout () + (signal 'quit nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Launcher +;;; + +(defun mew-pop-retrieve (case directive bnm &rest args) + ;; in +inbox + (let* ((server (mew-pop-server case)) + (user (mew-pop-user case)) + (port (mew-*-to-string (mew-pop-port case))) + (sshsrv (mew-pop-ssh-server case)) + (sslp (mew-pop-ssl case)) + (sslport (mew-pop-ssl-port case)) + (proxysrv (mew-pop-proxy-server case)) + (proxyport (mew-pop-proxy-port case)) + (pnm (mew-pop-info-name case)) + (buf (get-buffer-create (mew-pop-buffer-name pnm))) + (no-msg (eq directive 'biff)) + process sshname sshpro sslname sslpro lport tls + virtual-info disp-info virtual) + (if (mew-pop-get-process pnm) + (message "Another POP process is running. Try later") + (cond + (sshsrv + (setq sshpro (mew-open-ssh-stream case server port sshsrv)) + (when sshpro + (setq sshname (process-name sshpro)) + (setq lport (mew-ssh-pnm-to-lport sshname)) + (when lport + (setq process (mew-pop-open pnm "localhost" lport no-msg))))) + (sslp + (if (mew-port-equal port sslport) (setq tls mew-tls-pop)) + (setq sslpro (mew-open-ssl-stream case server sslport tls)) + (when sslpro + (setq sslname (process-name sslpro)) + (setq lport (mew-ssl-pnm-to-lport sslname)) + (when lport + (setq process (mew-pop-open pnm mew-ssl-localhost lport no-msg))))) + (proxysrv + (setq process (mew-pop-open pnm proxysrv proxyport no-msg))) + (t + (setq process (mew-pop-open pnm server port no-msg)))) + (if (null process) + (if (eq directive 'exec) + (mew-summary-visible-buffer bnm)) + (mew-summary-lock process "POPing" (or sshpro sslpro)) + (mew-sinfo-set-summary-form (mew-get-summary-form bnm)) + (mew-sinfo-set-summary-column (mew-get-summary-column bnm)) + (mew-sinfo-set-unread-mark nil) + (mew-sinfo-set-scan-id nil) + (mew-sinfo-set-scan-md5 nil) + (mew-info-clean-up pnm) + (mew-pop-set-no-msg pnm no-msg) ;; must come here + (mew-pop-message pnm "Communicating with the POP server...") + (mew-pop-set-process pnm process) + (mew-pop-set-ssh-process pnm sshpro) + (mew-pop-set-ssl-process pnm sslpro) + (mew-pop-set-server pnm server) + (mew-pop-set-port pnm port) + (mew-pop-set-user pnm user) + (mew-pop-set-account pnm (format "%s@%s" user server)) + (mew-pop-set-auth pnm (mew-pop-auth case)) + (mew-pop-set-auth-list pnm (mew-pop-auth-list case)) + (mew-pop-set-status pnm "greeting") + (mew-pop-set-directive pnm directive) + (mew-pop-set-bnm pnm bnm) + (mew-pop-set-status-buf pnm bnm) + (mew-pop-set-rcnt pnm 1) + (mew-pop-set-dcnt pnm 1) + (mew-pop-set-rttl pnm 0) + (mew-pop-set-dttl pnm 0) + (mew-pop-set-size pnm (mew-pop-size case)) + (mew-pop-set-case pnm case) + (mew-pop-set-body-lines pnm (mew-pop-body-lines case)) + (cond + ((eq directive 'biff) + (mew-pop-set-passwd pnm (nth 0 args))) ;; password + ((eq directive 'inc) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)) + (mew-pop-set-flush pnm (nth 0 args)) ;; no-flush + (mew-pop-set-delete pnm (mew-pop-delete case))) + ((eq directive 'get) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)) + (mew-pop-set-refs pnm (nth 0 args)) + (setq virtual-info (nth 1 args)) + (mew-pop-set-virtual-info pnm virtual-info) + (setq disp-info (nth 2 args)) + (mew-pop-set-disp-info pnm disp-info) + (setq virtual (mew-net-virtual-info-get-virtual virtual-info)) + (when virtual + (mew-pop-set-status-buf pnm virtual) + (with-current-buffer virtual + (mew-summary-lock process "POPing" (or sshpro sslpro))))) + ((eq directive 'scan) + (mew-pop-set-range pnm (nth 0 args)) + (mew-pop-set-get-body pnm (nth 1 args)) + (if (mew-pop-get-range pnm) + (progn + (mew-pop-set-mdb pnm (mew-summary-mark-collect4)) + (mew-net-folder-clean)) + (mew-sinfo-set-unread-mark (mew-get-unread-mark bnm)))) + ((eq directive 'sync) + ) + ((eq directive 'exec) + (mew-pop-set-rmvs pnm (nth 0 (nth 0 args))) + (mew-pop-set-kils pnm (nth 1 (nth 0 args))))) + (mew-sinfo-set-start-point (point)) ;; after erase-buffer + ;; + (set-process-sentinel process 'mew-pop-sentinel) + (set-process-filter process 'mew-pop-filter) + (set-process-buffer process buf))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defun mew-pop-debug (label string) + (when (mew-debug 'net) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +(defun mew-pop-filter (process string) + (let* ((pnm (process-name process)) + (status (mew-pop-get-status pnm)) + (mulrep (mew-pop-fsm-reply status)) + stay next func) + (mew-pop-debug (upcase status) string) + (mew-filter + ;; Process's buffer + (goto-char (point-max)) + (mew-set-buffer-multibyte nil) + (insert string) + (when (string= status "retr") + (mew-net-status2 (mew-pop-get-status-buf pnm) + (mew-pop-get-rttl pnm) + (mew-pop-get-rcnt pnm) + (mew-popinfo-get-size (car (mew-pop-get-rtrs pnm))) + nil + (mew-pop-secure-p pnm))) + (cond + ((and (and (goto-char (point-min)) (looking-at "-ERR")) + (and (goto-char (1- (point-max))) (looking-at "\n$"))) + (setq next (mew-pop-fsm-next status "-ERR"))) + ((and (and (goto-char (point-min)) (looking-at "\\+")) ;; +OK + (or (and mulrep + (goto-char (point-max)) + (= (forward-line -1) 0) + (looking-at "^\\.\r?$")) + (and (not mulrep) + (goto-char (1- (point-max))) + (looking-at "\n$")))) + (setq next (mew-pop-fsm-next status "+OK"))) + (t + (setq stay t))) + (unless stay + (unless next (setq next "quit")) + (mew-pop-set-status pnm next) + (setq func (intern-soft (concat "mew-pop-command-" next))) + (goto-char (point-min)) + (if (fboundp func) + (funcall func process pnm) + (error "No function called %s" (symbol-name func))) + (if (and process (equal (process-buffer process) (current-buffer))) + (mew-erase-buffer)))))) + +(defun mew-pop-sentinel (process event) + (let* ((pnm (process-name process)) + (directive (mew-pop-get-directive pnm)) + (mdb (mew-pop-get-mdb pnm)) + (sshpro (mew-pop-get-ssh-process pnm)) + (sslpro (mew-pop-get-ssl-process pnm)) + (rttl (mew-pop-get-rttl pnm)) + (dttl (mew-pop-get-dttl pnm)) + (left (mew-pop-get-left pnm)) + (bnm (or (mew-pop-get-bnm pnm) (current-buffer))) + (flush (mew-pop-get-flush pnm)) + (kils (mew-pop-get-kils pnm)) + (hlds (mew-pop-get-hlds pnm)) + (uidl (mew-pop-get-uidl pnm)) + (done (mew-pop-get-done pnm)) + (error (mew-pop-get-error pnm)) + (file (mew-expand-file bnm mew-pop-msgid-file)) + (buf (process-buffer process)) + (virtual-info (mew-pop-get-virtual-info pnm)) + (disp-info (mew-pop-get-disp-info pnm))) + (save-excursion + (mew-pop-debug "POP SENTINEL" event) + (set-process-buffer process nil) + (set-buffer bnm) + (mew-summary-mark-recover mdb) + (mew-remove-buffer buf) + (if (not done) + (let* ((rtrs (mew-pop-get-rtrs pnm)) + (lefts (length rtrs)) + (uid (mew-popinfo-get-uid (car rtrs))) + recovered) + (mew-pop-message pnm "POP connection is lost") + (when (mew-pop-get-dispatched pnm) + (cond + ((eq directive 'scan) + ;; uidl is reversed. + (setq uidl (cdr (member uid uidl))) + (mew-lisp-save file uidl nil 'unlimit) + (setq recovered t)) + ((eq directive 'inc) + ;; uidl is reversed. + (setq uid (assoc uid uidl)) + (setq uidl (cdr (member uid uidl))) + (mew-net-uidl-db-set (mew-pop-passtag pnm) uidl) + (setq recovered t))) + (when recovered + (mew-pop-message + pnm + "%d message retrieved. %d messages are left due to an error" + (- rttl lefts) lefts) + (mew-summary-folder-cache-save)))) + (if virtual-info (mew-summary-retrieve-message-for-virtual virtual-info)) + (cond + (error + ;; retain the error message + ) + ((eq directive 'biff) + (and (functionp mew-biff-function) + (funcall mew-biff-function rttl))) + ((eq directive 'sync) + (mew-pop-message pnm "Synchronizing messages...") + (mew-net-folder-sync bnm hlds) + (mew-pop-message pnm "Synchronizing messages...done")) + ((eq directive 'inc) + (mew-biff-clear) + (mew-net-uidl-db-set (mew-pop-passtag pnm) uidl) + (cond + ((= rttl 0) + (mew-pop-message2 pnm "No new messages" left)) + ((= rttl 1) + (mew-pop-message2 pnm "1 message retrieved" left) + (mew-summary-folder-cache-save)) + (t + (mew-pop-message2 pnm (format "%d messages retrieved" rttl) left) + (mew-summary-folder-cache-save)))) + ((eq directive 'get) + (cond + ((= rttl 0) + (mew-pop-message2 pnm "No new messages" left)) + ((= rttl 1) + (mew-pop-message2 pnm "1 message retrieved" left) + (mew-summary-folder-cache-save)) + (t + (mew-pop-message2 pnm (format "%d messages retrieved" rttl) left) + (mew-summary-folder-cache-save)))) + ((eq directive 'scan) + (mew-biff-clear) + (cond + ((or (= rttl 0) (null uidl)) + (mew-pop-message pnm "No messages scanned")) + ((= rttl 1) + (mew-pop-message pnm "1 message scanned") + (mew-lisp-save file uidl nil 'unlimit) + (mew-summary-folder-cache-save)) + (t + (mew-pop-message pnm "%d messages scanned" rttl) + (mew-lisp-save file uidl nil 'unlimit) + (mew-summary-folder-cache-save)))) + ((eq directive 'exec) + (when kils + (mew-mark-exec-unlink bnm kils) + (mew-mark-kill-invisible) + (mew-summary-folder-cache-save)) + (cond + ((= dttl 0) + (mew-pop-message pnm "No messages deleted")) + ((= dttl 1) + (mew-pop-message pnm "1 message deleted")) + (t + (mew-pop-message pnm "%d messages deleted" dttl)))))) + ;; + (and mew-use-async-write (mew-unix-sync)) + (mew-net-status-clear (mew-pop-get-status-buf pnm)) + (mew-info-clean-up pnm) + (set-buffer-modified-p nil) + (mew-summary-unlock) + (if (and (processp sshpro) (not mew-ssh-keep-connection)) + (process-send-string sshpro "exit\n")) + (if (and (processp sslpro) (not mew-ssl-keep-connection)) + (delete-process sslpro)) + (mew-net-disp-info-display disp-info) + (unless (eq directive 'biff) + (run-hooks 'mew-pop-sentinel-non-biff-hook)) + (run-hooks 'mew-pop-sentinel-hook) + (when (and mew-auto-flush-queue flush) + (mew-smtp-flush-queue mew-case))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Biff +;;; + +(defun mew-pop-biff () + (let* ((case mew-case) + (inbox (mew-proto-inbox-folder nil case)) + (case:inbox (mew-case-folder case inbox)) + (tag (mew-pop-passtag2 case)) + passwd) + (when (get-buffer case:inbox) + (with-current-buffer case:inbox + (when (and (mew-summary-exclusive-p 'no-msg) + (and (or mew-use-cached-passwd mew-use-master-passwd) + (setq passwd (mew-passwd-get-passwd tag)))) + (mew-pop-retrieve case 'biff case:inbox passwd)))))) + +(defun mew-pop-check () + "See if messages are arrived by POP." + (interactive) + (let* ((case mew-case) + (inbox (mew-proto-inbox-folder nil case)) + (case:inbox (mew-case-folder case inbox))) + (when (get-buffer case:inbox) + (with-current-buffer case:inbox + (when (mew-summary-exclusive-p) + (mew-pop-retrieve case 'biff case:inbox)))))) + +(provide 'mew-pop) + +;;; Copyright Notice: + +;; Copyright (C) 1999-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-pop.el ends here diff --git a/elpa/mew-20150813.2354/mew-refile.el b/elpa/mew-20150813.2354/mew-refile.el new file mode 100644 index 00000000..4660b395 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-refile.el @@ -0,0 +1,946 @@ +;;; mew-refile.el --- Refile for Mew + +;; Author: Yoshinari NOMURA +;; Kazu Yamamoto +;; Created: Jun 11, 1994 + +;;; Code: + +(require 'mew) + +(defmacro mew-summary-refilable (&rest body) + `(mew-pickable + (mew-summary-not-in-draft + (mew-summary-local-or-imap + ,@body)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Variables +;;; + +(defvar mew-refile-msgid-alist nil + "Alist of message-id and folder pair") + +(defvar mew-refile-from-alist nil + "Alist of From: address and folder pair") + +(defvar mew-refile-last-folder nil + "Folder name previously you refiled") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Initialize function +;;; + +(defun mew-refile-setup () + ;; load message id alist + (or mew-refile-msgid-alist + (setq mew-refile-msgid-alist (mew-lisp-load mew-refile-msgid-file))) + ;; load from alist + (or mew-refile-from-alist + (setq mew-refile-from-alist (mew-lisp-load mew-refile-from-file))) + (mew-assoc-folder-setup) + (add-hook 'kill-emacs-hook 'mew-refile-clean-up)) + +(defun mew-refile-clean-up () + (remove-hook 'kill-emacs-hook 'mew-refile-clean-up) + (if (and mew-refile-from-alist + (member 'mew-refile-guess-by-from mew-refile-guess-control)) + (mew-lisp-save mew-refile-from-file mew-refile-from-alist)) + (if (and mew-refile-msgid-alist + (member 'mew-refile-guess-by-thread mew-refile-guess-control)) + (mew-lisp-save mew-refile-msgid-file mew-refile-msgid-alist)) + (setq mew-refile-from-alist nil) + (setq mew-refile-msgid-alist nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess functions +;;; + +;; We have two types of functions in mew-refile-guess-control, +;; guess function and ctrl function. +;; guess function must return a folder list or folder string or nil. +;; guess function must not have a string "ctrl" in its symbol name. +;; ctrl function must have a string "ctrl" in its symbol name. + +;; dispatcher returns: ((guess1 guess2 ..) info1 info2 ...) multi guess mode +;; ((guess1) info1 info2 ...) single guess mode +;; info1: ('guess-func-name guess1 guess2 ...) +;; +;; that is, 'car' is a list of judged folders. +;; 'cdr' is a alist of opinions by guess functions. +;; + +(defun mew-refile-guess (&optional auto show-all) + (let ((case-fold-search t) + (funcs mew-refile-guess-control) ret guess info stop) + (catch 'last + (dolist (func funcs) + (if (string-match "ctrl" (symbol-name func)) + ;; func is control function + (when (setq ret (funcall func guess auto)) + (setq stop t) + (or show-all (throw 'last t))) + ;; func is guess function + (setq ret (funcall func))) + (unless (listp ret) (setq ret (list ret))) + (setq info (nconc info (list (cons func ret)))) + (unless stop + (dolist (re ret) + (mew-addq guess re))))) + (setq guess (nreverse guess)) + (if (not mew-refile-ctrl-multi) (setq guess (list (car guess)))) + (cons guess info))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess control functions +;;; + +(defun mew-refile-ctrl-auto-boundary (guess auto) + (if auto "stop")) + +(defun mew-refile-ctrl-throw (guess auto) + (if guess "stop")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Dispatcher +;;; + +(defun mew-refile-guess-from-dispatch (func &optional addr) + "Dispatcher to make mew-refile-guess-by-from-* consider +mew-refile-guess-from-me-is-special." + (let ((from (downcase (or addr (mew-header-parse-address mew-from:) "")))) + ;; if From: is my address, addr is the list extracted from To:, Cc: + (if (and mew-refile-guess-from-me-is-special + (mew-is-my-address mew-regex-my-address-list from)) + (let ((addrs (mew-header-parse-address-list mew-refile-guess-key-list)) + ret adr) + (dolist (addr addrs) + (setq adr (funcall func addr)) + (mew-addq ret adr)) + (nreverse ret)) + (funcall func from)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess by folder +;;; + +(defvar mew-assoc-folder nil) + +(defun mew-folder-func (full &optional name) + (if full (cons full name))) + +(defun mew-assoc-folder-setup () + (if mew-use-fast-refile + (setq mew-assoc-folder 'mew-assoc-folder-fast) + (setq mew-assoc-folder 'mew-assoc-folder-slow))) + +(defun mew-assoc-folder-slow (key alist sep) + ;; Case-sensitive so you can use capital letters for your folders. + ;; But this is slow. + (let ((skey (downcase key)) + (node-regex (concat (regexp-quote sep) "$")) + name ret first) + (catch 'loop + (dolist (al alist) + (setq ret al) + (setq name (cdr ret)) + (when (and (stringp name) (string= (downcase name) skey)) + (unless first + (setq first ret)) + (unless (string-match node-regex (car ret)) + (throw 'loop nil))) + (setq ret nil))) + (if mew-use-node-folder + (or ret first) + ret))) + +(defun mew-assoc-folder-fast (key alist sep) + ;; Case-insensitive so you cannot use capital letters for your folders. + ;; But this is fast. + ;; + ;; ("+foo/" . "foo") + ;; ("+foo/foo" . "foo") + (let* ((skey (downcase key)) + (node-regex (concat (regexp-quote sep) "$")) + ret first) + (catch 'loop + (while (setq ret (rassoc skey alist)) + (unless first + (setq first ret)) + (unless (string-match node-regex (car ret)) + (throw 'loop nil)) + (setq alist (cdr (member ret alist))) + (setq ret nil))) + (if mew-use-node-folder + (or ret first) + ret))) + +(defun mew-refile-guess-by-folder () + ;; Guess folders by the To:/Cc: field with folder alist. + ;; Mainly used for mailing-list. + (let* ((to-cc (mew-header-parse-address-list mew-refile-guess-key-list)) + (proto mew-inherit-refile-proto) + (case mew-inherit-refile-case) + (alist (mew-proto-folder-alist proto case)) + sep ent ret ml-addr ml-name) + (cond + ((mew-folder-imapp proto) + (setq sep (mew-imap-separator case))) + (t + (setq sep mew-path-separator))) + (dolist (tc to-cc) + (setq ml-addr (mew-addrstr-parse-address (or tc ""))) + (when ml-addr + (setq ml-name (mew-addrstr-extract-user ml-addr)) + (setq ent (or (funcall mew-assoc-folder ml-addr alist sep) + (funcall mew-assoc-folder ml-name alist sep))) + (mew-addq ret (nth 0 ent)))) + (nreverse ret))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess by alist +;;; + +(defun mew-refile-guess-by-alist () + (let ((alist (mew-refile-guess-alist mew-inherit-refile-case)) + (proto mew-inherit-refile-proto)) + ;; Guess folders by user-configured alist. + (mew-refile-guess-by-alist1 alist proto))) + +(defun mew-refile-guess-by-alist1 (rule &optional proto) + "Return a guessed folder according to the RULE. The syntax of +RULE is as follows: + rule ::= ' + ::= (( ) ( ) ... []) + ::= ( |) ( |) ... + ::= (t ) | (nil ) + +There are two special s: nil and t. + +nil is used to specify to be returned when nothing is +guessed. + +t can specify to be returned in addition to guessed +values." + (let (key alist val f-or-r header ent ret fin) + (dolist (rl rule) + (setq key (car rl)) + (setq alist (cdr rl)) ;; must not use mew-alist-get-value + (cond + ((eq key t) + (mew-addq ret (if (consp alist) (car alist) alist))) + ((eq key nil) + (or ret (mew-addq ret (if (consp alist) (car alist) alist)))) + ((setq header (mew-header-get-value key)) + (dolist (al alist) + (setq val (mew-alist-get-key al)) + (setq f-or-r (mew-alist-get-value al)) + (setq ent nil) + (when (and (stringp val) (string-match val header)) + (cond + ((stringp f-or-r) + (setq ent (mew-refile-guess-by-alist2 val header f-or-r))) + ((listp f-or-r) + (setq ent (mew-refile-guess-by-alist1 f-or-r proto))))) + (when ent + (if (listp ent) + (dolist (et ent) + (mew-addq ret et)) + (mew-addq ret ent))))))) + (if proto + (dolist (ent ret fin) + (if (string= proto (substring ent 0 1)) + (setq fin (cons ent fin)))) + (nreverse ret)))) + +(defun mew-refile-guess-by-alist2 (regex string template) + ;; regex: "\\([^@]+\\)@\\([^.]+\\)\\.ad\\.jp" + ;; string: "admin@example.org" + ;; template: "+net/\\2/\\1" + ;; -> "+net/iij/admin" + (let (str strs match repl) + (string-match regex string) + (setq match (cdr (cdr (match-data)))) + (while match + (setq str nil) + (if (car match) + (setq str (substring string (car match) (car (cdr match))))) + (setq strs (cons str strs)) + (setq match (cdr (cdr match)))) + (setq strs (cons nil (nreverse strs))) ;; cons nil for 0th + (while (string-match "\\\\\\([1-9]\\)" template) + (setq repl (nth (string-to-number (match-string 1 template)) strs)) + (setq template (replace-match (or repl "") nil nil template))) + template)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess by thread +;;; + +(defun mew-refile-guess-by-thread () + ;; Guess folders by thread with alist created by + ;; mew-refile-guess-by-thread-learn. + (let ((msgid (or (mew-idstr-get-last-id + (mew-header-get-value mew-references:)) + (mew-idstr-get-first-id + (mew-header-get-value mew-in-reply-to:)))) + (proto mew-inherit-refile-proto)) + (when msgid + (let ((ret (nth 1 (assoc msgid mew-refile-msgid-alist)))) + (if (and ret (string= proto (substring ret 0 1))) + ret))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess by from folder +;;; + +(defun mew-refile-guess-by-from-folder (&optional addr) + ;; Guess folders by the From: field with folders under +from. + (mew-refile-guess-from-dispatch 'mew-refile-guess-by-from-folder-body addr)) + +(defun mew-refile-guess-by-from-folder-body (&optional addr) + (let* ((proto mew-inherit-refile-proto) + (case mew-inherit-refile-case) + (list (mew-proto-friend-folder-list proto case)) + (sep (if (mew-folder-imapp proto) + (mew-imap-separator case) + mew-path-separator)) + (qsep (regexp-quote sep)) + (from (downcase (or addr (mew-header-parse-address mew-from:) ""))) + (user (mew-addrstr-extract-user from)) + (from-regex (concat qsep (regexp-quote from) "$")) + (user-regex (concat qsep (regexp-quote user) "$"))) + (or + (mew-member-match2 from-regex list) + (mew-member-match2 user-regex list)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess by from +;;; + +(defun mew-refile-guess-by-from (&optional addr) + ;; Guess folders by the From: field with alist created by + ;; mew-refile-guess-by-from-learn. + (mew-refile-guess-from-dispatch 'mew-refile-guess-by-from-body addr)) + +(defun mew-refile-guess-by-from-body (&optional addr) + (let ((from (downcase (or addr (mew-header-parse-address mew-from:) ""))) + (proto mew-inherit-refile-proto)) + (when from + (let ((ret (cdr (assoc from mew-refile-from-alist)))) + (if (and ret (string= proto (substring ret 0 1))) + ret))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess by newsgroup +;;; + +(defun mew-refile-guess-by-newsgroups () + ;; Guess folders by the Newsgroups field with folder alist. + (let* ((newsgroups (mew-addrstr-parse-value-list2 + (mew-header-get-value mew-newsgroups:))) + (proto mew-inherit-refile-proto) + (case mew-inherit-refile-case) + (alist (mew-proto-folder-alist proto case)) ;; local folders + ent ret) + (dolist (newsgroup newsgroups) + (setq ent (funcall mew-assoc-folder newsgroup alist mew-path-separator)) + (mew-addq ret (nth 0 ent))) + (nreverse ret))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Guess by default +;;; + +(defun mew-refile-guess-by-default (&optional addr) + ;; Concat +from and user. + (mew-refile-guess-from-dispatch 'mew-refile-guess-by-default-body addr)) + +(defun mew-refile-guess-by-default-body (&optional addr) + (let* ((proto mew-inherit-refile-proto) + (case mew-inherit-refile-case) + (fld (mew-proto-friend-folder proto case)) + (from (downcase (or addr (mew-header-parse-address mew-from:) "")))) + (if mew-refile-guess-strip-domainpart + (setq from (mew-addrstr-extract-user from))) + (mew-concat-folder2 fld from case))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Learning functions +;;; + +;; mew-refile-guess-learn (buf result) +;; +;; buf is message buffer. +;; +;; result is ((chosen1 chosen2 ...) +;; (guess-func-name1 guess1 guess2...) +;; (guess-func-name2 guess1 guess2...)) +;; +;; that is, 'car' is a list of user chosen folders. +;; 'cdr' is a list of opinions by guess functions. +;; + +(defun mew-refile-guess-learn (buf result) + (let ((chosen (car result)) ;; (folder1 folder2 ...) + (info (cdr result))) ;; (guess-func-name guess1 guess2...) + (with-current-buffer buf + (if (member 'mew-refile-guess-by-from mew-refile-guess-control) + (mew-refile-guess-by-from-learn chosen info)) + (if (member 'mew-refile-guess-by-thread mew-refile-guess-control) + (mew-refile-guess-by-thread-learn chosen info))))) + +(defun mew-refile-guess-by-thread-learn (chosen info) + ;; Create mew-refile-msgid-alist for mew-refile-guess-by-thread. + (let* ((msgid (mew-idstr-get-first-id + (mew-header-get-value mew-message-id:))) + (folder (car chosen)) + ;; other people's honest opinion and my honest opinion. + (oho info) + (mho (cdr (assoc 'mew-refile-guess-by-thread info)))) + (when (and msgid chosen) + ;; if my opinion was right, I learn it. + ;; or a folder was not in other people's opinion, + ;; I accept it. + (catch 'match + (dolist (csn chosen) + (if (or (member csn mho) + (not (catch 'find + (while oho + (and (member csn (car oho)) (throw 'find t)) + (setq oho (cdr oho)))))) + (throw 'match (setq folder csn))))) + (setq mew-refile-msgid-alist + (cons (list msgid folder "??") + (delq (assoc msgid mew-refile-msgid-alist) ;; delq is right + mew-refile-msgid-alist)))))) + +(defun mew-refile-guess-by-from-learn (chosen info) + ;; Create mew-refile-from-alist for mew-refile-guess-by-from. + (let* ((from (downcase (or (mew-header-parse-address mew-from:) ""))) + ;; 'my honest opinion' guessed by mew-refile-guess-by-from. + (mho (nth 1 (assoc 'mew-refile-guess-by-from info))) + folder to-cc) + ;; default leaning key X is the address derived from From: header, + ;; but only when + ;; mew-refile-guess-from-me-is-special is t + ;; X is my address. + ;; All addresses derived from To: Cc: values + ;; point to the only one address Y. + ;; the learning key is set to Y instead of X. + (if (and mew-refile-guess-from-me-is-special + (mew-is-my-address mew-regex-my-address-list from) + (setq to-cc + (mew-header-parse-address-list mew-refile-guess-key-list)) + (= (length to-cc) 1)) + (setq from (car to-cc))) + (unless (or (or (null from) (null chosen)) (and mho (member mho chosen))) + ;; I decide which folder is most important among the user chosen + ;; folders. + (catch 'match + (dolist (csn chosen) + ;; searching a folder anyone couldn't predict. + (unless (mew-member* csn info) + (throw 'match (setq folder csn))))) + (run-hooks 'mew-refile-guess-by-from-learn-hook) + ;; If candidate was found, I memorize it. + (when folder + (setq mew-refile-from-alist + (cons (cons from folder) + (delq (assoc from mew-refile-from-alist) ;; delq is right + mew-refile-from-alist))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Summary mode +;;; + +(defun mew-refile-get (msg) + (assoc msg (mew-sinfo-get-refile))) + +(defun mew-refile-set (msg folders) + (mew-sinfo-set-refile (cons (cons msg folders) (mew-sinfo-get-refile)))) + +(defun mew-refile-reset (msg) + (mew-sinfo-set-refile + (delq (mew-refile-get msg) (mew-sinfo-get-refile)))) + +(defun mew-refile-change (src dst) + (let ((ref (mew-refile-get src))) + (when ref (setcar ref dst)))) + +(defun mew-refile-folder-check (folder &optional force-to-create) + "A function to see if FOLDER exists. +Return t if exists or created. Otherwise, return nil." + (when (stringp folder) + (cond + ((mew-folder-popp folder) nil) + ((mew-folder-nntpp folder) nil) + ((mew-folder-virtualp folder) nil) + ((mew-folder-imapp folder) + (let* ((case mew-inherit-refile-case) + (mailboxes (mew-imap-folder-alist case))) + (cond + ((or (assoc folder mailboxes) + (assoc (mew-imap-file-name-as-directory folder case) mailboxes)) + t) + ;; This is very ad-hoc but no right way... + ((and (string= (mew-imap-separator case) ".") + (string-match mew-path-separator folder)) + (message "%s should not contain \"%s\"" folder mew-path-separator) + nil) + ((and (y-or-n-p (format "%s does not exist. Create it? " folder)) + (mew-imap-folder-insert case folder)) + (message "%s will be created" folder) + t)))) + (t ;; local + (let ((absdir (mew-expand-folder folder)) ;; /home/Mail/foo + (create-it force-to-create)) + (when absdir + (if (file-exists-p absdir) + (if (file-directory-p absdir) + t ;; exists + (message "%s is a file" folder) + nil) ;; xxx exists but a file + (unless create-it + (if (y-or-n-p (format "%s does not exist. Create it? " folder)) + (setq create-it t))) + (if (not create-it) + nil ;; not created + (mew-make-directory absdir) + (mew-local-folder-insert folder) + (message "%s has been created" folder) + t)))))))) ;; created + +(defun mew-refile-decide-folders (buf msg cur-folders &optional auto exfld) + ;; This functions returns + ;; ((folder1 folder2...) + ;; (func1 guess11 guess12...) ;; for learning + ;; (func2 guess12 guess22...)) + (let ((proto mew-inherit-refile-proto) + (case mew-inherit-refile-case) + learn-info folders ret cands singlep lst-lst) + (with-current-buffer buf + (setq learn-info (mew-refile-guess auto))) + (if auto + ;; if auto is set, simply use the guess. + (setq folders (car learn-info)) + (cond + (cur-folders + ;; add new folder + (setq cands cur-folders)) + ((nth 1 (car learn-info)) + ;; multi guess + (setq cands (car learn-info))) + (t + ;; single guess + (setq singlep t) + (setq cands (list (nth 0 (car learn-info)))))) + (setq cands (delete nil cands)) + (when exfld + ;; copying, two folders are necessary + (setq singlep nil) + (if (or (null cands) (equal (list exfld) cands)) + (setq cands (list exfld proto)) + (setq cands (cons exfld cands)))) + (setq cands (mew-uniq-list cands)) ;; unavoidable + (unless cands + (setq cands (list proto))) + (setq folders (mew-input-refile-folders cands singlep case proto))) + ;; check folder existence. + (setq lst-lst (mapcar (lambda (x) (mew-split x ?,)) folders)) + (dolist (lst lst-lst) + (dolist (fld lst) + (if (and fld (not (member fld ret)) (mew-refile-folder-check fld)) + (setq ret (cons fld ret))))) + (cons (nreverse ret) (cdr learn-info)))) ;; return value + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Copy +;;; + +(defun mew-summary-copy () + "Put the refile mark(default is 'o') on this message with +the current folder as a candidate in addition to guessed folders." + (interactive) + (mew-summary-msg-or-part + (mew-summary-refilable + (mew-summary-refile-body + nil nil nil nil (mew-summary-folder-name))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Refile (aka move) +;;; + +(defun mew-refile-log-buffer (fld) + (concat mew-buffer-prefix "refile " fld)) + +(defun mew-summary-refile (&optional report) + "Put the refile mark(default is 'o') on this message. If already +marked with 'o', it prints where this message will be refiled. This +can overlay other marks. When it overlays, the cursor stays on the +message. If it marks newly, displays the next message. If executed +with '\\[universal-argument]', it displays how the refile rules work in Message mode." + (interactive "P") + (mew-summary-msg-or-part + (mew-summary-refilable + (if report (mew-summary-refile-report) (mew-summary-refile-body))))) + +(defvar mew-override-body-open "<") +(defvar mew-override-body-close "> ") +(defconst mew-regex-override-body + (concat (regexp-quote mew-override-body-open) + "[^>\r\n]*" + (regexp-quote mew-override-body-close))) + +(defun mew-summary-refile-override-body (folders-str &optional force) + (let* ((open mew-override-body-open) + (close mew-override-body-close) + (len (+ (length folders-str) (length open) (length close)))) + (save-excursion + (when (mew-summary-goto-body 'after) + (when (and (not force) (looking-at mew-regex-override-body)) + (mew-elet + (delete-region (point) (match-end 0)))) + (mew-elet + (insert-and-inherit open folders-str close)))) + len)) + +(defun mew-summary-refile-remove-body () + (save-excursion + (when (and (mew-summary-goto-body 'after) + (looking-at mew-regex-override-body)) + (mew-elet + (delete-region (point) (match-end 0)))))) + +(defun mew-summary-refile-log (fld folders-str) + (save-excursion + (beginning-of-line) + (let ((beg (point)) + (cbuf (current-buffer)) + (msg-id (mew-summary-my-id)) + end) + (forward-line) + (when (search-backward "\r" nil t) + (setq end (point)) + (set-buffer (get-buffer-create (mew-refile-log-buffer fld))) + (goto-char (point-max)) + (mew-insert-buffer-substring cbuf beg end) + (insert "== src=" fld " dst=" folders-str " id=" msg-id) + (insert " date=" (mew-time-ctz-to-logtime (current-time)) "\n"))))) + +(defun mew-summary-refile-unlog (fld) + (save-excursion + (let ((msg-id (mew-summary-my-id)) + start) + (set-buffer (get-buffer-create (mew-refile-log-buffer fld))) + (goto-char (point-min)) + (when (search-forward (concat " id=" msg-id) nil t) + (beginning-of-line) + (setq start (point)) + (forward-line) + (delete-region start (point)))))) + +(defun mew-refile-decode-subject () + (save-excursion + (goto-char (point-min)) + (if (and (re-search-forward (concat "^$\\|^" mew-subj:) nil t) + (not (looking-at "^$"))) + (let ((med (point))) + (forward-line) + (mew-header-goto-next) + (mew-header-decode-region mew-subj: med (point)))))) + +(defun mew-summary-refile-body (&optional exp-flds auto no-msg no-mark exfld) + (let ((pos (point)) + fld msg folders cur-folders mark + buf learn-info tmp delbuf invalidp folders-str + mew-inherit-refile-proto mew-inherit-refile-case) + (mew-summary-goto-message) + (when (mew-sumsyn-match mew-regex-sumsyn-short) + (setq fld (mew-sumsyn-folder-name)) + (setq msg (mew-sumsyn-message-number)) ;; msg is never nil + (setq invalidp (not (mew-msg-validp msg)))) + (setq mew-inherit-refile-case (or (mew-case:folder-case fld) + mew-case)) + (setq mew-inherit-refile-proto (substring (mew-case:folder-folder fld) 0 1)) + (setq mark (mew-summary-get-mark)) ;; any mark + (cond + ((and mark (> (mew-markdb-level mark) (mew-markdb-level mew-mark-refile))) + (or no-msg + (message "Cannot mark here because '%s' is stronger than '%s'" + (mew-markdb-name mark) (mew-markdb-name mew-mark-refile))) + nil) + (invalidp + (or no-msg (message "Cannot refile this invalid message")) + nil) + (t + (if exp-flds + (setq folders exp-flds) + (unless (or auto (mew-sinfo-get-disp-msg)) + ;; need to make a cache or a message buffer. + (mew-summary-display)) + (setq buf (mew-cache-hit fld msg)) + (unless buf + (save-excursion + (setq buf (generate-new-buffer mew-buffer-prefix)) + (setq delbuf t) + (set-buffer buf) + (mew-erase-buffer) + (mew-insert-message + fld msg mew-cs-text-for-read mew-header-reasonable-size) + (mew-refile-decode-subject))) + (when (and (eq mew-mark-refile mark) (get-buffer fld)) + (with-current-buffer fld + (setq cur-folders (cdr (mew-refile-get msg))))) + (condition-case nil + (setq learn-info (mew-refile-decide-folders + buf msg cur-folders auto exfld)) + (quit (goto-char pos))) + (setq folders (car learn-info))) + ;; we must prevent refiling a message to +queue + (dolist (folder folders) + (unless (mew-folder-queuep folder) + (setq tmp (cons folder tmp)))) + (setq folders (nreverse tmp)) + (setq folders (delete mew-draft-folder folders)) + ;; mark refile + (unless no-mark + (when folders + (or exp-flds auto (mew-refile-guess-learn buf learn-info)) + (setq folders-str (mew-join "," folders)) + (cond + ((mew-virtual-p) + (with-current-buffer fld + (save-excursion + (when (mew-summary-search-msg msg) + (mew-refile-reset msg) + (mew-refile-set msg folders) + (if cur-folders (mew-summary-refile-unlog fld)) + (mew-summary-refile-log fld folders-str) + (mew-summary-refile-override-body folders-str) + ;; marked in mew-mark-put-mark + (set-buffer-modified-p nil))))) + (t + (mew-refile-reset msg) + (mew-refile-set msg folders) + (if cur-folders (mew-summary-refile-unlog fld)) + (mew-summary-refile-log fld folders-str))) + (mew-summary-refile-override-body folders-str) + (mew-mark-put-mark mew-mark-refile no-msg) + (setq pos (point)))) + (if delbuf (mew-remove-buffer buf)) + ;; memorize last-folder + (setq mew-refile-last-folder folders) + (set-buffer-modified-p nil))) + (goto-char pos) + folders)) ;; return value + +(defun mew-summary-refile-report () + (let ((win (selected-window)) + (customize-var '(mew-refile-ctrl-multi + mew-refile-guess-key-list + mew-refile-guess-strip-domainpart + mew-refile-guess-from-me-is-special + mew-header-reasonable-size)) + mew-inherit-refile-case + mew-inherit-refile-proto + fld msg guess boundary) + (save-excursion + (mew-summary-goto-message) + (when (mew-sumsyn-match mew-regex-sumsyn-short) + (setq fld (mew-sumsyn-folder-name)) + (setq msg (mew-sumsyn-message-number)))) + (setq mew-inherit-refile-case (or (mew-case:folder-case fld) + mew-case)) + (setq mew-inherit-refile-proto (substring (mew-case:folder-folder fld) 0 1)) + (with-temp-buffer + (mew-insert-message + fld msg mew-cs-text-for-read mew-header-reasonable-size) + (save-excursion + (goto-char (point-min)) + (setq boundary (search-forward "\n\n" nil t))) + (mew-refile-decode-subject) + (setq guess (mew-refile-guess nil t))) + (mew-window-configure 'message) + ;; message buffer + (mew-summary-display-preamble) + (mew-elet + (save-excursion + ;; report result of guess. + (insert (format "** Guess result: %s\n" (car guess))) + ;; report status of customize variables. + (insert "\n** Current Configurations:\n\n") + (dolist (cvar customize-var) + (insert (format "%-40s: " cvar)) + (insert (format "%s\n" (eval cvar)))) + (unless boundary + (insert "Warning: Not analyzing whole header. You may need to increase mew-header-reasonable-size\n")) + (insert "\n** Each function's opinion:\n\n") + ;; report how each functions guessed. + (setq guess (cdr guess)) + (dolist (gs guess) + (insert (format "%-32s " (car gs))) + (insert (format "return: %s\n" + (mapconcat 'identity (cdr gs) ",")))))) + (mew-summary-display-postscript 'no-hook) + (select-window win))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Refile again +;;; + +(defun mew-summary-refile-again () + "Put a refile mark on this message according to the previous +refile folder." + (interactive) + (mew-summary-refilable + (save-excursion + (mew-summary-goto-message) + (let ((msg (mew-summary-message-number))) + (when (mew-msg-validp msg) + (message "%s to %s" msg (mew-join ", " mew-refile-last-folder))))) + (mew-summary-refile-body mew-refile-last-folder))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Auto refile +;;; + +(defun mew-summary-auto-refile (&optional mew-mark-review-only) + "Refile each message in the folder automatically. If +'mew-refile-auto-refile-skip-any-mark' is non-nil, +any previously marked message will be skipped. +If '\\[universal-argument]' is specified, only messages marked with +'mew-mark-review' will be concerned." + (interactive "P") + (mew-summary-refilable + (mew-decode-syntax-delete) + (let ((mew-use-highlight-x-face nil) + (lines (mew-sinfo-get-ttl-line)) + (case-fold-search nil) + (line 1) (mark nil) msg) + (cond + (mew-mark-review-only + (setq msg (format "Refile all messages marked with '%c'? " + mew-mark-review))) + (mew-refile-auto-refile-skip-any-mark + (setq msg "Refile all non-marked messages? ")) + (t + (setq msg "Refile messages including marked with weak marks?"))) + (if (and mew-refile-auto-refile-confirm (not (y-or-n-p msg))) + (message "Not refiled") + (message "Auto refiling...") + (save-window-excursion + (goto-char (point-min)) + (while (re-search-forward mew-regex-sumsyn-valid nil t) + (setq mark (mew-summary-get-mark)) + (if mew-mark-review-only + (and mark + (char-equal mark mew-mark-review) + (mew-summary-refile-body nil t 'no-msg)) + (or (and mark + (or mew-refile-auto-refile-skip-any-mark + (>= (mew-markdb-level mark) + (mew-markdb-level mew-mark-refile)))) + (mew-summary-refile-body nil t 'no-msg))) + (if (= (% (/ (* 100 line) lines) 10) 0) + (message "Auto refiling...%s%%" (/ (* 100 line) lines))) + (setq line (1+ line)) + (forward-line))) + (message "Auto refiling...done"))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; "mx" extension +;;; + +(defun mew-summary-mark-copy () + "\\ +Put the refile mark onto all messages marked with '*', +with the current folder as a candidate in addition to guessed folders. +This is very convenient to refile all messages picked by '\\[mew-summary-pick]'." + (interactive) + (mew-summary-refilable + (let ((mew-use-highlight-x-face nil) + last) + (message "Mark copying...") + (save-excursion + (save-window-excursion + (goto-char (point-min)) + (catch 'loop + (while (re-search-forward mew-regex-msg-review nil t) + (setq last (mew-summary-refile-body + last nil 'no-msg nil (mew-summary-folder-name 'ext))) + (unless last (throw 'loop t)) + (forward-line))) + (message "Mark copying...done")))))) + +(defun mew-summary-mark-refile () + "\\ +Put the refile mark onto all messages marked with '*'. +This is very convenient to refile all messages picked by '\\[mew-summary-pick]'." + (interactive) + (mew-summary-refilable + (let ((mew-use-highlight-x-face nil) + last) + (message "Mark refiling...") + (save-excursion + (save-window-excursion + (catch 'loop + (while (or (re-search-forward mew-regex-msg-review nil t) + (re-search-backward mew-regex-msg-review nil t)) + (setq last (mew-summary-refile-body last nil 'no-msg)) + (unless last (throw 'loop t)) + (forward-line))) + (message "Mark refiling...done")))))) + +(provide 'mew-refile) + +;;; Copyright Notice: + +;; Copyright (C) 1994-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-refile.el ends here diff --git a/elpa/mew-20150813.2354/mew-scan.el b/elpa/mew-20150813.2354/mew-scan.el new file mode 100644 index 00000000..17bc985f --- /dev/null +++ b/elpa/mew-20150813.2354/mew-scan.el @@ -0,0 +1,908 @@ +;;; mew-scan.el --- Scanning messages for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Scan info +;;; + +(defvar mew-scan-info-list '("folder" "message")) +;; See mew-scan-fields. 0th is fld, 1st is msg (ie num). + +(mew-info-defun "mew-scan-" mew-scan-info-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Variables +;;; + +(defvar mew-summary-form-size-unit '("" "k" "M" "G" "T")) +(defvar mew-vec [0 1 2 3 4 5 6 8 9 10 11 12 13 14 15 16 17 18 19 20] + "Just for test of (MEW-FOO).") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Setup +;;; + +(defun mew-scan-setup () + "Define functions (MEW-FOO) according 'mew-scan-fields-alias'." + (dotimes (i (length mew-scan-fields-alias)) + (fset (intern (concat "MEW-" (nth i mew-scan-fields-alias))) + `(lambda () (aref mew-vec ,i))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Pre-defined functions for mew-summary-form +;;; + +(defun mew-summary-form-mark () + "A function to return a mark. +'mew-summary-form-mark-delete' and 'mew-summary-form-mark-review' +effect to this function." + (let ((mark-delete mew-mark-delete) + (mark-review mew-mark-review) + (mark-spam mew-mark-delete) + (unread (and mew-use-unread-mark (mew-sinfo-get-unread-mark))) + duplicated spam review id body md5) + (when mew-summary-form-mark-delete + (if (mew-characterp mew-summary-form-mark-delete) + (setq mark-delete mew-summary-form-mark-delete)) + (when (setq id (mew-idstr-get-first-id (MEW-ID))) + (if (member id (mew-sinfo-get-scan-id)) + (unless (mew-scan-message-invalidp) + (setq duplicated t)) + (mew-sinfo-set-scan-id (cons id (mew-sinfo-get-scan-id)))))) + (when (and mew-summary-form-mark-spam + (mew-sinfo-get-inboxp)) + (if (mew-characterp mew-summary-form-mark-spam) + (setq mark-spam mew-summary-form-mark-spam)) + (setq body (MEW-BODY)) + (unless (string= body "") + (setq md5 (mew-md5 body)) + (if (member md5 (mew-sinfo-get-scan-md5)) + (unless (mew-scan-message-invalidp) + (setq spam t)) + (mew-sinfo-set-scan-md5 (cons md5 (mew-sinfo-get-scan-md5)))))) + (when mew-summary-form-mark-review + (if (mew-characterp mew-summary-form-mark-review) + (setq mark-review mew-summary-form-mark-review)) + (let* ((mew-header-max-depth nil) + (to (mew-addrstr-parse-address-list (MEW-TO))) + (cc (mew-addrstr-parse-address-list (MEW-CC)))) + (setq to (nconc to cc)) + (catch 'loop + (dolist (cto to) + (if (mew-is-my-address mew-regex-my-address-list cto) + (throw 'loop (setq review t))))))) + (cond + (duplicated (char-to-string mark-delete)) + (spam (char-to-string mark-spam)) + (review (char-to-string mark-review)) + (unread (char-to-string mew-mark-unread)) + (t (char-to-string mew-mark-read))))) + +(defvar mew-type-mark-invalid "#") +(defvar mew-type-mark-truncated "T") +(defvar mew-type-mark-signed "S") +(defvar mew-type-mark-encrypted "E") +(defvar mew-type-mark-multipart "M") +(defvar mew-type-mark-alternative "-") +(defvar mew-type-mark-partial "P") +(defvar mew-type-mark-nothing " ") + +(defun mew-summary-form-type () + "A function to return a mark of content type." + (let ((ct (MEW-CT)) + (case-fold-search t)) + (cond + ((mew-scan-message-invalidp) mew-type-mark-invalid) + ((mew-scan-message-truncatedp) mew-type-mark-truncated) + ((string-match mew-ct-mls ct) mew-type-mark-signed) + ((string-match mew-ct-mle ct) mew-type-mark-encrypted) + ((string-match mew-ct-sms ct) mew-type-mark-encrypted) + ((string-match mew-ct-xsms ct) mew-type-mark-encrypted) + ((or (string-match mew-ct-smm ct) + (string-match mew-ct-xsmm ct)) + ;; checking smime-type + (cond + ((string-match mew-ct-smm-sig ct) mew-type-mark-signed) + ((string-match mew-ct-smm-enc ct) mew-type-mark-encrypted) + ;; smime-type is optional, sigh + (t mew-type-mark-encrypted))) + ((mew-ct-alternativep ct) mew-type-mark-alternative) + ((mew-ct-multipartp ct) mew-type-mark-multipart) + ((mew-ct-partialp ct) mew-type-mark-partial) + (t mew-type-mark-nothing)))) + +(defun mew-summary-form-time () + "A function to return a message time, HH:MM" + (let ((s (MEW-DATE))) + (if (or (string= s "") + (not (string-match mew-time-rfc-regex s))) + (setq s (mew-time-ctz-to-rfc + (mew-file-get-time (mew-expand-msg (MEW-FLD) (MEW-NUM)))))) + (if (string-match mew-time-rfc-regex s) + (format "%02d:%02d" + (or (mew-time-rfc-hour) 0) + (or (mew-time-rfc-min) 0)) + "00:00"))) + +(defun mew-summary-form-date () + "A function to return a date, MM/DD." + (let ((s (MEW-DATE))) + (when (or (string= s "") + (not (string-match mew-time-rfc-regex s))) + (setq s (mew-time-ctz-to-rfc + (mew-file-get-time (mew-expand-msg (MEW-FLD) (MEW-NUM)))))) + (if (string-match mew-time-rfc-regex s) + (format "%02d/%02d" + (mew-time-mon-str-to-int (mew-time-rfc-mon)) + (mew-time-rfc-day)) + ""))) + +(defun mew-summary-form-year () + "A function to return a message year, YYYY" + (let ((s (MEW-DATE)) year) + (when (or (string= s "") + (not (string-match mew-time-rfc-regex s))) + (setq s (mew-time-ctz-to-rfc + (mew-file-get-time (mew-expand-msg (MEW-FLD) (MEW-NUM)))))) + (if (not (string-match mew-time-rfc-regex s)) + "0000" + (setq year (mew-time-rfc-year)) + (cond + ((< year 50) + (setq year (+ year 2000))) + ((< year 100) + (setq year (+ year 1900)))) + (number-to-string year)))) + +(defun mew-summary-form-size () + "A function to return the size of the message. Should be used +with -4. See also 'mew-summary-form-size-0k' and 'mew-summary-form-size-huge'." + (let ((len-1 (1- (length mew-summary-form-size-unit))) + (SIZE (mew-scan-uid-size (MEW-UID))) + (i 0) size unit) + (if (and SIZE (string-match "^[0-9]+$" SIZE)) + (setq size (string-to-number SIZE)) + (setq size (mew-file-get-size (mew-expand-msg (MEW-FLD) (MEW-NUM))))) + (while (and (< i len-1) (>= size 1000)) + (setq size (/ size 1000)) + (setq i (1+ i))) + (if (and mew-summary-form-size-huge (>= size 1000)) + "HUGE" + (setq unit (nth i mew-summary-form-size-unit)) + (if (and mew-summary-form-size-0k (string= unit "")) + "0k" + (concat + (if (integerp size) + (number-to-string size) + (format "%.0f" size)) + unit))))) + +(defun mew-summary-form-extract-addr (addr) + "Extract addr according to 'mew-summary-form-extract-rule'." + (condition-case nil + (let* ((func (if mew-addrbook-for-summary + (mew-addrbook-func mew-addrbook-for-summary))) + (raw (or (mew-addrstr-parse-address addr) "")) + (rules mew-summary-form-extract-rule) + ret nickname) + (catch 'matched + (dolist (rule rules) + (cond + ((and (eq rule 'name) + (or (string-match "^\"\\([^\"]+\\)\"[ \t]*<[^>]+>" addr) + (string-match "^\\([^<]+\\)<[^>]+>" addr))) + (throw 'matched (setq ret (mew-chop (match-string 1 addr))))) + ((and (eq rule 'comment) + (string-match "^[^(]+(\\(.+\\))" addr)) + (throw 'matched (setq ret (mew-chop (match-string 1 addr))))) + ((eq rule 'address) + (throw 'matched (setq ret raw))) + ((and (eq rule 'nickname) + ;; set nickname here for efficiency + (or nickname + (setq nickname (if func (funcall func raw))))) + (throw 'matched (setq ret nickname))) + ((and (stringp rule) + (string-match rule addr)) + (throw 'matched (setq ret (mew-chop (match-string 1 addr)))))))) + (or ret addr)) + ;; a version of downcase causes error if argument is non-ascii. + (error mew-error-broken-address))) + +(defun mew-summary-form-from () + "A function to return an address. +If the message is destined to me AND 'mew-summary-form-from-me-prefix' +is a string, an address on To:, is returned. In this +case, 'mew-summary-form-from-me-prefix' is prepended to the address. + +Otherwise, an address on From: is returned. + +Address is converted by 'mew-summary-form-extract-addr'. See also +'mew-summary-form-extract-rule'." + (let* ((FROM (MEW-FROM)) (TO (MEW-TO)) + (from (or (mew-addrstr-parse-address FROM) ""))) + (cond + ((string= FROM "") + "") + ((and (stringp mew-summary-form-from-me-prefix) + (not (string= TO "")) + (mew-is-my-address mew-regex-my-address-list from)) + (mew-replace-white-space + (concat mew-summary-form-from-me-prefix (mew-summary-form-extract-addr TO)))) + (t + (mew-replace-white-space (mew-summary-form-extract-addr FROM)))))) + +(defun mew-summary-form-subj () + "A function to return Subject:. Unnecessary white spaces are removed." + ;; The beginning white spaces have been removed in mew-scan-header + ;; (mew-keyval). + (let ((subj (MEW-SUBJ))) + (if (string= subj "") (setq subj mew-error-no-subject)) + (if mew-decode-broken + subj + ;; already well-formatted + (mew-replace-white-space subj)))) + +(defun mew-summary-form-body () + (mew-header-sanity-check-string (MEW-BODY))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Scan from +;;; + +(defun mew-decide-summary-form (folder) + (mew-folder-spec folder + mew-summary-form-list + mew-summary-form-list-string-type + mew-summary-form-list-list-type)) + +(defun mew-get-summary-form (folder) + "Get summary-form from 'mew-summary-form-list', +'mew-summary-form-list-string-type, and 'mew-summary-form-list-list-type'. +'mew-summary-form-header' is prepended. " + (let* ((form-col (mew-decide-summary-form folder)) + (form (or (nth 0 form-col) mew-summary-form))) + (append mew-summary-form-header form))) + +(defun mew-get-summary-column (folder) + (let ((form-col (mew-decide-summary-form folder))) + (or (nth 1 form-col) + (mew-thread-column (mew-get-summary-form folder)) + mew-thread-column))) + +(defun mew-thread-column (form) + (let ((col 0)) + (catch 'loop + (dolist (ent form) + (cond + ((consp ent) + (setq col (+ col (abs (car ent))))) + ((stringp ent) + (setq col (+ col (string-width ent)))) + ((eq ent t) + (throw 'loop col)) + (t + (setq col (1+ col)))))))) + +(defun mew-get-unread-mark (folder) + (car (mew-folder-spec folder + mew-unread-mark-list + mew-unread-mark-list-string-type + mew-unread-mark-list-list-type))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; The engine function to call mew-summary-form-* +;;; + +(defvar mew-inherit-total nil) +(defvar mew-inherit-width nil) + +(defun mew-scan-get-piece (spec) + (let (func width str rightp nopad) + (if (stringp spec) + (progn + (setq mew-inherit-total (+ mew-inherit-total (string-width spec))) + spec) + (if (symbolp spec) + (setq width 1 func spec) + (mew-set '(width func) spec)) + (when (and (integerp width) (symbolp func)) + (when (= width 0) + (setq width (- mew-inherit-width mew-inherit-total 1)) + (unless mew-use-spc-padding + (setq nopad t))) + (if (< width 0) (setq width (abs width) rightp t)) + (setq mew-inherit-total (+ mew-inherit-total width)) + (setq func (intern-soft + (concat mew-summary-form-func-prefix (symbol-name func)))) + (when (fboundp func) + (setq str (funcall func)) + (if rightp + (if (<= (string-width str) width) + (format (format "%%%ds" width) str) + (setq mew-inherit-total (+ (- mew-inherit-total width) (string-width str))) + str) ;; width may exceed. + (mew-substring str width nil nopad))))))) + +(defun mew-sumsym-encode-folder (fld) + (mew-replace-character fld ? ?\t)) + +(defun mew-sumsym-decode-folder (fld) + (mew-replace-character fld ?\t ? )) + +(defun mew-scan-get-line (mew-vec mew-inherit-width) + (let* ((mew-inherit-total 0) (fld "") + (line (mapconcat 'mew-scan-get-piece (mew-sinfo-get-summary-form) "")) + par-id my-id msg ld uid siz irt-list) + (setq my-id (or (mew-idstr-get-first-id (MEW-ID)) "")) + ;; RFC 2822 says: the "In-Reply-To:" field may be used to identify + ;; the message (or messages) to which the new message is a reply, + ;; while the "References:" field may be used to identify a + ;; "thread" of conversation. + ;; + ;; However, even if the References field exists, it may not contain + ;; a parent's ID. So, if the In-Reply-To field contain one ID, + ;; we use it for thread. + ;; + ;; (1) The In-Reply-To contains one ID, use it. + ;; (2) The References contains one or more IDs, use the last one. + ;; (3) The In-Reply-To contains two or more IDs, use the first one. + (setq par-id (or (mew-idstr-get-first-id (MEW-XREF)) "")) + (when (string= par-id "") + (setq irt-list (mew-idstr-to-id-list (MEW-IRT))) + (if (= (length irt-list) 1) + (setq par-id (car irt-list)) + (setq par-id (or (mew-idstr-get-last-id (MEW-REF)) + (car irt-list) + "")))) + (when (mew-virtual-p) + (setq fld (mew-sumsym-encode-folder + (or (cdr (assoc (mew-scan-get-folder mew-vec) + (mew-vinfo-get-lra))) + ;; Spotlight + (MEW-FLD))))) ;; xxx + (setq msg (mew-scan-get-message mew-vec)) + (setq uid (or (mew-scan-uid-uid (MEW-UID)) "")) + (setq siz (or (mew-scan-uid-size (MEW-UID)) "")) + (setq ld (format "\r %s %s %s %s %s %s\n" fld msg my-id par-id uid siz)) + (cons line ld))) + +;; See also mew-summary-cook-region +(defun mew-scan-insert-line (folder vec width lmsg &optional mark-or-dst) + (when (get-buffer folder) + (with-current-buffer folder + (let* ((line (mew-scan-get-line vec width)) + (opos (point)) + (omax (point-max)) + beg med face olen nlen mark msg) + (mew-elet + (if (null lmsg) + (goto-char (point-max)) + ;; a message marked with 'T'. + (when (mew-summary-search-msg lmsg) + (setq mark (mew-summary-get-mark)) + (setq beg (point)) + (forward-line) + ;; To avoid inserting a line AFTER the cursor underline, + ;; keep this line and make it invisible. + (put-text-property beg (point) 'invisible t) + (forward-line -1))) + (setq beg (point)) + ;; To "insert" just after mew-marker-decode-syntax-end. + (insert (car line)) + (setq med (point)) + (insert (cdr line)) + (goto-char beg) + (cond + ((stringp mark-or-dst) ;; xxx + (setq msg (mew-scan-get-message vec)) + (mew-refile-reset msg) + (mew-refile-set msg (mew-split mark-or-dst ?,)) + (mew-summary-refile-log folder mark-or-dst) + (setq med (+ med (mew-summary-refile-override-body mark-or-dst 'force))) + (mew-mark-put mew-mark-refile)) + ((mew-characterp mark-or-dst) ;; mew-inbox-action-alist + (mew-mark-put mark-or-dst)) + (mark + (mew-summary-mark-as mark)) + ((and mew-use-highlight-mark ;; mew-summary-form-mark + (setq mark (mew-summary-get-mark)) ;; duplicated, etc + (setq face (mew-highlight-mark-get-face mark))) + (put-text-property beg med 'face face))) + (if mew-use-highlight-mouse-line + (put-text-property + beg med 'mouse-face mew-highlight-mouse-line-face)) + (forward-line) + (put-text-property med (1- (point)) 'invisible t) + ;; Removing the invisible line. + (when lmsg + ;; UID information will be removed. So, we need to adjust + ;; the position. + (setq nlen (- (point) beg)) + (setq beg (point)) + (forward-line) + (when (> opos beg) + (setq olen (- (point) beg)) + (setq opos (- opos (- olen nlen)))) + (delete-region beg (point)))) + (if (or (eq opos (mew-sinfo-get-start-point)) + (/= opos omax)) + ;; move the cursor to the original position. + (goto-char opos)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub-functions for Scan +;;; + +(defun mew-scan-header (&optional draftp) + (let ((vec (make-vector (length mew-scan-fields) "")) + (lim (1- mew-scan-max-field-length)) + i key med str n) + (goto-char (point-min)) + (unless (re-search-forward mew-eoh nil t) + (goto-char (point-max))) + (save-restriction + (narrow-to-region (point-min) (point)) + (goto-char (point-min)) + (while (not (eobp)) + (if (not (looking-at mew-keyval)) + (forward-line) + (setq key (mew-capitalize (mew-match-string 1))) + (setq med (match-end 0)) + ;; Three lines should be enough for Summary mode. + (forward-line) + (setq i 0) + (while (and (< i lim) (looking-at mew-lwsp)) + (forward-line) + (setq i (1+ i))) + (when (and (setq n (mew-member-case-equal key mew-scan-fields)) + (string= (aref vec n) "")) ;; avoid multiple times + (when (member key mew-scan-decode-fields) + (mew-header-decode-region key med (point) draftp)) + ;; We need to keep composite properties of charset. + ;; This must be "buffer-substring". + (setq str (buffer-substring med (1- (point)))) + (aset vec n str)) + (mew-header-goto-next)))) + vec)) + +(defun mew-scan-field-to-func (key) + (let ((n (mew-member-case-equal key mew-scan-fields)) + (len (length mew-scan-fields-alias)) + ali) + (if (and n (< n len)) (setq ali (nth n mew-scan-fields-alias))) + (if (stringp ali) (symbol-function (intern-soft (concat "MEW-" ali)))))) + +(defun mew-scan-inbox-action (mew-vec case) + (let ((alist (mew-inbox-action-alist case)) + key val val-func ret mark-or-dst regex-list) + (catch 'loop + (dolist (ent alist) + (setq key (car ent)) + (setq val-func (mew-scan-field-to-func key)) + (if (and val-func (functionp val-func)) + (setq val (funcall val-func)) + (setq val nil)) + (when val + (setq ent (cdr ent)) + (dolist (act ent) + (if (symbolp act) + (when (fboundp act) + (setq ret (funcall act val)) + (if ret (throw 'loop nil))) + (when (listp act) + (setq mark-or-dst (car act)) + (setq regex-list (cdr act)) + (dolist (rl regex-list) + (if (string-match rl val) + (throw 'loop (setq ret mark-or-dst)))))))))) + ret)) + +(defvar mew-regex-ignore-scan-body-list + '("^[ \t]*$" + "^[ \t]*[-a-zA-Z0-9]+: " + "^[ \t]*[[>:|#;/_}]" + "^[ \t]*\\w+\\(['._-]+\\w+\\)*>" + "^[ \t]*[[ mew-summary-scan-width 40)) ;; xxx + mew-summary-scan-width + (max mew-window-magic (window-width)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; X-Mew-Uidl: +;;; + +(defun mew-scan-uid-uid (uid) + (nth 0 (mew-split uid mew-sp))) + +(defun mew-scan-uid-size (uid) + (nth 1 (mew-split uid mew-sp))) + +(defun mew-scan-uid-case (uid) + (nth 2 (mew-split uid mew-sp))) + +(defun mew-header-insert-xmu (uid siz truncated &optional case) + (when (and (stringp uid) (stringp siz)) + (setq siz (number-to-string (string-to-number siz))) ;; removing 0 + (let (fields) + (if (not truncated) + (setq fields (concat uid " " siz)) + (setq fields (concat uid " 0" siz)) ;; e.g. 0500 == truncated + (if case (setq fields (concat fields " " case)))) + (save-excursion + (mew-header-delete-lines (list mew-x-mew-uidl:))) + (mew-header-insert mew-x-mew-uidl: fields 'no-fold)))) + +(defun mew-scan-message-truncatedp () + (mew-msg-truncatedp (mew-scan-uid-size (MEW-UID)))) + +(defun mew-scan-message-invalidp () + (mew-msg-invalidp (MEW-NUM))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Scanning a folder +;;; + +(defun mew-summary-ls (&optional header-only goend update) + "List this folder asynchronously. + +In a LOCAL folder: messages in the local folder are scanned according +to the range which you specify. + +In a REMOTE folder: messages in the server's folder are cached +according to the range which you specify. If +'mew-pop-header-only'/'mew-imap-header-only'/'mew-nntp-header-only' is +non-nil, only headers of messages are cached. If executed with +'\\[universal-argument]', these variables are considered reversed." + (interactive "P") + (mew-summary-only + (when (mew-summary-exclusive-p) + (let* ((bnm (mew-summary-folder-name 'ext)) + (case (mew-sinfo-get-case)) + (fld (mew-sinfo-get-folder)) + (askp mew-ask-range) + (directive 'scan) + (get-body (not header-only)) + scanp range dir-newp) + (mew-summary-folder-cache-load) + (cond + (update + (setq askp nil) + (setq range nil) ;; update + (setq scanp t)) + ((mew-called-interactively-p) ;; "s" + (setq askp t) + (setq scanp t)) + ((mew-summary-folder-dir-newp) ;; "g" + (setq askp nil) + (setq scanp t))) + ;; for mew-summary-exchange-point. + (mew-sinfo-set-ret-pos (point)) + (if (mew-summary-folder-dir-newp) (setq dir-newp t)) + (if (or (mew-called-interactively-p) goend) (goto-char (point-max))) + (set-buffer-modified-p nil) + (if (not scanp) + (progn + (run-hooks 'mew-summary-ls-no-scan-hook) + t) ;; return value (not scanned) + (mew-summary-reset) + ;; + (mew-sinfo-set-direction 'down) + (cond + ((and (mew-folder-remotep fld) + (not (mew-folder-imap-queuep))) + (if (and dir-newp (mew-folder-imapp fld)) + (mew-local-retrieve 'scan bnm (mew-range-update bnm)) + (if askp (setq range (mew-input-range-remote bnm))) + (when (eq range 'sync) + (setq range nil) + (setq directive 'sync)) + (cond + ((mew-folder-popp fld) + (if (mew-pop-header-only case) + (setq get-body (not get-body))) + (mew-pop-retrieve case directive bnm range get-body)) + ((mew-folder-imapp fld) + (if (mew-imap-header-only case) + (setq get-body (not get-body))) + (mew-imap-retrieve case directive bnm range get-body)) + ((mew-folder-nntpp fld) + (if (mew-nntp-header-only case) + (setq get-body (not get-body))) + (mew-nntp-retrieve case directive bnm range get-body))))) + (t ;; local + (setq range (mew-input-range bnm askp)) + (if range + (mew-local-retrieve 'scan bnm (nth 0 range) (nth 1 range)) + (message "range is wrong")))) + nil))))) ;; return value (scanned) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Summary file cache +;;; + +(defun mew-compare-times (t1 t2) + ;; Is t1 newer than t2? + (cond + ((null t1) nil) + ((null t2) t) ;; do update + ((> (nth 0 t1) (nth 0 t2)) t) + ((= (nth 0 t1) (nth 0 t2)) + (if (> (nth 1 t1) (nth 1 t2)) t nil)) ;; nil if equal + (t nil))) + +(defun mew-summary-folder-dir-newp () + (let* ((folder (mew-summary-folder-name 'ext)) + (dir (file-chase-links (mew-expand-folder folder))) + (mfile (expand-file-name mew-summary-touch-file dir)) + (t1 (mew-file-get-time mfile)) + (cache (expand-file-name mew-summary-cache-file dir)) + (t2 (mew-file-get-time cache))) + (if (and (null t1) + (file-directory-p dir) + (mew-dir-messages dir)) + t + (mew-compare-times t1 t2)))) + +(defun mew-summary-folder-cache-newp () + (let* ((folder (mew-summary-folder-name 'ext)) + (cache (mew-expand-file folder mew-summary-cache-file)) + (t1 (mew-file-get-time cache)) + (t2 (mew-sinfo-get-cache-time))) + (mew-compare-times t1 t2))) + +(defun mew-summary-set-count-line () + (let* ((ttl-line (mew-count-lines (point-min) (point-max))) + (mid-point (/ (buffer-size) 2)) + (mid-marker (mew-sinfo-get-mid-marker)) + mid-line) + (save-excursion + (goto-char mid-point) + (beginning-of-line) + (if (and (mew-thread-p) mew-use-thread-separator + (looking-at mew-regex-thread-separator)) + (forward-line)) + (setq mid-point (point)) + (setq mid-line (mew-count-lines (point-min) (point)))) + (mew-sinfo-set-ttl-line ttl-line) + (mew-sinfo-set-mid-line mid-line) + (unless (markerp mid-marker) + (setq mid-marker (make-marker)) + (mew-sinfo-set-mid-marker mid-marker)) + (set-marker mid-marker mid-point))) + +(defun mew-summary-folder-cache-load () + (let* ((folder (mew-summary-folder-name 'ext)) + (cache (mew-expand-file folder mew-summary-cache-file)) + refile refs) + (when (and (file-readable-p cache) + (mew-summary-folder-cache-newp)) + (mew-elet + (mew-erase-buffer) + (mew-frwlet mew-cs-m17n mew-cs-dummy + (mew-insert-file-contents cache)) + (mew-sinfo-set-cache-time (mew-file-get-time cache)) + (if (= (point-max) 1) + (setq mew-summary-buffer-raw nil) + (setq mew-summary-buffer-raw t)) + (mew-sinfo-load) + (setq refs (mew-summary-mark-collect mew-mark-refile)) + (setq refile (mew-summary-mark-recover + (mew-sinfo-get-mark-hist) (mew-sinfo-get-refile) refs)) + (mew-sinfo-set-refile refile) + (mew-summary-set-count-line) + (set-buffer-modified-p nil))))) + +(defun mew-summary-folder-cache-save () + (let* ((folder (mew-summary-folder-name 'ext)) + (cache (mew-expand-file folder mew-summary-cache-file))) + (when (file-writable-p cache) + (mew-touch-folder folder) + (save-restriction + (widen) + (if (mew-decode-syntax-p) + (let ((cbuf (current-buffer)) + (min (point-min)) + (max (point-max)) + (beg (mew-decode-syntax-begin)) + (end (mew-decode-syntax-end))) + (with-temp-buffer + (mew-insert-buffer-substring cbuf min beg) + (mew-insert-buffer-substring cbuf end max) + (mew-frwlet mew-cs-dummy mew-cs-m17n + (write-region (point-min) (point-max) cache nil 'no-msg)))) + ;; (write-region 1 1 ...) does not update the file timestamp + ;; but does the directory timestamp. So, we need to delete + ;; the file to update the file timestamp. + (if (= (point-min) (point-max)) (mew-delete-file cache)) + (mew-frwlet mew-cs-dummy mew-cs-m17n + (write-region (point-min) (point-max) cache nil 'no-msg)) + (mew-set-file-modes cache)) + (mew-summary-set-count-line) + (mew-sinfo-set-cache-time (mew-file-get-time cache)) + (mew-sinfo-save) + (mew-sinfo-set-mark-hist nil))))) + +;; See also mew-net-folder-clean. +(defun mew-summary-folder-cache-clean (folder) + "Erase Summary mode then remove and touch the cache file." + (if (get-buffer folder) + (with-current-buffer folder + (mew-erase-buffer) + (set-buffer-modified-p nil))) + (let ((cfile (mew-expand-file folder mew-summary-cache-file))) + (if (file-exists-p cfile) + (write-region "" nil cfile nil 'no-msg)))) + +(provide 'mew-scan) + +(defvar mew-compiling nil) +(eval-when-compile + (when mew-compiling + (require 'mew-varsx) + (mew-scan-setup))) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-scan.el ends here diff --git a/elpa/mew-20150813.2354/mew-search.el b/elpa/mew-20150813.2354/mew-search.el new file mode 100644 index 00000000..e9ccd26e --- /dev/null +++ b/elpa/mew-20150813.2354/mew-search.el @@ -0,0 +1,814 @@ +;;; mew-search.el --- Index Search + +;; Author: Kazu Yamamoto +;; Created: Aug 24, 2005 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Variables +;;; + +(defvar mew-prog-spotlight "mdfind") +(defvar mew-prog-wds "wdsgrep.exe") +(defvar mew-prog-google "gdgrep.rb") +(defvar mew-prog-est "estcmd") + +(mew-defstruct search + key name prog + func-search func-virtual + func-index-folder func-index-all + func-canonicalize-pattern + func-register func-unregister func-filter) + +(defvar mew-search-switch + `((spotlight "Spotlight" ,mew-prog-spotlight + mew-search-with-spotlight mew-search-virtual-with-spotlight + mew-spotlight-index-folder mew-spotlight-index-all + mew-pick-canonicalize-pattern-spotlight + nil nil) + (wds "WDS" ,mew-prog-wds + mew-search-with-wds mew-search-virtual-with-wds + mew-wds-index-folder mew-wds-index-all + mew-pick-canonicalize-pattern-wds + mew-wds-register mew-wds-unregister) + (google "Google" ,mew-prog-google + mew-search-with-google mew-search-virtual-with-google + mew-google-index-folder mew-google-index-all + mew-pick-canonicalize-pattern-google + mew-google-register mew-google-unregister) + (est "Hyper Estraier" ,mew-prog-est + mew-search-with-est mew-search-virtual-with-est + mew-est-index-folder mew-est-index-all + mew-pick-canonicalize-pattern-est + nil nil + mew-est-input-filter))) + +(defun mew-search-get-list (func) + (let ((sw mew-search-switch) + ent ret) + (while sw + (setq ent (car sw)) + (setq sw (cdr sw)) + (if (mew-which-exec (mew-search-get-prog ent)) + (setq ret (cons (funcall func ent) ret)))) + (nreverse ret))) + +(defun mew-search-get-ent (method) + (assoc method mew-search-switch)) + +(defvar mew-search-method (car (mew-search-get-list 'mew-search-get-key))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Launcher +;;; + +(defun mew-summary-search-change-method () + "Change a search method." + (interactive) + (let* ((names (mew-search-get-list 'mew-search-get-name)) + (ent (mew-search-get-ent mew-search-method)) + (default (mew-search-get-name ent)) + name) + (if (not names) + (message "No search method") + (setq names (mapcar (lambda (x) (list x)) names)) + (setq name (completing-read (format "Search method (%s): " default) + names nil t nil nil default)) + (setq mew-search-method (nth 0 (mew-assoc-equal name mew-search-switch 1)))))) + +(defun mew-summary-search () + "Pick messages according to a specified pick pattern +with a search method. Then put the '*' mark onto them. " + (interactive) + (mew-pickable + (if (not mew-search-method) + (message "No search method") + (let* ((ent (mew-search-get-ent mew-search-method)) + (func (mew-search-get-func-search ent)) + (name (mew-search-get-name ent)) + (canon-func (mew-search-get-func-canonicalize-pattern ent)) + (flt-func (mew-search-get-func-filter ent)) + (folder (mew-summary-physical-folder)) + pattern msgs filter) + (if (not (fboundp func)) + (message "This command cannot be used") + (setq pattern (if flt-func + (read-string (concat name " pick pattern: ")) + (mew-input-pick-pattern (concat name " pick")))) + (if (and (string= pattern "") (not (fboundp flt-func))) + (message (mew-substitute-for-summary "Keyword must be specified. You may use '\\[mew-summary-pick]' instead")) + (when (and canon-func (fboundp canon-func)) + (setq pattern (funcall canon-func pattern))) + (if (fboundp flt-func) + (setq filter (funcall flt-func))) + (setq msgs (funcall func pattern folder filter)) + (mew-summary-pick-ls folder msgs))))))) + +(defun mew-summary-selection-by-search (&optional ask-folder) + "Making selection according to a specified pick pattern +with a search method." + (interactive "P") + (if (not mew-search-method) + (message "No search method") + (let* ((ofolder (mew-summary-folder-name 'ext)) + (ent (mew-search-get-ent mew-search-method)) + (func (mew-search-get-func-virtual ent)) + (name (mew-search-get-name ent)) + (canon-func (mew-search-get-func-canonicalize-pattern ent)) + (flt-func (mew-search-get-func-filter ent)) + vfolder opattern pattern dfunc file opts rttl file-rttl flds filter) + (if (not (fboundp func)) + (message "This command cannot be used") + (if ask-folder + (setq flds (mew-input-folders + (or (mew-summary-folder-name) + (mew-case-folder + mew-case + (mew-proto-inbox-folder (mew-proto mew-case))))))) + (setq opattern (if flt-func + (read-string (concat name " virtual pattern: ")) + (mew-input-pick-pattern (concat name " virtual")))) + (if (and (string= opattern "") (not (fboundp flt-func))) + (message (mew-substitute-for-summary "Keyword must be specified")) + (if (string= opattern "") (setq opattern " ")) + (if (and canon-func (fboundp canon-func)) + (setq pattern (funcall canon-func opattern)) + (setq pattern opattern)) + (when (fboundp flt-func) + (setq filter (funcall flt-func)) + (if (string= opattern " ") (setq opattern "")) + (setq opattern (concat opattern filter))) + (setq vfolder (mew-folder-to-selection opattern)) + (mew-summary-switch-to-folder vfolder) + (mew-vinfo-set-mode 'selection) + (mew-vinfo-set-physical-folder nil) + (mew-vinfo-set-original-folder ofolder) + (mew-sinfo-set-find-key opattern) + (make-local-variable 'mew-summary-form-mark-delete) + (setq mew-summary-form-mark-delete nil) + (make-local-variable 'mew-summary-form-mark-spam) + (setq mew-summary-form-mark-spam nil) + (when (mew-summary-exclusive-p) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (mew-piolet mew-cs-text-for-read mew-cs-text-for-write + (setq file-rttl (funcall func pattern flds filter))))) + (mew-set '(file rttl) file-rttl) + (setq dfunc `(lambda () (mew-delete-file ,file))) + (setq opts (list "-i" file)) + (mew-local-retrieve 'vir opts dfunc nil nil rttl)))))) + +(defun mew-summary-make-index-folder () + "Make index for this folder." + (interactive) + (mew-summary-only + (if (not mew-search-method) + (message "No search method") + (let* ((ent (mew-search-get-ent mew-search-method)) + (func (mew-search-get-func-index-folder ent)) + (folder (mew-summary-folder-name 'ext))) + (if (not (fboundp func)) + (message "This command cannot be used") + (funcall func folder)))))) + +(defun mew-summary-make-index-all () + "Make index for all folders." + (interactive) + (if (not mew-search-method) + (message "No search method") + (let* ((ent (mew-search-get-ent mew-search-method)) + (func (mew-search-get-func-index-all ent))) + (if (fboundp func) + (funcall func) + (message "This command cannot be used"))))) + +(defun mew-summary-search-register () + (interactive) + (if (not mew-search-method) + (message "No search method") + (let* ((ent (mew-search-get-ent mew-search-method)) + (func (mew-search-get-func-register ent))) + (if (not (fboundp func)) + (message "This command cannot be used") + (funcall func))))) + +(defun mew-summary-search-unregister () + (interactive) + (if (not mew-search-method) + (message "No search method") + (let* ((ent (mew-search-get-ent mew-search-method)) + (func (mew-search-get-func-unregister ent))) + (if (not (fboundp func)) + (message "This command cannot be used") + (funcall func))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Spotlight +;;; + +(defun mew-assoc-match-list (key alist nth) + (let ((case-fold-search t) a n ret) + (while alist + (setq a (car alist)) + (setq n (nth nth a)) + (if (or (and (stringp n) (string-match key n)) + (equal n key) (eq n t)) + (setq ret (cons a ret))) + (setq alist (cdr alist))) + ret)) ;; not reversed + +(defun mew-expand-wildcard-folder (wlist) + (let (case fld ent ret flds regex alist) + (while wlist + (setq ent (car wlist)) + (setq wlist (cdr wlist)) + (setq case (mew-case:folder-case ent)) + (setq fld (mew-case:folder-folder ent)) + (if (not (string-match "\\*$" fld)) + (setq ret (cons ent ret)) + (setq regex (substring fld 0 -1)) + (setq regex (concat "^" (regexp-quote regex))) + (cond + ((mew-folder-popp fld) + (setq alist (mew-pop-folder-alist))) + ((mew-folder-nntpp fld) + (setq alist (mew-nntp-folder-alist case))) + ((mew-folder-imapp fld) + (setq alist (mew-imap-folder-alist case))) + (t + (setq alist (mew-local-folder-alist)))) + (setq flds (mew-assoc-match-list regex alist 0)) + (setq flds (mapcar (lambda (x) (mew-case-folder case (nth 0 x))) flds)) + (setq ret (nconc flds ret)))) + (nreverse ret))) + +(defun mew-search-spotlight (pattern path) + (setq pattern (mew-cs-encode-string pattern 'utf-8)) + (let* ((ent (mew-search-get-ent mew-search-method)) + (prog (mew-search-get-prog ent))) + (mew-plet + (mew-alet + (call-process prog nil t nil "-onlyin" path pattern))))) + +(defun mew-search-with-spotlight (pattern folder &optional dummy) + (let ((path (mew-expand-folder folder)) + msgs) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (mew-search-spotlight pattern path) + (goto-char (point-min)) + (while (re-search-forward mew-regex-message-files5 nil t) + (setq msgs (cons (mew-match-string 1) msgs)) + (forward-line)) + (setq msgs (nreverse msgs)) + (setq msgs (sort (mapcar 'string-to-number msgs) '<)) + (mapcar 'number-to-string msgs)))) + +(defun mew-search-virtual-with-spotlight (pattern flds &optional dummy) + (let* ((mpath (mew-expand-folder mew-folder-local)) + (mail-regex (regexp-quote (file-name-as-directory mpath))) + (regex (format "^%s%s\\([0-9]+\\)\\(%s\\)?$" mail-regex (file-name-as-directory "\\(.*\\)") mew-suffix)) + (file (mew-make-temp-name)) + (prev "") (rttl 0) (n 1) crnt path) + (unless flds (setq flds (list mew-folder-local))) + (setq flds (mew-expand-wildcard-folder flds)) + (while flds + (setq path (mew-expand-folder (car flds))) + (setq flds (cdr flds)) + (mew-search-spotlight pattern path) + (goto-char (point-min)) + (while (not (eobp)) + (when (looking-at regex) + (setq rttl (1+ rttl)) + (setq crnt (match-string 1)) + (delete-region (match-beginning 0) (match-beginning 2)) + (when (not (string= crnt prev)) + (beginning-of-line) + (insert "CD:" mew-folder-local crnt "\n")) + (setq prev crnt) + (forward-line))) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (write-region (point-min) (point-max) file (> n 1) 'no-msg)) + (mew-erase-buffer) + (setq n (1+ n))) + (list file rttl))) + +(defun mew-spotlight-index (dir) + (let* ((default-directory dir) + (msgs (mew-dir-messages dir mew-regex-message-files3 'full)) + dirent subdir) + (while msgs + (mew-set-file-type (car msgs)) + (setq msgs (cdr msgs))) + (when (/= (mew-file-get-links dir) 2) + (setq dirent (directory-files "." nil mew-regex-folder-candidate)) + (while dirent + (setq subdir (car dirent)) + (setq dirent (cdr dirent)) + (when (and (file-directory-p subdir) + (not (file-symlink-p subdir))) + (mew-spotlight-index (expand-file-name subdir dir))))))) + +(defun mew-spotlight-index-folder (folder) + "Making spotlight index for this folder." + (let* ((dir (mew-expand-folder folder)) + (msgs (mew-dir-messages dir mew-regex-message-files3 'full))) + (message "Spotlight indexing for %s..." folder) + (while msgs + (mew-set-file-type (car msgs)) + (setq msgs (cdr msgs))) + (message "Spotlight indexing for %s...done" folder))) + +(defun mew-spotlight-index-all () + "Making spotlight index for all messages." + (interactive) + (when (y-or-n-p "Make Spotlight index for all folders? ") + (message "Spotlight indexing for all folders...") + (let ((flds '("+" "+#imap" "+#pop" "+#nntp")) + dir) + (while flds + (setq dir (mew-expand-folder (car flds))) + (setq flds (cdr flds)) + (if (file-directory-p dir) (mew-spotlight-index dir)))) + (message "Spotlight indexing for all folders...done"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Google Desktop +;;; + +(defun mew-search-google (pattern path) + (setq pattern (mew-cs-encode-string pattern 'shift_jis)) + (let* ((ent (mew-search-get-ent mew-search-method)) + (prog (mew-search-get-prog ent))) + (mew-plet + (mew-alet + (call-process prog nil t nil "-m" "-p" path "-s" "-q" pattern))))) + +(defun mew-search-with-google (pattern folder &optional dummy) + (let* ((path (mew-expand-folder folder)) + msgs) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (mew-search-google pattern path) + (goto-char (point-min)) + (while (re-search-forward mew-regex-message-files5 nil t) + (setq msgs (cons (mew-match-string 1) msgs)) + (forward-line)) + (setq msgs (nreverse msgs)) + (setq msgs (sort (mapcar 'string-to-number msgs) '<)) + (mapcar 'number-to-string msgs)))) + +;; xxx flds are not used at this moment +(defun mew-search-virtual-with-google (pattern flds &optional dummy) + (let* ((path (mew-expand-folder mew-folder-local)) + (mail-regex (regexp-quote (file-name-as-directory path))) + (regex (concat "^" mail-regex "\\(.*\\)/" "\\([0-9]+\\)")) + (file (mew-make-temp-name)) + (prev "") (rttl 0) + crnt) + (mew-search-google pattern path) + (goto-char (point-min)) + (while (not (eobp)) + (when (looking-at regex) + (setq rttl (1+ rttl)) + (setq crnt (match-string 1)) + (delete-region (match-beginning 0) (match-beginning 2)) + (when (not (string= crnt prev)) + (beginning-of-line) + (insert "CD:" mew-folder-local crnt "\n")) + (setq prev crnt) + (forward-line))) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (write-region (point-min) (point-max) file nil 'no-msg)) + (list file rttl))) + +(defun mew-google-index-folder (folder) + "Make Google index for this folder." + (let* ((ent (mew-search-get-ent mew-search-method)) + (prog (mew-search-get-prog ent))) + (start-process prog nil prog "-m" "-i" (mew-expand-folder folder)) + (message "Google indexing for %s in background..." folder))) + +(defun mew-google-index-all () + "Make Google index for all folders." + (interactive) + (let* ((ent (mew-search-get-ent mew-search-method)) + (prog (mew-search-get-prog ent))) + (start-process prog nil prog "-m" "-r" "-i" (mew-expand-folder "+")) + (message "Google indexing for all folders in background..."))) + +(defun mew-google-register () + "Register Google component" + (interactive) + (message "Registering Google component...") + (call-process mew-prog-google nil nil nil "-R") + (message "Registering Google component...done")) + +(defun mew-google-unregister () + "Unregister Google component" + (interactive) + (message "Unregistering Google component...") + (call-process mew-prog-google nil nil nil "-U") + (message "Unregistering Google component...done")) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; WDS Desktop +;;; + +(defun mew-search-wds (pattern path) + (setq pattern (mew-cs-encode-string pattern default-file-name-coding-system)) + (let* ((ent (mew-search-get-ent mew-search-method)) + (prog (mew-search-get-prog ent))) + (mew-plet + (mew-alet + (call-process prog nil t nil "-e" mew-suffix "-p" path "-s" pattern))))) + +(defun mew-search-with-wds (pattern folder &optional dummy) + (let* ((path (mew-expand-folder folder)) + msgs) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (mew-search-wds pattern path) + (goto-char (point-min)) + (while (re-search-forward mew-regex-message-files5 nil t) + (setq msgs (cons (mew-match-string 1) msgs)) + (forward-line)) + (setq msgs (nreverse msgs)) + (setq msgs (sort (mapcar 'string-to-number msgs) '<)) + (mapcar 'number-to-string msgs)))) + +;; xxx flds are not used at this moment +(defun mew-search-virtual-with-wds (pattern flds &optional dummy) + (let* ((path (mew-expand-folder mew-folder-local)) + (mail-regex (regexp-quote (file-name-as-directory path))) + (regex (concat "^" mail-regex "\\(.*\\)/" "\\([0-9]+\\)")) + (file (mew-make-temp-name)) + (prev "") (rttl 0) + crnt) + (mew-search-wds pattern path) + (goto-char (point-min)) + (while (not (eobp)) + (when (looking-at regex) + (setq rttl (1+ rttl)) + (setq crnt (match-string 1)) + (delete-region (match-beginning 0) (match-beginning 2)) + (when (not (string= crnt prev)) + (beginning-of-line) + (insert "CD:" mew-folder-local crnt "\n")) + (setq prev crnt)) + (forward-line)) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (write-region (point-min) (point-max) file nil 'no-msg)) + (list file rttl))) + +(defun mew-wds-index-folder (folder) + "Make WDS index for all folders." + (mew-wds-index-all)) + +(defun mew-wds-index-all () + "Make WDS index for all folders." + (interactive) + (let* ((ent (mew-search-get-ent mew-search-method)) + (prog (mew-search-get-prog ent))) + (start-process prog nil prog "-R" (format "%s=%s" mew-suffix ".eml")) + (message "WDS indexing for all folders in background..."))) + +(defun mew-wds-register () + "Register '.mew' to WDS" + (interactive) + (message "Registering suffix '%s' to WDS..." mew-suffix) + (call-process mew-prog-wds nil nil nil "-R" (format "%s=%s" mew-suffix ".eml")) + (message "Registering suffix '%s' to WDS...done" mew-suffix)) + +(defun mew-wds-unregister () + "Unregister '.mew' from WDS" + (interactive) + (message "This command cannot be used")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Hyper Estraier +;;; + +(defun mew-est-input-filter () + (mew-input-pick-pattern "Hyper Estraier filter")) + +(defvar mew-search-est-db "casket") +(defvar mew-prog-est-update "mewest") + +(defun mew-search-est (pattern path filter) + (setq pattern (mew-cs-encode-string pattern mew-cs-est)) + (if (string= filter "") + (setq filter nil) + (setq filter (mew-cs-encode-string filter mew-cs-est)) + (setq filter (let ((mew-inherit-pick-omit-and t)) + (mew-pick-parse (mew-pick-lex filter)))) + (setq filter (mapcar 'mew-pick-filter-est-kyvl filter))) + (let* ((ent (mew-search-get-ent mew-search-method)) + (prog (mew-search-get-prog ent)) + (casket (expand-file-name mew-search-est-db mew-conf-path)) + ;; mew-home is not good for Zaurus + (pregex (concat "^" + (regexp-quote + (file-name-directory + (directory-file-name + (file-truename + (expand-file-name mew-mail-path))))))) + attr args) + (setq path (file-truename (file-name-as-directory path))) + (when (string-match pregex path) + (setq path (substring path (match-end 0))) + (mew-plet + (mew-alet + (setq attr (format "@uri STRINC %s" (mew-q-encode-string path ?%))) + (cond + ((string-match "^ *ANDNOT " pattern) + (setq pattern (concat "[UVSET] " pattern))) + ((string-match "^ *$" pattern) + (setq pattern "[UVSET]"))) + (setq args (list "-vu" "-max" "-1" "-ord" "@cdate NUMA" casket pattern)) + (unless (eq mew-cs-est 'utf-8) + (setq args (cons (mew-cs-to-charset mew-cs-est) args)) + (setq args (cons "-ic" args))) + (setq filter (nreverse filter)) + (while filter + (setq args (cons "-attr" (cons (car filter) args))) + (setq filter (cdr filter))) + (setq args (cons "-attr" (cons attr args))) + (apply 'call-process prog nil t nil "search" args)))))) + +(defun mew-search-with-est (pattern folder filter) + (let* ((path (mew-expand-folder folder)) + (regex (format "file://.*/%s/.*/\\([0-9]+\\)\\(%s\\)?$" + (file-name-nondirectory mew-mail-path) + (regexp-quote mew-suffix))) + msgs) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (mew-search-est pattern path filter) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (setq msgs (cons (mew-match-string 1) msgs)) + (forward-line)) + (setq msgs (nreverse msgs)) + (setq msgs (sort (mapcar 'string-to-number msgs) '<)) + (mapcar 'number-to-string msgs)))) + +(defun mew-search-virtual-with-est (pattern flds filter) + (let* ((regex (format "file://.*/%s/\\(.*\\)/\\([0-9]+\\)\\(%s\\)?$" + (file-name-nondirectory mew-mail-path) + (regexp-quote mew-suffix))) + (file (mew-make-temp-name)) + (prev "") (rttl 0) (n 1) + path crnt start) + (unless flds (setq flds (list mew-folder-local))) + (setq flds (mew-expand-wildcard-folder flds)) + (while flds + (setq path (mew-expand-folder (car flds))) + (setq flds (cdr flds)) + (mew-search-est pattern path filter) + (goto-char (point-min)) + (setq start (point)) + (while (re-search-forward regex nil t) + (setq rttl (1+ rttl)) + (setq crnt (match-string 1)) + (delete-region start (match-beginning 2)) + (when (not (string= crnt prev)) + (beginning-of-line) + (insert "CD:" mew-folder-local (mew-q-decode-string crnt ?%) "\n")) + (setq prev crnt) + (forward-line) + (setq start (point))) + (delete-region start (point-max)) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (write-region (point-min) (point-max) file (> n 1) 'no-msg)) + (mew-erase-buffer) + (setq n (1+ n))) + (list file rttl))) + +(defun mew-est-index-folder (folder) + "Make Hyper Estraier index for this folder." + (interactive) + (if (not (mew-which-exec mew-prog-est-update)) + (message "\"%s\" does not exist" mew-prog-est-update) + (message "Hyper Estraier indexing for %s..." folder) + (let* ((path (file-truename (mew-expand-folder folder))) + (pro (start-process "*Mew EST*" nil mew-prog-est-update "-s" mew-suffix "-b" (mew-expand-folder mew-mail-path) path))) + (set-process-filter pro 'mew-est-index-filter) + (set-process-sentinel pro 'mew-est-index-sentinel)))) + +(defun mew-est-index-all () + "Make Hyper Estraier index for all folders." + (interactive) + (if (not (mew-which-exec mew-prog-est-update)) + (message "'%s' does not exist" mew-prog-est-update) + (message "Hyper Estraier indexing...") + (let ((pro (start-process "*Mew EST*" nil mew-prog-est-update "-s" mew-suffix "-b" (mew-expand-folder mew-mail-path)))) + (set-process-filter pro 'mew-est-index-filter) + (set-process-sentinel pro 'mew-est-index-sentinel)))) + +(defun mew-est-index-filter (process string) + (save-excursion + (cond + ((string-match "exists" string) + (message "Another Hyper Estraier indexer is running")) + ((string-match "\.\.\.failed" string) + (message "Hyper Estraier indexing ...failed")) + ((string-match "old messages\.\.\.done" string) + (message "Hyper Estraier purging ...done")) + ((string-match "new messages\.\.\.done" string) + (message "Hyper Estraier indexing ...done"))))) + +(defun mew-est-index-sentinel (process event) + (save-excursion )) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; View +;;; + +(defvar mew-prog-smew "smew") +(defvar mew-prog-cmew "cmew") +(defvar mew-id-db-file "id.db") +(defvar mew-id-db-ignore-regex "^\\./casket$|^\\./casket/|/\\.") + +(defmacro mew-msgid-check (&rest body) + `(let ((db (mew-expand-file "+" mew-id-db-file))) + (cond + ((not (file-exists-p db)) + (message "%s not found" mew-id-db-file)) + ((not (mew-which-exec mew-prog-smew)) + (message "%s not found" mew-prog-smew)) + (t + ,@body)))) + +(defun mew-summary-selection-by-msgid () + "Creating Virtual mode with messages relating to the current message" + (interactive) + (mew-msgid-check + (mew-summary-msg + (let* ((ofolder (mew-summary-folder-name 'ext)) + (subj (or (mew-summary-get-subject) mew-error-no-subject)) + (str (mew-subject-simplify2 subj)) + (vfolder (mew-folder-to-selection + (if (string= str "") mew-error-no-subject subj))) + (regex (format "\\(.*\\)/\\([0-9]+\\)\\(%s\\)?$" (regexp-quote mew-suffix))) + (rttl 0) + (file (mew-make-temp-name)) + (db (mew-expand-file "+" mew-id-db-file)) + (mydir (substring (mew-path-to-folder (mew-expand-folder (mew-summary-folder-name))) 1)) + crnt start prev opts dfunc myid) + (mew-sumsyn-match mew-regex-sumsyn-long) + (setq myid (mew-sumsyn-my-id)) + ;; + (mew-summary-switch-to-folder vfolder) + (mew-vinfo-set-mode 'selection) + (mew-vinfo-set-physical-folder nil) + (mew-vinfo-set-original-folder ofolder) + (mew-erase-buffer) + ;; + (make-local-variable 'mew-summary-form-mark-delete) + (setq mew-summary-form-mark-delete nil) + (make-local-variable 'mew-summary-form-mark-spam) + (setq mew-summary-form-mark-spam nil) + (when (mew-summary-exclusive-p) + (message "Creating selection by message-id...") + (mew-redraw) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (mew-piolet mew-cs-text-for-read mew-cs-text-for-write + (call-process mew-prog-smew nil t nil myid db mydir) + (goto-char (point-min)) + (setq start (point)) + (while (re-search-forward regex nil t) + (setq rttl (1+ rttl)) + (setq crnt (match-string 1)) + (delete-region start (match-beginning 2)) + (when (not (string= crnt prev)) + (beginning-of-line) + (insert "CD:" mew-folder-local crnt "\n")) + (setq prev crnt) + (forward-line) + (setq start (point))) + (delete-region start (point-max)) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (write-region (point-min) (point-max) file nil 'no-msg)))) + (setq dfunc `(lambda () (mew-delete-file ,file))) + (setq opts (list "-i" file)) + (mew-local-retrieve 'vir opts dfunc nil nil rttl)))))) + +(defun mew-summary-get-subject () + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (cache (mew-cache-hit fld msg)) + subj) + (if (and cache (get-buffer cache)) + (with-current-buffer cache + (setq subj (mew-header-get-value mew-subj:))) + (with-temp-buffer + (mew-insert-message + fld msg mew-cs-text-for-read mew-header-reasonable-size) + (mew-refile-decode-subject) + (setq subj (mew-header-get-value mew-subj:)))) + subj)) + +(defun mew-summary-make-id-index-folder () + "Make ID database for this folder." + (interactive) + (mew-summary-only + (cond + ((not (file-exists-p (expand-file-name mew-id-db-file mew-mail-path))) + (message (mew-substitute-for-summary "Type '\\[mew-summary-make-id-index-all]' to create ID database"))) + ((not (mew-which-exec mew-prog-cmew)) + (message "%s not found" mew-prog-cmew)) + (t + (let* ((dbfile (expand-file-name mew-id-db-file mew-mail-path)) + (path (expand-file-name mew-mail-path)) + (regex mew-id-db-ignore-regex) + (target (mew-folder-string + (mew-path-to-folder + (mew-expand-folder (mew-summary-folder-name 'ext))))) + (options (list dbfile path regex target)) + (buf (generate-new-buffer (concat mew-buffer-prefix "cmew"))) + pro) + (message "Updating ID database...") + (setq pro (apply 'start-process "cmew" buf mew-prog-cmew options)) + (set-process-filter pro 'mew-summary-make-id-index-filter) + (set-process-sentinel pro 'mew-summary-make-id-index-sentinel)))))) + +(defun mew-summary-make-id-index-all (&optional full-update) + "Make ID database for all folders. +If called with '\\[universal-argument]', the database is created +from scratch." + (interactive "P") + (if (not (mew-which-exec mew-prog-cmew)) + (message "%s not found" mew-prog-cmew) + (let* ((dbfile (expand-file-name mew-id-db-file mew-mail-path)) + (path (expand-file-name mew-mail-path)) + (options (list dbfile path mew-id-db-ignore-regex)) + (buf (generate-new-buffer (concat mew-buffer-prefix "cmew"))) + pro) + (if full-update (setq options (cons "-f" options))) + (message "Updating ID database...") + (setq pro (apply 'start-process "cmew" buf mew-prog-cmew options)) + (set-process-filter pro 'mew-summary-make-id-index-filter) + (set-process-sentinel pro 'mew-summary-make-id-index-sentinel)))) + +(defun mew-summary-make-id-index-filter (process string) + (save-excursion + (mew-filter + (goto-char (point-max)) + (insert string)))) + +(defun mew-summary-make-id-index-sentinel (process event) + (let ((buf (process-buffer process))) + (with-current-buffer buf + (goto-char (point-max)) + (forward-line -1) + (let ((str (mew-buffer-substring (line-beginning-position) + (line-end-position)))) + (message "Updating ID database...done (%s)" str))) + (mew-remove-buffer buf))) + +(provide 'mew-search) + +;;; Copyright Notice: + +;; Copyright (C) 2005-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-search.el ends here diff --git a/elpa/mew-20150813.2354/mew-smime.el b/elpa/mew-20150813.2354/mew-smime.el new file mode 100644 index 00000000..ba5760bb --- /dev/null +++ b/elpa/mew-20150813.2354/mew-smime.el @@ -0,0 +1,501 @@ +;;; mew-smime.el --- S/MIME for Mew + +;; Author: Kazu Yamamoto +;; Created: Nov 12, 2004 + +;;; Code: + +;; for gpgsm only + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; S/MIME program +;;; + +(defvar mew-prog-smime "gpgsm") +(defvar mew-smime-ver nil) + +(defvar mew-prog-smime-options '("--include-certs" "3" "--status-fd" "1")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; S/MIME check +;;; + +(defun mew-smime-setup () + (if (mew-which-exec mew-prog-smime) + (setq mew-smime-ver t))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; S/MIME signing +;;; + +(defvar mew-smime-type "smime-type") +(defvar mew-smime-file-name "smime") +(defvar mew-smime-signature-suffix ".p7s") ;; application/pkcs7-signature +(defvar mew-smime-mime-suffix ".p7m") ;; application/pkcs7-mime + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Password +;;; + +(defun mew-smime-passtag () "GPGSM") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Micalg +;;; + +(defvar mew-smime-hash-alist + '(("1" . "md5") + ("2" . "sha1") + ("3" . "ripemd160") + ("5" . "md2") + ("6" . "tiger192") + ("7" . "haval-5-160") + ("8" . "sha256") + ("9" . "sha384") + ("10" . "sha512"))) + +(defun mew-smime-get-micalg () + (with-temp-buffer + (insert mew-smime-string) + (goto-char (point-min)) + (if (re-search-forward "SIG_CREATED [A-Z] [0-9]+ \\([0-9]+\\)" nil t) + (cdr (assoc (mew-match-string 1) mew-smime-hash-alist)) + "sha1"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Internal variables +;;; + +(defvar mew-smime-running nil) +(defvar mew-smime-string nil) +(defvar mew-smime-failure nil) + +(defvar mew-smime-decrypt-msg nil) +(defvar mew-smime-sign-msg nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defvar mew-smime-prompt-enter-pass "Enter S/MIME pass phrase: ") + +(defun mew-smime-passphrase () + (let ((prompt mew-smime-prompt-enter-pass) + (tag (mew-smime-passtag))) + (mew-input-passwd prompt tag))) + +(defvar mew-smime-msg-enter-pass "Enter passphrase:") +(defvar mew-smime-msg-bad-pass ": Bad") + +(defvar mew-smime-result-sec-succ "S/MIME decrypted") +(defvar mew-smime-result-pass "Pass phrase is wrong") + +(defun mew-smime-debug (label string) + (when (mew-debug 'smime) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +(defun mew-smime-process-filter (process string) + (save-excursion + ;; sign or decrypt + (mew-smime-debug "S/MIME filter" string) + (setq mew-smime-string (concat mew-smime-string string)) + (cond + ;; pass phrase for sign or decrypt + ((string-match mew-smime-msg-enter-pass string) + (process-send-string process (format "%s\n" (mew-smime-passphrase)))) + + ;; pass phrases were wrong three times + ((string-match mew-smime-msg-bad-pass string) + (setq mew-smime-failure t) ;; password failure + (mew-passwd-set-passwd (mew-smime-passtag) nil)) ;; cancel anyway + + ((string-match "INV_RECP \\([0-9]*\\) \\([^ \n]*\\)" string) + (setq mew-smime-failure (cdr (assoc (mew-match-string 1 string) mew-smime-inv-recp-alist))) + (setq mew-smime-failure (concat mew-smime-failure " for " (mew-match-string 2 string))))))) + +(defun mew-smime-process-sentinel (process event) + (save-excursion + (let ((decrypted mew-smime-result-sec-succ) + (msg "")) + (if (not mew-smime-failure) + (cond + ((eq mew-smime-running 'decrypting) + (setq mew-smime-decrypt-msg decrypted)) + ((eq mew-smime-running 'signing) + (setq mew-smime-sign-msg nil))) + (cond + ;; sign or decrypt + ((eq mew-smime-failure t) + (setq msg mew-smime-result-pass)) + ((stringp mew-smime-failure) + (setq msg mew-smime-failure))) + (cond + ((eq mew-smime-running 'decrypting) + (setq mew-smime-decrypt-msg msg)) + ((eq mew-smime-running 'signing) + (setq mew-smime-sign-msg msg)))) + (setq mew-smime-running nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Checking +;;; + +(defun mew-smime-verify-check () + (let (addr warning result trust ret) + (goto-char (point-min)) + (if (re-search-forward "EMail=\\(.*\\)" nil t) + (setq addr (mew-match-string 1))) + (goto-char (point-min)) + (cond + ((search-forward "GOODSIG" nil t) + (setq result "Good S/MIME sign")) + ((search-forward "EXPSIG" nil t) + (setq result "Good S/MIME sign") + (setq warning "signature has expired")) + ((search-forward "EXPKEYSIG" nil t) + (setq result "Good S/MIME sign") + (setq warning "certificate has expired")) + ((search-forward "REVKEYSIG" nil t) + (setq result "Good S/MIME sign") + (setq warning "certificate has been revoked")) + ((search-forward "BADSIG" nil t) + (setq result "BAD S/MIME sign")) + ((search-forward "ERRORSIG" nil t) + (setq result "BAD S/MIME sign")) ;; xxx + (t + (setq result "BAD S/MIME sign"))) + (goto-char (point-min)) + ;; xxx error code check for TRUST_UNDEFINED/NEVER? + (if (re-search-forward "TRUST_\\([A-Z]*\\)" nil t) + (setq trust (mew-match-string 1))) + (setq ret result) + (if addr (setq ret (concat ret " <" addr ">"))) + (if trust (setq ret (concat ret " " trust))) + (if warning (setq ret (concat ret " -" warning))) + ret)) + +(defvar mew-smime-inv-recp-alist + '(( "0" . "No specific reason given") + ( "1" . "Not Found") + ( "2" . "Ambigious specification") + ( "3" . "Wrong key usage") + ( "4" . "Key revoked") + ( "5" . "Key expired") + ( "6" . "No CRL known") + ( "7" . "CRL too old") + ( "8" . "Policy mismatch") + ( "9" . "Not a secret key") + ("10" . "Key not trusted") + ("11" . "Missing certifciate"))) + +(defun mew-smime-encrypt-check () + (let (ret) ;; this should be nil + (goto-char (point-min)) + (when (re-search-forward "INV_RECP \\([0-9]*\\) \\([^ \n]*\\)" nil t) + (setq ret (cdr (assoc (mew-match-string 1) mew-smime-inv-recp-alist))) + (setq ret (concat ret " for " (mew-match-string 2)))) + ret)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; S/MIME short cut +;;; + +(defun mew-smime-sign-message (&optional arg) + "Sign the entire draft with S/MIME. Input your passphrase." + (interactive "P") + (mew-smime-encode-message 'smime-signature arg)) + +(defun mew-smime-encrypt-message () + "Encrypt the entire draft with S/MIME." + (interactive) + (mew-smime-encode-message 'smime-encryption)) + +(defun mew-smime-sign-encrypt-message (&optional arg) + "Sign then encrypt the entire draft with S/MIME. Input your passphrase." + (interactive "P") + (mew-smime-encode-message 'smime-signature-encryption)) + +(defun mew-smime-encrypt-sign-message (&optional arg) + "Encrypt then sign the entire draft with S/MIME. Input your passphrase." + (interactive "P") + (mew-smime-encode-message 'smime-encryption-signature)) + +(defun mew-smime-encode-message (type &optional ask-signer) + (if (null mew-smime-ver) + (message "%s does not exist" mew-prog-smime) + (if (and ask-signer (string-match "signature" (symbol-name type))) + (mew-draft-make-message type (car (mew-input-address "Who's key?: "))) + (mew-draft-make-message type)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Encoding +;;; + +(defun mew-encode-smime (type cte decrypters) + (let ((file1 (mew-save-transfer-form (point-min) (point-max) nil cte)) + file2 errmsg file2-errmsg) + (cond + ((string= type mew-ct-smm-sig) + (setq file2-errmsg (mew-smime-sign file1))) + ((string= type mew-ct-smm-enc) + (setq file2-errmsg (mew-smime-encrypt file1 decrypters)))) + (mew-set '(file2 errmsg) file2-errmsg) + (if errmsg + (progn + (mew-delete-file file1) + (mew-delete-file file2) + (mew-tinfo-set-privacy-err t) + (mew-tinfo-set-privacy-type nil) + (mew-draft-mode-name) + (mew-encode-error errmsg)) + (mew-encode-singlepart + (mew-encode-syntax-single file2 + (list mew-ct-smm + (list mew-smime-type type) + (list "name" (concat mew-smime-file-name mew-smime-mime-suffix))) + mew-b64))) + (mew-delete-file file1) + (mew-delete-file file2))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Signature +;;; + +(defun mew-smime-sign (file1) + (setq mew-smime-running 'signing) + (setq mew-smime-string nil) + (setq mew-smime-sign-msg nil) + (setq mew-smime-failure nil) + (let* ((process-connection-type mew-connection-type2) + (file2 (mew-make-temp-name)) + (prog mew-prog-smime) + (opts `("--sign" ,@mew-prog-smime-options + "--local-user" ,mew-inherit-encode-smime-signer + "--output" ,file2 ,file1)) + process) + (message "S/MIME signing...") + (setq process (apply 'mew-start-process-lang "GPGSM sign" nil prog opts)) + (mew-set-process-cs process mew-cs-autoconv mew-cs-dummy) + (set-process-filter process 'mew-smime-process-filter) + (set-process-sentinel process 'mew-smime-process-sentinel) + (mew-rendezvous mew-smime-running) + (unless (file-exists-p file2) ;; for unpredictable error + (mew-passwd-set-passwd (mew-smime-passtag) nil)) + (message "S/MIME signing...done") + (list file2 mew-smime-sign-msg))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Encryption +;;; + +(defvar mew-smime-cipher "AES") + +(defun mew-smime-encrypt (file1 decrypters) + (let* ((process-connection-type mew-connection-type2) + (file2 (mew-make-temp-name)) + (decs (mew-gpg-roption decrypters "--recipient")) + (prog mew-prog-smime) + (opts `("--encrypt" ,@mew-prog-smime-options + ,@decs + "--cipher-algo" ,mew-smime-cipher + "--output" ,file2 ,file1)) + check) + (message "S/MIME encrypting...") + (with-temp-buffer + (apply 'mew-call-process-lang prog nil t nil opts) + (setq check (mew-smime-encrypt-check))) + (message "S/MIME encrypting...done") + (list file2 check))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Decoding +;;; + +(defun mew-decode-smime (syntax cnt) + (let* ((ctl (mew-syntax-get-ct syntax)) + (type (mew-syntax-get-param ctl mew-smime-type)) + file1 file2 syntax2 result privacy) + ;; xxx smime-type is optional, sigh + (if (null type) (setq type mew-ct-smm-enc)) + (mew-syntax-set-ct syntax mew-type-apo) + (setq file1 (mew-save-decode-form syntax)) + (setq file2 (mew-make-temp-name)) + (delete-region (point-min) (point-max)) + (cond + ((mew-case-equal type mew-ct-smm-sig) + (setq result (mew-smime-verify file1 file2))) + ((mew-case-equal type mew-ct-smm-enc) + (setq result (mew-smime-decrypt file1 file2))) + (t + (setq syntax2 syntax) + (mew-syntax-set-ct syntax mew-type-apo))) + (if (and (file-exists-p file2) + (> (mew-file-get-size file2) 0)) ;; shell creates file2 anyway + (mew-flet + (mew-insert-file-contents file2) + (put-text-property (point-min) (point-max) 'mew-noncontents nil) + (mew-decode-crlf-magic)) + (insert "\n") ;; CT: text/plain; charset=us-ascii + (insert (format "%s could not be decrypted.\n" mew-ct-smm)) + (mew-xinfo-set-not-decrypted t)) + ;; Throw away garbage + (mew-delete-file file1) + (mew-delete-file file2) + (goto-char (point-min)) + (setq syntax2 (mew-decode-singlepart cnt nil nil)) + (setq privacy (mew-syntax-get-privacy syntax2)) + (if privacy (setq result (concat result "\n\t"))) + (mew-syntax-set-privacy + syntax2 (cons (mew-make-privacy-dinfo :ct mew-ct-smm :proto type :result result) privacy)) + syntax2)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Verification +;;; + +(defun mew-smime-verify (file1 file2) + (let ((prog mew-prog-smime) + (opts `("--verify" ,@mew-prog-smime-options + "--output" ,file2 ,file1)) + result) + (message "S/MIME verifying...") + (with-temp-buffer + (apply 'mew-call-process-lang prog nil t nil opts) + (setq result (mew-smime-verify-check))) + (message "S/MIME verifying...done") + result)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Decription +;;; + +(defun mew-smime-decrypt (file1 file2) + (setq mew-smime-running 'decrypting) + (setq mew-smime-string nil) + (setq mew-smime-decrypt-msg nil) + (setq mew-smime-failure nil) + (let ((process-connection-type mew-connection-type2) + (prog mew-prog-smime) + (opts `("--decrypt" + "--output" ,file2 ,file1)) + process) + (message "S/MIME decrypting...") + (setq process (apply 'mew-start-process-lang "GPGSM decrypt" nil prog opts)) + (mew-set-process-cs process mew-cs-autoconv mew-cs-dummy) + (set-process-filter process 'mew-smime-process-filter) + (set-process-sentinel process 'mew-smime-process-sentinel) + (mew-rendezvous mew-smime-running) + (unless (file-exists-p file2) ;; for unpredictable error + (mew-passwd-set-passwd (mew-smime-passtag) nil)) + (message "S/MIME decrypting...done") + mew-smime-decrypt-msg)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Multipart/Signed +;;; + +(defun mew-smime-detach-verify (file1 file2) + (let ((prog mew-prog-smime) + (opts `("--verify" ,@mew-prog-smime-options + ,file2 ,file1)) + ret) + (message "S/MIME verifying...") + (with-temp-buffer + (apply 'mew-call-process-lang prog nil t nil opts) + (setq ret (mew-smime-verify-check))) + (message "S/MIME verifying...done") + ret)) + +(defun mew-smime-detach-sign (file1) + (setq mew-smime-running 'signing) + (setq mew-smime-string nil) + (setq mew-smime-sign-msg nil) + (setq mew-smime-failure nil) + (let* ((process-connection-type mew-connection-type2) + (file2 (concat (mew-make-temp-name mew-smime-file-name) + mew-smime-signature-suffix)) + (prog mew-prog-smime) + (opts `("--detach-sign" ,@mew-prog-smime-options + "--local-user" ,mew-inherit-encode-smime-signer + "--output" ,file2 ,file1)) + process) + (message "S/MIME signing...") + (setq process (apply 'mew-start-process-lang "GPGSM sign" nil prog opts)) + (mew-set-process-cs process mew-cs-autoconv mew-cs-dummy) + (set-process-filter process 'mew-smime-process-filter) + (set-process-sentinel process 'mew-smime-process-sentinel) + (mew-rendezvous mew-smime-running) + (unless (file-exists-p file2) ;; for unpredictable error + (mew-passwd-set-passwd (mew-smime-passtag) nil)) + (message "S/MIME signing...done") + (list file2 mew-b64 (mew-smime-get-micalg) mew-smime-sign-msg))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; GPG +;;; + +(defun mew-gpg-roption (decrypters roption) + (if (and mew-encrypt-to-myself + (not (member mew-inherit-encode-smime-signer decrypters))) + (setq decrypters (cons mew-inherit-encode-smime-signer decrypters))) + (setq decrypters + (mapcar (lambda (x) + (if (string-match "^[^<].*@" x) (concat "<" x ">") x)) + decrypters)) + (let (decs) + (dolist (decrypter decrypters) + (setq decs (cons decrypter (cons roption decs)))) + (nreverse decs))) + +(provide 'mew-smime) + +;;; Copyright Notice: + +;; Copyright (C) 2004-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-smime.el ends here diff --git a/elpa/mew-20150813.2354/mew-smtp.el b/elpa/mew-20150813.2354/mew-smtp.el new file mode 100644 index 00000000..58a05e3b --- /dev/null +++ b/elpa/mew-20150813.2354/mew-smtp.el @@ -0,0 +1,782 @@ +;;; mew-smtp.el + +;; Author: Kazu Yamamoto +;; Created: Dec 3, 1999 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SMTP info +;;; + +(defvar mew-smtp-info-list + '(;; parameters to be saved + "raw-header" "recipients" "orig-recipients" + "bcc" "fcc" "msgid" "logtime" + "case" ;; save for re-edit + ;; parameters used internally + "server" "port" "ssh-server" + "user" "auth-user" "auth-list" + "helo-domain" + "status" "process" "ssh-process" "ssl-process" + "qfld" "messages" + ;; parameters used internally and should be initialized + "string" "error" "auth-selected" "timer" "cont" "from" "sender" + "done" "imapp" "capa" "fallback")) + +(mew-info-defun "mew-smtp-" mew-smtp-info-list) + +(defvar mew-smtp-info-list-save-length 8) +(defvar mew-smtp-info-list-clean-length 21) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; FSM +;;; + +(defvar mew-smtp-fsm + '(("greeting" ("220" . "ehlo")) + ("ehlo" ("250" . "post-ehlo") (t . "helo")) + ;; + ("auth" ("250" . "next")) + ("auth-cram-md5" ("334" . "pwd-cram-md5") (t . "wpwd")) + ("pwd-cram-md5" ("235" . "next") (t . "wpwd")) + ("auth-login" ("334" . "user-login") (t . "wpwd")) + ("user-login" ("334" . "pwd-login") (t . "wpwd")) + ("pwd-login" ("235" . "next") (t . "wpwd")) + ("auth-plain" ("235" . "next") (t . "wpwd")) +;; See blow +;; ("auth-plain" ("334" . "pwd-plain") (t . "wpwd")) +;; ("pwd-plain" ("235" . "next") (t . "wpwd")) + ;; + ("helo" ("250" . "next")) + ("mail-from" ("250" . "rcpt-to")) + ("rcpt-to" ("250" . "data")) + ("data" ("354" . "content")) + ("content" ("250" . "done")) + ("quit" (t . "noop")))) + +(defun mew-smtp-fsm-by-status (status) + (assoc status mew-smtp-fsm)) + +(defun mew-smtp-fsm-next (status code) + (cdr (mew-assoc-match2 code (cdr (mew-smtp-fsm-by-status status)) 0))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filters +;;; + +(defun mew-smtp-command-helo (pro pnm) + (let ((helo-domain (mew-smtp-get-helo-domain pnm))) + (mew-smtp-process-send-string pro "HELO %s" helo-domain))) + +(defun mew-smtp-command-ehlo (pro pnm) + (let ((helo-domain (mew-smtp-get-helo-domain pnm))) + (mew-smtp-process-send-string pro "EHLO %s" helo-domain))) + +(defun mew-smtp-command-post-ehlo (pro pnm) + (let ((str (mew-smtp-get-string pnm)) (start 0) capa) + (catch 'loop + (while (string-match "^250\\([- ]?\\)\\(.*\\)$" str start) + (setq capa (cons (mew-split (match-string 2 str) 32) capa)) + (if (string= (match-string 1 str) " ") + (throw 'loop nil)) + (setq start (match-end 0)))) + (mew-smtp-set-capa pnm (nreverse capa)) + (mew-smtp-set-status pnm "auth") + (mew-smtp-command-auth pro pnm))) + +(defun mew-smtp-command-auth (pro pnm) + (let* ((case (mew-smtp-get-case pnm)) + (use-smtp-auth (mew-use-smtp-auth case)) + (capa (mew-smtp-get-capa pnm)) + (auths (assoc "AUTH" capa)) + (auth-list (mew-smtp-get-auth-list pnm)) + auth func) + (cond + ((and use-smtp-auth auths) + (if (and (setq auth (mew-auth-select2 auths auth-list)) + (setq func (mew-smtp-auth-get-func auth)) + (fboundp func)) + (progn + (mew-smtp-set-auth-selected pnm auth) + (funcall func pro pnm)) + (mew-smtp-debug "" "No preferred SMTP AUTH.\n") + (mew-smtp-command-wpwd pro pnm))) + (t + (mew-smtp-set-status pnm "next") + (mew-smtp-command-next pro pnm))))) + +(defun mew-smtp-command-wpwd (pro pnm) + (let ((auth (mew-smtp-get-auth-selected pnm))) + (mew-passwd-set-passwd (mew-smtp-passtag pnm) nil) + (if auth + (mew-smtp-set-error pnm (format "SMTP %s password is wrong!" auth)) + (mew-smtp-set-error pnm "No SMTP AUTH available!")) + (mew-smtp-command-quit2 pro pnm))) + +(defun mew-smtp-command-next (pro pnm) + (let ((msgs (mew-smtp-get-messages pnm)) + (qfld (mew-smtp-get-qfld pnm)) + (case (mew-smtp-get-case pnm)) + msg) + (if msgs + (progn + (setq msg (car msgs)) + (setq msgs (cdr msgs)) + (mew-queue-insert-file pnm mew-smtp-info-list-save-length qfld msg) + (mew-set-buffer-multibyte nil) + (mew-info-clean-up pnm mew-smtp-info-list-clean-length) + (mew-smtp-set-case pnm case) ;; override + (mew-smtp-set-messages pnm msgs) + (set-process-buffer pro (current-buffer)) + (mew-smtp-set-status pnm "mail-from") + (mew-smtp-command-mail-from pro pnm)) + (mew-smtp-set-status pnm "quit") + (mew-smtp-command-quit pro pnm)))) + +(defun mew-smtp-command-mail-from (pro pnm) + (widen) + (clear-visited-file-modtime) + ;; + (let* ((case (mew-smtp-get-case pnm)) + (resentp (mew-header-existp mew-resent-from:)) + (sender: (if resentp mew-resent-sender: mew-sender:)) + (from: (if resentp mew-resent-from: mew-from:)) + (from (mew-header-get-value from:)) + (froms (mew-addrstr-parse-address-list from)) + (nfrom (length froms)) + (mail-from (mew-smtp-mail-from case))) + (mew-smtp-set-from pnm from) ;; for Bcc: + (unless mail-from + ;; Which address is suitable for MAIL FROM if multiple? + (setq mail-from (car froms))) + (unless (mew-header-existp sender:) + (if (= nfrom 1) + (if (and mew-use-sender (not (string= mail-from (car froms)))) + (mew-smtp-set-sender pnm (cons sender: mail-from))) + (mew-smtp-set-sender pnm (cons sender: mail-from)))) + ;; + (mew-smtp-process-send-string pro "MAIL FROM:<%s>" mail-from))) + +(defun mew-smtp-command-rcpt-to (pro pnm) + (let* ((recipients (mew-smtp-get-recipients pnm)) + (recipient (car recipients))) + (setq recipients (cdr recipients)) + (mew-smtp-set-recipients pnm recipients) + (if recipients (mew-smtp-set-status pnm "mail-from")) + (mew-smtp-process-send-string pro "RCPT TO:<%s>" recipient))) + +(defun mew-smtp-command-data (pro pnm) + (goto-char (point-max)) + (unless (bolp) (insert "\n")) + (mew-dot-insert) + (mew-eol-fix-for-write) + (set-buffer-modified-p nil) + (mew-smtp-set-cont pnm (point-min)) + (mew-smtp-set-timer pnm nil) + (mew-smtp-process-send-string pro "DATA")) + +(defun mew-smtp-command-content (pro pnm) + (save-excursion + (let ((cont (mew-smtp-get-cont pnm)) + (sender (mew-smtp-get-sender pnm)) + (inc 1000) (i 0) (N 10)) + (set-buffer (process-buffer pro)) + ;; Sender: + (when sender + (mew-smtp-process-send-string pro "%s %s" (car sender) (cdr sender)) + (mew-smtp-set-sender pnm nil)) + ;; + (while (and (< cont (point-max)) (not (input-pending-p)) (< i N)) + (let ((next (min (point-max) (+ cont inc)))) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-region pro cont next)) + (setq cont next) + (setq i (1+ i)))) + (mew-smtp-set-cont pnm cont) + (if (< cont (point-max)) + (let ((timer + (if (input-pending-p) + (run-with-idle-timer + 0.01 nil 'mew-smtp-command-content pro pnm) + (run-at-time 0.05 nil 'mew-smtp-command-content pro pnm)))) + (mew-smtp-set-timer pnm timer)) + (mew-smtp-set-cont pnm nil) + (mew-smtp-set-timer pnm nil) + (mew-smtp-process-send-string pro "."))))) + +(defun mew-smtp-command-done (pro pnm) + (let ((fcc (mew-smtp-get-fcc pnm)) + (case (mew-smtp-get-case pnm)) + (back (mew-queue-backup (buffer-file-name) mew-queue-info-suffix)) + imapp) + ;; mew-folder-new-message may be slow if the folder contains + ;; a lot of messages. So, let's Fcc in background. + (setq imapp (mew-net-fcc-message case fcc back)) + (mew-smtp-set-imapp pnm imapp) + (mew-smtp-log pnm) + (if (mew-smtp-get-bcc pnm) + (mew-smtp-bcc pro pnm back) + (mew-smtp-set-status pro "next") + (mew-smtp-command-next pro pnm)))) + +(defun mew-smtp-command-quit (pro pnm) + (mew-smtp-set-done pnm t) + (mew-smtp-process-send-string pro "QUIT")) + +(defun mew-smtp-command-quit2 (pro pnm) + ;; error is set + (mew-smtp-set-done pnm t) + (when (and (processp pro) (eq (process-status pro) 'open)) + (mew-smtp-set-status pnm "quit") + (mew-smtp-process-send-string pro "QUIT"))) + +(defun mew-smtp-command-noop (pro pnm) + ()) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SMTP AUTH (RFC 2554) +;;; + +(defvar mew-smtp-auth-alist + '(("CRAM-MD5" mew-smtp-command-auth-cram-md5) ;; RFC 2195 + ("PLAIN" mew-smtp-command-auth-plain) ;; RFC 2595 + ("LOGIN" mew-smtp-command-auth-login))) ;; No spec + +(defun mew-smtp-auth-get-func (auth) + (nth 1 (mew-assoc-case-equal auth mew-smtp-auth-alist 0))) + +;; CRAM MD5 + +(defun mew-smtp-command-auth-cram-md5 (pro pnm) + (mew-smtp-process-send-string pro "AUTH CRAM-MD5") + (mew-smtp-set-status pnm "auth-cram-md5")) + +(defun mew-smtp-command-pwd-cram-md5 (pro pnm) + (let* ((str (mew-smtp-get-string pnm)) + (user (mew-smtp-get-auth-user pnm)) + (prompt (format "SMTP CRAM-MD5 password (%s): " user)) + challenge passwd cram-md5) + (if (string-match " \\([a-zA-Z0-9+/]+=*\\)" str) ;; xxx + (setq challenge (match-string 1 str))) + (setq passwd (mew-smtp-input-passwd prompt pnm)) + (setq cram-md5 (mew-cram-md5 user passwd challenge)) + (mew-smtp-process-send-string pro cram-md5))) + +;; LOGIN + +(defun mew-smtp-command-auth-login (pro pnm) + (mew-smtp-process-send-string pro "AUTH LOGIN") + (mew-smtp-set-status pnm "auth-login")) + +(defun mew-smtp-command-user-login (pro pnm) + (let* ((user (mew-smtp-get-auth-user pnm)) + (euser (mew-base64-encode-string user))) + (mew-smtp-process-send-string pro "%s" euser))) + +(defun mew-smtp-command-pwd-login (pro pnm) + (let* ((user (mew-smtp-get-auth-user pnm)) + (prompt (format "SMTP LOGIN password (%s): " user)) + (passwd (mew-smtp-input-passwd prompt pnm)) + (epasswd (mew-base64-encode-string passwd))) + (mew-smtp-process-send-string pro epasswd))) + +;; There are two variations for SMTP AUTH PLAIN. +;; 1) AUTH PLAIN then id+password +;; 2) AUTH PLAIN id+password +;; +;; 1) is popular however a server of an ISP supports 2) only, sigh. + +(defun mew-smtp-command-auth-plain (pro pnm) + (let* ((case (mew-smtp-get-case pnm)) + (user (mew-smtp-get-auth-user pnm)) + (authorize-id (mew-smtp-auth-plain-authorize-id case)) + (prompt (format "SMTP PLAIN password (%s): " user)) + (passwd (mew-smtp-input-passwd prompt pnm)) + (plain (mew-base64-encode-string + (if authorize-id + (format "%s\0%s\0%s" user user passwd) + (format "\0%s\0%s" user passwd))))) + (mew-smtp-process-send-string pro "AUTH PLAIN %s" plain) + (mew-smtp-set-status pnm "auth-plain"))) + +;; (defun mew-smtp-command-auth-plain (pro pnm) +;; (mew-smtp-process-send-string pro "AUTH PLAIN") +;; (mew-smtp-set-status pnm "auth-plain")) + +;; (defun mew-smtp-command-pwd-plain (pro pnm) +;; (let* ((case (mew-smtp-get-case pnm)) +;; (user (mew-smtp-get-auth-user pnm)) +;; (authorize-id (mew-smtp-auth-plain-authorize-id case)) +;; (prompt (format "SMTP PLAIN password (%s): " user)) +;; (passwd (mew-smtp-input-passwd prompt pnm)) +;; (plain (mew-base64-encode-string +;; (if authorize-id +;; (format "%s\0%s\0%s" user user passwd) +;; (format "\0%s\0%s" user passwd))))) +;; (mew-smtp-process-send-string pro "%s" plain))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub functions +;;; + +(defconst mew-smtp-info-prefix "mew-smtp-info-") + +(defun mew-smtp-info-name (case &optional fallbacked) + (let ((server (mew-smtp-server case)) + (port (mew-*-to-string (mew-smtp-port case))) + (user (mew-smtp-user case)) + (sshsrv (mew-smtp-ssh-server case)) + (name mew-smtp-info-prefix)) + (if user + (setq name (concat name user "@" server)) + (setq name (concat name server))) + (when (and (not fallbacked) + mew-use-submission ;; xxx to be deleted + (fboundp 'make-network-process) + (string= port "smtp")) + (setq port "submission")) + (unless (mew-port-equal port mew-smtp-port) + (setq name (concat name ":" port))) + (if sshsrv + (concat name "%" sshsrv) + name))) + +(defun mew-smtp-process-send-string (pro &rest args) + (let ((str (apply 'format args))) + (mew-smtp-debug "=SEND=" str) + (if (and (processp pro) (eq (process-status pro) 'open)) + (process-send-string pro (concat str mew-cs-eol)) + (message "SMTP time out")))) + +(defun mew-smtp-passtag (pnm) + (concat (mew-smtp-get-auth-user pnm) + "@" (mew-smtp-get-server pnm) + ":" (mew-smtp-get-port pnm))) + +(defun mew-smtp-input-passwd (prompt pnm) + (let ((tag (mew-smtp-passtag pnm)) + (pro (mew-smtp-get-process pnm)) + pass) + (setq pass (mew-input-passwd prompt tag)) + (unless (and (processp pro) (eq (process-status pro) 'open)) + (mew-passwd-set-passwd tag nil)) + pass)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Opening SMTP +;;; + +(defvar mew-use-submission nil) + +(defvar mew-smtp-submission-timeout 10) +(defun mew-smtp-submission-timeout (pro) + (when (and (processp pro) (eq (process-status pro) 'connect)) + (mew-smtp-sentinel pro "time out - failed\n"))) + +(defvar mew-smtp-submission-family 'ipv4) + +(if (fboundp 'make-network-process) + (defun mew-open-network-stream (name buf server port) + (let (family nowait pro) + (when mew-inherit-submission + (setq family mew-smtp-submission-family) + (setq nowait t)) + (setq pro (make-network-process :name name :buffer buf + :host server :service port + :family family :nowait nowait)) + (if nowait + (run-at-time mew-smtp-submission-timeout nil 'mew-smtp-submission-timeout pro)) + pro)) + (defalias 'mew-open-network-stream 'open-network-stream)) + +(defun mew-smtp-open (pnm server port) + (let ((sprt (mew-*-to-port port)) + pro tm) + ;; xxx some OSes do not define "submission", sigh. + (when (and (stringp sprt) (string= sprt "submission")) + (setq sprt (mew-serv-to-port sprt))) + (condition-case emsg + (progn + (setq tm (run-at-time mew-smtp-timeout-time nil 'mew-smtp-timeout)) + (message "Connecting to the SMTP server...") + (setq pro (mew-open-network-stream pnm nil server sprt)) + (mew-process-silent-exit pro) + (mew-set-process-cs pro mew-cs-text-for-net mew-cs-text-for-net) + (message "Connecting to the SMTP server...done")) + (quit + (setq pro nil) + (message "Cannot connect to the SMTP server")) + (error + (setq pro nil) + (message "%s, %s" (nth 1 emsg) (nth 2 emsg)))) + (if tm (cancel-timer tm)) + pro)) + +(defun mew-smtp-timeout () + (signal 'quit nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Launcher +;;; + +(defun mew-smtp-send-message (case qfld msgs &optional fallbacked) + (let ((server (mew-smtp-server case)) + (user (mew-smtp-user-only case)) + (port (mew-*-to-string (mew-smtp-port case))) + (pnm (mew-smtp-info-name case fallbacked)) + (sshsrv (mew-smtp-ssh-server case)) + (sslp (mew-smtp-ssl case)) + (sslport (mew-smtp-ssl-port case)) + mew-inherit-submission + process sshname sshpro sslname sslpro lport tlsp tls fallback) + (when (and sslp (mew-port-equal port sslport)) + (setq tlsp t) + ;; let stunnel know that a wrapper protocol is SMTP + (setq tls mew-tls-smtp)) + ;; a fallback: "submission" -> "smtp" + ;; mew-smtp-port is "smtp" and mew-use-submission is t on Emacs 22 + (when (and (or (not sslp) tlsp) + (not fallbacked) + mew-use-submission + (fboundp 'make-network-process) ;; Emacs 22 or later + (mew-port-equal port "smtp")) + (setq port "submission") + (setq fallback t) + (unless tlsp + ;; TLS uses stunnel. So, we should not use non-blocking connect. + ;; Timeout should be carried out by stunnel. + (setq mew-inherit-submission t)) + (if (mew-port-equal sslport "smtp") (setq sslport "submission"))) + (cond + (sshsrv + (setq sshpro (mew-open-ssh-stream case server port sshsrv)) + (when sshpro + (setq sshname (process-name sshpro)) + (setq lport (mew-ssh-pnm-to-lport sshname)) + (when lport + (setq process (mew-smtp-open pnm "localhost" lport))))) + (sslp + (setq sslpro (mew-open-ssl-stream case server sslport tls)) + (when sslpro + (setq sslname (process-name sslpro)) + (setq lport (mew-ssl-pnm-to-lport sslname)) + (when lport + (setq process (mew-smtp-open pnm mew-ssl-localhost lport))))) + (t + (setq process (mew-smtp-open pnm server port)))) + (if (null process) + (cond + ((and sshsrv (null sshpro)) + (message "Cannot create to the SSH connection")) + ((and sslp (null sslpro)) + (message "Cannot create to the SSL/TLS connection")) + (t + (if (and (or (not sslp) tlsp) + (not fallbacked) + mew-use-submission + (fboundp 'make-network-process) + (mew-port-equal port "submission")) + (progn + ;; make-network-process with :nowait t sometime + ;; returns nil, why? + (mew-smtp-send-message case qfld msgs t) + (mew-info-clean-up pnm)) + (message "Cannot connect to the SMTP server")))) + (mew-info-clean-up pnm mew-smtp-info-list-clean-length) + (mew-smtp-set-case pnm case) + (mew-smtp-set-qfld pnm qfld) + (mew-smtp-set-messages pnm msgs) + (mew-smtp-set-server pnm server) + (mew-smtp-set-port pnm port) + (mew-smtp-set-process pnm process) + (mew-smtp-set-ssh-server pnm sshsrv) + (mew-smtp-set-ssh-process pnm sshpro) + (mew-smtp-set-ssl-process pnm sslpro) + (mew-smtp-set-helo-domain pnm (mew-smtp-helo-domain case)) + (mew-smtp-set-user pnm user) + (mew-smtp-set-auth-user pnm (mew-smtp-user case)) + (mew-smtp-set-auth-list pnm (mew-smtp-auth-list case)) + (mew-smtp-set-status pnm "greeting") + (mew-smtp-set-fallback pnm fallback) + ;; + (set-process-buffer process nil) + (set-process-sentinel process 'mew-smtp-sentinel) + (set-process-filter process 'mew-smtp-filter) + (message "Sending in background...")))) + +(defun mew-smtp-flush-queue (case &optional qfld) + (let (msgs) + (unless qfld (setq qfld (mew-queue-folder case))) + (if (mew-smtp-get-server (mew-smtp-info-name case)) ;; lock + (message "%s is locked" qfld) + (setq msgs (mew-folder-messages qfld)) + (when msgs + (mew-summary-folder-cache-clean qfld) + (run-hooks 'mew-smtp-flush-hook) + (message "Flushing %s..." qfld) + (mew-smtp-send-message case qfld msgs))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defun mew-smtp-debug (label string) + (when (mew-debug 'net) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +(defun mew-smtp-filter (process string) + (let* ((pnm (process-name process)) + (status (mew-smtp-get-status pnm)) + (str (concat (mew-smtp-get-string pnm) string)) + (buf (process-buffer process)) + next func code) + (save-excursion + (mew-smtp-debug (upcase status) string) + (if (and buf (get-buffer buf)) (set-buffer buf)) + ;; SMTP server's strings should be short enough. + (mew-smtp-set-string pnm str) + (cond + ((and (string-match "\n$" str) + (string-match "^\\([1-5][0-7][0-9]\\) " str)) + (setq code (match-string 1 str)) + (setq next (mew-smtp-fsm-next status code)) + (cond + (next + (mew-smtp-set-status pnm next) + (setq func (intern-soft (concat "mew-smtp-command-" next))) + (and func (funcall func process pnm)) + (mew-smtp-set-string pnm nil)) + (t + (if (string-match "^pwd-" status) + (mew-smtp-set-error pnm "SMTP password is wrong!") + (if (string-match "\n$" str) + (setq str (substring str 0 -1))) + (unless (string-match "[.!]$" str) + (setq str (concat str ".")))) + (mew-smtp-set-error pnm str) + (mew-smtp-command-quit2 process pnm)))) + (t ()))))) ;; stay + +(defun mew-smtp-sentinel (process event) + (let* ((pnm (process-name process)) + (pro (mew-smtp-get-process pnm)) + (case (mew-smtp-get-case pnm)) + (qfld (mew-smtp-get-qfld pnm)) + (msgs (mew-smtp-get-messages pnm)) + (fallback (mew-smtp-get-fallback pnm)) + (status (mew-smtp-get-status pnm))) + (save-excursion + (mew-smtp-debug "SMTP SENTINEL" event) + (cond + ((or (string-match "failed" event) + (and (string= status "greeting") + (string-match "connection broken by remote peer" event))) + (if fallback + (progn + (mew-smtp-send-message case qfld msgs fallback) + ;; A failed process stays + (when (memq (process-status pro) '(failed connect)) + (delete-process pro) + (mew-info-clean-up pnm))) + (mew-smtp-set-error pnm (substring event 0 -1)) + (mew-smtp-sentinel2 process event))) + ((string-match "open" event) + ;; OK connected + ) + (t + (mew-smtp-sentinel2 process event)))))) + +(defun mew-smtp-sentinel2 (process event) + (let* ((pnm (process-name process)) + (buf (process-buffer process)) + (qfld (mew-smtp-get-qfld pnm)) + (case (mew-smtp-get-case pnm)) + (done (mew-smtp-get-done pnm)) + (imapp (mew-smtp-get-imapp pnm)) + (error (mew-smtp-get-error pnm)) + (sshpro (mew-smtp-get-ssh-process pnm)) + (sslpro (mew-smtp-get-ssl-process pnm))) + (save-excursion + (cond + (error + (when buf + ;; A message file is not inserted at the beginning of the SMTP + ;; session. + (set-buffer buf) + (mew-smtp-queue case error pnm)) + (mew-smtp-log pnm error) + (message-box (format "%s This mail has been queued to %s" error qfld))) + (done + (message "Sending in background...done")) + (t + (if (null buf) + (message "SMTP connection is lost") + (set-buffer buf) + (mew-smtp-queue case "SMTP connection is lost" pnm)))) + (mew-info-clean-up pnm) + (if (and (processp sshpro) (not mew-ssh-keep-connection)) + (process-send-string sshpro "exit\n")) + (if (and (processp sslpro) (not mew-ssl-keep-connection)) + (delete-process sslpro)) + (run-hooks 'mew-smtp-sentinel-hook) + (if (and done imapp) (mew-imap2-fcc case)) + (when buf (mew-remove-buffer buf))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Queuing +;;; + +(defun mew-smtp-queue (case err &optional apnm) + ;; Must be in a buffer where a message is contained. + (let* ((pnm (or apnm (mew-smtp-info-name case))) + (qfld (mew-queue-folder case)) + (oname (buffer-name)) + (work (buffer-file-name)) + file-info file info nname) + (mew-local-folder-check qfld) + (setq file-info (mew-queue-enqueue work qfld)) + (mew-set '(file info) file-info) + (setq file (file-name-nondirectory file)) + (setq nname (mew-concat-folder qfld file)) + (if (mew-draft-p) + (mew-smtp-set-case pnm (mew-tinfo-get-case))) + ;; + (mew-smtp-set-recipients pnm (mew-smtp-get-orig-recipients pnm)) + (let* ((n mew-smtp-info-list-save-length) + (data (make-vector n nil))) + (dotimes (i n) + (aset data i (aref (mew-info pnm) i))) + (mew-lisp-save info data)) + ;; + (message "%s has been queued to %s (%s)" oname nname err) + (mew-touch-folder qfld) + (file-name-sans-extension file))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Bcc: +;;; + +(defun mew-smtp-bcc (pro pnm back) + (let* ((dir (file-name-directory back)) + (msg (file-name-nondirectory back)) + (case (mew-smtp-get-case pnm)) + msgid logtime) + (mew-elet + (mew-erase-buffer) + (mew-set-buffer-multibyte t) + (mew-smtp-set-recipients pnm (mew-smtp-get-bcc pnm)) + (mew-smtp-set-orig-recipients pnm (mew-smtp-get-bcc pnm)) + (mew-smtp-set-bcc pnm nil) + ;; + (mew-set '(msgid logtime) (mew-encode-id-date pnm (mew-smtp-message-id case))) ;; save-excursion + (mew-smtp-set-msgid pnm msgid) + (mew-smtp-set-logtime pnm logtime) + (goto-char (point-max)) + (mew-draft-header-insert mew-to: "Bcc-Receiver:;") + (mew-draft-header-insert mew-subj: mew-bcc-subject) + (mew-draft-header-insert mew-from: (mew-smtp-get-from pnm)) + (mew-draft-header-insert mew-organization: (mew-organization case)) + (mew-draft-header-insert-alist (mew-header-alist case)) + ;; X-Mailer: must be the last + (if (mew-use-x-mailer case) + (mew-draft-header-insert mew-x-mailer: mew-x-mailer)) + (mew-header-set "\n") + (insert mew-bcc-body) + (goto-char (mew-header-end)) + (forward-line) + (setq mew-encode-syntax (mew-encode-syntax-initial dir)) + (setq mew-encode-syntax + (mew-syntax-insert-entry + mew-encode-syntax + '(2) + (mew-encode-syntax-single msg mew-type-msg nil nil nil))) + (mew-encode-multipart mew-encode-syntax dir 0 'buffered) + (mew-encode-make-header) + (mew-encode-save-draft) + (mew-overlay-delete-buffer) + (mew-set-buffer-multibyte nil) + (mew-info-clean-up pnm mew-smtp-info-list-clean-length) + (set-process-buffer pro (current-buffer)) + (mew-smtp-set-status pnm "mail-from") + (mew-smtp-command-mail-from pro pnm)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Logging +;;; + +(defun mew-smtp-log (pnm &optional err) + (let ((logtime (mew-smtp-get-logtime pnm)) + (msgid (mew-smtp-get-msgid pnm)) + (recipients (mew-smtp-get-orig-recipients pnm)) + (server (mew-smtp-get-server pnm)) + (port (mew-smtp-get-port pnm)) + (sshsrv (mew-smtp-get-ssh-server pnm)) + (sslp (mew-smtp-get-ssl-process pnm))) + (with-temp-buffer + (and logtime (insert logtime)) + (and msgid (insert " id=" msgid)) + (and server (insert " server=" server ":" port)) + (and sshsrv (insert " sshsrv=" sshsrv)) + (and sslp (insert " SSL/TLS")) + (and recipients + (setq recipients (mapconcat 'identity recipients ","))) + (and recipients (insert " recipients=" recipients)) + (if err + (insert " status=" "(" + (substring err 0 (string-match "\n+$" err)) + ")") + (insert " status=sent")) + (insert "\n") + (write-region (point-min) (point-max) + (expand-file-name mew-smtp-log-file mew-conf-path) + 'append 'no-msg)))) + +(provide 'mew-smtp) + +;;; Copyright Notice: + +;; Copyright (C) 1999-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-smtp.el ends here diff --git a/elpa/mew-20150813.2354/mew-sort.el b/elpa/mew-20150813.2354/mew-sort.el new file mode 100644 index 00000000..3ee3a59d --- /dev/null +++ b/elpa/mew-20150813.2354/mew-sort.el @@ -0,0 +1,527 @@ +;;; mew-sort.el --- Sorting messages for Mew + +;; Author: Takashi P.KATOH +;; Kazu Yamamoto +;; Created: Feb 6, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sort variety +;;; + +(defvar mew-sort-switch + '(("text" mew-sort-key-text mew-sort-string) + ("ml" mew-sort-key-ml mew-sort-string) + ("mlnum" mew-sort-key-mlnum mew-sort-string) + ("date" mew-sort-key-date mew-sort-string) + ("num" mew-sort-key-num mew-sort-number) + ("postnum" mew-sort-key-postnum mew-sort-number))) + +(defun mew-sort-key-text (key folder msg) + (mew-subject-simplify key nil 'no-replace)) + +(defun mew-sort-key-ml (key folder msg) + (mew-subject-simplify2 key)) + +(defun mew-sort-key-mlnum (key folder msg) + (let (mlname mlnum) + (cond + ((string-match "^\\([[(][^])]+\\)[: ]+\\([0-9]+\\)[])]" key) + (setq mlname (match-string 1 key)) + (setq mlnum (match-string 2 key))) + ((string-match "^[0-9]+$" key) + (setq mlname "") + (setq mlnum (match-string 0 key))) + (t + (setq mlname "") + (setq mlnum "0"))) + (concat mlname (format "\000%010d" (string-to-number mlnum))))) + +(defun mew-sort-key-date (key folder msg) + (if (string= key "") + (let ((time (mew-file-get-time (mew-expand-msg folder msg)))) + (mew-time-ctz-to-sortkey time)) + (mew-time-rfc-to-sortkey key))) + +(defun mew-sort-key-num (key folder msg) + (string-to-number key)) + +(defun mew-sort-key-postnum (key folder msg) + (if (string-match "[0-9]+$" key) + (string-to-number (match-string 0 key)) + (string-to-number key))) + +(defun mew-sort-key (x) (cdr x)) + +(defun mew-sort-string (x y) + (or (string= (mew-sort-key x) (mew-sort-key y)) + (string< (mew-sort-key x) (mew-sort-key y)))) + +(defun mew-sort-number (x y) + (<= (mew-sort-key x) (mew-sort-key y))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; +;;; + +(defvar mew-sort-line nil) + +(defun mew-sort-index (x) (car x)) + +(defun mew-sort-insert (line msg) + (insert line) + (when msg + (save-excursion + (forward-line -1) + (mew-syntax-change-message-number msg)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Moving messages +;;; + +(defun mew-summary-sort-move-rename (src dst pos &optional lastp) + (rename-file (mew-msg-get-filename src) (mew-msg-new-filename dst)) + (mew-refile-change src dst) + (mew-summary-sort-move src dst pos lastp)) + +(defun mew-summary-sort-move-for-selection (src dst pos &optional lastp) + (mew-summary-sort-move src nil pos lastp)) + +;; If not found, returns nil. +(defun mew-summary-sort-move (src dst pos &optional lastp) + (mew-elet + (let (beg end line) + (cond + (lastp + (when pos + (goto-char pos) + (mew-sort-insert mew-sort-line dst) + nil)) + ((null pos) ;; first + (when (mew-summary-search-msg src) + (setq beg (point)) + (forward-line) + (setq end (point)) + ;; We need to keep properties in Summary mode. + ;; This must be "buffer-substring". + (setq mew-sort-line (buffer-substring beg end)) + (delete-region beg end) + beg)) + (t + (when (mew-summary-search-msg src) + (setq beg (point)) + (forward-line) + (setq end (point)) + (cond + ((< pos beg) + ;; We need to keep properties in Summary mode. + ;; This must be "buffer-substring". + (setq line (buffer-substring beg end)) + (goto-char end) + (delete-region beg end) + (save-excursion + (goto-char pos) + (mew-sort-insert line dst)) + (point)) + ((= pos beg) + ;; We need to keep properties in Summary mode. + ;; This must be "buffer-substring". + (setq line (buffer-substring beg end)) + (delete-region beg end) + (goto-char pos) + (mew-sort-insert line dst) + (point)) + (t + ;; We need to keep properties in Summary mode. + ;; This must be "buffer-substring". + (setq line (buffer-substring beg end)) + (goto-char pos) + (mew-sort-insert line dst) + (delete-region beg end) + beg)))))))) + +(defun mew-summary-sort-move-for-debug (src dst pos &optional lastp) + (mew-elet + (insert (format "move %s to %s\n" src dst)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; +;;; + +(defun mew-sort-get-range (arg) + (let (region beg end range rbeg rend) + (if arg + (progn + (setq region (mew-summary-get-region)) + (setq beg (car region)) + (setq end (cdr region)) + (if (= beg end) (error "No region"))) + (setq beg (point-min)) + (setq end (point-max))) + (save-excursion + (goto-char beg) + (setq rbeg (mew-summary-message-number)) + (goto-char end) + (forward-line -1) + (setq rend (mew-summary-message-number)) + (forward-line) + (if (and rbeg rend) + (setq range (concat rbeg "-" rend)) + (error "No region"))) + (list range beg end))) + +(defun mew-sort-ask-key (folder) + (let* ((sort-key (or (mew-alist-get-value + (assoc folder mew-sort-default-key-alist)) + mew-sort-default-key)) + key type funcs newkey) + (mew-set '(key type) (mew-input-sort-key sort-key)) + (setq funcs (assoc type mew-sort-switch)) + (setq newkey (concat (capitalize key) ":")) + (cons newkey (cdr funcs)))) + +(defun mew-sort-get-file-index (folder range key func1 func2) + (let* ((i 0) + (fld (mew-expand-folder2 folder)) + num med value ent files idx) + (with-temp-buffer + (apply 'call-process + mew-prog-mewl nil t nil + (append (list "-b" mew-mail-path "-l" "0" + "-x" mew-suffix + "-d" key) + (mew-scan-mewl-src fld range))) + (goto-char (point-min)) + (while (not (eobp)) + (if (not (looking-at "^\\([0-9]+\\)[ \t]*:[ \t]*")) + (forward-line) + (setq num (mew-match-string 1)) + (setq med (match-end 0)) + (forward-line) + (mew-header-goto-next) + (mew-header-decode-region key med (point)) + (setq value (mew-buffer-substring med (1- (point)))) + (setq files (cons num files)) + (setq ent (cons (cons i (funcall func1 value folder num)) ent)) + (setq i (1+ i))))) + (setq files (vconcat (nreverse files))) + (setq ent (sort ent func2)) + (setq idx (vconcat (mapcar 'mew-sort-index ent))) + (list files idx))) + +(defun mew-sort-files (folder files idx func) + ;; + ;; sorted sorted + ;; files idx -> files + ;; 0 10 1 (was 20) + ;; 1 20 2 (was 30) + ;; 2 30 0 (was 10) + ;; 31(new) + ;; + ;; + ;; src dst + ;; 10 0 (*a) 31 (*b) + ;; 20 1 idx[0] 10 0 + ;; 30 2 idx[1] 20 1 + ;; 31 0 idx[2] 30 2 + ;; (*c) + ;; *a: initial src is 0 + ;; *b: initial files[dst] is 31 (new tmp file) + ;; *c: break condition, src is looped! + ;; files[src] is 31 (new tmp file) + ;; + (let* ((dir (mew-expand-folder folder)) + (default-directory dir) + (len (length idx)) ;; not (length files) + (tmp (mew-folder-new-message folder 'num-only)) + src dst pos) + (dotimes (i len) + (setq mew-sort-line nil) + (unless (= i (aref idx i)) + (setq dst len) + (setq src i) + (setq pos (funcall func (aref files src) tmp nil)) + (catch 'loop + (while t + (setq dst src) + (setq src (aref idx dst)) + (if (= src i) (throw 'loop nil)) + (setq pos (funcall func (aref files src) (aref files dst) pos)) + (aset idx dst dst))) + (funcall func tmp (aref files dst) pos 'last) + (aset idx dst dst))))) + +(defun mew-sort-push-mark () + (unless (eobp) + (beginning-of-line) + (mew-elet + (put-text-property (point) (1+ (point)) 'mew-sort-orig t)))) + +(defun mew-sort-pop-mark () + (let ((orig (next-single-property-change (point-min) 'mew-sort-orig))) + ;; 'mew-sort-orig may start with bob. + (if (null orig) + (mew-push-mark) + (save-excursion + (goto-char orig) + (beginning-of-line) + (setq orig (point))) + (mew-elet + ;; 'mew-sort-orig is copied onto the entire message + ;; number. (window-width) is long enough to remove + ;; it. + (remove-text-properties + orig (+ orig (window-width)) '(mew-sort-orig nil))) + (mew-push-mark)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sort bodies +;;; + +(defun mew-summary-sort-body (folder arg) + (let (key idx files range beg end func1 func2 diag) + ;; Summary cache updates + (mew-summary-reset) + (mew-summary-retrieve-gap folder) + ;; + (mew-set '(range beg end) (mew-sort-get-range arg)) + (mew-set '(key func1 func2) (mew-sort-ask-key folder)) + (setq diag (if arg folder (format "%s: %s" folder range))) + ;; + (message "Sorting %s..." diag) + (mew-summary-lock t "Sorting") + (unwind-protect + (progn + (mew-set '(files idx) (mew-sort-get-file-index folder range key func1 func2)) + ;; + (mew-sort-push-mark) + (if arg (narrow-to-region beg end)) + ;; + (mew-sort-files folder files idx 'mew-summary-sort-move-rename) + ;; + (goto-char (point-min)) + (if arg (widen)) + (mew-sort-pop-mark) + ;; + (run-hooks 'mew-sort-hook) + (message "Sorting %s...done. Type '%s' to update ID database" diag (mew-substitute-for-summary "\\[mew-summary-make-id-index-folder]"))) + (mew-summary-folder-cache-save) + (set-buffer-modified-p nil) + (mew-summary-unlock)))) + +(defun mew-summary-sort-body-for-debug (folder arg) + (let ((win (selected-window)) + key idx files range func1 func2 diag) + (mew-set '(range beg end) (mew-sort-get-range arg)) + (mew-set '(key func1 func2) (mew-sort-ask-key folder)) + (setq diag (if arg folder (format "%s: %s" folder range))) + ;; + (message "Sorting %s..." diag) + (mew-summary-lock t "Sorting") + (unwind-protect + (mew-set '(files idx) (mew-sort-get-file-index folder range key func1 func2)) + (mew-summary-unlock)) + (when (and files idx) + (mew-window-configure 'message) + ;; message buffer + (mew-elet + (mew-erase-buffer) + (insert "Sort as follows:\n")) + ;; + (unwind-protect + (progn + (mew-sort-files folder files idx 'mew-summary-sort-move-for-debug) + (message "Sorting %s...done" diag)) + (mew-message-clear-end-of) + (set-buffer-modified-p nil) + (goto-char (point-min)) + (select-window win))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sort command +;;; + +(defun mew-summary-sort (&optional arg) + "Sort messages and list them up again. +If called with '\\[universal-argument]', sort the region. +After sorting, the cursor moves onto the beginning of the buffer +or the region. " + (interactive "P") + (mew-summary-only + (mew-summary-local-only + (mew-summary-not-in-queue + (mew-summary-not-in-draft + (mew-summary-with-mewl + (when (mew-summary-exclusive-p) + (let ((folder (mew-summary-folder-name))) + (if (null folder) + (message "No message") + (if (mew-mark-active-p) (setq arg t)) + (if (mew-debug 'sort) + (mew-summary-sort-body-for-debug folder arg) + (mew-summary-sort-body folder arg))))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sort for selection +;;; + +(defun mew-summary-selection-by-sort-body (arg) + (let* ((buf (current-buffer)) + (ofolder (mew-summary-folder-name 'ext)) + (vfolder (mew-folder-to-selection ofolder)) + (pfolder (mew-summary-physical-folder)) + key idx files range beg end func1 func2 diag) + (mew-set '(range beg end) (mew-sort-get-range arg)) + (mew-set '(key func1 func2) (mew-sort-ask-key ofolder)) + (setq diag (if arg ofolder (format "%s: %s" ofolder range))) + ;; + (message "Sorting %s..." diag) + (mew-summary-lock t "Sorting") + (unwind-protect + (mew-set '(files idx) (mew-sort-get-file-index ofolder range key func1 func2)) + (mew-summary-unlock)) + (when (and files idx) + (mew-summary-switch-to-folder vfolder) + (mew-vinfo-set-mode 'selection) + (mew-vinfo-set-physical-folder pfolder) + (mew-vinfo-set-original-folder ofolder) + (unwind-protect + (progn + (mew-erase-buffer) + (mew-elet + (insert (with-current-buffer buf (buffer-substring beg end))) + (mew-sort-files ofolder files idx 'mew-summary-sort-move-for-selection) + (mew-summary-set-count-line) + (goto-char (point-min)) + (message "Sorting %s...done" diag))) + (set-buffer-modified-p nil))))) + +(defun mew-summary-selection-by-sort (&optional arg) + (interactive "P") + (mew-summary-only + (mew-summary-not-in-queue + (mew-summary-not-in-draft + (mew-summary-with-mewl + (when (mew-summary-exclusive-p) + (if (mew-mark-active-p) (setq arg t)) + (mew-summary-selection-by-sort-body arg))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Packing +;;; + +(defun mew-summary-pack-rename (src dst) + (mew-elet + (rename-file (mew-msg-get-filename src) (mew-msg-new-filename dst)) + (mew-refile-change src dst) + (when (re-search-forward (mew-regex-sumsyn-msg src) nil t) + (mew-syntax-change-message-number2 dst) + (forward-line)))) + +(defun mew-summary-pack (&optional force) + "Pack messages and list them up again. +After packing, the cursor stays in the current message. +If this command is used in a remote folder, +local cache messages are packed." + (interactive "P") + (if (not force) + (message (mew-substitute-for-summary + "Pack breaks search index, so pack was obsoleted. Type '\\[universal-argument]\\[mew-summary-pack]' to force pack.")) + (mew-summary-only + (mew-summary-local-only + (mew-summary-not-in-queue + (mew-summary-not-in-draft + (when (mew-summary-exclusive-p) + (let ((folder (mew-summary-folder-name))) + (cond + ((null folder) + (message "No message")) + ((or (not mew-ask-pack) (y-or-n-p (format "Pack %s? " folder))) + (mew-summary-pack-body folder))))))))))) + +(defun mew-summary-pack-body (folder) + (let* ((dir (mew-expand-folder folder)) + (default-directory dir) + (n 1) + msgs src dst) + ;; + (mew-summary-reset) + (mew-summary-retrieve-gap folder) + ;; + (message "Packing %s..." folder) + (mew-summary-lock t "Packing") + (condition-case nil + (progn + (setq msgs (mew-dir-messages ".")) + (setq msgs (mapcar 'string-to-number msgs)) + (setq msgs (sort msgs '<)) ;; sort is inevitable + ;; the cursor stays the current position. + (save-excursion + (goto-char (point-min)) + (dolist (msg msgs) + (setq src (number-to-string msg)) + (cond + ((= msg n);; including src is a directory + (setq n (1+ n))) + ((file-directory-p src) + ) + (t + (setq dst (number-to-string n)) + (while (file-exists-p dst) + (setq n (1+ n)) + (setq dst (number-to-string n))) + (mew-summary-pack-rename src dst) + (setq n (1+ n)))))) + (mew-summary-folder-cache-save) + (set-buffer-modified-p nil) + (mew-summary-unlock) + (run-hooks 'mew-pack-hook) + (message "Packing %s...done (the last is %d). Type '%s' to update ID database" folder (1- n) (mew-substitute-for-summary "\\[mew-summary-make-id-index-folder]"))) + (quit + (set-buffer-modified-p nil) + (mew-summary-unlock))))) + +(provide 'mew-sort) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-sort.el ends here diff --git a/elpa/mew-20150813.2354/mew-ssh.el b/elpa/mew-20150813.2354/mew-ssh.el new file mode 100644 index 00000000..3a2359a0 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-ssh.el @@ -0,0 +1,258 @@ +;;; mew-ssh.el + +;; Author: Kazu Yamamoto +;; Created: Dec 14, 1999 + +;;; Code: + +(require 'mew) + +(defvar mew-ssh-prog-ver nil) ;; 0-SSH1, 1-SSH2, 2-OpenSSH, 3-PuTTY + +(defun mew-ssh-get (case list-or-vec) + (elt list-or-vec (mew-ssh-prog-ver case))) + +(defconst mew-ssh-msg-passwd + '("password:\\|Enter passphrase" + "password:\\|Passphrase for\\|Enter passphrase" + "password:\\|Enter passphrase" + "Password:\\|Passphrase for key")) + +(defconst mew-ssh-msg-connected + '("Entering interactive session" + "Authentication successful\\|client_authenticated" + "Entering interactive session" + "Access granted")) + +(defconst mew-ssh-msg-denied + '("Permission denied\\." "Permission denied\\." "Permission denied\\." + "Permission denied\\.")) ;XXX + +(defconst mew-ssh-msg-refused + '("Secure connection .* refused\\." + "FATAL: Connecting .* failed:" + "Secure connection .* refused\\." + "Secure connection .* refused\\.")) ;XXX + +(defconst mew-ssh-process-exec-cnt 3) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SSH info +;;; + +(defvar mew-ssh-info-list '("case" "status" "try" "account")) + +(mew-info-defun "mew-ssh-" mew-ssh-info-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Process name +;;; + +(defconst mew-ssh-info-prefix "mew-ssh-info-") + +(defun mew-ssh-info-name (sshserver server remoteport localport) + (format "%s:%s:%s:%d:%d" + mew-ssh-info-prefix sshserver server remoteport localport)) + +(defun mew-ssh-info-name-regex (sshserver server remoteport) + (format "^%s:%s:%s:%d" mew-ssh-info-prefix sshserver server remoteport)) + +(defun mew-ssh-pnm-to-lport (pnm) + (if (string-match ":\\([0-9]+\\)$" pnm) (match-string 1 pnm))) + +;; user@host:port should be used here. +;; However, SSH does not symbolic port name "ssh" for the "-p" option +;; while OpenSSH does. Sigh... +(defun mew-ssh-passtag (name) + (if (string-match (format "^%s:[^:]+:" mew-ssh-info-prefix) name) + (match-string 0 name))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Executing SSH +;;; + +(defun mew-open-ssh-stream (case server serv sshserver) + "Open SSH stream for SERVER's SERV via SSHSERVER. +This function returns a process when an SSH connection is created +successfully. A local port number can be obtained the process name +after ':'." + (let* ((ssh (mew-ssh-prog case)) + (args (mew-ssh-prog-args case)) + (remoteport (mew-serv-to-port serv)) + (localport (+ 8000 (% (mew-random) 4000))) + (process-connection-type mew-connection-type2) + (N mew-ssh-process-exec-cnt) + (pros (process-list)) + (regex (mew-ssh-info-name-regex sshserver server remoteport)) + name pnm pro status) + (cond + ((not (mew-which-exec ssh)) + (message "'%s' is not found" ssh)) + (t + (catch 'find + (dolist (pr pros) + (when (string-match regex (process-name pr)) + (if (memq (process-status pr) '(run)) + (setq pro pr) + (delete-process pr)) + (throw 'find nil)))) + (if pro + pro + (message "Connecting to the SSH server...") + (setq pro nil) + (catch 'loop + (dotimes (i N) + (setq name (mew-ssh-info-name sshserver server remoteport localport)) + (setq pro (apply 'start-process + name nil + ssh "-x" "-v" "-L" + (format "%d:%s:%d" localport server remoteport) + (append args (list sshserver)))) + ;; An error would occur. So, let's exit in the case. + (mew-timing) + (cond + ((not (processp pro)) + (message "Connecting to the SSH server...FAILED") + (throw 'loop nil)) + ((not (memq (process-status pro) '(run))) + (delete-process pro) + (message "Connecting to the SSH server...FAILED") + (throw 'loop nil))) + ;; ssh is now running. + (mew-process-silent-exit pro) + (setq pnm (process-name pro)) + (mew-info-clean-up pnm) + (mew-ssh-set-try pnm 0) + (mew-ssh-set-case pnm case) + (mew-ssh-set-account pnm (format "%s" sshserver)) + (mew-set-process-cs pro mew-cs-text-for-read mew-cs-text-for-write) + (set-process-filter pro 'mew-ssh-filter) + (set-process-sentinel pro 'mew-ssh-sentinel) + (mew-rendezvous (null (mew-ssh-get-status pnm))) + (setq status (mew-ssh-get-status pnm)) + (cond + ((eq status t) + (throw 'loop pro)) ;; return value + ((not (eq status 'bound)) + (message "Connecting to the SSH server...FAILED") + (throw 'loop nil))) ;; return value + ;; 'bound + (setq localport (1+ localport)) + (message "Connecting to the SSH server...FAILED") + nil))))))) ;; return value + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defun mew-ssh-debug (label string) + (when (mew-debug 'net) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +(defun mew-ssh-filter (process string) + (save-excursion + (mew-ssh-debug "SSH: " string) + (let* ((pnm (process-name process)) + (case (mew-ssh-get-case pnm)) + pass) + (cond + ((string-match (mew-ssh-get case mew-ssh-msg-passwd) string) + (if (= (mew-ssh-get-try pnm) 0) + (setq pass (mew-input-passwd (format "SSH password (%s): " + (mew-ssh-get-account pnm)) + (mew-ssh-passtag pnm))) + (mew-passwd-set-passwd (mew-ssh-passtag pnm) nil) + (setq pass (mew-input-passwd (format "SSH password again (%s): " + (mew-ssh-get-account pnm)) + (mew-ssh-passtag pnm)))) + (mew-ssh-set-try pnm (1+ (mew-ssh-get-try pnm))) + (if (and (processp process) + (memq (process-status process) '(run))) + (progn + (message "Sending password to the SSH server...") + (process-send-string process (concat pass "\n"))) + (mew-passwd-set-passwd (mew-ssh-passtag pnm) nil) + (message "Cannot find SSH process"))) + ((or (string-match (mew-ssh-get case mew-ssh-msg-denied) string) + (string-match (mew-ssh-get case mew-ssh-msg-refused) string)) + (message "Cannot connect to the SSH server") + (mew-passwd-set-passwd (mew-ssh-passtag pnm) nil) + (mew-ssh-set-status pnm 'denied)) + ((string-match (mew-ssh-get case mew-ssh-msg-connected) string) + (mew-ssh-set-status pnm t) + (message "Connecting to the SSH server...done")) + ((string-match "Local: bind: Address already in use" string) + (mew-ssh-set-status pnm 'bound) + (message "Connecting to the SSH server...done")))))) + +(defun mew-ssh-sentinel (process event) + (let ((pnm (process-name process))) + (save-excursion + (unless (mew-ssh-get-status pnm) + (mew-ssh-set-status pnm 'exit))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SSH version check +;;; + +(defun mew-ssh-setup () + (let ((ssh (mew-ssh-prog))) + (if (not (mew-which-exec ssh)) + (setq mew-ssh-prog-ver nil) + (with-temp-buffer + (call-process ssh nil t nil "-V") + (goto-char (point-min)) + (cond + ((looking-at "SSH Version 1") + (setq mew-ssh-prog-ver 0)) + ((looking-at (concat ssh ": SSH Version 2")) + (setq mew-ssh-prog-ver 1)) + ((looking-at (concat ssh ": SSH Secure Shell [23]")) + (setq mew-ssh-prog-ver 1)) + ((looking-at "\\(SSH Version \\)?\\(OpenSSH\\|NetBSD\\|Sun_SSH\\)") + (setq mew-ssh-prog-ver 2)) + ((looking-at "plink:") + (setq mew-ssh-prog-ver 3)) + (t + (setq mew-ssh-prog-ver nil))))))) + +(provide 'mew-ssh) + +;;; Copyright Notice: + +;; Copyright (C) 1999-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-ssh.el ends here diff --git a/elpa/mew-20150813.2354/mew-ssl.el b/elpa/mew-20150813.2354/mew-ssl.el new file mode 100644 index 00000000..d6d8380a --- /dev/null +++ b/elpa/mew-20150813.2354/mew-ssl.el @@ -0,0 +1,313 @@ +;;; mew-ssl.el + +;; Author: Kazu Yamamoto +;; Created: Jul 25, 2002 + +;;; Code: + +(require 'mew) + +(defvar mew-prog-ssl "stunnel") +(defvar mew-ssl-cert-directory "~/.certs" + "The directory where certificates of root servers are stored. +A file name of a certificate should be 'cert-hash.0'. +'cert-hash' can be extracted by 'openssl x509 -hash -noout -in cert.pem'.") + +(defvar mew-ssl-verify-level 1 + "Verification level of server's certificate. +0 - no verification. +1 - verify server's certificate if present. If verification failed, an + SSL/TLS connection is not created. If not present, an SSL/TLS connection + is created. +2 - verify server's certificate. If verification failed, an SSL/TLS + connection is not created. If not present, an SSL/TLS connection is + not created. +3 - verify server's certificate which locally installed (not one from + the server).") + +(defvar mew-prog-ssl-arg nil + "For stunnel v3, a list of command-line arguments, each one a string. +For stunnel v4 or v5, a string of extra text to place in the configuration +file, which should end with a newline (example: \"fips=no\\n\"); or nil to +insert no extra text.") + +(defvar mew-ssl-ver nil) +(defvar mew-ssl-minor-ver nil) + +(defvar mew-ssl-libwrap nil) + +(defconst mew-ssl-process-exec-cnt 3) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Magic words +;;; + +(defconst mew-tls-smtp "smtp") +(defconst mew-tls-pop "pop3") +(defconst mew-tls-nntp "nntp") +(defconst mew-tls-imap "imap") ;; xxx stunnel does not support this. + +;; stunnel does not support IPv6, sigh +(defconst mew-ssl-localhost "127.0.0.1") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SSL/TLS info +;;; + +(defvar mew-ssl-info-list '("status" "try" "file" "string")) + +(mew-info-defun "mew-ssl-" mew-ssl-info-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Process name +;;; + +(defconst mew-ssl-info-prefix "mew-ssl-info-") + +(defun mew-ssl-info-name (server remoteport localport) + (format "%s:%s:%d:%d" mew-ssl-info-prefix server remoteport localport)) + +(defun mew-ssl-info-name-regex (server remoteport) + (format "^%s:%s:%d" mew-ssl-info-prefix server remoteport)) + +(defun mew-ssl-pnm-to-lport (pnm) + (if (string-match ":\\([0-9]+\\)$" pnm) (match-string 1 pnm))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Executing SSL/TLS +;;; + +(defun mew-ssl-server (server) + (if (string= server "localhost") + mew-ssl-localhost + server)) + +(defun mew-ssl-options (case server remoteport localport tls) + (setq server (mew-ssl-server server)) + (if (= mew-ssl-ver 3) + (let (args) + (setq args + `("-c" "-f" + "-a" ,(expand-file-name (mew-ssl-cert-directory case)) + "-d" ,(format "%s:%d" mew-ssl-localhost localport) + "-v" ,(number-to-string (mew-ssl-verify-level case)) + "-D" "debug" + "-P" "" + "-r" ,(format "%s:%d" server remoteport) + ,@mew-prog-ssl-arg)) + (if tls (setq args (cons "-n" (cons tls args)))) + args) + (let ((file (mew-make-temp-name))) + (with-temp-buffer + (insert "client=yes\n") + (insert "pid=\n") + (insert (format "verify=%d\n" (mew-ssl-verify-level case))) + (insert "foreground=yes\n") + (insert "debug=debug\n") + (if (and mew-ssl-libwrap (or (>= mew-ssl-ver 5) (>= mew-ssl-minor-ver 45))) + (insert "libwrap=no\n")) + (if (or (>= mew-ssl-ver 5) (>= mew-ssl-minor-ver 22)) + (insert "syslog=no\n")) + (insert "CApath=" (expand-file-name (mew-ssl-cert-directory case)) "\n") + (if mew-prog-ssl-arg + (insert mew-prog-ssl-arg)) + (insert (format "[%d]\n" localport)) + (insert (format "accept=%s:%d\n" mew-ssl-localhost localport)) + (insert (format "connect=%s:%d\n" server remoteport)) + (if tls (insert (format "protocol=%s\nsslVersion=TLSv1\n" tls))) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + ;; NEVER use call-process-region for privacy reasons + (write-region (point-min) (point-max) file nil 'no-msg)) + (list file))))) + +(defun mew-open-ssl-stream (case server serv tls) + "Open an SSL/TLS stream for SERVER's SERV. +This function returns a process when an SSL/TLS connection is created +successfully. +If TLS is nil, an SSL connection is created. +If TLS is a magic word for 'stunnel', a TLS connection is created. +A local port number can be obtained the process name after ':'. " + (cond + ((or (null mew-ssl-ver) (not (mew-which-exec mew-prog-ssl))) + (message "'%s' is not found" mew-prog-ssl) + nil) + (t + (let* ((remoteport (mew-serv-to-port serv)) + (localport (+ 8000 (% (mew-random) 4000))) + (process-connection-type mew-connection-type2) + (N mew-ssl-process-exec-cnt) + (pros (process-list)) + (regex (mew-ssl-info-name-regex server remoteport)) + name pnm pro dummy bound opts) + (catch 'find + (dolist (pr pros) + (when (string-match regex (process-name pr)) + (if (memq (process-status pr) '(run)) + (setq pro pr) + (delete-process pr)) + (throw 'find nil)))) + (if pro + pro + (message "Creating an SSL/TLS connection...") + (setq pro nil) + (catch 'loop + (dotimes (i N) + (setq name (mew-ssl-info-name server remoteport localport)) + (setq opts (mew-ssl-options case server remoteport localport tls)) + (setq pro (apply 'start-process name nil mew-prog-ssl opts)) + ;; An error would occur. So, let's exit in the case. + (cond + ((not (processp pro)) + (message "Creating an SSL/TLS connection...FAILED") + (throw 'loop nil)) + ((not (memq (process-status pro) '(run))) + (delete-process pro) + (message "Creating an SSL/TLS connection...FAILED") + (throw 'loop nil))) + ;; stunnel is now running. + (mew-process-silent-exit pro) + (setq pnm (process-name pro)) + (mew-info-clean-up pnm) + (mew-ssl-set-try pnm 0) + (if (>= mew-ssl-ver 4) (mew-ssl-set-file pnm (car opts))) + (mew-set-process-cs pro mew-cs-text-for-read mew-cs-text-for-write) + (set-process-filter pro 'mew-ssl-filter1) + (set-process-sentinel pro 'mew-ssl-sentinel) + (mew-rendezvous (null (mew-ssl-get-status pnm))) + (if (eq (mew-ssl-get-status pnm) t) + (throw 'loop (setq bound t))) + ;; bind-failure + (setq localport (1+ localport)))) + (mew-ssl-set-status pnm nil) + (if (not bound) + (progn + (message "Creating an SSL/TLS connection...FAILED") + nil) + ;; "stunnel" does not gain access to the remote port + ;; until a tunneled connection is created. + ;; So, we need to check the SSL/TLS tunnel with a dummy + ;; tunneled connection here. + (set-process-filter pro 'mew-ssl-filter2) + (setq dummy (open-network-stream " *Mew dummy*" nil mew-ssl-localhost localport)) + (mew-rendezvous (null (mew-ssl-get-status pnm))) + (if (processp dummy) (delete-process dummy)) + (if (eq (mew-ssl-get-status pnm) t) + (progn + (message "Creating an SSL/TLS connection...done") + (set-process-filter pro 'mew-ssl-filter3) + pro) + ;; verify-failure + (delete-process pro) + (message "Creating an SSL/TLS connection...FAILED (cert verify failure)") + nil))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Filter and sentinel +;;; + +(defun mew-ssl-debug (label string) + (when (mew-debug 'net) + (with-current-buffer (get-buffer-create mew-buffer-debug) + (goto-char (point-max)) + (insert (format "\n<%s>\n%s\n" label string))))) + +(defun mew-ssl-filter1 (process string) + (let* ((pnm (process-name process)) + (prev-str (mew-ssl-get-string pnm))) + (save-excursion + (mew-ssl-debug "SSL/TLS: " string) + (mew-ssl-set-string pnm string) + (setq string (concat prev-str string)) + (cond + ((string-match "bound \\(\\|FD=[0-9]+ \\)to" string) + (mew-ssl-set-status pnm t)) + ((string-match "gethostbyname: Valid name, no data record of requested type" string) + (mew-ssl-set-status pnm 'gethostbyname-failure)) + ((string-match "gethostbyname: Host not found" string) + (mew-ssl-set-status pnm 'gethostbyname-failure)) + ((string-match "Local: bind: Address already in use" string) + (mew-ssl-set-status pnm 'bind-failure)))))) + +(defun mew-ssl-filter2 (process string) + (let* ((pnm (process-name process)) + (prev-str (mew-ssl-get-string pnm))) + (save-excursion + (mew-ssl-debug "SSL/TLS: " string) + (mew-ssl-set-string pnm string) + (setq string (concat prev-str string)) + (cond + ((string-match "Negotiated \\|opened with SSL" string) + (mew-ssl-set-status pnm t)) + ((string-match "Failed to initialize" string) + (mew-ssl-set-status pnm t)) ;; xxx + ((string-match "verify failed" string) + (mew-ssl-set-status pnm 'verify-failure)))))) + +(defun mew-ssl-filter3 (process string) + (save-excursion + (mew-ssl-debug "SSL/TLS: " string))) + +(defun mew-ssl-sentinel (process event) + (let* ((pnm (process-name process)) + (file (mew-ssl-get-file pnm))) + (save-excursion + (mew-delete-file file)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; stunnel version check +;;; + +(defun mew-ssl-setup () + (if (not (mew-which-exec mew-prog-ssl)) + (setq mew-ssl-ver nil) + (with-temp-buffer + (call-process mew-prog-ssl nil t nil "-version") + (goto-char (point-min)) + (re-search-forward "^stunnel " nil t 1) + (if (looking-at "\\([45]\\)\\.\\([0-9]+\\)") + (progn + (setq mew-ssl-ver (string-to-number (mew-match-string 1))) + (setq mew-ssl-minor-ver (string-to-number (mew-match-string 2)))) + (setq mew-ssl-ver 3)) + (when (re-search-forward "LIBWRAP" nil t) + (setq mew-ssl-libwrap t))))) + +(provide 'mew-ssl) + +;;; Copyright Notice: + +;; Copyright (C) 2002-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-ssl.el ends here diff --git a/elpa/mew-20150813.2354/mew-summary.el b/elpa/mew-20150813.2354/mew-summary.el new file mode 100644 index 00000000..4d5aa29a --- /dev/null +++ b/elpa/mew-20150813.2354/mew-summary.el @@ -0,0 +1,415 @@ +;;; mew-summary.el --- Summary mode for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Summary info +;;; + +(defvar mew-sinfo-list + '(;; parameters to be saved + "refile" "mark-hist" + ;; parameters used internally + "scan-id" "scan-md5" "find-key" "cursor-line" "direction" "start-point" + "cache-time" "summary-form" "summary-column" "unread-mark" "refile-back" + "disp-msg" "case" "folder" "proto" "mid-marker" "mid-line" "ttl-line" + "mark-review" "ret-pos" "inboxp" "column")) + +(mew-blinfo-defun 'mew-sinfo mew-sinfo-list) + +(defvar mew-sinfo-list-save-length 2) +(defvar mew-sinfo-file ".mew-sinfo") + +(defun mew-sinfo-save () + (when (mew-summary-p) + (let* ((n mew-sinfo-list-save-length) + (data (make-vector n nil)) + (bnm (mew-summary-folder-name 'ext)) + (file (mew-expand-file bnm mew-sinfo-file))) + (dotimes (i n) + (aset data i (aref mew-sinfo i))) + (mew-lisp-save file data nil 'unlimit)))) + +(defun mew-sinfo-load () + (when (mew-summary-p) + (let* ((n mew-sinfo-list-save-length) + (bnm (mew-summary-folder-name 'ext)) + (file (mew-expand-file bnm mew-sinfo-file)) + data) + (setq data (mew-lisp-load file)) + (when data + (dotimes (i n) + (aset mew-sinfo i (aref data i))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Macros +;;; + +(defmacro mew-summary-msg-or-part (&rest body) + "See if the cursor is on a message or a part." + `(cond + ((eobp) (message "No message")) + ((not (or (mew-summary-message-number) (mew-syntax-number))) + (message "No message")) + (t ,@body))) + +(defmacro mew-summary-msg (&rest body) + "See if the cursor is on a message." + `(cond + ((eobp) (message "No message")) + ((not (mew-summary-message-number)) + (message "Please use this command on a message, not a part")) + (t ,@body))) + +(defmacro mew-summary-part (&rest body) + "See if the cursor is on a part." + `(cond + ((eobp) (message "No part")) + ((not (mew-syntax-number)) + (message "Please use this command on a part, not a message")) + (t ,@body))) + +(defmacro mew-summary-multi-msgs (&rest body) + "Collect messages marked with '*' and set their corresponding +files to FILES." + `(let* ((FLD-MSGS (mew-summary-mark-collect2 mew-mark-review)) + (FLD-MSG-LIST FLD-MSGS) ;; may be used in body + FILES) ;; may be used in body + (cond + ((null FLD-MSGS) + (message "No %c marks" mew-mark-review)) + (t + ;; a little bit complicated because of Virtual mode + (dolist (fld-msg FLD-MSGS) + (setq FILES (cons (mew-expand-msg (car fld-msg) (cdr fld-msg)) + FILES))) + (setq FILES (nreverse FILES)) + ,@body)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Subfunctions +;;; + +(defun mew-summary-local-p () + (mew-folder-localp (mew-summary-folder-name 'ext))) + +(defun mew-summary-draft-p () + (mew-folder-draftp (mew-summary-folder-name 'ext))) + +(defun mew-summary-queue-p () + (or (mew-folder-queuep (mew-summary-folder-name 'ext)) + (mew-folder-postqp (mew-summary-folder-name 'ext)))) + +(defun mew-summary-pop-p () + (mew-folder-popp (mew-summary-folder-name 'ext))) + +(defun mew-summary-case1 () + (and (mew-summary-or-virtual-p) (not (mew-summary-draft-p)))) + +(defun mew-summary-case2 () + (and (mew-summary-p) (not (mew-summary-queue-p)))) + +(defun mew-summary-case3 () + (and (mew-summary-p) mew-summary-buffer-process)) + +(defmacro mew-summary-only (&rest body) + "See if the mode of this buffer is Summary mode. +This macro is used to prohibit using a command in Virtual mode." + `(cond + ((not (mew-summary-p)) + (message "This command can be used in Summary mode only")) + (t ,@body))) + +(defmacro mew-virtual-only (&rest body) + "See if the mode of this buffer is Virtual mode. +This macro is used to prohibit using a command in Summary mode." + `(cond + ((not (mew-virtual-p)) + (message "This command can be used in Virtual mode only")) + (t ,@body))) + +(defmacro mew-thread-only (&rest body) + "See if this buffer is Thread folder. +This macro is used to prohibit using a command in Summary mode." + `(cond + ((not (mew-thread-p)) + (message "This command can be used in Thread folder only")) + (t ,@body))) + +(defmacro mew-pickable (&rest body) + "See if pick can be used for this folder." + `(cond + ((not (mew-pickable-p)) + (message "This command cannot be used in this folder")) + (t ,@body))) + +(defmacro mew-summary-not-in-queue (&rest body) + "See if this folder is not +queue." + `(cond + ((not (mew-summary-or-virtual-p)) + (message "This command cannot be used in this mode")) + ((mew-summary-queue-p) + (message "This command cannot be used in %s" (mew-summary-folder-name))) + (t ,@body))) + +(defmacro mew-summary-not-in-draft (&rest body) + "See if this folder is not +draft." + `(cond + ((not (mew-summary-or-virtual-p)) + (message "This command cannot be used in this mode")) + ((mew-summary-draft-p) + (message "This command cannot be used in %s" (mew-summary-folder-name))) + (t ,@body))) + +(defmacro mew-summary-not-in-nntp (&rest body) + "See if this folder is not NNTP." + `(cond + ((mew-folder-nntpp (mew-sinfo-get-folder)) + (message "This command cannot be used in %s" (mew-summary-folder-name))) + (t ,@body))) + +(defmacro mew-summary-local-or-imap (&rest body) + "See if this folder is either local or IMAP." + `(cond + ((not (mew-summary-or-virtual-p)) + (message "This command cannot be used in this mode")) + ((or (mew-folder-nntpp (mew-sinfo-get-folder)) + (mew-folder-popp (mew-sinfo-get-folder))) + (message "This command cannot be used in %s" (mew-summary-folder-name))) + (t ,@body))) ;; local or IMAP + +(defmacro mew-summary-local-only (&rest body) + "See if this folder is local." + `(cond + ((not (mew-summary-or-virtual-p)) + (message "This command cannot be used in this mode")) + ((not (mew-summary-local-p)) + (message "This command cannot be used in %s" (mew-summary-folder-name))) + (t ,@body))) + +(defmacro mew-summary-with-mewl (&rest body) + `(cond + ((not (mew-which-exec mew-prog-mewl)) + (message "'%s' not found!" mew-prog-mewl)) + (t ,@body))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Region +;;; + +(defun mew-summary-get-region () + "Get a region according to 'mew-summary-region-include-cursor-line' +and return (beg . end)." + (save-excursion + (let ((beg (region-beginning)) + (end (region-end))) + (goto-char beg) + (beginning-of-line) + (setq beg (point)) + (goto-char end) + (cond + ((eq mew-summary-region-include-cursor-line t) + (forward-line)) + ((eq mew-summary-region-include-cursor-line 'end) + (if (eq (char-after) ?\n) + (forward-line) + (beginning-of-line))) + (t + (if (> (current-column) 0) + (forward-line) + (beginning-of-line)))) + (cons beg (point))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Dialog +;;; + +(defun mew-substitute-for-summary (msg) + (substitute-command-keys (concat "\\" msg))) + +(defun mew-message-for-summary (msg) + (message "%s" (mew-substitute-for-summary msg))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Modeline +;;; + +(defvar mew-mode-line-target "%p") +(defvar mew-mode-line-format + `("" + (mew-summary-buffer-left-msgs mew-summary-buffer-left-msgs "L%l") + (mew-summary-buffer-raw "*") + (mew-summary-buffer-secure-process ,mew-secure-format2))) + +(defvar mew-mode-line-process + '((mew-summary-buffer-secure-process mew-secure-format) + (mew-summary-buffer-process mew-summary-buffer-process-status))) + +(defun mew-summary-setup-mode-line () + (let ((tgt mew-mode-line-target) + target prev pos) + (if (boundp 'mode-line-position) + (progn + (make-local-variable 'mode-line-position) ;; Emacs 21.3.50 + (setq mode-line-position + (copy-sequence (default-value 'mode-line-position))) + (setq prev mode-line-position)) + (setq mode-line-format (copy-sequence (default-value 'mode-line-format))) + (setq prev mode-line-format)) + (setq target (or (rassoc (list tgt) prev) ;; Emacs 21.3.50 + (rassoc tgt prev) + (car (member tgt prev)))) + (when target + (setq pos (- (length prev) (length (member target prev)))) + (setcar (nthcdr pos prev) mew-mode-line-format)) + (when (boundp 'line-number-mode) + (make-local-variable 'line-number-mode) + (setq line-number-mode nil)) + (or (assq 'mew-summary-buffer-process mode-line-process) + (setq mode-line-process + (append mew-mode-line-process mode-line-process))))) + +(defun mew-summary-reset-mode-line () + (setq mew-summary-buffer-left-msgs nil)) + +(defun mew-summary-mode-name (name) + (let ((case (if (mew-case-default-p mew-case) "" mew-case))) + (if (string= case "") + (setq mode-name name) + (setq mode-name (format "%s %s" name case))) + (force-mode-line-update))) + +(defun mew-summary-mode-line () + (unless mew-summary-buffer-process + (let ((pos (point)) + (mid-point (marker-position (mew-sinfo-get-mid-marker))) + (mid-line (mew-sinfo-get-mid-line)) + (ttl (mew-sinfo-get-ttl-line)) + cur left) + (if (< pos mid-point) + (if (< pos (/ mid-point 2)) + (setq cur (mew-count-lines (point-min) pos)) + (setq cur (- mid-line (mew-count-lines pos mid-point)))) + (if (< pos (+ mid-point (/ mid-point 2))) + (setq cur (+ mid-line (mew-count-lines mid-point pos))) + (setq cur (- ttl (mew-count-lines pos (point-max)))))) + (unless (and (mew-decode-syntax-p) + (equal (mew-decode-syntax-buffer) (current-buffer)) + (>= pos (mew-decode-syntax-begin)) + (<= pos (mew-decode-syntax-end))) + (setq cur (1+ cur))) + (setq left (- ttl cur)) + (setq mew-summary-buffer-left-msgs (format "[%d/%d{%d}]" cur ttl left))) + (force-mode-line-update))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Locking +;;; + +(defun mew-summary-exclusive-p (&optional no-msg) + (cond + ((eq mew-summary-buffer-process t) + (or no-msg (message "Try again later")) + nil) ;; not exclusive + ((processp mew-summary-buffer-process) + (or no-msg + (mew-message-for-summary + "Another process is running. Try later or type '\\[mew-summary-kill-subprocess]' to kill it")) + nil) ;; not exclusive + (t t))) ;; exclusive + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Summary mode +;;; + +(defun mew-summary-mode () + "A major mode to show a list of messages in a folder. + +\\{mew-summary-mode-map}" + (interactive) + (setq major-mode 'mew-summary-mode) + (setq mode-line-buffer-identification (mew-mode-line-id)) + (use-local-map mew-summary-mode-map) + (setq buffer-read-only t) + (setq truncate-lines t) + ;; + (if (boundp 'bidi-paragraph-direction) + (setq bidi-paragraph-direction 'left-to-right)) + (make-local-variable 'tab-width) + (make-local-variable 'search-invisible) + (setq search-invisible nil) + (make-local-variable 'line-move-ignore-invisible) + (setq line-move-ignore-invisible t) + (make-local-variable 'search-invisible) + (jit-lock-register 'mew-summary-cook-region) + (add-hook 'kill-buffer-hook 'mew-sinfo-save nil 'local) + (mew-sinfo-set-disp-msg t) + ;; + (mew-summary-mode-name mew-mode-name-summary) + (mew-summary-setup-mode-line) + (mew-summary-setup-decoration) + (mew-highlight-cursor-line) + (mew-run-mode-hooks 'mew-summary-mode-hook)) + +(defun mew-summary-kill () + "Kill this Summary mode." + (interactive) + (mew-kill-buffer) + (when (and mew-use-other-frame-for-summary (> (length (frame-list)) 1)) + (mew-remove-buffer (mew-buffer-message)) + (delete-frame))) + +(defun mew-summary-reset () + (mew-unhighlight-cursor-line) + (mew-window-configure 'summary) + (mew-remove-buffer (mew-buffer-message)) + (mew-current-set nil nil nil) + (mew-summary-reset-mode-line) + (mew-decode-syntax-delete)) + +(provide 'mew-summary) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-summary.el ends here diff --git a/elpa/mew-20150813.2354/mew-summary2.el b/elpa/mew-20150813.2354/mew-summary2.el new file mode 100644 index 00000000..7434d273 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-summary2.el @@ -0,0 +1,819 @@ +;;; mew-summary2.el --- Summary mode for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; End of +;;; + +(defun mew-message-set-end-of () + (save-restriction + (widen) + (save-excursion + (mew-elet + (goto-char (point-max)) + (unless (bolp) (insert "\n")) + (mew-message-clear-end-of) + (when (or mew-end-of-message-string mew-end-of-part-string) + (move-overlay (mew-minfo-get-eom) (point-max) (point-max)) + (if (mew-decode-syntax-p) + (if (mew-summary-end-of-message-p) + (mew-message-set-end-of-message) + (mew-message-set-end-of-part)) + (mew-message-set-end-of-message))))))) + +(defun mew-message-clear-end-of () + (unless (overlayp (mew-minfo-get-eom)) + (mew-minfo-set-eom (mew-overlay-make (point-max) (point-max)))) + (mew-message-set-end-of-nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Prefetch +;;; + +(defun mew-summary-cache-prefetch () + (let ((mew-inherit-prefetching t) + fld next) + (save-excursion + (mew-redraw) ;; need to display + (mew-summary-goto-message) + (cond + ((eq (mew-sinfo-get-direction) 'up) + (when (re-search-backward mew-regex-msg-show nil t) + (setq fld (mew-summary-folder-name)) + (setq next (mew-summary-message-number)))) + ((eq (mew-sinfo-get-direction) 'down) + (if (mew-decode-syntax-end) + (goto-char (mew-decode-syntax-end)) + (forward-line)) + (when (re-search-forward mew-regex-msg-show nil t) + (setq fld (mew-summary-folder-name)) + (setq next (mew-summary-message-number)))))) + ;; should get the cursor back for display + (save-excursion + (if (and fld next + (not (mew-cache-hit fld next)) + (not (string= fld mew-draft-folder)) + (not (mew-summary-message-toobig fld next))) + (mew-cache-message fld next nil 'no-err))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Caching +;;; + +(defun mew-summary-cache-message (fld msg sumbuf &optional unlimit nodisplay) + "Create a cache for the message specified with FLD and MSG. +If UNLIMIT is non-nil, decodes it without limitations. +If nodisplay is non-nil, displays the cached message." + ;; message buffer + (mew-elet + (mew-summary-display-preamble) + (let ((cache (mew-cache-message fld msg unlimit))) + (mew-decode-syntax-copy cache) + (unless nodisplay + (mew-mime-message/rfc822 cache mew-decode-syntax)) + ;; Must print the syntax before mew-summary-display-postscript + ;; to tell the end of message. + (mew-decode-syntax-print sumbuf + mew-decode-syntax + (mew-xinfo-get-multi-form) + (mew-xinfo-get-icon-spec)) + (unless nodisplay + (mew-summary-display-postscript)) + cache))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; After step +;;; + +(defun mew-summary-display-after (direction) + (cond + ((eq direction 'down) + (mew-summary-display-down)) + ((eq direction 'up) + (mew-summary-display-up)) + ((eq direction 'next) + (mew-summary-display-next)) + (t ()))) ;; 'stop + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Preamble and postscript +;;; + +(defun mew-summary-recenter () + "Make the current line to the center of Summary mode." + (interactive) + (if (or mew-summary-recenter-p (mew-called-interactively-p)) + (recenter (/ (- (window-height) 2) 2)))) + +(defun mew-summary-display-preamble () + ;; message buffer + (mew-erase-buffer) + (mew-message-clear-end-of) + (mew-overlay-delete-buffer) ;; veil, xxx also delete extents? + ;; kill mark for cite + (and (mark-marker) (set-marker (mark-marker) nil)) + (mew-normal-line)) + +(defvar mew-message-last-buffer nil) + +(defun mew-summary-display-postscript (&optional no-hook) + ;; message buffer + (unless no-hook (run-hooks 'mew-message-hook)) + (mew-minfo-set-reob nil) + (setq mew-message-last-buffer (current-buffer)) + (mew-message-set-end-of) + (set-buffer-modified-p nil)) + +(defun mew-summary-cursor-postscript () + (mew-summary-mode-line) + (mew-summary-recenter) + (mew-thread-move-cursor) + (mew-highlight-cursor-line) + (when (and mew-use-unread-mark + (mew-summary-message-number) + ;; mark would be nil. MUST be equal + (equal (mew-summary-get-mark) mew-mark-unread)) + (unless (and mew-inherit-after-marking + (not mew-delete-unread-mark-by-mark)) + (mew-mark-put-mark mew-mark-read 'no-msg))) + (set-buffer-modified-p nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Displaying +;;; + +(defun mew-summary-message-toobig (fld msg) + (let ((file (mew-expand-msg fld msg))) + (and (file-readable-p file) + (> (mew-file-get-size file) mew-file-max-size)))) + +(defun mew-summary-display (&optional redisplay) + " (1) If called interactively, this command lets you read +through messages. That is, display a message, scroll it, and +move-then-display another message or part. + +See 'mew-summary-show-direction' to set the direction that the +cursor moves. You can select a value out of 'up, 'down, +'next(current direction) or 'stop. Default is +'down. 'mew-summary-show-direction' is valid in this case only +because the cursor stays in the other cases. + + (2) If called interactively with '\\[universal-argument]' (i.e. +REDISPLAY is non-nil), this command displays the current message +or part again. This is a convenient way to get back to the +beginning of the current message or part. + + (3) If called internally, this function displays the current +message or part. If it is already displayed, nothing changes. + + (4) If called internally and REDISPLAY is 'non-nil', this +function displays the current message or part. Even if it is +already displayed, this function displays it again getting back +to the beginning." + (interactive "P") + (when (or redisplay (mew-sinfo-get-disp-msg) (mew-called-interactively-p)) + (mew-summary-msg-or-part + (let* ((fld (mew-summary-folder-name)) + (vfld (mew-summary-folder-name 'ext)) + (msg (mew-summary-message-number)) + (part (mew-syntax-nums)) + (fid (mew-frame-id)) + (ofld (mew-current-get-fld fid)) + (omsg (mew-current-get-msg fid)) + (opart (mew-current-get-part fid)) + (cache (mew-cache-hit fld (or msg omsg))) + (win (selected-window)) + (read-through (mew-called-interactively-p)) + (sumbuf (current-buffer)) + next prefetch) + (unwind-protect + (progn + (mew-summary-toggle-disp-msg 'on) + (mew-window-configure 'message) + ;; message buffer + (mew-current-set fld (or msg omsg) part) + (mew-minfo-set-summary vfld) + (cond + ((null cache) + (mew-decode-syntax-delete) + (cond + ((string= fld mew-draft-folder) + (if (and (string= fld ofld) (string= msg omsg) + (not redisplay)) + (if read-through + (if (mew-message-next-page) + (setq next t))) + (mew-decode-syntax-clear) + (mew-summary-display-draft fld msg) + (setq prefetch t))) + ((mew-summary-message-toobig fld msg) + (if (and (string= fld ofld) (string= msg omsg) + (not redisplay)) + (if read-through + (if (mew-message-next-page) + (setq next t))) + (mew-decode-syntax-clear) + (mew-summary-display-raw fld msg mew-file-max-size) + (setq prefetch t) + (mew-message-for-summary + "Too large, truncated. To see the entire message, type '\\[mew-summary-analyze-again]'"))) + (t + (mew-decode-syntax-clear) + (mew-summary-cache-message fld msg sumbuf) + (setq prefetch t)))) + (msg + (cond + ((or (null ofld) + (not (and (string= fld ofld) (string= msg omsg))) + opart redisplay) + (mew-decode-syntax-clear) + (mew-decode-syntax-delete) + (mew-summary-display-message cache sumbuf) + (setq prefetch t)) + (read-through + (if (mew-message-next-page) + (setq next t))))) + (part + (cond + ((or (null opart) + (not (equal opart part)) + redisplay) + (mew-summary-display-part cache part)) + ;; If called internally, never match below + (read-through + (if (mew-message-next-page) + (setq next t))))))) + (if (mew-xinfo-get-decode-err) + (message "MIME decoding error: %s" (mew-xinfo-get-decode-err))) + (if (mew-xinfo-get-action) + (message "%s" (mew-xinfo-get-action))) + (mew-message-mode-line fld msg) + (select-window win) + ;; summary buffer + (mew-summary-cursor-postscript) + (if prefetch (mew-summary-cache-prefetch)) + (if next (mew-summary-display-after mew-summary-show-direction))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Displaying message or part +;;; + +(defun mew-summary-display-message (cache sumbuf) + "Display a message from the CACHE." + ;; message buffer + (mew-elet + (mew-summary-display-preamble) + (mew-decode-syntax-copy cache) + (mew-mime-message/rfc822 cache mew-decode-syntax) + ;; Must print the syntax before mew-summary-display-postscript + ;; to tell the end of message. + (mew-decode-syntax-print sumbuf + mew-decode-syntax + (mew-xinfo-get-multi-form) + (mew-xinfo-get-icon-spec)) + (mew-summary-display-postscript))) + +(defun mew-summary-display-part (cache nums) + "Display a part from the CACHE." + ;; message buffer + (mew-elet + (mew-summary-display-preamble) + (mew-decode-syntax-copy cache) + (mew-mime-part cache mew-decode-syntax nums) + (mew-summary-display-postscript))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Displaying draft +;;; + +(defun mew-summary-display-draft (fld msg) + "Display the message in +draft specified by FLD and MSG. +The message is not in the MIME form. So, it cannot be decoded as MIME. +Just display it as is. This function does not create a cache." + ;; message buffer + (mew-elet + (mew-summary-display-preamble) + (mew-insert-message fld msg mew-cs-m17n nil) + (mew-header-goto-end) + (mew-highlight-header-region (point-min) (point)) + (mew-summary-display-postscript))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Displaying draft +;;; + +(defun mew-summary-display-raw (fld msg size) + "Display the message specified by FLD and MSG as is. +If SIZE is specified, truncates it with the size. +This function does not create a cache." + ;; message buffer + (mew-elet + (mew-summary-display-preamble) + (mew-insert-message fld msg mew-cs-binary size) + (goto-char (point-min)) + (when (re-search-forward mew-eoh nil t) + (let ((beg (point))) + (goto-char (point-max)) + (mew-cs-decode-region beg (point) mew-cs-autoconv))) + (goto-char (point-min)) + (condition-case nil + (progn + (mew-decode-rfc822-header) ;; xxx limit.. + (mew-decode-syntax-arrange-warning) + (mew-header-goto-end) + (mew-header-arrange (point-min) (point)) + (setq mew-decode-syntax (mew-decode-syntax-rfc822))) + (error ())) + (mew-summary-display-postscript 'no-hook))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Analyze again +;;; + +(defun mew-summary-analyze-again-alternative (&optional arg) + "This command analyzes the message again with +'mew-use-alternative' and 'mew-use-text-body' reversed." + (interactive "P") + (mew-summary-goto-message) + (let ((mew-use-alternative (not mew-use-alternative)) + (mew-use-text-body (not mew-use-text-body))) + (mew-summary-analyze-again arg))) + +(defun mew-summary-analyze-again (&optional arg) + "1) If this command executed on a message, the cache of the +message is removed and the message is analyzed then displayed. + +1a) If the size of the current message exceeds +'mew-file-max-size', MIME analysis is skipped then the beginning +of the raw message is displayed. In this situation, this command +analyzes the current message without the limitation then displays +it. + +1b) If the length of a header exceeds 'mew-header-max-length', a +broken message is displayed. In this situation, this command +analyzes the current message without the limitation then displays +it. + +1c) If the current message is displayed by '\\\\[mew-summary-analyze-again-alternative]', this command gets it back to +the normal display. + +1d) If 'mew-use-text/html' is nil, its HTML body is displayed as +is. In this situation, this command analyzes the HTML body and +displays it. + +1e) If called with '\\[universal-argument]', analyze the message +with 'mew-decode-broken' reversed. + +2) If this command is called on a part, the part is displayed again. + +2a) If 'mew-use-text/html' is nil, its HTML part is displayed as +is. In this situation, this command analyzes the HTML part and +displays it." + (interactive "P") + (mew-summary-msg-or-part + (if (mew-folder-draftp (mew-summary-folder-name)) + (mew-summary-display 'redisplay) + (let ((mew-decode-broken + (if arg (not mew-decode-broken) mew-decode-broken)) + (mew-use-text/html t) + (mew-use-text/xml t) + (fld (mew-summary-folder-name)) + (vfld (mew-summary-folder-name 'ext)) + (msg (mew-summary-message-number2)) + (part (mew-syntax-nums)) + (win (selected-window)) + (sumbuf (current-buffer)) + cache) + (unwind-protect + (progn + (mew-summary-toggle-disp-msg 'on) + (mew-window-configure 'message) + ;; message buffer + (if part + (progn + (setq cache (mew-cache-hit fld msg)) + (mew-summary-display-part cache part)) + (mew-cache-delete2 fld msg) + (mew-summary-goto-message) + (mew-current-set fld msg part) + (mew-minfo-set-summary vfld) + (mew-decode-syntax-clear) + (mew-decode-syntax-delete) + (mew-summary-cache-message fld msg sumbuf 'unlimit))) + (if (mew-xinfo-get-decode-err) + (message "MIME decoding error: %s" (mew-xinfo-get-decode-err))) + (mew-message-mode-line fld msg) + (select-window win) + ;; summary buffer + (mew-summary-cursor-postscript)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Display ASIS +;;; + +(defun mew-summary-display-asis () + "Insert this message or part into Message mode in the raw format. +This command treats PGP/MIME transparent. That is an encrypted/signed +part is displayed as a decrypted/verified part. Also, if this command +is used for a message whose entire body is encrypted/signed, +a decrypted/verified body is displayed." + (interactive) + (mew-summary-msg-or-part + (let* ((fld (mew-summary-folder-name)) + (vfld (mew-summary-folder-name 'ext)) + (msg (mew-summary-message-number2)) + (nums (mew-syntax-nums)) + (win (selected-window)) + (buf (generate-new-buffer mew-buffer-prefix)) + (cbuf (mew-cache-hit fld msg)) + (alt (if cbuf + (mew-cache-dinfo-get-use-alt cbuf) + mew-use-alternative)) + syntax ct begin end) + (with-current-buffer buf + (mew-erase-buffer) + (mew-insert-message fld msg mew-cs-text-for-read nil) + (mew-dinfo-set nil t nil alt) + (mew-decode-for-edit) + (setq syntax (mew-syntax-get-entry mew-decode-syntax nums))) + (setq ct (mew-syntax-get-value (mew-syntax-get-ct syntax) 'cap)) + (setq begin (mew-syntax-get-begin syntax)) + (setq end (mew-syntax-get-end syntax)) + (unwind-protect + (progn + (mew-summary-toggle-disp-msg 'on) + (mew-window-configure 'message) + ;; message buffer + (mew-current-set fld msg nums) + (mew-minfo-set-summary vfld) + ;; The following codes are not necessary. + ;; (mew-decode-syntax-clear) + ;; (mew-decode-syntax-delete) + (mew-elet + (mew-summary-display-preamble) + (mew-decode-syntax-copy buf) + (cond + ((string= ct mew-ct-msg) + (if nums + (setq end (mew-syntax-get-end (mew-syntax-get-part syntax))) + (setq end nil)) + ;; We need to keep properties of a header. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring buf begin end) + (goto-char (point-min)) + (mew-header-goto-end) + (mew-header-arrange (point-min) (point)) + (setq mew-decode-syntax (mew-decode-syntax-rfc822))) + (t + ;; We need to keep composite properties of charset. + ;; This must be "insert-buffer-substring". + (insert-buffer-substring buf begin end) + (goto-char (point-min))))) + (mew-summary-display-postscript 'no-hook)) + (mew-remove-buffer buf) + (mew-message-mode-line fld msg) + (select-window win) + ;; summary buffer + (mew-summary-cursor-postscript))))) + +(defun mew-summary-find-file (&optional arg) + "Open this message and makes it read-only. +If called with '\\[universal-argument]', it stays writable." + (interactive "P") + (mew-summary-msg-or-part + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (file (mew-expand-msg fld msg))) + (when (mew-sinfo-get-disp-msg) + (mew-summary-toggle-disp-msg)) + (mew-frwlet (if (mew-folder-draftp fld) mew-cs-m17n mew-cs-autoconv) mew-cs-dummy + (if arg + (switch-to-buffer (mew-find-file-noselect2 file)) + (view-buffer (mew-find-file-noselect2 file) 'kill-buffer)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Trace Path +;;; + +(defun mew-summary-trace-path () + "Parse the Received: fields and display them in Message mode." + (interactive) + (mew-summary-msg-or-part + (let* ((win (selected-window)) + (fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + lst svr-date (snd "?") (rcv "?") last svr date tmp) + (mew-summary-set-message-buffer fld msg) + ;; message buffer or cache buffer + (setq lst (nreverse (mew-header-get-value mew-received: 'as-list))) + (set-buffer (mew-buffer-message)) + ;; message buffer + (mew-summary-display-preamble) + (save-excursion + (dolist (ent lst) + (while (string-match "\n" ent) + (setq ent (replace-match "" nil t ent))) + (setq svr-date (mew-split ent ?\;)) + (mew-set '(svr date) svr-date) + (unless date + ;; for broken MTAs + (if (string-match "Mon\\|Tue\\|Wed\\|Thu\\|Fri\\|Sat\\|Sun" ent) + (setq date (substring ent (match-beginning 0))))) + (if date (setq date (mew-time-rfc-to-sortkey date 'tzadj))) + (unless date (setq date "19700101000000")) + (setq tmp (cons (list date svr) tmp)) + (cond + ((string-match "(\\(qmail [0-9]+\\)" svr) + (setq rcv (match-string 1 svr))) + ((string-match "by[ \t]+\\([^() \t\n]+\\)" svr) + (setq rcv (match-string 1 svr)) + (if (string-match "from[ \t]+\\([^() \t\n]+\\).*\\([[][.0-9]+[]]\\)" svr) + (setq snd (format "%s %s" (match-string 1 svr) (match-string 2 svr))) + (if (string-match "from[ \t]+\\([^() \t\n]+\\)" svr) + (setq snd (match-string 1 svr)))) + (when (and (string= snd "unknown") + (string-match "from unknown (HELO \\([^() \t\n]+\\))" svr)) + (setq snd (concat (match-string 1 svr) "(unknown)")))) + ((string-match "[ \t]*\\([^() \t\n]+\\)" svr) + (setq rcv (match-string 1 svr)) + (if (string-match "from[ \t]*\\([^() \t\n]+\\)" svr) + (setq snd (match-string 1 svr))))) + (mew-elet + (insert date) + (beginning-of-line) + (forward-char 4) + (insert "/") + (forward-char 2) + (insert "/") + (forward-char 2) + (insert " ") + (forward-char 2) + (insert ":") + (forward-char 2) + (insert ":") + (forward-char 2) + (insert " (" (mew-time-tmzn-int) ") ") + (if (and snd (not (string= snd last))) (insert snd)) + (insert " => ") + (if rcv (insert rcv)) + (insert "\n") + (setq last rcv) + (setq snd "?" rcv "?")))) + (mew-summary-display-postscript 'no-hook) + (select-window win)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Direction +;;; + +(defun mew-summary-next () + (if (eq (mew-sinfo-get-direction) 'up) + (mew-summary-up) + (mew-summary-down))) + +(defvar mew-summary-down-function 'forward-line + "This function is called by mew-summary-down(). This is a very +ad-hoc solution for putting the review mark on a thread.") + +(defun mew-re-search-forward-visibile (regex) + (catch 'loop + (while (re-search-forward regex nil t) + (unless (eq (get-text-property (point) 'invisible) t) + (throw 'loop t))))) + +(defun mew-re-search-backward-visible (regex) + (catch 'loop + (while (re-search-backward regex nil t) + (unless (eq (get-text-property (point) 'invisible) t) + (throw 'loop t))))) + +(defun mew-summary-down () + (funcall mew-summary-down-function) + (cond + ((mew-re-search-forward-visibile mew-regex-msg-or-part) + (mew-thread-move-cursor) + (mew-sinfo-set-direction 'down) + t) + (t + (mew-decode-syntax-delete) + (forward-line -1) ;; for invisible + (unless (pos-visible-in-window-p) + ;; This ensures that some messages are displayed in Summary. + (recenter)) + (mew-thread-move-cursor) + (mew-summary-reset) + (message "No more messages") + nil))) + +(defun mew-summary-up () + (beginning-of-line) + (cond + ((mew-re-search-backward-visible mew-regex-msg-or-part) + (mew-thread-move-cursor) + (mew-sinfo-set-direction 'up) + t) + (t + (mew-thread-move-cursor) + (mew-decode-syntax-delete) + (mew-summary-reset) + (message "No more messages") + nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Direction 2 +;;; + +(defun mew-summary-display-next () + (if (mew-summary-next) (mew-summary-display))) + +(defun mew-summary-display-up (&optional arg) + "Move to above then display. Targets includes parts, messages +marked with '*', and non-marked messages. When called with '\\[universal-argument]', +parts are skipped." + (interactive "P") + (beginning-of-line) + (when arg + (mew-summary-goto-message) + (mew-decode-syntax-delete)) + (if (mew-summary-up) (mew-summary-display))) + +(defun mew-summary-display-down (&optional arg) + "Move to below then display. Targets includes parts, messages +marked with '*', and non-marked messages. When called with '\\[universal-argument]', +parts are skipped." + (interactive "P") + (when arg + (mew-summary-goto-message) + (mew-decode-syntax-delete)) + (if (mew-summary-down) (mew-summary-display))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Paging +;;; + +(defun mew-summary-prev-page () + "\\Back-scroll this message. Unnecessary header fields are hidden +over the window. Type '\\[mew-summary-prev-page]' to see them when a message is displayed." + (interactive) + (mew-summary-scroll-down 'fullpage)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Scrolling +;;; + +(defun mew-summary-scroll-up () + "Make this message scroll up with one line." + (interactive) + (mew-summary-msg-or-part + (let* ((win (selected-window)) + (msg (mew-summary-message-number)) + (part (mew-syntax-nums)) + (fid (mew-frame-id)) + (omsg (mew-current-get-msg fid)) + (opart (mew-current-get-part fid))) + ;; xxx how about folder check? + (if (or (and msg (string= msg omsg) (null part) (null opart)) + (and part (equal part opart))) ;; MUST be equal + (unwind-protect + (progn + (mew-summary-toggle-disp-msg 'on) + (mew-window-configure 'message) + ;; message buffer + (mew-message-next-page 1)) + (select-window win)) + (call-interactively 'mew-summary-display))))) + +(defun mew-summary-scroll-down (&optional fullpage) + "Make this message scroll down with one line." + (interactive) + (mew-summary-msg-or-part + (let* ((win (selected-window)) + (msg (mew-summary-message-number)) + (part (mew-syntax-nums)) + (fid (mew-frame-id)) + (omsg (mew-current-get-msg fid)) + (opart (mew-current-get-part fid))) + ;; xxx how about folder check? + (if (or (and msg (string= msg omsg) (null part) (null opart)) + (and part (equal part opart))) ;; MUST be equal + (unwind-protect + (progn + (mew-summary-toggle-disp-msg 'on) + (mew-window-configure 'message) + ;; message buffer + (mew-message-prev-page (if fullpage nil 1))) + (select-window win)) + (call-interactively 'mew-summary-display))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Cursor motion +;;; + +(defun mew-summary-next-line (&optional arg) + "Go to the next line." + (interactive "p") + (or arg (setq arg 1)) + (if (< arg 0) + (mew-summary-previous-line (- arg)) + (let (col) + (if (eq last-command this-command) + (setq col (mew-sinfo-get-column))) + (unless col + (setq col (current-column)) + (mew-sinfo-set-column col)) + (while (> arg 0) + (forward-line) + (while (or (looking-at mew-regex-thread-separator) + (eq (get-text-property (point) 'invisible) t)) + (forward-line)) + (setq arg (1- arg))) + (move-to-column col)))) + +(defun mew-summary-previous-line (&optional arg) + "Go to the previous line." + (interactive "p") + (or arg (setq arg 1)) + (if (< arg 0) + (mew-summary-next-line (- arg)) + (let (col) + (if (eq last-command this-command) + (setq col (mew-sinfo-get-column))) + (unless col + (setq col (current-column)) + (mew-sinfo-set-column col)) + (while (> arg 0) + (forward-line -1) ;; for invisible + (while (or (looking-at mew-regex-thread-separator) + (eq (get-text-property (point) 'invisible) t)) + (forward-line -1)) + (setq arg (1- arg))) + (move-to-column col)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mouse +;;; + +(defun mew-summary-mouse-show (e) + "Mouse version of 'mew-summary-display'." + (interactive "e") + (mouse-set-point e) + (beginning-of-line) + (call-interactively 'mew-summary-display)) + +(provide 'mew-summary2) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-summary2.el ends here diff --git a/elpa/mew-20150813.2354/mew-summary3.el b/elpa/mew-20150813.2354/mew-summary3.el new file mode 100644 index 00000000..fdf03780 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-summary3.el @@ -0,0 +1,491 @@ +;;; mew-summary3.el --- Summary mode for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Subfunctions +;;; + +(defmacro mew-summary-prepare-draft (&rest body) + "Common procedure to prepare a draft." + `(progn + (unwind-protect + (let ((inhibit-quit t)) + ,@body + (mew-redraw) + (if quit-flag (setq quit-flag nil))) + (mew-draft-save-buffer)) ;; to make sure not to use this draft again + (mew-set-file-modes (buffer-file-name)) + (mew-touch-folder mew-draft-folder) + (message "Draft is prepared"))) + +(defun mew-summary-prepare-three-windows () + "Prepare three windows: Summary mode, Message mode, and Draft mode" + (unless mew-use-other-frame-for-draft + (if (get-buffer (mew-buffer-message)) + (delete-windows-on (mew-buffer-message))) + (cond + ((< (window-height) 25) + (delete-other-windows)) + (mew-use-full-window + (mew-delete-other-window))) + (let ((split-window-keep-point t)) + (split-window-vertically)))) + +(defun mew-draft-multi-copy (draft files) + (let* ((attach (mew-draft-to-attach draft)) + (attachdir (mew-expand-folder attach))) + (mew-check-directory attachdir) + (dolist (file files) + (if mew-use-symbolic-link-for-forwarding + (mew-symbolic-link file (mew-folder-new-message attach)) + (copy-file file (mew-folder-new-message attach)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sending +;;; + +(defun mew-summary-set-message-buffer (fld msg) + ;; need to make a cache or a message buffer. + (mew-summary-toggle-disp-msg 'on) + ;; Since we will switch to a draft buffer, + ;; the window of the draft buffer must not be deleted. + ;; So, binding mew-use-full-window to nil. + (let ((mew-use-full-window nil)) + (mew-summary-display)) + (set-buffer (mew-buffer-message)) + ;; header exists only in cache if multipart + (unless (mew-msghdr-p) (set-buffer (mew-cache-hit fld msg)))) + +(defun mew-summary-write (&optional from) + "Write a message. A new draft is prepared in Draft mode. +If called with '\\[universal-argument]', the From: address of +the current message is copied to To: in a draft." + (interactive "P") + (if (null from) + (mew-summary-send) + (mew-summary-msg-or-part + (let ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + to) + (if (not (and fld msg)) + (message "No message") + (save-excursion + (mew-summary-set-message-buffer fld msg) + (setq to (mew-addrstr-parse-address (mew-header-get-value mew-from:))) + (if (mew-is-my-address mew-regex-my-address-list to) + (setq to (mew-addrstr-parse-address (mew-header-get-value mew-to:))))) + (mew-summary-send to) + (goto-char (point-min)) + (if (search-forward mew-subj: nil t) + (end-of-line))))))) + +(defun mew-summary-send (&optional to cc subject newsgroups) + "Write a message. A new draft is prepared in Draft mode." + (interactive) + (let ((draft (mew-folder-new-message mew-draft-folder)) + asked) + (if (and (mew-summary-physical-folder) + (mew-folder-nntpp (mew-summary-physical-folder))) + (if (null newsgroups) (setq newsgroups "")) + (when (and mew-ask-to (null to)) + (setq to (mew-input-address (concat mew-to: " "))) + (setq asked t)) + (when (and mew-ask-cc (null cc)) + (setq cc (mew-input-address (concat mew-cc: " "))) + (setq asked t))) + (mew-current-set-window-config) + (mew-window-configure 'draft) + (mew-summary-prepare-draft + (mew-draft-find-and-switch draft) + (mew-delete-directory-recursively (mew-attachdir draft)) + (mew-draft-header subject nil to cc newsgroups nil nil nil asked) + (mew-draft-mode) + (run-hooks 'mew-draft-mode-newdraft-hook)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Replying +;;; + +(defun mew-subject-simplify (str &optional act-lst no-replace) + "A function to simplify a value of Subject: according to +'mew-subject-simplify-replace-alist'." + (let ((case-fold-search t) + (action-list (or act-lst mew-subject-simplify-replace-alist)) + (ret str) + regexp replace) + (dolist (action action-list) + (setq regexp (mew-alist-get-key action)) + (setq replace (if no-replace nil (mew-alist-get-value action))) + (if (string-match regexp ret) + (setq ret (replace-match (if replace (eval replace) "") nil t ret)))) + ret)) + +(defun mew-subject-simplify-ml (str) + "Remove leading \"[...]\" and \"(...)\" from subject line." + (if (string-match "^[[(][^])]+[])][ \t]*" str) + (substring str (match-end 0)) + str)) + +(defun mew-subject-simplify2 (str) + (mew-subject-simplify + (mew-subject-simplify-ml + (mew-subject-simplify str nil 'no-replace)) nil 'no-replace)) + +(defun mew-to-cc-newsgroups (replysender) + (let (alist key tcn flds to cc newsgroups fromme func) + (cond + (replysender + (setq alist mew-reply-sender-alist) + (setq func 'mew-header-parse-address-list2)) + ((mew-is-my-address mew-regex-my-address-list + (mew-header-parse-address mew-from:)) + (setq fromme t) + (setq alist mew-reply-fromme-alist) + ;; If from me, let's leave the "anonymous:;" keyword. + (setq func 'mew-header-parse-address-list)) + (t ;; reply all + (setq alist mew-reply-all-alist) + (setq func 'mew-header-parse-address-list2))) + (catch 'loop + (dolist (ent alist) + (setq key (car ent)) + (setq ent (cdr ent)) + (when (or (eq key t) + (and (stringp key) (mew-header-get-value key)) + (and (listp key) + (string= (mew-header-get-value (nth 0 key)) + (nth 1 key)))) + (dolist (tcn-flds ent) + (setq tcn (car tcn-flds)) + (setq flds (cdr tcn-flds)) + (cond + ((mew-case-equal tcn mew-to:) + (setq to (funcall func flds))) + ((mew-case-equal tcn mew-cc:) + (setq cc (funcall func flds))) + ((mew-case-equal tcn mew-newsgroups:) + (setq newsgroups (funcall func flds))))) + (throw 'loop nil)))) + (list to cc newsgroups fromme))) + +(defun mew-in-reply-to-references () + (let ((old-message-id (mew-idstr-get-first-id + (mew-header-get-value mew-message-id:))) + (old-in-reply-to (mew-idstr-get-first-id + (mew-header-get-value mew-in-reply-to:))) + (old-references (mew-idstr-to-id-list + (mew-header-get-value mew-references:) 'rev)) + id-list in-reply-to references) + ;; Assuming that In-Reply-To: contains one ID. + (when old-message-id + ;; when old-message-id is nil, + ;; we do not care even if old-references exist. + (setq in-reply-to old-message-id) + (cond + (old-references + (setq id-list old-references) + (mew-addq id-list old-in-reply-to) + (mew-addq id-list old-message-id) + (setq id-list (nreverse id-list))) + (t + (setq id-list (list old-message-id)) + (mew-addq id-list old-in-reply-to))) + (setq references (mew-id-list-to-idstr id-list))) + (list in-reply-to references))) + +(defun mew-summary-reply (&optional replysender) + "Reply to this message. A new draft is prepared in Draft mode. +Values of To:, Cc:, and Newsgroups: are prepared according to +three alists. + +\(1) If called with '\\[universal-argument]', replying to the + sender/poster only. In this case, 'mew-reply-sender-alist' is used. + +\(2) If this message is sent by ME, you probably intend to reply with + the original header. In this case, 'mew-reply-fromme-alist' is used. + +\(3) Otherwise, replying to all people listed. In this case, + 'mew-reply-all-alist' is used. + +The default value of 'mew-reply-sender-alist' is as follows: + + '((\"Reply-To:\" + (\"To:\" \"Reply-To:\" \"From:\")) + (t + (\"To:\" \"From:\"))) + +This is read as follows: + + (1.1) If Reply-To: exists, copy the values of Reply-To: + and From: to new To:. + (1.2) Otherwise, copy the value of From: to To:. + +If you would like to reply only to the address on Reply-To: (if any), +set 'mew-reply-sender-alist' to: + + '((\"Reply-To:\" + (\"To:\" \"Reply-To:\")) + (t + (\"To:\" \"From:\"))) + +The default value of 'mew-reply-fromme-alist' is as follows: + + '((t + (\"To:\" \"To:\") + (\"Cc:\" \"Cc:\") + (\"Newsgroups:\" \"Newsgroups:\")))) + +This is read as follows: + + (2.1) Copying the value of To: to new To: and + copying the value of Cc: to new Cc: and + copying the value of Newsgroups: to new Newsgroups:. + +The default value of 'mew-reply-all-alist' is as follows: + + '(((\"Followup-To:\" \"poster\") + (\"To:\" \"From:\")) + (\"Followup-To:\" + (\"Newsgroups:\" \"Followup-To:\" \"Newsgroups:\")) + (\"Newsgroups:\" + (\"Newsgroups:\" \"Newsgroups:\")) + (\"Reply-To:\" + (\"To:\" \"Reply-To:\" \"From:\") + (\"Cc:\" \"To:\" \"Cc:\" \"Apparently-To:\")) + (t + (\"To:\" \"From:\") + (\"Cc:\" \"To:\" \"Cc:\" \"Apparently-To:\"))) + +This is read as follows: + + (3.1) If the value of Followup-To: is \"poster\", copying the + value of From: to new To:. + (3.2) If Followup-To: exists, copying the values of + Followup-To: and Newsgroups: to new Newsgroups:. + (3.3) If Newsgroups: exists, copying the value of Newsgroups: + to Newsgroups:. + (3.4) If Reply-To: exists, copying the values of Reply-To: and + From: to new To:. And copying the values of To:, Cc: and + Apparently-To: to new Cc:. + + (3.5) Otherwise, copying the value of From: to new To:. And + copying the values of To:, Cc: and Apparently-To: to + new Cc:. + +You may want to set 'mew-reply-all-alist' to: + + '(((\"Followup-To:\" \"poster\") + (\"To:\" \"From:\")) + (\"Followup-To:\" + (\"Newsgroups:\" \"Followup-To:\")) + (\"Newsgroups:\" + (\"Newsgroups:\" \"Newsgroups:\")) + (\"Reply-To:\" + (\"To:\" \"Reply-To:\")) + (t + (\"To:\" \"From:\") + (\"Cc:\" \"To:\" \"Cc:\" \"Apparently-To:\"))) +" + (interactive "P") + (mew-summary-msg-or-part + (mew-summary-not-in-draft + (mew-current-set-window-config) + (let ((owin (selected-window)) + (fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (split-width-threshold nil) + cwin cbuf draft case + subject to cc newsgroups in-reply-to references + encrypted fromme ret) + (if (string= (mew-summary-folder-name) mew-draft-folder) + (message "Cannot reply to draft message") + (setq draft (mew-folder-new-message mew-draft-folder)) + (mew-summary-prepare-draft + (mew-summary-prepare-three-windows) + (mew-draft-find-and-switch draft t) + (mew-delete-directory-recursively (mew-attachdir draft)) + (setq cwin (selected-window)) ;; draft + (setq cbuf (window-buffer cwin)) + (select-window owin) + (mew-summary-set-message-buffer fld msg) + (when mew-case-guess-when-replied + (setq case (mew-draft-get-case-by-guess + mew-case-guess-when-replied-alist))) + (setq encrypted (mew-syntax-encrypted-p mew-decode-syntax)) + (save-restriction + ;; if body contains ^L, header is not accessible. + ;; mew-header-* cannot widen essentially. So widen here. + (widen) + ;; now cache buffer + ;; + ;; Subject: + (setq subject (mew-header-get-value mew-subj:)) + (when subject + (setq subject (concat mew-reply-string subject)) + (setq subject (mew-subject-simplify subject))) + ;; + ;; To:, Cc:, Newsgroups: + (setq ret (mew-to-cc-newsgroups replysender)) + (mew-set '(to cc newsgroups fromme) ret) + ;; + ;; In-Reply-To:, References: + (setq ret (mew-in-reply-to-references)) + (mew-set '(in-reply-to references) ret)) + ;; + (if (window-live-p cwin) + (select-window cwin) ;; draft + (pop-to-buffer cbuf)) + (when case + (if mew-case-guess-addition + (setq case (mew-draft-add-case (mew-tinfo-get-case) case))) + (mew-tinfo-set-case case)) + (mew-draft-header subject nil to cc newsgroups in-reply-to references + nil fromme) + (when (eq mew-summary-reply-position 'body) + (goto-char (mew-header-end)) + (forward-line)) + (mew-draft-mode encrypted) + (run-hooks 'mew-draft-mode-newdraft-hook))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Replaying with citation +;;; + +(defun mew-summary-reply-with-citation (&optional replysender) + "Answer to this message. A new draft is prepared in Draft mode. +And this message is automatically cited. See also 'mew-summary-reply'." + (interactive "P") + (mew-summary-msg-or-part + (mew-summary-not-in-draft + (let ((mew-summary-reply-position nil) + (mew-message-citation-frame-id (mew-frame-id))) + (mew-summary-reply replysender) + ;; mew-draft-mode-hook may insert text. + (save-excursion + (goto-char (point-max)) + (run-hooks 'mew-before-cite-hook) + (mew-draft-cite))) + ;; the cursor is after To: + (cond + ((eq mew-summary-reply-with-citation-position 'body) + (goto-char (mew-header-end)) + (forward-line)) + ((eq mew-summary-reply-with-citation-position 'end) + (goto-char (point-max))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Forwarding +;;; + +(defun mew-summary-forward () + "Forward this message to a third person. A new draft is prepared in +Draft mode and this message is automatically attached." + (interactive) + (mew-summary-msg-or-part + (mew-summary-not-in-draft + (mew-current-set-window-config) + (let* ((owin (selected-window)) + (fld (mew-summary-folder-name)) + (msg (mew-summary-message-number2)) + (file (mew-expand-msg fld msg)) + (draft (mew-folder-new-message mew-draft-folder)) + (draftdir (file-name-nondirectory draft)) + (to (and mew-ask-to (mew-input-address (concat mew-to: " ")))) + (cc (and mew-ask-cc (mew-input-address (concat mew-cc: " ")))) + (asked (or mew-ask-to mew-ask-cc)) + subject fwsubject cwin) + (mew-summary-prepare-draft + (mew-summary-prepare-three-windows) + (mew-draft-find-and-switch draft t) + (mew-delete-directory-recursively (mew-attachdir draft)) + (setq cwin (selected-window)) ;; draft + (select-window owin) + (mew-summary-set-message-buffer fld msg) + (setq subject (mew-header-get-value mew-subj:)) + (if subject + (setq fwsubject (mew-subject-simplify (concat mew-forward-string subject)))) + (select-window cwin) ;; draft + ;; + (mew-draft-header fwsubject 'nl to cc nil nil nil nil asked) + (mew-draft-mode) + (run-hooks 'mew-draft-mode-newdraft-hook) + (mew-draft-multi-copy draft (list file)) + (setq mew-encode-syntax (mew-encode-syntax-initial-multi draftdir 1)) + (save-excursion + (mew-draft-prepare-attachments t))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Multi forwarding +;;; + +(defun mew-summary-multi-forward () + "Forward messages marked with '*' to a third person. A new draft +is prepared in Draft mode and this message is automatically +attached." + (interactive) + (mew-summary-multi-msgs + (mew-summary-not-in-draft + (mew-current-set-window-config) + (let* ((draft (mew-folder-new-message mew-draft-folder)) + (draftdir (file-name-nondirectory draft)) + (to (and mew-ask-to (mew-input-address (concat mew-to: " ")))) + (cc (and mew-ask-cc (mew-input-address (concat mew-cc: " ")))) + (asked (or mew-ask-to mew-ask-cc))) + (mew-summary-prepare-draft + (mew-summary-prepare-three-windows) + (mew-draft-find-and-switch draft t) + (mew-delete-directory-recursively (mew-attachdir draft)) + (mew-draft-header nil 'nl to cc nil nil nil nil asked) + (mew-draft-mode) + (run-hooks 'mew-draft-mode-newdraft-hook) + (mew-draft-multi-copy draft FILES) + (setq mew-encode-syntax + (mew-encode-syntax-initial-multi draftdir (length FILES))) + (save-excursion + (mew-draft-prepare-attachments t))))))) + +(provide 'mew-summary3) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-summary3.el ends here diff --git a/elpa/mew-20150813.2354/mew-summary4.el b/elpa/mew-20150813.2354/mew-summary4.el new file mode 100644 index 00000000..3e900cc9 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-summary4.el @@ -0,0 +1,1229 @@ +;;; mew-summary4.el --- Summary mode for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Variables +;;; + +(defvar mew-last-shell-command "") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Switching to folder +;;; + +(defun mew-summary-switch-to-folder (case:folder &optional func) + (let ((ofolder (mew-summary-folder-name 'ext))) + (cond + ((get-buffer case:folder) + (switch-to-buffer case:folder) + (mew-set-buffer-cs mew-cs-m17n) + (unless (mew-folder-virtualp case:folder) (mew-summary-folder-cache-load)) + (unless (string= ofolder case:folder) (mew-window-configure 'summary)) + nil) ;; existing folder + (t + (funcall (or func 'switch-to-buffer) (get-buffer-create case:folder)) + (kill-all-local-variables) + (mew-set-buffer-cs mew-cs-m17n) + (mew-buffers-setup case:folder) + (let* ((case (mew-case:folder-case case:folder)) + (folder (mew-case:folder-folder case:folder)) + (inboxp (string= folder (mew-proto-inbox-folder folder (or case mew-case))))) + (mew-sinfo-set-case case) + (mew-sinfo-set-folder folder) + (mew-sinfo-set-inboxp inboxp)) + (if (mew-folder-virtualp case:folder) + (mew-virtual-mode) + (mew-summary-mode) + (if mew-summary-trace-directory (cd (mew-expand-folder case:folder))) + (mew-summary-folder-cache-load)) + (mew-window-configure 'summary) + t)))) ;; new-folder + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Moving to folder +;;; + +(defun mew-summary-goto-folder (&optional goend) + "Go to the folder which you specify. If executed with +'\\[universal-argument]', the cursor always goes to the bottom of +Summary mode." + (interactive "P") + (let* ((proto (mew-proto-to-go (mew-summary-folder-name 'ext))) + (case1 (car (mew-summary-case-proto))) + (inbox (mew-proto-inbox-folder proto case1)) + (case:folder (mew-input-folder case1 inbox)) + case folder buf win frame folder-alist) + (if (null case:folder) + (message "The folder does not exist") + (setq case (mew-case:folder-case case:folder)) + (setq folder (mew-case:folder-folder case:folder)) + (cond + ((mew-folder-imapp folder) + (setq folder-alist (mew-imap-folder-alist case)) + ;; + (unless (or (assoc folder folder-alist) + (assoc (concat folder (mew-imap-separator case)) folder-alist)) + (message "\"%s\" does not exist. %s" case:folder + (mew-substitute-for-summary "Type '\\[universal-argument]\\[mew-status-update]' to collect IMAP folders")) + (setq case:folder nil))) + ((mew-folder-nntpp folder) + (unless (assoc folder (mew-nntp-folder-alist case)) + (message "\"%s\" does not exist. %s" case:folder + (mew-substitute-for-summary "Type '\\[universal-argument]\\[mew-status-update]' to collect newsgroups")) + (setq case:folder nil)))) + (when case:folder + (when mew-use-other-frame-for-summary + (if (setq buf (get-buffer case:folder)) + (if (setq win (get-buffer-window buf 0)) + (progn + (setq frame (window-frame win)) + (raise-frame frame) + (select-frame frame) + ;; Ensure, if possible, that frame gets input focus. + (mew-focus-frame frame)) + (select-frame (make-frame))) + (select-frame (make-frame)))) + (mew-summary-visit-folder case:folder goend))))) + +(defun mew-summary-visit-folder (folder &optional goend no-ls) + (let ((dir (mew-expand-folder folder)) + new-folder scanp) + (cond + ((mew-folder-virtualp folder) + (if (get-buffer folder) + (if (mew-virtual-thread-p folder) + (if (mew-thread-cache-valid-p folder) + (mew-summary-switch-to-folder folder) + (message "%s is old" folder)) + (mew-summary-switch-to-folder folder)) + (message "No such virtual folder: %s" folder))) + (t ;; local/remote folders + (if (null dir) + (message "Folder is wrong") + (cond + ((mew-folder-remotep (mew-case:folder-folder folder)) + (unless (file-directory-p dir) + (mew-make-directory dir)) + (setq scanp t)) + (t ;; +, ~, /, drive letter + (if (file-directory-p dir) + (setq scanp t) + (message "No such folder %s" folder)))) + (when scanp + (if no-ls + (progn + (mew-summary-switch-to-folder folder) + (if goend (goto-char (point-max))) + (if (pos-visible-in-window-p (point-min)) + (mew-summary-cook-window))) + (setq new-folder (mew-summary-switch-to-folder folder)) + (if (and (mew-summary-ls nil (or goend new-folder)) + (pos-visible-in-window-p (point-min))) + (mew-summary-cook-window))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Going to a line +;;; + +(defun mew-summary-goto-line (&optional arg) + "Jump to a line according to the number which you input. +If 'mew-summary-goto-line-then-display' is non-nil, +the message is then displayed." + (interactive "P") + (if arg + (let ((msg (read-string "Message No.: " ""))) + (while (not (string-match mew-regex-message-files3 msg)) + (setq msg (read-string "Message No.: " ""))) + (when (mew-summary-search-msg msg) + (if mew-summary-goto-line-then-display + (mew-summary-display)))) + (let ((line (string-to-number (read-string "Line No.: " "")))) + (when (/= line 0) + (goto-char (point-min)) (forward-line (1- line)) + (if mew-summary-goto-line-then-display + (mew-summary-display)))))) + +(defun mew-summary-goto-original-message () + "Go to the original message in the original Summary mode" + (interactive) + (cond + ((mew-summary-p) + (message "This is the original")) + ((mew-virtual-p) + (let ((folder (mew-folder-path-to-folder (mew-summary-folder-name) 'has-proto)) + (msg (mew-summary-message-number))) + (when folder + (mew-summary-visit-folder folder nil 'no-ls) + (if (mew-summary-search-msg msg) + (mew-summary-display) + (message "No original message found"))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Moving to Message mode +;;; + +(defun mew-summary-goto-msg-mode () + "Go to Header mode." + (interactive) + (let (msgp) + (with-current-buffer (window-buffer (next-window)) + (if (mew-message-p) (setq msgp t))) + (if msgp + (other-window 1) + (message "No Message mode displayed")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Moving to +draft +;;; + +(defun mew-max-draft-buffer () + (let* ((draft-dir (file-name-as-directory mew-draft-folder)) + (regex (mew-folder-regex draft-dir)) + (bufs (mew-buffer-list regex)) + (msgregex (format "\\([0-9]+\\)\\(%s\\)?$" mew-suffix)) + nums n) + (setq nums (mapcar (lambda (x) (string-match msgregex x) (string-to-number (mew-match-string 1 x))) bufs)) + (dolist (num nums) + (if (or (null n) (< n num)) + (setq n num))) + (and n (format "%s%d%s" draft-dir n (if mew-use-suffix mew-suffix ""))))) + +(defun mew-summary-jump-to-draft-buffer () + "Jump to one of drafts if exists." + (interactive) + (let* ((draft (mew-max-draft-buffer)) buf) + (if (null draft) + (message "No draft buffer exists!") + (setq buf (mew-input-draft-buffer draft)) + (if (get-buffer buf) + (switch-to-buffer buf) + (message "No such draft buffer!"))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Moving to top and bottom +;;; + +(defun mew-summary-jump-top () + "Go to the beginning of this Summary mode. +If 'mew-summary-jump-top-then-display' is non-nil, +the top message is then displayed." + (interactive) + (if mew-use-push-mark (mew-push-mark)) + (goto-char (point-min)) + (if mew-summary-jump-top-then-display + (mew-summary-display))) + +(defun mew-summary-jump-bottom () + "Go to the end of this Summary mode. +If 'mew-summary-jump-bottom-then-display' is non-nil, +the top message is then displayed." + (interactive) + (if mew-use-push-mark (mew-push-mark)) + (goto-char (point-max)) + (if (and (mew-summary-exclusive-p 'no-msg) + (not (bobp)) + (mew-sinfo-get-disp-msg)) + (forward-line -1)) + (if mew-summary-jump-bottom-then-display + (mew-summary-display))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Moving to the marker +;;; + +(defun mew-summary-exchange-point () + "\\Get back to the position before typing '\\[mew-summary-retrieve]' or '\\[mew-summary-ls]'." + (interactive) + (mew-summary-only + (let ((pos (mew-sinfo-get-ret-pos))) + (if pos (goto-char pos))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Searching +;;; + +(defun mew-summary-isearch-forward (&optional arg) + "Incremental search forward in Message mode." + (interactive "P") + (let ((cwin (get-buffer-window (current-buffer))) + (mwin (get-buffer-window (mew-buffer-message)))) + (if (not mwin) + (message "No message is displayed") + (select-window mwin) + (unwind-protect + (progn + (widen) + (isearch-forward arg) + (mew-message-narrow-to-page)) + (select-window cwin))))) + +(defun mew-summary-isearch-backward (&optional arg) + "Incremental search backward in Message mode." + (interactive) + (let ((cwin (get-buffer-window (current-buffer))) + (mwin (get-buffer-window (mew-buffer-message)))) + (if (not mwin) + (message "No message is displayed") + (select-window mwin) + (unwind-protect + (progn + (widen) + (isearch-backward arg) + (mew-message-narrow-to-page)) + (select-window cwin))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Pipe +;;; + +(defun mew-summary-pipe-message (prefix command) + "Send the content of Message buffer to a command via pipe. +If called with '\\[universal-argument]', the body of the message +\(excluding its header) is sent." + (interactive + (list current-prefix-arg + (read-string "Shell command on message: " mew-last-shell-command))) + (mew-summary-display 'redisplay) + (when (or (not mew-ask-pipe) + (y-or-n-p "Send this message to pipe? ")) + (with-current-buffer (mew-buffer-message) + (save-restriction + (widen) + (if (string= command "") (setq command mew-last-shell-command)) + (goto-char (point-min)) ; perhaps this line won't be necessary + (if prefix (search-forward "\n\n")) + (let ((max-mini-window-height 1)) + (shell-command-on-region (point) (point-max) command nil)) + (setq mew-last-shell-command command))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Print +;;; + +(defun mew-summary-print (&optional arg) + "Print the content of Message mode according to 'mew-print-function'. +If called with '\\[universal-argument]', you can specify a printer name." + (interactive "P") + (mew-summary-display 'redisplay) + (let ((printer-name (if arg + (read-string "Printer name: ") + printer-name)) + have-header str) + (with-current-buffer (mew-buffer-message) + (save-restriction + (widen) + (setq have-header (mew-msghdr-p)) + (setq str (buffer-substring (point-min) (point-max))))) + (when (y-or-n-p "Print this message? ") + (with-temp-buffer + (insert str) + (if have-header + (mew-header-delete-other-lines mew-field-for-printing)) + (funcall mew-print-function))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Saving a message to a file with header decoded +;;; + +(defun mew-summary-store (&optional askcs) + "Saving a buffer of Message mode to a file. +If executed with '\\[universal-argument]', coding-system is asked." + (interactive "P") + (mew-summary-display 'redisplay) + (let* ((file (mew-summary-input-file-name)) + (doit (if (file-exists-p file) + (if (y-or-n-p (format "File exists. Override it? ")) + t + nil) + t))) + (if (not doit) + (message "Not saved") + (let ((writecs (if askcs + (read-coding-system "Coding-system: ") + (default-value 'buffer-file-coding-system)))) + (with-current-buffer (mew-buffer-message) + (mew-frwlet mew-cs-dummy writecs + ;; do not specify 'no-msg + (write-region (point-min) (point-max) file))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; X-Face: +;;; + +(defun mew-summary-x-face () + "Display xface." + (interactive) + (mew-summary-msg + (let ((file (mew-make-temp-name)) xface) + (with-current-buffer (mew-buffer-message) + (setq xface (mew-header-get-value mew-x-face:))) + (when xface + (with-temp-buffer + (insert xface) + (mew-x-face-compface-to-xbm) + (mew-frwlet mew-cs-dummy mew-cs-text-for-write + (write-region (point-min) (point-max) file nil 'no-msg))) + (mew-mime-image-ext file))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Calling a command +;;; + +(defun mew-summary-cmd-msg () + "Executing an external command specifying this message as an +argument." + (interactive) + (mew-summary-msg-or-part + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (file (mew-expand-msg fld msg)) + (cmd-args (mew-input-command)) + (cmd (car cmd-args)) + (args (nconc (cdr cmd-args) (list file)))) + (message "Executing %s for %s..." cmd msg) + (apply 'call-process cmd nil nil nil args) + (message "Executing %s for %s...done" cmd msg)))) + +(defun mew-summary-cmd-msgs () + "Executing an external command specifying messages +marked with '*' as arguments." + (interactive) + (mew-summary-multi-msgs + (let* ((cmd-args (mew-input-command)) + (cmd (car cmd-args)) + (args (nconc (cdr cmd-args) FILES))) + (message "Executing %s ..." cmd) + (apply 'call-process cmd nil nil nil args) + (message "Executing %s ...done" cmd)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Citation +;;; + +(defun mew-summary-cite (&optional arg) + "Cite this message to one of drafts." + (interactive "P") + (let ((draft (mew-max-draft-buffer)) buf) + (if (null draft) + (message "No draft buffer exists!") + (setq buf (mew-input-draft-buffer draft)) + (if (get-buffer buf) + (with-current-buffer buf + (mew-draft-cite arg)) + (message "No such draft buffer!"))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Flushing the queue +;;; + +(defun mew-summary-send-message (&optional arg) + "If in +queue, send the messages in +queue. +If in +postq, post the messages in +postq. +If in %queue, process the jobs in %queue. +Otherwise, flush the default queue. +If executed with '\\[universal-argument]', you can set the sending case." + (interactive "P") + (if (mew-folder-imap-queuep) + (progn + (mew-window-configure 'summary) + (mew-imap-flush-queue)) + (let* ((fld (mew-summary-folder-name 'ext)) + (proto (mew-proto-to-flush fld)) + qfld case) + (if (or arg mew-ask-flush-case) + (setq case (mew-input-case mew-case "Queue")) + (setq case mew-case)) + (if (or (mew-folder-queuep fld) (mew-folder-postqp fld)) + (progn + (setq qfld fld) + (mew-window-configure 'summary)) + (setq qfld (mew-proto-queue-folder proto case))) + (if (and mew-ask-flush-queue + (not (y-or-n-p (concat "Flush " qfld "? ")))) + (message "The queue is not flushed") + (cond + ((mew-folder-postqp qfld) + (mew-nntp2-flush-queue case qfld)) + (t + (mew-smtp-flush-queue case qfld))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Unlocking +;;; + +(defun mew-subprocess-init () + (add-hook 'kill-emacs-hook 'mew-subprocess-kill)) + +(defun mew-subprocess-clean-up () + (mew-summary-kill-subprocess t) + (remove-hook 'kill-emacs-hook 'mew-subprocess-kil)) + +(defun mew-subprocess-kill () + (mew-summary-kill-subprocess t)) + +(defun mew-summary-kill-subprocess (&optional kill-ssx) + "\\ +Kill a process in Summary mode. +Sometime a process accidentally remains in Summary mode. +In this situation, you cannot execute '\\[mew-summary-retrieve]', '\\[mew-summary-ls]', nor '\\[mew-summary-exec]'. +Use this command to solve this problem. + +If called with '\\[universal-argument]', all SSH processes, if +any, are killed." + (interactive "P") + (let ((process mew-summary-buffer-process) + (disp-msg (mew-called-interactively-p)) + pros sentinel) + (if kill-ssx + (progn + (setq pros (process-list)) + (dolist (pro pros) + (if (string-match "mew" (process-name pro)) + (delete-process pro))) + (if disp-msg (message "All SSH/SSL/TLS processes were killed"))) + (cond + ((not (processp process)) + ;; If you type "x" over SSH and type "C-g" to quit, + ;; refile information remains invisible. + ;; This command turns it visible. + (mew-summary-visible-buffer (current-buffer)) + (if disp-msg (message "No process to kill. This buffer is unlocked anyway"))) + ((eq process t) + ;; Emacs is locking + (if disp-msg (message "This buffer was unlocked"))) + ((memq (process-status process) '(open closed)) + ;; Network process + (setq sentinel (process-sentinel process)) + (if (fboundp sentinel) + (funcall sentinel process "killed by the user")) + (delete-process process) + (if disp-msg (message "The process was killed"))) + (t + ;; Local process or SSH/SSL/TLS + (delete-process process) + (if disp-msg (message "The process was killed"))))) + (mew-summary-unlock))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; De-composing with the old style +;;; + +(defun mew-summary-unshar () + "Apply 'unshar' on messages marked with '*'." + (interactive) + (mew-summary-multi-msgs + (if (y-or-n-p (format "Execute %s for these messages? " mew-prog-unshar)) + (let* ((default-directory (mew-summary-input-directory-name))) + (message "Executing %s..." mew-prog-unshar) + (apply 'call-process mew-prog-unshar nil nil nil FILES) + (message "Executing %s...done" mew-prog-unshar))))) + +(defun mew-summary-uudecode () + "Apply 'uudecode' on messages marked with '*'." + (interactive) + (mew-summary-multi-msgs + (cond + ((not (mew-which-exec mew-prog-mime-decode)) + ()) + ((not (y-or-n-p "Uudecode these messages? ")) + ()) + (t + (let ((dir (mew-summary-input-directory-name)) + (fn nil) + (tmp (mew-make-temp-name)) + (case-fold-search nil) + (files FILES) start) + (with-temp-buffer + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (dolist (file files) + (mew-erase-buffer) + (mew-insert-file-contents file) + (goto-char (point-min)) + (if (re-search-forward mew-eoh nil t) + (forward-line)) + (setq start (point)) + (goto-char (point-max)) + (unless (bolp) (insert "\n")) + (write-region start (point-max) tmp 'append 'no-msg))) + (mew-erase-buffer) + (cd dir) + ;; mew-folder-local is dummy to let mewencode use + ;; the embedded filename + (call-process mew-prog-mime-decode tmp t nil + "-d" "-u" "-" mew-folder-local) + (mew-delete-file tmp) + (goto-char (point-min)) + (if (not (looking-at "^filename: \\(.*\\)")) + (message "Failed to execute %s" mew-prog-mime-decode) + (setq fn (mew-match-string 1)) + (setq fn (mew-summary-prog-exec mew-prog-compress "-df" "Z" fn)) + (setq fn (mew-summary-prog-exec mew-prog-gzip "-df" "gz" fn)) + (when (and (string-match "^\\(.*\\)\\.tar$" fn) + (y-or-n-p (format "Execute %s for %s? " mew-prog-tar fn))) + (message "Executing %s for %s..." mew-prog-tar fn) + (call-process mew-prog-tar nil nil nil "-xf" fn) + (message "Executing %s for %s...done" mew-prog-tar fn))))))))) + +(defun mew-summary-prog-exec (prog opts suffix tarfile) + (if (string-match (format "^\\(.*\\)\\.%s$" suffix) tarfile) + (let ((basename (match-string 1 tarfile))) + (if (not (y-or-n-p (format "Execute %s for %s? " prog tarfile))) + tarfile + (message "Executing %s for %s..." prog tarfile) + (call-process prog nil nil nil opts tarfile) + (message "Executing %s for %s...done" prog tarfile) + basename)) + tarfile)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; De-composing with the new style +;;; + +(defun mew-summary-join () + "Concat Message/Partial fragments marked with '*' to an original +message." + (interactive) + (mew-summary-only + (mew-summary-with-mewl + (mew-summary-multi-msgs + (let ((cfld (mew-summary-folder-name)) + (folder (mew-input-burst-folder)) + (tfile (mew-make-temp-name)) + (targets FLD-MSG-LIST) + num ct med dbl vec len idx ttl TTL fid FID i + beg regex) + (message "Joining...") + (with-temp-buffer + (mew-set-buffer-multibyte t) + (insert "CD: " (mew-expand-folder2 cfld) "\n") + (let ((default-directory (mew-expand-folder cfld))) + (dolist (fld-msg targets) + (insert (mew-msg-get-filename (cdr fld-msg)) "\n"))) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (write-region (point-min) (point-max) tfile nil 'no-msg)) + (mew-erase-buffer) + (call-process mew-prog-mewl nil t nil + "-b" mew-mail-path "-l" "0" + "-x" mew-suffix + "-i" tfile "-d" "content-type") + (mew-delete-file tfile) + (goto-char (point-min)) + (while (not (eobp)) + (if (not (looking-at "^\\([0-9]+\\)[ \t]*:[ \t]*")) + (forward-line) + (setq num (mew-match-string 1)) + (setq med (match-end 0)) + (forward-line) + (mew-header-goto-next) + (setq ct (mew-param-decode + (mew-buffer-substring med (1- (point))))) + (setq dbl (cons (cons num ct) dbl)))) + (setq len (length dbl)) + (setq vec (make-vector len nil)) + (dolist (ent dbl) + (setq num (car ent)) + (setq ttl (mew-syntax-get-param ent "total")) + (setq fid (mew-syntax-get-param ent "id")) + (setq idx (mew-syntax-get-param ent "number")) + (if TTL + (if (and ttl (not (string= TTL ttl))) + (error "total mismatch")) + (setq TTL ttl)) + (if FID + (if (or (null fid) (not (string= FID fid))) + (error "fragment id mismatch")) + (setq FID fid)) + (unless idx (error "no number")) + (setq idx (1- (string-to-number idx))) + (if (and (>= idx 0) (< idx len)) + (aset vec idx num) + (error "invalid number"))) + (unless TTL (error "no total")) + (dotimes (i len) + (unless (stringp (aref vec i)) (error "Not enough fragments"))) + ;; now reassemble + (mew-erase-buffer) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + ;; the first fragment + (goto-char (point-max)) + (save-restriction + (narrow-to-region (point) (point)) + (mew-insert-file-contents (mew-expand-msg cfld (aref vec 0))) + ;; Removing unnecessary fields from the encapsulating + ;; (outer) header. + (goto-char (point-min)) + (mew-header-delete-lines mew-field-delete-for-joining) + ;; Concatenating the two headers. + (goto-char (point-min)) + (re-search-forward mew-eoh nil t) + (setq beg (point)) + (while (looking-at mew-eoh) + (forward-line) + (if (eobp) (error "invalid message (number 1)"))) + (delete-region beg (point)) + ;; Removing unnecessary fields from the encapsulated + ;; (inner) header. + (setq beg (point)) + (when (re-search-forward mew-eoh nil t) + (setq regex (mew-make-field-regex mew-field-delete-for-joining)) + (save-restriction + (narrow-to-region beg (point)) + (goto-char (point-min)) + (let ((case-fold-search t)) + (while (not (eobp)) + (if (looking-at regex) + (setq beg nil) ;; logic is reversed + (setq beg (point))) + (forward-line) + (mew-header-goto-next) + (if beg (delete-region beg (point)))))))) + ;; the second and subsequent fragments. + (setq i 1) + (while (< i len) + (goto-char (point-max)) + (save-restriction + (narrow-to-region (point) (point)) + (mew-insert-file-contents (mew-expand-msg cfld (aref vec i))) + (goto-char (point-min)) + (re-search-forward mew-eoh nil t) + (forward-line) + (if (eobp) (error "invalid message (number %d)" (1+ i))) + (delete-region (point-min) (point))) + (setq i (1+ i))) + (mew-header-delete-lines `(,mew-x-mew-uidl:)) + (write-region (point-min) (point-max) + (mew-folder-new-message folder) + nil 'no-msg))) + (mew-touch-folder folder) + (message "Joining...done") + (when mew-ask-folder-after-join + (if (y-or-n-p (format "Go to %s? " folder)) + (mew-summary-visit-folder folder 'goend)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Cleaning +trash +;;; + +(defun mew-summary-clean-trash () + "Remove all messages in +trash." + (interactive) + (let* ((case (mew-sinfo-get-case)) + (folder (mew-sinfo-get-folder)) + case:trash trash trashdir msgs) + (cond + ((mew-folder-imapp folder) + (setq trash (mew-imap-trash-folder case))) + (t + (setq trash mew-trash-folder))) + (unless trash + (setq trash folder)) + (setq case:trash (mew-input-folder case trash)) + (if (null case:trash) + (message "Nothing was processed") + (setq case (mew-case:folder-case case:trash)) + (setq trash (mew-case:folder-folder case:trash)) + (setq trashdir (mew-expand-folder case:trash)) + (setq msgs (mew-dir-messages trashdir)) + (if (and (mew-folder-localp trash) (null msgs)) + (message "No messages to be removed in %s" trash) + (if (not (y-or-n-p (format "Remove all messages in %s? " case:trash))) + (message "No messages removed in %s" trash) + (if (string= folder trash) (mew-summary-reset)) + (message "Removing all messages in %s..." case:trash) + (when (get-buffer case:trash) + (with-current-buffer case:trash + (mew-summary-kill-subprocess))) + (mew-summary-unlink-msgs case:trash msgs) + (mew-summary-folder-cache-clean case:trash) + (message "Removing all messages in %s...done" case:trash) + (when (mew-folder-imapp trash) + (if (get-buffer case:trash) + (set-buffer case:trash) + (mew-summary-switch-to-folder case:trash 'set-buffer)) + (mew-imap-retrieve case 'exec case:trash + (mew-make-execinfo :remove '("1:*") + :rttl 0 + :dttl -1)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Copy local +;;; + +(defun mew-summary-local-copy () + "Copy a message to a local folder." + (interactive) + (mew-summary-msg-or-part + (let ((fld (mew-summary-folder-name)) + (exclusivep t) + msg dstmsg dstfld file dstfile) + (save-excursion + (mew-summary-goto-message) + (setq msg (mew-summary-message-number))) + (setq file (mew-expand-msg fld msg)) + (setq dstfld (mew-input-local-folder mew-inbox-folder)) + (when (and dstfld (mew-local-folder-check dstfld 'ask)) + (setq dstmsg (mew-folder-new-message dstfld 'numonly)) + (setq dstfile (mew-expand-msg dstfld dstmsg)) + (when (get-buffer dstfld) + (set-buffer dstfld) + (setq exclusivep (mew-summary-exclusive-p))) + (cond + ((not exclusivep) + (message "Try again later")) + ((string= file dstfile) + (message "You cannot copy this onto itself")) + (t + (mew-summary-local-copy-one file dstfile) + (mew-touch-folder dstfld) + (message "Copied to %s/%s" dstfld dstmsg))))))) + +(defun mew-summary-mark-local-copy (&optional arg) + "Copy messages marked with '*' to a local folder. If called +with '\\[universal-argument]', only messages marked with '*' in +the region are handled." + (interactive "P") + (mew-summary-not-in-draft + (let ((mew-use-highlight-x-face nil) + (fld (mew-summary-folder-name)) + (exclusivep t) + msgs file dstmsg dstfld dstfile + beg end region total i) + (if (mew-mark-active-p) (setq arg t)) + (cond + (arg + (setq region (mew-summary-get-region)) + (setq beg (car region)) + (setq end (cdr region))) + (t + (setq beg (point-min)) + (setq end (point-max)))) + (setq dstfld (mew-input-local-folder mew-inbox-folder)) + (when (and dstfld (mew-local-folder-check dstfld 'ask)) + (let ((mew-use-suffix nil)) + (setq dstmsg (mew-folder-new-message dstfld 'numonly))) + (setq msgs (mew-summary-mark-collect mew-mark-review beg end)) + (when (get-buffer dstfld) + (with-current-buffer dstfld + (setq exclusivep (mew-summary-exclusive-p)))) + (cond + ((null msgs) + (message "No mark")) + ((not exclusivep) + (message "Try again later")) + (t + (message "Copying...") + (setq total (length msgs)) + (setq i 1) + (dolist (msg msgs) + (setq file (mew-expand-msg fld msg)) + (setq dstfile (mew-expand-new-msg dstfld dstmsg)) + (message "Copying (%d/%d)..." i total) + (mew-summary-local-copy-one file dstfile) + (setq dstmsg (number-to-string (1+ (string-to-number dstmsg)))) + (setq i (1+ i))) + (mew-touch-folder dstfld) + (message "Copying...done"))))))) + +(defun mew-summary-local-copy-one (srcfile dstfile) + (with-temp-buffer + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (mew-insert-file-contents srcfile) + (goto-char (point-min)) + (mew-header-delete-lines (list mew-x-mew-uidl:)) + (write-region (point-min) (point-max) dstfile nil 'no-msg) + (mew-set-file-modes dstfile)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Deleting and moving a folder +;;; + +(defun mew-summary-delete-folder () + "Delete this folder." + (interactive) + (mew-summary-only + (let* ((folder (or (mew-sinfo-get-folder) + (mew-summary-folder-name 'ext))) + (case (mew-sinfo-get-case)) + (case:folder (mew-summary-folder-name 'ext)) + (dir (mew-expand-folder case:folder)) + (buf (current-buffer))) + (cond + ((mew-folder-localp folder) + (if (mew-folder-node-p folder) + (message "%s cannot be deleted" folder) + (when (y-or-n-p "Delete this folder? ") + (mew-delete-directory-recursively dir) + (mew-local-folder-delete folder) + (run-hook-with-args 'mew-summary-delete-folder-hook folder) + (mew-summary-visit-folder mew-inbox-folder) + (mew-kill-buffer buf)))) + ((mew-folder-imapp folder) + (if (mew-folder-node-p folder case) + (message "%s cannot be deleted" folder) + (when (y-or-n-p "Delete this folder? ") + (setq mew-summary-buffer-process-error nil) + (mew-imap-retrieve case 'delete case:folder) + (mew-timing) + (mew-rendezvous mew-summary-buffer-process) + (if mew-summary-buffer-process-error + (progn + (message "%s cannot be deleted" folder) + (setq mew-summary-buffer-process-error nil)) + (mew-imap-folder-delete case folder) + (mew-delete-directory-recursively dir) ;; cache + (run-hook-with-args 'mew-summary-delete-folder-hook case:folder) + (mew-summary-visit-folder mew-imap-inbox-folder) + (mew-kill-buffer buf))))))))) + +(defun mew-summary-rename-folder () + "Rename this folder." + (interactive) + (mew-summary-only + (let* ((folder (or (mew-sinfo-get-folder) + (mew-summary-folder-name 'ext))) + (case (mew-sinfo-get-case)) + (case:folder (mew-summary-folder-name 'ext)) + (dir (mew-expand-folder case:folder)) + (buf (current-buffer)) + new-folder new-dir case:new-folder) + (cond + ((mew-folder-localp folder) + (setq new-folder (mew-input-local-folder folder)) + (setq new-dir (mew-expand-folder new-folder)) + (cond + ((string= folder new-folder) + (message "%s was not moved" folder)) + ((file-exists-p new-dir) + (message "%s was not moved since %s exists" folder new-folder)) + (t + (mew-rename-directory dir new-dir) + (mew-summary-switch-to-folder new-folder) + (mew-kill-buffer buf) + (if (mew-folder-node-p folder) + ;; xxx remove all related buffer? + (mew-local-update 'force) + (mew-local-folder-delete folder) + (mew-local-folder-insert new-folder)) + (run-hook-with-args 'mew-summary-rename-folder-hook folder new-folder)))) + ((mew-folder-imapp folder) + (setq new-folder (car (mew-input-refile-folders (list folder) t case mew-folder-imap))) + (setq case:new-folder (mew-case-folder case new-folder)) + (setq new-dir (mew-expand-folder case:new-folder)) + (cond + ((string= folder new-folder) + (message "%s was not moved" folder)) + ((file-exists-p new-dir) + (message "%s was not moved since %s exists" folder new-folder)) + (t + (mew-imap-retrieve case 'rename case:folder case:new-folder) + (mew-timing) + (mew-rendezvous mew-summary-buffer-process) + (if mew-summary-buffer-process-error + (progn + (message "%s cannot be renamed" folder) + (setq mew-summary-buffer-process-error nil)) + (rename-file dir new-dir t) ;; cache + (mew-summary-switch-to-folder case:new-folder) + (mew-kill-buffer buf) + (if (mew-folder-node-p folder case) + (if (y-or-n-p "Collect folders now? ") + (mew-imap-update case) + (mew-message-for-summary "Type '\\[universal-argument]\\[mew-status-update]' to collect folders")) + (mew-imap-folder-delete case folder) + (mew-imap-folder-insert case new-folder)) + (run-hook-with-args 'mew-summary-rename-folder-hook + case:folder case:new-folder))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Toggle +;;; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Summary only vs Summary/Message +;;; + +(defun mew-summary-toggle-disp-msg (&optional arg) + "Toggle 'Summary mode only' and 'Summary & Message mode'. If +you choose 'Summary mode only', you can quickly put the delete + marks since the next message is not displayed." + (interactive) + (cond + ((eq arg 'on) + (mew-sinfo-set-disp-msg t)) + ((eq arg 'off) + (mew-sinfo-set-disp-msg nil) + (mew-summary-reset-mode-line)) + (t + (mew-sinfo-set-disp-msg (not (mew-sinfo-get-disp-msg))) + (if (mew-sinfo-get-disp-msg) + (mew-summary-display 'redisplay) + (mew-summary-goto-message) + (mew-summary-reset) + (mew-summary-cook-window)))) + (run-hooks 'mew-summary-toggle-disp-msg-hook)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; 8bit clean +;;; + +(defun mew-summary-toggle-8bit () + "Toggle 8bit mode(i.e. 'mew-use-8bit')." + (interactive) + (setq mew-use-8bit (not mew-use-8bit)) + (if mew-use-8bit + (message "mew-use-8bit has been set to 't'") + (message "mew-use-8bit has been set to 'nil'"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mew cache clean up +;;; + +(defun mew-summary-cache-clean-up () + "Clean-up caches of analyzed messages." + (interactive) + (mew-cache-clean-up) + (message "Mew cache clean up...done")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Toggle warning +;;; + +(defun mew-summary-toggle-warning () + "Toggle warning level. +If 'mew-warning-field-level' is 2, set it to 1. +If 'mew-warning-field-level' is 1, set it to 2." + (interactive) + (if (= mew-warning-field-level 2) + (setq mew-warning-field-level 1) + (setq mew-warning-field-level 2)) + (mew-cache-clean-up) + (mew-summary-analyze-again) + (message "Mew warning level %d" mew-warning-field-level)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Toggle decode policy +;;; + +(defun mew-summary-toggle-policy (&optional arg) + "Toggle decode policy(i.e. 'mew-decode-broken')." + (interactive "P") + (if arg + (setq mew-decode-broken nil + mew-use-name-parameter nil) + (setq mew-decode-broken (not mew-decode-broken)) + (setq mew-use-name-parameter (not mew-use-name-parameter))) + (mew-cache-clean-up) + (mew-summary-analyze-again) + (message "Mew \"%s\" mode" (if mew-decode-broken "TOLERANT" "STRICT"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Toggle debug +;;; + +(defun mew-summary-toggle-debug () + "Toggle 'mew-debug'." + (interactive) + (setq mew-debug (not mew-debug)) + (if mew-debug + (message "'mew-debug' is now 't'") + (message "'mew-debug' is now 'nil'"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Toggle PGP/MIME and old PGP +;;; + +(defun mew-summary-toggle-pgp () + "Toggle PGP/MIME and old PGP (i.e. 'mew-use-old-pgp')." + (interactive) + (setq mew-use-old-pgp (not mew-use-old-pgp)) + (if mew-use-old-pgp + (message "mew-use-old-pgp has been set to 't'") + (message "mew-use-old-pgp has been set to 'nil'"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Learning spam and ham +;;; + +(defun mew-summary-learn-spam () + "Learn that this message is a spam. +See also 'mew-spam-prog' and 'mew-spam-prog-args." + (interactive) + (mew-summary-msg + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (file (mew-expand-msg fld msg)) + (case (mew-sinfo-get-case)) + (prog (mew-spam-prog case)) + (args (mew-spam-prog-args case)) + beg end) + (message "Learning as spam...") + (when (mew-which-exec prog) + (with-temp-buffer + (apply 'call-process prog file (current-buffer) nil args) + (setq beg (point-min)) + (goto-char beg) + (forward-line) + (if (= (point) beg) + (message "Learning as spam...done") + (setq end (1- (point))) + (message "%s" (concat "Learned as spam: " (mew-buffer-substring beg end))))))))) + +(defun mew-summary-learn-ham () + "Learn that this message is a ham. +See also 'mew-ham-prog' and 'mew-ham-prog-args." + (interactive) + (mew-summary-msg + (let* ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (file (mew-expand-msg fld msg)) + (case (mew-sinfo-get-case)) + (prog (mew-ham-prog case)) + (args (mew-ham-prog-args case)) + beg end) + (message "Learning as ham...") + (when (mew-which-exec prog) + (with-temp-buffer + (apply 'call-process prog file (current-buffer) nil args) + (setq beg (point-min)) + (goto-char beg) + (forward-line) + (if (= (point) beg) + (message "Learning as ham...done") + (setq end (1- (point))) + (message "%s" (concat "Learned as ham: " (mew-buffer-substring beg end))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Search invisible +;;; + +(defun mew-summary-toggle-invisible () + "Toggle the value of search-invisible. +Invisible information in Summary mode cannot be searched by default. +Executing this command enables searching such information." + (interactive) + (if (eq search-invisible t) + (setq search-invisible 'open) + (setq search-invisible t)) + (message "'search-invisible' is set to '%s'" search-invisible)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Lines +;;; + +(defun mew-summary-line () + "Toggle normal lines, wrapped lines and long lines." + (interactive) + (let ((fld (mew-summary-folder-name)) + (msg (mew-summary-message-number)) + (cwin (get-buffer-window (current-buffer))) + (mwin (get-buffer-window (mew-buffer-message)))) + (if (not mwin) + (message "No message is displayed") + (select-window mwin) + (unwind-protect + (progn + (mew-message-line) + (mew-message-mode-line fld msg)) + (select-window cwin))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Horizontal Scrolling +;;; + +(defun mew-summary-scroll-left () + "Scroll the Message window to the right." + (interactive) + (let ((cwin (get-buffer-window (current-buffer))) + (mwin (get-buffer-window (mew-buffer-message)))) + (if (not mwin) + (message "No message is displayed") + (select-window mwin) + (unwind-protect + (mew-message-scroll-left) + (select-window cwin))))) + +(defun mew-summary-scroll-right () + "Scroll the Message window to the left." + (interactive) + (let ((cwin (get-buffer-window (current-buffer))) + (mwin (get-buffer-window (mew-buffer-message)))) + (if (not mwin) + (message "No message is displayed") + (select-window mwin) + (unwind-protect + (mew-message-scroll-right) + (select-window cwin))))) + +(provide 'mew-summary4) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-summary4.el ends here diff --git a/elpa/mew-20150813.2354/mew-syntax.el b/elpa/mew-20150813.2354/mew-syntax.el new file mode 100644 index 00000000..621af5d9 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-syntax.el @@ -0,0 +1,1057 @@ +;;; mew-syntax.el --- Internal syntax for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; mew-encode-syntax +;; +;; = [ 'single file (dcr) () (CT:) CTE: CD: nil (CDP:) ] +;; = [ 'multi dir/ (dcr) () ("mul") CTE: CD: nil (CDP:) 1* ] +;; = | +;; = list of (mew-ct-mls mew-ct-pgs) +;; +;; mew-decode-syntax +;; +;; = [ 'message hbeg hend () ("msg") CTE: CD: CID: (CDP:) ] +;; = [ 'single beg end () (CT:) CTE: CD: CID: (CDP:) ] +;; = [ 'multi beg end () ("mul") CTE: CD: CID: (CDP:) 1* ] +;; = | Text/Plain +;; = | | +;; = list of (mew-ct-mls mew-ct-pgs RESULT) in reverse order ;; for cons + +;; +;; +;; + +(defun mew-syntax-singlepart-p (syntax) + (eq (aref syntax 0) 'single)) + +(defun mew-syntax-multipart-p (syntax) + (eq (aref syntax 0) 'multi)) + +(defun mew-syntax-message-p (syntax) + (eq (aref syntax 0) 'message)) + +;; +;; +;; + +(defun mew-syntax-get-key (syntax) + (aref syntax 0)) + +(defun mew-syntax-get-begin (syntax) + (let ((beg (aref syntax 1))) + (if (listp beg) (car beg) beg))) + +(defun mew-syntax-get-begin2 (syntax) + (let ((beg (aref syntax 1))) + (if (listp beg) (cdr beg) beg))) + +(defun mew-syntax-get-end (syntax) + (aref syntax 2)) + +(defun mew-syntax-get-privacy (syntax) + (aref syntax 3)) + +(defun mew-syntax-get-ct (syntax) + (aref syntax 4)) + +(defun mew-syntax-get-cte (syntax) + (aref syntax 5)) + +(defun mew-syntax-get-cd (syntax) + (aref syntax 6)) + +(defun mew-syntax-get-cid (syntax) + (aref syntax 7)) + +(defun mew-syntax-get-cdp (syntax) + (aref syntax 8)) + +(defun mew-syntax-get-part (syntax) + (aref syntax 9)) + + +(defun mew-syntax-set-key (syntax key) + (aset syntax 0 key)) + +(defun mew-syntax-set-begin (syntax begin) + (aset syntax 1 begin)) + +(defun mew-syntax-set-end (syntax end) + (aset syntax 2 end)) + +(defun mew-syntax-set-privacy (syntax privacy) + (aset syntax 3 privacy)) + +(defun mew-syntax-set-ct (syntax ct) + (aset syntax 4 ct)) + +(defun mew-syntax-set-cte (syntax cte) + (aset syntax 5 cte)) + +(defun mew-syntax-set-cd (syntax cd) + (aset syntax 6 cd)) + +(defun mew-syntax-set-cid (syntax cid) + (aset syntax 7 cid)) + +(defun mew-syntax-set-cdp (syntax cdp) + (aset syntax 8 cdp)) + +(defun mew-syntax-set-part (syntax part) + (aset syntax 9 part)) + + +;; alias for encode syntax + +(defun mew-syntax-get-file (syntax) + (aref syntax 1)) + +(defun mew-syntax-set-file (syntax file) + (aset syntax 1 file)) + +(defun mew-syntax-get-decrypters (syntax) + (aref syntax 2)) + +(defun mew-syntax-set-decrypters (syntax decrypters) + (aset syntax 2 decrypters)) + +;; for content parameters + +(defun mew-syntax-get-value (ctl &optional capitalizep) + (if capitalizep + (mew-capitalize (car ctl)) + (car ctl))) + +(defun mew-syntax-get-params (ctl) + (cdr ctl)) + +;; ctl = (value (pname pvalue) (pname pvalue) ...) +;; ctl = ((pname pvalue) (pname pvalue) ...) +(defun mew-syntax-get-param (ctl member) + (nth 1 (assoc member ctl))) + +(defun mew-syntax-treat-filename-default-function (file) + (if (stringp file) + (mew-replace-white-space + (mew-chop (file-name-nondirectory file))))) + +(defun mew-syntax-get-filename (cdpl &optional ctl) + (let ((file (mew-syntax-get-param cdpl "filename"))) + ;; for broken MUAs + (if (and (null file) mew-use-name-parameter ctl) + (setq file (mew-syntax-get-param ctl "name"))) + (if mew-syntax-treat-filename-function + (setq file (funcall mew-syntax-treat-filename-function file))) + file)) + +;; need to setq +(defun mew-syntax-cat (syntax part) + (vconcat syntax (vector part))) + +(defun mew-syntax-cdp-format (ct file &optional cdp force-file) + ;; If cdp is a string, it is used as a file. + (let* ((cdpdb (mew-cdpdb-by-ct ct)) + (val (mew-cdpdb-val cdpdb)) + (filep (mew-cdpdb-file cdpdb))) + (if (stringp cdp) (setq file cdp)) + (when val + (if (and (or filep force-file) file) + (list val (list "filename" (file-name-nondirectory (mew-header-sanity-check-string file)))) + (list val))))) + +;; Encryption + +(defun mew-syntax-encrypted-p (syntax) + (catch 'loop + (dolist (ent (mew-syntax-get-privacy (mew-syntax-get-part syntax))) + (if (or (mew-case-equal (mew-privacy-dinfo-get-ct ent) mew-ct-mle) + (mew-case-equal (mew-privacy-dinfo-get-proto ent) mew-ct-smm-enc)) + (throw 'loop t))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Entry functions +;; + +(defun mew-syntax-get-entry (syntax nums) + (cond + ((null nums) syntax) ;; single & message match + ((mew-syntax-message-p syntax) + (let ((body (mew-syntax-get-part syntax))) + (if (mew-syntax-multipart-p body) + (mew-syntax-get-entry (mew-syntax-get-part syntax) nums) + ;; nums should be "1" + body))) + ((mew-syntax-multipart-p syntax) + (if (null nums) + syntax + (mew-syntax-get-entry + (aref syntax (+ mew-syntax-magic (1- (car nums)))) (cdr nums)))))) + +(defun mew-syntax-insert-entry (syntax nums entry) + (let* ((root syntax) + (child entry) + grand parent + (nl (length nums)) + (rev (reverse nums)) + (n0 (nth 0 rev)) + (n1 (nth 1 rev)) + (ns (reverse (nthcdr 2 rev)))) + (cond + ((= nl 1) + (setq parent root) + (mew-syntax-add-entry parent n0 child)) + (t + (if (= nl 2) + (setq grand root) + (setq grand (mew-syntax-get-entry root ns))) + (setq parent (mew-syntax-get-entry grand (list n1))) + (setq parent (mew-syntax-add-entry parent n0 child)) + (aset grand (+ mew-syntax-magic (1- n1)) parent) + root)))) + +(defun mew-syntax-add-entry (syntax n entry) + "Must not use in functions other than mew-syntax-insert-entry" + (let* ((len (1+ (length syntax))) + (vec (make-vector len nil)) + (cnt 0) (thr (+ mew-syntax-magic (1- n)))) + (while (< cnt thr) + (aset vec cnt (aref syntax cnt)) + (setq cnt (1+ cnt))) + (aset vec cnt entry) + (setq cnt (1+ cnt)) + (while (< cnt len) + (aset vec cnt (aref syntax (1- cnt))) + (setq cnt (1+ cnt))) + vec)) ;; return value + +(defun mew-syntax-remove-entry (syntax nums) + (let* ((root syntax) + grand parent + (nl (length nums)) + (rev (reverse nums)) + (n0 (nth 0 rev)) + (n1 (nth 1 rev)) + (ns (reverse (nthcdr 2 rev)))) + (cond + ((= nl 1) + (setq parent root) + (mew-syntax-cut-entry parent n0)) + (t + (if (= nl 2) + (setq grand root) + (setq grand (mew-syntax-get-entry root ns))) + (setq parent (mew-syntax-get-entry grand (list n1))) + (setq parent (mew-syntax-cut-entry parent n0)) + (aset grand (+ mew-syntax-magic (1- n1)) parent) + root)))) + +(defun mew-syntax-cut-entry (syntax n) + "Must not use in functions other than mew-syntax-remove-entry" + (let* ((len (1- (length syntax))) + (vec (make-vector len nil)) + (cnt 0) (thr (+ mew-syntax-magic (1- n)))) + (while (< cnt thr) + (aset vec cnt (aref syntax cnt)) + (setq cnt (1+ cnt))) + (while (< cnt len) + (aset vec cnt (aref syntax (1+ cnt))) + (setq cnt (1+ cnt))) + vec)) ;; return value + +(defun mew-syntax-get-entry-by-cid (syntax cid) + (cond + ((and (stringp (mew-syntax-get-cid syntax)) + (string= (mew-syntax-get-cid syntax) cid)) + syntax) + ((mew-syntax-message-p syntax) + (mew-syntax-get-entry-by-cid (mew-syntax-get-part syntax) cid)) + ((mew-syntax-multipart-p syntax) + (let ((i mew-syntax-magic) + (len (length syntax)) + entry) + (catch 'multi + (while (< i len) + ;; xxx aref (see mew-summary-burst-body) + (setq entry (mew-syntax-get-entry-by-cid (aref syntax i) cid)) + (if entry (throw 'multi entry)) + (setq i (1+ i)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; +;; + +(defun mew-summary-goto-part (msg part) + (let (here) + (save-excursion + (goto-char (point-min)) + (when (and (re-search-forward (mew-regex-sumsyn-msg msg) nil t) + (re-search-forward (mew-regex-jmp-part part) nil t)) + (beginning-of-line) + (setq here (point)))) + (and here (goto-char here)))) + +(defun mew-summary-goto-message () + (if (eobp) (forward-line -1)) + (when (mew-in-decode-syntax-p) + (goto-char (mew-decode-syntax-begin)) + (forward-line -1)) + (beginning-of-line)) + +(defun mew-syntax-number () + (if (or (mew-in-attach-p) + (mew-in-decode-syntax-p)) + (save-excursion + (beginning-of-line) + (if (looking-at mew-regex-part) (mew-sumsyn-part))))) + +(defun mew-syntax-number-to-nums (strnum) + (if strnum + (mapcar 'string-to-number (mew-split strnum ?.)) + nil)) + +(defun mew-syntax-nums () + (mew-syntax-number-to-nums (mew-syntax-number))) + +(defun mew-summary-goto-mark () + (beginning-of-line)) + +(defun mew-summary-goto-body (&optional after) + (when mew-summary-form-body-starter + (beginning-of-line) + (let ((beg (point))) + (forward-line) + (if (search-backward "\r" nil t) + (if (search-backward mew-summary-form-body-starter beg t) + (progn + (if after (goto-char (match-end 0))) + t) + nil) + (forward-line -1) ;; just in case + nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Summary mode syntax +;;; + +(defvar mew-use-cut-file-name t) + +(defun mew-summary-info (arg) + "Display the folder name of this message, its number, its size +and its unique id. If this is a cache message, both the unique +id and the size are also shown. If called with +'\\[universal-argument]', its Message-ID: and its parent's +Message-ID: are displayed instead. If 'mew-use-cut-file-name' is +non-nil, the file path is pushed to the cut buffer of your window +system." + (interactive "P") + (mew-summary-msg + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (if arg + (message "my-id=%s par-id=%s" + (mew-sumsyn-my-id) + (mew-sumsyn-parent-id)) + (let* ((fld (mew-sumsyn-folder-name)) + (msg (mew-sumsyn-message-number)) + (size (mew-sumsyn-message-size)) + (uid (mew-sumsyn-message-uid)) + (file (concat (file-name-as-directory fld) msg)) + (path (mew-expand-folder file)) + (rpath (mew-msg-get-filename path))) + (if (mew-virtual-p) + (setq file (mew-folder-path-to-folder file 'has-proto))) + (message "%s size=%s uid=%s" file size uid) + (when mew-use-cut-file-name + (kill-new rpath))))))) + +(defun mew-sumsyn-match (regex) + (save-excursion + (beginning-of-line) + (let ((start (point))) + (end-of-line) + (when (search-backward "\r" start t) + (looking-at regex))))) + +(defun mew-sumsyn-folder-name () + (let ((fn (mew-match-string 1)) + (bn (buffer-name))) + (cond + ((not (string= fn "")) (mew-sumsym-decode-folder fn)) + ((mew-virtual-for-one-summary) + (mew-vinfo-get-physical-folder)) + (t bn)))) + +(defun mew-sumsyn-message-number () (mew-match-string 2)) +(defun mew-sumsyn-my-id () (mew-match-string 3)) +(defun mew-sumsyn-parent-id () (mew-match-string 4)) +(defun mew-sumsyn-message-uid () (mew-match-string 5)) +(defun mew-sumsyn-message-size () (mew-match-string 6)) + +(defun mew-sumsyn-part () (mew-match-string 1)) + +(defun mew-summary-folder-name (&optional ext) + (cond + ((or ext (mew-summary-p)) + (buffer-name)) + (t ;; Virtual mode + (save-excursion + (mew-summary-goto-message) + (when (mew-sumsyn-match mew-regex-sumsyn-short) + (mew-sumsyn-folder-name)))))) + +(defun mew-summary-message-number () + (unless (mew-in-decode-syntax-p) + (when (mew-sumsyn-match mew-regex-sumsyn-short) + (mew-sumsyn-message-number)))) + +(defun mew-summary-message-number2 () + (save-excursion + (mew-summary-goto-message) + (when (mew-sumsyn-match mew-regex-sumsyn-short) + (mew-sumsyn-message-number)))) + +(defun mew-summary-my-id () + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (mew-sumsyn-my-id))) + +(defun mew-summary-parent-id () + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (mew-sumsyn-parent-id))) + +(defun mew-summary-message-uid () + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (mew-sumsyn-message-uid))) + +(defun mew-summary-message-size () + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (mew-sumsyn-message-size))) + +(defun mew-syntax-change-message-number (msg) + (save-excursion + (when (mew-sumsyn-match mew-regex-sumsyn-short) + (mew-syntax-change-message-number2 msg)))) + +;; see also mew-sumsyn-message-number +(defun mew-syntax-change-message-number2 (msg) + (delete-region (match-beginning 2) (match-end 2)) + (goto-char (match-beginning 2)) + (insert-and-inherit msg)) + +(defun mew-syntax-change-parent-id (id) + (save-excursion + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (delete-region (match-beginning 4) (match-end 4)) + (goto-char (match-beginning 4)) + (insert-and-inherit id)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; mew-encode-syntax +;; + +(defun mew-encode-syntax-single (file &optional ctl cte cd cid cdp + privacy decrypters) + ;; cid is just for beauty + ;; if cdp is non-nil, set cdp from file. + ;; if cdp is a string, set cdp from cdp as a file. + (let* (ct ctdb) + (cond + (ctl + (setq ct (car ctl)) + (setq ctdb (mew-ctdb-by-ct ct))) + (t + (setq ctdb (mew-ctdb-by-file file)) + (setq ct (mew-ctdb-ct ctdb)) + (unless ct + (setq ct (mew-content-type (mew-tinfo-get-case))) + (setq ctdb (mew-ctdb-by-ct ct))) + (setq ctl (list ct)))) + (or cte (setq cte (mew-ctdb-cte ctdb))) + (if cdp (setq cdp (mew-syntax-cdp-format ct file cdp))) + (vconcat [single] (list file decrypters privacy ctl cte cd cid cdp)))) + +(defun mew-encode-syntax-multi (dir ct) + (unless (string-match (concat mew-path-separator "$") dir) + (setq dir (file-name-as-directory dir))) + (vconcat [multi] (list dir) [nil nil] (list ct) [nil nil nil nil])) + +(defun mew-encode-syntax-text () + (mew-encode-syntax-single mew-draft-coverpage (list mew-ct-txt))) + +(defun mew-encode-syntax-initial (dir) + (vconcat + (mew-encode-syntax-multi dir mew-type-mlm) + ;; ensure to guess charset .... + (list (mew-encode-syntax-text)))) + +(defun mew-encode-syntax-initial-multi (dir n) + (let ((i 1) file ret) + (while (<= i n) + (setq file (mew-msg-new-filename (number-to-string i))) + (setq ret (vconcat ret (list (mew-encode-syntax-single + file nil nil nil nil 'cdp)))) + (setq i (1+ i))) + (vconcat (mew-encode-syntax-multi dir mew-type-mlm) + (list (mew-encode-syntax-single mew-draft-coverpage + (list mew-ct-txt))) + ret))) + +(defconst mew-encode-syntax-dot + [nil "." nil nil ("") nil nil nil nil]) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; mew-decode-syntax +;; + +;; MUST generate a new vector + +(defun mew-decode-syntax-rfc822 (&optional msg-head multi) + ;; msg-head may include CD: + (unless msg-head (setq msg-head (mew-decode-syntax-rfc822-head t))) + (if (not multi) + (vconcat msg-head (vector (mew-decode-syntax-text))) + (let ((body (mew-decode-syntax-text)) + (head (mew-decode-syntax-multi-head))) + (mew-syntax-set-begin head (mew-syntax-get-begin body)) + (mew-syntax-set-end head (mew-syntax-get-end body)) + (vconcat msg-head (vector (mew-syntax-cat head body)))))) + +(defun mew-decode-syntax-rfc822-head (&optional reg-hend) + (vector 'message (point-min) + (and reg-hend + (save-excursion (forward-line -1) (beginning-of-line) (point))) + nil mew-type-msg nil nil nil nil)) + +(defun mew-decode-syntax-text () + (vector 'single (point) (point-max) nil mew-type-txt nil nil nil nil)) + +(defun mew-decode-syntax-multi-head () + (vector 'multi nil nil nil mew-type-mlm nil nil nil nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; syntax printer +;; + +(defconst mew-draft-attach-boundary-beg + "------------------------------ attachments ------------------------------") +(defconst mew-draft-attach-boundary-end + "--------0-1-2-3-4-5-6-7-8-9----------------------------------------------") + +(defun mew-encode-syntax-delete (&optional all) + (mew-elet + (let (end) + (goto-char (point-max)) + (when (re-search-backward mew-regex-attach-end nil t) + (setq end (point)) + (when (re-search-backward mew-regex-attach-beg nil t) + (cond + (all + (beginning-of-line) + (backward-char) + (delete-region (point) (point-max))) + (t + (forward-line) + (delete-region (point) end)))))))) + +(defun mew-encode-syntax-print (syntax) + (mew-elet + (let ((nums (mew-syntax-nums))) + (when (mew-attach-p) + (mew-encode-syntax-delete) + (mew-xinfo-set-multi-form nil) + (mew-xinfo-set-icon-spec nil) + (mew-syntax-multipart syntax nil nil 'mew-draft-button) + (mapc 'insert-and-inherit (nreverse (mew-xinfo-get-multi-form))) + (put-text-property (mew-attach-begin) (point-max) 'read-only t) + (mew-front-nonsticky (mew-attach-begin) (1+ (mew-attach-begin))) + (mew-rear-sticky (1- (point-max)) (point-max)) + (mew-attach-goto-number 'here nums))))) + +;; +;; +;; + +(defun mew-decode-syntax-insert (line) + (let ((beg (point))) + (insert line) + (when (and mew-use-highlight-mouse-line window-system) + (put-text-property + beg (1- (point)) 'mouse-face mew-highlight-mouse-line-face)))) + +(defun mew-decode-syntax-print (sumbuf syntax form icon) + (let* ((stx (mew-syntax-get-part syntax))) + (with-current-buffer sumbuf + (when (mew-syntax-multipart-p stx) + (forward-line) + (mew-elet + (let ((pos (point))) + (mew-decode-syntax-begin-set) + (mapc 'mew-decode-syntax-insert form) + (if (= pos (point)) + ;; Nothing was printed. + (mew-decode-syntax-remove) + (mew-decode-syntax-end-set))) + (forward-line -1) + (mew-summary-goto-message) + (set-buffer-modified-p nil)))))) + +;; +;; +;; + +(defun mew-decode-syntax-clear () + (mew-xinfo-clear)) + +(defun mew-decode-syntax-copy (cache) + (setq mew-decode-syntax (mew-cache-decode-syntax cache)) + (mew-xinfo-copy cache)) + +(defun mew-decode-syntax-set () + ;; cache buffer + (let ((part (mew-syntax-get-part mew-decode-syntax))) + (mew-decode-syntax-arrange-warning) + (if (mew-syntax-multipart-p part) + (progn + (mew-syntax-multipart part 'decoding nil 'mew-summary-button 'body) + (mew-xinfo-set-multi-form (nreverse (mew-xinfo-get-multi-form))) + (mew-xinfo-set-icon-spec (nreverse (mew-xinfo-get-icon-spec)))) + (mew-decode-syntax-set-privacy part "body")))) + +(defun mew-syntax-multipart (syntax dec part func &optional body) + (let* ((ct (mew-syntax-get-value (mew-syntax-get-ct syntax) 'cap)) + (cnt mew-syntax-magic) + (num 1) + (len (length syntax)) + (mew-inherit-alt (string= mew-ct-mla ct)) + strpart subsyntax) + ;; multipart itself is displayed only when encoding. + (if dec + (mew-decode-syntax-set-privacy + syntax + (concat (if part (concat part " ")) + (if body "body ") + "multi")) + (mew-syntax-format syntax part dec)) + (while (< cnt len) + (if part + (setq strpart (concat part "." (number-to-string num))) + (setq strpart (number-to-string num))) + (setq subsyntax (aref syntax cnt)) + (cond + ((mew-syntax-multipart-p subsyntax) + (mew-syntax-multipart subsyntax dec strpart func nil)) + ((mew-syntax-message-p subsyntax) + (mew-syntax-message subsyntax dec strpart func)) + ((mew-syntax-singlepart-p subsyntax) + (mew-syntax-singlepart subsyntax dec strpart func + (and body (= cnt mew-syntax-magic))))) + (setq cnt (1+ cnt)) + (setq num (1+ num))) + (unless dec + (if part + (setq part (concat part "." (number-to-string num))) + (setq part (number-to-string num))) + (mew-syntax-format mew-encode-syntax-dot part dec)))) + +(defun mew-syntax-singlepart (syntax dec part func first) + ;; part is valid only when called by mew-syntax-multipart. + (let ((ct (mew-syntax-get-value (mew-syntax-get-ct syntax) 'cap))) + ;; see also mew-mime-message/rfc822. + (if (and dec + ;; the first singlepart in multipart under message if t + ;; the first singlepart under message if 'body + first + ;; CT: is text/plain but not attached file. + mew-use-text-body + (mew-ct-textp ct)) + () ;; skip displaying. + ;; reach here only when called by mew-syntax-multipart. + (mew-syntax-format syntax part dec)) + (if dec (mew-decode-syntax-set-privacy + syntax + (if (eq first 'body) + (if part (concat part " body") "body") + part))))) + +(defun mew-syntax-message (syntax dec part func) + (let ((subsyntax (mew-syntax-get-part syntax))) + (mew-syntax-format syntax part dec) + (if dec (mew-decode-syntax-set-privacy + syntax + (format "%s message" part))) + (cond + ((mew-syntax-multipart-p subsyntax) + (mew-syntax-multipart subsyntax dec part func 'body)) + ((mew-syntax-message-p subsyntax) + ) ;; never happens + ((mew-syntax-singlepart-p subsyntax) + ;; text/plain only + (mew-syntax-singlepart subsyntax dec part func 'body))))) + +;012345678901234567890123456789012345678901234567890123456789012345678901234567 +;<4>snss<27-2 >ss<24+2 >ss<16 > + +(defun mew-syntax-format (syntax number dec) + (let* ((file (if (not dec) (mew-syntax-get-file syntax))) + (ctl (mew-syntax-get-ct syntax)) + (ct (mew-syntax-get-value ctl 'cap)) + (char (mew-syntax-get-param ctl "charset")) + (ichar (mew-syntax-get-param ctl "icharset")) + (cte (mew-syntax-get-cte syntax)) ;; cte may be nil + (cd (mew-syntax-get-cd syntax)) + (cdpl (mew-syntax-get-cdp syntax)) + (filename (mew-syntax-get-filename cdpl ctl)) + (decrypters-list (mew-syntax-get-decrypters syntax)) + (decrypters (and (not dec) decrypters-list + (mew-join "," decrypters-list))) + (cd-or-dec cd) + (privacy (mew-syntax-get-privacy syntax)) + (space " ") (LT (- (max mew-window-magic (window-width)) 2)) + (ln (length number)) + (lm 4) (lt 27) + (ld (* (/ (- LT lm lt) 5) 3)) + (lf (- LT lm ln lt ld 8)) + (marks (make-string lm mew-sp)) + (i 0) (N (length privacy)) + ctm ctp) + + (run-hooks 'mew-syntax-format-hook) + + (if (mew-ct-textp ct) + (if char + (setq ct (concat ct "(" char ")")) + (if dec + (setq ct (concat ct "(" mew-us-ascii ")")) + (if ichar + (setq ct (concat ct "(*" ichar ")")) + (setq ct (concat ct "(guess)")))))) + (if (and dec mew-inherit-alt) (setq ct (concat ct "*"))) + (setq ct (mew-substring ct lt 'cnt)) + + (if (null privacy) + (when cte + (setq cte (downcase cte)) + (cond + ((or (string= cte mew-7bit) + (string= cte mew-8bit) + (string= cte mew-bin)) + ;; no mark + ) + ((string= cte mew-b64) (aset marks 0 ?B)) + ((string= cte mew-qp) (aset marks 0 ?Q)) + ((string= cte mew-xg) (aset marks 0 ?G)) + (t (aset marks 0 ??)))) + + (if dec (setq privacy (reverse privacy))) + (while (< i N) + (mew-set '(ctm ctp) (nth i privacy)) + (let ((case-fold-search t)) + (cond + ((string-match "pgp" ctp) (aset marks (* i 2) ?P)) + ((string-match "pkcs" ctm) (aset marks (* i 2) ?S)) + ((string-match "moss" ctp) (aset marks (* i 2) ?M))) + (cond + ((mew-case-equal mew-ct-mle ctm) (aset marks (1+ (* i 2)) ?E)) + ((mew-case-equal mew-ct-mls ctm) (aset marks (1+ (* i 2)) ?S)) + ((mew-case-equal "enveloped-data" ctp) (aset marks (1+ (* i 2)) ?E)) + ((mew-case-equal "signed-data" ctp) (aset marks (1+ (* i 2)) ?S))) + (setq i (1+ i))))) + + (if (and (not dec) decrypters) (setq cd-or-dec decrypters)) + (setq cd-or-dec (mew-substring cd-or-dec ld 'cnt)) + + (cond + (filename + (setq file filename)) + ((and file (not (string= file ".")) (not (string-match "/$" file))) + (setq file (concat "*" file)))) + (setq file (mew-substring file lf 'cnt)) + + (mew-xinfo-set-multi-form + (cons (concat + marks + (if number (concat space number)) + space space + ct + space space + cd-or-dec + space space + file + "\n") + (mew-xinfo-get-multi-form))))) + +(defun mew-decode-syntax-buffer () + (marker-buffer mew-marker-decode-syntax-begin)) + +(defun mew-decode-syntax-delete () + (when (mew-decode-syntax-p) + (with-current-buffer (mew-decode-syntax-buffer) + (mew-xinfo-set-icon-spec nil) + (mew-summary-toolbar-update) + (save-excursion + (mew-elet + (delete-region (mew-decode-syntax-begin) (mew-decode-syntax-end)))) + (mew-decode-syntax-remove) + (mew-highlight-cursor-line) + (set-buffer-modified-p nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; decode privacy +;; + +(defun mew-decode-syntax-set-privacy (syntax label) + (let (results) + (dolist (privacy (mew-syntax-get-privacy syntax)) + (setq results (concat results (nth 2 privacy)))) + (when results + (mew-xinfo-set-pri-result + (concat (mew-xinfo-get-pri-result) + mew-x-mew: (format " <%s> " label) results "\n"))))) + +(defun mew-decode-syntax-insert-privacy () + (when (mew-xinfo-get-pri-result) + (let ((beg (point))) + (insert (mew-xinfo-get-pri-result)) + (mew-decode-header-property-region beg (point)) + (save-excursion + (save-restriction + (narrow-to-region beg (point)) + (goto-char (point-min)) + (while (re-search-forward "BAD.*sign" nil t) + (put-text-property + (match-beginning 0) + (match-end 0) + 'face 'mew-face-header-xmew-bad))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Broken messages +;; + +(defun mew-decode-syntax-arrange-warning () + (when (mew-xinfo-get-warning) + (mew-xinfo-set-warning + (mew-uniq-list (sort (mew-xinfo-get-warning) 'string<))))) + +(defun mew-decode-syntax-insert-warning () + (when (or (mew-xinfo-get-warning) (mew-xinfo-get-info)) + (let ((beg (point)) + (pref (make-string (1+ (length mew-x-mew:)) mew-sp))) + (when (mew-xinfo-get-warning) + (insert mew-x-mew: " " + (mapconcat 'identity (mew-xinfo-get-warning) pref))) + (when (mew-xinfo-get-info) + (insert mew-x-mew: " " + (mapconcat 'identity (mew-xinfo-get-info) pref))) + (mew-decode-header-property-region beg (point))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; markers +;; + +(defvar mew-marker-decode-syntax-begin (make-marker)) +(defvar mew-marker-decode-syntax-end (make-marker)) + +;; location + +(defun mew-in-decode-syntax-p () + (and (marker-position mew-marker-decode-syntax-begin) + (marker-position mew-marker-decode-syntax-end) + (eq (current-buffer) (marker-buffer mew-marker-decode-syntax-begin)) + (>= (point) (marker-position mew-marker-decode-syntax-begin)) + (< (point) (marker-position mew-marker-decode-syntax-end)))) + +(defun mew-in-header-p () + (let ((end (mew-header-end))) + (and end (<= (point) end)))) + +(defun mew-in-attach-p () + (let ((beg (mew-attach-begin))) + (and beg (> (point) beg)))) ;; excluding the preceding \n + +;; existence + +(defun mew-decode-syntax-p () + (and (marker-position mew-marker-decode-syntax-begin) + (marker-position mew-marker-decode-syntax-end))) + +(defun mew-msghdr-p () + (save-restriction + (widen) + (next-single-property-change (point-min) 'read-only))) + +(defun mew-attach-p () + (if (/= (point-max) 1) + (get-text-property (1- (point-max)) 'mew-attach-end))) + +(defun mew-encode-syntax-have-one-part () + (= (length mew-encode-syntax) (1+ mew-syntax-magic))) + +;; point + +(defun mew-decode-syntax-begin () + (marker-position mew-marker-decode-syntax-begin)) + +(defun mew-decode-syntax-end () + (marker-position mew-marker-decode-syntax-end)) + +(defun mew-header-end () + (mew-msghdr-p)) + +(defun mew-attach-begin () + (if (mew-attach-p) + (let ((beg (previous-single-property-change + (point-max) 'mew-attach-begin))) + (if beg (1- beg) nil)))) + +;; + +(defun mew-decode-syntax-begin-set () + (set-marker mew-marker-decode-syntax-begin (point))) + +(defun mew-decode-syntax-end-set () + (set-marker mew-marker-decode-syntax-end (point))) + +(defun mew-decode-syntax-remove () + (set-marker mew-marker-decode-syntax-begin nil) + (set-marker mew-marker-decode-syntax-end nil)) + +(defun mew-summary-end-of-message-p () + (let (pos beg end) + (with-current-buffer (mew-decode-syntax-buffer) + (save-excursion + (setq pos (point)) + (setq end (mew-decode-syntax-end)) + (goto-char end) + (forward-line -1) + (beginning-of-line) + (setq beg (point)) + (and (<= beg pos) (< pos end)))))) + +;; + +(defun mew-header-set (sep) + (mew-elet + (let ((pos (point))) + (if sep + (progn + (insert-before-markers sep) ;; for mew-summary-reply + (unless (bolp) (forward-line))) + (forward-line)) + (put-text-property pos (point) 'read-only t) + (mew-front-nonsticky pos (1+ pos)) + (if (mew-header-p) + (mew-rear-sticky (1- (point)) (point)) + (mew-rear-nonsticky (1- (point)) (point))) + pos))) + +(defun mew-header-clear (&optional keep-read-only) + ;; the cursor moves to the end of the header (with some exceptions) + (mew-elet + (mew-header-goto-end) ;; do not use mew-header-end + (let ((pos (point))) + (forward-line) + ;; If the body contains the read-only property, mew-in-header-p() + ;; makes a mistake. So, remove the read-only property from + ;; the entire buffer. + (unless keep-read-only + (put-text-property (point) (point-max) 'read-only nil)) + (delete-region pos (point))))) + +;; + +(defun mew-attach-set () + (mew-elet + (let (beg) + (goto-char (point-max)) + (unless (bolp) (insert "\n")) + (setq beg (point)) + (insert "\n") + (insert mew-draft-attach-boundary-beg) + (insert "\n") + (insert mew-draft-attach-boundary-end) + (insert "\n") + (put-text-property beg (1+ beg) 'mew-attach-begin t) + (put-text-property (1- (point)) (point) 'mew-attach-end t) + (beginning-of-line) + (mew-draft-attach-keymap)))) + +(defun mew-attach-clear () + (when (mew-attach-p) + (save-excursion + (mew-elet + (delete-region (mew-attach-begin) (point-max))) + (mew-overlay-delete (mew-tinfo-get-attach-keymap)) + (mew-tinfo-set-attach-keymap nil)))) + +(defun mew-header-prepared () + (mew-header-set (concat mew-header-separator "\n")) + (mew-highlight-header) + (unless (mew-header-p) (mew-draft-header-keymap))) + +(defun mew-draft-header-keymap () + (save-excursion + (if (overlayp (mew-tinfo-get-header-keymap)) + (move-overlay + (mew-tinfo-get-header-keymap) (point-min) (1+ (mew-header-end))) + (mew-tinfo-set-header-keymap + (mew-overlay-make (point-min) (1+ (mew-header-end)))) + (overlay-put + (mew-tinfo-get-header-keymap) 'local-map mew-draft-header-map)))) + +(defun mew-draft-attach-keymap () + (if (overlayp (mew-tinfo-get-attach-keymap)) + (move-overlay + (mew-tinfo-get-attach-keymap) (1+ (mew-attach-begin)) (point-max)) + (mew-tinfo-set-attach-keymap + (mew-overlay-make (1+ (mew-attach-begin)) (point-max))) + (overlay-put + (mew-tinfo-get-attach-keymap) 'local-map mew-draft-attach-map))) + +(provide 'mew-syntax) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-syntax.el ends here diff --git a/elpa/mew-20150813.2354/mew-thread.el b/elpa/mew-20150813.2354/mew-thread.el new file mode 100644 index 00000000..603e658f --- /dev/null +++ b/elpa/mew-20150813.2354/mew-thread.el @@ -0,0 +1,1183 @@ +;;; mew-thread.el + +;; Author: Kazu Yamamoto +;; Created: Feb 1, 1999 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Customizable variables +;;; + +(defvar mew-use-sorted-thread t) + +(defcustom mew-use-complete-thread t + "If non-nil, threads are made using two passes. + +First pass - Repeat the following procedure in numerical order: + (1.0) Pick one message from the message list. + (1.1) Register the current message-id: to DB. + (1.2) Find its parent message-id: in DB. + (1.3) If found, register the current message as a child of + the parent. + (1.4) Otherwise, register the current message to the top + node list. + +Here we have pretty good threads. However, if the messages are not +sorted by Date:, it is possible that some top nodes can be +connected to other threads. If 'mew-use-complete-thread' is non-nil, +the second pass is carried out. + +Second pass - Repeat the following procedure for top nodes linearly: + (2.0) Pick one message from the top node list. + (2.1) Find its parent message-id: in DB. + (2.2) If found, register the current message as a child of + the parent. + (2.3) Otherwise, register the current message to the new top + node list. + +If you have bogus messages and the second pass is carried out, thread +structure MAY loop. This results in an infinite loop of visualizing +threads (not making threads). + +Mew does not provide any loop detection/avoidance mechanism. So, you +should understand this risk." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-thread-indent-strings [" +" " +" " |" " "] + "*Vector of strings to be used for indentation of thread. + +This consists of four members; 1st member for prefixing to a child +message that is not the last one, 2nd member is for prefixing to the +last child, 3rd and 4th members are for prefixing to grand-child thread trees, +4th member is for the child tree of the last child message. + +Example1: [\" +\" \" +\" \" |\" \" \"] makes thread view below. + + Message 1 + +Message 2 + | +Message 3 + +Message 4 + +Message 5 + +Example2: [\" \" \" \" \" \" \" \"] makes thread view below. + + Message 1 + Message 2 + Message 3 + Message 4 + Message 5 + +All members must have the same length." + :group 'mew-summary + :type 'sexp) + +(defcustom mew-use-thread-cursor nil + "*If non-nil, move cursor after the indentation of thread." + :group 'mew-summary + :type 'boolean) + +(defvar mew-use-thread-separator nil + "*If non-nil, the specified string is inserted between threads.") +(defvar mew-thread-separator "--") + +(defun mew-thread-insert-separator () + (if (and mew-use-thread-separator + (/= (save-excursion (beginning-of-line) (point)) 1)) + (insert mew-thread-separator "\n"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Thread info macro +;;; + +(defun mew-thread-make-entry () + (make-vector 5 nil)) + +(defun mew-thread-get-myid (entry) + (aref entry 0)) + +(defun mew-thread-get-prntid (entry) + (aref entry 1)) + +(defun mew-thread-get-child (entry) + (aref entry 2)) + +(defun mew-thread-get-msg (entry) + (aref entry 3)) + +(defun mew-thread-get-line (entry) + (aref entry 4)) + +(defun mew-thread-set-myid (entry myid) + (aset entry 0 myid)) + +(defun mew-thread-set-prntid (entry prntid) + (aset entry 1 prntid)) + +(defun mew-thread-set-child (entry child) + (aset entry 2 child)) + +(defun mew-thread-set-msg (entry msg) + (aset entry 3 msg)) + +(defun mew-thread-set-line (entry line) + (aset entry 4 line)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Thread setup +;;; + +(defvar mew-thread-indent-length nil) +(defvar mew-thread-indent-width nil) + +(defun mew-thread-setup () + (let ((idt1 (aref mew-thread-indent-strings 0)) + (idt2 (aref mew-thread-indent-strings 1)) + (idt3 (aref mew-thread-indent-strings 2)) + (idt4 (aref mew-thread-indent-strings 3))) + (unless (and (= (string-width idt1) (string-width idt2)) + (= (string-width idt2) (string-width idt3)) + (= (string-width idt3) (string-width idt4))) + (error + "All members of mew-thread-indent-strings must have the same length")) + (setq mew-thread-indent-width (string-width idt1)) + (setq mew-thread-indent-length (length idt1)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Commands +;;; + +(defun mew-summary-mark-thread () + "Make threads for messages marked with '*'." + (interactive) + (mew-summary-thread-region (point-min) (point-max) 'mark)) + +(defun mew-thread-cache-valid-p (vfolder) + (let ((cfolder (mew-summary-folder-name 'ext)) + ofld) + (when (get-buffer vfolder) + (with-current-buffer vfolder + (setq ofld (mew-vinfo-get-original-folder)) + (and (equal ofld cfolder) + (get-buffer ofld) + (equal (mew-sinfo-get-cache-time) + (progn (set-buffer ofld) (mew-sinfo-get-cache-time)))))))) + +(defun mew-summary-make-thread (&optional arg) + "If called in Summary mode or Selection, make threads for +all messages. + +If called with '\\[universal-argument]', make threads for +messages in the region. + +If called in Thread, switch back to the corresponding Summary +mode or Selection." + (interactive "P") + (if (mew-mark-active-p) (setq arg t)) + (if arg + (let ((begend (mew-summary-get-region))) + (mew-summary-thread-region (car begend) (cdr begend))) + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (let* ((msg (mew-summary-message-number)) + (disp (mew-sinfo-get-disp-msg)) + (folder (mew-summary-folder-name 'ext)) ;; xxx + fld vfolder) + (cond + ((mew-thread-p) + (setq fld (mew-vinfo-get-original-folder)) + (if (not (and fld (get-buffer fld))) + (message "No original folder") + (mew-summary-visit-folder fld nil 'no-ls) + (mew-summary-toggle-disp-msg (if disp 'on 'off)) + (if (not msg) + (goto-char (point-max)) + (mew-summary-move-and-display msg)))) + ((and (setq vfolder (mew-folder-to-thread folder)) + (mew-thread-cache-valid-p vfolder)) + (mew-summary-visit-folder vfolder) + (mew-summary-toggle-disp-msg (if disp 'on 'off)) + (when msg + (mew-summary-move-and-display msg) + (mew-thread-move-cursor))) + ((mew-selection-p) + (mew-summary-thread-region (point-min) (point-max) nil msg)) + (t + (mew-summary-thread-region (point-min) (point-max) nil msg)))))) + +(defun mew-summary-regexp-make-thread (&optional args) + "Make threads for messages matched to a specified regular expression." + (interactive "P") + (mew-decode-syntax-delete) + (let ((regex "") iter) + (while (string= regex "") + (setq regex (read-string "Regexp: "))) + (if args + (setq iter (lambda () (re-search-forward regex nil t))) + (setq iter (lambda () (mew-summary-search-regexp-visible regex)))) + (mew-summary-thread-region (point-min) (point-max) nil nil iter))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Making thread +;;; + +(defun mew-thread-get-iter (mark iter) + (cond + (iter iter) + (mark (lambda () (re-search-forward mew-regex-msg-review nil t))) + (t (lambda () (not (eobp)))))) + +(defun mew-thread-create-db (size) + (let ((dbsize + (cond + ((<= size 211) 211) + ((<= size 1511) 1511) + ((<= size 7211) 7211) + (t 18211)))) + (make-vector dbsize 0))) ;; hash + +(defun mew-thread-pass-1 (db func) + (let (start msg my-id prnt-id prnt-cld me top line prnt) + (save-excursion + (goto-char (point-min)) + (while (funcall func) + (beginning-of-line) + (setq start (point)) + (if (not (mew-sumsyn-match mew-regex-sumsyn-long)) + (forward-line) + (setq msg (mew-sumsyn-message-number)) + (setq my-id (mew-sumsyn-my-id)) + (setq prnt-id (mew-sumsyn-parent-id)) + (forward-line) + ;; Throw away properties here and give properties later. + ;; This is faster than inheriting properties. + (setq line (mew-buffer-substring start (point))) + (setq me (mew-thread-make-entry)) + (mew-thread-set-msg me msg) + (mew-thread-set-line me line) + (if (string= my-id "") + (setq top (cons me top)) + ;; some broken messages refer themselves + ;; don't register me here so that his parent + ;; will not be found. + (if (or (string= prnt-id "") (string= my-id prnt-id)) + (setq top (cons me top)) + (mew-thread-set-prntid me prnt-id) + (setq prnt (symbol-value (intern-soft prnt-id db))) + (if (null prnt) + (setq top (cons me top)) + (setq prnt-cld (mew-thread-get-child prnt)) + (if prnt-cld + (nconc prnt-cld (list me)) + (mew-thread-set-child prnt (list me))))) + (mew-thread-set-myid me my-id) + (set (intern my-id db) me))))) + top)) + +(defun mew-summary-setup-vfolder (db top column) + (let* ((ofolder (mew-summary-folder-name 'ext)) + (vfolder (mew-folder-to-thread ofolder)) + (pfolder (mew-summary-physical-folder)) + (disp (mew-sinfo-get-disp-msg)) + (ctime (mew-sinfo-get-cache-time)) + (case (mew-sinfo-get-case))) + (mew-summary-switch-to-folder vfolder) + (mew-vinfo-set-mode 'thread) + (mew-vinfo-set-physical-folder pfolder) + (mew-vinfo-set-original-folder ofolder) + (mew-erase-buffer) + (mew-hscroll) + (mew-summary-toggle-disp-msg (if disp 'on 'off)) + (mew-sinfo-set-cache-time ctime) + (mew-sinfo-set-case case) + (setq mew-summary-buffer-raw t) + (mew-vinfo-set-db db) + (mew-vinfo-set-top top) + (mew-vinfo-set-column column))) + +(defun mew-thread-pass-2 (db top) + (if (null mew-use-complete-thread) + (nreverse top) + ;; This may create looped thread. + ;; See mew-use-complete-thread for more information. + (let (prnt prnt-id prnt-cld ret) + (dolist (me top) + (if (not (and (mew-thread-get-myid me) + (setq prnt-id (mew-thread-get-prntid me)))) + (setq ret (cons me ret)) + (setq prnt (symbol-value (intern-soft prnt-id db))) + (if (null prnt) + (setq ret (cons me ret)) + (setq prnt-cld (mew-thread-get-child prnt)) + (if prnt-cld + (setq prnt-cld (nconc prnt-cld (list me))) + (mew-thread-set-child prnt (list me)))))) + ret))) + +(defun mew-thread-postscript (mark disp-msg) + (when mark (mew-mark-undo-mark mew-mark-review)) + (jit-lock-register 'mew-summary-cook-region) + (mew-summary-set-count-line) + (set-buffer-modified-p nil) + (if disp-msg + (mew-summary-move-and-display disp-msg) + (goto-char (point-max))) + (mew-thread-move-cursor)) + +(defun mew-thread-debug-info (tm1 tm2 tm3 tm4 tm5 tm6) + (when (mew-debug 'thread) + (let* ((t1 (mew-time-calc tm2 tm1)) + (t2 (mew-time-calc tm4 tm3)) + (t3 (mew-time-calc tm6 tm5))) + (message "pass1 %f, pass2 %f, visual %f" t1 t2 t3)))) + +(defun mew-summary-thread-region (beg end &optional mark disp-msg iter) + "Make threads for messages in a region. If you want to know how +threads are created, see 'mew-use-complete-thread'." + (interactive "r") + (when (mew-summary-exclusive-p) + (let* ((column (or (mew-sinfo-get-summary-column) ;; scanned + ;; Summary only + (mew-get-summary-column (mew-summary-folder-name 'ext)))) + db top tm1 tm2 tm3 tm4 tm5 tm6) + (save-restriction + (narrow-to-region beg end) + (setq db (mew-thread-create-db (count-lines beg end))) + ;; + (message "Making thread (first pass)...") + (setq tm1 (current-time)) + (setq top (mew-thread-pass-1 db (mew-thread-get-iter mark iter))) + (setq tm2 (current-time))) + ;; + (if (null top) + (message "No target messages") + (message "Making thread (second pass)...") + (setq tm3 (current-time)) + (setq top (mew-thread-pass-2 db top)) + (setq tm4 (current-time)) + ;; + (mew-summary-setup-vfolder db top column) + ;; + (message "Displaying thread...") + (setq tm5 (current-time)) + (mew-summary-thread-print-top (mew-vinfo-get-top) column) + (setq tm6 (current-time)) + ;; + (mew-thread-postscript mark disp-msg) + ;; + (message "Displaying thread...done") + (run-hooks 'mew-thread-display-hook) + (mew-thread-debug-info tm1 tm2 tm3 tm4 tm5 tm6))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Subfunctions +;;; + +(defun mew-thread-put-property (beg end level) + (put-text-property beg end 'mew-thread-indent level)) + +(defun mew-thread-get-property (beg) + (get-text-property beg 'mew-thread-indent)) + +(defun mew-thread-previous-property (beg) + (previous-single-property-change beg 'mew-thread-indent)) + +(defun mew-thread-next-property (beg) + (next-single-property-change beg 'mew-thread-indent)) + +(defun mew-thread-next-property2 (beg end level) + (text-property-any beg end 'mew-thread-indent level)) + +(defun mew-thread-adjust-body (level) + (when (mew-summary-goto-body) + (mew-elet + (let ((end (point)) + (width (* level mew-thread-indent-width)) + (sum 0)) + (while (< sum width) + (setq sum (+ (char-width (char-before)) sum)) + (forward-char -1)) + (delete-region (point) end) + (when (/= sum width) + (insert (make-string (- sum width) mew-sp))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Visualizing thread +;;; + +(defun mew-summary-thread-print-top (top column) + (let (cld) + (dolist (me top) + (setq cld (mew-thread-get-child me)) + (mew-elet + (mew-thread-insert-separator) + (insert (mew-thread-get-line me)) + (forward-line -1) + (move-to-column column) + (mew-thread-put-property (point) (1+ (point)) 0) + (forward-line)) + (if cld (mew-summary-thread-print-tree cld column))))) + +(defun mew-summary-thread-print-tree (tree column) + (let ((tree-stack nil) + (prefix "") + (level 1) pos) + (while tree + (let* ((me (car tree)) + (next (cdr tree)) + (cld (mew-thread-get-child me))) + (mew-elet + (insert (mew-thread-get-line me)) + (forward-line -1) + (move-to-column column) + (setq pos (point)) + (if next + (insert prefix (aref mew-thread-indent-strings 0)) + (insert prefix (aref mew-thread-indent-strings 1))) + (mew-thread-put-property pos (point) level) + (mew-thread-adjust-body level) + (forward-line)) + ;; + (setq tree next) + (cond + (cld + (if next + (setq prefix + (concat prefix (aref mew-thread-indent-strings 2))) + (setq prefix + (concat prefix (aref mew-thread-indent-strings 3)))) + (setq tree-stack (cons tree tree-stack)) + (setq tree cld) + (setq level (1+ level))) + (t + (while (and (null tree) tree-stack) + (setq prefix (substring prefix 0 (- mew-thread-indent-length))) + (setq tree (car tree-stack)) + (setq tree-stack (cdr tree-stack)) + (setq level (1- level))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Marking thread +;;; + +(defun mew-thread-mark-review () + "Put the '*' mark on all messages of the current sub-thread." + (interactive) + (mew-thread-mark mew-mark-review)) + +(defun mew-thread-mark-delete () + "Put the 'D' mark on all messages of the current sub-thread." + (interactive) + (mew-summary-not-in-nntp + (mew-thread-mark mew-mark-delete 'valid-only))) + +(defun mew-thread-mark-unlink () + "Put the 'X' mark on all messages of the current sub-thread." + (interactive) + (mew-thread-mark mew-mark-unlink 'valid-only)) + +(defun mew-thread-mark-escape () + "Put the '$' mark on all messages of the current sub-thread." + (interactive) + (mew-thread-mark mew-mark-escape)) + +(defun mew-thread-mark-refile () + "Put the 'o' mark on all messages of the current sub-thread." + (interactive) + (mew-thread-only + (let* ((fld (mew-folder-basename (mew-summary-folder-name 'ext))) + (folders (mew-summary-refile-body nil nil nil 'no-mark)) + (folders-str (mew-join "," folders)) + (func (lambda () + (mew-summary-refile-override-body folders-str) + (unless (mew-virtual-p) + (mew-summary-refile-log fld folders-str)))) + alist) + (when folders + (setq alist (mew-thread-mark mew-mark-refile 'valid-only func)) + (mew-refile-set-from-alist alist folders))))) + +(defun mew-thread-mark-copy () + "Put the 'o' mark on all messages of the current sub-thread +with the current folder as a candidate in addition to guessed folders." + (interactive) + (mew-thread-only + (let* ((folders (mew-summary-refile-body + nil nil nil 'no-mark (mew-summary-folder-name))) + (folders-str (mew-join "," folders)) + (func (lambda () (mew-summary-refile-override-body folders-str))) + alist) + (when folders + (setq alist (mew-thread-mark mew-mark-refile 'valid-only func)) + (mew-refile-set-from-alist alist folders))))) + +(defun mew-refile-set-from-alist (alist folders) + (let (fld) + (dolist (ent alist) + (setq fld (car ent)) + (dolist (msg (sort (copy-sequence (cdr ent)) '<)) ;; sort has side effect + (setq msg (number-to-string msg)) + (when (get-buffer fld) + (with-current-buffer fld + (mew-refile-reset msg) + (mew-refile-set msg folders))))))) + +(defun mew-thread-mark (mark &optional valid-only func) + (mew-thread-only + (mew-summary-msg-or-part + (let ((regex (if valid-only mew-regex-sumsyn-valid mew-regex-sumsyn-short)) + (column (mew-vinfo-get-column)) + indent cindent fld msg alist bottom pruned) + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (save-excursion + (beginning-of-line) + (when (looking-at + (concat "^." (regexp-quote (char-to-string mew-mark-thread-root)))) + (setq pruned (point)) + (mew-thread-graft 'nomsg)) + (move-to-column column) + (setq indent (mew-thread-get-property (point))) + (when (mew-sumsyn-match regex) + (setq fld (mew-sumsyn-folder-name)) + (setq msg (mew-sumsyn-message-number)) + (if func (funcall func)) + (mew-mark-put mark) + (mew-mark-alist-set alist fld msg)) + (forward-line) + (catch 'loop + (while (not (eobp)) + (move-to-column column) + (when (setq cindent (mew-thread-get-property (point))) + (if (>= indent cindent) + (throw 'loop nil) + (when (mew-sumsyn-match regex) + (setq fld (mew-sumsyn-folder-name)) + (setq msg (mew-sumsyn-message-number)) + (if func (funcall func)) + (mew-mark-put mark) + (mew-mark-alist-set alist fld msg)))) + (forward-line))) + (beginning-of-line) + (setq bottom (point)) + (mew-summary-mark-in-physical-alist alist mark func) + (when pruned + (goto-char pruned) + (mew-thread-prune 'nomsg))) + (mew-push-mark) + (let ((mew-summary-down-function (lambda () (goto-char bottom)))) + (mew-summary-display-after mew-summary-mark-direction)) + alist)))) + +(defun mew-thread-undo (fld msg) + (let* ((mark (mew-summary-get-mark)) + (func (mew-markdb-func-undo mark))) + (and func (fboundp func) (funcall func fld msg)))) + +(defun mew-thread-unmark () + "Unmark messages under this sub-thread." + (interactive) + (mew-thread-only + (mew-summary-msg-or-part + (let ((column (mew-vinfo-get-column)) + fld msg alist indent cindent pruned) + (mew-summary-goto-message) + (mew-thread-move-cursor) + (mew-decode-syntax-delete) + (save-excursion + (beginning-of-line) + (when (looking-at + (concat "^." (regexp-quote (char-to-string mew-mark-thread-root)))) + (setq pruned (point)) + (mew-thread-graft 'nomsg)) + (move-to-column column) + (setq indent (mew-thread-get-property (point))) + (setq fld (mew-summary-folder-name)) + (setq msg (mew-summary-message-number)) + (mew-mark-alist-set alist fld msg) + (mew-thread-undo fld msg) + (mew-mark-unmark) + (forward-line) + (catch 'loop + (while (not (eobp)) + (move-to-column column) + (when (setq cindent (mew-thread-get-property (point))) + (if (>= indent cindent) + (throw 'loop nil) + (setq fld (mew-summary-folder-name)) + (setq msg (mew-summary-message-number)) + (mew-mark-alist-set alist fld msg) + (mew-thread-undo fld msg) + (mew-mark-unmark))) + (forward-line))) + (when pruned + (goto-char pruned) + (mew-thread-prune 'nomsg)) + (mew-thread-unmark-physical-from-alist alist)))))) + +(defun mew-thread-unmark-physical-from-alist (alist) + (let (fld msgs) + (dolist (ent alist) + (setq fld (car ent)) + (setq msgs (sort (copy-sequence (cdr ent)) '<)) ;; sort has side effect + (when (get-buffer fld) + (set-buffer fld) + (save-excursion + (goto-char (point-min)) + (dolist (msg msgs) + (setq msg (number-to-string msg)) + (when (re-search-forward (mew-regex-sumsyn-msg msg) nil t) + (mew-thread-undo fld msg) + (mew-mark-unmark)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Thread utilities +;;; + +(defun mew-thread-up () + "Move onto the top of the current thread. If the current message is +a top node, move onto the top of the previous thread." + (interactive) + (mew-thread-only + (let (here pos) + (mew-summary-goto-message) + (save-excursion + (mew-decode-syntax-delete) + (beginning-of-line) + (setq pos (point)) + (catch 'loop + (while (and (not (bobp)) + (setq pos (mew-thread-previous-property pos))) + (when (and pos (eq (mew-thread-get-property pos) 0)) + (throw 'loop (setq here pos)))))) + (if (not here) + (message "No more threads") + (goto-char here) + (mew-thread-move-cursor) + (mew-summary-display))))) + +(defun mew-thread-down () + "Move onto the top of the next thread." + (interactive) + (mew-thread-only + (let (here) + (mew-summary-goto-message) + (save-excursion + (mew-decode-syntax-delete) + (forward-line) + (setq here (mew-thread-next-property2 (point) (point-max) 0))) + (if (not here) + (message "No more threads") + (goto-char here) + (unless (mew-summary-message-number) (forward-line)) + (mew-thread-move-cursor) + (mew-summary-display))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Diag +;;; + +(defun mew-summary-parent-global (par-id) + (mew-summary-diag-global par-id "-p" "Parent")) + +(defun mew-summary-child-global (my-id) + (mew-summary-diag-global my-id "-c" "Child")) + +(defun mew-summary-diag-global (id opt who) + (mew-msgid-check + (let ((db (mew-expand-file "+" mew-id-db-file)) + (regex (format "\\(.*\\)/\\([0-9]+\\)\\(%s\\)?$" (regexp-quote mew-suffix))) + path msg folder) + (with-temp-buffer + (mew-piolet mew-cs-text-for-read mew-cs-text-for-write + (call-process mew-prog-smew nil t nil opt id db "") + (goto-char (point-min)) + (when (looking-at regex) + (setq path (mew-match-string 1)) + (setq msg (mew-match-string 2))))) + (if (not msg) + nil + (setq folder (mew-folder-path-to-folder path)) + (when folder + (mew-summary-visit-folder folder nil 'no-ls) + (if (mew-summary-search-msg msg) + (progn + (mew-summary-display) + t) + (concat who " not found. Scan 'update would be necessary"))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Parent +;;; + +(defun mew-summary-parent () + "Move onto the parent message of the current message." + (interactive) + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (let ((par-id (mew-summary-parent-id)) result) + (cond + ((or (null par-id) (string= par-id "")) + (message "No parent")) + ((mew-summary-parent-local par-id) + (message "Parent found")) + ((and (y-or-n-p "No parent in this folder. Find in others? ") + (setq result (mew-summary-parent-global par-id))) + (if (eq result t) + (message "Parent found") + (message "%s" result))) + (t + (message "Parent not found"))))) + +(defun mew-summary-parent-local (par-id) + (let ((pos (point)) + (key (mew-regex-sumsyn-my-id par-id))) + (if (or (re-search-backward key nil t) + (re-search-forward key nil t)) + (progn + (mew-thread-move-cursor) + (mew-summary-display) + t) + (goto-char pos) + nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Child +;;; + +(defun mew-summary-child () + "Move onto the first child message of the current message." + (interactive) + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (let ((my-id (mew-summary-my-id)) result) + (cond + ((or (null my-id) (string= my-id "")) + (message "No child")) + ((mew-summary-child-local my-id) + (message "Child found")) + ((and (y-or-n-p "No child in this folder. Find in others? ") + (setq result (mew-summary-child-global my-id))) + (if (eq result t) + (message "Child found") + (message "%s" result))) + (t + (message "Child not found"))))) + +(defun mew-summary-child-local (my-id) + (let ((pos (point)) + (key (mew-regex-sumsyn-par-id my-id))) + (if (or (re-search-forward key nil t) + (re-search-backward key nil t)) + (progn + (mew-thread-move-cursor) + (mew-summary-display) + t) + (goto-char pos) + nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sibling +;;; + +(defun mew-summary-thread-sibling-up () + "Search backward by one sibling message of the current message." + (interactive) + (let ((pos (point)) + (par-id (mew-summary-parent-id)) + key) + (if (or (null par-id) (string= par-id "")) + (message "No sibling") + (setq key (mew-regex-sumsyn-par-id par-id)) + (if (re-search-backward key nil t) + (progn + (mew-thread-move-cursor) + (mew-summary-display) + (message "Sibling found")) + (goto-char pos) + (message "Sibling not found"))))) + +(defun mew-summary-thread-sibling-down () + "Search forward by one sibling message of the current message." + (interactive) + (let ((pos (point)) + (par-id (mew-summary-parent-id)) + key) + (if (or (null par-id) (string= par-id "")) + (message "No sibling") + (setq key (mew-regex-sumsyn-par-id par-id)) + (forward-line) + (if (re-search-forward key nil t) + (progn + (mew-thread-move-cursor) + (mew-summary-display) + (message "Sibling found")) + (goto-char pos) + (message "Sibling not found"))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Thread sub-functions +;;; + +(defun mew-thread-move-cursor () + "Move cursor after indentation of thread." + (if (and mew-use-thread-cursor + (mew-thread-p) + (mew-summary-message-number)) + (let (indent) + (move-to-column (mew-vinfo-get-column)) + (if (setq indent (mew-thread-get-property (point))) + (unless (= indent 0) + (goto-char (mew-thread-next-property (point)))) + (beginning-of-line))) + (beginning-of-line))) + +(defun mew-summary-thread-get-msglst (tree &optional add-separator) + "Get a list of message in the thread order specified by TREE." + (let ((tree-stack nil) (level 0) msgs me cld) + (while tree + (setq me (car tree)) + (setq cld (mew-thread-get-child me)) + (if (and mew-use-thread-separator add-separator (= level 0)) + (setq msgs (cons "s" msgs))) ;; "s" thread-separator line + (setq msgs (cons (mew-thread-get-msg me) msgs)) + (setq tree (cdr tree)) + (if (null cld) + (while (and (null tree) tree-stack) + (setq tree (car tree-stack)) + (setq tree-stack (cdr tree-stack)) + (setq level (1- level))) + (setq tree-stack (cons tree tree-stack)) + (setq tree cld) + (setq level (1+ level)))) + (if (and mew-use-thread-separator add-separator) + ;; discard first "s" + (cdr (nreverse msgs)) + (nreverse msgs)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Hide/disclose children +;;; + +(defvar mew-mark-thread-root ?+) + +(defun mew-thread-toggle () + "If children of a message are displayed, they will hide and +\"+\" is displayed on the parent. +If the children are hidden, they will appear." + (interactive) + (mew-thread-only + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (if (looking-at (concat "^." (regexp-quote (char-to-string mew-mark-thread-root)))) + (mew-thread-graft) + (mew-thread-prune)) + (mew-thread-move-cursor) + (set-buffer-modified-p nil))) + +(defun mew-thread-toggle-all () + "Toggle appearance of children for all threads." + (interactive) + (mew-thread-only + (let (here) + (save-excursion + (goto-char (point-min)) + (mew-decode-syntax-delete) + (while (setq here (mew-thread-next-property2 (point) (point-max) 0)) + (goto-char here) + (beginning-of-line) + (if (looking-at (concat "^." (regexp-quote (char-to-string mew-mark-thread-root)))) + (mew-thread-graft) + (mew-thread-prune)) + (forward-line)) + (mew-thread-move-cursor) + (set-buffer-modified-p nil))))) + +(defun mew-thread-all-prune () + "Hide all children." + (interactive) + (mew-thread-only + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (save-excursion + (goto-char (point-min)) + (let (pos) + (while (setq pos (mew-thread-next-property2 (point) (point-max) 0)) + (goto-char pos) + (mew-thread-prune 'nomsg) + (forward-line)))) + (when (eq (get-text-property (point) 'invisible) t) + (mew-re-search-backward-visible mew-regex-msg-or-part)) + (mew-thread-move-cursor) + (set-buffer-modified-p nil))) + +(defun mew-thread-all-graft () + "Display all children." + (interactive) + (mew-thread-only + (mew-summary-goto-message) + (mew-decode-syntax-delete) + (save-excursion + (goto-char (point-min)) + (let ((regex (concat "^." (regexp-quote (char-to-string mew-mark-thread-root))))) + (while (re-search-forward regex nil t) + (mew-thread-graft 'nomsg) + (forward-line)))) + (mew-thread-move-cursor) + (set-buffer-modified-p nil))) + +(defun mew-thread-prune (&optional nomsg) + (beginning-of-line) + (let ((pos (mew-thread-next-property (point)))) + (unless (and pos (eq (mew-thread-get-property pos) 0)) ;; root + (catch 'loop + (while (setq pos (mew-thread-previous-property pos)) + (when (and pos (eq (mew-thread-get-property pos) 0)) + (throw 'loop (goto-char pos))))))) + (beginning-of-line) + (save-excursion + (forward-line) + (let ((beg (point)) + (next (mew-thread-next-property2 (point) (point-max) 0))) + (goto-char (or next (point-max))) + (forward-line -1) + (if (mew-summary-message-number) (forward-line)) + (if (= beg (point)) + (or nomsg (message "No children to be pruned")) + (mew-elet + (put-text-property beg (point) 'invisible t) + (goto-char beg) + (forward-line -1) + (forward-char) + (put-text-property (point) (1+ (point)) 'invisible t) + (insert mew-mark-thread-root)))))) + +(defun mew-thread-graft (&optional nomsg) + (save-excursion + (forward-line) + (let ((start (point)) + (next (mew-thread-next-property2 (point) (point-max) 0)) + beg end) + (goto-char (or next (point-max))) + (forward-line -1) + (if (mew-summary-message-number) (forward-line)) + (setq end (point)) + (if (= start end) + (or nomsg (message "No children to be leaned")) + (mew-elet + (goto-char start) + (setq beg start) + (while (search-forward "\r" end t) + (put-text-property beg (1- (point)) 'invisible nil) + (forward-line) + (put-text-property (1- (point)) (point) 'invisible nil) + (setq beg (point))) + (goto-char start) + (forward-line -1) + (forward-char) + (delete-char 1) + (put-text-property (point) (1+ (point)) 'invisible nil)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Thread editing +;;; + +(defun mew-thread-glue () + "Glue a thread/message to the current message as its child(ren). +The thread/message is specified with the mark(\\[set-mark-command])." + (interactive) + (mew-summary-msg + (let* ((zmacs-regions nil) + (pos (marker-position (mark-marker)))) + (cond + ((null pos) + (message "No marker")) + ((mew-thread-p) + (mew-thread-glue-it)) + (t ;; summary or virtual + (mew-summary-glue-it)))))) + +(defun mew-summary-glue-it () + (save-excursion + (mew-summary-goto-message) + (beginning-of-line) + ;; parent + (let ((id (mew-summary-my-id)) + fld msg) + (goto-char (mark-marker));; user's mark + ;; children + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (setq fld (mew-sumsyn-folder-name)) + (setq msg (mew-sumsyn-message-number))) + (when (and fld msg id) + (mew-thread-change-parent-id id) + (mew-thread-save-xref fld msg id) + (if (mew-virtual-p) + (mew-summary-change-parent-id fld msg id)) + (message "Glued"))))) + +(defun mew-thread-glue-it () + (let ((column (mew-vinfo-get-column)) + (width 0) (wd 0) (adjust 0) + (prefix "") + fld msg id beg end tree indent idt pbeg pindent has-child m) + (save-excursion + ;; parent + (mew-summary-goto-message) + (beginning-of-line) + (setq id (mew-summary-my-id)) + (move-to-column column) + (setq beg (point)) + (setq pindent (mew-thread-get-property (point))) + (goto-char (mew-thread-next-property (point))) + (setq end (point)) + (unless (= pindent 0) + (while (< width mew-thread-indent-width) + (forward-char -1) + (setq width (+ width (char-width (char-after))))) + (setq prefix (mew-buffer-substring beg (point))) + (if (string= (mew-buffer-substring (point) end) + (aref mew-thread-indent-strings 0)) + (setq prefix (concat prefix (aref mew-thread-indent-strings 2))) + (setq prefix (concat prefix (aref mew-thread-indent-strings 3))))) + (when (mew-summary-goto-body) + (while (> (point) beg) + (setq wd (+ wd (char-width (char-before)))) + (forward-char -1))) + (setq wd (/ wd mew-thread-indent-width)) + (if (> pindent wd) (setq adjust (- pindent wd))) + (setq pindent (1+ pindent)) + (forward-line) + ;; the next line of parent + (setq m (point-marker)) + (unless (looking-at mew-regex-thread-separator) + (move-to-column column) + (if (and (mew-thread-get-property (point)) + (= (mew-thread-get-property (point)) pindent)) + (setq has-child t))) + (move-to-column column) + ;; children + (goto-char (mark-marker));; user's mark + (when (mew-sumsyn-match mew-regex-sumsyn-long) + (setq fld (mew-sumsyn-folder-name)) + (setq msg (mew-sumsyn-message-number))) + (when (and fld msg id) + (mew-elet + (mew-syntax-change-parent-id id) + (beginning-of-line) + (setq beg (point)) + (move-to-column column) + (setq pbeg (point)) + (setq indent (mew-thread-get-property (point))) + (insert prefix) + (if has-child + (insert (aref mew-thread-indent-strings 0)) + (insert (aref mew-thread-indent-strings 1))) + (goto-char (mew-thread-next-property (point))) + (mew-thread-put-property pbeg (point) (+ indent pindent)) + (mew-thread-adjust-body (- pindent adjust)) + (catch 'loop + (while t + (forward-line) + (move-to-column column) + (setq pbeg (point)) + (setq idt (mew-thread-get-property (point))) + (if (or (null idt) (<= idt indent)) + (throw 'loop nil)) + (insert prefix) + (if has-child + (insert (aref mew-thread-indent-strings 2)) + (insert (aref mew-thread-indent-strings 3))) + (goto-char (mew-thread-next-property (point))) + (mew-thread-put-property pbeg (point) (+ idt pindent)) + (mew-thread-adjust-body (- pindent adjust)))) + (beginning-of-line) + (setq end (point)) + (when (looking-at mew-regex-thread-separator) + (forward-line) + (delete-region end (point))) + ;; This must be "buffer-substring". + (setq tree (buffer-substring beg end)) + (delete-region beg end) + ;; the next line of parent + (goto-char m) + (insert tree) + (set-buffer-modified-p nil)) + (mew-summary-change-parent-id fld msg id) + (mew-thread-save-xref fld msg id))))) + +(defun mew-summary-change-parent-id (fld msg id) + (set-buffer fld) + (save-excursion + (when (mew-summary-search-msg msg) + (mew-thread-change-parent-id id)))) + +(defun mew-thread-change-parent-id (id) + (mew-elet + (mew-syntax-change-parent-id id)) + (unless (mew-virtual-p) + (mew-summary-folder-cache-save)) + (set-buffer-modified-p nil)) + +(defun mew-thread-save-xref (fld msg id) + (with-temp-buffer + (let ((file (mew-expand-msg fld msg))) + (mew-plet + (mew-insert-file-contents2 file) + (mew-header-delete-lines (list mew-x-mew-ref:)) + (goto-char (point-min)) + (mew-header-insert mew-x-mew-ref: id) + (write-region (point-min) (point-max) file nil 'no-msg))))) + +(provide 'mew-thread) + +;;; Copyright Notice: + +;; Copyright (C) 2000-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-thread.el ends here diff --git a/elpa/mew-20150813.2354/mew-unix.el b/elpa/mew-20150813.2354/mew-unix.el new file mode 100644 index 00000000..7b5ecd2a --- /dev/null +++ b/elpa/mew-20150813.2354/mew-unix.el @@ -0,0 +1,149 @@ +;;; mew-unix.el -- MIME content type for UNIX + +;; Author: Kazu Yamamoto +;; Created: Dec 4, 1997 + +;;; Code: + +;;; +;;; Text/Html, Application/Xml +;;; + +(defvar mew-format-html "%s.html") +(defvar mew-format-xml "%s.xml") + +(defvar mew-unix-browser "firefox") +(defvar mew-unix-browser-arg '("%s")) +(defvar mew-unix-browser-form `(,mew-unix-browser ,mew-unix-browser-arg t)) + +(defvar mew-prog-text/html + (if (and (fboundp 'shr-render-region) + (fboundp 'libxml-parse-html-region)) + 'shr-render-region + 'mew-mime-text/html-w3m)) ;; See w3m.el +(defvar mew-prog-text/html-ext mew-unix-browser-form) + +(defvar mew-prog-text/xml + (if (and (fboundp 'shr-render-region) + (fboundp 'libxml-parse-html-region)) + 'shr-render-region + 'mew-mime-text/html-w3m)) ;; See w3m.el +(defvar mew-prog-text/xml-ext mew-unix-browser-form) + +(defvar mew-prog-application/xml nil) +(defvar mew-prog-application/xml-ext mew-unix-browser-form) + + +;;; +;;; Image +;;; + +(defvar mew-prog-image/* 'mew-mime-image/*) +(defvar mew-prog-image/*-ext '("display" ("-geometry" "+0+0"))) + +;;; +;;; MIME setting +;;; + +(defvar mew-prog-plain 'mew-mime-text/plain) +(defvar mew-prog-html '(mew-mime-text/html mew-mime-text/html-ext)) +(defvar mew-prog-xml '(mew-mime-text/xml mew-mime-text/xml-ext)) +(defvar mew-prog-patch '(mew-mime-text/plain mew-mime-text/patch-ext)) +(defvar mew-prog-enriched 'mew-mime-text/enriched) +(defvar mew-prog-text 'mew-mime-text/plain) +(defvar mew-prog-audio + `(,shell-file-name (,shell-command-switch "cat - > /dev/audio") nil)) +(defvar mew-prog-audio2 + `(,shell-file-name (,shell-command-switch "cat < /dev/audio") nil)) +(defvar mew-prog-image '(mew-mime-image/* mew-mime-image/*-ext)) +(defvar mew-prog-iges nil) +(defvar mew-prog-vrml nil) +(defvar mew-prog-mesh nil) +(defvar mew-prog-video '("xine" ("--auto-play") t)) +(defvar mew-prog-rfc822 'mew-mime-message/rfc822) +(defvar mew-prog-rfc822-headers 'mew-mime-text/rfc822-headers) +(defvar mew-prog-external-body '(mew-mime-external-body mew-mime-external-body-ext)) +(defvar mew-prog-delivery-status 'mew-mime-text/plain) +(defvar mew-prog-postscript '("gv" ("-geometry" "+0+0") t)) +(defvar mew-prog-xml2 '(mew-mime-application/xml + mew-mime-application/xml-ext)) +(defvar mew-prog-pgp-keys '(mew-mime-pgp-keys mew-mime-pgp-keys-ext)) +(defvar mew-prog-oasys nil) +(defvar mew-prog-octet-stream 'mew-mime-application/octet-stream) + +(defvar mew-prog-visio 'mew-mime-application/octet-stream) +(defvar mew-prog-mstnef '(mew-mime-application-ms-tnef + mew-mime-application-ms-tnef-ext)) +(defvar mew-prog-unzip 'mew-mime-application/octet-stream) + +;;; +;;; +;;; + +(defvar mew-prog-application/pdf "pdftotext") +(defvar mew-prog-pdf-ext '("xpdf" ("-geometry" "+0+0") t)) +(defvar mew-prog-pdf `(mew-mime-application/pdf ,mew-prog-pdf-ext)) + +(defvar mew-prog-application/rtf "rtf2html") +(defvar mew-prog-rtf '(mew-mime-application/rtf + mew-mime-application/rtf-ext)) + +;;; +;;; Office +;;; + +(defvar mew-prog-ooffice "ooffice") + +(defvar mew-prog-application/msword "wvHtml") +(defvar mew-prog-msword-ext mew-prog-ooffice) +(defvar mew-prog-msword `(mew-mime-application/msword ,mew-prog-msword-ext)) + + +(defvar mew-prog-application/msexcel "xlhtml") +(defvar mew-prog-msexcel-ext mew-prog-ooffice) +(defvar mew-prog-msexcel `(mew-mime-application/msexcel ,mew-prog-msexcel-ext)) + +(defvar mew-prog-application/mspowerpoint "ppthtml") +(defvar mew-prog-mspowerpoint-ext mew-prog-ooffice) +(defvar mew-prog-mspowerpoint `(mew-mime-application/mspowerpoint ,mew-prog-mspowerpoint-ext)) + +;;; +;;; Misc +;;; + +(defvar mew-default-external-program nil) +(defvar mew-dir-list-function 'mew-dir-list-with-link-count) + +(provide 'mew-unix) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-unix.el ends here diff --git a/elpa/mew-20150813.2354/mew-vars.el b/elpa/mew-20150813.2354/mew-vars.el new file mode 100644 index 00000000..167cb67f --- /dev/null +++ b/elpa/mew-20150813.2354/mew-vars.el @@ -0,0 +1,3319 @@ +;;; mew-vars.el --- Variables and Constants for Mew + +;; Author: Kazu Yamamoto +;; Created: Nov 22, 1997 + +;;; Code: + +(require 'mew-env) + +;;; +;;; User option variables which are easy to set. +;;; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Defining groups +;;; + +(defgroup mew nil + "Messaging in the Emacs World." + :group 'mail) + +(defgroup mew-basic nil + "Basic configuration." + :group 'mew) + +(defgroup mew-env nil + "Basic environment." + :group 'mew) + +(defgroup mew-folder nil + "Basic folder." + :group 'mew) + +(defgroup mew-summary nil + "Summary mode." + :group 'mew) + +(defgroup mew-message nil + "Message mode." + :group 'mew) + +(defgroup mew-cache nil + "Message Caching." + :group 'mew) + +(defgroup mew-draft nil + "Draft mode." + :group 'mew) + +(defgroup mew-cite nil + "Citation." + :group 'mew) + +(defgroup mew-reply nil + "Reply to message." + :group 'mew) + +(defgroup mew-refile nil + "Refiling." + :group 'mew) + +(defgroup mew-complete nil + "Completion." + :group 'mew) + +(defgroup mew-highlight nil + "Highlight." + :group 'faces + :group 'mew) + +(defgroup mew-privacy nil + "Privacy setting." + :group 'mew) + +(defgroup mew-addrbook nil + "Address book." + :group 'mew) + +(defgroup mew-net nil + "Network." + :group 'mew) + +(defgroup mew-pop nil + "POP." + :group 'mew) + +(defgroup mew-smtp nil + "SMTP." + :group 'mew) + +(defgroup mew-imap nil + "IMAP." + :group 'mew) + +(defgroup mew-nntp nil + "NNTP." + :group 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Environment variables +;;; + +(defcustom mew-rc-file "~/.mew" + "*A file to be loaded after Mew's variables are initialized." + :group 'mew-env + :type 'file) + +(defcustom mew-mail-path "~/Mail" + "*A directory where folders locate." + :group 'mew-env + :type 'directory) + +(defcustom mew-conf-path mew-mail-path + "*A directory where Mew's configuration files locate." + :group 'mew-env + :type 'directory) + +(defcustom mew-pop-inbox-folder "$inbox" + "*The default folder for POP." + :group 'mew-folder + :type 'string) + +(defcustom mew-imap-inbox-folder "%inbox" + "*The default folder for IMAP." + :group 'mew-folder + :type 'string) + +(defcustom mew-imap-queue-folder "%queue" + "*The queue folder for IMAP jobs." + :group 'mew-folder + :type 'string) + +(defcustom mew-imap-trash-folder "%trash" + "*The trash folder for IMAP. If non-nil, deleted messages are +moved to this folder. Deleting messages in this folder makes them +really deleted." + :group 'mew-folder + :type '(choice string (const nil))) + +(defcustom mew-imap-trash-folder-list nil + "*A list of IMAP folders whose messages marked with 'D' are really deleted." + :group 'mew-summary + :type '(choice (const nil) (repeat string))) + +(defcustom mew-inbox-folder "+inbox" + "*The folder where new messages are incorporated." + :group 'mew-folder + :type 'string) + +(defcustom mew-draft-folder "+draft" + "*The folder where draft are contained." + :group 'mew-folder + :type 'string) + +(defcustom mew-trash-folder "+trash" + "*The trash folder." + :group 'mew-folder + :type '(choice string (const nil))) + +(defcustom mew-trash-folder-list nil + "*A list of folders whose messages marked with 'D' are really deleted." + :group 'mew-summary + :type '(choice (const nil) (repeat string))) + +(defcustom mew-queue-folder "+queue" + "*The queue folder to send messages." + :group 'mew-folder + :type 'string) + +(defcustom mew-postq-folder "+postq" + "*The queue folder to post messages." + :group 'mew-folder + :type 'string) + +(defcustom mew-attach-folder "+attach" + "*The folder where attachments are contained." + :group 'mew-folder + :type 'string) + +(defcustom mew-friend-folder "+from" + "*The folder where personal messages are refiled." + :group 'mew-folder + :type 'string) + +(defcustom mew-imap-friend-folder "%from" + "*The folder where personal messages are refiled for IMAP." + :group 'mew-folder + :type 'string) + +(defcustom mew-imap-spam-field nil + "*The field name of anti spam information to be used for IMAP spam filter. +If both 'mew-imap-spam-field' and 'mew-imap-spam-word' are defined, +messages whose the field contains the word are automatically +removed or refiled to 'mew-imap-spam-folder' or 'mew-imap-trash-folder' +\(if defined) while scanning %inbox." + :group 'mew-imap + :type '(choice (const :tag "Not use" nil) + (string :tag "Spam field"))) + +(defcustom mew-imap-spam-word nil + "*The word of anti spam information to be used for IMAP spam filter. +See 'mew-imap-spam-field'." + :group 'mew-imap + :type '(choice (const :tag "Not use" nil) + (string :tag "Spam word"))) + +(defcustom mew-imap-spam-pattern nil + "*IMAP SEARCH pattern to filter spams. +If non-nil, 'mew-imap-spam-field' and 'mew-imap-spam-field' +treated as 'nil'." + :group 'mew-imap + :type '(choice (const :tag "Not use" nil) + (string :tag "Spam word"))) + +(defcustom mew-imap-spam-folder nil + "*A folder to be used for IMAP spam filter. +See 'mew-imap-spam-field'." + :group 'mew-imap + :type '(choice (const :tag "Not use" nil) + (string :tag "Spam folder"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Hooks +;;; + +(defcustom mew-env-hook nil + "*Hook called at initialize time before setting environment." + :group 'mew-env + :type 'hook) + +(defcustom mew-init-hook nil + "*Hook called at initialize time." + :group 'mew-env + :type 'hook) + +(defcustom mew-summary-mode-hook nil + "*Hook called in Summary mode." + :group 'mew-summary + :type 'hook) + +(defcustom mew-virtual-mode-hook nil + "*Hook called in Virtual mode." + :group 'mew-summary + :type 'hook) + +(defcustom mew-thread-display-hook nil + "*Hook called after new threads are displayed." + :group 'mew-summary + :type 'hook) + +(defcustom mew-header-mode-hook nil + "*Hook called in Header mode." + :group 'mew-draft + :type 'hook) + +(defcustom mew-draft-mode-hook nil + "*Hook called in Draft mode." + :group 'mew-draft + :type 'hook) + +(defcustom mew-draft-mode-newdraft-hook nil + "*Hook called in Draft mode only when new draft is prepared." + :group 'mew-draft + :type 'hook) + +(defcustom mew-draft-mode-reedit-hook nil + "*Hook called in Draft mode when a message not in +draft or +queue +is re-edited." + :group 'mew-draft + :type 'hook) + +(defcustom mew-draft-mode-reedit-draft-hook nil + "*Hook called in Draft mode when a message in +draft is re-edited." + :group 'mew-draft + :type 'hook) + +(defcustom mew-draft-mode-reedit-queue-hook nil + "*Hook called in Draft mode when a message in +queue is re-edited." + :group 'mew-draft + :type 'hook) + +(defcustom mew-draft-mode-edit-hook nil + "*Hook called in Edit mode" + :group 'mew-draft + :type 'hook) + +(defcustom mew-draft-mode-edit-again-hook nil + "*Hook called in Draft mode when a message returned with the old style +is edited again." + :group 'mew-draft + :type 'hook) + +(defcustom mew-message-mode-hook nil + "*Hook called in Message mode." + :group 'mew-message + :type 'hook) + +(defcustom mew-message-hook nil + "*Hook called whenever message displayed." + :group 'mew-message + :type 'hook) + +(defcustom mew-make-message-hook nil + "*Hook called before making a message in Draft mode. A good example +is as follows: + (add-hook 'mew-make-message-hook 'ispell-message)" + :group 'mew-draft + :type 'hook) + +(defcustom mew-send-hook nil + "*Hook called before sending/queuing an e-mail message in Draft mode. +Note that this hook is called before composition of the message." + :group 'mew-draft + :type 'hook) + +(defcustom mew-post-hook nil + "*Hook called before posting/queuing a NetNews message in Draft mode. +Note that this hook is called before composition of the message." + :group 'mew-draft + :type 'hook) + +(defcustom mew-real-send-hook nil + "*Hook called before sending/queuing an e-mail message in Draft mode. +Note that this hook is called after composition of the message." + :group 'mew-draft + :type 'hook) + +(defcustom mew-real-post-hook nil + "*Hook called before sending/queuing a NetNews message in Draft mode. +Note that this hook is called after composition of the message." + :group 'mew-draft + :type 'hook) + +(defcustom mew-smtp-flush-hook nil + "*Hook called before SMTP runs if messages exist in +queue." + :group 'mew-draft + :type 'hook) + +(defcustom mew-nntp2-flush-hook nil + "*Hook called before NNTP runs if messages exist in +postq" + :group 'mew-draft + :type 'hook) + +(defcustom mew-smtp-sentinel-hook nil + "*Hook called when a SMTP process finished." + :group 'mew-draft + :type 'hook) + +(defcustom mew-nntp-sentinel-hook nil + "*Hook called when a NNTP process to receive messages finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-nntp2-sentinel-hook nil + "*Hook called when a NNTP process to post messages finished." + :group 'mew-draft + :type 'hook) + +(defcustom mew-pop-sentinel-hook nil + "*Hook called when a POP process finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-pop-sentinel-non-biff-hook nil + "*Hook called when a non-Biff POP process finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-imap-sentinel-hook nil + "*Hook called when an IMAP process finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-imap-sentinel-non-biff-hook nil + "*Hook called when a non-Biff IMAP process finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-scan-sentinel-hook nil + "*Hook called when scan finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-summary-ls-no-scan-hook nil + "*Hook called when mew-summary-ls does not scan a folder." + :group 'mew-summary + :type 'hook) + +(defcustom mew-summary-exec-hook nil + "*Hook called when mew-summary-exec finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-sort-hook nil + "*Hook called when sort finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-summary-toggle-disp-msg-hook nil + "*Hook called when mew-summary-toggle-disp-msg finished." + :group 'mew-summary + :type 'hook) + +(defcustom mew-summary-delete-folder-hook nil + "*Hook called when a folder deleted. +Eash function is called with a deleted folder as the argument." + :group 'mew-summary + :type 'hook) + +(defcustom mew-summary-rename-folder-hook nil + "*Hook called when a folder renamed. +Each function is called with a source folder and a destination folder as the argument." + :group 'mew-summary + :type 'hook) + +(defcustom mew-syntax-format-hook nil + "*Hook called when mew-syntax-format is called." + :group 'mew-message + :type 'hook) + +(defcustom mew-addrbook-mode-hook nil + "*Hook called in Addrbook mode." + :group 'mew-addrbook + :type 'hook) + +(defcustom mew-suspend-hook nil + "*Hook called on suspend." + :group 'mew-env + :type 'hook) + +(defcustom mew-quit-hook nil + "*Hook called on quit." + :group 'mew-env + :type 'hook) + +(defcustom mew-status-update-hook nil + "*Hook called to update status." + :group 'mew-env + :type 'hook) + +(defcustom mew-refile-guess-by-from-learn-hook nil + "*Hook called in mew-refile-guess-by-from-learn." + :group 'mew-env + :type 'hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mail Addresses for Draft +;;; + +(defcustom mew-mail-address-list nil + "*The addresses included in this list never appear on the Cc: field +on a draft buffer. If nil, this value is automatically generated from +'mew-config-alist'." + :group 'mew-draft + :type '(choice (const nil) (repeat string))) + +(defcustom mew-mail-domain-list nil + "*Your e-mail address domain list like +\(\"example.org\" \"example.jp\"). +They are used for mail-domain completion in Draft mode(C-cTAB). If +nil, this value is automatically generated from 'mew-config-alist'." + :group 'mew-draft + :type '(choice (const nil) (repeat string))) + +(defcustom mew-from-list nil + "*A list of From: for circular completion in Draft mode. If nil, +this value is automatically generated from 'mew-config-alist'. See +also 'mew-from'." + :group 'mew-draft + :type '(choice (const nil) (repeat string))) + +(defcustom mew-warn-addresses nil + "A list of addresses to be warned." + :group 'mew-draft + :type '(choice (const nil) (repeat string))) + +(defcustom mew-safe-addresses nil + "A list of addresses not to be warned." + :group 'mew-draft + :type '(choice (const nil) (repeat string))) + +(defcustom mew-warn-domains nil + "A list of domains to be warned." + :group 'mew-draft + :type '(choice (const nil) (repeat string))) + +(defcustom mew-safe-domains nil + "A list of domains not to be warned." + :group 'mew-draft + :type '(choice (const nil) (repeat string))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mail Addresses +;;; + +(defcustom mew-name (user-full-name) + "*Friendly name of e-mail address. +i.e. \"Friendly name \"." + :group 'mew-basic + :type '(choice string (const nil))) + +(defcustom mew-user (user-login-name) + "*User part of e-mail address." + :group 'mew-basic + :type 'string) + +(defcustom mew-mail-domain (or (car mew-mail-domain-list) + mail-host-address + (system-name)) + "*Your e-mail address domain." + :group 'mew-basic + :type 'string) + + +(defvar mew-reply-all-alist + '((("Followup-To:" "poster") + ("To:" "From:")) + ("Followup-To:" + ("Newsgroups:" "Followup-To:" "Newsgroups:")) + ("Newsgroups:" + ("Newsgroups:" "Newsgroups:")) + ("Reply-To:" + ("To:" "Reply-To:" "From:") + ("Cc:" "To:" "Cc:" "Apparently-To:")) + (t + ("To:" "From:") + ("Cc:" "To:" "Cc:" "Apparently-To:"))) + "*Alist to be used to prepare To:/Cc:/Newsgroups: in a reply draft. +For most cases, this alist is used. +For more infomation, see the document of '\\\\[mew-summary-reply]'") + +(defvar mew-reply-sender-alist + '(("Reply-To:" + ("To:" "Reply-To:" "From:")) + (t + ("To:" "From:"))) + "*Alist to be used to prepare To:/Cc:/Newsgroups: in a reply draft. +When '\\[universal-argument]' is specified for '\\\\[mew-summary-reply]' and '\\[mew-summary-reply-with-citation]', this alist is used. +For more infomation, see the document of '\\[mew-summary-reply]'") + +(defvar mew-reply-fromme-alist + '((t + ("To:" "To:") + ("Cc:" "Cc:") + ("Newsgroups:" "Newsgroups:"))) + "*Alist to be used to prepare To:/Cc:/Newsgroups: in a reply draft. +When the message to be replied is sent/posted by ME, this alist is used. +For more infomation, see the document of '\\\\[mew-summary-reply]'") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SSH/SSL/TLS +;;; + +(defcustom mew-ssh-keep-connection t + "*If non-nil, an SSH process for each service (POP, IMAP, NNTP, SMTP) +is kept for further connections. This must be 't' for IMAP and NNTP." + :group 'mew-net + :type 'boolean) + +(defcustom mew-ssl-keep-connection t + "*If non-nil, an SSL/TLS process for each service (POP, IMAP, NNTP, SMTP) +is kept for further connections. This must be 't' for IMAP and NNTP." + :group 'mew-net + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SMTP +;;; + +(defcustom mew-smtp-server "localhost" + "*The name of your SMTP server. If you want to use a remote SMTP +server, set an appropriate value." + :group 'mew-smtp + :type 'string) + +(defcustom mew-smtp-port "smtp" + "*The SMTP port. (e.g. \"smtp\" or 25)" + :group 'mew-smtp + :type 'string) + +(defcustom mew-smtp-ssh-server nil + "*The name of SSH server which forwards the SMTP port." + :group 'mew-smtp + :type '(choice (const :tag "Not use" nil) + (string :tag "Ssh server"))) + +(defcustom mew-smtp-ssl nil + "*If non-nil, SMTP connections are made over SSL/TLS." + :group 'mew-smtp + :type 'boolean) + +(defcustom mew-smtp-ssl-port 465 ;; no universal consensus + "*The port for SMTP over SSL/TLS. Set this to \"smtp\" if you +want to use TLS." + :group 'mew-smtp + :type 'string) + +(defcustom mew-smtp-user nil + "*The user name on your SMTP server. If not configured, +your e-mail address is automatically set" + :group 'mew-smtp + :type '(choice string (const nil))) + +(defcustom mew-smtp-auth-list '("CRAM-MD5" "PLAIN" "LOGIN") + "*A list of SMTP AUTH methods in the preferred order. +Currently, \"CRAM-MD5\", \"PLAIN\", and \"LOGIN\" can be used." + :group 'mew-smtp + :type '(repeat (choice (const "CRAM-MD5") (const "PLAIN") (const "LOGIN")))) + +(defcustom mew-smtp-helo-domain "localhost" + "*An e-mail domain to tell a SMTP server with HELO/EHLO." + :group 'mew-smtp + :type 'string) + +(defcustom mew-smtp-mail-from nil + "*An e-mail address to tell a SMTP server with MAIL FROM:. +If nil, an address specified by the From: field is used." + :group 'mew-smtp + :type '(choice string (const nil))) + +(defcustom mew-smtp-msgid-user nil + "*A user part for creation of Message-Id: for SMTP. If nil, the +value of 'mew-user' is used." + :group 'mew-smtp + :type '(choice string (const nil))) + +(defcustom mew-smtp-msgid-domain nil + "*A domain name for creation of Message-Id: for SMTP. If nil, the +value of 'mew-mail-domain' is used." + :group 'mew-smtp + :type '(choice string (const nil))) + +(defvar mew-smtp-timeout-time 4) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Retrieving messages +;;; + +(defcustom mew-mailbox-type 'pop + "'pop, 'imap or 'mbox" + :group 'mew-net + :type '(choice (const pop) (const imap) (const mbox))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; mbox +;;; + +(defcustom mew-mbox-command "incm" + "*A command to be execute if 'mew-mailbox-type' is 'mbox." + :group 'mew-pop + :type '(choice string (const nil))) + +(defcustom mew-mbox-command-arg "-u" + "*Arguments for 'mew-mbox-command'. +For maildir, set this to '-u -d /path/to/mbox'." + :group 'mew-pop + :type '(choice string (const nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Biff +;;; + +(defcustom mew-biff-interval 5 + "*Minutes of biff interval. This should be smaller than +'mew-passwd-timer-unit' * 'mew-passwd-lifetime'." + :group 'mew-net + :type 'integer) + +(defcustom mew-biff-function 'mew-biff-bark + "*A function to be called when messages arrive." + :group 'mew-net + :type '(choice function (const nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; POP +;;; + +(defcustom mew-pop-server "localhost" + "*The name of your POP server. If you want to use a remote POP +server, set an appropriate value." + :group 'mew-pop + :type 'string) + +(defcustom mew-pop-port "pop3" + "*The POP3 port. (e.g. \"pop3\" or 110)" + :group 'mew-pop + :type 'string) + +(defcustom mew-pop-ssh-server nil + "*The name of SSH server which forwards the POP3 port." + :group 'mew-pop + :type '(choice string (const nil))) + +(defcustom mew-pop-ssl nil + "*If non-nil, POP connections are made over SSL/TLS." + :group 'mew-pop + :type 'boolean) + +(defcustom mew-pop-ssl-port "pop3s" + "*The port for POP over SSL/TLS." + :group 'mew-pop + :type 'string) + +(defcustom mew-pop-user (user-login-name) + "*The user name on your POP server." + :group 'mew-pop + :type 'string) + +(defcustom mew-pop-auth 'apop + "*The authentication method for POP3. +'pass means the authentication with USER/PASS (i.e. plain password). +'apop means the authentication with APOP. +t means SASL according to 'mew-pop-auth-list'." + :group 'mew-pop + :type '(choice (const apop) (const pass) (const t))) + +(defcustom mew-pop-auth-list '("CRAM-MD5" "PLAIN") + "*A list of SASL methods in the preferred order. +Currently, \"CRAM-MD5\" can be used." + :group 'mew-pop + :type '(repeat (choice (const "CRAM-MD5") (const "PLAIN")))) + +(defcustom mew-pop-delete t + "*Whether or not delete messages on a POP server after retrieval by +POP. If t, delete the messages. If nil, retain the messages. If +number N, delete the messages N days after the first access. +Otherwise they are not deleted." + :group 'mew-pop + :type '(choice + (const :tag "Delete immediately" t) + (const :tag "Retain the messages" nil) + (integer :tag "Delete N days after"))) + +(defcustom mew-pop-size (* 54 1024) ;; 4K hdr + 50K bdy + "*The limit size of messages to be retrieved by POP. The default is +55296 byte. 0 means unlimited, so you can get all messages from the +POP server." + :group 'mew-pop + :type 'integer) + +(defcustom mew-pop-body-lines 40 + "*The limit of body lines to get when the size of message +exceeds 'mew-pop-size'." + :group 'mew-pop + :type 'integer) + +(defcustom mew-pop-header-only nil + "*Whether or not the body of a message is retrieved by POP. +If non-nil, only header is retrieved." + :group 'mew-pop + :type 'boolean) + +(defcustom mew-pop-proxy-server nil + "*The name of POP proxy server." + :group 'mew-pop + :type '(choice (const :tag "Not use" nil) + (string :tag "Pop proxy server"))) + +(defcustom mew-pop-proxy-port nil + "*The port for POP proxy." + :group 'mew-pop + :type '(choice string (const nil))) + +(defvar mew-pop-timeout-time 4) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; IMAP +;;; + +(defcustom mew-imap-server "localhost" + "*The name of your IMAP server. If you want to use a remote IMAP +server, set an appropriate value." + :group 'mew-imap + :type 'string) + +(defcustom mew-imap-port "imap" + "*The IMAP4 port. (e.g. \"imap\" or 143)" + :group 'mew-imap + :type 'string) + +(defcustom mew-imap-ssh-server nil + "*The name of SSH server which forwards the IMAP4 port." + :group 'mew-imap + :type '(choice string (const nil))) + +(defcustom mew-imap-ssl nil + "*If non-nil, IMAP connections are made over SSL/TLS." + :group 'mew-imap + :type 'boolean) + +(defcustom mew-imap-ssl-port "imaps" + "*The port for IMAP over SSL/TLS." + :group 'mew-imap + :type 'string) + +(defcustom mew-imap-user (user-login-name) + "*The user name on the IMAP server." + :group 'mew-imap + :type 'string) + +(defcustom mew-imap-auth t + "*The authentication method for IMAP4. +nil means the authentication with LOGIN (i.e. plain password). +t means SASL according to 'mew-imap-auth-list'." + :group 'mew-imap + :type 'boolean) + +(defcustom mew-imap-auth-list '("CRAM-MD5" "LOGIN") + "*A list of SASL methods in the preferred order. +Currently, \"CRAM-MD5\" and \"LOGIN\" can be used." + :group 'mew-imap + :type '(repeat (choice (const "CRAM-MD5") (const "LOGIN")))) + +(defcustom mew-imap-delete t + "*Whether or not delete messages on an IMAP server after retrieval by +IMAP. If t, delete the messages. If nil, retain the messages. If +number N, delete the messages N days after the first access. +Otherwise they are not deleted." + :group 'mew-imap + :type 'boolean) + +(defcustom mew-imap-size (* 54 1024) ;; 4K hdr + 50K bdy + "*The limit size of messages to be retrieved by IMAP. The default is +55296 byte. 0 means unlimited, so you can get all messages from the +IMAP server." + :group 'mew-imap + :type 'integer) + +(defcustom mew-imap-header-only nil + "*Whether or not the body of a message is retrieved by IMAP. +If non-nil, only header is retrieved." + :group 'mew-imap + :type 'boolean) + +(defcustom mew-imap-prefix-list nil + "A list to define which prefixes of user mailboxes should be used. + +For example, the WU IMAP server returns the following value +for the NAMESPACE command. + + ((\"\" \"/\")(\"#mhinbox\" NIL)(\"#mh/\" \"/\")) ((\"/\" \"/\")) ((\"#shared/\" \"/\")(\"#ftp/\" \"/\")(\"#news.\" \".\")(\"#public/\" \"/\")) + +The first list is prefixes of user mailboxes. Each element consists +of a prefix and a separator. + +If this valuable is nil, the prefix in the first element of the +list is used as a prefix of user mailboxes. + +If this value is a list of strings, matched elements are used. +If the separator is non-nil, the prefix is used. If the separator +is nil, the prefix is added to mailbox alist as a mailbox. + +If you want to used your home directory with WU, configure as +follows: + + (setq mew-imap-prefix-list '(\"\")) + +If you want to used the MH directory with WU, configure as +follows: + + (setq mew-imap-prefix-list '(\"#mh/\" \"#mhinbox\")) + +Note that %inbox means /var/mail/ while %#mhinbox refers to +Mail/inbox. +" + :group 'mew-imap + :type '(choice (const nil) (repeat string))) + +(defcustom mew-imap-proxy-server nil + "*The name of IMAP proxy server." + :group 'mew-imap + :type '(choice (const :tag "Not use" nil) + (string :tag "Imap proxy server"))) + +(defcustom mew-imap-proxy-port nil + "*The port for IMAP proxy." + :group 'mew-imap + :type '(choice string (const nil))) + +(defvar mew-imap-timeout-time 4) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; NNTP +;;; + +(defcustom mew-nntp-server "localhost" + "*The name of your NNTP server. If you want to use a remote NNTP +server, set an appropriate value." + :group 'mew-nntp + :type 'string) + +(defcustom mew-nntp-port "nntp" + "*The NNTP port. (e.g. \"nntp\" or 119)" + :group 'mew-nntp + :type 'string) + +(defcustom mew-nntp-ssh-server nil + "*The name of SSH server which forwards the NNTP port." + :group 'mew-nntp + :type '(choice string (const nil))) + +(defcustom mew-nntp-ssl nil + "*If non-nil, NNTP connections are made over SSL/TLS." + :group 'mew-nntp + :type 'boolean) + +(defcustom mew-nntp-ssl-port "nntps" + "*The port for NNTP over SSL/TLS." + :group 'mew-nntp + :type 'string) + +(defcustom mew-nntp-user nil + "*The user name on the NNTP server. If non-nil, authentication is +used." + :group 'mew-nntp + :type '(choice (const :tag "Not use" nil) + (string :tag "Nntp user"))) + +(defcustom mew-nntp-newsgroup "-fj.mail.reader.mew" + "*The name of default Newsgroup." + :group 'mew-nntp + :type 'string) + +(defcustom mew-nntp-size (* 54 1024) ;; 4K hdr + 50K bdy + "*The limit size of messages to be retrieved by NNTP. The default is +55296 byte. 0 means unlimited, so you can get all messages from the +NNTP server." + :group 'mew-nntp + :type 'integer) + +(defcustom mew-nntp-header-only nil + "*Whether or not the body of a message is retrieved by NNTP. +If non-nil, only header is retrieved." + :group 'mew-nntp + :type 'boolean) + +(defcustom mew-nntp-msgid-user nil + "*A user part for creation of Message-Id: for NNTP. If nil, the +value of 'mew-user' is used." + :group 'mew-nntp + :type '(choice string (const nil))) + +(defcustom mew-nntp-msgid-domain nil + "*A domain name for creation of Message-Id: for NNTP. If nil, the +value of 'mew-mail-domain' is used." + :group 'mew-nntp + :type '(choice string (const nil))) + +(defvar mew-nntp-timeout-time 4) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; range +;;; + +(defcustom mew-range-list nil + "*A list of (KEY VALUE) to define RANGE for each folder. + +If KEY is t, all folders matches it. The corresponding RANGE is +returned always. + +If KEY is a string, match-function is applied according to +'mew-range-list-string-type'. If matched, the corresponding RANGE is +returned. + +If KEY is a list of strings, match-function is applied according to +'mew-range-list-list-type'. If a match found out of the strings, +the corresponding RANGE is returned. + +Candidate values for 'mew-rage-list-string-type' and +'mew-range-list-list-type' are as follows: + + 'regex Regular expression. + 'recursive Initial substring match. That is, + not only a folder specified but all so + all sub-folders are matched. + 'string String comparison. + +An example is as follows: + '(((\"+queue\" \"+postq\" \"+draft\") \"all\") + ((\"$inbox\") \"sync\") + (t \"update\")) + +If this value is nil, an appropriate value is set when Mew is booting. +" + :group 'mew-summary + :type '(choice + (const nil) + (repeat + (list (choice (string :tag "Folder") + (repeat :tag "Folders" (string :tag "Folder")) + (const :tag "Other" t)) + string)))) + +(defcustom mew-range-list-string-type 'regex + "*A value to specify an action if the key is a string in +'mew-range-list'. Candidates are 'regex, 'recursive, and 'string." + :group 'mew-summary + :type '(choice (const regex) (const recursive) (const string))) + +(defcustom mew-range-list-list-type 'recursive + "*A value to specify an action if the key is a list of strings in +'mew-range-list'. Candidates are 'regex, 'recursive, and 'string." + :group 'mew-summary + :type '(choice (const regex) (const recursive) (const string))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; unread-mark +;;; + +(defcustom mew-unread-mark-list + '((("+inbox" "$inbox" "%inbox" "-") t) + (t nil)) + "*A list of (KEY VALUE) to define the read/unread marks for +each folder when scanning. If VALUE is non-nil, messages are +marked as unread. Otherwise, message are not marked, that is, +marked as read. + +If KEY is t, all folders matches it. The corresponding VALUE is +returned always. + +If KEY is a string, match-function is applied according to +'mew-unread-mark-list-string-type'. If matched, the corresponding +VALUE is returned. + +If KEY is a list of strings, match-function is applied according to +'mew-unread-mark-list-list-type'. If a match found out of the strings, +the corresponding VALUE is returned. + +Candidate values for 'mew-rage-list-string-type' and +'mew-unread-mark-list-list-type' are as follows: + + 'regex Regular expression. + 'recursive Initial substring match. That is, + not only a folder specified but all so + all sub-folders are matched. + 'string String comparison. + +The default value is: + '(((\"+inbox\" \"$inbox\" \"%inbox\" \"-\") t) + (t nil)) + +An example for the case where messages are marked as unread in any +folders: + '((t t)) + +Note that this variable is effective only when 'mew-use-unread-mark' +is non-nil. +" + :group 'mew-summary + :type '(choice + (const nil) + (repeat + (list (choice (string :tag "Folder") + (repeat :tag "Folders" (string :tag "Folder")) + (const :tag "Other" t)) + string)))) + +(defcustom mew-unread-mark-list-string-type 'regex + "*A value to specify an action if the key is a string in +'mew-unread-mark-list'. Candidates are 'regex, 'recursive, and 'string." + :group 'mew-summary + :type '(choice (const regex) (const recursive) (const string))) + +(defcustom mew-unread-mark-list-list-type 'recursive + "*A value to specify an action if the key is a list of strings in +'mew-unread-mark-list'. Candidates are 'regex, 'recursive, and 'string." + :group 'mew-summary + :type '(choice (const regex) (const recursive) (const string))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Scan +;;; + +(defconst mew-summary-form-header '(mark) + "*A list to be appended to summary-form if the first element of +summary-form is not an integer. Since Mew assumes that +each line of Summary mode begins with one mark, this variable +MUST be '(mark).") + +(defconst mew-custom-type-of-summary-form + '(choice + (cons :tag "Setup message number column" + (integer :tag "Message number column" ) + (repeat (choice (string :tag "Insert string") + (const :tag "Thread indent" t) + (list :tag "Width and symbol" + :value (0 type) + (integer :tag "Display width") + (choice :tag "Symbol" + :value type + (const type) (const time) + (const date) (const year) + (const size) (const from) + (const subj) (symbol :tag "Other"))) + (choice :tag "Symbol" + :value type + (const type) (const time) + (const date) (const year) + (const size) (const from) + (const subj) (symbol :tag "Other"))))) + (repeat :tag "Use default number column" + (choice (integer :tag "Message number column") + (string :tag "Insert string") + (const :tag "Thread indent" t) + (list :tag "Width and symbol" + :value (0 type) + (integer :tag "Display width") + (choice :tag "Symbol" + :value type + (const type) (const time) + (const date) (const year) + (const size) (const from) + (const subj) (symbol :tag "Other"))) + (choice :tag "Symbol" + :value type + (const type) (const time) + (const date) (const year) + (const size) (const from) + (const subj) (symbol :tag "Other")))))) + +(defvar mew-summary-form-body-starter "|") + +(defcustom mew-summary-form + `(type (5 date) " " (14 from) " " t (30 subj) + ,mew-summary-form-body-starter (0 body)) + "*The format in Summary mode, called summary-form. summary-form is a list +of list, symbol, and string. + +\(a) A string is printed as it is. + +\(b) A list consists of an integer and a symbol. The symbol specifies a +function to be called. The name of the function is produced by +concatenating 'mew-summary-form-func-prefix' and the symbol name. +\(e.g. 'mew-summary-form-date' for the symbol 'date'). + +Pre-defined symbols are 'type, 'time, 'date, 'year, 'size, 'from, +'subj and 'body. For more details, see the explanation of the +functions called 'mew-summary-form-'. + +The integer specifies the width of field which will be filled with a +return string of the function. + +A positive value means padding SPCs on the right if necessary. + +A negative value means padding SPCs on the left if necessary. If a +negative value is specified, the corresponding function must return an +ASCII string. + +0 means the remaining width and is treated as a positive value. + +\(c) A symbol except 't' is equivalent to (1 symbol). + +\(d) The value of mew-summary-form-header (mark) is appended to +summary-form when used. See also 'mew-summary-form-header'. + +\(e) 't' means the position where thread indentation is inserted. + +An example is as follows: + '(type (5 date) \" \" (-4 size) \" \" (14 from) \" \" t (30 subj) \"|\" (0 body)) + +You can also set this value in 'mew-summary-form-list'." + :group 'mew-summary + :type mew-custom-type-of-summary-form) + +(defcustom mew-summary-form-list nil + "*A list of (KEY VALUE) to define 'mew-summary-form' for each +folder. Each component is (key summary-form). + +If KEY is t, all folders matches it. The corresponding SUMMARY-FORM is +returned always. + +If KEY is a string, match-function is applied according to +'mew-summary-form-list-string-type'. If matched, the corresponding +SUMMARY-FORM is returned. + +If KEY is a list of strings, match-function is applied according to +'mew-summary-form-list-list-type'. If a match found out of the strings, +the corresponding SUMMARY-FORM is returned. + +Candidate values for 'mew-summary-form-list-string-type' and +'mew-summary-form-list-list-type' are as follows: + + 'regex Regular expression. + 'recursive Initial substring match. That is, + not only a folder specified but all so + all sub-folders are matched. + 'string String comparison. + +SUMMARY-FORM is a list. See 'mew-summary-form' for more information. + +An example is as follows: + '(((\"+inbox\") + (type (5 date) \" \" (-4 size) \" \" (14 from) \" \" t (30 subj) \"|\" (0 body))) + (t + (type (5 date) \" \" (14 from) \" \" t (30 subj) \"|\" (0 body)))) +" + :group 'mew-summary + :type `(choice + (const nil) + (repeat + (list (choice (string :tag "Folder") + (repeat :tag "Folders" (string :tag "Folder")) + (const :tag "Other" t)) + ,mew-custom-type-of-summary-form + (choice (integer :tag "Thread indent column") + (const nil)))))) + +(defcustom mew-summary-form-list-string-type 'regex + "*A value to specify an action if the key is a string in +'mew-summary-form-list'. Candidates are 'regex, 'recursive, and 'string." + :group 'mew-summary + :type '(choice (const regex) (const recursive) (const string))) + +(defcustom mew-summary-form-list-list-type 'recursive + "*A value to specify an action if the key is a list of strings in +'mew-summary-form-list'. Candidates are 'regex, 'recursive, and 'string." + :group 'mew-summary + :type '(choice (const regex) (const recursive) (const string))) + +(defcustom mew-summary-form-from-me-prefix "To:" + "*The prefix to be prepend to an destination address +if the message is originated by me." + :group 'mew-summary + :type 'string) + +(defcustom mew-summary-form-extract-rule '(nickname) + "*A list to specify what part to extract from the From: field. Each +element must be 'name, 'comment, 'address, 'nickname, or appropriate +\"regex\". + +Consider the following examples: + + A: Kazu Yamamoto + B: kazu@example.org (Kazu Yamamoto) + C: Kazuhiko Yamamoto (Kazu) + +Each element returns the following value: + + 'name Name part, if any + A: Kazu Yamamoto + B: (No match) + C: Kazuhiko Yamamoto (Kazu) + 'comment Comment part, if any + A: (No match) + B: Kazu Yamamoto + C: (Kazu) + 'address Address part + A: kazu@example.org + B: kazu@example.org + C: kazu@example.org + + 'nickname One element of personal information in + Addrbook according to 'mew-addrbook-for-summary'. + The default value of 'mew-addrbook-for-summary' + is 'nickname. So, From: is converted a nickname + by default. For more information, see + 'mew-addrbook-switch'. + + (regex) The substring first matched + +If a element does not match, the next element is applied. If no +element matches to the From: field, or this value is nil, the whole +of the From: field is used." + :group 'mew-summary + :type '(repeat (choice regexp (const name) (const comment) + (const address) (const nickname)))) + +(defcustom mew-summary-form-mark-delete nil + "*If non-nil, the 'D' mark automatically is put onto +duplicated messages. If a character, use it as a mark +instead of the 'D' mark." + :group 'mew-summary + :type '(choice (const :tag "Use mew-mark-delete" t) + (const :tag "Not use" nil) + (character :tag "Use another character"))) + +(defcustom mew-summary-form-mark-spam nil + "*If non-nil, the 'D' mark automatically is put onto +SPAM messages. A message is considered a SPAM message +if the MD5 checksum of its body is duplicated in a scan. +If a character, use it as a mark instead of the 'D' mark." + :group 'mew-summary + :type '(choice (const :tag "Use mew-mark-delete" t) + (const :tag "Not use" nil) + (character :tag "Use another character"))) + +(defcustom mew-summary-form-mark-review nil + "*If non-nil, the '*' mark automatically is put onto +messages destined to me. If a character, use it as a mark +instead of the '*' mark." + :group 'mew-summary + :type '(choice (const :tag "Use mew-mark-review" t) + (const :tag "Not use" nil) + (character :tag "Use another character"))) + +(defcustom mew-summary-form-size-0k nil + "*If non-nil, the size of message is displayed as '0k' +if the size is less than 1k byte." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-summary-form-size-huge t + "*If non-nil, the size of message is displayed as 'HUGE' +when the size is greater than or equal to 1000 after maximum +quantization by 'mew-summary-form-size-unit'." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-spam: "X-Bogosity:" + "*The field name which your spam filter inserts. +E.g. + \"X-Spam-Flag:\" for 'spamassassin' + \"X-Bogosity:\" for 'bogofilter'" + :group 'mew-summary + :type 'string) + +(defcustom mew-scan-fields nil + "*A list which specifies mewl's output. +The first element MUST be \"Folder:\". +The second element MUST be \"Filename:\". +Both \"In-Reply-To:\" and \"References:\" MUST be included for thread. +The last MUST be \"Body\"." + :group 'mew-summary + :type '(cons (const "Folder:") + (cons (const "Filename:") + (repeat string)))) + +(defvar mew-scan-fields-alias nil + "*A list of aliases for 'mew-scan-fields'. +Functions called MEW-FOO will be defined according to this variable.") + +(defvar mew-summary-form-func-prefix "mew-summary-form-" + "The prefix for symbol used in 'mew-summary-form'.") + +(defvar mew-scan-decode-fields (list mew-subj: mew-from: mew-to:)) + +(defvar mew-scan-decode-bq-body t) + +(defvar mew-draft-address-warning-fields + (list mew-to: mew-cc: mew-dcc: mew-bcc: + mew-resent-to: mew-resent-cc: mew-resent-dcc: mew-resent-bcc:)) + +(defcustom mew-thread-column 28 + "A position where thread indentation is inserted +for indentation of thread. This valuable is for backward compatibility +only. Use 't' in 'mew-summary-form instead." + :group 'mew-summary + :type 'integer) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Demo +;;; + +(defcustom mew-demo t + "*Mew demo is displayed at boot time if *non-nil*." + :group 'mew-env + :type 'boolean) + +(defcustom mew-demo-picture t + "*A picture of cats is displayed if *non-nil*." + :group 'mew-env + :type 'boolean) + +(defcustom mew-demo-sit-for 0 + "*Time of demo picture staying." + :group 'mew-env + :type '(choice integer (const nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Limits +;;; + +(defcustom mew-file-max-size 100000 + "*The max size of messages. If the size of a message is greater +than mew-file-max-size, Mew skips MIME analysis." + :group 'mew-message + :type 'integer) + +(defcustom mew-header-reasonable-size 10000 + "*The max size of header to be inserted to a temporary buffer to +obtain any fields." + :group 'mew-message + :type 'integer) + +(defcustom mew-header-max-length 200 + "*If the length of a header exceeds this value, +it is not arranged nor MIME decoded. +See also 'mew-header-max-depth'." + :group 'mew-message + :type 'integer) + +(defcustom mew-header-max-depth 50 + "*A value to decide loop depth for header field syntax analysis. +It was known as mew-loop-depth. +See also 'mew-header-max-length'." + :group 'mew-message + :type 'integer) + +(defcustom mew-references-max-count 3 + "*A value for the max number of message IDs in References: when reply. +Non-integer means no limit." + :group 'mew-reply + :type '(choice (integer :tag "Max count") + (const :tag "No limit" nil))) + +(defcustom mew-lisp-max-length 2000 + "*Mew saves an internal lisp structure to a file truncating +to this file." + :group 'mew-env + :type 'integer) + +(defcustom mew-expand-max-depth 5 + "*A value to limit Addrbook expansion loop." + :group 'mew-draft + :type 'integer) + +(defcustom mew-log-max-size 512000 ;; 500KB + "*A value for the max size of log files." + :group 'mew-draft + :type 'integer) + +(defcustom mew-highlight-body-max-size 10000 + "A limit for highlighting a body. '0' means No-Limitation" + :group 'mew-highlight + :type 'integer) + +(defcustom mew-scan-max-field-length 5 + "*Max field length which 'mewl' treats." + :group 'mew-env + :type 'integer) + +(defcustom mew-scan-max-body-length 20 + "*Max body length which 'mewl' treats." + :group 'mew-env + :type 'integer) + +(defcustom mew-scan-body-length 10 + "*Body length which Mew treats. +Increase this value if 'mew-summary-form-mark-spam' put +the 'D' mark onto different messages." + :group 'mew-env + :type 'integer) + +(defcustom mew-flowed-fold-threshold 78 + "*A threshold length of lines in a draft body. +if `mew-use-format-flowed' is `t' and any lines are over this +threshold, the format=flowed encoding is used." + :group 'mew-draft + :type 'integer) + +(defcustom mew-flowed-fold-length 70 + "*A length to which each line is folded when format=flowed is used." + :group 'mew-draft + :type 'integer) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Ask? +;;; + +(defcustom mew-ask-subject nil + "*If *non-nil* and Subject: is empty, ask a user its value." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-ask-to nil + "*If *non-nil*, ask a user to whom he/she sends." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-ask-cc nil + "*If *non-nil*, ask a user to whom he/she sends Cc." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-ask-fcc nil + "*If *non-nil* and a folder on Fcc: does not exist, ask a user to +create it. If nil, folders which are not present are created without +any query." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-ask-newsgroups nil + "*If *non-nil* and Newsgroups: exists, ask a user to send this really." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-ask-range nil + "*If *non-nil*, Mew asks range if the cache in Summary mode seems +invalid. Otherwise, 'update is used for range in the case." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-ask-cite-prefix nil + "*If *non-nil*, ask citation prefix when cite a message." + :group 'mew-cite + :type 'boolean) + +(defcustom mew-ask-pack t + "*If *non-nil*, ask whether or not you really want to pack." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-ask-send t + "*If *non-nil*, ask whether or not you really want to send the message." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-ask-post t + "*If *non-nil*, ask whether or not you really want to post the message." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-ask-flush-queue nil + "*If *non-nil*, ask whether or not you really want to flush queue." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-ask-flush-case nil + "*If *non-nil*, ask case when flushing queue." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-ask-charset nil + "*Mew asks a user whether or not the charset chosen on composing +is appropriate. + nil: not ask + A list of charset: ask if the charset is not a member of the list + t: ask if 'mew-charset-m17n' is used." + :group 'mew-draft + :type '(choice (const nil) (const t) (repeat string))) + +(defcustom mew-ask-folder-after-join nil + "*If *non-nil*, Mew asks to move to the folder where the join +message is stored." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-ask-folder-after-burst nil + "*If *non-nil*, Mew asks to move to the folder where the burst +messages are stored." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-ask-pipe nil + "*If *non-nil*, Mew confirms when '\\\\[mew-summary-pipe-message]' is used." + :group 'mew-summary + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Use +;;; + +(defcustom mew-use-full-window nil + "*If non-nil, the entire frame is used for Mew. +Otherwise, windows are configured dynamically." + :group 'mew-env + :type 'boolean) + +(defcustom mew-use-other-frame-for-draft nil + "*If non-nil, a new frame is created when a draft is prepared." + :group 'mew-env + :type 'boolean) + +(defcustom mew-use-other-frame-for-summary nil + "*If non-nil, a new frame is created when you visit a new folder." + :group 'mew-env + :type 'boolean) + +(defcustom mew-use-text/enriched t + "*If non-nil, Mew parses enriched format text messages." + :group 'mew-message + :type 'boolean) + +(defcustom mew-use-text/html nil + "*If non-nil, Mew parses text/html messages. +If you want to use 'mew-use-text/html-list', this value should be 'nil'." + :group 'mew-message + :type 'boolean) + +(defcustom mew-use-text/html-list nil + "*A list of (KEY VALUE) to define whether or not HTML should be parsed +for each folder. + +If KEY is t, all folders matches it. The corresponding boolean is +returned always. + +If KEY is a string, match-function is applied according to +'mew-use-text/html-string-type'. If matched, the corresponding +boolean is returned. + +If KEY is a list of strings, match-function is applied according +to 'mew-use-text/html-list-type'. If a match found out of the +strings, the corresponding boolean is returned. + +Candidate values for 'mew-use-text/html-string-type' and +'mew-use-text/html-list-type' are as follows: + + 'regex Regular expression. + 'recursive Initial substring match. That is, + not only a folder specified but all so + all sub-folders are matched. + 'string String comparison. +" + :group 'mew-summary + :type '(choice + (const nil) + (repeat + (list (choice (string :tag "Folder") + (repeat :tag "Folders" (string :tag "Folder")) + (const :tag "Other" t)) + boolean)))) + +(defcustom mew-use-text/html-string-type 'regex + "*A value to specify an action if the key is a string in +'mew-use-text/html-list'. Candidates are 'regex, 'recursive, and 'string." + :group 'mew-summary + :type '(choice (const regex) (const recursive) (const string))) + +(defcustom mew-use-text/html-list-type 'recursive + "*A value to specify an action if the key is a list of strings in +'mew-use-text/html-list'. Candidates are 'regex, 'recursive, and 'string." + :group 'mew-summary + :type '(choice (const regex) (const recursive) (const string))) + + +(defcustom mew-use-text/xml nil + "*If non-nil, Mew parses text/xml messages." + :group 'mew-message + :type 'boolean) + +(defcustom mew-use-symbolic-link-for-forwarding nil + "*If nil, messages to be forwarded is copied to +draft when +'\\\\[mew-summary-forward]' and '\\[mew-summary-multi-forward]' are used. Otherwise, symbolic links are +created (if the feature is provided)." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-use-cached-passwd nil + "*if non-nil, passwords are cached." + :group 'mew-privacy + :type 'boolean) + +(defcustom mew-use-master-passwd nil + "*if non-nil, a master password is used." + :group 'mew-privacy + :type 'boolean) + +(defcustom mew-use-8bit nil + "*If non-nil, the 8bit-clean charset mechanism is used for 8bit +charsets, such as ISO-8859-1, in Draft mode. If nil, an appropriate +MIME encoding such as quoted-printable is applied. This also enables +to attach 8bit messages as it is. If nil, 8bit messages are converted +into the 7bit form." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-use-charset-sanity-check t + "*If non-nil, the sanity check of character set is used when +composing." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-use-autoconv-when-unknown t + "*If non-nil, Mew uses 'mew-cs-autoconv' for an unknown coding system." + :group 'mew-message + :type 'boolean) + +(defcustom mew-use-burst-folder-history nil + "*If non-nil, the folder specified at the previous burst job +is used as a folder candidate instead of inbox." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-use-biff nil + "*If non-nil, Mew displays \"Mail(n)\" in the mode line if your +message server receives messages. This is confirmed by POP or IMAP +every 'mew-biff-interval' minutes. + +To use this feature, 'mew-use-cached-passwd' should be 't'. + +If you want to use the biff functionality against a local mailbox, use +'display-time-mode' instead." + :group 'mew-env + :type 'boolean) + +(defcustom mew-use-biff-bell nil + "*If non-nil, Mew beeps when the number of messages in +your POP server becomes non-zero. To use this feature, +'mew-use-biff' should be 't'." + :group 'mew-env + :type 'boolean) + +(defcustom mew-use-sender nil + "*If From: contains multiple addresses, Mew adds Sender: anyway. +If From: contains one address and SMTP MAIL FROM +\('mew-smtp-mail-from') is different from it, this variable effects. +If non-nil, Mew adds Sender: and specifies SMTP MAIL FROM to its value. +Otherwise, Mew does not add Sender:." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-use-x-mailer t + "*If non-nil, X-Mailer: is prepared in Draft mode" + :group 'mew-draft + :type 'boolean) + +(defcustom mew-use-alternative t + "*If non-nil, Multipart/Alternative is treated as a singlepart +according to 'mew-mime-multipart-alternative-list'." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-disable-alternative-regex-list nil + "*A list of regular expression to match the value of X-Mailer:. +If one of them matches, Multiprat/Alternative is treated as +Multipart/Mixed. + +An example: + (setq mew-disable-alternative-regex-list '(\"Apple Mail\"))" + :group 'mew-summary + :type '(list regexp)) + +(defcustom mew-use-text-body t + "*If non-nil, a single Text/* body or the first Text/* part in a top level +multipart is displayed with its header." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-use-nfs-hack nil + "*If non-nil, Mew takes some workarounds for NFS." + :group 'mew-env + :type 'boolean) + +(defcustom mew-use-old-wvhtml nil + "*If non-nil, Mew calls wvHtml in the old argument style." + :group 'mew-message + :type 'boolean) + +(defcustom mew-use-net-status t + "*If non-nil, Mew displays network status to the mode line." + :group 'mew-net + :type 'boolean) + +(defcustom mew-use-fast-refile nil + "*If non-nil, 'rassoc' is used to look up the alist of +folders. Since it is a built-in function, it makes marking for refile +much faster especially when the alist is long. But the fast method +is not case-sensitive. So, you should set this variable to 't' only when +you does not use capital letters for your folders. If nil, the old +slow method, which is case-sensitive, is used." + :group 'mew-refile + :type 'boolean) + +(defcustom mew-use-node-folder t + "*If non-nil, candidate folders chosen by 'mew-refile-guess-by-folder' +includes node folders as well as leaf folders. Otherwise, candidates +are selected out of leaf folders only." + :group 'mew-refile + :type 'boolean) + +(defcustom mew-use-case-completion t + "*If non-nil, 'mew-case' is automatically completed when you +input a folder. For example, consider that you input a folder in a +local folder after typing '\\\\[mew-summary-goto-folder]'. +Typing '%' automatically inserts 'mew-case' before '%'." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-use-spc-padding t + "*If non-nil, SPCs are padded from the end of lines of Summary mode +to the right side." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-use-push-mark nil + "*If non-nil, '\\\\[mew-summary-jump-top]' and '\\\\[mew-summary-jump-bottom]' push the mark." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-use-old-pgp nil + "*If non-nil, the old fashioned PGP message are used when signing/encrypting. +Otherwise PGP/MIME is used." + :group 'mew-privacy + :type 'boolean) + +(defcustom mew-use-full-alias nil + "*If non-nil, the entire addresses of learned address are used +as a key of address completion. Otherwise, the user parts of the +learned address are used." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-use-unread-mark nil + "*If non-nil, the unread mark is used in Summary mode." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-delete-unread-mark-by-mark t + "*If nil, the unread mark remains when the cursor is moved +to the current message from the previous message by +putting any mark on the previous one. If non-nil, +the unread mark is deleted." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-use-smtp-auth t + "*If nil, SMTP AUTH is ignored even an SMTP server +returns the AUTH capability." + :group 'mew-smtp + :type 'boolean) + +(defcustom mew-smtp-auth-plain-authorize-id nil + "*If nil, SMTP AUTH PLAIN is created as follow: + NUL authenticate-id NUL password +If non-nil, it is created as follow: + authorize-id NUL authenticate-id NUL password +For more information, see RFC 2595." + :group 'mew-smtp + :type 'boolean) + +(defcustom mew-use-punycode t + "*If non-nil, punycode strings are decoded into IDN strings" + :group 'mew-message + :type 'boolean) + +(defcustom mew-use-async-write nil + "*If non-nil, message retrieval of POP/IMAP/NNTP on Unix uses +asynchronous write for each message and fsync in their sentinel." + :group 'mew-net + :type 'boolean) + +(defcustom mew-use-format-flowed nil + "*If non-nil, Text/Plain; format=flowed is used when composing. +If you cite a message, the citation style of format=flowed is used. " + :group 'mew-draft + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Appearance +;;; + +(defcustom mew-window-configuration + '((summary (1 0)) + (message (8 31)) + (draft (1 0))) + "*Ratio of windows" + :group 'mew-env + :type '(list + (list (const summary) (list integer integer)) + (list (const message) (list integer integer)) + (list (const draft) (list integer integer)))) + +(defcustom mew-mode-line-id "Mew: %12b" + "*A default value of mode-line-buffer-identification for each Mew mode." + :group 'mew-summary + :type 'sexp) + +;; Indirect call of propertized-buffer-identification due to XEmacs +(defun mew-mode-line-id () + (propertized-buffer-identification mew-mode-line-id)) + +(defcustom mew-multipart-icon-position 'right + "*Position where multipart icons are displayed. +If 'left, displayed at the left size of the default toolbar. +If 'right, displayed at the right size of the default toolbar. +Otherwise, not displayed." + :group 'mew-summary + :type 'symbol) + +(defcustom mew-window-home-buffer "*scratch*" + "*Buffer name to return if window stack is empty." + :group 'mew-summary + :type 'string) + +(defcustom mew-window-magic 80 + "*Minimum window width to scan messages in Summary mode." + :group 'mew-summary + :type 'integer) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Summary mode +;;; + +(defcustom mew-print-function 'lpr-buffer + "*A function for printing" + :group 'mew-summary + :type 'symbol) + +(defcustom mew-summary-show-direction 'next + "*Direction for SPC at end of message. +'up 'down 'next(current direction) 'stop. +Other values are considered as 'stop. +See also 'mew-summary-mark-direction'." + :group 'mew-summary + :type '(choice (const next) (const up) (const down) (const stop))) + +(defcustom mew-summary-mark-direction 'next + "*Direction after marking a message +'up 'down 'next(current direction) 'stop. +Other values are considered as 'stop. +See also 'mew-summary-show-direction'." + :group 'mew-summary + :type '(choice (const next) (const up) (const down) (const stop))) + +(defcustom mew-summary-show-pause nil + "*Pause on going to next message if *non-nil*. +See also 'mew-summary-show-direction' and 'mew-summary-mark-direction'." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-summary-mark-duplicated-skip 'first + "*This value decides which duplicated message should not be +marked with 'mew-mark-duplicated' when 'mew-summary-mark-duplicated' +is executed. + +Possible value is 'first, 'last, or nil. +nil means to mark all duplicated messages. +Other values are considered as 'first." + :group 'mew-summary + :type '(choice (const first) (const last) (const nil))) + +(defcustom mew-summary-recenter-p t + "*If *non-nil*, the current message is recentered in Summary mode when +displayed." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-summary-scan-width nil + "*If *non-nil*, used as the width of Summary mode." + :group 'mew-summary + :type '(choice integer (const nil))) + +(defcustom mew-summary-goto-line-then-display t + "*If non-nil 'mew-summary-goto-line' displays the message +where the cursor jumped." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-summary-jump-top-then-display t + "*If non-nil 'mew-summary-jump-top' displays the top message +where the cursor jumped to the top." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-summary-jump-bottom-then-display t + "*If non-nil 'mew-summary-jump-bottom' displays the bottom message +where the cursor jumped to the bottom." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-summary-region-include-cursor-line nil + "*This value decides whether or not the cursor line is included +to a region." + :group 'mew-summary + :type '(choice (const :tag "Include if the cursor is not on the beginning of the line" nil) + (const :tag "Include if the cursor is on the end of the line" end) + (const :tag "Include always" t))) + +(defvar mew-highlight-timer-interval 3) + +(defcustom mew-syntax-treat-filename-function + 'mew-syntax-treat-filename-default-function + "*A function to modify file names specified by Content-Disposition:" + :group 'mew-summary + :type 'symbol) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message mode +;;; + +(defcustom mew-end-of-message-string "[End of message]" + "*A value inserted on the end of message buffer if *non-nil*." + :group 'mew-message + :type '(choice string (const nil))) + +(defcustom mew-end-of-part-string "[Message is continued]" + "*A value inserted on the end of message buffer if *non-nil*." + :group 'mew-message + :type '(choice string (const nil))) + +(defcustom mew-break-pages t + "*If *non-nil*, a message is broken by mew-page-delimiter." + :group 'mew-message + :type 'boolean) + +(defcustom mew-insert-final-newline t + "*If *non-nil*, and if text/plain does not have final newline, +insert a newline at the end of buffer. " + :group 'mew-message + :type 'boolean) + +(defcustom mew-field-other-visible t + "*If *non-nil*, fields which are not found in 'mew-field-spec' +are displayed after visible fields. Otherwise they are +hidden before visible fields (and after invisible fields)." + :group 'mew-message + :type 'boolean) + +(defcustom mew-use-header-veil t + "*If *non-nil*, field lines of To: and Cc: +over 'mew-header-veil-count' are covered with invisible veils." + :group 'mew-message + :type 'boolean) + +(defcustom mew-header-veil-string "..." + "*A string to indicate some lines are covered with a veil." + :group 'mew-message + :type 'string) + +(defcustom mew-header-veil-count 4 + "*The limit number for veil." + :group 'mew-message + :type 'integer) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Draft mode +;;; + +(defcustom mew-draft-mode-auto-save t + "*If t, a draft is repeatedly saved to 'buffer-auto-save-file-name' +by 'do-auto-save'. If automatic saving is enabled and Emacs is crashed, +the '.save-' file remains. If this value is nil, automatic saving does +not work resulting that no garbage file remains." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-header-alist nil + "*List of (key value) for header field to be inserted on draft. +'((\"X-fingerprint:\" \"6B 63 38 88 67 5E 96 8E CE A4 62 73 3F 11 64 94\") + (\"X-URL:\" \"http://www.example.org/\"))" + :group 'mew-draft + :type '(list (list string string))) + +(defcustom mew-require-final-newline t + "*If non-nil, Mew adds a new line to the draft if ended without a new +line." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-comment-start ">" + "*The value to be set to comment-start in Draft mode." + :group 'mew-draft + :type 'string) + +(defcustom mew-comment-start-skip "^> *" + "*The value to be set to comment-start-skip in Draft mode." + :group 'mew-draft + :type 'string) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Draft mode +;;; + +(defcustom mew-reply-to nil + "*A value inserted into Reply-To: field in Draft mode if *non-nil*. +See also 'mew-config-alist'." + :group 'mew-draft + :type '(choice string (const nil))) + +(defcustom mew-fcc "+backup" + "*A value inserted into Fcc: field in Draft mode if *non-nil*. +See also 'mew-config-alist'." + :group 'mew-draft + :type '(choice string (const nil))) + +(defcustom mew-cc nil + "*A value inserted into Cc: field in Draft mode if *non-nil*. +See also 'mew-config-alist'." + :group 'mew-draft + :type '(choice string (const nil))) + +(defcustom mew-bcc nil + "*A value inserted into Bcc: field in Draft mode if *non-nil*. +See also 'mew-config-alist'." + :group 'mew-draft + :type '(choice string (const nil))) + +(defcustom mew-dcc nil + "*A value inserted into Dcc: field in Draft mode if *non-nil*. +If the value is 'me, your address is automatically inserted +according to the case. +See also 'mew-config-alist'." + :group 'mew-draft + :type '(choice string (const nil))) + +(defcustom mew-from nil + "*A value inserted into From: field in Draft mode if *non-nil*. +For backward-compatibility. See also 'mew-name', 'mew-user', and +'mew-mail-domain'." + :group 'mew-draft + :type '(choice string (const nil))) + +(defcustom mew-organization nil + "*A value inserted into Organization: field in Draft mode if *non-nil*. +See also 'mew-config-alist'." + :group 'mew-draft + :type '(choice string (const nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Citation +;;; + +(defcustom mew-cite-prefix nil + "*Prefix of citation." + :group 'mew-cite + :type '(choice string (const nil))) + +(defcustom mew-cite-hook nil + "*Hook for an external cite mechanism. If you want to use +super-cite, (setq mew-cite-hook 'sc-cite-original)." + :group 'mew-cite + :type 'hook) + +(defcustom mew-cite-strings-function 'mew-cite-strings + "*Function called from mew-cite-original which to create cite labels +according to 'mew-cite-format' and 'mew-cite-fields'." + :group 'mew-cite + :type '(choice function (const nil))) + +(defcustom mew-before-cite-hook nil + "Called in mew-summary-reply-with-citation before citation." + :group 'mew-cite + :type 'hook) + +(defcustom mew-cite-prefix-function nil + "*Function called on citations. A good candidate is +'mew-cite-prefix-username" + :group 'mew-cite + :type '(choice function (const nil))) + +(defcustom mew-cite-prefix-confirmp nil + "*If *non-nil*, citation prefix (such as 'kazu> ') is +confirmed to be used." + :group 'mew-cite + :type 'boolean) + +(defcustom mew-cite-fields (list mew-from: mew-subj: mew-date:) + "*The fields that you want to extract as citation label. +If you change this valuable, you must change mew-cite-format. +The value of the first field becomes the first argument for mew-cite-format. +\(e.g. The default first argument is a value of From: field.) +The value of the second field becomes the second argument for mew-cite-format. +.... +If this is nil, label is not generated." + :group 'mew-cite + :type '(repeat string)) + +(defcustom mew-cite-format "From: %s\nSubject: %s\nDate: %s\n\n" + "*Format for the citation label." + :group 'mew-cite + :type 'string) + +(defcustom mew-draft-cite-fill-mode nil + "*A method to format a citation header. +If 'wrap, format with fill-region. +If 'truncate, cut over fill-column and insert 'mew-draft-cite-ellipses'." + :group 'mew-draft + :type '(choice (symbol :tag "Wrap" wrap) + (symbol :tag "Truncate" truncate) + (symbol :tag "Asis" nil))) + +(defcustom mew-draft-cite-ellipses " .." + "String that is inserted a truncated line when +'mew-draft-cite-fill-mode' is 'truncate." + :group 'mew-cite + :type 'string) + +(defcustom mew-draft-cite-label-fill-column nil + "If *non-nil*, this value is used for 'mew-draft-cite-fill-mode' +instead of 'fill-column'." + :group 'mew-cite + :type '(choice integer (const nil))) + +(defcustom mew-summary-reply-position 'body + "If 'body, the cursor locates in the beginning of the body. +Otherwise, the cursor is after To:." + :group 'mew-cite + :type 'symbol) + +(defcustom mew-summary-reply-with-citation-position 'end + "If 'body, the cursor locates in the beginning of the body. +If 'end, the cursor locates after the citation. +Otherwise, the cursor is after To:." + :group 'mew-cite + :type 'symbol) + +(defcustom mew-cite-ignore-region nil + "*If *non-nil*, the region of a draft is ignored when citing." + :group 'mew-cite + :type 'boolean) + +(defcustom mew-cite-ignore-mouse-region t + "*If *non-nil*, a region specified by mouse is ignored when citing." + :group 'mew-cite + :type 'boolean) + +(defcustom mew-visit-queue-after-sending nil + "*If *non-nil*, visit to +queue after '\\\\[mew-draft-make-message]' in Draft mode." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-visit-inbox-after-setting-case nil + "*If *non-nil*, visit to an appropriate inbox after setting a case with '\\\\[mew-summary-set-case]'." + :group 'mew-summary + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Charset +;;; + +(defcustom mew-charset-input-method-alist nil + "*Alist of charset and input-method. When a message is cited +into Draft mode the charset of the message is found in this +variable, the corresponding input-method is automatically +selected. An example configuration is as follows: + +\(setq mew-charset-input-method-alist + '((\"iso-8859-1\" \"latin-1-postfix\") + (\"iso-8859-2\" \"latin-2-postfix\"))) +" + :group 'mew-draft + :type '(list (list string string))) + +(defun mew-charset-to-input-method (charset) + (if (stringp charset) + (mew-alist-get-value + (mew-assoc-case-equal + charset mew-charset-input-method-alist 0)))) + +(defcustom mew-charset-m17n "utf-8" + "*A charset to be used if multiple character set are found and +an appropriate charset cannot be chosen. Possible candidates are +\"utf-8\" and \"iso-2022-jp-2\"." + :group 'mew-draft + :type '(choice (const "utf-8") (const "iso-2022-jp-2"))) + +(defcustom mew-charset-latin "iso-8859-15" + "*This variable is used for selection of charset when composing. +If characters of both Latin 1 and Lain 9 exist in a draft, Mew takes +the following step to decide a charset. + +1. If 'unify-8859-on-decoding-mode' is used: + 1.1. Use \"iso-8859-1\" if no loss. + 1.2. Otherwise, use \"utf-8\". +2. If 'unify-8859-on-decoding-mode' is not used: + + 2.1. If both ISO-8859-1 and ISO-8859-15 can be used with no + loss, 'mew-charset-latin' is used. + 2.2. Use \"iso-8859-1\" if no loss. + 2.3. Use \"iso-8859-15\" if no loss. + 2.3. Otherwise, use \"utf-8\". +" + :group 'mew-draft + :type '(choice (const "iso-8859-1") (const "iso-8859-15"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Signature +;;; + +(defcustom mew-signature-file "~/.signature" + "*A signature file to be inserted in Draft mode. To support multiple +signature files, use 'c-sig.el'." + :group 'mew-draft + :type 'file) + +(defcustom mew-signature-insert-last nil + "*If *non-nil*, the signature file is inserted in the last of body. +Otherwise, it is inserted at the current point. If you created multipart +and mew-signature-as-lastpart is *non-nil*, this variable is ignored." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-signature-as-lastpart nil + "*If *non-nil*, the signature file is appended as the final part +when you create multipart." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-signature-description "My signature" + "*This variable is used as a description if the signature is appended +as the final part." + :group 'mew-draft + :type 'string) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Samba +;;; + +(defcustom mew-use-samba-encoding nil + "*Use SAMBA encoding for non-ASCII file name when saving." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-use-samba-encoding-type 'cap + "*A type of SAMBA encoding. Either 'cap or 'hex." + :group 'mew-summary + :type '(choice (const cap) (const hex))) + +(defcustom mew-cs-samba 'shift_jis + "*A character set before SAMBA encoding." + :group 'mew-summary + :type 'coding-system) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Attachments +;;; + +(defcustom mew-attach-move-by-line nil + "*If non-nil, 'mew-attach-{next,previous}' move the cursor line by line." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-attach-move-next-after-copy nil + "If non-nil, the cursor moves the next position after copying/linking +in Attachments." + :group 'mew-draft + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Completion +;;; + +(defcustom mew-fields + (list mew-from: mew-to: mew-cc: mew-dcc: mew-fcc: mew-bcc: mew-subj: + mew-reply-to: mew-followup-to: mew-newsgroups: mew-distribution: + mew-resent-from: mew-resent-to: mew-resent-cc: + mew-resent-dcc: mew-resent-fcc: mew-resent-bcc:) + "*Completion field list in Draft mode." + :group 'mew-complete + :type '(repeat string)) + +(defcustom mew-complete-case-ignore-case nil + "*Non-nil means Mew does not consider case is significant in case +completion." + :group 'mew-complete + :type 'boolean) + +(defcustom mew-complete-folder-ignore-case nil + "*Non-nil means Mew does not consider case is significant in folder +completion." + :group 'mew-complete + :type 'boolean) + +(defcustom mew-complete-address-ignore-case t + "*Non-nil means Mew does not consider case is significant in address +completion." + :group 'mew-complete + :type 'boolean) + +(defcustom mew-circular-complete-domain-ignore-case t + "*Non-nil means Mew does not consider case is significant in +circular domain completion." + :group 'mew-complete + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Field order +;;; + +(defcustom mew-field-order-for-editing + (list mew-to: mew-newsgroups: mew-cc: mew-subj: mew-from:) + "*A field order list for editing." + :group 'mew-draft + :type '(repeat string)) + +(defcustom mew-field-order-for-reediting + (list mew-to: mew-newsgroups: mew-cc: mew-subj: mew-from:) + "*A field order list for reediting." + :group 'mew-draft + :type '(repeat string)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Fields to be deleted +;;; + +(defcustom mew-field-delete-common + '("From " ">From" "X-Mew") + "*A field list to be deleted for reediting/resending/forwarding/saving." + :group 'mew-draft + :type '(choice (const nil) + (repeat :tag "Field list" (string :tag "Field")))) + +(defvar mew-field-delete nil) ;; backward compatibility + +(defcustom mew-field-delete-for-editing + (list mew-received: "Return-Path:" "Delivery-Date:" "Delivered-To:" + mew-message-id: mew-mv: "Content-" + "Precedence:" mew-organization: "X-" + "Lines:" "Status:" "Posted:" "Forwarded:" "Replied:" "X-UIDL:" + "DomainKey-Signature:" "DKIM-Signature:" + "Authentication-Results:" "List-.*:" "Errors-To:") + "*A field list to be deleted in Edit mode." + :group 'mew-draft + :type '(choice (const nil) + (repeat :tag "Field list" (string :tag "Field")))) + +(defcustom mew-field-delete-for-reediting + (or mew-field-delete + (list mew-received: "Return-Path:" "Delivery-Date:" "Delivered-To:" + mew-date: mew-message-id: mew-mv: "Content-" + "Precedence:" mew-organization: "X-" + "Lines:" "Status:" "Posted:" "Forwarded:" "Replied:" "X-UIDL:" + "DomainKey-Signature:" "DKIM-Signature:" + "Authentication-Results:" "List-.*:" "Errors-To:" "Sender:")) + "*A field list to be deleted when edit again." + :group 'mew-draft + :type '(choice (const nil) + (repeat :tag "Field list" (string :tag "Field")))) + +(defcustom mew-field-delete-for-others + (list mew-received: "Return-Path:" "Delivery-Date:" "Delivered-To:" + mew-to: mew-cc: mew-from: mew-organization: + "Lines:" "Status:" "Posted:" "Forwarded:" "Replied:" "X-UIDL:" + "DomainKey-Signature:" "DKIM-Signature:") + "*A field list to be deleted when send with different To: and Cc:." + :group 'mew-draft + :type '(choice (const nil) + (repeat :tag "Field list" (string :tag "Field")))) + +(defcustom mew-field-delete-for-resending + (list mew-received: "Return-Path:" "Delivery-Date:" "Delivered-To:" + "Resent-" "X-Resent-" + "Lines:" "Status:" "Posted:" "Forwarded:" "Replied:" "X-UIDL:") + "*A field list to be deleted when resending." + :group 'mew-draft + :type '(choice (const nil) + (repeat :tag "Field list" (string :tag "Field")))) + +(defcustom mew-field-delete-for-forwarding + '("Lines:" "Status:" "Posted:" "Forwarded:" "Replied:" "X-UIDL:") + "*A field list to be deleted when forwarding." + :group 'mew-draft + :type '(choice (const nil) + (repeat :tag "Field list" (string :tag "Field")))) + +(defcustom mew-field-delete-for-saving () + "*A field list to be deleted when saving a message to a file." + :group 'mew-summary + :type '(choice (const nil) + (repeat :tag "Field list" (string :tag "Field")))) + +(defcustom mew-field-delete-for-joining + (list mew-mv: mew-subj: mew-message-id: "Encrypted" "Content-") + "*A field list to be deleted when joining." + :group 'mew-summary + :type '(repeat :tag "Field list" (string :tag "Field"))) + +(defcustom mew-field-for-printing + '("Subject:" "From:" "To:" "Cc:" "Date:") + "*A field list to print" + :group 'mew-summary + :type '(repeat :tag "Field list" (string :tag "Field"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Directory stuff +;;; + +(defcustom mew-summary-trace-directory t + "*If non-nil, change to the folder directory when +mew-summary-goto-folder." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-save-dir mew-home + "*The default directory to save messages or parts in Summary mode. +See also 'mew-copy-dir'." + :group 'mew-summary + :type 'directory) + +(defcustom mew-summary-preserve-dir nil + "*If non-nil, the previous directory is used as the default +directory for save, etc. See also 'mew-draft-preserve-dir'." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-copy-dir mew-home + "*The default directory from which attachments are copied in Draft mode. +See also 'mew-save-dir'." + :group 'mew-draft + :type 'directory) + +(defcustom mew-draft-preserve-dir nil + "*If non-nil, the previous directory is used as the default +directory for copy, etc. See also 'mew-summary-preserve-dir'." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-file-append-p nil + "*If *non-nil*, a message or a part is appended to the existing file +on '\\\\[mew-summary-save]'. Otherwise overwrote." + :group 'mew-summary + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Folders +;;; + +(defcustom mew-regex-folder-candidate "^[^.#0-9]\\|^[0-9].*[^0-9]" + "*Regular expression used in 'mew-dir-list-with-link-count' +and 'mew-dir-list-without-link-count' to list up folder +candidates. The default value \"^[^.#0-9]\\\\|^[0-9].*[^0-9]\" lists up +folders whose name is alphabet only." + :group 'mew-env + :type 'regexp) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Refile +;;; + +(defconst mew-custom-type-of-guess-alist + '(list (list string (list string string)))) + +(defcustom mew-refile-guess-alist nil + "*If non-nil, mew guesses destination folder by using this hint. +The format is like this: + + (setq mew-refile-guess-alist + '((\"To:\" + (\"wide@wide\" \"+wide/wide\") + (\"adam\" \"+labo/adam\")) + (\"Newsgroups:\" + (\"^nifty\\\\.\\\\([^ ]+\\\\)\" \"+Nifty/\\\\1\")) + (\"From:\" + (\"uucp\" \"+adm/uucp\") + (\".*\" \"+misc\")) + )) +" + :group 'mew-refile + :type mew-custom-type-of-guess-alist) + + +(defcustom mew-refile-ctrl-multi t + "*If *non-nil*, guess functions guess multi folders." + :group 'mew-refile + :type 'boolean) + +(defcustom mew-refile-guess-key-list + (append mew-resent-dest:-list mew-destination:-list) + "*A list of field key used by mew-refile-guess-by-folder." + :group 'mew-refile + :type '(repeat string)) + +(defvar mew-refile-guess-control + '(mew-refile-guess-by-alist + mew-refile-ctrl-throw + mew-refile-guess-by-newsgroups + mew-refile-guess-by-folder + mew-refile-ctrl-throw + mew-refile-ctrl-auto-boundary + mew-refile-guess-by-thread + mew-refile-ctrl-throw + mew-refile-guess-by-from-folder + mew-refile-ctrl-throw + mew-refile-guess-by-from + mew-refile-ctrl-throw + mew-refile-guess-by-default)) + +(defcustom mew-refile-auto-refile-skip-any-mark nil + "*If *non-nil*, 'mew-summary-auto-refile' does not touch +any already marked message." + :group 'mew-refile + :type 'boolean) + +(defcustom mew-refile-auto-refile-confirm nil + "*If *non-nil*, 'mew-summary-auto-refile' prompts the user for +confirmation before refiling." + :group 'mew-refile + :type 'boolean) + +(defcustom mew-refile-guess-strip-domainpart t + "*If *non-nil*, 'mew-refile-guess-by-default' strips domainpart of from" + :group 'mew-refile + :type 'boolean) + +(defcustom mew-refile-guess-from-me-is-special nil + "*If *non-nil*, 'mew-refile-guess-by-from-*' think the messages from +yourself as special. They use To: or Cc: instead of From:" + :group 'mew-refile + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Case guess +;;; + +(defcustom mew-case-guess-alist nil + "*If *non-nil*, this value is used to guess cases when +prepared or composed. +The syntax is exactly the same as 'mew-refile-guess-alist'." + :group 'mew-draft + :type mew-custom-type-of-guess-alist) + +(defcustom mew-case-guess-when-replied-alist nil + "*If *non-nil*, this value is used to guess cases when replied. +The syntax is exactly the same as 'mew-refile-guess-alist'." + :group 'mew-draft + :type mew-custom-type-of-guess-alist) + +(defcustom mew-case-guess-when-prepared t + "*If *non-nil*, case is guessed when a draft is prepared." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-case-guess-when-composed nil + "*If *non-nil*, case is guessed when a message is composed." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-case-guess-when-replied t + "*If *non-nil*, case is guessed when replying to a message." + :group 'mew-draft + :type 'boolean) + +(defcustom mew-case-guess-addition nil + "*If *non-nil*, new guessed cases are added to old cases. +Otherwise, the old cases are overridden." + :group 'mew-draft + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Temporary files +;;; + +(defcustom mew-temp-file-initial + (expand-file-name (user-login-name) (if (fboundp 'temp-directory) + (temp-directory) + (if (boundp 'temporary-file-directory) + temporary-file-directory + "/tmp"))) + "*Hint to make a secure directory on the local file system. On +setup phase Mew make a secure directory from this variable and set +mew-temp-file a file name prefix contained the directory name. The +directory must be unreadable from others, otherwise it might become a +big security hole. And this directory must not be gained access +through network to prevent tire-tapping. Mew never uses +'call-process-region' rather does use 'call-process' creating a +temporary file with mew-temp-file by itself. If 'call-process-region' +is used, Emacs creates a temporary file (probably in /tmp). So bad +guys can wiretap the temporary file." + :group 'mew-privacy + :type 'directory) + +(defcustom mew-delete-temp-file t + "*If *non-nil*, delete temporary files when external commands terminate." + :group 'mew-summary + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Auto +;;; + +(defcustom mew-auto-get t + "If *non-nil*, Mew gets messages from your mailbox automatically. +'\\[universal-argument] \\[mew]' equals to '\\[mew]' with 'mew-auto-get' +reversed." + :group 'mew-summary + :type 'boolean) + +(defcustom mew-auto-flush-queue t + "If *non-nil* and if there are queued messages in +queue, +they are flushed after getting message (i.e. '\\\\[mew-summary-retrieve]'). This idea saves money in dial up environment." + :group 'mew-draft + :type 'boolean) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Pick and Sort +;;; + +(defcustom mew-pick-pattern-list nil + "*A list of pick pattern which can be circular completed with '\\\\[mew-circular-complete-switch]' +The first member is displayed as a default value." + :group 'mew-summary + :type '(choice (const nil) (repeat string))) + +(defcustom mew-pick-field-list + '("head=" "to=" "cc=" "subject=" "dcc=" "fcc=" "bcc=" "date=" + "reply-to=" "followup-to=" "from=" "newsgroups=") + "*A list of key for pick pattern." + :group 'mew-summary + :type '(choice (const nil) (repeat string))) + +(defcustom mew-sort-default-key "date" + "*Default sort key when inputting a sort key. +Its format is key:mode where more is found in 'mew-sort-mode'." + :group 'mew-summary + :type 'string) + +(defcustom mew-sort-default-key-alist nil + "*List of (folder sort-key) to decide a default sort-key +of a specific folder. An example is follows: +\(setq mew-sort-default-key-alist + '((\"+tmp/beginners\" \"x-sequence\") + (\"+tmp/elips\" \"x-mail-count\")))" + :group 'mew-summary + :type '(list (list string string))) + +(defcustom mew-sort-key-alist + '(("date" "date") ("subject") ("from") ("to") ("newsgroups") + ("posted" "date") ("x-sequence" "postnum") + ("x-mail-count" "num") ("x-ml-count" "num")) + "*List of fields for 'mew-summary-sort'. +Each element is (FIELD-NAME) or (FIELD-NAME . MODE). +MODE is one of \"date\" (by chronological order) or + \"num\" (by numerical order) or + \"postnum\" (by numerical order of postfix numeric) or + \"text\" (by alphabetical order) or + \"ml\" (by alphabetical order with ml prefix removed) or + \"mlnum\" (by numerical order of ml number). +\(nil means \"text\")." + :group 'mew-summary + :type 'sexp) + +(defvar mew-sort-modes '("date" "num" "postnum" "text" "ml" "mlnum")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Range +;;; + +(defvar mew-range-all "0") + +(defvar mew-range-str-all "all") +(defvar mew-range-str-update "update") +(defvar mew-range-str-last "last:") +(defvar mew-range-str-sync "sync") + +(defcustom mew-input-range-list + (list mew-range-str-update mew-range-str-all mew-range-str-last) + "*A list used by range completion." + :group 'mew-complete + :type '(repeat string)) + +(defcustom mew-input-range-remote-list + (list mew-range-str-update mew-range-str-all mew-range-str-last mew-range-str-sync) + "*A list used by range completion." + :group 'mew-complete + :type '(repeat string)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Highlight +;;; + +(defvar mew-summary-cook-function 'mew-summary-cook-region) + +(defcustom mew-use-highlight-mark t + "*If non-nil, highlight marked lines in Summary/Virtual mode." + :group 'mew-highlight + :type 'boolean) + +(defcustom mew-use-highlight-header t + "*If non-nil, highlight a header in Message/Draft mode." + :group 'mew-highlight + :type 'boolean) + +(defcustom mew-use-highlight-body t + "*If non-nil, highlight a body in Message/Draft mode." + :group 'mew-highlight + :type 'boolean) + +(defcustom mew-use-highlight-url t + "*If non-nil, highlight URLs in Message/Draft mode." + :group 'mew-highlight + :type 'boolean) + +(defcustom mew-use-cursor-mark nil + "*If *non-nil*, show 'mew-cursor-mark' in the beginning of the +cursor line. This is convenient if 'mew-use-highlight-cursor-line' is +not available." + :group 'mew-highlight + :type 'boolean) + +(defcustom mew-use-highlight-cursor-line t + "*Put the 'mew-highlight-cursor-line-face' face on the current line +in Summary/Virtual mode." + :group 'mew-highlight + :type 'boolean) + +(defcustom mew-use-highlight-mouse-line nil + "*Put the 'mew-highlight-mouse-line-face' face on the mouse location +in Summary/Virtual mode." + :group 'mew-highlight + :type 'boolean) + +(defcustom mew-use-highlight-x-face mew-icon-p + "*Iconify X-Face: in Message mode." + :group 'mew-highlight + :type 'boolean) + +(defcustom mew-use-highlight-x-face-inversion nil + "*Invert an X-Face: image in Message mode." + :group 'mew-highlight + :type 'boolean) + +;;; +;;; Styles and colors +;;; + +(defcustom mew-cursor-mark ">" + "*The mark in the beginning of the cursor line if +'mew-use-cursor-mark' is *non-nil*." + :group 'mew-highlight + :type '(choice string (const nil))) + +(defcustom mew-highlight-cursor-line-face 'underline + "*Face to highlight the cursor line in Summary/Virtual mode" + :group 'mew-highlight + :type 'face) + +(defcustom mew-highlight-mouse-line-face 'highlight + "*Mouse face to highlight URL in Message/Draft mode" + :group 'mew-highlight + :type 'face) + +(defcustom mew-regex-url + (concat + "\\b\\(" + "\\(\\(file\\|news\\|mailto\\):\\)" + "\\|" + "\\(\\(s?https?\\|ftp\\|gopher\\|telnet\\|wais\\)://\\)" + "\\)" + "[^ \t\n>)\"]*" + "[^] \t\n>.,:)\"]") + "*Regular expression to find URL." + :group 'mew-highlight + :type 'regexp) + +(defcustom mew-highlight-url-mouse-face 'highlight + "*Mouse face to highlight URL in Message/Draft mode" + :group 'mew-highlight + :type 'face) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Addrbook +;;; + +(defcustom mew-use-auto-alias t + "*If non-nil, addresses on the To: and Cc: field in Draft mode +will be automatically leaned as alias." + :group 'mew-addrbook + :type 'boolean) + +(defcustom mew-addrbook-comment-regex "^;.*$\\|#.*$" + "*Regular expression for Addrbook." + :group 'mew-addrbook + :type 'regexp) + +(defcustom mew-addrbook-append-domain-p t + "If non-nil, addresses, which do not have domain part in a header, +will be appended (mew-mail-domain) when composing." + :group 'mew-addrbook + :type 'boolean) + +(defcustom mew-addrbook-override-by-newone t + "If non-nil, the 'user' entry in 'mew-alias-auto-alist' +is override by a new entry of (user different-address). +This means that addresses in To: and Cc: in Draft mode are +always learned with an exception 'user' is defined in Addrbook. +If nil, the old 'user' entry remains." + :group 'mew-addrbook + :type 'boolean) + +(defcustom mew-addrbook-for-cite-label nil + "*How to replace the From: value in cite label +with Addrbook. See 'mew-addrbook-switch'." + :group 'mew-addrbook + :type 'symbol) + +(defcustom mew-addrbook-for-cite-prefix 'username + "*How to replace the From: value in cite prefix +with Addrbook. See 'mew-addrbook-switch'." + :group 'mew-addrbook + :type 'symbol) + +(defcustom mew-addrbook-for-address-expansion 'name + "*How to replace an address in address fields +with Addrbook. See 'mew-addrbook-switch'." + :group 'mew-addrbook + :type 'symbol) + +(defcustom mew-addrbook-for-summary 'nickname + "*How to replace a From: address in summary-form with Addrbook. +See 'mew-addrbook-switch' and 'mew-summary-form-extract-rule'." + :group 'mew-addrbook + :type 'symbol) + +(defcustom mew-addrbook-strip-domainpart t + "*If *non-nil*, a shortname is created by stripping its domain part +when '\\\\[mew-summary-addrbook-add]' in Summary mode." + :group 'mew-addrbook + :type 'boolean) + +(defcustom mew-addrbook-alias-not-learn-list nil + "*A list of a part of address. If an address matches to one out of the +list. the address is not registered to Addrbook." + :group 'mew-addrbook + :type '(choice (const nil) (repeat string))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Cache +;;; + +(defcustom mew-cache-size 10 + "*Number of buffer for message cache." + :group 'mew-cache + :type 'integer) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Privacy +;;; + +(defcustom mew-draft-privacy-method 'pgp + "Privacy method to create messages in Draft mode. +You should choose 'pgp or 'smime." + :group 'mew-privacy + :type '(choice (const pgp) (const smime))) + +(defcustom mew-protect-privacy-always nil + "*If non-nil, a draft is to be protected according to +'mew-protect-privacy-always-type'." + :group 'mew-privacy + :type 'boolean) + +(defcustom mew-protect-privacy-always-type 'pgp-signature + "*A type of privacy protection for all drafts. +Currently, 'pgp-signature, 'pgp-encryption, 'pgp-signature-encryption, +'pgp-encryption-signature, and nil are available. Since signature +does not require receiver's public key, signature service may be +appropriate for this value." + :group 'mew-privacy + :type '(choice (const pgp-signature) + (const pgp-encryption) + (const pgp-signature-encryption) + (const pgp-encryption-signature) + (const smime-signature) + (const smime-encryption) + (const smime-signature-encryption) + (const smime-encryption-signature) + (other :tag "nil" nil))) + +(defcustom mew-protect-privacy-encrypted nil + "*If non-nil, a draft replying a encrypted message is to be protected +according to 'mew-protect-privacy-encrypted-type'." + :group 'mew-privacy + :type 'boolean) + +(defcustom mew-protect-privacy-encrypted-type 'pgp-encryption + "*A type of privacy protection for drafts replying encrypted +messages. Currently, 'pgp-signature, 'pgp-encryption, +'pgp-signature-encryption, 'pgp-encryption-signature, +and nil are available." + :group 'mew-privacy + :type '(choice (const pgp-signature) + (const pgp-encryption) + (const pgp-signature-encryption) + (const pgp-encryption-signature) + (const smime-signature) + (const smime-encryption) + (const smime-signature-encryption) + (const smime-encryption-signature) + (other :tag "nil" nil))) + +(defcustom mew-protect-privacy-with-old-pgp-signature nil + "*If non-nil and 'mew-use-old-pgp' is non-nil, +the old fashioned PGP message are used when composing." + :group 'mew-privacy + :type 'boolean) + +(defcustom mew-passwd-timer-unit 10 + "*Minutes of timer unit to cancel the cached passwords." + :group 'mew-privacy + :type 'integer) + +(defcustom mew-passwd-lifetime 2 + "*Number of 'mew-passwd-timer-unit' to cancel the cached passwords." + :group 'mew-privacy + :type 'integer) + +(defcustom mew-passwd-reset-timer t + "*If non-nil, put the lifetime of a cached password longer when +the password is used." + :group 'mew-privacy + :type 'boolean) + +(defcustom mew-encrypt-to-myself t + "*if non-nil, any message/part to be encrypted is encrypted with +your public key as well as receivers' one." + :group 'mew-privacy + :type 'boolean) + +(defcustom mew-pgp-signer nil + "*ID of a PGP key to use for sign" + :group 'mew-privacy + :type 'string) + +(defcustom mew-smime-signer nil + "*ID of a S/MIME key to use for sign" + :group 'mew-privacy + :type 'string) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; PGP Public key fetch +;;; + +(defvar mew-x-pgp-key-list + '("x-pgp-key:" "x-pgp-key-url:" "x-pgp-public-key:" "x-pgp-public-key-url:" + "x-pgp5-key:" "x-pgp5-key-url:" "x-pgp5-public-key:" + "x-pgp5-public-key-url:" "x-public-key:")) + +(defvar mew-pgp-pks-port 11371) +(defvar mew-pgp-pks-lang "/pks/lookup?op=get&search=") + +;; Tue Dec 16 16:28:11 JST 2003 +;; http://pgp.zdv.uni-mainz.de/keyserver/bigbrother/ + +(defvar mew-pgp-pks-servers + '(("openpksd.org" t) + ("blackhole.pca.dfn.de" nil) + ("pgp.ael.be" nil) + ("pgp.dtype.org" nil) + ("pgp.mit.edu" nil) + ("pgp.nic.ad.jp" nil) + ("pgp.rediris.es" nil) + ("pgp.uni-mainz.de" nil) + ("pgp.uni-paderborn.de" nil) + ("wwwkeys.1.us.pgp.net" nil) + ("wwwkeys.2.us.pgp.net" nil) + ("wwwkeys.3.us.pgp.net" nil) + ("wwwkeys.ch.pgp.net" nil) + ("wwwkeys.cz.pgp.net" nil) + ("wwwkeys.es.pgp.net" nil) + ("wwwkeys.uk.pgp.net" nil))) + +(defun mew-pgp-pks-http-port-p (server alist) + (nth 1 (assoc server alist))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; SSH +;;; + +(defvar mew-ssh-number-of-password-prompts 3) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Sub-programs +;;; + +(defvar mew-prog-mewl "mewl") +(defvar mew-prog-mime-encode "mewencode") +(defvar mew-prog-mime-decode "mewencode") +(defvar mew-prog-8bit "mewencode") +(defvar mew-prog-unshar "unshar") +(defvar mew-prog-tar "tar") +(defvar mew-prog-compress "compress") +(defvar mew-prog-gzip "gzip") +(defvar mew-prog-zip "zip") +(defcustom mew-prog-pgp "gpg" + "*PGP name for version check." + :group 'mew-privacy + :type 'string) + +(defvar mew-prog-pgpkey "wget") +(defvar mew-prog-pgpkey-args '("-q" "-O" "-")) + +(defvar mew-ssh-prog "ssh") +(defvar mew-ssh-prog-args nil) + +(defvar mew-prog-uncompface "uncompface") +(defvar mew-prog-icontopbm "icontopbm") +(defvar mew-prog-pbmtoxbm "pbmtoxbm") +(defvar mew-prog-pbminvert "pnminvert") + +(defvar mew-prog-grep "grep") +(defvar mew-prog-grep-opts '("-l" "-e")) + +(defvar mew-prog-grep-max-msgs 10000) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; X face +;;; + +(defcustom mew-x-face-file "~/.xface" + "*If *non-nil* and the file exists, X-Face: fields is inserted." + :group 'mew-summary + :type '(choice file (const nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; spam and ham +;;; + +(defcustom mew-spam-prog "bogofilter" + "*A command which learns spams." + :group 'mew-summary + :type 'string) + +(defcustom mew-spam-prog-args '("-s" "-N" "-v") + "*A list of command arguments which learns spams." + :group 'mew-summary + :type '(choice (const nil) (repeat string))) + +(defcustom mew-ham-prog "bogofilter" + "*A command which learns hams." + :group 'mew-summary + :type 'string) + +(defcustom mew-ham-prog-args '("-n" "-S" "-v") + "*A list of command arguments which learns hams." + :group 'mew-summary + :type '(choice (const nil) (repeat string))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mode names +;;; + +(defvar mew-mode-name-header "Header") +(defvar mew-mode-name-draft "Draft") +(defvar mew-mode-name-message "Message") +(defvar mew-mode-name-summary "Summary") +(defvar mew-mode-name-virtual "Virtual") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Types +;;; + + +(defvar mew-file-type "MewX") +(defvar mew-file-creator "EMAx") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; For broken MUAs +;;; + +(defcustom mew-decode-broken t + "If non-nil, Mew decode broken messages. + +\(1) Decode quoted encoded-words, which violates RFC 2047. + +Good example: + From: Kazu Yamamoto (=?ISO-2022-JP?B?GyRCOzNLXE9CSScbKEI=?=) + +Bad example: + From: Kazu Yamamoto (\"=?ISO-2022-JP?B?GyRCOzNLXE9CSScbKEI=?=\") + + +\(2) Decode raw non-ASCII text, which violates RFC 822. +This is typically found in Subject: field. + +Good example: + Subject: =?iso-2022-jp?B?GyRCJEYkOSRIGyhC?= +Bad example: + Subject: Raw non-ASCII text. + +\(3) Decode invalid MIME parameters, which violates RFC 2231. +\(i) Raw text. +\(ii) Encorded-word defined in RFC 2047. + +Good example: + Content-Disposition: attachment; + filename*=iso-2022-jp''%1B%24B%24F%249%24H%1B%28B + +Bad example + Content-Disposition: attachment; + filename=\"=?iso-2022-jp?B?GyRCJEYkOSRIGyhC?=\" + +=(4) Decode invalid non-ASCII MIME body, whose charset is US-ASCII or +not present. + +Good example: + Content-Type: text/plain; charset=ISO-2022-jp + + ISO-2022-JP text + +Bad example: + Content-Type: text/plain + + ISO-2022-JP text + +\(5) Decode invalid non-ASCII text, whose charset is UTF-8 or not present. + +Good example: + Content-Type: text/plain; charset=ISO-8859-15 + + ISO-8859-15 text + +Bad example: + Content-Type: text/plain; charset=UTF-8 + + ISO-8859-15 text +" + :group 'mew-message + :type 'boolean) + +(defcustom mew-use-name-parameter t + "*If non-nil, the invalid NAME parameter of Content-Type: is checked +as a file name in addition to the legal FILENAME parameter of +Content-Disposition:." + :group 'mew-message + :type 'boolean) + +(defcustom mew-broken-parameter-list '("name" "filename") + "*A list of parameter names whose value contains non-ASCII strings +produced by broken MUAs." + :group 'mew-message + :type '(repeat string)) + +(defvar mew-decode-ws-fields '("Subject:")) + +(defvar mew-no-warning-fields ()) ;; capitalized + +(defvar mew-no-warning-params ()) ;; downcased + +(defcustom mew-warning-field-level 1 + "*If warning level of a field is greater than or equal to this value, +the warning is displayed on X-Mew:. +Level 1: syntax is correct, but not recommenced. +Level 2: syntax error." + :group 'mew-message + :type 'integer) + +(defcustom mew-encode-singlepart-hook nil + "*Hook called before making a single part." + :group 'mew-draft + :type 'hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Preventing warning messages when byte-compiling +;;; + +(defvar mew-regex-message-files nil) +(defvar mew-regex-message-files2 nil) +(defvar mew-regex-message-files3 nil) +(defvar mew-regex-message-files4 nil) +(defvar mew-regex-message-files5 nil) + +(defvar mew-basic-folders nil) + +(provide 'mew-vars) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-vars.el ends here diff --git a/elpa/mew-20150813.2354/mew-vars2.el b/elpa/mew-20150813.2354/mew-vars2.el new file mode 100644 index 00000000..42c237ea --- /dev/null +++ b/elpa/mew-20150813.2354/mew-vars2.el @@ -0,0 +1,1012 @@ +;;; mew-vars2.el + +;; Author: Kazu Yamamoto +;; Created: Feb 1, 1999 + +;;; Code: + +(require 'mew-vars) + +;;; (1) Variables closer to constant. +;;; (2) Variables for soft-coding. +;;; (3) Difficult options with some macros. +;;; Use mew-add-first, mew-insert-after, mew-replace-with, +;;; and mew-remove-entry to modify the variables. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Marks +;;; + +(defvar mew-mark-review ?*) +(defvar mew-mark-escape ?$) +(defvar mew-mark-delete ?D) +(defvar mew-mark-unlink ?X) +(defvar mew-mark-refile ?o) +(defvar mew-mark-read mew-sp) +(defvar mew-mark-unread ?U) +(defvar mew-mark-tmp ?\0) ;; temporary use only. +(defvar mew-mark-default-walk mew-mark-review) +(defvar mew-mark-walk mew-mark-default-walk) +(defvar mew-mark-duplicated mew-mark-delete) +(defvar mew-mark-show-list (list mew-mark-read mew-mark-unread mew-mark-review)) +(defvar mew-mark-show-list2 (list mew-mark-unread mew-mark-review)) + +(defvar mew-summary-mark-undo-marks + `(,mew-mark-delete ,mew-mark-unlink ,mew-mark-refile ,mew-mark-read) + "*A list of marks to be canceled by '\\\\[mew-summary-mark-undo-all]'.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Field Magic +;;; + +(defvar mew-reply-string "Re: ") +(defvar mew-reply-regex + "Re\\(\\|[*^]?[0-9]+\\|\\[[0-9]+\\]\\|([0-9]+)\\)[:>] *" + "Regexp of various Re: expression in Subject:") +(defvar mew-forward-string "Fw: ") +(defvar mew-forward-regex "\\(Fw\\|Fwd\\|Forward\\): *" + "Regexp of various Fw: expression in Subject:") +(defvar mew-was-regex " *[[(] *\\(was[^a-z]\\|Re:\\).*[])] *$" + "Regexp of various (was ...) expression in Subject:") + +(defvar mew-subject-simplify-replace-alist + `(;; (REGEXP . NEW) --- NEW may be nil for deletion (same to "") + ;; replace multiple Re: and Fw: into single Re: + (,(concat "^" ;; regexp + mew-reply-regex + "\\(" + mew-reply-regex + "\\|" + mew-forward-regex + "\\)*") + mew-reply-string) ;; new text + ;; replace multiple Fw: and Re: into single Fw: + (,(concat "^" ;; regexp + mew-forward-regex + "\\(" + mew-reply-regex + "\\|" + mew-forward-regex + "\\)*") + mew-forward-string) ;; new text + ;; delete extra string (no new text means delete) + (,mew-was-regex nil)) ;; regexp + "*Replacement alist to simplify Subject: field body +Each element is cons cell whose car is REGEXP to replace, +cdr is new text.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Error +;;; + +(defvar mew-error-unknown-charset "**UNKNOWN CHARSET**") +(defvar mew-error-broken-string "**BROKEN STRING**") +(defvar mew-error-invalid-b-encoding " **B ENCODING ERROR** ") +(defvar mew-error-invalid-q-encoding " **Q ENCODING ERROR** ") +(defvar mew-error-no-subject "** no subject **") +(defvar mew-error-broken-address "**BROKEN ADDRESS**") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Files +;;; + +;; In each folder + +(defvar mew-summary-cache-file ".mew-summary" + "Cache file for Summary mode contents.") + +(defvar mew-summary-touch-file ".mew-mtime" + "Time-stamp file for message folders.") + +;; Under mew-conf-path + +(defcustom mew-addrbook-file "Addrbook" + "*A file which contains AddrBook information." + :group 'mew-addrbook + :type 'string) + +(defvar mew-alias-auto-file ".mew-alias") + +(defvar mew-refile-msgid-file ".mew-refile-msgid-alist") + +(defvar mew-refile-from-file ".mew-refile-from-alist") + +(defvar mew-smtp-log-file "Smtplog") +(defvar mew-nntp-log-file "Nntplog") +(defvar mew-refile-log-file "Refilelog") + +;; xxx Home + +(defvar mew-fib-item-file "~/.mew-fib") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Modes +;;; + +(defvar mew-folder-mode 448 ;; decimal for octal 0700 + "Secure file mode for folders. 448(0700 in octal) is STRONGLY +recommended for privacy reasons.") + +(defvar mew-file-mode-mask 432 ;; decimal for octal 0660 + "Secure file mode mask. 432(0660 in octal) is STRONGLY recommended +for privacy reasons.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Separators +;;; + +(defvar mew-path-separator "/") +(defvar mew-regex-drive-letter (file-name-as-directory "^[a-zA-Z]:")) +(defvar mew-regex-file-absolute (format "^[~%s]" mew-path-separator)) +(defvar mew-header-separator "----") +(defvar mew-eoh nil) ;; set by mew-regex-setup +(defvar mew-lwsp "^[ \t]") +(defvar mew-lwsp+ "^[ \t]+") +(defvar mew-address-separator ":, \t\n") +(defvar mew-page-delimiter "^\^L") +(defvar mew-keyval "^\\([^ \t:]+:?\\)[ \t]*") +;; "^\\([^ \t:]+:?\\)[ \t]*\\(.*\\)$" faces a stupid error. +;; "$" does not mean end-of-line if the second match is empty, sigh. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Explanation string in messages +;;; + +(defvar mew-bcc-subject "A blind carbon copy") +(defvar mew-bcc-body "This is a blind carbon copy.\n") + +(defvar mew-field-comment "(modified by Mew)") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Addrbook +;;; + +(defvar mew-addrbook-switch + '((shortname mew-addrbook-shortname-get) + (address identity) + (username mew-addrstr-extract-user) + (nickname mew-addrbook-nickname-get) + (name mew-addrbook-name-get)) + "Function database to get each field of Addrbook. +'shortname, 'address, 'username, 'nickname, and 'name is defined.") + +(defun mew-addrbook-func (key) + (mew-alist-get-value (assq key mew-addrbook-switch))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; MIME types +;;; + +(defun mew-ct-textp (ct) + (string-match "^Text" (capitalize ct))) + +(defun mew-ct-imagep (ct) + (string-match "^Image" (capitalize ct))) + +(defun mew-ct-modelp (ct) + (string-match "^Model" (capitalize ct))) + +(defun mew-ct-multipartp (ct) + (string-match "^Multipart" (capitalize ct))) + +(defun mew-ct-alternativep (ct) + (string-match "^Multipart/Alternative" (capitalize ct))) + +(defun mew-ct-partialp (ct) + (string-match "^Message/Partial" (capitalize ct))) + +(defun mew-ct-messagep (ct) + (string-match "^Message" (capitalize ct))) + +(defun mew-ct-linebasep (ct) + (or (mew-ct-textp ct) + (mew-case-equal ct mew-ct-aps) + (mew-case-equal ct mew-ct-msg))) ;; xxx mew-ct-messagep? + +(defvar mew-mime-content-type-multipart-list + `(,mew-ct-mlm ,mew-ct-mla) + "Candidate of 'Content-Type: Multipart/' when CT: is changed +in draft buffer.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Completion +;;; + +(defconst mew-custom-type-of-field-completion + '(list (list string function))) + +(defcustom mew-field-completion-switch + '(("To:" mew-complete-address) + ("Cc:" mew-complete-address) + ("Dcc:" mew-complete-address) + ("Bcc:" mew-complete-address) + ("Reply-To:" mew-complete-address) + ("Fcc:" mew-complete-fcc-folder) + ("Resent-To:" mew-complete-address) + ("Resent-Cc:" mew-complete-address) + ("Resent-Dcc:" mew-complete-address) + ("Resent-Bcc:" mew-complete-address) + ("Resent-Fcc:" mew-complete-fcc-folder) + ("Newsgroups:" mew-complete-newsgroups) + ("Followup-To:" mew-complete-newsgroups)) + "*Completion function alist concerned with the key." + :group 'mew-complete + :type mew-custom-type-of-field-completion) + +(defcustom mew-field-circular-completion-switch + '(("To:" mew-circular-complete-domain) + ("Cc:" mew-circular-complete-domain) + ("Dcc:" mew-circular-complete-domain) + ("Bcc:" mew-circular-complete-domain) + ("Reply-To:" mew-circular-complete-domain) + ("Resent-To:" mew-circular-complete-domain) + ("Resent-Cc:" mew-circular-complete-domain) + ("Resent-Dcc:" mew-circular-complete-domain) + ("Resent-Bcc:" mew-circular-complete-domain) + ("From:" mew-circular-complete-from) + ("Resent-From:" mew-circular-complete-from)) + "*Circular completion function alist concerned with the key." + :group 'mew-complete + :type mew-custom-type-of-field-completion) + +(defcustom mew-field-expansion-switch + '(("To:" mew-expand-address) + ("Cc:" mew-expand-address) + ("Dcc:" mew-expand-address) + ("Bcc:" mew-expand-address) + ("Reply-To:" mew-expand-address) + ("Resent-To:" mew-expand-address) + ("Resent-Cc:" mew-expand-address) + ("Resent-Dcc:" mew-expand-address) + ("Resent-Bcc:" mew-expand-address)) + "*Expansion function alist concerned with the key." + :group 'mew-complete + :type mew-custom-type-of-field-completion) + +(defun mew-field-get-func (key switch) + (mew-alist-get-value (mew-assoc-match key switch 0))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; MIME control +;;; + +(defvar mew-content-type mew-ct-txt + "*The default Content-Type: for a file whose suffix is unknown.") + +(defvar mew-mime-content-type nil + "\\Database for MIME content type. +This is a list of entries which consist of , +, , +, , . + +Here is an example: + + (\"image/png\" \"\\\\.png$\" mew-b64 mew-prog-image mew-icon-image png) + +This database is used both when visualizing and composing. For +example, when visualizing, a visualizer is chosen according to +its . When composing, content-type is selected +according to the suffix of the file to be attached with . + +For , 'nil', 'mew-b64', or 'mew-qp' +should be specified. 'mew-b64' and 'mew-qp' means Base64 and +Quoted-Printable, respectively. This is used as an appropriate +content-transfer-encoding when composing. + +Each symbol specified at should have a value +whose format is one of followings: + +- \"prog\" + \"prog\" is an external program. + (1) The program name is displayed. + (2) \"prog\" is executed asynchronously. +- func + is a function. + (1) is called. + (2) is called. +- (\"prog\" args async) + \"prog\" is an external program. + is a list of arguments for the external program. + + If nil, the external program is called synchronously. + If t, the external program is called asynchronously. + (1) The program name is displayed. + (2) \"prog\" is executed asynchronously with . +- (nil \"prog\") + Equivalent to \"prog\". +- (nil (\"prog\" args async)) + Equivalent to (\"prog\" args async). +- (nil func2) + (1) Displayed 'type \\[mew-summary-execute-external]'. + (2) is called. +- (func1 func2) + (1) is called. + (2) is called. + If the original content-type is Application/Octet-Stream, + you are asked to choose or . +- (func1 \"prog\") + (1) is called. + (2) \"prog\" is executed asynchronously. + If the original content-type is Application/Octet-Stream, + you are asked to choose or \"prog\". +- (func1 (\"prog\" args async)) + (1) is called. + (2) \"prog\" is executed asynchronously with . + If the original content-type is Application/Octet-Stream, + you are asked to choose or \"prog\". + +Note that (1) indicates the action for '\\[mew-summary-display]' and +\(2) indicates the action for '\\[mew-summary-execute-external]'. + +If you want to add an entry for new content-type, please let the author +know. Such an entry should be shared by all users and be included in +the next version of Mew.") + +(defun mew-ctdb-by-ct (ct) + (mew-assoc-match2 ct mew-mime-content-type 0)) + +(defun mew-ctdb-by-file (file) + (mew-assoc-match2 file mew-mime-content-type 1)) + +(defun mew-ctdb-ct (attr) + (and (nth 0 attr) (mew-capitalize (nth 0 attr)))) + +(defun mew-ctdb-regex (attr) + (nth 1 attr)) + +(defun mew-ctdb-cte (attr) + (symbol-value (nth 2 attr))) + +(defun mew-ctdb-prog (attr) + (let ((val (symbol-value (nth 3 attr)))) + (if (and (listp val) (eq 'if (car val))) + (eval val) + val))) + +(defun mew-ctdb-icon (attr) + (symbol-value (nth 4 attr))) + +(defun mew-mime-image-format-name (ct) + (nth 5 (mew-ctdb-by-ct ct))) + +(defvar mew-mime-content-type-for-ooffice nil + "A list of (content-type suffix) for OpenOffice.org to be prepended +'mew-mime-content-type'") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; MIME Content-Disposition: +;;; + +(defvar mew-mime-content-disposition + '(("text" "inline" t) + ("image" "inline" t) + ("message" "inline" nil) + ("multipart" nil nil) + (t "attachment" t)) + "(content-type inline/attachment filename)") + +(defun mew-cdpdb-by-ct (ct) + (mew-assoc-match2 ct mew-mime-content-disposition 0)) + +(defun mew-cdpdb-val (attr) + (nth 1 attr)) + +(defun mew-cdpdb-file (attr) + (nth 2 attr)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Privacy +;;; + +(defcustom mew-privacy-database + `((pgp-signature ((,mew-ct-mls ,mew-ct-pgs)) "PS") + (pgp-encryption ((,mew-ct-mle ,mew-ct-pge)) "PE") + (pgp-signature-encryption + ((,mew-ct-mls ,mew-ct-pgs) (,mew-ct-mle ,mew-ct-pge)) "PSPE") + (pgp-encryption-signature + ((,mew-ct-mle ,mew-ct-pge) (,mew-ct-mls ,mew-ct-pgs)) "PEPS") + (smime-signature ((,mew-ct-smm ,mew-ct-smm-sig)) "SS") + (smime-encryption ((,mew-ct-smm ,mew-ct-smm-enc)) "SE") + (smime-signature-encryption + ((,mew-ct-smm ,mew-ct-smm-sig) (,mew-ct-smm ,mew-ct-smm-enc)) "SSSE") + (smime-encryption-signature + ((,mew-ct-smm ,mew-ct-smm-enc) (,mew-ct-smm ,mew-ct-smm-sig)) "SESS")) + "*Alist of key, a list of privacy Content-Type, and its mark." + :group 'mew-privacy + :type 'sexp) + +(defun mew-pcdb-services () + (mapcar 'car mew-privacy-database)) + +(defun mew-pcdb-by-service (service) + (assq service mew-privacy-database)) + +(defun mew-pcdb-ct (pcdb) + (nth 1 pcdb)) + +(defun mew-pcdb-mark (pcdb) + (nth 2 pcdb)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Multipart/Alternative +;;; + +(defvar mew-mime-multipart-alternative-list + `(,mew-ct-txt ".*")) + +(defun mew-multipart-alternative-preference (part) + (let ((ct (mew-syntax-get-value (mew-syntax-get-ct part) 'cap))) + (mew-member-match ct mew-mime-multipart-alternative-list))) + +(defvar mew-mime-external-body-list + '("anon-ftp" "url" "mail-server")) + +(defun mew-mime-external-body-preference (part) + (let* ((ctl (mew-syntax-get-ct part)) + (ct (mew-syntax-get-value ctl 'cap)) + (access-type (mew-syntax-get-param ctl "access-type"))) + (if (and (string= ct mew-ct-ext) (stringp access-type)) + (mew-member-match access-type mew-mime-external-body-list)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Field database +;;; + +;; strictly, content-* are necessary but they are not practical. +(defvar mew-field-database + `((,mew-to: mailbox struct) + (,mew-cc: mailbox struct) + (,mew-from: mailbox struct) + (,mew-apparently-to: mailbox struct) + (,mew-bcc: mailbox struct) + (,mew-dcc: mailbox struct) + (,mew-reply-to: mailbox struct) + (,mew-resent-to: mailbox struct) + (,mew-resent-cc: mailbox struct) + (,mew-resent-from: mailbox struct) + (,mew-mv: mime struct) + (,mew-subj: text text) + (,mew-keywords: comma-text text) + (,mew-received: unstruct unstruct) + (,mew-message-id: unstruct unstruct) + (,mew-references: unstruct unstruct) + (,mew-in-reply-to: unstruct unstruct) + (,mew-x-face: unstruct unstruct) + (,mew-face: unstruct unstruct) + ("Authentication-Results:" unstruct struct2) ;; capitalized + ("Domainkey-Signature:" unstruct unstruct) ;; capitalized + ("Dkim-Signature:" unstruct unstruct)) ;; capitalized + "(field enc dec)") + +(defun mew-field-type-for-encoding (key) + (or (nth 1 (assoc (mew-capitalize key) mew-field-database)) 'unstruct)) + +(defun mew-field-type-for-decoding (key) + (or (nth 2 (assoc (mew-capitalize key) mew-field-database)) 'text)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Theme +;;; + +(defvar mew-theme-file nil + "The file name which contains theme.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Highlight header +;;; + +(defcustom mew-field-spec + '(("^Resent-\\(Sender\\|From\\|To\\|Cc\\|Date\\)" t + mew-face-header-important + mew-face-header-important) + ("^Subject:$" t + mew-face-header-important + mew-face-header-subject) + ("^From:$" t + mew-face-header-important + mew-face-header-from) + ("^\\(To\\|Apparently-To\\):$" t + mew-face-header-important + mew-face-header-to) + ("^\\(Cc\\|Dcc\\|Bcc\\):$" t + mew-face-header-important + mew-face-header-to) + ("^Newsgroups:$" t + mew-face-header-important + mew-face-header-to) + ("^Date:$" t + mew-face-header-important + mew-face-header-date) + ("^Sender:$" t) + ("^Reply-To:$" t) + ("^\\(X-Mailer\\|User-Agent\\):$" t) + ("^X-Mew:$" t + mew-face-header-important + mew-face-header-xmew) + ("^\\(Received\\|Return-Path\\|Errors-To\\):$" nil) + ("^\\(Path\\|Distribution\\|Xref\\):$" nil) + ("^NNTP-Posting-" nil) + ("^\\(Message-Id\\|Posted\\|In-Reply-To\\|References\\|Precedence\\):$" nil) + ("^DomainKey-Signature:$" nil) + ("^DKIM-Signature:$" nil) + ("^Authentication-Results:$" + mew-authentication-results + mew-face-header-important + mew-face-header-xmew + ("hardfail" mew-face-header-xmew-bad + "fail" mew-face-header-xmew-bad + "softfail" mew-face-header-xmew-bad)) + ("^Delivered-" nil) + ("^List-" nil) ;; RFC 2369 +;; ("^Content-" t) + ("^\\(Mime-Version\\|Lines\\):$" nil) + ("^From$" nil) + ("^Status:$" nil) + ("^Face:$" nil + mew-face-header-private + mew-face-header-marginal) + ("^\\(X\\|Original\\)-" nil + mew-face-header-private + mew-face-header-marginal)) + "*An alist of field spec for Message mode. Each spec +consists of field-regular-expression, visible-p, face-for-key, +and face-for-value. Fields whose visible-p is t are displayed in +Message mode in the defined order. Fields whose visible-p is nil are +hidden in Message mode. Type DEL to see them. Fields not matched +to field-regular-expressions are operated by the value of +'mew-field-other-visible'. If face-for-key is omitted, +'mew-face-header-key' is used. If face-for-value is not +present, mew-face-header-marginal is used." + :group 'mew-highlight + :type '(alist :key-type regexp + :value-type + (choice (list boolean) + (list boolean face face)))) + +;; cons the position to the spec. +(defun mew-nspec-by-key (key) + (mew-assoc-match3 key mew-field-spec 0)) + +(defun mew-nspec-n (nspec) + (nth 0 nspec)) + +(defun mew-nspec-visiblep (nspec) + (nth 2 nspec)) + +(defun mew-nspec-keyface (nspec) + (nth 3 nspec)) + +(defun mew-nspec-valface (nspec) + (nth 4 nspec)) + +(defun mew-nspec-extraface (nspec) + (nth 5 nspec)) + +(defun mew-authentication-results (val) + (save-match-data + (or (string-match "=hardfail" val) + (string-match "=fail" val) + (string-match "=softfail" val)))) + +(mew-defstruct header-color field key val) +(defvar mew-header-color-alist nil) + +;; See also mew-face-make-spec. + +(defun mew-header-color-base (field key-color val-color bold) + (unless val-color (setq val-color key-color)) + (let ((face-key (intern (concat "mew-face-color-" key-color (if bold "-bold")))) + (face-val (intern (concat "mew-face-color-" val-color (if bold "-bold"))))) + (unless (facep face-key) + (make-empty-face face-key) + (face-spec-set face-key (list (mew-face-spec-func t (mew-face-spec-primitive key-color bold))))) + (unless (facep face-val) + (make-empty-face face-val) + (face-spec-set face-val (list (mew-face-spec-func t (mew-face-spec-primitive val-color bold))))) + (setq mew-header-color-alist + (cons (list (capitalize field) face-key face-val) mew-header-color-alist)))) + +(defun mew-header-color (field key-color &optional val-color) + "Set the color of FIELD key to KEY-COLOR. +And set the color of FIELD value to VAL-COLOR. +If VAL-COLOR is omitted, set the color of FIELD value to KEY-COLOR." + (mew-header-color-base field key-color val-color nil)) + +(defun mew-header-color-bold (field key-color &optional val-color) + "Set the color of FIELD key to KEY-COLOR. +And set the color of FIELD value to VAL-COLOR. +If VAL-COLOR is omitted, set the color of FIELD value to KEY-COLOR. +The style becomes bold." + (mew-header-color-base field key-color val-color t)) + +(defun mew-key-face (key nspec) + (or (mew-header-color-get-key (assoc key mew-header-color-alist)) + (mew-nspec-keyface nspec) + 'mew-face-header-key)) + +(defun mew-val-face (key nspec) + (or (mew-header-color-get-val (assoc key mew-header-color-alist)) + (mew-nspec-valface nspec) + 'mew-face-header-marginal)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Highlight body +;;; + +(defvar mew-highlight-body-regex-comment "^#+.*") + +(defvar mew-highlight-body-regex-cite + "^\\(\\([ \t]\\{,7\\}\\([>:|]\\|\\w+\\([._-]+\\w+\\)*>+\\)\\)+\\).*") + +(defcustom mew-highlight-body-prefix-width 20 + "*Maximum string width assume prefix for fancy highlight a body." + :group 'mew-highlight + :type 'integer) + +(defvar mew-highlight-body-cite-faces + '(mew-face-body-cite1 + mew-face-body-cite2 + mew-face-body-cite3 + mew-face-body-cite4 + mew-face-body-cite5)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Highlight mark +;;; + +(defvar mew-highlight-mark-keywords + `((,mew-mark-review mew-face-mark-review) + (,mew-mark-escape mew-face-mark-escape) + (,mew-mark-delete mew-face-mark-delete) + (,mew-mark-unlink mew-face-mark-unlink) + (,mew-mark-refile mew-face-mark-refile) + (,mew-mark-unread mew-face-mark-unread)) + "A list of mark-face pair to used in Summary/Virtual mode.") + +(defun mew-highlight-mark-get-face (mark) + (mew-alist-get-value (assoc mark mew-highlight-mark-keywords))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mark spec +;;; + +(defvar mew-mark-afterstep-spec + `((,mew-mark-review 0 0 0 0 0 0 0) + (,mew-mark-escape 0 0 0 0 0 0 0) + (,mew-mark-read 0 0 0 0 0 0 0) + (,mew-mark-delete 2 0 2 0 0 0 0) + (,mew-mark-unlink 2 0 2 0 0 0 0) + (,mew-mark-refile 2 0 2 0 0 0 0)) + "*A list of cursor action spec. +The cursor action spec is a list of a mark and seven cursor +actions after marking. + +0th (the first element of a list) is a mark value. A mark value is +ASCII code of the mark. For example, the value of the '*' mark +\(mew-mark-review) is 42. + +Seven values following a mark value means as follows: + +1st is the case of no mark. +2nd is the case where the new mark is equal to the old one. +3rd is the case where level of the new mark is greater than that of the + old one. +4th, 5th, and 6th is the case where levels are equal. + 4th and 5th is the case that the old mark has state. + 4th means that the old mark is overrode. + 5th means that the old mark remains. + 6th is the case that the old mark does not have state. +7th is the case where level of the new mark is smaller than that of the + old one. + +The value of cursor actions means as follows: + + 0 means staying. + 1 means moving according to the direction, + 2 means moving according to the direction + then displaying the next message. + +For more detail, see mew-mark-put-mark and mew-mark-afterstep.") + +(defun mew-markas-nth (mark case) + (nth case (assoc mark mew-mark-afterstep-spec))) + +(defvar mew-mark-spec + `((,mew-mark-read "read" 0 nil nil nil nil nil) + (,mew-mark-unread "unread" 0 nil nil nil nil nil) + (,mew-mark-review "review" 1 nil nil nil nil nil) + (,mew-mark-escape "escape" 1 nil nil nil nil nil) + (,mew-mark-delete "delete" 2 nil t nil mew-mark-exec-delete nil) + (,mew-mark-unlink "unlink" 2 nil t nil mew-mark-exec-unlink nil) + (,mew-mark-refile "refile" 2 t mew-mark-kill-refile mew-mark-unrefile + mew-mark-exec-refile mew-mark-sanity-refile)) + "*A list of lists which consists of +mark, name, level, statefullp, kill-line-p, +undo-func, exec-func, and sanity-fucn.") + +;; + +(defun mew-mark-get-all-marks () + "Collecting all defined marks." + (mapcar 'car mew-mark-spec)) + +(defun mew-markdb-by-mark (mark) + (assoc mark mew-mark-spec)) + +(defun mew-markdb-name (mark) + (nth 1 (mew-markdb-by-mark mark))) + +(defun mew-markdb-level (mark) + (nth 2 (mew-markdb-by-mark mark))) + +(defun mew-markdb-statefullp (mark) + (nth 3 (mew-markdb-by-mark mark))) + +(defun mew-markdb-killp (mark) + (nth 4 (mew-markdb-by-mark mark))) + +(defun mew-markdb-func-undo (mark) + (nth 5 (mew-markdb-by-mark mark))) + +(defun mew-markdb-func-exec (mark) + (nth 6 (mew-markdb-by-mark mark))) + +(defun mew-markdb-func-sanity (mark) + (nth 7 (mew-markdb-by-mark mark))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Inbox action +;;; + +(defvar mew-inbox-action-alist nil + "*This variable controls actions when retrieving messages. +Currently this works when '\\\\[mew-summary-retrieve]'. +You can put any marks, typically 'o' and 'D' according to message +headers. + +This value must be a list of entries. An entry is a list whose first +element is a field defined in 'mew-scan-fields'. + +If the second element is a list, the first element of the list must be +a mark (e.g. ?D) or a string which is a comma separated folders (e.g +\"+foo,+bar\" for ?o). Other elements of the list are regular +expressions to be matched to the value of the field. + +With the following configuration, Mew marks messages whose Subject: +matches \"adult\" or \"money\" with 'D'. And Mew marks messages whose +Subject is \"daily log\" with 'o' to be refiled \"+log\". Also Mew +marks messages whose Content-Type: contains \"gb2312\" with 'D'. + +\(setq mew-inbox-action-alist + '((\"Subject:\" + (?D \"adult\" \"money\") + (\"+log\" \"daily log\")) + (\"Content-Type:\" + (?D \"gb2312\")))) + +If the second element of the entry is a symbol, it will be called as a +function which returns nil or a mark or a string. + +If you are using 'spamassassin' which adds the \"X-Spam-Flag:\" field +to messages and puts them in your mailbox, configure as follows: + +\(setq mew-spam: \"X-Spam-Flag:\") + +\(defun mew-spam-assassin (val) + (let ((case-fold-search t)) + (if (string-match \"yes\" val) ?D))) + +\(setq mew-inbox-action-alist + '((\"X-Spam-Flag:\" mew-spam-assassin))) + +With this configuration, messages with the \"X-Spam-Flag:\" whose +value is \"Yes\" are automatically marked with 'D' since the +'mew-spam-assassin' function returns 'D' marks when the value is +\"Yes\". + +If you are using 'bogofilter' which adds the \"X-Bogosity:\" field +to messages and puts them to your mailbox, configure as follows: + +\(setq mew-spam: \"X-Bogosity:\") + +\(defun mew-spam-bogofilter (val) + (let ((case-fold-search t)) + (if (string-match \"yes\" val) ?D))) + +\(setq mew-inbox-action-alist + '((\"X-Bogosity:\" mew-spam-bogofilter))) +") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Proto +;;; + +(defvar mew-proto mew-folder-local) + +(defvar mew-proto-spec + ;; key go refile flush + '(("+" "+" "+" "+") + ("$" "+" nil "+") + ("%" "%" "%" "+") + ("*" nil nil nil) + ("-" "-" nil "-"))) + +(defun mew-proto-to-body (fld n) + (if (mew-folder-virtualp fld) + (setq fld (mew-folder-basename fld))) + (setq fld (mew-case:folder-folder fld)) + (let ((proto (mew-folder-prefix fld))) + (unless (member proto mew-folder-prefixes) + (setq proto (mew-proto))) ;; default proto + (nth n (assoc proto mew-proto-spec)))) + +(defun mew-proto-to-go (fld) + (mew-proto-to-body fld 1)) + +(defun mew-proto-to-refile (fld) + (mew-proto-to-body fld 2)) + +(defun mew-proto-to-flush (fld) + (mew-proto-to-body fld 3)) + +(defun mew-proto-inbox-folder (proto &optional case) + (or proto (setq proto (mew-proto case))) + (cond + ((mew-folder-popp proto) mew-pop-inbox-folder) + ((mew-folder-imapp proto) (mew-imap-inbox-folder case)) + ((mew-folder-nntpp proto) (mew-nntp-newsgroup case)) + (t ;; local + (mew-inbox-folder case)))) + +(defun mew-proto-queue-folder (proto &optional case) + (or proto (setq proto (mew-proto case))) + (cond + ((mew-folder-nntpp proto) (mew-postq-folder case)) + (t (mew-queue-folder case)))) + +(defun mew-proto-friend-folder (proto &optional case) + (cond + ((mew-folder-imapp proto) (mew-imap-friend-folder case)) + (t ;; local + mew-friend-folder))) + +(defun mew-proto-friend-folder-list (proto &optional case) + (cond + ((mew-folder-imapp proto) (mew-imap-friend-folder-list case)) + (t ;; local + (mew-local-friend-folder-list)))) + +(defun mew-proto-folder-alist (proto &optional case) + (cond + ((mew-folder-popp proto) (mew-pop-folder-alist)) + ((mew-folder-imapp proto) (mew-imap-folder-alist case)) + ((mew-folder-nntpp proto) (mew-nntp-folder-alist case)) + (t ;; local + (mew-local-folder-alist)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Config +;;; + +(defcustom mew-config-alist nil + "*Alist of config. This is a list of + ( ( ) ( ) ...). + - is a string of case. + - is a symbol of Mew value with the 'mew-' prefix removed. + - is a string. + +Currently, the following keys are supported: +name, user, mail-domain, +cc, fcc, dcc, reply-to, organization, header-alist, proto, +smtp-server, smtp-port, smtp-ssh-server, smtp-ssl, smtp-ssl-port, +smtp-user, smtp-auth-list, +smtp-msgid-user, smtp-msgid-domain, smtp-helo-domain, smtp-mail-from, +pop-server, pop-port, pop-ssh-server, pop-ssl, pop-ssl-port, +pop-user, pop-auth, pop-auth-list, +pop-size, pop-header-only, pop-delete, pop-body-lines, +pop-proxy-server, pop-proxy-port, +imap-server, imap-port, imap-ssh-server, imap-ssl, imap-ssl-port, +imap-user, imap-auth, imap-auth-list, +imap-size, imap-header-only, imap-delete, +imap-trash-folder, imap-queue-folder, imap-spam-field, imap-spam-word, +imap-proxy-server, imap-proxy-port, +nntp-server, nntp-port, nntp-ssh-server, nntp-ssl, nntp-ssl-port, +nntp-user, nntp-size, nntp-header-only, +nntp-msgid-user, nntp-msgid-domain, +ssl-cert-directory, ssl-verify-level, +inbox-folder, queue-folder, postq-folder, +mailbox-type, mbox-command, mbox-command-arg, +signature-file, content-type, refile-guess-alist, +spam-prog, spam-prog-args, ham-prog, ham-prog-args, +use-old-pgp, pgp-signer, smime-signer, privacy-method, +protect-privacy-always, protect-privacy-always-type, +protect-privacy-encrypted, protect-privacy-encrypted-type, +protect-privacy-with-old-pgp-signature + +from = name +message-id = *random*.smtp-msgid-user@smtp-msgid-domain +message-id = *random*.nntp-msgid-user@nntp-msgid-domain + +An example is as follows: + +\(setq mew-config-alist + '((mew + (mail-domain \"example.org\") + (inbox-folder \"+inbox-mew\")) + (keio + (cc \"kazu@example.jp\") + (user \"pooh\") + (mail-domain \"example.net\")) + (default + (name \"Kazu Yamamoto\") + (mail-domain \"example.jp\")))) +" +;; bcc can be used but not recommended + :group 'mew-env + :type '(alist :key-type string + :value-type (repeat (cons string string)))) + +(defun mew-cfent-by-case (case) + (if (null case) + (or (assoc mew-case-default mew-config-alist) + (assoc (intern mew-case-default) mew-config-alist)) + (or (assoc case mew-config-alist) + (assoc (intern case) mew-config-alist)))) + +(provide 'mew-vars2) + +;;; Copyright Notice: + +;; Copyright (C) 2000-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-vars2.el ends here diff --git a/elpa/mew-20150813.2354/mew-vars3.el b/elpa/mew-20150813.2354/mew-vars3.el new file mode 100644 index 00000000..a35ec18d --- /dev/null +++ b/elpa/mew-20150813.2354/mew-vars3.el @@ -0,0 +1,225 @@ +;;; mew-vars3.el + +;; Author: Kazu Yamamoto +;; Created: May 10, 2006 + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Macro +;;; + +(defvar mew-face-spec-alist + '((:tty (type tty)) + (:light (background light)) + (:dark (background dark)))) + +;; See also mew-header-color-base + +(defun mew-face-make-spec (bold &rest spec) + (let (ret key col) + (if (and bold (not (member :tty spec))) + (setq ret (cons (mew-face-spec-func '((class color) (type tty)) + (mew-face-spec-primitive nil t)) + ret))) + (while spec + (setq key (car spec)) + (setq spec (cdr spec)) + (setq col (car spec)) + (setq spec (cdr spec)) + (setq ret (cons + (mew-face-spec-func + (list '(class color) + (mew-alist-get-value (assoc key mew-face-spec-alist))) + (mew-face-spec-primitive col bold)) + ret))) + (setq ret (cons (mew-face-spec-func t (mew-face-spec-primitive nil bold)) + ret)) + (nreverse ret))) + +(defmacro mew-setface (sym &rest spec) + ;; (declare (indent 1)) + `(face-spec-set + ',(intern (concat "mew-face-" (symbol-name sym))) + ',(apply 'mew-face-make-spec nil spec))) +(put 'mew-setface 'lisp-indent-function 1) + +(defmacro mew-setface-bold (sym &rest spec) + ;; (declare (indent 1)) + `(face-spec-set + ',(intern (concat "mew-face-" (symbol-name sym))) + ',(apply 'mew-face-make-spec 'bold spec))) +(put 'mew-setface-bold 'lisp-indent-function 1) + +(defmacro mew-defface (sym doc &rest spec) + ;; (declare (indent 1)) + `(defface ,(intern (concat "mew-face-" (symbol-name sym))) + ',(apply 'mew-face-make-spec nil spec) + ,(concat "*" doc) + :group 'mew-highlight)) +(put 'mew-defface 'lisp-indent-function 1) + +(defmacro mew-defface-bold (sym doc &rest spec) + ;; (declare (indent 1)) + `(defface ,(intern (concat "mew-face-" (symbol-name sym))) + ',(apply 'mew-face-make-spec 'bold spec) + ,(concat "*" doc) + :group 'mew-highlight)) +(put 'mew-defface-bold 'lisp-indent-function 1) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Highlight header +;;; + +(mew-defface-bold header-subject + "Face to highlight the value of Subject:" + :tty "red" :light "Firebrick" :dark "OrangeRed") + +(mew-defface-bold header-from + "Face to highlight the value of From:" + :tty "yellow" :light "DarkOrange4" :dark "Gold") + +(mew-defface-bold header-date + "Face to highlight the value of Date:" + :tty "green" :light "ForestGreen" :dark "LimeGreen") + +(mew-defface-bold header-to + "Face to highlight the value of To:" + :tty "magenta" :light "DarkViolet" :dark "violet") + +(mew-defface-bold header-key + "Face to highlight by default" + :tty "green" :light "ForestGreen" :dark "LimeGreen") + +(mew-defface-bold header-private + "Face to highlight private field-keys") + +(mew-defface-bold header-important + "Face to highlight important field-keys" + :tty "cyan" :light "MediumBlue" :dark "SkyBlue") + +(mew-defface-bold header-marginal + "Face to highlight marginal field-values" + :light "gray50" :dark "gray50") + +(mew-defface-bold header-warning + "Face to highlight non-my-domain addresses on To:/Cc:/Bcc:" + :tty "red" :light "red" :dark "red") + +(mew-defface-bold header-xmew + "Face to highlight the value of X-Mew:" + :tty "yellow" :light "chocolate" :dark"chocolate") + +(mew-defface-bold header-xmew-bad + "Face to highlight the value of X-Mew: in bad cases" + :tty "red" :light "red" :dark "red") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Highlight body +;;; + +(mew-defface body-url + "Face to highlight URL in Message/Draft mode" + :tty "red" :light "Firebrick" :dark "OrangeRed") + +(mew-defface body-comment + "Face to highlight comments in a body" + :tty "blue" :light "gray50" :dark "gray50") + +(mew-defface body-cite1 + "Face to highlight the first citation" + :tty "green" :light "ForestGreen" :dark "LimeGreen") + +(mew-defface body-cite2 + "Face to highlight the second citation" + :tty "cyan" :light "MediumBlue" :dark "SkyBlue") + +(mew-defface body-cite3 + "Face to highlight the third citation" + :tty "magenta" :light "DarkViolet" :dark "violet") + +(mew-defface body-cite4 + "Face to highlight the forth citation" + :tty "yellow" :light "DarkOrange4" :dark "Gold") + +(mew-defface body-cite5 + "Face to highlight the fifth citation" + :tty "red" :light "Firebrick" :dark "OrangeRed") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Highlight mark +;;; + +(mew-defface mark-review + "Face to highlight the review mark" + :tty "cyan" :light "MediumBlue" :dark "SkyBlue") + +(mew-defface mark-escape + "Face to highlight the escape mark" + :tty "magenta" :light "DarkViolet" :dark "violet") + +(mew-defface mark-delete + "Face to highlight the delete mark" + :tty "red" :light "Firebrick" :dark "OrangeRed") + +(mew-defface mark-unlink + "Face to highlight the unlink mark" + :tty "yellow" :light "DarkOrange4" :dark "Gold") + +(mew-defface mark-refile + "Face to highlight the refile mark" + :tty "green" :light "ForestGreen" :dark "LimeGreen") + +(mew-defface mark-unread + "Face to highlight the unread mark") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Highlight eof +;;; + +(mew-defface-bold eof-message + "Face to highlight the 'end of message' string" + :tty "green" :light "ForestGreen" :dark "LimeGreen") + +(mew-defface-bold eof-part + "Face to highlight the 'end of part' string" + :tty "yellow" :light "DarkOrange4" :dark "Gold") + +(provide 'mew-vars3) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-vars.el ends here diff --git a/elpa/mew-20150813.2354/mew-varsx.el b/elpa/mew-20150813.2354/mew-varsx.el new file mode 100644 index 00000000..49f000c1 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-varsx.el @@ -0,0 +1,268 @@ +;;; mew-varsx.el --- Variables depends on other variables + +;; Author: Kazu Yamamoto +;; Created: May 10, 2006 + +;;; Code: + +(defun mew-defvar (sym val) + (unless (symbol-value sym) + (set sym val))) + +;; +;; Scan +;; + +(mew-defvar + 'mew-basic-folders + (list mew-inbox-folder mew-draft-folder mew-queue-folder mew-postq-folder)) + +(mew-defvar + 'mew-scan-fields + (list "Folder:" "Filename:" + mew-subj: mew-date: mew-from: mew-to: mew-cc: + mew-ct: mew-cte: mew-x-mew-uidl: + mew-message-id: mew-in-reply-to: mew-references: mew-x-mew-ref: + mew-spam: "Body")) + +(mew-defvar + 'mew-scan-fields-alias + '("FLD" "NUM" "SUBJ" "DATE" "FROM" "TO" "CC" + "CT" "CTE" "UID" + "ID" "IRT" "REF" "XREF" + "SPAM" "BODY")) + +;; +;; Office +;; + +;; strict valid +(mew-defvar + 'mew-regex-message-files + (format "^[1-9][0-9]*\\(%s\\)?$" (regexp-quote mew-suffix))) + +;; strict invalid +(mew-defvar + 'mew-regex-message-files4 + (format "^0[1-9][0-9]*\\(%s\\)?$" (regexp-quote mew-suffix))) + +;; strict all +(mew-defvar + 'mew-regex-message-files3 + (format "^\\([0-9]+\\)\\(%s\\)?$" (regexp-quote mew-suffix))) + +;; mewl and grep +(mew-defvar + 'mew-regex-message-files2 + (format "^\\([0-9]+\\)\\(%s\\)?" (regexp-quote mew-suffix))) + +;; search +(mew-defvar + 'mew-regex-message-files5 + (format "\\([0-9]+\\)\\(%s\\)?$" (regexp-quote mew-suffix))) + +;; +;; MIME +;; + + +(mew-defvar + 'mew-mime-content-type + `(("multipart" nil nil nil mew-icon-multipart) + ;; + ("audio/basic" "\\.au$" mew-b64 mew-prog-audio mew-icon-audio) + ("audio/x-wav" "\\.wav$" mew-b64 mew-prog-audio mew-icon-audio) + ("audio/x-aiff" "\\.aif?f$" mew-b64 mew-prog-audio mew-icon-audio) + ("audio/x-midi" "\\.midi?$" mew-b64 mew-prog-audio mew-icon-audio) + ("audio/x-mpeg" "\\.mpga$\\|\\.mp[23]$" mew-b64 mew-prog-audio mew-icon-audio) + ;; + ("image/gif" "\\.gif$" mew-b64 mew-prog-image mew-icon-image gif) + ("image/tiff" "\\.tif?f$" mew-b64 mew-prog-image mew-icon-image tiff) + ("image/jpeg" "\\.jpe?g$" mew-b64 mew-prog-image mew-icon-image jpeg) + ("image/pjpeg" "\\.jfif$" mew-b64 mew-prog-image mew-icon-image jpeg) ;; MS + ("image/jpg" "^$" mew-b64 mew-prog-image mew-icon-image jpeg) ;; unofficial + ("image/png" "\\.png$" mew-b64 mew-prog-image mew-icon-image png) + ("image/x-xwd" "\\.xwd$" mew-b64 mew-prog-image mew-icon-image xwd) + ("image/x-xbm" "\\.xbm$" mew-b64 mew-prog-image mew-icon-image xbm) + ("image/x-xpm" "\\.xpm$" mew-b64 mew-prog-image mew-icon-image xpm) + ("image/x-bmp" "\\.bmp$" mew-b64 mew-prog-image mew-icon-image bmp) + ("image/bmp" "^$" mew-b64 mew-prog-image mew-icon-image bmp) ;; unofficial + ("image/x-pcx" "\\.pcx$" mew-b64 mew-prog-image mew-icon-image PCX) + ("image/x-tga" "\\.tga$" mew-b64 mew-prog-image mew-icon-image TGA) + ("image/vnd.ms-modi" "\\.mdi$" mew-b64 mew-prog-image mew-icon-image) + ("image/vnd.microsoft.icon" "\\.ico$" mew-b64 mew-prog-image mew-icon-image ICO) + ("image/x-portable-bitmap" "\\.pbm$" mew-b64 mew-prog-image mew-icon-image pbm) + ("image/x-portable-graymap" "\\.pgm$" mew-b64 mew-prog-image mew-icon-image pbm) + ("image/x-portable-pixmap" "\\.ppm$" mew-b64 mew-prog-image mew-icon-image pbm) + ("image/x-portable-anymap" "\\.pnm$" mew-b64 mew-prog-image mew-icon-image pbm) + ("image/x-portable-arbitrarymap" "\\.pam$" mew-b64 mew-prog-image mew-icon-image PAM) + ("image" "^$" mew-b64 mew-prog-image mew-icon-image) + ;; + ("model/iges" "\\.ige?s$" mew-b64 mew-prog-iges mew-icon-image) ;; xxx + ("model/vrml" "\\.wrl$" mew-b64 mew-prog-vrml mew-icon-image) + ("model/mesh" "\\.me?sh$" mew-b64 mew-prog-mesh mew-icon-image) + ("model" "^$" mew-b64 mew-prog-model mew-icon-image) + ;; + ("video/mpeg" "\\.mpe?g$" mew-b64 mew-prog-video mew-icon-video) + ("video/quicktime" "\\.mov$" mew-b64 mew-prog-video mew-icon-video) + ("video/x-msvideo" "\\.avi$" mew-b64 mew-prog-video mew-icon-video) + ;; + ("message/rfc822" ,(format "^[0-9]+\\(%s\\)?$" mew-suffix) nil + mew-prog-rfc822 mew-icon-message/rfc822) + ("message/external-body" "\\.ext$" nil + mew-prog-external-body mew-icon-message/external-body) + ("message/delivery-status" "^$" nil + mew-prog-delivery-status mew-icon-text) + ;; + ("application/postscript" "\\.e?ps$" mew-qp + mew-prog-postscript mew-icon-application/postscript) + ("application/pdf" "\\.pdf$" mew-b64 + mew-prog-pdf mew-icon-application/postscript) + ;; Thunderbird/3.1.7 only, not registered in IANA + ("text/pdf" "\\.pdf$" mew-b64 + mew-prog-pdf mew-icon-application/postscript) + ("application/octet-stream" "\\.pages$" mew-b64 + mew-default-external-program mew-icon-application/octet-stream) + ("application/octet-stream" "\\.key$" mew-b64 + mew-default-external-program mew-icon-application/octet-stream) + ("application/octet-stream" "\\.numbers$" mew-b64 + mew-default-external-program mew-icon-application/octet-stream) + ("application/msword" "\\.doc$" mew-b64 + mew-prog-msword mew-icon-text) + ("application/vnd.ms-excel" "\\.xl[st]$" mew-b64 + mew-prog-msexcel mew-icon-text) + ("application/vnd.ms-powerpoint" "\\.ppt$" mew-b64 + mew-prog-mspowerpoint mew-icon-text) + ("application/vnd.openxmlformats-officedocument.wordprocessingml.document" "\\.docx$" mew-b64 + mew-prog-msword mew-icon-text) + ("application/vnd.openxmlformats-officedocument.wordprocessingml.template" "\\.dotx$" mew-b64 + mew-prog-msword mew-icon-text) + ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" "\\.xlsx$" mew-b64 + mew-prog-msexcel mew-icon-text) + ("application/vnd.openxmlformats-officedocument.spreadsheetml.template" "\\.xltx$" mew-b64 + mew-prog-msexcel mew-icon-text) + ("application/vnd.openxmlformats-officedocument.presentationml.presentation" "\\.pptx$" mew-b64 + mew-prog-mspowerpoint mew-icon-text) + ("application/vnd.openxmlformats-officedocument.presentationml.slideshow" "\\.ppsx$" mew-b64 + mew-prog-mspowerpoint mew-icon-text) + ("application/vnd.openxmlformats-officedocument.presentationml.template" "\\.potx$" mew-b64 + mew-prog-mspowerpoint mew-icon-text) + ("application/vnd.openxmlformats-officedocument.presentationml.slide" "\\.sldx$" mew-b64 + mew-prog-mspowerpoint mew-icon-text) + ("application/vnd.visio" "\\.vsd$" mew-b64 + mew-prog-visio mew-icon-text) + ("application/ms-tnef" "\\.dat$" mew-b64 + mew-prog-mstnef mew-icon-unknown) + ("application/rtf" "\\.rtf$" mew-b64 + mew-prog-rtf mew-icon-text) + ("application/pgp-keys" "\\.pka$" nil + mew-prog-pgp-keys mew-icon-unknown) + ("application/x-pkcs7-signature" "\\.p7s$" mew-b64 + nil mew-icon-unknown) + ("application/vnd.fujitsu.oasys" "\\.oas$" mew-b64 + mew-prog-oasys mew-icon-text) + ("application/vnd.fujitsu.oasys2" "\\.oa2$" mew-b64 + mew-prog-oasys mew-icon-text) + ("application/vnd.fujitsu.oasys3" "\\.oa3$" mew-b64 + mew-prog-oasys mew-icon-text) + ("application/zip" "\\.zip$" mew-b64 + mew-prog-unzip mew-icon-application/octet-stream) + ("application/x-zip-compressed" "\\.zip$" mew-b64 + mew-prog-unzip mew-icon-application/octet-stream) + ("application/octet-stream" + "\\.tar$\\|\\.tar\\.\\|\\.jar$\\|\\.gz$\\|\\.Z$\\|\\.taz$\\|\\.tgz$\\|\\.xz$\\|\\.txz$\\|\\.lzma?$\\|\\.tlz$\\|\\.tbz$\\|\\.bz2?$\\|\\.lzh$\\|\\.bin$\\|\\.pgp$\\|\\.gpg$\\|\\.exe$\\|\\.dll$\\|\\.class$" + mew-b64 mew-prog-octet-stream mew-icon-application/octet-stream) + ;; + ("text/html" "\\.html?$" nil mew-prog-html mew-icon-text) + ("text/enriched" "\\.rtf$" nil mew-prog-enriched mew-icon-text) + ("text/css" "\\.css$" nil mew-prog-text mew-icon-text) + ("text/sgml" "\\.sgml$" nil mew-prog-text mew-icon-text) + ("text/xml" "\\.xml$" nil mew-prog-xml mew-icon-text) + ("text/calendar" "\\.ics$" nil mew-prog-text mew-icon-text) + ("text/x-patch" "\\.diff$\\|\\.patch$" + nil mew-prog-patch mew-icon-text) + ("text/plain" "\\.txt$\\|\\.c$\\|\\.h$\\|\\.el$\\|\\.diff$\\|\\.patch$" + nil mew-prog-plain mew-icon-text) + ("text/rfc822-headers" "\\.hdr$" nil + mew-prog-rfc822-headers mew-icon-message/rfc822) + ("text/csv" "\\.csv$" nil mew-prog-text mew-icon-text) + ("text" "^$" nil mew-prog-text mew-icon-text) + ("application/xml" "\\.xml$" mew-b64 + mew-prog-xml2 mew-icon-text) + ;; Unknown CT: matches here. + (t "^$" nil mew-prog-octet-stream mew-icon-unknown) + ;; Unknown suffix matches here and return the entry specified + ;; by mew-content-type. + (nil ".*"))) + +(mew-defvar + 'mew-mime-content-type-for-ooffice + '(("application/vnd.oasis.opendocument.text" "\\.odt") + ("application/vnd.oasis.opendocument.text-template" "\\.ott") + ("application/vnd.oasis.opendocument.text-web" "\\.oth") + ("application/vnd.oasis.opendocument.text-master" "\\.odm") + ("application/vnd.oasis.opendocument.graphics" "\\.odg") + ("application/vnd.oasis.opendocument.graphics-template" "\\.otg") + ("application/vnd.oasis.opendocument.presentation" "\\.odp") + ("application/vnd.oasis.opendocument.presentation-template" "\\.otp") + ("application/vnd.oasis.opendocument.spreadsheet" "\\.ods") + ("application/vnd.oasis.opendocument.spreadsheet-template" "\\.ots") + ("application/vnd.oasis.opendocument.chart" "\\.odc") + ("application/vnd.oasis.opendocument.chart-template" "\\.otc") + ("application/vnd.oasis.opendocument.image" "\\.odi") + ("application/vnd.oasis.opendocument.image-template" "\\.oti") + ("application/vnd.oasis.opendocument.formula" "\\.odf") + ("application/vnd.oasis.opendocument.formula-template" "\\.otf") + ("application/vnd.oasis.opendocument.database" "\\.odb") + ("application/vnd.sun.xml.writer" "\\.sxw$") + ("application/vnd.sun.xml.writer.template" "\\.stw$") + ("application/vnd.sun.xml.calc" "\\.sxc$") + ("application/vnd.sun.xml.calc.template" "\\.stc$") + ("application/vnd.sun.xml.draw" "\\.sxd$") + ("application/vnd.sun.xml.draw.template" "\\.std$") + ("application/vnd.sun.xml.impress" "\\.sxi$") + ("application/vnd.sun.xml.impress.template" "\\.sti$") + ("application/vnd.sun.xml.writer.global" "\\.sxg$") + ("application/vnd.sun.xml.math" "\\.sxm$"))) + +(when mew-mime-content-type-for-ooffice + (setq mew-mime-content-type + (nconc + (mapcar + (lambda (x) (list (nth 0 x) (nth 1 x) 'mew-b64 'mew-prog-ooffice 'mew-icon-text)) + mew-mime-content-type-for-ooffice) + mew-mime-content-type))) + +(provide 'mew-varsx) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-varsx.el ends here diff --git a/elpa/mew-20150813.2354/mew-virtual.el b/elpa/mew-20150813.2354/mew-virtual.el new file mode 100644 index 00000000..adc7f6da --- /dev/null +++ b/elpa/mew-20150813.2354/mew-virtual.el @@ -0,0 +1,245 @@ +;;; mew-virtual.el --- Virtual mode for Mew + +;; Author: Kazu Yamamoto +;; Created: Oct 2, 1996 + +;;; Code: + +(require 'mew) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Virtual info +;;; + +(defvar mew-vinfo-list + '("func" "lra" "top" "db" "column" + "mode" ;; 'selection or 'thread + "physical-folder" + "original-folder")) ;; tt back from Thread + +(mew-blinfo-defun 'mew-vinfo mew-vinfo-list) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Virtual mode +;;; + +(defun mew-virtual-mode () + "A major mode to visualize messages in a virtual folder. + +\\{mew-summary-mode-map}" + (interactive) + (setq major-mode 'mew-virtual-mode) + (setq mode-line-buffer-identification (mew-mode-line-id)) + (use-local-map mew-summary-mode-map) + (setq buffer-read-only t) + (setq truncate-lines t) + ;; + (if (boundp 'bidi-paragraph-direction) + (setq bidi-paragraph-direction 'left-to-right)) + (make-local-variable 'tab-width) + (make-local-variable 'search-invisible) + (setq search-invisible nil) + (unless (mew-thread-p) + (jit-lock-register 'mew-summary-cook-region)) + (mew-sinfo-set-disp-msg t) + ;; + (mew-summary-mode-name mew-mode-name-virtual) + (mew-summary-setup-mode-line) + (mew-summary-setup-decoration) + (mew-highlight-cursor-line) + (mew-run-mode-hooks 'mew-virtual-mode-hook)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Making Virtual mode +;;; + +(defun mew-summary-selection-by-pick (&optional regionp) + "Making selection according to a specified pick pattern. +'mewl' or 'grep' is called as a picking command. If called with +'\\[universal-argument]', the target is the region." + (interactive "P") + (mew-pickable + (mew-summary-with-mewl + (let* ((ofolder (mew-summary-folder-name 'ext)) + (vfolder (mew-folder-to-selection ofolder)) + (pfolder (mew-summary-physical-folder)) + (msgs (mew-summary-pick-msgs pfolder regionp)) + (prompt (format "%s/%s virtual" mew-prog-mewl mew-prog-grep)) + (prog mew-prog-grep) + (opts mew-prog-grep-opts) + mew-inherit-pick-mewlp + grepp pattern prog-opts-pat + rfolder lra) + (if (not msgs) + (message "No message") + (setq pattern (mew-input-pick-pattern prompt)) + (cond + ((string= pattern "") + (setq prog-opts-pat (mew-input-pick-command prog opts)) + (mew-set '(prog opts pattern) prog-opts-pat) + (setq grepp t)) + (t + (setq pattern (mew-pick-canonicalize-pattern pattern)) + (unless mew-inherit-pick-mewlp (setq grepp t)))) + (if (and grepp (not (mew-which-exec prog))) + (message "'%s' not found" prog) + (setq rfolder (mew-expand-folder2 pfolder)) + (setq lra (list (cons rfolder pfolder))) + (mew-summary-switch-to-folder vfolder) + (when (mew-summary-exclusive-p) + (mew-vinfo-set-mode 'selection) + (mew-vinfo-set-physical-folder pfolder) + (mew-vinfo-set-original-folder ofolder) + (cond + (grepp + (mew-sinfo-set-find-key pattern) + (message "Picking messages in %s..." pfolder) + (mew-summary-selection-by-pick-with-grep prog opts pattern pfolder msgs rfolder lra)) + (t + (mew-sinfo-set-find-key nil) + (message "Picking messages in %s..." pfolder) + (mew-summary-selection-by-pick-with-mewl pattern pfolder msgs rfolder lra)))))))))) + +(defun mew-summary-selection-by-pick-with-mewl (pattern folder src-msgs rfolder lra) + "Create selection with 'mewl'" + (let ((opts (list "-a" "-p" pattern "-b" mew-mail-path)) + (range (mew-summary-pick-range src-msgs))) + (setq rfolder (mew-scan-mewl-folder rfolder)) + (if range + (setq opts (nconc opts (list rfolder range))) + (setq opts (nconc opts (list rfolder)))) + (mew-local-retrieve 'vir opts nil lra))) + +(defun mew-summary-selection-by-pick-with-grep (prog opts pattern folder msgs rfolder lra) + "Create selection with 'grep'" + (interactive) + (let ((file-rttl (mew-summary-selection-by-pick-with-grep1 prog opts pattern rfolder msgs)) + file rttl func args) + (mew-set '(file rttl) file-rttl) + (setq func `(lambda () (mew-delete-file ,file))) + (setq args (list "-i" file)) + (mew-local-retrieve 'vir args func lra nil rttl))) + +(defun mew-summary-selection-by-pick-with-grep1 (prog opts pattern folder msgs) + (let ((dir (mew-expand-folder folder)) + (file (mew-make-temp-name)) + (rttl 0) nxt) + (if (= (length msgs) 1) (setq msgs (cons null-device msgs))) + (if pattern (setq pattern (mew-cs-encode-arg pattern))) + (with-temp-buffer + (mew-set-buffer-multibyte t) + (cd dir) + (mew-piolet mew-cs-text-for-read mew-cs-text-for-write + (mew-alet ;; xxx + (while msgs + (goto-char (point-max)) + (setq nxt (nthcdr mew-prog-grep-max-msgs msgs)) + (if nxt (mew-ntake mew-prog-grep-max-msgs msgs)) + (apply 'call-process prog nil t nil + (append opts (and pattern (list pattern)) msgs)) + (setq msgs nxt))) + (setq msgs nil) + (goto-char (point-min)) + (while (re-search-forward mew-regex-message-files2 nil t) + (setq msgs (cons (mew-match-string 1) msgs)) + (forward-line)) + (setq msgs (mew-uniq-list msgs)) + (setq msgs (mapcar 'string-to-number msgs)) + (setq msgs (sort msgs '<)) + (setq msgs (mapcar 'number-to-string msgs))) + (mew-erase-buffer) + (setq rttl (length msgs)) + (insert "CD: " folder "\n") + (mapc (lambda (x) (insert (mew-msg-get-filename x) "\n")) msgs) + (mew-frwlet mew-cs-text-for-read mew-cs-text-for-write + (write-region (point-min) (point-max) file nil 'no-msg)) + (list file rttl)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; mark virtual +;;; + +(defun mew-summary-selection-by-mark (&optional ask-mark) + "Making selection for messages marked with '*'. +If called with '\\[universal-argument]', you can specify a target mark." + (interactive "P") + (if (not (mew-pickable)) + (message "This command cannot be used in this folder") + (let* ((ofolder (mew-summary-folder-name 'ext)) + (vfolder (mew-folder-to-selection ofolder)) + (pfolder (mew-summary-physical-folder)) + (mark mew-mark-review) + (start (point)) + (case-fold-search nil) + beg line med regex) + (if ask-mark (setq mark (mew-input-mark))) + (setq regex (mew-mark-regex mark)) + ;; + (mew-summary-switch-to-folder vfolder) + (mew-vinfo-set-mode 'selection) + (mew-vinfo-set-physical-folder pfolder) + (mew-vinfo-set-original-folder ofolder) + (mew-erase-buffer) + ;; + (set-buffer pfolder) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (beginning-of-line) + (setq beg (point)) + (forward-line) + ;; This must be buffer-substring + (setq line (buffer-substring beg (point))) + (with-current-buffer vfolder + (mew-elet + (insert line) + (save-excursion + (when (and (search-backward "\r") + (setq med (point)) + (looking-at mew-regex-sumsyn-short)) + (goto-char (match-beginning 1)) + (insert pfolder) + (put-text-property med (point) 'invisible t)))))) + (goto-char start) + (set-buffer vfolder) + (mew-summary-set-count-line) + ;; Unmarking in both Summary and Thread + (if (char-equal mark mew-mark-review) + (mew-mark-undo-mark mark 'no-msg 'virtual-only))))) + +(provide 'mew-virtual) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-virtual.el ends here diff --git a/elpa/mew-20150813.2354/mew-win32.el b/elpa/mew-20150813.2354/mew-win32.el new file mode 100644 index 00000000..69e891f2 --- /dev/null +++ b/elpa/mew-20150813.2354/mew-win32.el @@ -0,0 +1,244 @@ +;;; mew-win32.el --- Settings for Mew on Win32 + +;; Author: Shuichi Kitaguchi +;; Created: Dec 05, 1997 + +;;; Code: + +(eval-when-compile + (mew-no-warning-defvar w32-start-process-show-window) + (mew-no-warning-defun mw32script-init) + (mew-no-warning-defun mw32script-make-pathext-regexp) + (mew-no-warning-defun mw32script-openp) + (mew-no-warning-defun mw32script-argument-editing-function) + (mew-no-warning-defun dos-to-unix-filename)) + +;;; for NTEmacs User +;; +;; put mw32script.el(in Meadow's archive) into load-path. +;; + +;; +;; ~/.mew settings +;; + +;;; for PRINTING +;; mew-w32-prog-print --- print command +;; mew-w32-prog-print-arg --- print command argument +;; mew-w32-cs-print --- coding-system for printing +;; define-process-argument-editing --- for argument-editing +;; +;;; example +;; (setq mew-w32-prog-print "notepad.exe") +;; (setq mew-w32-prog-print-arg "/p") +;; (setq mew-w32-cs-print 'shift_jis-dos) ;; Meadow +;; (define-process-argument-editing "/notepad\\.exe$" +;; (lambda (x) +;; (general-process-argument-editing-function x nil t))) +;; (setq mew-print-function 'mew-w32-print-buffer) + +;; Win32 programs. +(defvar mew-w32-exec "fiber.exe") +(defvar mew-w32-prog-print "notepad.exe") +(defvar mew-w32-prog-print-arg nil) + +(defvar mew-default-external-program mew-w32-exec) + +(defvar mew-w32-cs-print nil) + +(setq mew-which-exec-suffixes (if (and (boundp 'exec-suffixes) + exec-suffixes) + exec-suffixes + '(".exe" ".com" ".bat" ".cmd" ""))) + +(setq mew-delete-temp-file nil) + +;; Emacs version dependent variables. +(cond + ((featurep 'meadow) ;; Meadow + (require 'mw32script) + (mw32script-init)) + ((condition-case nil + (progn + (require 'mw32script) + (load "mw32misc")) + (file-error nil)) ;; NTEmacs + (mw32script-make-pathext-regexp) + (defun mew-w32-argument-editing-function (program args) + (let ((default-process-argument-editing-function 'identity) + (process-argument-editing-alist nil) + prog sargs) + (setq prog (mw32script-openp program)) + (if (and (null prog) + (setq prog (mew-which-exec program)) + (setq sargs (mw32script-argument-editing-function (list prog)))) + (cons (car sargs) (cons prog args)) + (cons program args)))) + (defadvice call-process + (before mew-w32-call-process + (program &optional infile buffer display &rest args) + activate) + (let ((sargs (mew-w32-argument-editing-function program args))) + (setq program (car sargs) + args (cdr sargs)))) + (defadvice call-process-region + (before mew-w32-call-process-region + (start end program &optional infile buffer display &rest args) + activate) + (let ((sargs (mew-w32-argument-editing-function program args))) + (setq program (car sargs) + args (cdr sargs)))) + (defadvice start-process + (before mew-w32-start-process + (name buffer program &rest program-args) + activate) + (let ((sargs (mew-w32-argument-editing-function program program-args))) + (setq program (car sargs) + program-args (cdr sargs)))))) + +;; printing +(defun mew-w32-print-buffer () + (let ((tempfile (mew-make-temp-name))) + (mew-frwlet mew-cs-dummy mew-w32-cs-print + (write-region (point-min) (point-max) tempfile nil nil)) + (setq w32-start-process-show-window t) + (cond + ((eq mew-w32-prog-print-arg nil) + (call-process mew-w32-prog-print nil nil nil tempfile)) + (t + (call-process mew-w32-prog-print nil nil nil mew-w32-prog-print-arg tempfile))) + (setq w32-start-process-show-window nil) + (mew-delete-file tempfile))) + + +;; MIME setting + +(defvar mew-prog-plain 'mew-mime-text/plain) +(defvar mew-prog-html '(mew-mime-text/html mew-mime-text/html-ext)) +(defvar mew-prog-xml '(mew-mime-text/xml mew-mime-text/xml-ext)) +(defvar mew-prog-patch '(mew-mime-text/plain mew-mime-text/patch-ext)) +(defvar mew-prog-enriched 'mew-mime-text/enriched) +(defvar mew-prog-text 'mew-mime-text/plain) +(defvar mew-prog-audio mew-w32-exec) +(defvar mew-prog-audio2 mew-w32-exec) ;; dummy +(defvar mew-prog-image '(mew-mime-image/* mew-mime-image/*-ext)) +(defvar mew-prog-iges mew-w32-exec) +(defvar mew-prog-vrml mew-w32-exec) +(defvar mew-prog-mesh mew-w32-exec) +(defvar mew-prog-video mew-w32-exec) +(defvar mew-prog-rfc822 'mew-mime-message/rfc822) +(defvar mew-prog-rfc822-headers 'mew-mime-text/rfc822-headers) +(defvar mew-prog-external-body '(mew-mime-external-body mew-mime-external-body-ext)) +(defvar mew-prog-delivery-status 'mew-mime-text/plain) +(defvar mew-prog-postscript mew-w32-exec) +(defvar mew-prog-pgp-keys '(mew-mime-pgp-keys mew-mime-pgp-keys-ext)) +(defvar mew-prog-application/pdf "pdftotext") +(defvar mew-prog-pdf-ext mew-w32-exec) +(defvar mew-prog-pdf `(mew-mime-application/pdf ,mew-prog-pdf-ext)) +(defvar mew-prog-xml2 '(mew-mime-application/xml + mew-mime-application/xml-ext)) +(defvar mew-prog-oasys mew-w32-exec) +(defvar mew-prog-octet-stream mew-w32-exec) +(defvar mew-prog-msword mew-w32-exec) +(defvar mew-prog-msexcel mew-w32-exec) +(defvar mew-prog-mspowerpoint mew-w32-exec) +(defvar mew-prog-visio mew-w32-exec) +(defvar mew-prog-ooffice mew-w32-exec) +(defvar mew-prog-rtf mew-w32-exec) +(defvar mew-prog-unzip mew-w32-exec) + +;;; +;;; Text/Html, Application/Xml, Image +;;; + +(defvar mew-format-html "%s.htm") +(defvar mew-format-xml "%s.xml") + +(defvar mew-prog-text/html + (if (and (fboundp 'shr-render-region) + (fboundp 'libxml-parse-html-region)) + 'shr-render-region + 'mew-mime-text/html-w3m)) ;; See w3m.el +(defvar mew-prog-text/html-ext mew-w32-exec) + +(defvar mew-prog-text/xml + (if (and (fboundp 'shr-render-region) + (fboundp 'libxml-parse-html-region)) + 'shr-render-region + 'mew-mime-text/html-w3m)) ;; See w3m.el +(defvar mew-prog-text/xml-ext mew-w32-exec) + +(defvar mew-prog-application/xml nil) +(defvar mew-prog-application/xml-ext mew-w32-exec) + +(defvar mew-prog-image/* 'mew-mime-image/*) +(defvar mew-prog-image/*-ext mew-w32-exec) + +(defvar mew-prog-application/msword nil) +(defvar mew-prog-application/msexcel nil) +(defvar mew-prog-application/mspowerpoint nil) +(defvar mew-prog-application/rtf nil) + +(setq mew-cs-database-for-arg + '((iso-2022-jp . shift_jis-unix) + (iso-2022-kr . euc-kr-unix))) + +(setq mew-prog-grep-max-msgs 2000) ;; for external grep (pick & virtual) + +(defvar mew-dir-list-function 'mew-dir-list-without-link-count) + +(defun mew-draft-dnd-for-meadow (event) + (interactive "e") + (when (eq (posn-window (event-start event)) (selected-window)) + (let ((files (car (cdr (cdr event)))) + to) + (if (stringp files) + (setq files (list files))) + (dolist (from files) + (setq from (dos-to-unix-filename from)) + (when (file-exists-p from) + (setq to (file-name-nondirectory from)) + (unless (mew-attach-p) + (mew-draft-prepare-attachments)) + (goto-char (point-max)) + (forward-line -2) + (mew-attach-next) + (cond + ((file-directory-p from) + (message "Directory cannot be attached")) + (t + (mew-attach-copy from to)))))))) + +(provide 'mew-win32) + +;;; Copyright Notice: + +;; Copyright (C) 1996-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew-win32.el ends here diff --git a/elpa/mew-20150813.2354/mew.el b/elpa/mew-20150813.2354/mew.el new file mode 100644 index 00000000..8ad8b65f --- /dev/null +++ b/elpa/mew-20150813.2354/mew.el @@ -0,0 +1,775 @@ +;;; mew.el --- Messaging in the Emacs World + +;; Author: Kazu Yamamoto +;; Created: Mar 23, 1994 +;; Revised: Aug 4, 2015 + +;;; Commentary: + +;; The updated version is available from: +;; http://www.Mew.org/ +;; +;; See info for configuring a site file/.emacs/.mew.el. + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Mew version +;;; + +(defconst mew-version-number "6.7" + "Version number for this version of Mew.") +(defconst mew-version (format "Mew version %s" mew-version-number) + "Version string for this version of Mew.") +(provide 'mew) +(require 'mew-const) +(require 'mew-blvs) +(require 'mew-func) +(require 'mew-vars) ;; mew-env && mew-key +(require 'mew-vars2) +(require 'mew-vars3) + +(defun mew-version-show () + "Show mew-version in minibuffer." + (interactive) + (message "%s" mew-version)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; For developers +;;; + +(defvar mew-debug nil + "'decode, 'encode, 'net, 'pgp, 'thread, 'sort, t for all.") +(defun mew-debug (category) + (or (eq mew-debug t) (eq mew-debug category))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Bootstrap +;;; + +(defvar mew-init-p nil) + +;;;###autoload +(defun mew (&optional arg) + "Execute Mew first unless Mew is running. And retrieve arrived +messages or just visit to the default folder. + +'proto' is determined by 'mew-proto' and 'mew-case'. + +If 'proto' is '+' (ie a local folder), a mailbox is determined +according to 'mew-mailbox-type'. Otherwise (ie a remote folder), an +appropriate protocol to retrieve messages is chosen according to +'proto'. + +If 'mew-auto-get' is 't', arrived messages are asynchronously fetched +and listed up in Summary mode. + +'mew-auto-get' is 'nil', just visit to the folder determined by +'proto'. + +When executed with '\\[universal-argument]', 'mew-auto-get' is +considered reversed." + (interactive "P") + (mew-window-push) + (unless mew-init-p (mew-init)) + (let* ((auto (if arg (not mew-auto-get) mew-auto-get)) + (case mew-case) + (proto (mew-proto case)) + inbox case:inbox) + (if auto + (mew-summary-scan-boot proto case) + ;; see also mew-summary-retrieve + (setq inbox (mew-proto-inbox-folder proto case)) + (setq case:inbox (mew-case-folder case inbox)) + (mew-summary-visit-folder case:inbox 'goend)) + (setq mew-inbox-window (current-window-configuration)))) + +;;;###autoload +(defun mew-send (&optional to cc subject) + "Execute Mew then prepare a draft. This may be used as library +function." + (interactive) + (mew-current-set-window-config) + (unless mew-init-p (mew-init)) + (mew-summary-send to cc subject)) + +;;;###autoload +(defun mew-user-agent-compose (&optional to subject other-headers continue + switch-function yank-action + send-actions + &rest dummy) + "Set up message composition draft with Mew. +This is 'mail-user-agent' entry point to Mew. + +The optional arguments TO and SUBJECT specify recipients and the +initial Subject field, respectively. + +OTHER-HEADERS is an alist specifying additional +header fields. Elements look like (HEADER . VALUE) where both +HEADER and VALUE are strings. + +A Draft buffer is prepared according to SWITCH-FUNCTION. + +CONTINUE, YANK-ACTION and SEND-ACTIONS are ignored." + (unless mew-init-p (mew-init)) + (let* ((draft (mew-folder-new-message mew-draft-folder)) + (attachdir (mew-attachdir draft)) + cc asked) + (when (and mew-ask-to (null to)) + (setq to (mew-input-address (concat mew-to: " "))) + (setq asked t)) + (when mew-ask-cc + (setq cc (mew-input-address (concat mew-cc: " "))) + (setq asked t)) + (mew-current-set-window-config) + (mew-window-configure 'draft) + (mew-summary-prepare-draft + (mew-draft-find-and-switch draft switch-function) + (mew-delete-directory-recursively attachdir) + (mew-draft-header subject nil to cc nil nil nil other-headers asked) + (mew-draft-mode) + (run-hooks 'mew-draft-mode-newdraft-hook)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Functions for boot time +;;; + +(defun mew-init () + (let ((buf (get-buffer-create "*Mew hello*"))) + (run-hooks 'mew-env-hook) + (load mew-rc-file 'no-err 'no-msg) + (cond + ((memq system-type '(windows-nt cygwin)) + (require 'mew-win32)) + ((eq system-type 'darwin) + (require 'mew-darwin)) + (t + (require 'mew-unix))) + (require 'mew-varsx) + (if mew-theme-file (load mew-theme-file 'no-err 'no-msg)) + (switch-to-buffer buf) + (mew-window-configure '(1 0)) ;; Using mew-mode-name-message + (mew-hello) + (message "Setting up Mew world...") + (mew-set-environment) + (run-hooks 'mew-init-hook) + (mew-transit-folder) + (mew-status-update t) + (mew-passwd-setup) + (mew-highlight-timer-setup) + (setq mew-init-p t) + (mew-kill-buffer buf) + (message "Setting up Mew world...done"))) + +(defun mew-set-environment (&optional no-dir) + (let (error-message) + (condition-case nil + (progn + ;; sanity check + (cond + ((featurep 'xemacs) + (setq error-message "Not support XEmacs\n") + (error "")) + ((string-match "^\\(18\\|19\\|20\\)" emacs-version) + (setq error-message "Not support Emacs 18/19/20 nor Mule 1\n") + (error ""))) + ;; initializing + (or no-dir (mew-buffers-init)) + (or no-dir (mew-temp-dir-init)) + (mew-mark-init) + (mew-config-init) + (mew-subprocess-init) + (mew-rotate-log-files mew-smtp-log-file) + (mew-rotate-log-files mew-nntp-log-file) + (mew-rotate-log-files mew-refile-log-file)) + (error + (set-buffer (generate-new-buffer mew-buffer-debug)) + (goto-char (point-max)) + (insert "\n\nMew errors:\n\n") + (and error-message (insert error-message)) + (set-buffer-modified-p nil) + (setq buffer-read-only t) + ;; cause an error again + (error "Mew found some errors above"))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Status update +;;; + +(defun mew-folder-init (folders) + (let (dir) + (dolist (folder folders) + (setq folder (mew-canonicalize-folder folder)) + (setq dir (mew-expand-folder folder)) + (unless (file-exists-p dir) + (mew-make-directory dir) + (mew-local-folder-insert folder) + (message "%s was created" dir)) + (setq dir (file-chase-links dir)) + (if (file-exists-p dir) + (if (/= mew-folder-mode (file-modes dir)) + (set-file-modes dir mew-folder-mode)))))) + +(defun mew-status-update (&optional arg) + "Read Addrbook and update its information. +If executed with '\\[universal-argument]', information about folders +of the current world is also updated." + (interactive "P") + (cond + ((and arg (integerp arg)) + (mew-message-for-summary "This command was obsoleted. Type '\\[universal-argument]\\[mew-status-update]' to collect folders")) + ((consp arg) + (let (case proto) + (mew-set '(case proto) (mew-summary-case-proto)) + (cond + ((mew-folder-localp proto) + (mew-local-update (mew-called-interactively-p))) + ((mew-folder-popp proto) + (message "Nothing updated for POP")) + ((mew-folder-imapp proto) + (mew-imap-update case)) + ((mew-folder-nntpp proto) + (mew-nntp-update case))))) + (t + (if (mew-called-interactively-p) (mew-set-environment 'no-dir)) + ;; These two must be before mew-local-update + (message "Updating status...") + (mew-config-setup) + (mew-regex-setup) + (if arg (mew-local-update (mew-called-interactively-p))) + (mew-folder-init mew-basic-folders) + (mew-folder-init mew-inbox-folders) + (mew-folder-init mew-queue-folders) + (mew-folder-init mew-postq-folders) + (mew-refile-setup) + (mew-addrbook-setup) + (mew-scan-setup) + (mew-pgp-setup) + (mew-smime-setup) + (mew-ssh-setup) + (mew-ssl-setup) + (mew-net-setup) + (mew-thread-setup) + (mew-decoration-setup) + (mew-biff-setup) + (mew-ct-setup) + (run-hooks 'mew-status-update-hook) + (message "Updating status...done")))) + +(defvar mew-mime-content-type-list nil + "Candidate of Content-Type: when CT: is changed in draft buffer.") + +(defun mew-ct-setup () + (dolist (ct (mapcar 'car mew-mime-content-type)) + (if (and (stringp ct) (not (string-match "/$" ct))) + (setq mew-mime-content-type-list + (cons (capitalize ct) mew-mime-content-type-list))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Current status +;;; + +(defun mew-frame-id (&optional frame) + (if window-system + (let ((fram (or frame (selected-frame)))) + (concat "mew-current-info-" + (cdr (assq 'window-id (frame-parameters fram))))) + "mew-current-info-no-window")) + +(defvar mew-current-info-list '("fld" "msg" "part" "window")) + +(mew-info-defun "mew-current-" mew-current-info-list) + +(defun mew-current-set (fld msg part) + (let ((fid (mew-frame-id))) + (mew-current-set-fld fid fld) + (mew-current-set-msg fid msg) + (mew-current-set-part fid part))) + +(defun mew-current-clean-up () + (if window-system + (dolist (frame (frame-list)) + (mew-info-clean-up (concat "mew-current-info-" (mew-frame-id frame)))) + (mew-info-clean-up "mew-current-info-no-window"))) + +(defun mew-current-set-window-config () + (mew-current-set-window (mew-frame-id) (current-window-configuration))) + +(defun mew-current-get-window-config () + (let ((win (mew-current-get-window (mew-frame-id)))) + (unless (window-configuration-p win) + (setq win mew-inbox-window)) + (if win (set-window-configuration win)) + (mew-current-set-window (mew-frame-id) nil) + (mew-summary-toolbar-update) + (mew-redraw))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Window configuration stack +;;; + +(defvar mew-inbox-window nil) +(defvar mew-window-stack nil) + +(defun mew-window-clean-up () + (setq mew-window-stack nil)) + +(defun mew-window-push () + (let ((frame (selected-frame)) + (config (current-window-configuration))) + (setq mew-window-stack (cons (cons frame config) mew-window-stack)))) + +(defun mew-window-pop () + (let* ((frame (selected-frame)) + (assoc (assoc frame mew-window-stack))) + (if (and assoc (window-configuration-p (cdr assoc))) + (set-window-configuration (cdr assoc)) + (switch-to-buffer (get-buffer-create mew-window-home-buffer))) + (setq mew-window-stack (delq assoc mew-window-stack)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Window configuration +;;; +(defun mew-delete-other-window () + (unless (one-window-p) + (let ((owin (selected-window)) + wins ret) + (walk-windows + (lambda (win) + (set-buffer (window-buffer win)) + (unless (or (eq owin win) + (string-match "^mew-" (symbol-name major-mode))) + (setq wins (cons win wins)))) + nil) + (dolist (win wins) + (unless (one-window-p) + (setq ret t) + (delete-window win))) + (select-window owin) + ret))) + +(defun mew-window-configure (action) + "Configure windows according to ACTION. +ACTION should be symbol or a list of two numbers. +Predefined symbol is 'summary, 'message, and 'draft. +They are used as a key of 'mew-window-configuration to get +a list of two numbers. + +Two numbers means the ratio of the upper window and +the lower window (i.e. the window of Message buffer). + +If Message buffer does not exist, it will be created. If the height of +the lower window is not zero, switch to the buffer." + (let* ((windows + (if (listp action) + action + (car (cdr (assq action mew-window-configuration))))) + (msgbuf (mew-buffer-message)) + (obufwin (get-buffer-window (current-buffer))) + (msgwin (get-buffer-window msgbuf)) + (height nil) (winsum nil) (sum-height 0) (msg-height 0)) + (setq height (+ (if obufwin (window-height obufwin) 0) + (if msgwin (window-height msgwin) 0))) + (cond + ((<= height (* 2 window-min-height)) + ;; Delete other windows and use full emacs window. + (delete-other-windows) + (setq height (window-height (selected-window)))) + ((and mew-use-full-window (mew-delete-other-window)) + ;; delete windows all but Mew's one. + (setq height (+ (if obufwin (window-height obufwin) 0) + (if msgwin (window-height msgwin) 0))))) + ;; + (if (get-buffer msgbuf) + (delete-windows-on msgbuf) + (with-current-buffer (get-buffer-create msgbuf) + (kill-all-local-variables) + ;; "truncate?" is asked in Message mode. + ;; so set the same toolbar as Summary mode + (mew-summary-toolbar-update) + (mew-message-mode))) + ;; + (setq winsum (apply '+ windows)) + (unless (zerop (nth 0 windows)) + (setq sum-height (max window-min-height + (/ (* height (nth 0 windows)) winsum)))) + (if (and (eq action 'message) (= (% sum-height 2) 1)) + (setq sum-height (1+ sum-height))) + (unless (zerop (nth 1 windows)) + (setq msg-height (max window-min-height (- height sum-height)))) + (setq height (+ sum-height msg-height)) + ;; + (unless (zerop msg-height) + (split-window nil sum-height) + (other-window 1) + (switch-to-buffer msgbuf 'norecord) + (mew-set-buffer-cs mew-cs-m17n)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Message buffer +;;; + +(defun mew-window-number () + (let ((x (car (window-edges (selected-window)))) + (i 1)) + (walk-windows + (lambda (win) + (when (with-current-buffer (window-buffer win) + (mew-summary-or-virtual-p)) + (if (< (car (window-edges win)) x) + (setq i (1+ i))))) + 'nominibuf) + i)) + +(defun mew-buffer-message () + (let* ((me (selected-frame)) + (frames (frame-list)) + (len (length frames)) + (n (mew-window-number)) + (i 0)) + (catch 'loop + (dolist (frame frames) + (if (equal me frame) (throw 'loop i)) + (setq i (1+ i)))) + (setq i (- len i 1)) + (if (= n 1) + (format "%s%d" mew-buffer-message i) + (format "%s%d<%d>" mew-buffer-message i n)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Buffers +;;; + +(defvar mew-buffers nil) + +(defun mew-buffers-init () + (setq mew-buffers nil)) + +(defun mew-buffers-setup (folder) + (mew-addq mew-buffers folder)) + +(defun mew-buffers-bury () + (dolist (buffer mew-buffers) + (if (get-buffer buffer) (bury-buffer buffer)))) + +(defun mew-buffers-clean-up () + (dolist (buffer mew-buffers) + (mew-remove-buffer buffer)) + (mew-buffers-init)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Temporary directory +;;; + +(defvar mew-temp-dir nil) ;; the default is "/tmp/user_name_uniq" +(defvar mew-temp-file nil) ;; the default is "/tmp/user_name_uniq/mew" + +(defun mew-temp-dir-init () + "Setting temporary directory for Mew. +mew-temp-file must be local and readable for the user only +for privacy/speed reasons." + (setq mew-temp-dir (make-temp-name mew-temp-file-initial)) + (mew-make-directory mew-temp-dir) + (set-file-modes mew-temp-dir mew-folder-mode) + (setq mew-temp-file (expand-file-name "mew" mew-temp-dir)) + (add-hook 'kill-emacs-hook 'mew-temp-dir-clean-up)) + +(defun mew-temp-dir-clean-up () + "A function to remove Mew's temporary directory recursively. +It is typically called by kill-emacs-hook." + (remove-hook 'kill-emacs-hook 'mew-temp-dir-clean-up) + (if (and mew-temp-dir (file-exists-p mew-temp-dir)) + (mew-delete-directory-recursively mew-temp-dir)) + (setq mew-temp-dir nil) + (setq mew-temp-file nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Regular expressions +;;; + +(defvar mew-regex-msg-show-list nil) +(defvar mew-regex-msg-show nil) +(defvar mew-regex-msg-or-part nil) +(defvar mew-regex-msg-review nil) +(defvar mew-regex-msg-delete nil) +(defvar mew-regex-attach-beg nil) +(defvar mew-regex-attach-end nil) +(defvar mew-regex-my-address-list nil) +(defvar mew-regex-ignore-folders nil) +(defvar mew-regex-thread-separator nil) + +(defun mew-mark-regex (mark) + (concat "^" (regexp-quote (char-to-string mark)))) + +(defun mew-mark-list-regex (mark-list) + (concat "^" "[" (mapconcat 'char-to-string mark-list "") "]")) + +(defun mew-regex-setup-msg (lst) + (setq mew-regex-msg-show-list lst) + (setq mew-regex-msg-show (mew-mark-list-regex lst)) + (setq mew-regex-msg-or-part (concat mew-regex-msg-show "\\|" mew-regex-part))) + +(defun mew-regex-setup () + (setq mew-eoh (format "^\\(%s\\|\\)$" (regexp-quote mew-header-separator))) + (mew-regex-setup-msg mew-mark-show-list) + (setq mew-regex-msg-review (mew-mark-regex mew-mark-review)) + (setq mew-regex-msg-delete (mew-mark-regex mew-mark-delete)) + (setq mew-regex-thread-separator + (concat "^" (regexp-quote mew-thread-separator))) + (setq mew-regex-attach-beg + (concat "^" mew-draft-attach-boundary-beg "$")) + (setq mew-regex-attach-end + (concat "^" mew-draft-attach-boundary-end "$")) + (setq mew-regex-my-address-list (mew-get-my-address-regex-list)) + (setq mew-regex-ignore-folders + (mapconcat + 'mew-folder-regex + (mew-uniq-list + (append + mew-basic-folders + mew-inbox-folders + mew-queue-folders + mew-postq-folders + (list + mew-friend-folder + mew-attach-folder))) + "\\|")) + (unless mew-range-list + (setq mew-range-list + `((,mew-queue-folders ,mew-range-str-all) + (, mew-postq-folders ,mew-range-str-all) + ((,mew-draft-folder) ,mew-range-str-all) + (t ,mew-range-str-update))))) + +(defun mew-summary-toggle-mark-regex () + (interactive) + (let (lst) + (if (equal mew-regex-msg-show-list mew-mark-show-list) + (setq lst mew-mark-show-list2) + (setq lst mew-mark-show-list)) + (mew-regex-setup-msg lst) + (message "Target marks are: %s" (mapconcat (lambda (x) (message "'%c'" x)) lst ", ")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Theme +;;; + +(defun mew-decoration-setup () + (interactive) + (put-text-property 0 (length mew-end-of-message-string) + 'face 'mew-face-eof-message + mew-end-of-message-string) + (put-text-property 0 (length mew-end-of-part-string) + 'face 'mew-face-eof-part + mew-end-of-part-string)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Tear down +;;; + +(defun mew-bury-buffer (&optional buf) + (bury-buffer buf) + (delete-windows-on buf t)) + +(defun mew-kill-buffer (&optional buf) + "Erase the current buffer." + (interactive) + (let* ((buf (or buf (current-buffer))) + (folder (if (bufferp buf) (buffer-name buf) buf)) + obuf) + (if (get-buffer buf) + (with-current-buffer buf + (when (mew-summary-or-virtual-p) + (mew-summary-kill-subprocess) + (setq obuf (mew-local-buffer-name folder)) + ;; xxx should kill pop's buffer... + (mew-remove-buffer obuf)) + (mew-overlay-delete-buffer))) + (mew-remove-buffer buf))) + +(defun mew-buffer-clean-up (regex &optional func) + (unless func (setq func 'mew-kill-buffer)) + (dolist (buf (mew-buffer-list regex)) + (funcall func buf))) + +(defun mew-quit-toolbar-update () + (mew-redraw) ;; due to mouse-face bug + (if (fboundp 'redraw-frame) ;; for BOW + (redraw-frame (selected-frame)))) ;; update toolbar + +(defun mew-summary-suspend () + "Suspend Mew then switch to another buffer. All buffers of +Mew remain, so you can resume with buffer operations." + (interactive) + (mew-buffer-clean-up + (concat "^" (regexp-quote mew-buffer-message)) + 'mew-bury-buffer) + (mew-buffers-bury) + (mew-window-pop) + (mew-quit-toolbar-update) + (run-hooks 'mew-suspend-hook)) + +(defun mew-summary-quit () + "Quit Mew. All buffers of Mew are erased." + (interactive) + (when (y-or-n-p "Quit Mew? ") + ;; killing buffers + (mew-cache-clean-up) + (mew-buffer-clean-up (concat "^" (regexp-quote mew-buffer-message))) + (mew-buffer-clean-up (mew-folder-regex mew-draft-folder)) ;; +draft/* + (mew-buffer-clean-up mew-buffer-regex) ;; other buffers + ;; + (mew-sinfo-clean-up) + (mew-buffers-clean-up) ;; Summary mode and Virtual mode + ;; + (mew-passwd-clean-up) ;; should be before dir clean up + (mew-temp-dir-clean-up) + (mew-subprocess-clean-up) + ;; + (run-hooks 'mew-quit-hook) + ;; + ;; lastly, clean up variables + ;; + (mew-folder-clean-up) + (mew-refile-clean-up) + (mew-current-clean-up) + (mew-addrbook-clean-up) + (mew-highlight-timer-clean-up) + (mew-net-clean-up) + (mew-biff-clean-up) + ;; + (mew-window-pop) + (mew-window-clean-up) + (mew-quit-toolbar-update) + ;; + (setq mew-init-p nil) + (message nil))) ;; just clear + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Transit (should be removed someday) +;;; + +;; Spotlight does not handle Files/Directories starting with ".". +(defvar mew-transit-folder-alist + '(("+.pop" "+#pop") ("+.imap" "+#imap") ("+.nntp" "+#nntp"))) + +(defun mew-transit-folder () + (let (old new dirs subnew) + (with-temp-buffer + (dolist (ent mew-transit-folder-alist) + (setq old (mew-expand-folder (nth 0 ent))) + (setq new (mew-expand-folder (nth 1 ent))) + (when (and (file-directory-p old) (not (file-exists-p new))) + (rename-file old new) + (cd new) + (setq dirs (directory-files ".")) + (dolist (subold dirs) + ;; % is a special character for URL. + ;; And "open" does not convert % to %25, sigh. + (when (string-match "@[^%]+\\(%\\)" subold) + (setq subnew (copy-sequence subold)) + (aset subnew (match-beginning 1) ?#) + (rename-file subold subnew)))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Load Mew libraries +;;; + +(require 'mew-local) +(require 'mew-addrbook) +(require 'mew-complete) +(require 'mew-minibuf) +(require 'mew-cache) +(require 'mew-encode) +(require 'mew-decode) +(require 'mew-edit) +(require 'mew-mime) +(require 'mew-mark) +(require 'mew-exec) +(require 'mew-header) +(require 'mew-pgp) +(require 'mew-smime) +(require 'mew-bq) +(require 'mew-syntax) +(require 'mew-scan) +(require 'mew-passwd) +(require 'mew-pick) +(require 'mew-search) +(require 'mew-summary) +(require 'mew-summary2) +(require 'mew-summary3) +(require 'mew-summary4) +(require 'mew-virtual) +(require 'mew-thread) +(require 'mew-message) +(require 'mew-draft) +(require 'mew-attach) +(require 'mew-demo) +(require 'mew-refile) +(require 'mew-ext) +(require 'mew-fib) +(require 'mew-sort) +(require 'mew-highlight) +(require 'mew-net) +(require 'mew-ssh) +(require 'mew-ssl) +(require 'mew-smtp) +(require 'mew-pop) +(require 'mew-nntp) +(require 'mew-nntp2) +(require 'mew-imap) +(require 'mew-imap2) +(require 'mew-config) +(require 'mew-auth) + +(eval-when-compile + (if (mew-which-el "timer") + (require 'timer))) + +;;; Copyright Notice: + +;; Copyright (C) 1994-2015 Mew developing team. +;; All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; 1. Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; 3. Neither the name of the team nor the names of its contributors +;; may be used to endorse or promote products derived from this software +;; without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND +;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; mew.el ends here diff --git a/elpa/mew-20150813.2354/mew.info b/elpa/mew-20150813.2354/mew.info new file mode 100644 index 00000000..eefea827 --- /dev/null +++ b/elpa/mew-20150813.2354/mew.info @@ -0,0 +1,132 @@ +Info file: mew.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew: (mew.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +Indirect: +mew.info-1: 282 +mew.info-2: 50929 +mew.info-3: 101676 +mew.info-4: 153693 +mew.info-5: 214499 + +Tag table: +(Indirect) +Node: Top285 +Node: Overview1499 +Node: characteristic2392 +Node: Emacsen4118 +Node: modes4335 +Node: folder convention5102 +Node: configuration8154 +Node: password10927 +Node: start13310 +Node: Viewing14478 +Node: singlepart15774 +Node: multipart17263 +Node: analysis20493 +Node: cipher-viewing24442 +Node: retrieving29468 +Node: moving33477 +Node: sum-write36125 +Node: features38502 +Node: status-update40982 +Node: invalid42007 +Node: Composing44204 +Node: header46252 +Node: cheader47252 +Node: addr-comp49054 +Node: addrbook50932 +Node: auto-alias54124 +Node: addr-comp155843 +Node: addr-comp258265 +Node: send60482 +Node: cite63573 +Node: mime-comp65819 +Node: charset-guess73166 +Node: longline76853 +Node: reply78681 +Node: forward82499 +Node: resend83372 +Node: shortcut85445 +Node: mark-b-comp90879 +Node: pgp-key93844 +Node: anonymous94725 +Node: Marks96292 +Node: unread mark97936 +Node: delete mark99437 +Node: refile mark101679 +Node: target mark103290 +Node: escape mark104921 +Node: unmark105776 +Node: mark change106755 +Node: sync108199 +Node: off-line109377 +Node: mew-mark111227 +Node: Refile111949 +Node: by-folder113809 +Node: by-alist115706 +Node: by-thread117789 +Node: by-from-folder118643 +Node: by-from120000 +Node: by-newsgroups121579 +Node: by-default121914 +Node: guess-rule122368 +Node: auto-refile124139 +Node: copy-msg126351 +Node: Virtual127618 +Node: selection129278 +Node: sorting129998 +Node: dialog131841 +Node: search132968 +Node: condition134132 +Node: dbsearch136371 +Node: keyword137595 +Node: thread138453 +Node: thread-op139713 +Node: Quit141879 +Node: Customize142428 +Node: summary-mode143243 +Node: message-mode147402 +Node: draft-mode150729 +Node: charset153696 +Node: highlight155902 +Node: hooks158866 +Node: pop163415 +Node: imap165094 +Node: nntp166662 +Node: smtp168023 +Node: config170508 +Node: config2176438 +Node: custom-misc177954 +Node: Tips178975 +Node: region179563 +Node: visiting180253 +Node: SSH180783 +Node: SSL181755 +Node: TLS184133 +Node: spam185032 +Node: spam2187321 +Node: addr-warn188655 +Node: biff189783 +Node: edit190541 +Node: Convention191816 +Node: Implementation193884 +Node: Avail196247 +Node: obtain196554 +Node: ml196846 +Node: Copyright197242 +Node: Variable Index199191 +Node: Key Index214502 + +End tag table diff --git a/elpa/mew-20150813.2354/mew.info-1 b/elpa/mew-20150813.2354/mew.info-1 new file mode 100644 index 00000000..6154d58f --- /dev/null +++ b/elpa/mew-20150813.2354/mew.info-1 @@ -0,0 +1,1421 @@ +Info file: mew.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew: (mew.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +File: mew.info, Node: Top, Next: Overview, Prev: (dir), Up: (dir) + +Mew 6.7 Manual +************** + + Kazu YAMAMOTO + Created 1996/02/18 + Modified 2015/07/03 + +This manual documents Mew version 6.7. In addition to this manual, you +may find useful information about Mew from Mew's official home page +(http://www.Mew.org/). + + +* Menu: + +* Overview:: Read me first +* Viewing:: Viewing messages +* Composing:: Composing messages +* Marks:: Funny marks +* Refile:: Happy refiling +* Virtual:: Virtual folder +* Quit:: Give me a break +* Customize:: Customizing Mew +* Tips:: Advanced usage +* Convention:: E-mail convention +* Implementation:: Implementation Issues +* Avail:: Availability and mailing-list +* Copyright:: Copyright +* Variable Index:: Variable Index +* Key Index:: Key Index + + + + +File: mew.info, Node: Overview, Next: characteristic, Prev: Top, Up: Top + +Read me first +************* + +Mew is a user interface for text messages, multimedia messages (MIME), +news articles and security functionality including PGP, S/MIME, SSH, +and SSL. Also, Mew can work with the recent search services. + +Mew is an acronym for "Messaging in the Emacs World". You should spell +it with the first letter capitalized and pronounce it as it is +(i.e. the meow of cats). When the author started programming it, he +chose a cute word from his English dictionary. Thus, Mew. + +* Menu: + +* characteristic:: Mew's features +* Emacsen:: Supported Emacs versions +* modes:: Modes +* folder convention:: Folder convention +* configuration:: Configuration +* password:: Password +* start:: Starting + + + + +File: mew.info, Node: characteristic, Next: Emacsen, Prev: Overview, Up: Overview + +Mew's features +============== + +The features of Mew 6.7 are as follows: + + - You can easily display a very complicated structured + message. What you should do to view messages is just type `SPC'. + - If you know how to do file operations such as copy, you can + compose a very complicated message without any difficulty. + - You can start to read messages before they are all fully listed. + - Since Mew preserves lists of messages in Summary mode, when you + move messages to a new folder, they will automatically be listed + incrementally. + - Mew neatly suggests default folders for refiling. Those who + receive many messages cannot live without this feature. + - In Draft mode, you can complete field names, e-mail addresses, + receiver's names, domain names, and folder names. + - You can easily search messages with keywords etc. + - Mew automatically decodes messages encrypted with PGP or + S/MIME. It also automatically verifies signed messages. + - You can easily encrypt or sign a message with PGP or S/MIME. + - It takes a bit of time to analyze MIME syntax or to verify a PGP + or S/MIME signature. While the user is reading a message, Mew + processes the next message so that the next message can be + displayed faster. Analyzed messages are cached briefly. + - You can view multiple folders simultaneously. + - Selection/Thread, a mechanism to display the flow of messages, is + supported. You can make Selection from messages matched to a + keyword and make Thread from the Selection. + - When you input a folder name, you can search it with a substring + of the name. + + + + +File: mew.info, Node: Emacsen, Next: modes, Prev: characteristic, Up: Overview + +Supported Emacs versions +======================== + +Please use Emacs 22.3 or later. Mew doesn't support earlier versions +nor XEmacs. + + + + +File: mew.info, Node: modes, Next: folder convention, Prev: Emacsen, Up: Overview + +Modes +===== + +Mew has the following seven modes: + +`Summary mode' + A mode to list and select messages. +`Virtual mode' + A mode to list messages selected with a specific condition from + one or more folders. This is similar to Summary mode. This mode + is categorized to Selection or Thread. +`Message mode' + A mode to display the content of a message. +`Draft mode' + A mode to prepare a message to be sent, answered, and forwarded. +`Header mode' + A mode to edit the header of a message and to send it. +`Edit mode' + A mode to edit a message to generate another new message. +`Addrbook mode' + A mode to register an entry to the address book (Addrbook). + + + + +File: mew.info, Node: folder convention, Next: configuration, Prev: modes, Up: Overview + +Folder convention +================= + +With Mew's terminology, a place where messages are deliver is called +'mailbox'. There are three kinds of mailbox: local, POP server, IMAP +server, and NNTP server. + +A box which contains messages used by Mew is called "folder". The name +of a folder is in the format that "proto" is followed by a string, +where "proto" is one sign letter. For example, the proto of "+inbox" +is "+". + +Mew's folders are categorized to two types: "local folder" and "remote +folder". + +A local folder is a folder which is *original* and is created the +computer on which Mew is running. Also, messages stored in the folder +are *original*. (So, if you remove them, you cannot revive them.) + +The proto of a local folder is "+". We summarize special local folders +as follows: + +`+inbox' + The first local folder to store messages which you fetch from + your local mailbox or your POP server. To refile messages, what + you do is to move the messages from "+inbox" to other folders. +`+draft' + A local folder where messages, which you have not completed yet, + are stored. +`+queue' + A local folder where e-mail messages to be sent are stored. The + messages in "+queue" will be eventually sent by SMTP. +`+postq' + A local folder where NetNews message to be sent are stored. The + messages in "+postq" will be eventually sent by NNTP. + +A remote folder is a COPY whose original is on a server side. A +message in a remote folder is a cache which is copied from the server. + +Here are a list of available proto of remote folders: + +`%' + Folders on an IMAP servers. Example: "%inbox" +`$' + The folder on a POP server. Example: "$inbox" (Since there is + only one folder in a POP server, "$inbox" is the only folder + whose name starts with "$".) +`-' + Newsgroups of NetNews. Example: "-fj.mail.reader.mew" + +If you use several servers, there are multiple sets of remote folders. +You can specify several servers by using "case". For more information +about the "case", see *Note config::. To specify a remote folder +corresponding to a "case", you should write "case:folder". You can +omit "case:" if a case is "default". + +A combination of "case" and proto organized a world to which a message +belongs. A message can move within its world. To make it easy to +search received messages afterward, they should be moved to proper +folders. To know how to refile received messages, see *Note Refile::. + +You cannot move a message in the "$" world because there is only one +folder, "$inbox". You cannot move a message in the "-" world either +since messages in the "-" world are not yours. + +If you want to move a message from one world to another, you should +COPY it. Its destination is restricted to a local folder. This method +is described in *Note retrieving::. + +If you make a list of folders, you can use the completion +functionality for folders. To know how to make a list of folders, +please refer to *Note status-update::. + + + + +File: mew.info, Node: configuration, Next: password, Prev: folder convention, Up: Overview + +Configuration +============= + +To execute Mew, the followings are necessary either in the site +configuration file or in your "~/.emacs". + + (autoload 'mew "mew" nil t) + (autoload 'mew-send "mew" nil t) + + ;; Optional setup (Read Mail menu): + (setq read-mail-command 'mew) + + ;; Optional setup (e.g. C-xm for sending a message): + (autoload 'mew-user-agent-compose "mew" nil t) + (if (boundp 'mail-user-agent) + (setq mail-user-agent 'mew-user-agent)) + (if (fboundp 'define-mail-user-agent) + (define-mail-user-agent + 'mew-user-agent + 'mew-user-agent-compose + 'mew-draft-send-message + 'mew-draft-kill + 'mew-send-hook)) + +If you are using Emacs with the --unibyte option or the EMACS_UNIBYTE +environment variable for Latin-1, put the following into your +"~/.emacs". + + (set-language-environment "Latin-1") + (set-input-method "latin-1-prefix") ;; or "latin-1-postfix" + +If you use the following configuration for Latin-1, please remove it. +This is an obsolete handling of Latin-1 that can cause Mew to function +incorrectly. + + (standard-display-european 1) + +When booting, Mew reads the file "~/.mew.el". All Mew configurations +should be written in this file. + +To configure your e-mail address, the followings are necessary. + + ;; (setq mew-name "your name") ;; (user-full-name) + ;; (setq mew-user "user name of e-mail address") ;; (user-login-name) + (setq mew-mail-domain "domain of e-mail address") + +To send e-mail messages by SMTP, the following is necessary. + + (setq mew-smtp-server "your SMTP server") ;; if not localhost + +If you want to use POP to receive e-mail messages, the followings are +necessary. + + ;; (setq mew-pop-user "your POP account") ;; (user-login-name) + (setq mew-pop-server "your POP server") ;; if not localhost + +If you want to use a local mailbox to receive e-mail messages, the +followings are necessary. + + ;; To use local mailbox "mbox" or "maildir" instead of POP + (setq mew-mailbox-type 'mbox) + (setq mew-mbox-command "incm") + (setq mew-mbox-command-arg "-u -d /path/to/mbox") + ;; If /path/to/mbox is a file, it means "mbox". + ;; If /path/to/mbox is a directory, it means "maildir". + +If you want to use IMAP to receive e-mail messages, the followings are +necessary. + + (setq mew-proto "%") + ;; (setq mew-imap-user "your IMAP account") ;; (user-login-name) + (setq mew-imap-server "your IMAP server") ;; if not localhost + +To read and/or write articles of NetNews, the followings are +necessary. + + ;; (setq mew-nntp-user "your NNTP account") + (setq mew-nntp-server "your NNTP server") + + + + +File: mew.info, Node: password, Next: start, Prev: configuration, Up: Overview + +Password +======== + +When fetching/sending messages or using PGP or S/MIME, you may be +required to input your password. Before you type your password, check +carefully to see if either the following conditions is satisfied: + + - Emacs is running on a local computer + - Emacs is running on a remote computer, but an encryption + mechanism is being used for communication. + +If neither of these conditions are satisfied, do not input a +password. Your password could be accessed without your knowledge. + +If you get sick of inputting your password from time to time, please +use one of two password-cache mechanisms. + + 1. Storing passwords in memory temporarily. Not writing them to a + file. + 2. Storing passwords in memory while Mew is running. When Mew/Emacs + quits, Mew encrypts the passwords and writes them to a file. + +To use Feature 1., configure as follows: + + (setq mew-use-cached-passwd t) + +To use Feature 2., after installing GnuPG, configure as follows (GnuPG +version 1.x, 2.0 and 2.1 are supported for this feature): + + (setq mew-use-master-passwd t) + +If both variables are `t', the feature 2. is used. + +Feature 1.: Any passwords including POP and PGP are cached in +memory. While a password is cached, you can omit to input the +password. The cached password will expire after a certain period (20 +minutes by default). However, its timer is cleared (reset to 20 +minutes) if the password is used internally. + +Feature 2: When Mew boots, Mew asks you to input a master password. +Mew decrypts encrypted passwords in a file and caches them in memory. +For instance, if you have already typed POP password, it is to be +stored in memory. Thus, when the POP password is required, you can +omit to input it. If you use a master password at the first time, you +are asked to input it twice. When Mew boots, you might type a wrong +master password. In this case, if you enabled Feature 1., it is +used. Otherwise, no password-cache mechanisms is used. + +If you want to change the master password, type `C-cC-m' in Summary +mode. + +Cached passwords in memory are not encrypted. So, if you use either +Feature 1. or Feature 2., you should take care so that nobody can +touch your Emacs. If you leave your PC and an Emacs expert happens to +check your configuration, your passwords could be stolen. + + + + +File: mew.info, Node: start, Next: Viewing, Prev: password, Up: Overview + +Starting +======== + +To start Mew, you can choose one of the following: + +`M-x mew' + Execute Mew first unless Mew is running. And retrieve arrived + messages or just visit to the default folder. + + `proto' is determined by `mew-proto' and the "case" (see + *Note config::). + + If `proto' is `+' (i.e. a local folder), a mailbox is determined + according to `mew-mailbox-type' (see *Note retrieving::). + Otherwise (i.e. a remote folder), an appropriate protocol to + retrieve messages is chosen according to `proto'. + + If `mew-auto-get' is `t', arrived messages are asynchronously + fetched and listed up in Summary mode. + + `mew-auto-get' is `nil', just visit to the folder determined by + `proto'. +`C-uM-x mew' + Perform `M-x mew' with `mew-auto-get' reversed. +`M-x mew-send' + Enter Draft mode for message composing. +`C-xm' + Enter Draft mode for message composing if `mail-user-agent' is + configured. + +When Mew is executed on Emacs, two cute cats appear on the cover page. + +For the methods of quitting Mew, please refer to *Note Quit::. + + + + +File: mew.info, Node: Viewing, Next: singlepart, Prev: start, Up: Top + +Viewing messages +**************** + +If you input `M-x mew' (regardless Mew is running or not), Mew +displays a list of message like this: + + * 03/12 Hidenori Ohta This weekend |Let's go to StoneMagic + M03/14 Momo-chan The pictures of Noto |Attached are the pictu + 03/15 Neat Sumikawa Re: wine |OK. I vote for Wednesd + +This is called Summary mode. This section mainly explains how to read +messages in Summary mode. + +As you can see the example above, the format of Summary mode consists +of a mark, data type (a mark by Mew), date, a sender, Subject:, and a +body. + +For the method of terminating Summary mode, please see *Note Quit::. + +* Menu: + +* singlepart:: Reading Basis +* multipart:: Displaying MIME +* analysis:: Controlling MIME analysis +* cipher-viewing:: Visualizing cipher or signature +* retrieving:: Getting messages +* moving:: Moving to another folder +* sum-write:: Write, answer, and forward +* features:: Useful features +* status-update:: Updating status +* invalid:: Invalid messages + + + +File: mew.info, Node: singlepart, Next: multipart, Prev: Viewing, Up: Viewing + +Reading Basis +============= + +To read messages in the order of their arrival, type `SPC' to display +them. That's it. It's easy, isn't it? + +Yet this might not be comprehensive, so the basic commands for page +processing are listed as follows: + +`SPC' + Read through messages. That is, display a message, scroll it, and + move-then-display another message. refer to *Note summary-mode:: + to know which direction the cursor moves. +`C-uSPC' + Redisplay the message from its header. +`DEL' + Back-scroll this message. Unnecessary header fields are hidden + over the window. Type `DEL' to see them when a message is + displayed. +`RET' + Make this message scroll up one line. +`M-RET' +`-' + Make this message scroll down one line. + +`C-n' + Go to the next line. +`C-p' + Go to the previous line. +`n' + Move down then display. Targets include parts, messages marked with + `*', and non-marked messages. +`C-un' + Move down then display. Targets include messages marked with `*', + and non-marked messages. +`p' + Move up then display. Targets include parts, messages marked with + `*', and non-marked messages. +`C-up' + Move up then display. Targets include messages marked with `*', + and non-marked messages. +`j' + Jump to a line according to the line number which you input. +`C-uj' + Jump to a message according to the message number which you + input. + + + +File: mew.info, Node: multipart, Next: analysis, Prev: singlepart, Up: Viewing + +Displaying MIME +=============== + +It's not difficult to read a multipart message. As usual, just type +`SPC'. + +A multipart message is marked with `M' on the left side of date as +follows: + + * 03/12 Hidenori Ohta This weekend |Let's go to StoneMagic + M03/14 Momo-chan The pictures of Noto |Attached are the pictu + 03/15 Neat Sumikawa Re: wine |OK. I vote for Wednesd + +When you type `SPC' on the message marked with `M', its header is +displayed in Message mode. Then its multipart structure is displayed +in Summary mode as follows: + + * 03/12 Hidenori Ohta This weekend |Let's go to StoneMagic + M03/14 Momo-chan The pictures of Noto |Attached are the pictu + B 2 Image/Jpeg picture 1 noto1.jpg + Q 3 Application/Postscript Note map map.ps + 03/15 Neat Sumikawa Re: wine |OK. I vote for Wednesd + +If the first part is Text/, the first part is not displayed in Summary +mode but the first part is displayed with its header in Message mode. + +Each line of multipart consists of + + - marks (Content-Transfer-Encoding:) + - part number + - data type (Content-Type:) + - description (Content-Description:) + - file name (Content-Disposition:). + +Content-Description can be considered Subject: for each part. This +format is very similar to that of the attachment region in Draft mode. + +If you type `SPC' or `n', the cursor moves onto part 2 and the content +is displayed according to its data type. For instance, Text/Plain is +showed in Message mode and PostScript is visualized with "ghostview". + +Please note that `n' and `p' move lines including multipart. +To display the message below skipping multipart, type `C-un'. +Likewise, to display the message above (not this message), input +`C-up'. + +Mew processes MIME recursively. The following example is a forwarded +multipart message. + + M03/15 Kazu yamamoto Fw: The pictures of Noto |Attached are the pictu + 2 Message/Rfc822 The pictures of Noto + B 2.2 Image/Jpeg picture 1 noto1.jpg + Q 2.3 Application/Postscript Note map map.ps + +Note: We strongly recommend that you not embed any object other than +text as a top level single part to a message directly. Instead, it is +better to make a multipart message whose part 1 is a textual +description of part 2 and part 2 is a non-text object. + +A message which contains a single part other than text is displayed as +multipart. + +Since the syntax of MIME messages can be complex, it sometime takes a +bit of time to analyze the syntax. However, Mew guesses the message to +be read next and analyzes it beforehand while the user is reading the +current message. Analyzed messages are temporarily cached. + +To make it clear where the message ends, Mew displays the string "[End +of message]" in the end of the message. At the end of each part, Mew +displays the string "[Message is continued]". These strings are +customized by `mew-end-of-message-string' and +`mew-end-of-part-string', respectively. + + + +File: mew.info, Node: analysis, Next: cipher-viewing, Prev: multipart, Up: Viewing + +Controlling MIME analysis +========================= + +There are several variables for controlling message analysis. + +`mew-file-max-size' + The size limit of messages to be analyzed. If the size of a + message is less than or equal to this value, it is analyzed and + displayed. Otherwise, the raw message is displayed without + analysis. The default value is 10000 bytes. +`mew-header-max-length' + The length limit of header to be analyzed. If the length of a + header is less than or equal to this value, it is analyzed and + displayed. Otherwise, the message is displayed as fragmentarily + since the analysis is stopped. The default value is 100 lines. +`mew-decode-broken' + Whether Mew be liberal or conservative to invalid messages. If the value + is `t', the setting is liberal. If the value is `nil', the + setting is for conservative. If conservative and invalid portions are + found, they are reported in the X-Mew: field. The default value is + `t'. +`mew-use-text-body' + Whether or not the text part of a body is displayed with its + header. If the value is `t', both the body which is a single part + text and the first text part in a multipart body are displayed + with its header. If the value is `nil', they are displayed as a + single part in a multipart. The default value is `t'. +`mew-use-alternative' + How to treat Multipart/Alternative. Messages containing + Multipart/Alternative are marked with `-'. If the value is + `t', one part is displayed according to the preference defined in + `mew-mime-multipart-alternative-list'. If the value is + `nil', it is displayed as a multipart. The default value is + `t'. +`mew-use-text/html' + How to treat Text/Html. If `nil', HTML is displayed as is + (without parsing). Otherwise, HTML is parsed and displayed. The + default value is `nil'. +`mew-use-text/xml' + How to treat Text/Xml. If `nil', XML is displayed as is (without + parsing). Otherwise, XML is parsed and displayed. The default + value is `t'. + +The basic command relating to the variables above is `.'. The command +acts as follows: + +1) If this command executed on a message, the cache of the message is +removed and the message is analyzed then displayed. + +1a) If the size of the current message exceeds `mew-file-max-size', +MIME analysis is skipped then the beginning of the raw message is +displayed. In this situation, this command analyzes the current +message without the limitation then displays it. + +1b) If the length of a header exceeds `mew-header-max-length', a +broken message is displayed. In this situation, this command analyzes +the current message without the limitation then displays it. + +1c) If the current message is displayed by `:', the multipart +structure is displayed different from the normal display. In this +situation, this command gets the multipart structure back to the +normal display. + +1d) If `mew-use-text/html' is `nil', its HTML body is displayed as +is. In this situation, this command analyzes the HTML body and +displays it. + +2) If this command is called on a part, the part is displayed again. + +2a) If 'mew-use-text/html' is `nil', its HTML part is displayed as +is. In this situation, this command analyzes the HTML part and +displays it. + +In addition to `.', the following commands are prepared: + +`.' + Analyze the message and re-display it. +`C-u.' + Analyze the message with `mew-decode-broken' reversed (see + *Note invalid::). +`:' + The same as `.' with `mew-use-alternative' and + `mew-use-text-body' reversed. +`C-u:' + The same as `C-u.' with `mew-use-alternative' and + `mew-use-text-body' reversed. +`,' + Insert a message or a part into Message mode in raw format. +`C-cTAB' + Open an entire message as a file in read-only mode. +`C-uC-cTAB' + Open an entire message as a file. + + + +File: mew.info, Node: cipher-viewing, Next: retrieving, Prev: analysis, Up: Viewing + +Visualizing cipher or signature +=============================== + +Basic commands such as `SPC' visualize messages signed or encrypted as +well. Let's start with a simple example: + + S03/18 Kanda PC shop A written estimate |Here is a written esti + E03/21 Anonymous Secret message | + +Messages above are marked with `S' and `E', respectively. This means +that the body of the first message is signed and that of the second +message is encrypted. + +PGP/MIME and/or S/MIME also allow to sign and/or encrypt some parts of +a message. In this case, these marks do not appear. The `S' or `E' +mark appears only when the entire body of the message is signed or +encrypted. + +The terms "sign" and "encrypt" used above mean the last procedure +applied the body is "sign" and "encryption", respectively. The above +examples may have been produced with more complex processes. For +instance, in the case of the former message, the body may have been +signed after encrypting the body. It is likely that some part of the +latter message was first signed then the body was encrypted. + +If some parts or the entire body is encrypted, Mew asks you to input +your pass-phrase to get plain text. Please refer to *Note start:: to +know what you should pay attention when inputting pass-phrase. The +pass-phrase is used to decrypt your secret key. The secret key is then +used to decrypt cipher text. + +To visualize a cipher message, you need to input your pass-phrase +every time you encounter cipher text. This is because Mew does not +cache pass-phrases anywhere for security reasons. If you feel this is +inconvenient, you can configure Mew to cache your pass-phrase. Please +refer to *Note password:: for more information. + +Since decrypted messages are cached for a while, you may not be asked +for your pass-phrase at the next time you display the message, even if +you are not using the pass-phrase cache. + +To verify signatures, senders' public keys are used. Hence you are not +asked to type your pass-phrase. + +Since Mew automatically verifies signatures and/or decrypts cipher +text with a pass-phrase, it is likely that users do not notice that +the original message has signatures and/or which parts were encrypted. + +To inform users the results of verification of signatures or which +parts were decrypted, Mew inserts the X-Mew: field in the header as +follows: + + X-Mew: PGP decrypted. + Good PGP sign "kazu@example.org" COMPLETE + +The number enclosed by "<>" indicates which part was protected with +PGP. "body" means the body was protected. This example tells us that +the body was singed by kazu then encrypted for the reader. Mew first +decrypted the message and then verified its signature of the decrypted +message. The fact that the signature is valid indicates that no one +has modified the content of the message since it was signed by the +secret key whose ID is kazu@example.org. The validity of the public +key used to verify the signature is "complete". Thus, the receiver can +be sure that the public key actually belongs to the user indicated by +the ID. That is, this message was verified by a reliable public key +AND its results were correct, so no alternation was found. + +In the following example, the signature of the body (multipart), is +first verified, then part 2 (a message), is decrypted. That is, the +composing process was that part 2 is first encrypted then the entire +body is signed. + + X-Mew: Good PGP sign "kazu@example.org" COMPLETE + X-Mew: <2 message> PGP decrypted. + +Intelligent users may wonder what happens in the case where a devious +person sends a message that contains an invalid X-Mew: field. This is +not a problem. First Mew carefully removes the X-Mew: field, and then +inserts a valid X-Mew: field into the header. + +About PGP/MIME: + +X-Mew: informs the user of various other types of results. For +example, the lack of availability of a public key, decryption +failures, etc. The following example indicates the absence of a public +key whose key ID is 0x1B8BF431. + + X-Mew: No his/her public key. ID = 0x1B8BF431 + +In this case, if you type `C-cC-f', Mew tries fetching this public +key. You can interactively select a public key server. If the X-Mew: +field does not exist, `C-c C-f' takes the From: field as ID. Also, +`C-uC-cC-f' extracts key IDs from fields specified in +`mew-x-pgp-key-list' in addition to the X-Mew: field, and then tries +to fetch them. + +Mew supports PGPv2, PGPv5, and GNUPG. You can select one of these by +typing `C-cC-v' in Summary mode. If you want to use those PGPs, you +should set the command name of PGPv2, PGPv5, and GNUPG to +`mew-prog-pgp2', `mew-prog-pgp5', and `mew-prog-gpg', +respectively. Also, set the default PGP name to `mew-prog-pgp'. Note +that pass-phrases are cached independently for each PGP. + +Old fashioned PGP messages cannot be processed automatically. You can +decrypt and/or verify this kind messages with `C-cC-z'. + + + +File: mew.info, Node: retrieving, Next: moving, Prev: cipher-viewing, Up: Viewing + +Getting messages +================ + +To copy arrived messages to your mailbox to +inbox and list up a list of +the messages, use `i'. The mailbox is determined according to +`mew-mailbox-type'. (When you type `M-x mew' and if +`mew-proto' is `+', messages are also copied according to +`mew-mailbox-type'.) Here are summary of its values. + +`'mbox' + A local mailbox. "incm" is used to copy messages for the local + mailbox by default. To know how to configure it, see *Note + configuration::. +`'pop' + A POP server. To use POP as it is. (This is a default value.) +`'imap' + An IMAP server. This is not recommended. + +To flush a list of messages in a local folder and display them again, +use `s'. + +To retrieve messages or flush-then-retrieve messages again in a remote +folder, type `s'. It is recommended to use `s', not `i', for IMAP and +NetNews. + +If you use `s', it asks you a range. Here are a summary of important +ranges for Mew. + +`update' + From "the last message in the Summary mode + 1" to "the last + message in the corresponding folder". That is, the gap between + the Summary mode and the existing folder +`all' + All messages in the folder. When Summary mode in a local folder + becomes inconsistent, use this range to flush the list. For a + remote folder, this range results in retrieval of all messages + again. +`sync' + Deleting cache messages whose originals were removed in the + server side. Valid for remote folders only. + +The default range both for +draft, +queue, and +postq is `all'. For +other folders, the default is `update'. So, just type `RET' after `s' +to get the up-to-date list of the current folder except +draft, ++queue, and +postq. + +Although they are not especially important in Mew, you can specify the +following ranges: + +`-' + From to . Valid for local folders only. +`-' + From to the last. Valid for local folders only. +`-' + From the first to . Valid for local folders only. +`last:' + Last messages. + +If you execute `s' with `C-u' on a remote folder, you can +toggle "copying a header only" and "copying both a header and a body". +This action can be defined by `mew-pop-header-only', +`mew-imap-header-only', and `mew-nntp-header-only' for POP, +IMAP, and NNTP, respectively. The default values of these are +`nil', that is, "copying both a header and a body". + +Messages that are of large size may be truncated. This kind of message +is marked with `T'. To retrieve the rest of this kind of message, type +`I' on the message. + +Suppose that there is a message marked with `T' in $inbox. If you type +`I' on it, you can retrieve the entire message. + +Here is a summary of the commands concerned with message retrieval: + +`i' + In a local folder, fetch arrived messages, store them to the +inbox + folder and create a list. If `mew-auto-flush-queue' is `t', + send messages in +queue. Please refer to *Note send:: for more + information. In a remote folder, visit to its inbox folder and execute + `s' + `update'. +`C-ui' + Perform `i' with `mew-auto-flush-queue' reversed. +`I' + Retrieve the rest of a truncated(`T') message. + + If you use this command in a local folder, a method to retrieve + the message is determined by the "case" and + `mew-mailbox-type'. If `mew-pop-delete'/`mew-imap-delete' is `t', + delete the message from the mailbox. + + If you use this command in a remote folder, a "case" and protocol + is determined by the folder. The message in the server side is + always retained. +`C-uI' + Perform `I' with `mew-pop-delete' or `mew-imap-delete' reversed. +`s' + List up messages in Summary mode or flush them. +`C-us' + On a remote folder, list up messages in Summary mode by toggling + "copying a header only" and "copying both a header and a body". +`lc' + Copy a cached message in a remote folder to a local folder. + + + +File: mew.info, Node: moving, Next: sum-write, Prev: retrieving, Up: Viewing + +Moving to another folder +======================== + +To go to another folder, type `g'. Mew asks you to input a folder name +as follows: + + Folder name (+inbox): + + +Let's call the right side of ":" 'writable area'. In this example, +proto "+" is displayed in the writable area. Typing an appropriate +string following proto and typing `RET' decides a folder name, then +Mew moves to the folder. + +When you move to a folder and if Mew finds its list of messages old, +Mew automatically displays the differences. + +The string in "()" is a default. If you specifies "+" by simply typing +`RET', Mew considers that the default folder name is specified. + +To make use of completion, type `TAB' or `SPC'. + +Now, lets get back to the state just after typing `g'. + + Folder name (+inbox): + + +If you want to change, for example, "+" to "%", you have to delete "+" +first then type "%" in normal situation. But this is inconvenient. So, +typing "%" just after "+" removes "+" automatically. Like this, typing +another proto just after a proto replaces the previous one without +deletion. + +When you type a remote folder, you may want to specify the "case" +(described in *Note config::). The "case" must be specified before a +folder, separated by ":". Consider moving "%inbox" for a "case" +"home". In this case, you should type "home:%inbox". Yes, this is +inconvenient. So, typing `C-cTAB' in any position does circular +completion for available "cases". Let's look at the following example. + + Folder name (+inbox): %inbox + +Typing `C-cTAB' here results in the following: + + Folder name (+inbox): home:%inbox + +You may want to search a folder by specifying a substring of the +folder. For this purpose, `C-s' and `C-r' are available. The +following is the state of the minibuffer after typing `C-s'. + + Folder name (+inbox): () + +"()" appeared in the writable area indicates you have switched to +search mode. While you are typing here, a matched candidate is shown +in "()". The following is the case where a search key is "mew". + + Folder name (+inbox): (+work/mew-release) mew + +To select the matched candidate, type `RET'. Then the search mode is +finished and the matched candidate is displayed in the writable area. + + Folder name (+inbox): +work/mew-release + +Typing `RET' again means that you decide the folder. + +A list of folders to be searched is decided by a combination of "case" +and proto. When you enter the search mode by typing `C-s' or `C-r', a +pair of "case" and proto is extracted from the writable area, and a +list of folders is selected according to the pair. + + + +File: mew.info, Node: sum-write, Next: features, Prev: moving, Up: Viewing + +Write, answer, and forward +========================== + +Please use the following commands for writing, replying, and +forwarding messages. + +`w' + Write a message. A new draft is prepared in Draft mode. Please refer to + *Note Composing::. +`C-uw' + Write a message. A new draft is prepared in Draft mode. The From: + address of the current message is copied to the To: field in the + draft. +`W' + Send a message by modifying a part of the header of another + message. Please refer to *Note resend::. +`a' + Answer to this message. A new draft is prepared in Draft + mode. Mew automatically inserts the content of the fields To: and + Cc:. Please refer to *Note reply::. +`C-ua' + Answer to this message only to the sender. +`A' + Answer to this message. A new draft is prepared in Draft + mode. Mew automatically inserts the content of the fields To: and + Cc: and cites the body. Please refer to *Note reply::. +`C-uA' + Answer to this message only to the sender with citation. +`f' + Forward this message to a third person. A new draft is prepared in Draft + mode and this message is automatically attached. Please refer to + *Note forward::. +`F' + Forward messages marked with `*' to a third person. A new draft is + prepared in Draft mode and this message is automatically attached. For + more information, refer to *Note target mark::. Please refer to + *Note forward::. + +If an error message returns, please try again with the following +commands. + +`E' + Edit this message again to retry sending. Or edit this RFC822 + part typically included in a MIME-encapsulated error message. + + 1. In +draft, the message is just edited. + 2. In +queue or +postq, the message is moved to +draft and is + edited. + 3. Otherwise, the message is copied to +draft and is edited. + + For +draft, +queue, and +postq, the "case" revives. + + For the other folders, if `mew-case-guess-when-prepared' is `t', + each field of the original header is replaced according to a + guessed "case". For more information, see *Note config::. +`C-uE' + The same as `E'. But, when used for other folders than +draft, + +queue, and +postq, the original header is retained even if + `mew-case-guess-when-prepared' is `t'. + + + +File: mew.info, Node: features, Next: status-update, Prev: sum-write, Up: Viewing + +Useful features +=============== + +Mew provides you with the following useful commands in Summary mode: + +`v' + Toggle "Summary mode only" and "Summary & Message mode". If you + choose "Summary mode only", you can quickly put the `D' mark + since the next message is not displayed. +`_' + Toggle normal lines, wrapped lines and long lines. +`zv' + If `mew-use-header-veil' is non-nil, field lines of To: and Cc: + over `mew-header-veil-count' are covered with invisible + veils. This commands toggles visibility of these lines. + `mew-use-header-veil' and `mew-header-veil-count' are default to + `t' and 4, respectively. +`M-l' + Make the current line the center of the Summary mode. +`C-cC-s' + Incremental search forward in Message mode. +`C-cC-r' + Incremental search backward in Message mode. +`y' + Save this message or this part into the file whose name is + specified by you. +`b' + Save the buffer of Message mode as is into the file whose name is + specified by you. +`C-uy' + Save this message or this part into the file whose name is + specified by you, specifying coding-system for text. +`#' + Print the content of Message mode according to + `mew-print-function'. +`C-u#' + Print the content of Message mode with a specified printer name. +`|' + Send the content of Message buffer to a command via pipe. +`C-u|' + Send the body of Message buffer (excluding its header) to a + command via pipe. +`\' + Executing an external command specifying this message as an + argument. +`B' + De-capsulate embedded messages in MIME format. +`C-uB' + Decompose embedded files in this message. +`C-cC-a' + Register the information on the current message to Addrbook + (*Note addrbook::). +`C-cC-v' + Select PGP version (*Note cipher-viewing::). +`C-cC-z' + Let PGP decrypt and/or verify old fashioned PGP messages (*Note + cipher-viewing::). +`C' + Change the value of the "case". For more information, please refer to + *Note config::. +`=' + Display the folder name of this message and the message + number. If this is a cache message, both the unique id and the + size are also shown. The full path to the message is set to the + cut buffer of your window manager. +`;' + Parse the Received: fields and display them in Message mode. +`Rd' + Delete this folder. +`Rr' + Rename this folder. + + + +File: mew.info, Node: status-update, Next: invalid, Prev: features, Up: Viewing + +Updating status +=============== + +In some cases of configuration modifications, you have to update +status to reflect them. When you think configuration modifications +don't make any effects or some errors occur, use one of the following +commands: + +`Z' + Update information including Addrbook (*Note addrbook::). +`C-uZ' + Update information about folders of the current world. + +Here is a summary of toggle commands. + +`z8' + Toggle 8bit mode (i.e. `mew-use-8bit'). +`zc' + Clean-up caches of analyzed messages. +`zd' + Toggle `mew-debug'. +`zo' + Toggle PGP/MIME or old-fashioned PGP (`mew-use-old-pgp') when + composing with shortcut methods. +`zp' + Toggle decode policy (i.e. `mew-decode-broken'). +`zv' + Toggle whether or not veil is used in Message + mode(`mew-use-header-veil'). +`zw' + Toggle warning level. If `mew-warning-field-level' is 2, set it + to 1. If `mew-warning-field-level' is 1, set it to 2. + + + +File: mew.info, Node: invalid, Next: Composing, Prev: status-update, Up: Viewing + +Invalid messages +================ + +The following message contains Japanese text in its body. The charset +parameter is not specified in the Content-Type: field. So, the body +should be treated as US-ASCII. + + To: piglet + Subject: an invalid message + From: pooh + MIME-Version: 1.0 + Content-Type: Text/Plain + + Japanese comes here. + +The following header is invalid as well. + + From: "=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?=" + +The string delimited by "=?" and "?=" in the above example was +originally Japanese. Since the spec of mail limits the content of +headers to ASCII characters, if a string whose character set is other +than ASCII, is to be stored in a header, the string must be encoded +with ASCII strings according to the defined rule. But it is certainly +invalid to embed the ASCII strings with `"'. Strings surrounded by `"' +are treated as is. Therefore, the string between "=?" and "?=" in the +example will not be decoded into Japanese. + +Several mailers are careless about the spec and regularly violate +these rules. The right way to do is ask the programmers of such +mailers to make the programs conformant to the spec. However, since +there are so many mailers of this kind around the world, Mew tries to +decode as many different formats as possible. In these cases Mew +displays warnings such as: + + X-Mew: Charset for body is not specified. + To: has encoded-words in quoted text. + +If you want to decode messages strictly, set `mew-decode-broken' to +`nil'. This value can be toggled dynamically by `C-u.' (see +*Note singlepart::). + +The following message is displayed as a mess since the character set +specified with the charset parameter and the actual character set of +its body are different. + + Content-Type: Text/Plain; charset=ISO-2022-JP + + Japanese text written in Shift_JIS + +By using `C-cC-l', the text is re-displayed with charset guessed +according to a specified language, ignoring the character set +specified by the charset parameter. If you type `C-uC-cC-l', you can +re-display the text by specifying a character set explicitly. + + + + +File: mew.info, Node: Composing, Next: header, Prev: invalid, Up: Top + +Composing messages +****************** + +This section explains how to compose a message. + +Methods to enter Draft mode to write a new message are given below. + + 1. Type `M-x mew-send'. + 2. Type `C-xm' if `mail-user-agent' is configured. + 3. Press `w' in Summary mode. + +Then a buffer like the following is prepared. + + To: + Subject: + From: Kazu Yamamoto + X-Mailer: Mew version 6.7 on Emacs 24.4 + ---- + +We call this "Draft mode". In Draft mode, we call the region above +"----" the header, and the region below "----" the body. + +Also, replying a message (`a' or `A') and/or forwarding messages (`f' +or `F') lead you to Draft mode from Summary mode. + +Drafts are temporarily stored in the +draft folder. You can write +multiple messages simultaneously. + +For the method of deleting a prepared draft, please refer to +*Note Quit::. + +Now let's see how to use Draft mode. + +* Menu: + +* header:: Completions in a header +* cheader:: Circular completions in a header +* addr-comp:: Address Completion +* addrbook:: Address book +* auto-alias:: Learning addresses +* addr-comp1:: Address Completion(1) +* addr-comp2:: Address Completion(2) +* send:: Sending a message +* cite:: Signature and citation +* mime-comp:: Composing multipart +* charset-guess:: Defining charset +* longline:: Handling long lines +* reply:: Replying to a message and deciding recipients +* forward:: Forwarding messages +* resend:: Re-sending messages +* shortcut:: Creating signature or cipher message +* mark-b-comp:: Mark based composer +* pgp-key:: PGP key distribution +* anonymous:: Sending messages with anonymous receivers + + + +File: mew.info, Node: header, Next: cheader, Prev: Composing, Up: Composing + +Completions in a header +======================= + +In the header, completions for each field are assigned to `TAB' as +follows: + + - Field completion + - Address completion (To:, Cc:, etc) (see *Note addr-comp::) + - Folder completion (Fcc:) + + + +If the cursor is at the beginning of a line and the previous line does +not end with ",", you can complete field defined in the +`mew-fields' variable with `TAB'. + + To: kazu@example.org + R`TAB' + +At the point above, if you type `TAB', you get: + + To: kazu@example.org + Reply-To: + + + +At a point, such as Fcc:, you can complete folder name with +`TAB'. For example: + + Fcc: `TAB' + +Here, "+" is completed. + + Fcc: +`TAB' + +One more type of `TAB' shows candidates. Please type in the +appropriate characters then type `TAB'. + + Fcc: +b`TAB' + +If a single candidate can be determined, you get a completion. + + Fcc: +backup + + + +File: mew.info, Node: cheader, Next: addr-comp, Prev: header, Up: Composing + +Circular completions in a header +================================ + +In a header, circular completions are assigned to `C-cTAB'. Circular +completion means that a value of a list is replaced by the next value +of the list. The end of the list is considered continuous to the top +of the list. Circular completions in a header are different for each +field as follows: + + - Circular completion of domain name (To:, Cc:, etc) + - Circular completion of From: (From:) + + + +On a field where addresses are written, use `C-cTAB' for domain +completion. Candidates are selected from `mew-mail-domain-list'. + + To: kazu@`C-cTAB' + +If you try to complete just after "@" as up above, the first domain of +`mew-mail-domain-list' is inserted. + + To: kazu@example.org`C-cTAB' + +After completion, pressing `C-cTAB' one more times inserts the next +domain of `mew-mail-domain-list'. This completion is looped. + + To: kazu@example.jp + +If a single candidate can be determined, it is inserted. + + To: kazu@w`C-cTAB' + +The above example gives: + + To: kazu@example.jp + + + +In Draft mode, the From: field is inserted with the format of +"mew-name ". + + From: Kazu Yamamoto + +On the From: field, `C-cTAB' circularly completes its value from +`mew-from-list'. You can set `mew-from-list' by yourself. Also, +`mew-from-list' can be set automatically. For automatic setup, please +refer to *Note config::. + +Typing `C-cTAB' anywhere on the value replaces the value with the next +value of `mew-from-list'. For example, + + From: Kazu Yamamoto `C-cTAB' + +becomes as follows: + + From: Kazuhiko Yamamoto + + + +File: mew.info, Node: addr-comp, Next: addrbook, Prev: cheader, Up: Composing + +Address Completion +================== + +You can complete addresses on To: or Cc:. This completion command is +bound to `TAB'. + + To: kazu`TAB' + +When you type `TAB' after a part of an address as the example above, +the entire address is completed as follows: + + To: kazu@example.org + +There are three kinds of registered addresses to be used for the +completion. + + 1. The expansion rule in an address book + 2. The personal information in the address book + 3. Learned addresses when sending + +Mew provides two ways to complete addresses. You can select one of +them with `mew-use-full-alias', which is default to `nil'. + +If `mew-use-full-alias' is `nil', the portion before `@', a user name +or a short name, is a target of the completion. When you type `TAB', +the user name is completed. And if the user name is uniquely completed +and you type `TAB' again, it is expanded to its entire address. Let's +call this Address Completion(1). + +An advantage of Address Completion(1) (*Note addr-comp1::) is that you +can use the completion/expansion against the three kinds of addresses +seamlessly. You can also explicitly expand the user name with `TAB' as +described later. A disadvantage is that user names must be unique. So, +if a user name is already registered, other addresses with the same +user name cannot be learned. + +If `mew-use-full-alias' is `t', for learned addresses when sending, +completion target is an entire address. Let's call this Address +Completion(2). + +An advantage of Address Completion(2) (*Note addr-comp1::) is that Mew +can learn addresses whose user names are the same. One of +disadvantages is that only the first address of personal information +can be used (the other addresses are useless). And for the explicit +expansion, you have to type `M-C-e', a different key from +`TAB'. + + + diff --git a/elpa/mew-20150813.2354/mew.info-2 b/elpa/mew-20150813.2354/mew.info-2 new file mode 100644 index 00000000..ba023bce --- /dev/null +++ b/elpa/mew-20150813.2354/mew.info-2 @@ -0,0 +1,1430 @@ +Info file: mew.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew: (mew.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +File: mew.info, Node: addrbook, Next: auto-alias, Prev: addr-comp, Up: Composing + +Address Book +============ + +Mew provides an address book ("~/Mail/Addrbook). The address book has +2 formats. One specifies expansion rules, while the other defines +personal information. + +First, let's look at the format that specifies expansion rules. + + : [, , ,...] + +In this way, you should specify a short name and a full address +separated by `:'. If you want to expand the short name to multiple +addresses, you can delimit them with a comma `,'. (This is exactly +same as addresses delimited by `,' in the To: field, for instance.) A +space SPC is allowed after the comma `,'. For example: + + pooh: winnie-the-pooh@example.net + piglet: piglet@example.org + friends: pooh, piglet + + + +Next, the format to define personal information is shown below: + + [, , ,...] + +In this way, four elements are separated by SPC. is a short +name. and are the person's nickname and full name, +respectively. (For proper usage of the nickname, please refer to +*Note summary-mode:: and/or *Note draft-mode::.) + +The second element is the addresses. If the person has multiple +addresses, delimit them using `,'. SPC is allowed after `,', which +means that it does not function as the delimiter. SPC surrounded by +quotes `"' also has no delimiting function here. For example: + + kazu kazu@example.org, kazu@example.net Kazu-kun "Kazuhiko Yamamoto" + +In the personal information format, you can omit any element. When you +want to omit an intermediate element, specify `*'. The following is an +example to define nicknames for addresses. + + * kazu@example.org, kazu@example.net Kazu-kun + +The nickname is used to replace addresses in Summary mode and to +replace the citation prefix (*Note cite::) in Draft mode. + +The comment letters are `;' and `#'. `;' is valid only +when it appears at the beginning of lines, resulting in the disregarding +of the entire line. The comment marker `#' is valid everywhere. The +strings between `#' and the end of the line are ignored. Also, +`\' means a continuous line. + + + +Summary mode includes the feature of directly registering the +information of the current message into Addrbook. To register a +expansion rule, type `C-cC-a'. + + #If you want to register this entry, type 'C-c C-c'. + #If you want to NOT register this entry, type 'C-c C-q'. + Shortname: kazu + Addresses: kazu@example.org + Comments: + +To register personal information, type `C-uC-cC-a'. + + #If you want to register this entry, type C-c C-c. + #If you want to NOT register this entry, type C-c C-q. + Shortname: kazu + Addresses: kazu@example.org + Nickname: + Name: Kazuhiko Yamamoto + Comments: + +Add or modify the information if necessary. To register this +information, type `C-cC-c'. To quit the registration, type +`C-cC-q'. You should also refer to *Note Quit::. + +If you want to use characters of multiple languages, put the following +onto the beginning of Addrbook. + + #-*-coding:ctext;-*- + + + + +File: mew.info, Node: auto-alias, Next: addr-comp1, Prev: addrbook, Up: Composing + +Learning addresses +================== + +When you send a message, addresses on the To: and Cc: field are +automatically registered. Consider the following: + + To: kazu@example.org + +In the case of Address Completion(1) (*Note addr-comp1::): When this +message is sent, a short name "kazu" is automatically registered for +the address "kazu@example.org". If there is already a short name of +"kazu", the next action is decided according to +`mew-addrbook-override-by-newone'. If `nil', the old entry +remains. Otherwise, the new entry overrides the old one. When +expanded, the address book short name has priority over the automatic +short name. Only automatic short names which are not contained in the +address book are valid. + +In the case of Address Completion(1) (*Note addr-comp2::): When this +message is sent, the address "kazu@example.org" is automatically +registered. + +The limit number of automatic short names is 2000 +(`mew-lisp-max-length'). Once the number exceeds 2000, the tail +entries in the alphabetical order are removed. This information is +automatically saved to the file "~/Mail/.mew-alias". + +The automatic registration would register unnecessary short names. If +you want to remove these entry, take the following steps. First, type +`M-a' to open "~/Mail/.mew-alias". Then edit it as you do against a +text file. Lastly, type `C-xC-s' to save it. When saving it, the +modifications are automatically reflected to Mew. + +The formats of Address Completion (1) and (2) are different. When you +change the value of `mew-use-full-alias' to switch one to the other, +type `Z' once in Summary mode. This converts the format properly. + + + +File: mew.info, Node: addr-comp1, Next: addr-comp2, Prev: auto-alias, Up: Composing + +Address Completion(1) +===================== + +As far as Address Completion (2) is concerned, there is an assumption: +user names or short names of expansion rules, personal information and +learned addresses are unique. + +For example, consider the following configuration of expansion rules: + + pooh: winnie-the-pooh@example.net + +When you are in a header in Draft mode, working within an address +field, after typing one or more characters, you can complete a short +name for an address by pressing the `TAB' key. + + To: piglet@example.org, + po`TAB' + +If you press the `TAB' key, "pooh" is completed (unless other +candidates exist). + + To: piglet@example.org, + pooh`TAB' + +One more press of the `TAB' key expands the name to +"winnie-the-pooh@example.net". + + To: piglet@example.org, + winnie-the-pooh@example.net + +A string ending with "@" is explicitly expanded. Please pay attention +to the following case where similar short names are defined. + + pooh: winnie-the-pooh@example.net + pooh-pooh: pooh-pooh@example.org + +It is obvious that "pooh-" is completed to "pooh-pooh". But if you +input "pooh", Mew cannot tell whether it should be expanded or +completed to "pooh-pooh". Thus, if you want to explicitly complete +"pooh" to "winnie-the-pooh@example.net", insert `@' and type +`TAB'. + + To: pooh@`TAB' + +Explicit expansion can be accomplished by `M-C-e' instead of insertion +of `@'. + +The explanation above can be applied to learned addresses when +sending. + +The format of personal information means that each subsequently +generated address will replace the former one. For example: + + kazu kazu@example.org, kazu@example.net Kazu-kun "Kazuhiko Yamamoto" + +Let's watch how it will be converted: + + To: kazu`TAB' + +Typing `TAB' after "kazu" generates "kazu@example.org". + + To: kazu@example.org`TAB' + +Typing `TAB' after "kazu@example.org" brings about "kazu@example.net". + + To: kazu@example.net`TAB' + +Then "kazu@example.org" will appear again if you type `TAB' +after "kazu@example.net". In this way, each address is replaced +one by one. + +After deciding an address, you can add its full name. + + To: kazu@example.org`M-TAB' + +Like this, typing `M-TAB' replace the address with the following +format. + + To: Kazuhiko Yamamoto + + + +File: mew.info, Node: addr-comp2, Next: send, Prev: addr-comp1, Up: Composing + +Address Completion(2) +===================== + +As far as Address Completion(2) is concerned, for learned addresses +when sending, the entire addresses are completion targets. For +expansion rules in the address book, short names are completion +targets and unique short names are expanded to corresponding +addresses. For personal information in the address book, short names +are completion targets and unique short names are expanded to their +first addresses. + +When you are in a header in Draft mode, working within an address +field, after typing one or more characters, you can complete a short +name or a learned address by pressing the `TAB' key. + +Suppose that kazu@example.org is already learned. + + To: ka`TAB' + +When you type some characters and press `TAB', its address is +completed: + + To: kazu@example.org + +Also suppose that "kazunori@example.jp" is learned. To expand a user +name to "kazu@example.org", you should input "kazu@". To convert it +to "kazunori@example.jp", you need to input "kazun". + +For expansion rules and personal information, `TAB' completes short +names first. You can expand a unique short name to corresponding +address with `TAB'. + +For example, consider the following configuration of expansion rules: + + pooh: winnie-the-pooh@example.net + +Let's complete "pooh": + + To: po`TAB' + +If you press the `TAB' key, "pooh" is completed (unless other +candidates exist). + + To: pooh`TAB' + +One more press of the `TAB' key expands the name to +"winnie-the-pooh@example.net". + + To: winnie-the-pooh@example.net + +A problem occurs when a short name is not unique. Consider the +following example: + + pooh: winnie-the-pooh@example.net + pooh-pooh: pooh-pooh@example.org + +It is obvious that "pooh-" is completed to "pooh-pooh". But if you +input "pooh", Mew cannot tell whether it should be expanded or +completed to "pooh-pooh". Thus, if you want to explicitly complete +"pooh" to "winnie-the-pooh@example.net", type +`M-C-e'. (There is no way to accomplish this with `TAB'.) + + To: pooh`M-C-e' + +This example is explicitly expanded as follows: + + To: winnie-the-pooh@example.net + + + + +File: mew.info, Node: send, Next: cite, Prev: addr-comp2, Up: Composing + +Sending a message +================= + +When you are ready to send a message after completing composition, +choose one of the following two commands. + +`C-cC-m' + Compose a message, put it into +queue or +postq, and leave it for + later sending. +`C-cC-c' + Compose a message and send it. You receive the prompt: "Really + send this message? (y or n) ". Type `y' to send it. + +Let's look at how a message is modified when sent. Please see the +following example: + + To: pooh + Subject: the next Sunday + From: Piglet + X-Mailer: Mew version 6.7 on Emacs 24.4 + ---- + Would you like to play with me next Sunday? + + // Piglet + +This message is modified as follows, for example, if it is put into ++queue or +postq by `C-cC-m'. + + Date: Mon, 13 Mar 2000 19:49:50 +0900 (JST) + Message-Id: <20000313.194950.59499544.piglet@example.org> + To: winnie-the-pooh@example.net + Subject: the next Sunday + From: Piglet + X-Mailer: Mew version 6.7 on Emacs 24.4 + Mime-Version: 1.0 + Content-Type: Text/Plain; charset=us-ascii + Content-Transfer-Encoding: 7bit + + Would you like to play with me in the next Sunday? + + // Piglet + +As you can see, Data: and Message-Id: are added. You should note that +both its data type and its character set are guessed correctly and +added. + +When composing a message using `C-cC-m' and `C-cC-c', you can make use +of a feature that identifies errors in a header. + +Suppose you set `mew-ask-subject' to `t'. If Subject: is +empty, Mew asks you its value. If you want to leave it empty, just type +`RET'. The default value of this variable is `nil'. + +Suppose you set `mew-ask-fcc' to `t'. If there is a folder that +doesn't exist, Mew asks you whether or not you want to create it. If +you want to create it, type `y'. Otherwise, type `n'. If you type `n', +sending is aborted and the cursor returns to the draft. The default +value of this variable is `nil'. + +Mew asks you to input your password for sending if the server requires +user authentication. Historically speaking, passwords are not +necessary to send e-mail messages. This is one reason why e-mail +addresses can be faked. In the near future, passwords are always +required for sending messages as are for receiving messages. + +There are two ways to send messages waiting in +queue. Please note +that both of these are commands in Summary mode. + +`i' + If `mew-auto-flush-queue' is `t', the messages being held in + +queue will be sent after the incoming messages have been received. + This method is appropriate for dial-up environments, since one can save + on connection fees and repeated authentication for sending. + `mew-auto-flush-queue' is default to `t'. +`C-cC-c' + Send messages in +queue. Method is appropriate if you like to + preview composed messages first in +queue and then send them. If + `mew-ask-flush-queue' is `t', you are asked, Flush queue? (y or + n) ". `mew-ask-flush-queue' is default to `nil'. + + + +File: mew.info, Node: cite, Next: mime-comp, Prev: send, Up: Composing + +Signature and citation +====================== + +Next is the explanation of the commands for processing the text in the +body of the message. + +The first one is signature. To insert your signature file +("~/.signature") on the cursor point, type `C-cTAB'. You can define +your own signature file to `mew-signature-file'. Setting +`mew-signature-as-lastpart' and `mew-signature-insert-last', you can +customize the action of `C-cTAB'. + +`C-cTAB' + Insert "~/.signature" on the cursor point. + +The next one is citation. If you use `a' or `A' in Summary mode, a +draft for reply is opened up and Emacs is split into three +windows. The top is Summary mode, the middle is Message mode, and the +bottom is Draft mode. + +Here are the commands for citing text from Message mode to Draft mode. + +`C-cC-y' + Copy and paste a part of a message from Message mode WITH + citation prefix and label. + 1. Roughly speaking, it copies the body in Message mode. For + example, if Text/Plain is displayed, the entire Message mode + is copied. If Message/Rfc822 is displayed, the body without + the header is copied. + 2. If you type `C-uC-cC-y', the header is also copied if + exists. + 3. If an Emacs mark exists, the target is the region between + the mark and the cursor. +`C-cC-t' + Copy and paste a part of the message from Message mode WITHOUT + citation prefix and label. + +The default label and prefix is as follows: + + From: SUMIKAWA Munechika + Subject: Wine + Date: Wed, 23 Jul 1997 11:40:50 +0900 + + > Hi, it's Sumikawa, the guy who's neat from good morning + > to good night. + > + > Talking about the wonderful wine party, I would propose + > Cabernet Sauvignon, Bordeaux, '90. + +In Draft mode, you can cite any text displayed in Message mode. So, +you can cite text from multiple messages easily. Select a message in +Summary mode and display it in Message mode, then cite it in Draft +mode. Please repeat this procedure as you like. Triple windows are +opened for this purpose. + + +When highlighting gets wrong, type `C-cC-l' to re-highlight both the +header and the body + + + +File: mew.info, Node: mime-comp, Next: charset-guess, Prev: cite, Up: Composing + +Composing multipart +=================== + +Now let's see how to create multipart messages. + +When you are writing a message in +draft/1 and type `C-cC-a', the +following lines are inserted at the bottom of the draft. + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + 2 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +"1/" is a temporary directory to create multipart and provides a +location for "~/Mail/attach/1". The part 1, "CoverPage", refers to the +body. Now the entire draft looks like: + + To: mew-dist + Subject: This is header + X-Mailer: Mew version 6.7 on Emacs 24.4 + ---- + This is the body. + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + 2 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +Here we designate three regions as follows: + + * the region above "----" `header' + * the region from "----" to "attachments" `body' + * the region below "attachments" `attachments' + +In Draft mode, the key bindings differ according to the region. + +To `TAB', for instance, the following functions are assigned: + +header + Completions. +body + Insert TAB. +attachments + Do nothing. + +To `c', functions are assigned as follows: + +header + Insert c. +body + Insert c. +attachments + Copy a file. + +The following is a summary of commands in the attachments region. + +`C-p' + Go to the previous file in the current directory. +`C-n' + Go to the next file in the current directory. +`C-f' + Go to the first subdirectory. +`C-b' + Go to the parent directory. +`c' + Copy a file (possibly via networks) on ".". To copy a remote + file, use the "/[user@]hostname:/filepath" syntax. +`l' + Link a file with a symbolic link on ".". If you want to edit the + attached file, you should `c' instead of `l' so that you do not + edit the original file. +`d' + Delete this file or this directory. +`m' + Create a subdirectory (i.e. multipart) on ".". +`f' + Open this file into a buffer. +`F' + Open a new file into a buffer on ".". +`y' + Link the message which is displayed in Message mode on ".". +`e' + Input external-body on ".". +`a' + Sampling voice and insert as audio file on ".". +`p' + Extract the PGP key for the specified user on ".". +`D' + Input a description (Content-Description:). +`T' + Change the data type (Content-Type:). +`t' + Toggle text and binary for the data type. +`I' + Specify input coding-system for a Text/* object. +`C' + Specify output coding-system for a Text/* object. +`P' + Specify a file name (Content-Disposition:) to save this part in the + receiver side. If you type just `RET' without any string, its value + is cleared. Then the file name in the sender side is displayed with + `*'. + +In attachments, data types are guessed by suffix. The currently +supported suffixes are as follows: + + .txt Text/Plain + .html Text/Html + .xml Text/Xml + .rtf Text/Enriched + .css Text/Css + .sgml Text/Sgml + [0-9]+ Message/Rfc822 + .ps Application/Postscript + .pdf Application/Pdf + .doc Application/Msword + .xls Application/Vnd.Ms-Execl + .ppt Application/Vnd.Ms-Powerpoint + .vsd Application/Vnd.Visio + .dat Application/Ms-Tnef + .tar|.tar.|.gz|.Z|.taz|.tgz|.bz2?|.lzh|.zip|.bin|.pgp|.gpg|.exe|.dll + Application/Octet-Stream + .gif Image/Gif + .tiff Image/Tiff + .jpe?g Image/Jpeg + .png Image/Png + .xwd Image/X-Xwd + .xbm Image/X-Xbm + .xpm Image/X-Xpm + .bmp Image/X-Bmp + .pcx Image/X-Pcx + .tga Image/X-Tga + .au Audio/Basic + .wav Audio/X-Wav + .aif?f Auido/X-Aiff + .midi? Auido/X-Midi + .mpga|.mp[23] Audio/X-Mpeg + .mpe?g Video/Mpeg + .mov Video/Quicktime + .avi Video/X-Msvideo + +Please choose an appropriate suffix for the file name so that Mew can +guess its data type. If there is no matched suffix, the data type +specified by `mew-content-type' is chosen. Its default value is +Text/Plain. + + +For instance, if you copy files with `c', the part becomes as follows: + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + B 2 Image/Gif MagicPoint logo mgp.gif + Q 3 Application/Postscript Presentation Material ohp.ps + 4 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +Each line of a multipart message consists of + + - marks (Content-Transfer-Encoding:) + - part number + - data type (Content-Type:) + - description (Content-Description:) + - file name (Content-Disposition:). + +You can change data types (Content-Type:) by pressing `T' at any +time. If the data type is either text (Text/Plain) or binary +(Application/Octet-Stream), you can toggle between them using `t'. + +Please refer to *Note mark-b-comp:: for explanation on changing the +mark (Content-Transfer-Encoding:). You can also insert descriptions +(Content-Description:) by `D'. This description column is overwritten +when encrypted as described in *Note mark-b-comp::. + +Strictly speaking, the fifth column is the copied file name or the +value of Content-Disposition:, namely the file name to which the +receiver saves the part. If Content-Disposition: exists, Mew displays +it. Otherwise, Mew displays the copied file name with `*' +appended. When you copy a file, the file name is specified as +Content-Disposition:. But this is not true for both Message/* and +Multipart/*. To specify Content-Disposition: for Message/*, use +`P'. + +Files are treated as singlepart while directories are treated as being +multipart. Therefore you can create very complex multipart MIME +messages in the same way as you would create a file system. Very easy, +isn't it? + +The default data type for directories is Multipart/Mixed. Of course, +you can change it by pressing `T'. + +Once you are ready to send a multipart message, type `C-cC-m' or +`C-c C-c' to send it as described the previous subsection. + +Next is the explanation of the creation of a Message/External-body by +pressing `e'. If the access-type is "ftp" or "anon-ftp", you can take +advantage of remote filename completion due to the existence of the +native Emacs mode of ange-ftp. Of course file completion is available +for the access-type of "local-file". + +If you want to abort creating multipart and to get back to singlepart, +type `d' in the top level of the multipart message. + + + +File: mew.info, Node: charset-guess, Next: longline, Prev: mime-comp, Up: Composing + +Defining charset +================ + +Mew has a mechanism for determining the character set of the transfer +form for both singlepart and multipart. + + + +When you type `C-cC-m' or `C-cC-c' to compose a message in Draft mode, +Mew decides the character set of the transfer based on the internal +representation of its body. On Bilingual Emacs, US-ASCII is chosen for +7bit character sets while ISO-8859-1 is selected for 8bit character +sets. On Internationalized Emacs, the character set of the transfer +form is chosen based on rules defined by Mew. + + + +Since the data to be attached as a part of multipart is a file, it is +stored on disk. Therefore, in order to determine its character set for +the transfer form, it is necessary to load the file into an Emacs +buffer converting it into internal representation. After that, Mew +determines the character set of the transfer form for the file by the +same method as singlepart. + +On Bilingual Emacs, Mew reads a file as is. So if the file is 7bit, +US-ASCII is chosen. Otherwise ISO-8859-1 is selected. + +On Internationalized Emacs, Mew reads a file according to the local +convention (i.e. auto conversion). The command to set a local +convention is `C-x RET l'. + +For example, in Japan, ISO-2022-JP, EUC-JP, and Shift_JIS is readily +guessed and stored in buffer as internal representations for +Japanese. Mew chooses ISO-2022-JP as the character set of the transfer +form from the internal representation. That is, even if the character +set of the file is EUC-JP or Shift_JIS, it is automatically converted +into ISO-2022-JP, which is the transfer form for Japanese. This means +that you can attach a file without needing to pay attention to its +character set. + +If you want to specify the coding-system of a file to be attached, type +`I'. Let's call the character set "input character set". Also, if +you want to specify the coding-system of the transfer form, use +`C'. + +Information regarding the character set is displayed in +parentheses. If the character set of the transfer form is specified +explicitly, it is displayed. Otherwise, if the input character set is +specified, it is displayed with "*". Otherwise, "guess" is displayed. + +Let's look at the following example. Since part 1 is a body, it is +stored in an Emacs buffer. Because "guess" is displayed, it is Mew +that determines the character set of the transfer form according to +the rules that Mew defines. + +Since iso-8859-1 is specified as the input character set, Mew loads +the file considering that its character set is iso-8859-1, and then +converts it into internal representation. The character set of the +transfer form is decided according to rules defined by Mew. + +The input character set in part 3 cannot be identified just from this +example. (But a user certainly knows what it is since he actually +specified it.) In any case, a file will be loaded and be converted +into internal representation, then be converted into EUC-JP which is +specified as the character set of the transfer form. + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + 2 Text/Plain(*iso-8859-1) text1 + B 3 Text/Plain(euc-jp) text2 + 4 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +Note that both `C' and `I' are not available on Bilingual Emacs. + + + +File: mew.info, Node: longline, Next: reply, Prev: charset-guess, Up: Composing + +Handling long lines +=================== + +For a long period, when you are writing a message, you should fold +each line around 70 characters by yourself. RFC 3676 extended +Text/Plain and defined "flowed" as a value of the "format" parameter. + +Thanks to this, long lines can be automatically folded on a sender +side while they can be unfolded on a receiver side. From the point of +user view, you can write long lines casually. + +There are two ways to apply the flowed folding. + +1) To apply the flowed folding explicitly, type `C-cC-f'. + +Then, Mew sees if long lines exist in a draft. If long lines whose +length is over `mew-flowed-fold-threshold' are found, Mew applies +the "flowed" folding. This variable defaults to 78. + +`mew-flowed-fold-length' controls the max length of folded lines. Its +initial value is 70. + +Folding method is decided according to character set. If the language +is separated by SPC, the new line characters are inserted after +existing SPCs(delsp=no). Otherwise, pairs of SPC and the new line +character are inserted in appropriate positions(delsp=yes). + +If you type `C-cC-f' again, the folded lines are unfolded. + +2) If `mew-use-format-flowed' is `t', this functionality is +took into account automatically at composing with `C-cC-c' or +`C-cC-m'. Its default value is `nil'. + +3) You can toggle the value of `mew-use-format-flowed' by +`C-cC-pC-f'. + + +Note that folded lines with the "flowed" folding are always unfolded +on viewing regardless of the value of `mew-use-format-flowed'. If you +feel it is hard to see long lines, use `_' in Summary mode. + +If `mew-flowed-auto-wrap' is `t', at visualizing a message, `_' is +automatically executed so as unfolded lines are folded. The default +value of `mew-flowed-auto-wrap' is `t'. + + + +File: mew.info, Node: reply, Next: forward, Prev: longline, Up: Composing + +Replying to a message and deciding recipients +============================================= + +As distinguished from the case of a new message, where the writer +specifies the addresses of the To:, Cc: or Newsgroups: fields, in a +reply message addresses are automatically generated. + +When `a' and `A' is used in Summary mode, a new draft is prepared in +Draft mode. Values of To:, Cc:, and Newsgroups: are prepared according +to three alists. + + 1. If called with `C-u', replying to the sender/poster only. In this + case, `mew-reply-sender-alist' is used. + 2. If this message is sent by ME, you probably intend to reply with + the original header. In this case, `mew-reply-fromme-alist' is + used. + 3. Otherwise, replying to all people listed. In this case, + `mew-reply-all-alist' is used. + +The default value of `mew-reply-sender-alist' is as follows: + + '(("Reply-To:" + ("To:" "Reply-To:" "From:")) + (t + ("To:" "From:"))) + +This is read as follows: + + 1. If Reply-To: exists, copy the values of Reply-To: and From: to + new To:. + 2. Otherwise, copy the value of From: to To:. + +If you would like to reply only to the address on Reply-To: (if any), +set `mew-reply-sender-alist' like this: + + (setq mew-reply-sender-alist + '(("Reply-To:" + ("To:" "Reply-To:")) + (t + ("To:" "From:")))) + +The default value of `mew-reply-fromme-alist' is as follows: + + '((t + ("To:" "To:") + ("Cc:" "Cc:") + ("Newsgroups:" "Newsgroups:")))) + +This is read as follows: + + 1. Copying the value of To: to new To: and copying the value of Cc: + to new Cc: and copying the value of Newsgroups: to new + Newsgroups:. + +The default value of `mew-reply-all-alist' is as follows: + + '((("Followup-To:" "poster") + ("To:" "From:")) + ("Followup-To:" + ("Newsgroups:" "Followup-To:" "Newsgroups:")) + ("Newsgroups:" + ("Newsgroups:" "Newsgroups:")) + ("Reply-To:" + ("To:" "Reply-To:" "From:") + ("Cc:" "To:" "Cc:" "Apparently-To:")) + (t + ("To:" "From:") + ("Cc:" "To:" "Cc:" "Apparently-To:"))) + +This is read as follows: + + 1. If the value of Followup-To: is "poster", copying the value of + From: to new To:. + 2. If Followup-To: exists, copying the values of Followup-To: and + Newsgroups: to new Newsgroups:. + 3. If Newsgroups: exists, copying the value of Newsgroups: to + Newsgroups:. + 4. If Reply-To: exists, copying the values of Reply-To: and From: to + new To:. And copying the values of To:, Cc:, and Apparently-To: + to new Cc:. + 5. Otherwise, copying the value of From: to new To:. And copying the + values of To:, Cc:, and Apparently-To: to new Cc:. + +You may want to set `mew-reply-all-alist' like this: + + (setq mew-reply-all-alist + '((("Followup-To:" "poster") + ("To:" "From:")) + ("Followup-To:" + ("Newsgroups:" "Followup-To:")) + ("Newsgroups:" + ("Newsgroups:" "Newsgroups:")) + ("Reply-To:" + ("To:" "Reply-To:")) + (t + ("To:" "From:") + ("Cc:" "To:" "Cc:" "Apparently-To:")))) + +If there are multiple entries for a certain address, they are +unified. Addresses ending with ":;", which indicates anonymous +recipients, are automatically removed. + +Your addresses are automatically removed. Your addresses are +automatically defined to `mew-mail-address-list' according to, for +example, `mew-config-alist'. If you dislike this value, you can also +explicitly set it like this: + + (setq mew-mail-address-list + '("^pooh@[a-z]*.example.org$" + "^pooh@example.net$" + "^winnie@example.jp$")) + + + +File: mew.info, Node: forward, Next: resend, Prev: reply, Up: Composing + +Forwarding messages +=================== + +To forward messages, type `f' or `F' in Summary mode. Then Draft mode +appears and the messages are already attached in the attachments +region. + +Also, you can prepare the attachments region by yourself, then copy +(`c') the messages or make links (`l') to the messages. If the file +names of the messages are numeric ([0-9]+), they are automatically +considered as messages. `y' is very convenient because it make a link +to the message displayed in Message mode. + +By default, the entire message is forwarded. If you want to remove +some parts of its header, define +`mew-field-delete-for-forwarding'. The following is an example to +remove "Received:" and "Return-Path:" when forwarded. + + (setq mew-field-delete-for-forwarding '("Received:" "Return-Path:")) + + + +File: mew.info, Node: resend, Next: shortcut, Prev: forward, Up: Composing + +Re-sending messages +=================== + +You may occasionally wish to send messages modifying the header of a +message. + +For instance, you may want to send a message with the same body to +multiple receivers independently. Please imagine the case where you +put a created message destined to Pooh in +queue and then you wish to +send an another message to Piglet by copying it and modifying its +header. Let's call this recycle sending. + +Also, you occasionally wish to send a message adding the Resent-To: +field to a target message. This is a kind of forwarding. This is +called header conversion because a message header is modified. The +forwarding described the previous subsection is called encapsulation +because a message is embedded into another new message. + +Header mode exists for this reason, modifying a part of the header, +sending/queuing the created message. You can think this is a kind of +Draft mode which prohibits modifications of its body. + +The following commands are provided in Summary mode to enter Header +mode. + +`W' + Recycle sending. Enter Header mode in order to modify To:, Cc:, + From: of a target message. Typical usage is for messages in + +queue or +postq. +`r' + Re-sending. Enter Header mode in order to add Resent-To:, + Resent-Cc:, Resent-From: of a target message. Re-sending may + confuse receivers, so you should think carefully before using it. + +In Header mode, you can make use of completion and circular completion +like in Draft mode. When you are finished inputting the header, send +the message using one of the following commands. You may be concerned +because the body of the message is not displayed in your new +message. But you need not worry, since the body and a part of the +target message is certainly used. + +`C-cC-m' + Compose a message, put it into +queue or +postq, and let it be + waiting to be sent. +`C-cC-c' + Compose a message and send it. You are asked, "Really send this + message? (y or n) ". Type `y' to send it. + + + +File: mew.info, Node: shortcut, Next: mark-b-comp, Prev: resend, Up: Composing + +Creating signature or cipher message +==================================== + +This section explains the method for signing or encrypting "text only" +messages with PGP or S/MIME. The following commands are explained. + +`C-cC-s' + Sign the entire draft. Input your pass-phrase. +`C-cC-e' + Encrypt the entire draft. +`C-cC-b' + Sign, and then encrypt the entire draft. Input your pass-phrase. +`C-cC-r' + Encrypt, and then sign the entire draft. Input your pass-phrase. + +To encrypt a message, receivers' public keys are used. On the other +hand, your secret key is used to sign a message, and so you need to +input your pass-phrase when applying the signature. Note that if you +are using the pass-phrase cache or the master password mechanism and +there are pass-phrases presently cached, you do not have to type your +pass-phrase (*Note password::). + +These commands create a PGP/MIME message by default. If you want to +use S/MIME, configure as follows: + + (setq mew-draft-privacy-method 'smime) + +You can change this variable with `C-cC-pC-m' in Draft mode. + +We can consider that these four commands above are shortcut methods of +mark based composing described in the next section. + +To sign a message, type `C-cC-s'. When signing, because your secret +key is needed to be decrypted, you may be asked for your pass-phrase +if it is not cached. Created messages are stored in +queue or +postq. + +Your secret key is identified in From: address. If From: does not +exist, your default secret key is selected. When you want to specify a +secret key that is not identified the address of From:, type +`C-uC-cC-s'. + + +To encrypt a message, type `C-cC-e'. A message is encrypted with +public keys identified with the addresses on To: and Cc:. Since this +is encryption only, you are not asked for your pass-phrase. Created +cipher messages are stored in +queue. + +This message is encrypted with your public key in addition to those of +the receivers. Therefore you can decrypt created messages. For +example, you can go to +queue by `g' and preview a created message to +reconfirm this. + +To sign a draft and then encrypt it, type `C-cC-b'. To encrypt a draft +and then sign it, type `C-cC-r'. In both cases, created messages are +stored in +queue. + +It is very likely that you will forget to sign and/or encrypt a draft +even if you intended to do so. To prevent this, Mew provides an +mechanism to automatically sign or encrypt a message when +`C-cC-m' or `C-cC-c' is typed. + +If you want to protect privacy of all drafts, set +`mew-protect-privacy-always' to `t' and set +`mew-protect-privacy-always-type' to one of services. + +If you want to protect the privacy of drafts when replying encrypted +messages, set `mew-protect-privacy-encrypted' to `t' and set +`mew-protect-privacy-encrypted-type' to one of the services. This +configuration is preferred to the configuration for all drafts +described above in the case of replying encrypted messages. + +The following services are available. The strings enclosed in braces are +the symbols for each service. The service applied when typing +`C-cC-m' or `C-cC-c' is displayed in the mode line. + +pgp-signature (PS) + Sign with PGP +pgp-encryption (PE) + Encrypt with PGP +pgp-signature-encryption (PSPE) + Sign then encrypt with PGP +pgp-encryption-signature (PEPS) + Encrypt then sign with PGP +pgp-signature (SS) + Sign with S/MIME +pgp-encryption (sE) + Encrypt with S/MIME +pgp-signature-encryption (SSSE) + Sign then encrypt with S/MIME +pgp-encryption-signature (SESS) + Encrypt then sign with S/MIME + +The following example works for signing all drafts. + + (setq mew-protect-privacy-always t) + (setq mew-protect-privacy-always-type 'pgp-signature) + +The following example is for encrypting drafts with PGP when replying +encrypted messages. + + (setq mew-protect-privacy-encrypted t) + (setq mew-protect-privacy-encrypted-type 'pgp-encryption) + +In Draft mode, `C-cC-pC-a' toggles +`mew-protect-privacy-always' and `C-cC-pC-e' toggles +`mew-protect-privacy-encrypted'. + +You can specify privacy services for the current draft in Draft mode +beforehand so that you do not forget to apply the privacy services +when sending. To set privacy services to the current draft evaluated +when typing `C-cC-m' or `C-cC-c', type `C-cC-pC-d', and then input one +of privacy services listed above. To cancel the current privacy +service, just type `RET' instead of selecting the privacy service. + +When you compose a message by `C-cC-c' or `C-cC-m', and if signing +and/or encryption fails, the cursor gets back to the draft. At this +time, the service that you specified is canceled. If you type `C-cC-c' +or `C-cC-m' in this situation, a plain message is created, so please +be careful. After correcting the cause of the failure, if you want the +same service, type `C-cC-pC-d' to specify your service explicitly or +use `C-cC-s', `C-cC-e', etc. + + +If `mew-use-old-pgp' is set to `t' (the default value is `nil'), +`C-cC-s' and `C-cC-e', etc create old fashioned PGP message instead of +PGP/MIME. If the attachment region exists, an error occurs. + +`mew-protect-privacy-*' described above are effective only to +PGP/MIME, not to old PGP. If you want to create old PGP signature with +`C-cC-m' or `C-cC-c' always, set +`mew-protect-privacy-with-old-pgp-signature' to `t'. + +For PGP/MIME and S/MIME, Mew supports GnuPG 1.x and 2.0, not 2.1. + + + +File: mew.info, Node: mark-b-comp, Next: pgp-key, Prev: shortcut, Up: Composing + +Mark based composer +=================== + +To support PGP/MIME, S/MIME and ZIP, mark based composing is +provided. Remember the previous example. + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + B 2 Image/Gif MagicPoint logo mgp.gif + Q 3 Application/Postscript Presentation Material ohp.ps + 4 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +You can find the `B' mark and the `Q' mark at the beginning of the +line. Mew provides you with a new concept of "encoding". Encoding +includes Base64, Quoted-Printable, Gzip64 (Gzip + Base64), signature, +encryption. + +At present, 8 marks are prepared. + +`" "' + No encoding. But 8bit text would be encoded. +`B' + Base64 +`Q' + Quoted-Printable +`G' + Gzip64 (compressed with gzip then encoded with Base64. This is + experimental. Do not use this if receivers do not use Mew.) +`PS' + Sign with PGP +`PE' + Encrypt with PGP +`SS' + Sign with S/MIME +`SE' + Encrypt with S/MIME + +Additional key binding for marks in attachments is as follows: + +`B' + Put the `B' mark to encode with Base64. +`Q' + Put the `Q' mark to encode with Quoted-Printable. +`G' + Put the `G' mark to encode with Gzip64. This is applicable only + to Text/Plain and Application/Postscript since compression is not + effective with other objects. For example, JPEG is already + compressed. +`S' + Put the `PS' mark to sign with PGP. +`E' + Put the `PE' mark to encrypt with PGP. Input decrypters' + addresses. +`M-s' + Put the `SS' mark to sign with S/MIME. +`M-e' + Put the `SE' mark to encrypt with S/MIME. Input decrypters' + addresses. +`Z' + Encrypt the part with ZIP immediately. After the encryption, the + `B' mark appears. +`U' + Unmark. The original mark appears. + +Consider the following example: The second part will be signed with +PGP then encrypted with PGP for "kazu". Don't be alarmed. Its +description is overwritten but saved. The third part will be encoded +with Gzip64. + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + PSPE 2 Image/Gif kazu@example.org mgp.gif + G 3 Application/Postscript Presentation Material ohp.ps + 4 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +After applying marks, type `C-cC-m' or `C-cC-c' to create messages. + + + +File: mew.info, Node: pgp-key, Next: anonymous, Prev: mark-b-comp, Up: Composing + +PGP key distribution +==================== + +To distribute a PGP public key, please use `p' on attachments in Draft +mode. It asks whose public key you want to distribute. Just type `RET' +if it is yours. If you want to distribute someone else's key, input +his e-mail address with completion. The PGP public key will +distributed as Content-Type: Application/Pgp-Keys. + +If Mew finds that the part is Application/Pgp-keys, it tries to add +the PGP public key onto your PGP public keyring. Remember that Mew is +not responsible for TRUST or VALIDITY. It is YOU who set these +values. Please use the commands described by Mew to set these as +necessary. If you do not know the meaning of TRUST and VALIDITY, you +should learn the web of trust system provided by PGP BEFORE using PGP +to protect your privacy. + + + +File: mew.info, Node: anonymous, Next: Marks, Prev: pgp-key, Up: Composing + +Sending messages with anonymous receivers +========================================= + +You may occasionally wish to send a message to anonymous receivers. + +For instance, please imagine that Pooh is trying to invite multiple +friends to a party. Piglet should reply only to Pooh. However, Piglet +might make a mistake of replying to other people if the addresses of +all the invitees are listed in Cc:. Moreover, Pooh does not want to +disclose the names of those who he invited until the day of the party. + +To handle this, Mew makes use of ":;" for anonymous addresses. Please +look at the following example. + + To: party:piglet@example.org,roo@example.org; + From: Pooh + +Here, there is a colon (":") after the explanatory comment +"party". This is followed by some addresses that are delimited by +"," and terminated by ";". If you write addresses in this format, Mew +sends the message to the addresses with them removed form the +header. In this example, Piglet and Roo will receive the following +message. + + To: party:; + From: Pooh + +The receiver knows that the sender is Pooh, but will not know who else +received the message. Also, the string "party:;" is not address, so +the receiver cannot reply to it. + +You should understand that enumerating many addresses on To: or Cc: is +basically not a good practice anyway. If you often have the occasion +to send messages a set group of people, you should create a +mailing-list. + + + + +File: mew.info, Node: Marks, Next: unread mark, Prev: anonymous, Up: Top + +Funny marks +*********** + +Here is a listing of marks that a user can use for insertion or +deletion in Summary mode. This mark is displayed in the beginning of a +line as follows: (Note that the marks that Mew inserts are displayed +left side of date.) + + D 03/12 Hidenori Ohta This weekend |Let's go to StoneMagic + oM03/14 Momo-chan The pictures of Noto |Attached are the pictu + * 03/15 Neat Sumikawa Re: wine |OK. I vote for Wednesd + +There are six marks at present. + +`U' + The unread mark. +`D' + The delete mark. +`X' + The delete mark. +`o' + The refile mark, that is, to move a message to another folder. +`*' + The target mark. +`$' + The mark to save another mark temporarily. + +Just putting a mark on to a message does NOT process anything at all. +It is typing `x' that processes the marks including `o', `D', `X'. So, +take it easy to put marks but take care to type `x'. + +The marks above are explained in sequence. The marks which Mew inserts +are summarized here as well. + +* Menu: + +* unread mark:: Unread `U' +* delete mark:: Delete `D' and `X' +* refile mark:: Refile `o' +* target mark:: Target `*' +* escape mark:: Escape `$' +* unmark:: Deleting marks +* mark change:: Overwriting marks +* sync:: Mark consistency against an IMAP server +* off-line:: Processing marks off-line for IMAP +* mew-mark:: Marks displayed by Mew + + + +File: mew.info, Node: unread mark, Next: delete mark, Prev: Marks, Up: Marks + +Unread `U' +========== + +With the following configuration, messages are marked with the unread +mark `U' when scanning the messages. + + (setq mew-use-unread-mark t) + +When you read a message with `SPC', `n', or `p' and etc, the `U' mark +disappears. + +These three commands read through messages marked with the `*' mark, +the `U' mark, and non-marked messages. If you type `zSPC', they read +through messages marked with the `*' mark and the `U' mark only. This +is convenient to read through unread messages. Typing `zSPC' again +gets the target messages back. + +When you move onto the current message by putting a mark on the +previous message, the `U' mark is deleted. It's sure that you want to +read the current message if you move onto it by `SPC', `n', and +`p'. However, you might not intend to read the current message when +you move onto it by putting a mark. If this is the case, this spec is +inconvenient for you. If you want to retain the unread mark on the +current message when you move onto it by putting a mark on the +previous message, configure as follows: + + (setq mew-delete-unread-mark-by-mark nil) + +The followings are summary of commands related to the `U' mark. + +`zSPC' + Toggle the target of `SPC', `n', and `p'. Toggling means change + one to the other out of "the `U' mark, the `*' mark, and + non-mark" and "the `U' mark and the `*' mark". +`M-u' + Put the `U' mark to the current message. + + + + +File: mew.info, Node: delete mark, Next: refile mark, Prev: unread mark, Up: Marks + +Delete `D' and `X' +================== + +If you want to delete a message, type `d' in Summary mode to put the +`D' mark on it. Don't be worried about losing the message by +mistake. Since putting the `D' mark has no immediate effect, it does +not result in a serious mistake. By default, typing `x' moves messages +marked with `D' to a trash. + +For local folders, a trash is +trash. For IMAP, it is %trash. + +To really delete messages in the trashes, there are two methods: + + 1. Type `D' in Summary mode. + 2. Put the `D' mark in the trashes then type `x'. + +Exactly speaking, the following rule is applied for local folders. +(`mew-trash-folder' is default to +trash. +`mew-trash-folder-list' is default to `nil'.) + + - If `mew-trash-folder' is `nil', messages marked with + `D' are deleted. + - If `mew-trash-folder-list' is defined, messages marked with `D' + in one of the folders defined in it are deleted. Otherwise, they + are moved to the trash. + - If `mew-trash-folder-list' is `nl', messages marked with `D' in + `mew-trash-folder' are deleted. Otherwise, they are moved to the + trash. (This is default.) + +For IMAP, the same rule is applied according to both +`mew-imap-trash-folder' and `mew-imap-trash-folder-list' + +It is convenient if you can change the `*' mark to the `D' mark since +you can put many the `D' marks at once. To achieve this, use `md'. + +Also, typing `Md' put the `D' mark to all duplicated messages +excluding one for each. + +There is also another mark, `X', which is like the mark `D'. +Messages marked with `X' are deleted when `x' is typed. The +`X' mark can be put by `M-d'. + +`mxM-d' processes messages marked with `X' only. Typing +`mM-d' converts all `*' marks to `X'. + + +The following is a summary regarding with the `D' mark and the +`X' mark. + +`d' + Put the `D' mark. +`M-d' + Put the `X' mark. +`md' + Convert all `*' marks to `D'. +`mM-d' + Convert all `*' marks to `X'. +`x' + Process marked messages. +`mxd' + Process messages marked with `D' only. +`mxM-d' + Delete messages marked with `X' only. +`D' + Delete all messages in a trash. +`C-uD' + Delete all messages in a specified folder. + + + diff --git a/elpa/mew-20150813.2354/mew.info-3 b/elpa/mew-20150813.2354/mew.info-3 new file mode 100644 index 00000000..b3aa484d --- /dev/null +++ b/elpa/mew-20150813.2354/mew.info-3 @@ -0,0 +1,1573 @@ +Info file: mew.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew: (mew.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +File: mew.info, Node: refile mark, Next: target mark, Prev: delete mark, Up: Marks + +Refile `o' +========== + +To refile a message, type `o' and input a folder name, then +`o' is put. A folder is guessed neatly, so most time what you +should to is just type `RET'. For more information, refer to +*Note Refile::. + +If you type `o' on a message marked with `o', the refile folder is +shown. When typing `x', messages marked with `o' are actually refiled. + +Consider that you specify multiple folders and refiles actually. If +your file system has hard link, the message is moved to the first +folder, and hard links are created from the other folders. Otherwise, +the message is moved to the first folder, and it is copied to the +other folders. + +If the number of specified folders are 1, and it is the current +folder, refiling means do nothing. If the number is more than two and +the current folder is included, refiling means that the message number +in the current folder remains and hard links are created from the +other folders (or it is copied to the other folders). + +Mew provides `c' which is very similar to `o'. `c' shows the current +folder as a candidate in addition to guessed folders. + +A summary about the `o' mark is here. + +`o' + Put the `o' mark. +`c' + Put the `o' mark. Showing the current folder as a candidate in + addition to guessed folders. +`x' + Refile messages marked with `o'. +`mxo' + Refile messages marked with `o' only. This command does not + process other marks. +`C-umxo' + Refile messages marked with `o', whose destination is the same as + that of the current message. + + + +File: mew.info, Node: target mark, Next: escape mark, Prev: refile mark, Up: Marks + +Target `*' +========== + +Please put the `*' mark onto messages that you want to review +later. `?' also put the `*' mark onto matched messages (for more +information, refer to *Note search::). Use `N' and `P' to walk around +messages marked with `*'. + +Here is a summary for `*' commands. + +`*' + Put the `*' mark. +`N' + Jump to the message marked with `*' below and display it. +`P' + Jump to the message marked with `*' above and display it. +`ma' + Put the `*' mark to all unmarked messages. +`mr' + Put the `*' mark to all matching messages with specified regular + expression. + +The `*' mark is used to handle multiple messages. The following is a +list of commands which handle multiple messages. + +`F' + Prepare a draft to forward multiple messages marked with `*' in + MIME format. +`J' + A large message is occasionally fragmented into multiple messages + whose Content-Type: is Message/Partial. Mew puts the `P' mark to + these messages. Now a user marks these messages with `*' and + executing this commands results in producing the original + message. +`mI' + Retrieve the rest of truncated(`T') messages marked with + `*'. +`C-umI' + Perform `mI'. +`M-b' + De-capsulate messages embedded in the messages marked with `*'. +`M-\' + Executing an external command specifying messages marked with `*' + as arguments. +`M-t' + Apply "uudecode" on messages marked with `*'. + +For `M-t', messages marked with `*' are supposed to be in the right +order. If out of order, sorting with `S' would help. + + + +File: mew.info, Node: escape mark, Next: unmark, Prev: target mark, Up: Marks + +Escape `$' +========== + +Suppose that you want to put the `*' marks to messages matched to a +pattern specified to the `/' command. If there are messages marked +with `*' already, these messages are merged to the results of +`/'. Thus, you would want to escape the current messages marked with +`*'. + +For this sake, the escape mark `$' is provided. A typical usage is as +follows: + + 1. Change the `*' marks to the `$' marks with `m$'. + 2. Put the `*' marks to messages, for instance, with `/' and process + the messages marked with `*'. + 3. Cancel the `*' marks with `U*'. + 4. Get the old `*' marks back with `m*'. + +Here is summary of the commands related to the `$' mark. + +`m$' + Change the `*' marks to the `$' marks. +`m*' + Change the `$' marks to the `*' marks. + + + +File: mew.info, Node: unmark, Next: mark change, Prev: escape mark, Up: Marks + +Deleting marks +============== + +Refiling and deleting is not processed unless you type `x'. So, if you +press `u' to unmark before you type `x', messages do not disappear +accidentally. + +Here is a summary for unmark commands. + +`u' + Cancel the mark on this message. +`U' + Cancel all marks according to what you input. + +The method with the `$' mark, that is, preserve the `*' marks and +operate something then get them back, is friendly to users since it is +visible. But since messages are marked, they would not be the targets +of the operation. + +To solve this problem, a method to recover `*' marks is provided. The +command is bound to `M*'. This method would not be friendly to users +since the `*' marks to recover are invisible. But because the marks +are canceled, these message are surely the target of any operations. + +`M*' + Recover the `*' marks which are canceled by the last `U*'. + + + + +File: mew.info, Node: mark change, Next: sync, Prev: unmark, Up: Marks + +Overwriting marks +================= + +Marks have levels of strength. You can override a mark by another +same-level mark weak mark. Also stronger marks can override weaker +marks. + +The followings shows the marks in the strong order: + +`o', `D', and `X' + After marking a message newly, the next message is shown. After + overriding another mark, the cursor stays on the message. +`*' and `$' + After marking a message, the cursor stays on the message. +`U' + After marking a message, the cursor stays on the message. + +refer to *Note summary-mode:: to know which direction the cursor moves +after putting a strong mark. + +You can exchange marks as follows: + +`m$' + `*' -> `$' :: Preserve the `*' marks temporarily. +`m*' + `$' -> `*' :: Get the `*' marks back. +`ms' + `$' <-> `*' +`mM-u' + `*' -> `U' :: It is useful when you put `U' marks to messages + picked by `?'. +`md' + `*' -> `D' :: It is useful when you put `D' marks to messages + picked by `?'. +`mM-d' + `*' -> `X' :: It is useful when you put `X' marks to messages + picked by `?'. +`mo' + `*' -> `o' :: It is useful when you put `o' marks to messages to + be moved picked by `?'. `*' -> `o' :: It is useful when you put + `o' marks to messages to be copied picked by `?'. +`e' + Exchange the first input mark to the second one. The `o' mark is + not exchangeable. + + + +File: mew.info, Node: sync, Next: off-line, Prev: mark change, Up: Marks + +Mark consistency against an IMAP server +======================================= + +Mew can maintain consistency of the following marks against an IMAP +server: + +`U' + Whether a message is read or not. This IMAP flag is \Seen. This + is usually valid in %inbox only. +`*' + Review mark. This IMAP flag is \Flagged. + +To allow off-line operations, Mew synchronizes marks with an IMAP +server everytime when a user makes an action. Mew does not +automatically synchronize marks repeatedly. The followings are how Mew +synchronizes marks. + + 1. `s' + 'update + - Reflecting modified marks of the existing messages to the server + - For newly arrived messages, reflecting flags of the server + to the messages. + + 2. `x' + - Reflecting modified marks of the existing messages to the server + + 3. `s' + 'sync + - Reflecting modified marks of the existing messages to the server + - Clearing `*',`U', `$', ` ' mark on the existing messages. + - Reflecting flags of the server to the existing messages + - Removing messages which were deleted in the server + + + +File: mew.info, Node: off-line, Next: mew-mark, Prev: sync, Up: Marks + +Processing marks off-line for IMAP +================================== + +An IMAP user may want to cache messages in folder A and go out. Then +he may want to put the `o' and/or `D' marks, and process the marks +off-line. In this story, these jobs should be done in his IMAP server +after connecting the Internet. + +If a message in folder A is moved to folder B with IMAP, the cached +message in folder A usually must be deleted and a corresponding +message in folder B must be retrieved from his IMAP server again. This +is because information embedded in a cached message in folder A is +valid only in folder A. + +Suppose you refile a message in folder A to folder B off-line. It is +very inconvenient for you to retrieve a corresponding message in +folder B from your IMAP server , in order to read it, after refile +jobs are done online. You may want to read the messages refiled to +folder B by just going to the folder B, without retrieval form the +IMAP server. + +Mew implements delayed jobs processing and viewing refiled messages +without retrieval. If you want to process marks off-line, type `lx'. +`lx' carries out the following jobs. + + 1. Deleting messages marked with `o' and/or `D' from folder A. + 2. Queuing these jobs in %queue. + 3. Moving messages marked with `o' to folder B and marking them + invalid. + +'invalid' means that you can read it but you cannot put the `o'/`D' +mark on it. Invalid messages are marked with `#'. When you go to +folder B by typing `g', a list of invalid messages is displayed +automatically. + +If you want to let your IMAP server process jobs in %queue after you +get back online, type `C-cC-c' in %queue. + +Typing `s' in folder B after jobs in %queue are done in your IMAP +server results in deletion of invalid messages and caching valid +messages. + + + +File: mew.info, Node: mew-mark, Next: Refile, Prev: off-line, Up: Marks + +Marks displayed by Mew +====================== + +Here is a summary of marks displayed by Mew. + +`M' + This message is a multipart. Please refer to *Note multipart::. +`-' + This message contains a Multipart/Alternative content. Please refer to + *Note analysis::. +`T' + This message was truncated by Mew. Please refer to *Note + retrieving::. +`S' + This message is signed. Please refer to *Note cipher-viewing::. +`E' + This is a cipher message. Please refer to *Note cipher-viewing::. +`P' + This message is fragmented. Please refer to *Note target mark::. +`#' + This message is invalid. Please refer to *Note off-line::. + + + + +File: mew.info, Node: Refile, Next: by-folder, Prev: mew-mark, Up: Top + +Happy refiling +************** + +When you come to receive hundreds of messages in a day (do not you +believe it?), refiling messages becomes a very tough job. Mew neatly +guesses default folders where the message is supposed to be refiled +when you type `o'. You can see an example below. + + Folder name (+work/mew-dist): + + +If the default value in () is proper, just type `RET'. The messages +will be marked with `o' if its refiling folders are decided. + +You can refile a message to folders of the same world to which the +message belong. As described above, a world is identified by a +combination of "case" and proto. When you input a folder to which the +message is refiled, you must not specify "case" and you must input a +folder whose proto is the same. The reason why you must not specify +"case" is that the "case" is already known. With other commands, you +have to specify the "case", if necessary, when you input folder name +in minibuffer. This command is only the exception. + +Mew also provides `c' which is very similar to `o'. To know the +difference, please refer to *Note refile mark::. + +As you know, the more excellent refiling guess algorithms become, the +less user's job troublesome. Mew provides you with the following +rules. + +* Menu: + +* by-folder:: Guess by mailing-list folders +* by-alist:: Guess by user defined rules +* by-thread:: Guess by thread +* by-from-folder:: Guess by private folders +* by-from:: Guess by From: +* by-newsgroups:: Guess by Newsgroups: +* by-default:: Guess by default rule +* guess-rule:: Controlling rules +* auto-refile:: Auto refile +* copy-msg:: Copying messages across worlds + + + +File: mew.info, Node: by-folder, Next: by-alist, Prev: Refile, Up: Refile + +Guess by mailing-list folders +============================= + +Many users tend to refile messages destined to a mailing-list to a +folder whose name is the same as the mailing-list. Mew provides a +mechanism to guess a mailing-list folder for messages destined to +mailing-lists. + +Suppose that you have a folder named +misc/pooh-lovers. The following +message is probably to be refiled to this folder. + + To: pooh-lovers@example.org + +Likewise, Mew searches a matching folder forward with addresses on To: +and Cc:. There are many people who do not use recursive folders. With +Mew, however, you would not be smart if you do not use it. + +Smart users may wonder that they get a trouble in the following +situation where private addresses are on To: or Cc:. + + To: piglet@example.org + Cc: pooh-lovers@example.org + +Since Pooh is a member of pooh-lovers, he receives this message. But +he has a folder for his friend, Piglet. So, +from/piglet may be +chosen. + +To avoid this, Mew allows you to specify which folders are to be +ignored. The default is +from. So, please take a convention to refile +personal messages under +from. + +When Mew guesses a candidate by the folders, it asks you: + + Folder name (+misc/pooh-lovers): + + +Just type `RET' if the default is exactly what you want. + +If you specify a new folder with `o', the folder is created and added +to the folder list to be used for guess. Convenient, isn't it? + +The function name to provide this feature is +`mew-refile-guess-by-folder'. + +If you don't use capital letters for folder names, configure as +follows to make this function faster: + + (setq mew-use-fast-refile t) + +By default, candidate includes node folders as well as leaf folders. +If you want to not select node folders but leave folders only, +configure as follows: + + (setq mew-use-node-folder nil) + + + +File: mew.info, Node: by-alist, Next: by-thread, Prev: by-folder, Up: Refile + +Guess by user defined rules +=========================== + +There are some cases where the refile guess mechanism by folders does +not work as you wish. For example, for both a message whose To: is +staff@example.jp and another message whose To: is staff@example.net, +the same folder would be selected with guess by folders +(e.g. "+net/staff"). So, Mew allows you to define your own rules +explicitly. (You must use the new format for +`mew-refile-guess-alist'. For more information, see + +Let's look at an example. + + (setq mew-refile-guess-alist + '(("To:" + ("staff@example.jp" "+jp/staff") + ("staff@example.net" "+net/staff")))) + +This means that if To: contains staff@example.jp +jp/staff is selected +and if To: has staff@example.net +net/staff is chosen. + +The format of this rule is as follow: + + rule ::= ' + ::= (( ) ( ) ... []) + +The whole is a list of ( ). A field name is specified for +. The format for is as follows: + + ::= ( |) ( |) ... + + is a field value for . means a folder to be +chosen if matched. You can write recursively instead of +. (*Note config2::.) + +There are two special s: `nil' and `t'. `nil' is used to specify + to be returned when nothing is guessed. `t' can specify + to be returned in addition to guessed values. + + ::= (t ) | (nil ) + +If you know regular expression, a more advanced rule can be defined +like this. + + (setq mew-refile-guess-alist + '(("Newsgroups:" + ("^nifty\\.\\([^ ]+\\)" "+Nifty/\\1") + (".*" "+rec/news")) + ("To:" + ("\\(inet\\|wide\\)@wnoc-fuk" "+wide/\\1-wnoc-fuk")) + ("From:" + ("uucp@" "+adm/uucp") + ("ftpsync@" "+adm/ftpsync")) + (nil "+unknown"))) + +The function name to provide this feature is +`mew-refile-guess-by-alist'. + + + +File: mew.info, Node: by-thread, Next: by-from-folder, Prev: by-alist, Up: Refile + +Guess by thread +=============== + +Mew provides a mechanism to guess a folder where the parent message of +a current message was refiled before. + +For example, Pooh, Piglet, and Roo had a chat to go and get honey. So, +Pooh made +project/honey then refiled the message to it. The further +messages, if they are properly replied, they are supposed to be +refiled to +project/honey. + +Information that which folder was chosen for messages is stored to +"~/Mail/.mew-refile-msgid-alist". `mew-lisp-max-length' +controls the amount of this information. The default value is 2000 +messages. If you want limits it to 3000 messages, put the following to +"~/.mew.el". + + (setq mew-lisp-max-length 3000) + +The function name to provide this feature is +`mew-refile-guess-by-message-id'. + + + +File: mew.info, Node: by-from-folder, Next: by-from, Prev: by-thread, Up: Refile + +Guess by private folders +======================== + +In addition to the mechanism to select a mailing-list folder described +in *Note by-folder::, Mew provides a mechanism to choose a private +folder. Since private folders locate under +from, we can say that this +mechanism select a folder from the folders under +from. Let's see the +following example: + + To: pooh@example.net + From: piglet@example.org + +Pooh received a message from Piglet. If Pooh uses this mechanism, ++from/piglet will be chosen according to From:. (Folders under +from +can be recurse. And you can select the entire address for a folder +name instead of the user part.) + +The function to provide this feature is +`mew-refile-guess-by-from-folder'. + +Next, let's consider a care where Pooh replied to Piglet. Since Pooh +Cc:ed the message to himself, the message was also delivered to him. + + To: piglet@example.org + Cc: pooh@example.net + From: pooh@example.net + +How do you feel if you are Pooh? You may want to refile this to ++from/pooh. Also, you may want to move this to +from/piglet. So, it +can be customized. + +If `mew-refile-guess-from-me-is-special' is `t' and if an address in +From: is yourself, `mew-refile-guess-by-from-folder' select a folder +under +from according to To: and/or Cc:. + + + +File: mew.info, Node: by-from, Next: by-newsgroups, Prev: by-from-folder, Up: Refile + +Guess by From: +============== + +Mew also provides a mechanism to guess a folder by the place where a +message that has the same From: field is refiled. + +Suppose that Piglet has two addresses, piglet@example.org and +p-p-p@example.org. Pooh wants to refile messages from Piglet to ++from/piglet no matter what his From: is. This policy can, of course, +be implemented if Pooh specifies rules explicitly as follows: + + (setq mew-refile-guess-alist + '(("From:" + ("piglet@example.org" "+from/piglet") + ("p-p-p@example.org" "+from/piglet")))) + +But such a work may bother you. So, first refile a message whose From: +is piglet@example.org to +from/piglet. At this time, +from/piglet is +created. Next, refile a message whose From: is p-p-p@example.org to ++from/piglet. Here Mews learns that p-p-p@example.org was refiled to ++from/piglet. After this, when messages whose From: is +p-p-p@example.org are refiled, +from/piglet is chosen. + +For another example, you can refile messages from machinery to ++adm/misc without defining an explicit rule. + +Information for relationship between From: and folder is stored to +"~/Mail/.mew-refile-from-alist". `mew-lisp-max-length' +controls the amount of this information as the same as +*Note by-thread::. + +The function name to provide this feature is +`mew-refile-guess-by-from'. + +If the value of `mew-refile-guess-from-me-is-special' is `t', +`mew-refile-guess-by-from' acts as +`mew-refile-guess-by-from-folder' (*Note by-from-folder::). + + + +File: mew.info, Node: by-newsgroups, Next: by-default, Prev: by-from, Up: Refile + +Guess by Newsgroups: +==================== + +For those who read articles of NetNews received by e-mail with Mew, +Mew provides a mechanism to guess a folder by Newsgroups:. The +function name to provide this feature is +`mew-refile-guess-by-newsgroups'. + + + +File: mew.info, Node: by-default, Next: guess-rule, Prev: by-newsgroups, Up: Refile + +Guess by default rule +===================== + +The default rule is to extract a user name from From: and to choose +`+from/user'. But if `mew-refile-guess-strip-domainpart' is +`nil', it extracts the entire address. So, +`+from/user@domain' is chosen. The default value of +`mew-refile-guess-strip-domainpart' is `t'. + +The function name is `mew-refile-guess-by-default'. + + + +File: mew.info, Node: guess-rule, Next: auto-refile, Prev: by-default, Up: Refile + +Controlling rules +================= + +Mew controls guess rules by two variables, +`mew-refile-guess-control' and `mew-refile-ctrl-multi'. If you +want multiple candidates, set `mew-refile-ctrl-multi' +`t'. Otherwise, set it `nil'. + +By default, `mew-refile-guess-control' is declared as follows (since +it is a declaration, `defvar' is used): + + (defvar mew-refile-guess-control + '(mew-refile-guess-by-alist + mew-refile-ctrl-throw + mew-refile-guess-by-newsgroups + mew-refile-guess-by-folder + mew-refile-ctrl-throw + mew-refile-ctrl-auto-boundary + mew-refile-guess-by-thread + mew-refile-ctrl-throw + mew-refile-guess-by-from-folder + mew-refile-ctrl-throw + mew-refile-guess-by-from + mew-refile-ctrl-throw + mew-refile-guess-by-default)) + +Mew executes every function defined in `mew-refile-guess-control' in +order. Each function may guess multiple candidates. + +Let's see the following example of `mew-refile-guess-control' action. + +`mew-refile-guess-by-alist' + guessed +aaa and +bbb. +`mew-refile-guess-by-folder' + guessed +ccc and +ddd. +`mew-refile-guess-by-default' + guessed +eee. + +If you want to provide all candidates, +aaa - +eee, set +`mew-refile-ctrl-multi' `t'. If you want to provide +aaa only, set it +`nil'. + +If you want +aaa - +ddd but do not want left candidates, in other +words, you want +eee only when no candidate is guessed by functions +executed before, set `mew-refile-ctrl-multi' `t' and insert +`mew-refile-ctrl-throw' between `mew-refile-guess-by-folder' and +`mew-refile-guess-by-default'. + +`C-uo' displays the flow of guess rules in Message buffer. + + + +File: mew.info, Node: auto-refile, Next: copy-msg, Prev: guess-rule, Up: Refile + +Auto refile +=========== + +Those who receives many messages everyday is prone to store thousands of +messages in the +inbox (or %inbox) folder. In such a case, they may want +to speak out like this, "Hey messages, get out of the folder to +somewhere". Mew provides a feature to satisfy such laziness. :) +`M-o' is the spell. + +When you execute this function, it marks specific messages with +`o'. The specific messages mean messages which are not marked +with `o' nor `D' if +`mew-refile-auto-refile-skip-any-mark' is `nil'. If +`mew-refile-auto-refile-skip-any-mark' is `t', they mean +non-marked messages (i.e. read). The default value of +`mew-refile-auto-refile-skip-any-mark' is `nil'. + +`C-uM-o' targets messages marked with `*' regardless the value of +`mew-refile-auto-refile-skip-any-mark'. + +Refile rule is the same described in the previous section. Please note +that what this function does is just mark messages with +`o'. Messages are not refiled until you will press `x'. + +Mew's refile mechanism is so smart that it would be harmful for this +function. That is, most users would not understand where messages have +been refiled if Mew made most use of its guess mechanism. :) For this +reason, break is provided to limit usage of guess functions. Recall +the declaration up above. + + (defvar mew-refile-guess-control + '(mew-refile-guess-by-alist + mew-refile-ctrl-throw + mew-refile-guess-by-newsgroups + mew-refile-guess-by-folder + mew-refile-ctrl-throw + mew-refile-ctrl-auto-boundary + mew-refile-guess-by-thread + mew-refile-ctrl-throw + mew-refile-guess-by-from-folder + mew-refile-ctrl-throw + mew-refile-guess-by-from + mew-refile-ctrl-throw + mew-refile-guess-by-default)) + +You can find the `mew-refile-ctrl-auto-boundary' function in +`mew-refile-guess-control'. Only when auto refile is used, Mew +ignores guess functions below this function. If guess functions above +`mew-refile-ctrl-auto-boundary' didn't guess any folder for a +message, the message is not marked with `o'. Insert +`mew-refile-ctrl-auto-boundary' before you ruin. + + + + +File: mew.info, Node: copy-msg, Next: Virtual, Prev: auto-refile, Up: Refile + +Copying messages across worlds +============================== + +"Refile" described above is moving messages in the same world. By +contrast, you may want to move messages from a world to another +world. You can accomplish this by copying messages from a world to +another and deleting the original messages. Here we describe how to +copy messages to another world. + +You may want to copy a message to a local folder. For this, type +`lc'. If you execute `lc' in a remote folder, Mew removes information +related to the remote folder from the cached message and copy it to a +local folder. (You can use `lc' in a local folder, too. In this case, +a message is moved in the same world.) + +To opy a message in a folder to an IMAP folder (the server side), type +`li'. + +To copy messages marked with `*' to a local folder, use `mlc'. To +copy messages marked with `*' to an IMAP folder, use `mli'. + +Here is a summary of commands which copy messages from a world to +another. + +`lc' + Copy a message to a local folder. +`mlc' + Copy messages marked with `*' to a local folder. +`li' + Copy a message to the server side of IMAP. +`mli' + Copy messages marked with `*' to the server side of IMAP. + + + + +File: mew.info, Node: Virtual, Next: selection, Prev: copy-msg, Up: Top + +Virtual folder +************** + +Virtual mode is a virtual folder and it consists of "selection" and +"thread". + +`Selection' + A virtual folder collecting necessary messages from several + folders. Its folder name has "*" on the left side. +`Thread' + A virtual folder to visualize message flow with indentation, + created from a folder or a virtual folder. Its folder name has + "*" on the both sides. + +In Virtual mode, you can use most commands that you can find in +Summary mode. + +If you put a mark on a message in Virtual mode and if corresponding +Summary mode exists, the mark is also put onto the corresponding +message there. But if you put a mark on a message in Summary mode, +the mark is not put any corresponding messages in Virtual mode. + +You cannot process marks in Virtual mode. Even if you type `x' to +process marks in Virtual mode, the cursor moves to corresponding +Summary mode, if exsists, and you are asked to type `x' again. + +You should take note that Virtual folder is really virtual and it does +not exist in file system. If you exit Mew, it then disappears. To +know how to delete Virtual mode, please refer to *Note Quit::. + +* Menu: + +* selection:: Selection +* sorting:: Sorting +* dialog:: Dialog +* search:: Searching +* condition:: How to input search conditions +* dbsearch:: Search Engine +* keyword:: Highlighting a keyword +* thread:: Thread +* thread-op:: Thread operations + + + +File: mew.info, Node: selection, Next: sorting, Prev: Virtual, Up: Virtual + +Selection +========= + +Selection is a virtual folder collecting necessary messages from +several folders. There are five ways to create selection: + +`m/' + Listing messages marked with `*' on a folder. see *Note + sorting::. +`S' + Sorting messages on a folder and display them. (No effect to the + original folder.) see *Note dialog::. +`V' + Listing messages which have relationship with the current message. See + *Note dialog::. +`/' + Listing messaged matched to a search condition on a folder. see + *Note search::. +`k/' + Listing messaged matched to a search condition from all folders. See + *Note search::. + + + + +File: mew.info, Node: sorting, Next: dialog, Prev: selection, Up: Virtual + +Sorting +======= + +To make selection by sorting messages, use `S'. Then you will be asked +to input the field name as follows: + + Sort by? (default date): + +There are some cases where strings stored in the specified field +should not be compared as text. For example, while Subject: can be +considered as text, Date: and X-Mail-Count: should be treated as date +and number, respectively. In this way, we call the distinctions in +methods of string sorting "modes". Default modes for typical field +names are configured in `mew-sort-key-alist'. + +When you want to specify the mode of sorting, the mode is followed by +`:'. For example, to sort with the X-Mail-Count: field as arithmetic +value (not text), input like this: + + x-mail-count:num + +You can complete field names and modes with `TAB'. + +Mew provides four modes for sorting: + +`text' + String with preceding "Re: " and or "Fw: " removed. +`ml' + The same as text but preceding mailing-list-string removed. +`num' + Number. +`date' + Date. + +The default field name, your response to the prompt "Sort by?", can be +specified in `mew-sort-default-key'. The following example changes the +default value from "date" to "x-ml-count". + + (setq mew-sort-default-key "x-ml-count") + +You can also set a default field name for each folder by +`mew-sort-default-key-alist'. For folders not explicitly specified +here, `mew-sort-default-key' is used for their default field name. +The following is an example that specifies "subject" for the +inbox +folder and "x-mail-count" for the +mew-dist folder. + + (setq mew-sort-default-key-alist + '(("+inbox" "subject") + ("+mew-dist" "x-mail-count"))) + +To really sort messages in a local folder, use `M-s'. This command is +not available in remote folders. + + + +File: mew.info, Node: dialog, Next: search, Prev: sorting, Up: Virtual + +Dialog +====== + +Mew can list messages which have relationship with the current +message. Let's call this "dialog". This is different from thread +described later in the following points: + + - Thread can be made from one folder or one virtual + folder. Messages relating to dialog can ubiquitously exists in + several folders. + + - Thread visualizes tree structres with indentation. while dialog + lists up messages in order of time. + +To use the feature of dialog, execute `kI' to create database. New +messages are not automatically registered in to the database, you +should periodically execute `kI'. `kI' updates the database +incrementally by default. This method is fast but garbages are +left. So, sometime you should type `C-ukI' to update the database +fully. + +To make dialog, type `V' on the current message. This command displays +him, his ancestors, and his children only. His brothers and so on are +not shown. If you display the entire of the family, type `V' again on +the first message of the dialog, which is the origin of the family. + + + +File: mew.info, Node: search, Next: condition, Prev: dialog, Up: Virtual + +Searching +========= + +Mew provides the following method to search messages: + +`?' + Put the `*' mark onto messages in this folder, which are matched + to a specified pattern. Either `mewl' or `grep' is called + according to the specified pattern. +`C-u?' + `?' with a region specified. +`/' + Make selection with messages in this folder, which are matched to + a specified pattern. Either `mewl' or `grep' is called according + to the specified pattern. +`C-u/' + `/' with a region specified. + +We can also search messages with a search engine, including Spotlight, +Windows Desktop Search, etc. This feature is supported by the +following commands. + +`k?' + Put the `*' mark onto messages in this folder, which are matched + to a specified pattern. +`k/' + Make selection with messages in all folders, which are matched to + a specified pattern. +`C-uk/' + Make selection with messages in specified folders, which are + matched to a specified pattern. If you want to specify multiple + folders, separate them with ",". You can also use a wildcar "*". + + + +File: mew.info, Node: condition, Next: dbsearch, Prev: search, Up: Virtual + +How to input search conditions +============================== + +If you type `?' or `/', Mew asks you to input search pattern as +follows: + + mewl/grep pick pattern: + +If you specify just a keyword, Mew executes `grep'. On the contrast +if you type an expression, Mew calls `mewl'. + +Here is a list of expression elements. (In the strong order) + +`field=string' + Match if the "field" field contains the "string" string + (case-insensitive). If you specify "head", it means the entire + header. +`field==string' + Match if the "field" field contains the "string" string + (case-sensitive). If you specify "head", it means the entire + header. +`field!=string' + Match if the "field" field does not the "string" string + (case-insensitive). If you specify "head", it means the entire + header. +`field!==string' + Match if the "field" field does not the "string" string + (case-sensitive). If you specify "head", it means the entire + header. +`( )' + Evaluate first. +`! ' + Match if not . +` & ' + Match if AND . You can omit this. +` | ' + Match if OR . + +Some examples are shown below. + +(a) Messages whose From: contains "kazu". + + from=kazu + +(b) Messages whose To: contains "mew" OR Cc: contains "mew". + + to=mew | cc=mew + +(c) Messages whose To: contains "mew" OR Cc: contains "mew" AND From: +contains "kazu". + + (to=mew | cc=mew) & from=kazu + +When you execute `?' or `/' and if you just type `RET' to a pattern, +you can specify a command to be executed. + + Cmd opts pattern: grep -l -e + +When you use an search engine with `k?' or `k/', the pattern +(including just a keyword and an expression) will be converted to the +syntax of the search engine. + +For example, you can write an expression, that From: is "kazu" and +body contains "wine" but does not contain "bordeaux", as follows: + + from=kazu wine ! bordeaux + +If you set `mew-pick-pattern-list' to a list of pattern, you can enjoy +circular completion with `C-cTAB'. In this case, the first member is +displayed as a default value. + + + + +File: mew.info, Node: dbsearch, Next: keyword, Prev: condition, Up: Virtual + +Search Engine +============= + +To operate search engines, the following commands are provided: + +`km' + Make index for the current folder. +`kM' + Make index for all folders. +`kc' + Switch one search engine to another. + +The followings are expiation of each search engines. + +`Hyper Estraier' + Type `kM' periodically. It's OK to execute "mewest" on the + command line instead. If you want to update the index for the + current folder quickly, you can use `km'. Both `k?' and `k/' are + available. When you specify folders with `C-uk/', sub-folders, if + any, are included in the target. +`Spotlight' + Type `kM' just once. `km' is not necessary. Both `k?' and `k/' + are available. +`Windows Desktop Search' + Type `kM' just once. `km' is not necessary. +`Google Desktop' + Type `kM' just once. `km' is not necessary. Only `k/' is + available. + +The default search engine is automatically set to the one found first. +If you explicitly specify it, set `mew-search-method' to one out of +'est, 'spotlight, 'wds, and 'google. The following is an example to +choose Hyper Estraier. + + (setq mew-search-method 'est) + + + +File: mew.info, Node: keyword, Next: thread, Prev: dbsearch, Up: Virtual + +Highlighting a keyword +====================== + +The keyword which you specified on search is shorted in a buffer. You +can display messages with the keyword highlighted. The commands to +enable this functionality are as follows: + +`M-n' + Display a message in the forward direction and find a keyword and + highlight it. In Summary mode, the target is messages marked with + `*'. In Virtual mode, it is all messages. If you repeat this + command, text around the keyword is displayed from one to + another. If no key word is set to the variable, this command + first asks you a keyword. +`C-uM-n' + The same as `M-n' except that you can change the stored keyword + explicitly. +`M-p' + A reverse version of `M-n'. +`C-uM-p' + A reverse version of `C-uM-n'. + + + +File: mew.info, Node: thread, Next: thread-op, Prev: keyword, Up: Virtual + +Thread +====== + +When in the process of exchanging messages, the relationship of the +messages is presented in a tree structure. Visualization of the +structure with indentation is called thread. Here is an example: + + 03/12 Hidenori Ohta This weekend |Let's go to StoneMagic + 03/13 Kazu-kun +Re: This weekend |Since it'll be rainy, + 03/15 Hidenori Ohta | +Re: This weekend |OK. Get together at 12 + 03/14 Oda-chan +Re: This weekend |Sounds lovely. I'd lik + +The thread feature is implemented as virtual folder. For instance, if +you make threads for +inbox, a buffer *+inbox* is prepared. + +To make thread, the following commands exist. + +`tt' + Make threads from Summary mode or selection and move the cursor + to the current message. If corresponding threads already exist, + switch to the Virtual mode. When this command is executed on + threads, switch to the original folder and move the cursor to the + current message. +`C-utt' + Make threads for messages in the region. +`mt' + Make threads for messages marked with `*'. +`tr' + Make threads for messages matched to a regular expression. + + + +File: mew.info, Node: thread-op, Next: Quit, Prev: thread, Up: Virtual + +Thread operations +================= + +Here are the commands used for moving to thread presentation. + +`tp' + Move to the top of the current thread. If the current message is + a top node, move to the top of the next thread. +`tn' + Move to the top of the next thread. +`^' + Move to the parent message of the current message. (Available in + both Summary and Virtual) +`&' + Move to the child message of the current message. (Available in + both Summary and Virtual) +`(' + Search backward by one sibling message of the current message. +`)' + Search forward by one sibling message of the current message. + + +Here are commands to mark messages in a thread. + +`t*' + Put the `*' mark all messages of the current sub-thread. Please + refer to *Note target mark:: for more information. +`t$' + Put the `$' mark all messages of the current sub-thread. Please + refer to *Note escape mark:: for more information. +`td' + Put the `D' mark all messages of the current sub-thread. Please + refer to *Note delete mark:: for more information. +`tM-d' + Put the `X' mark all messages of the current sub-thread. Please + refer to *Note delete mark:: for more information. +`to' + Put the `o' mark all messages of the current sub-thread. Please + refer to *Note refile mark:: for more information. + +A command to unmark all messages of the current sub-thread is `tu'. + + +Here are commands to manipulate a thread: + +`tSPC' + Hide children and leave the parent only. If its children are + hidden, "+" is displayed on the parent. Also, if this command is + executed on a message whose children are hidden, they appear. +`ta' + Toggle appearance of children for all threads. +`tg' + Graft a thread to a message. To specify which thread is grafted, + type `C-SPC' on the root of the thread. Then move onto your + target message, and typing `tg' grafts the thread to the target + message as children. + + +If `mew-use-thread-separator' is `t', threads are +distinguished by a separator defined by `mew-thread-separator' +(its default value is "--"). + + + + +File: mew.info, Node: Quit, Next: Customize, Prev: thread-op, Up: Top + +Give me a break +*************** + +Here are how to quit and suspend Mew and how to erase a mode (buffer). + +

+ +`q' + Suspend Mew then switch to another buffer. All buffers of Mew + remain, so you can resume with buffer operations. +`Q' + Quit Mew. All buffers of Mew are erased. +`C-cC-q' + Erase the current mode (buffer). + + + +`C-cC-q' + Erase the draft. + + + +`C-cC-q' + Erase the buffer. + + + + +File: mew.info, Node: Customize, Next: summary-mode, Prev: Quit, Up: Top + +Customizing Mew +*************** + +Here are explained how to change default setting of Mew and make Mew +your favorite. Edit "~/.mew.el" to do it! + +* Menu: + +* summary-mode:: Summary mode +* message-mode:: Message mode +* draft-mode:: Draft mode +* charset:: Character set +* highlight:: Highlighting +* hooks:: Hooks +* pop:: POP +* imap:: IMAP +* nntp:: NNTP +* smtp:: SMTP +* config:: Changing receiving/sending behavior +* config2:: The format of configuration +* custom-misc:: Miscellaneous + + + +File: mew.info, Node: summary-mode, Next: message-mode, Prev: Customize, Up: Customize + +Summary mode +============ + +You can specify the format of Summary mode by `mew-summary-form'. The +default value is as follows: + + (setq mew-summary-form '(type (5 date) " " (14 from) " " t (30 subj) "|" (0 body))) + +Like this, `mew-summary-form' is a list of list, symbol, and string. + + 1. A string is printed as it is. + 2. A list consists of an integer and a symbol. The symbol specifies + a function to be called. The name of the function is produced by + concatenating "mew-summary-form-" and the symbol name. + (e.g. `mew-summary-form-date' for the symbol 'date'). Pre-defined + symbols are 'type, 'time, 'date, 'year, 'size, 'from, 'subj and + 'body. For more details, see the explanation of the functions + called `mew-summary-form-'. The integer specifies the + width of field which will be filled with a return string of the + function. A positive value means padding SPCs on the right if + necessary. A negative value means padding SPCs on the left if + necessary. If a negative value is specified, the corresponding + function must return an ASCII string. 0 means the remaining width + of the line and is treated as a positive value. + 3. A symbol is equivalent to (1 symbol). + 4. '(mark) is appended to `mew-summary-form' when used. + 5. `t' means the position of thread indentation. + +An example is as follows: + + (setq mew-summary-form + '(type (5 date) " " (-4 size) " " (14 from) " " t (30 subj) "|" (0 body))) + +`mew-summary-form-from-me-prefix' is the prefix to be prepend to an +destination address if the message is originated by me. The default is +"To:". + + +`mew-summary-form-extract-rule' is a list to specify what part to +extract from the From: field. Each element must be 'name, 'comment, +'address, 'nickname, or appropriate "regex". The default value is +'(nickname). + +Consider the following examples: + + A: Kazu Yamamoto + B: kazu@example.org (Kazu Yamamoto) + C: Kazuhiko Yamamoto (Kazu) + +Each element returns the following value: + + 1. 'name:: Name part, if any + A. Kazu Yamamoto + B. (No match) + C. Kazuhiko Yamamoto (Kazu) + 2. 'comment:: Comment part, if any + A: (No match) + B: Kazu Yamamoto + C: (Kazu) + 3. 'address:: Address part + A: kazu@example.org + B: kazu@example.org + C: kazu@example.org + 4. 'nickname:: one element of personal information in Addrbook + according to `mew-addrbook-for-summary'. The default value of + `mew-addrbook-for-summary' is `'nickname'. So, From: is converted + a nickname by default. To know what kind of value can be used, + refer to *Note draft-mode::. + 5. (regex):: The substring first matched. + +If a element does not match, the next element is applied. If no +element matches to the From: field, or this value is `nil', the whole +of the From: field is used. + + +If `mew-summary-form-mark-delete' is `t', the `D' mark +automatically is put onto duplicated messages. The default is +`nil'. + + +If `mew-summary-form-mark-spam' is `t', the `D' mark automatically is +put onto SPAM messages. A message is considered a SPAM message if the +MD5 checksum of its body is duplicated in a scan. The default is +`nil'. + +If `mew-summary-form-mark-review' is `t', the `*' mark +automatically is put onto messages destined to me. The default is +`nil'. + + +If you want to use Mew with full Emacs frame, set like this. + + (setq mew-use-full-window t) + + +`SPC' in Summary mode decide the next action to view a message +according to `mew-summary-show-direction'. Likewise, you can specify +the cursor direction after putting a strong mark by +`mew-summary-mark-direction'. You can select one from the following +candidates. + +`up' + Display the message above. +`down' + Display the message below. +`next' + Display the next message in the direction. +`stop' + Do not display the next message. + +The default value for both is `next'. If you read messages from the +bottom, set as follows: + + (setq mew-summary-show-direction 'up) + + + +File: mew.info, Node: message-mode, Next: draft-mode, Prev: summary-mode, Up: Customize + +Message mode +============ + +It is impossible to display a file to the Message buffer if its data +type is not supported by Emacs. Install an external program which +converts the data to text and you can display the file to the Message +buffer. + +If you install "w3m" and "emacs-w3m", Text/Html can be displayed in +Message mode. (Please note that multilingualized "w3m", not pure +"w3m", is necessary for "wvHtml", "xlhtml", and "ppthtml" +described below.) When you install both of them, add the following to +"~/.mew.el'. + + (condition-case nil + (require 'mew-w3m) + (file-error nil)) + +With this, Text/Html can be displayed in Message mode as if it were +Text/Plain. Even in this situation, `C-cC-e' described below is a +valid operation. + +If you install "wvHtml", "xlhtml", and "ppthtml", you can display text +parts of WORD, Excel, and PowerPoint file in Message, +respectively. Since these commands uses HTML, the configuration of +Text/Html above is required. With this, a WORD file, for example, can +be displayed in Message mode as if it were text. + +You can display the file with an external application itself instead +of displaying it in the Message buffer. For this, type `C-cC-e'. + +You can visualize an image file into the Message buffer. Also, you can +display it with an external application by typing `C-cC-e', of course. + +You can display an HTML file to a browser with `C-cC-e'. A default +browser is used on Windows and Mac. On Unix, "mozilla" is set to a +default browser as follows: + + (defvar mew-prog-text/html-ext '("mozilla" ("-remote" "openFile(%s)") t)) + +If you want to set it to "firefox", for example, configure like this: + + (setq mew-prog-text/html-ext + '("firefox" ("-a" "firefox" "-remote" "openFile(%s)") t)) + +You can visualize an Office-family file to each application by typing +`C-cC-e'. On Windows and Mac, an Office-family application is +executed. On Unix, "ooffice" is set to the default application as +follows: + + (defvar mew-prog-msword-ext "ooffice") + (defvar mew-prog-msexcel-ext "ooffice") + (defvar mew-prog-mspowerpoint-ext "ooffice") + +If you want to set it to "soffice", for instace, do like this: + + (setq mew-prog-msword-ext "soffice") + (setq mew-prog-msexcel-ext "soffice") + (setq mew-prog-mspowerpoint-ext "soffice") + +If you want to not visualize an Office-family file into the Message +buffer, but want to display it with "wvHtml", configure as follows: + + (setq mew-prog-msword '(nil mew-mime-application/msword)) + (setq mew-prog-msexcel '(nil mew-mime-application/msexcel)) + (setq mew-prog-mspowerpoint '(nil mew-mime-application/mspowerpoint)) + +If you want to specify an application instead of the pre-defined +application, type `C-uC-cC-e'. + +Recently there are many message whose have Multipart/Alternative, +which consists of Text/Plain and Text/Html. By default, Mew selects +Text/Plain. When you install "emacs-w3m", you may want to choose +Text/Html. In this case, add the following to "~/.mew.el". (Now, it's +good idea to get back to *Note multipart:: to review how to use +`:'.) + + (setq mew-mime-multipart-alternative-list + '("Text/Html" "Text/Plain" ".*")) + +You can decrypt a ZIP attach file and display it with `zz'. + + + +File: mew.info, Node: draft-mode, Next: charset, Prev: message-mode, Up: Customize + +Draft mode +========== + +Define `mew-cc' to use Cc:. When replying, another Cc: field may be +prepared from the target message. If there are multiple Cc: fields, +they are combined to one field on sending. + +If you want to receive your originating messages for backup without +specifying your address, use Dcc:. Set your address to `mew-dcc'. + +Set header fields that you want to insert every time when you write +messages to `mew-header-alist' as an associate list. The following is +an example. + + (setq mew-header-alist + '(("X-fingerprint:" "6B 63 38 88 67 5E 96 8E CE A4 62 73 3F 11 64 94") + ("X-URL:" "http://www.example.org/~kazu/"))) + +To customize citation label, define field to cite in `mew-cite-fields' +and format in `mew-cite-format'. Define citation prefix to +`mew-cite-prefix'. The default declaration is as follows: + + (defvar mew-cite-fields '("From:" "Subject:" "Date:")) + (defvar mew-cite-format "From: %s\nSubject: %s\nDate: %s\n\n") + (defvar mew-cite-prefix "> ") + +To add Message-ID: to citation label, take this way. + + (setq mew-cite-fields '("From:" "Subject:" "Date:" "Message-ID:")) + (setq mew-cite-format "From: %s\nSubject: %s\nDate: %s\nMessage-ID: %s\n\n") + +To add a user part of an address to the citation prefix, configure as +follows: + + (setq mew-cite-prefix-function (function mew-cite-prefix-username)) + +With this, the citation prefix becomes like this: + + From: SUMIKAWA Munechika + Subject: Wine + Date: Wed, 23 Jul 1997 11:40:50 +0900 + + sumikawa> Hi, it's Sumikawa, the guy who's neat from good morning + sumikawa> to good night. + sumikawa> + sumikawa> Talking about the wonderful wine party, I would propose + sumikawa> Cabernet Sauvignon, Bordeaux, '90. + +Both an address in the citation label and the citation prefix can be +converted to an element of a personal information in Addrbook. They +can be configured by `mew-addrbook-for-cite-label' and +`mew-addrbook-for-cite-prefix', respectively. The default values are +`nil' and `'username', respectively. You can set out of the following +values. + + +'shortname + Short name +'address + Address +'username + User part of address +'nickname + Nickname +'name + Full name + +Let's consider the following example. + + (setq mew-addrbook-for-cite-label 'nickname) + (setq mew-addrbook-for-cite-prefix 'nickname) + +With the first line, an address in the citation label is replaced with +its nickname. The second line indicates that the cite prefix is +replaced with its nickname. + + From: sumitch + Subject: Wine + Date: Wed, 23 Jul 1997 11:40:50 +0900 + + sumitch> Hi, it's Sumikawa, the guy who's neat from good morning + sumitch> to good night. + sumitch> + sumitch> Talking about the wonderful wine party, I would propose + sumitch> Cabernet Sauvignon, Bordeaux, '90. + + + diff --git a/elpa/mew-20150813.2354/mew.info-4 b/elpa/mew-20150813.2354/mew.info-4 new file mode 100644 index 00000000..6a25079a --- /dev/null +++ b/elpa/mew-20150813.2354/mew.info-4 @@ -0,0 +1,1576 @@ +Info file: mew.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew: (mew.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +File: mew.info, Node: charset, Next: highlight, Prev: draft-mode, Up: Customize + +Character set +============= + +As described in *Note charset-guess::, Mew automatically chooses an +appropriate charset for the message when composing. + +If characters of multiple languages exist, and if it is necessary to use +an international charset, `mew-charset-m17n' is used. Its default +value is "utf-8" (equivalent to Unicode). If you want to set it to +"iso-2022-jp-2", configure like this: + + (setq mew-charset-m17n "iso-2022-jp-2") + +If you want to check a chosen charset when composing, configure +`mew-ask-charset'. + +`nil' + Not ask. +`A list of charset' + Ask if the charset is not a member of the list. +`t' + Ask if `mew-charset-m17n' is used. + +For instance, if you want to check when charset other than US-ASCII, +ISO-8859-1, and ISO-8859-15, configure like this: + + (setq mew-ask-charset '("us-ascii" "iso-8859-1" "iso-8859-15")) + + +For example, when "utf-8" is chosen for a message with this +configuration, you are asked like this: + + utf-8 is used. OK? (y or n) + +Typing `y' makes the composed message sent (or queued). If you type +`n', you will go back to the original draft. + +In Europe Latin 9 (ISO-8859-15 or Latin 0), which includes the euro +sign, is getting more and more popular instead of Latin 1 +(ISO-8859-1). If characters of both Latin 1 and Lain 9 exist in a +draft, Mew takes the following step to decide a charset. + + 1. If `unify-8859-on-decoding-mode' is used: + 1. Use "iso-8859-1" if no loss. + 2. Otherwise, use "utf-8". + 2. If `unify-8859-on-decoding-mode' is not used: + 1. If both ISO-8859-1 and ISO-8859-15 can be used with no loss, + "ISO-8859-1" is used. + 2. Use "iso-8859-1" if no loss. + 3. Use "iso-8859-15" if no loss. + 4. Otherwise, use "utf-8". + +The default value of `mew-charset-latin' is "iso-8859-15". If you want +to set it to "iso-8859-1", configure like this: + + (setq mew-charset-latin "iso-8859-1") + +If you want to always use UTF-8 for any characters other than +US-ASCII, configure as follows: + + (setq mew-cs-database-for-encoding + `(((ascii) nil "7bit" "7bit") + (nil utf-8 "base64" "B"))) + + + +File: mew.info, Node: highlight, Next: hooks, Prev: charset, Up: Customize + +Highlighting +============ + +If `mew-use-highlight-mark' is `t', marked message are +highlighted. The default is `t'. + +If `mew-use-highlight-header' is `t', the header of a message is +highlighted. The default is `t'. + +If `mew-use-highlight-body' is `t', the body of a message is +highlighted. The default is `t'. The limit to be highlighted can be +set by `mew-highlight-body-max-size'. The default is 10000 bytes. + +If `mew-use-highlight-url' is `t', a spell is cast to URL strings in a +message. So, when you move the cursor onto the URL, it is +highlighted. The default is `t'. + +If `mew-use-cursor-mark' is `t', the mark specified `mew-cursor-mark' +is putted to the beginning of the current line. The default is +`nil'. The default of `mew-cursor-mark' is ">". + +If `mew-use-highlight-cursor-line' is `t', underline is put on the +cursor line in Summary mode. The default is `t'. + +If `mew-use-highlight-mouse-line' is `t' on Emacs which supports mouse +highlight, the mouse line is painted in Summary mode. This is very +convenient to read messages clicking the middle button of the +mouse. The default value is `nil'. + +If `mew-use-highlight-x-face' is `t', X-Face: in a header is iconified +in Message mode. The default value is `t'. To use this feature, +install the "netpbm" package and the "compface" package. + +To modify colors, copy "dot.theme" contained Mew's source file to +an appropriate place, say "~/.mew-theme.el". First, set +`mew-theme-file' to this file name in ".mew.el" as follows: + + (setq mew-theme-file "~/.mew-theme.el") + +Then, change the contents. For instance, you can find the following +configuration. + + (mew-setface-bold header-subject + :tty "red" :light "Firebrick" :dark "OrangeRed") + +The symbol `header-subject' means the value of the "Subject:" field in +a header. :tty is the case where Emacs is executed on a terminal while +:light and :dark indicates the case where the background of Emacs +executed with a window is white and black, respectively. + +If you wish green for a terminal, ForestGreen for the white +background, and LimeGreen for the black background, modify the +configuration as follows: + + (mew-setface-bold header-subject + :tty "green" :light "ForestGreen" :dark "LimeGreen") + +To know what kind of symbols are prepared, see the "dot.mew". + +The method above does not prepare symbols for all field names and +field value. So, `mew-header-color' and `mew-header-color-bold' exist +to change colors easily. If you use the latter, characters become +bold. The former results in normal. The following is a typical usage: + + (mew-header-color-bold "Subject:" "LimeGreen" "OrangeRed") + +With this configuration, "Subject:" becomes bold LimeGreen and its +value turns into bold OrangeRed. + +The second method cannot specify the cases of terminal or background. +If you omit the field value color, the field name color is used for +the field value. + + + +File: mew.info, Node: hooks, Next: pop, Prev: highlight, Up: Customize + +Hooks +===== + +Here is a summary of hooks used in Mew. + +`mew-env-hook' + Hook called at initialize time before setting environment. +`mew-init-hook' + Hook called at initialize time. +`mew-status-update-hook' + Hook called at status update(`Z'). +`mew-summary-mode-hook' + Hook called in Summary mode. +`mew-virtual-mode-hook' + Hook called in Virtual mode. +`mew-thread-display-hook' + Hook called after new threads are displayed. +`mew-header-mode-hook' + Hook called in Header mode. +`mew-draft-mode-hook' + Hook called in Draft mode. +`mew-draft-mode-newdraft-hook' + Hook called in Draft mode only when new draft is prepared. +`mew-draft-mode-reedit-hook' + Hook called in Draft mode when a message not in +draft is + re-edited. +`mew-draft-mode-reedit-draft-hook' + Hook called in Draft mode when a message in +draft is re-edited. +`mew-draft-mode-reedit-queue-hook' + Hook called in Draft mode when a message in +queue or +postq is + re-edited. +`mew-draft-mode-edit-again-hook' + Hook called in Draft mode when a message returned with the old + style is edited again. +`mew-message-mode-hook' + Hook called in Message mode. +`mew-message-hook' + Hook called whenever message displayed. +`mew-make-message-hook' + Hook called before making a message in Draft mode. A good example + is as follows: (add-hook 'mew-make-message-hook 'ispell-message) +`mew-send-hook' + Hook called before sending/queuing an e-mail message in Draft + mode. Note that this hook is called before composition of the + message +`mew-post-hook' + Hook called before posting/queuing a NetNews message in Draft + mode. Note that this hook is called before composition of the + message. +`mew-real-send-hook' + Hook called before sending/queuing an e-mail message in Draft + mode. Note that this hook is called after composition of the + message. +`mew-real-post-hook' + Hook called before sending/queuing a NetNews message in Draft + mode. Note that this hook is called after composition of the + message. +`mew-smtp-flush-hook' + Hook called before SMTP runs if messages exist in +queue. +`mew-nntp2-flush-hook' + Hook called before NNTP runs if messages exist in +postq. +`mew-smtp-sentinel-hook' + Hook called when a SMTP process finished. +`mew-nntp-sentinel-hook' + Hook called when a NNTP process to receive messages finished. +`mew-nntp2-sentinel-hook' + Hook called when a NNTP process to post messages finished. +`mew-pop-sentinel-hook' + Hook called when a POP process finished. +`mew-pop-sentinel-non-biff-hook' + Hook called when a non-Biff POP process finished. +`mew-imap-sentinel-hook' + Hook called when a NNTP process to post messages finished. +`mew-imap-sentinel-hook' + Hook called when an IMAP process finished. +`mew-imap-sentinel-non-biff-hook' + Hook called when a non-Biff IMAP process finished. +`mew-scan-sentinel-hook' + Hook called when scan finished. +`mew-summary-ls-no-scan-hook' + Hook called when mew-summary-ls does not scan a folder. +`mew-summary-exec-hook' + Hook called when `x' in Summary mode finished. +`mew-refile-guess-by-from-learn-hook' + Hook called in mew-refile-guess-by-from-learn. +`mew-sort-hook' + Hook called when `M-s' in Summary mode finished. +`mew-pack-hook' + Hook called when `O' in Summary mode finished. +`mew-summary-delete-folder-hook' + Hook called when a folder deleted. +`mew-summary-rename-folder-hook' + Hook called when a folder renamed. +`mew-summary-toggle-disp-msg-hook' + Hook called when `v' in Summary finished. +`mew-syntax-format-hook' + Hook called when mew-syntax-format is called. +`mew-addrbook-mode-hook' + Hook called in Addrbook mode. +`mew-cite-hook' + Hook for an external cite mechanism. If you want to use + super-cite, (setq mew-cite-hook 'sc-cite-original). +`mew-before-cite-hook' + Called in mew-summary-reply-with-citation before citation. +`mew-suspend-hook' + Hook called on suspend. +`mew-quit-hook' + Hook called on quit. + +Here are some example configurations of hook + +Draft mode evaluates `text-mode-hook' and `mew-draft-mode-hook' in +order. If you do not set `auto-fill-mode' to `text-mode-hook', It +would be useful to define `mew-draft-mode-hook' as follows: + + (add-hook 'mew-draft-mode-hook + (lambda () + (auto-fill-mode 1) + (set-fill-column 70))) + +In this example, the number of fill column is also set to 70. + + + +File: mew.info, Node: pop, Next: imap, Prev: hooks, Up: Customize + +POP +=== + +Mew can POP to retrieve messages. This section describes following +variables to control POP. + +`mew-pop-server' + The name of your POP server. +`mew-pop-ssh-server' + The name of SSH server which forwards the POP3 port. +`mew-pop-ssl' + If non-nil, POP connections are made over SSL. +`mew-pop-ssl-port' + The port for POP over SSL. +`mew-pop-user' + The user name on your POP server. The default is your login name. +`mew-pop-auth' + The authentication method for POP3. 'pass means the + authentication with USER/PASS (i.e. plain password). 'apop means + the authentication with APOP. `t' means SASL according to + `mew-pop-auth-list'. The default is 'apop. +`mew-pop-auth-list' + A list of SASL methods in the preferred order. Currently, + "CRAM-MD5" can be used. +`mew-pop-delete' + Whether or not delete messages on a POP server after retrieval by + POP. If `t', delete the messages. If `nil', retain the messages. + If number N, delete the messages N days after the first + access. The default is `t'. +`mew-pop-size' + The limit size of messages to be retrieved by POP. The default is + 55296 byte. 0 means unlimited, so you can get all messages from + the POP server. To know how to retrieve the rest of a truncated + message, please refer to *Note retrieving::. +`mew-pop-body-lines' + *The limit of body lines to get when the size of message exceeds + `mew-pop-size'. The default is 40. +`mew-pop-header-only' + Whether or not the body of a message is retrieved by POP. If + non-nil, only header is retrieved. The default is `nil' + + + +File: mew.info, Node: imap, Next: nntp, Prev: pop, Up: Customize + +IMAP +==== + +Mew can use IMAP to retrieve messages. This section describes +following variables to control IMAP. + +`mew-imap-server' + The name of your IMAP server. +`mew-imap-ssh-server' + The name of SSH server which forwards the IMAP4 port. +`mew-imap-ssl' + If non-nil, IMAP connections are made over SSL. +`mew-imap-ssl-port' + The port for IMAP over SSL. +`mew-imap-user' + The user name on the IMAP server. The default is your login name. +`mew-imap-auth' + The authentication method for IMAP4. `nil' means the authentication with + LOGIN (i.e. plain password). `t' means SASL according to + `mew-imap-auth-list'. The default is `t'. +`mew-imap-auth-list' + A list of SASL methods in the preferred order. Currently, + "CRAM-MD5" and "LOGIN" can be used. +`mew-imap-delete' + Whether or not delete messages on an IMAP server after retrieval + by IMAP. If `t', delete the messages. If `nil', retain the + messages. If number N, delete the messages N days after the first + access. Otherwise they are not deleted. The default is `t'. +`mew-imap-size' + The limit size of messages to be retrieved by IMAP. The default + is 55296 byte. 0 means unlimited, so you can get all messages + from the IMAP server. To know how to retrieve the rest of a + truncated message, please refer to *Note retrieving::. +`mew-imap-header-only' + Whether or not the body of a message is retrieved by IMAP. If + non-nil, only header is retrieved. The default is `nil' + + + +File: mew.info, Node: nntp, Next: smtp, Prev: imap, Up: Customize + +NNTP +==== + +Mew uses NNTP to read/write News articles. This section describes +following variables to control NNTP. + +`mew-nntp-server' + The name of your NNTP server. +`mew-nntp-ssh-server' + The name of SSH server which forwards the NNTP port. +`mew-nntp-ssl' + If non-nil, NNTP connections are made over SSL. +`mew-nntp-ssl-port' + The port for NNTP over SSL. +`mew-nntp-user' + The user name on the NNTP server. If non-nil, authentication is + used. (Note that mew-nntp-auth does not exist.) +`mew-nntp-newsgroup' + The name of default Newsgroup. +`mew-nntp-size' + The limit size of messages to be retrieved by NNTP. The default + is 55296 byte. 0 means unlimited, so you can get all messages + from the NNTP server. +`mew-nntp-header-only' + Whether or not the body of a message is retrieved by NNTP. If + non-nil, only header is retrieved. +`mew-nntp-msgid-user' + A user name for creation of Message-Id:. If `nil', the value of + `mew-user' is used. The default is `nil'. +`mew-nntp-msgid-domain' + A domain name for creation of Message-Id:. If `nil', the value of + `mew-mail-domain' is used. The default is `nil'. + +A value of Message-Id: for NNTP is created by the following rule: + + message-id = *random*.nntp-msgid-user@nntp-msgid-domain + + + +File: mew.info, Node: smtp, Next: config, Prev: nntp, Up: Customize + +SMTP +==== + +Mew uses SMTP to send messages. If an SMTP server requires +authentication, Mew automatically asks you to input your +password. This section describes following variables to control SMTP. + +`mew-smtp-server' + The name of your SMTP server. +`mew-smtp-port' + The port for SMTP. +`mew-smtp-ssh-server' + The name of SSH server which forwards the SMTP port. +`mew-smtp-ssl' + If non-nil, SMTP connections are made over SSL. +`mew-smtp-ssl-port' + The port for SMTP over SSL. +`mew-smtp-user' + The user name on your SMTP server. If not configured, your e-mail + address is automatically set. +`mew-smtp-auth-list' + A list of SMTP AUTH methods in the preferred order. Currently, + "CRAM-MD5", "PLAIN", and "LOGIN" can be used. +`mew-smtp-helo-domain' + An e-mail domain to tell a SMTP server with HELO/EHLO. The + default is "localhost". +`mew-smtp-mail-from' + The default is `nil'. An e-mail address to tell a SMTP server + with MAIL FROM:. If `nil', an address specified by the From: + field is used. +`mew-smtp-msgid-user' + A user name for creation of Message-Id:. If `nil', the value of + `mew-user' is used. The default is `nil'. +`mew-smtp-msgid-domain' + A domain name for creation of Message-Id:. If `nil', the value of + `mew-mail-domain' is used. The default is `nil'. +`mew-use-8bit' + Whether or not send 8bit text without MIME encoding. If `nil', an + appropriate MIME encoding is applied. The default is `nil'. + +A value of Message-Id: for SMTP is created by the following rule: + + message-id = *random*.smtp-msgid-user@smtp-msgid-domain + +If you want to use Message Submission (SMTP for submission whose port +number is 587), configure as follows: + + (setq mew-smtp-port "submission") + +Please refer also to SSL (*Note SSL::) and TLS (*Note TLS::). + +Some SMTP servers are mis-configured. They requests authentication +though errors occur if passwords are received. Mew automatically ask a +user to input user's password and send it to an SMTP server if it +requires authentication. To get along with such SMTP servers above, +configure as follows: + + (setq mew-use-smtp-auth nil) + +`mew-use-smtp-auth' + If non-nil, Mew send user's password if an SMTP server requests + authentication. The default value is `t'. If `nil', Mew does not + send user's password even if the (mis-configured) SMTP server + requests authentication. + + + +File: mew.info, Node: config, Next: config2, Prev: smtp, Up: Customize + +Changing receiving/sending behavior +=================================== + +With `mew-config-alist', you can differ actions of sending/receiving +messages. Let's look at the following example: + + (setq mew-config-alist + '((home + (inbox-folder "+inbox-home") + (pop-server "pop.iij4u.or.jp")) + (ext + (pop-ssh-server "ssh.example.org")) + (default + (proto "%") + (imap-server "imap.example.org") + (pop-server "pop.example.org")))) + +This example defines three "cases": "home", "ext", and "default". For +each case, some pair of key and value are defined. + +We explain the semantics of `mew-config-alist' with this example. +If the "case" is "home", looking up "pop-server" results in +"pop.iij4u.or.jp". If the "case" is "ext", looking up "pop-server" +results in "pop.example.org" since there is no specified key for the +"case" and the "default" is used. If the "case" is "default", +looking up "pop-server" results in "pop.example.org". + +If the "case" is "home", looking up "inbox-folder" results in +"+inbox-home". If the "case" is "ext", looking up "inbox-folder" +results in the value of `mew-inbox-folder' since there is no +specified key for both "ext" and "default". If the "case" is +"default", looking up "inbox-folder" also results in the value of +`mew-inbox-folder'. + +"proto" (`mew-proto') is used to specify a folder which is selected +when you type `M-x mew'. (If you input `M-x mew' when Mew is not +executed, ""proto" for the "default" "case" is used. If you type `M-x +mew' when Mew is running, "proto" is chosen according to the value of +the "case". + +Candidates of the value are "+", "$", "%", and "-". These means +"+inbox", "$inbox", "%inbox", and "-fj.mail.reader.mew" without +any special configuration. + +Each key which can be specified in `mew-config-alist' corresponds to +the variable `mew-"key"'. The following list enumerates such keys. + + name, user, mail-domain, + cc, fcc, dcc, reply-to, organization, header-alist, proto, + smtp-server, smtp-port, smtp-ssh-server, smtp-ssl, smtp-ssl-port, + smtp-user, smtp-auth-list, + smtp-msgid-user, smtp-msgid-domain, smtp-helo-domain, smtp-mail-from, + pop-server, pop-port, pop-ssh-server, pop-ssl, pop-ssl-port, + pop-user, pop-auth, pop-auth-list, + pop-size, pop-header-only, pop-delete, pop-body-lines, + pop-proxy-server, pop-proxy-port, + imap-server, imap-port, imap-ssh-server, imap-ssl, imap-ssl-port, + imap-user, imap-auth, imap-auth-list, + imap-size, imap-header-only, imap-delete, + imap-trash-folder, imap-queue-folder, imap-spam-field, imap-spam-word, + imap-proxy-server, imap-proxy-port, + nntp-server, nntp-port, nntp-ssh-server, nntp-ssl, nntp-ssl-port, + nntp-user, nntp-size, nntp-header-only, + nntp-msgid-user, nntp-msgid-domain, + ssl-cert-directory, ssl-verify-level, + inbox-folder, queue-folder, postq-folder, + mailbox-type, mbox-command, mbox-command-arg, + signature-file, content-type, refile-guess-alist, + spam-prog, spam-prog-args, ham-prog, ham-prog-args, + use-old-pgp, pgp-signer, smime-signer, privacy-method, + protect-privacy-always, protect-privacy-always-type, + protect-privacy-encrypted, protect-privacy-encrypted-type, + protect-privacy-with-old-pgp-signature, + use-format-flowed + +A value for From: is made of 'name', 'user', and 'mail-domain' +according to the following rule: + + from = name + +Unless you set `mew-from-list' by yourself, `mew-from-list' is +automatically set collecting 'from' for each "case" according to the +rule above. see *Note cheader::. + +Cases configured in `mew-config-alist' can be specified to the +"case". When Mew boots up, both the "case" is "default". + +If you want to change the "case", type `C'. You can use completion by +`TAB' and circular completion by `C-cTAB'. + +If the "case" is not "default", they are displayed in the mode line of +Summary mode. The following is an example where the "case" is "home". + + (Summary home) + + +In Draft mode, if the "case" is not "default", the value is displayed +in mode line. The following is an example that the "case" is "home". + + (Draft home) + +To change the "case" of a draft in Draft mode, use `C-cC-o'. Its +header is dynamically modified according to the value of the +'mail-domain' key and the 'header-alist' key. Note that the "case" is +a local variable of the Draft mode. + +You can automatically set the "case" in Draft mode. + +`mew-case-guess-when-prepared' + If this variable is `t', the "case" is automatically guessed + according `mew-case-guess-alist' when a draft is prepared. The + default is `t'. +`mew-case-guess-when-composed' + If this variable is `t', the "case" is automatically guessed + according `mew-case-guess-alist' when a message is composed. The + default is `nil'. +`mew-case-guess-when-replied' + If this variable is `t', the "case" is automatically guessed + according `mew-case-guess-when-replied-alist' when a draft is + prepared by replying. The default is `t'. + +The syntax of `mew-case-guess-alist' and +`mew-case-guess-when-replied-alist' is the same as +`mew-refile-guess-alist'. For more information, please refer to +*Note by-alist::. + +When typing `C-cC-c' in Draft mode to send a draft, the "case" in +Draft mode is used to determine an SMTP/NNTP server, etc. When typing +`C-cC-c' in Summary mode to flush messages in +queue/+postq, the +"case" in Summary mode is used even if it is different from the +one which was used in Draft mode. `C-uC-cC-c' in Summary mode let +you specify the "case" to flush messages in +queue/postq. + + +The following is a summary of commands concerned with the "case". + +`C' + In Summary mode, set the "case". +`C-cC-o' + In Draft mode, set the "case" of a draft. + + + +File: mew.info, Node: config2, Next: custom-misc, Prev: config, Up: Customize + +The format of configuration +=========================== + +In Mew 6.1, configuration format of "mew.el" is improved. You can use +a new format as well as the old format. + + - In the old format, sometime "." appears. In the new fomat, no "." + appears at all. For instance, you can write ("foo" "bar") instead + of ("foo" . "bar"). + - In the old format, a numeric port is specified as string. An + example is "25". In the new format, you can write it as + integer. An example is 25. The string is still valid. An example + is "smtp". + - In the old format, the cases and the keys of `mew-config-alist' + are written as string. In the new format, you can specify them as + symbol. + +Here is an example of the new format: + + (setq mew-config-alist + '((home + (imap-server "imap.example.org") + (imap-ssl t) + (imap-ssl-port 993) + (smtp-server "smtp.example.org") + (smtp-port "submission")))) + +Compare this with the following old one: + + (setq mew-config-alist + '(("home" + ("imap-server" . "imap.example.org") + ("imap-ssl" . t) + ("imap-ssl-port" . "993") + ("smtp-server" . "smtp.example.org") + ("smtp-port" . "submission")))) + +Again, the old format is still valid. You can also mix the new format +and the old format. + + + +File: mew.info, Node: custom-misc, Next: Tips, Prev: config2, Up: Customize + +Miscellaneous +============= + +In a certain environment, it would be useful to encode a file with SAMBA +encoding when saving an attached file. For this, set +`mew-use-samba-encoding' to `t'. You can set +`mew-cs-samba' to a character set for the file name. The default is +`shift_jis'. + +You can print the current message by typing `#' in Summary mode. A +function for printing can be set to `mew-print-function'. Since its +default value is `ps-print-buffer', a message is converted into a +PostScript file before sent to a printer. You can set your own print +function as follows: + + (setq mew-print-function 'my-print-function) + +You can set fields in a header to be printed to +`mew-field-for-printing'. Its default value is as follows: + + '("Subject:" "From:" "To:" "Cc:" "Date:") + +For instance, if you want to print Subject:, From:, and Date: only, +configure as follows: + + (setq mew-field-for-printing '("Subject:" "From:" "Date:")) + + + + +File: mew.info, Node: Tips, Next: region, Prev: custom-misc, Up: Top + +Advanced usage +************** + +* Menu: + +* region:: Region +* visiting:: Visiting another buffer +* SSH:: Secure SHell +* SSL:: Secure Socket Layer +* TLS:: Transport Layer Security +* spam:: Spam messages +* spam2:: Spam messages (2) +* addr-warn:: Warning addresses +* biff:: Biff +* edit:: Edit mode + + + +File: mew.info, Node: region, Next: visiting, Prev: Tips, Up: Tips + +Region +====== + +In Summary mode, there are commands which work for a region if called +with `C-u'. If a visible region is specified, these commands work for +the region without `C-u'. + +For Emacs, you can use the visible region feature by putting the +following into your "~/.emacs". + + (transient-mark-mode 1) + +Here is a summary of such commands. + + `?', `/', `tt', `x', `lx', `ma', `Md', `S', `mlc', `mli', `*', `$', `d', `u' + +Also you can specify a repeat count before you call `*', `$', `d', and +`u'. For example, typing `3d' puts the `*' mark onto three +messages. You don't have to type `C-u' before the number. + + + +File: mew.info, Node: visiting, Next: SSH, Prev: region, Up: Tips + +Visiting another buffer +======================= + +If you want to move to +queue after making a message and putting it to ++queue with `C-cC-m' in Draft mode, set +`mew-visit-queue-after-sending' to `t'. + +If you want to visit to an appropriate inbox after setting the "case" +with `C' in Summary mode, set +`mew-visit-inbox-after-setting-case' to `t'. + +If you want to move from Summary mode to a draft (Draft mode) whose +name is the smallest number, type `C-cC-o'. + + + +File: mew.info, Node: SSH, Next: SSL, Prev: visiting, Up: Tips + +Secure SHell +============ + +Mew supports SSH version 1 and version 2 and OpenSSH for SSH. You must +execute "ssh" on the command and obtain server's public key before you +use Mew with SSH. That is, you should set up so that you can login the +server with your user password or with the password to decrypt the +secret key of the local machine. Of source, you can omit the password +to decrypt the secret key if you use "ssh-agent". + +After that, you should configure SSH variables relating to each +protocol. For example, if you want to use POP over SSH, set +`mew-pop-ssh-server' to your SSH server name. + +While a connection is protected by SSH, a picture of a lock is shown +in the mode line. + +The implementation of Mew does not allow to use both SSH and SSL/TLS +at the same time. If you need to use SSL/TLS over an SSH tunnel, +please configure SSL/TLS only with Mew and set up an SSH tunnel on a +command line. + + + +File: mew.info, Node: SSL, Next: TLS, Prev: SSH, Up: Tips + +Secure Socket Layer +=================== + +Before you use SSL, you should understand the trust model of +certificate authorities (CA). Currently, Mew supports "stunnel" +version 3 and version 4 for SSL. + +Before you use Mew with SSL, you must be sure that an SSL connection +can be established to your SSL server. Since "stunnel" is linked to +the "openssl" library, you should understand "openssl". + +Suppose we use "~/.certs" as a directory where certificates of trusted +CAs are contained. You need to copy PEM-format certificates embedded +in the source of "openssl" to this director. Each name should be +".0". + +Here we call a sample CA certificate "ca.pem". You can calculate + as follows: + + % openssl x509 -hash -noout -in ca.pem + +To copy the certificate, do as follows: + + % cp ca.pem ~/.certs/`openssl x509 -hash -noout -in ca.pem`.0 + +The certificates in the source of "openssl" do not cover all CAs. If +the certificate of your SSL server is signed by another CA, you must +copy the certificate of the CA to the directory. You may be able to +find appropriate certificate from the following page: + + http://www.columbia.edu/~ariel/good-certs/ns45/ + +There are two important Mew variables to control "stunnel". +`mew-ssl-cert-directory' is the directory where you install +certificates of trusted CAs. It's default value if "~/.certs". Also, +you can set the verification level with `mew-ssl-verify-level'. It's +default to 1. The meanings of the values are as follows: + +0 + No verification. +1 + Verify server's certificate if present. If verification failed, + an SSL/TLS connection is not created. If not present, an SSL/TLS + connection is created. +2 + Verify server's certificate. If verification failed, an SSL/TLS + connection is not created. If not present, an SSL/TLS connection + is not created. +3 + Verify server's certificate which locally installed (not one from + the server). + +Then configure SSL-related variables of each protocol. For example, if +you want to use POP over SSL, set `mew-pop-ssl' to `t'. +Also, if its port is not a standard one, configure +`mew-pop-ssl-port'. + + (setq mew-pop-ssl t) + +To use SSL for SMTP, configure as follows: + + (setq mew-smtp-ssl t) + +While a connection is protected by SSL, a picture of a lock is shown +in the mode line. + + + +File: mew.info, Node: TLS, Next: spam, Prev: SSL, Up: Tips + +Transport Layer Security +======================== + +Mew can use TLS instead of SSL. To enable TLS, Mew relies on +"stunnel", too. So, before using TLS, you should configure +according to the explanations in *Note SSL::. + +Then, set the SSL port to the same one of the protocol to be +protected. For instance, configure as follows for POP: + + ;; mew-pop-port is default to "pop3" (110) + (setq mew-pop-ssl t) + (setq mew-pop-ssl-port mew-pop-port) ;; The default is "pop3s" (995) + +That is, if the SSL port is the same as the port of the protocol to be +protected, TLS is used. Otherwise, SSL is used. + +The following is an example to protect Message Submission with TLS. + + (setq mew-smtp-port "submission") ;; The default is "smtp" (25) + (setq mew-smtp-ssl t) + (setq mew-smtp-ssl-port mew-smtp-port) ;; The default is 465 + + + +File: mew.info, Node: spam, Next: spam2, Prev: TLS, Up: Tips + +Spam messages +============= + +(1) In the case where a spam filter is running on your POP server or +your IMAP server. + +You can put the `D' mark to spam messages while you are retrieving +messages in +inbox or you are scanning messages in $inbox/%inbox. + +If you use "bogofilter", put the following to your "~/.mew.el". + + (defun mew-spam-bogofilter (val) + (let ((case-fold-search t)) + (if (string-match "yes" val) ?D))) + + (setq mew-inbox-action-alist + '(("X-Bogosity:" mew-spam-bogofilter))) + +If you want to put the `o' mark so as to be refiled to the +spam +folder, instead of putting to th `D' mark, you should program the +function as follows: + + (defun mew-spam-bogofilter (val) + (let ((case-fold-search t)) + (if (string-match "yes" val) "+spam"))) + +If you use "spamassassin", put the following to your "~/.mew.el". + + (setq mew-spam: "X-Spam-Flag:") + (defun mew-spam-assassin (val) + (let ((case-fold-search t)) + (if (string-match "yes" val) ?D))) + + (setq mew-inbox-action-alist + '(("X-Spam-Flag:" mew-spam-assassin))) + +In the case where you want to use bsfilter, see a document in the +bsfilter package. + + +(2) In the case where a spam filter is running in your IMAP server. + +You can delete or move spam messages while you are scanning %inbox. +If you use "bogofilter", put the following to your "~/.mew.el". + + (setq mew-imap-spam-field "X-Bogosity") + (setq mew-imap-spam-word "Yes") + +If `mew-imap-spam-folder' or `mew-imap-trash-folder' is defined, spam +messages are moved to the folder. Otherwise, they are removed. + +(3) In the case where you installed "bogofilter" in your local +machine, you can put the `*' mark to spam messages. First you need to +install the following script, say "bogo": + + #!/bin/sh + + bogofilter -v -T -B $* | grep S + +Type `?' and `RET', then specify "bogo", and spam messages are marked +with `*'. After that, you may want to process them with `md' + `x'. + +(4) In the case where you use POP and a spam filter does not run on +the POP server but you want to mark spam messages when retrieving + +Since bsfilter can be a POP proxy server, you can implement your +policy. See a document in the bsfilter package. + + + +File: mew.info, Node: spam2, Next: addr-warn, Prev: spam, Up: Tips + +Spam messages(2) +================ + +If you want to let your filter learn the current message in Summary as +a spam, type `ls'. Likewise type `lh' to let your filter learn it as a +ham (non-spam). + +To use these commands, you need to configure four variables in +advance. We consider bogofilter as an example and see three cases. + +(2) To let your local filter learn: + + (setq mew-spam-prog "bogofilter") + (setq mew-spam-prog-args '("-s" "-N" "-v")) + (setq mew-ham-prog "bogofilter") + (setq mew-ham-prog-args '("-n" "-S" "-v"))) + +(2) To let your filter on your learn via SSH: + + (setq mew-spam-prog "ssh") + (setq mew-spam-prog-args '("" "bogofilter" "-s" "-N" "-v")) + (setq mew-ham-prog "ssh") + (setq mew-ham-prog-args '("" "bogofilter" "-n" "-S" "-v"))) + +(3) To pass through your with SSH and to let your filter on +your learn via SSH: + + (setq mew-spam-prog "ssh") + (setq mew-spam-prog-args '("-A" "" "ssh" "" "bogofilter" "-s" "-N" "-v")) + (setq mew-ham-prog "ssh") + (setq mew-ham-prog-args '("-A" "" "ssh" "" "bogofilter" "-n" "-S" "-v"))) + +If you use SSH, you need to configure related hosts so that you can +login them without passwords. + + + +File: mew.info, Node: addr-warn, Next: biff, Prev: spam2, Up: Tips + +Warning addresses +================= + +Suppose you are writing a message which must be closed in your +company. You might write an non-employee's address by mistake. If you +tells your company's domains, for instance, to Mew, it turns +non-employee's addresses to red. + +There are four variables to decide which address should trun red. +They are all a list of strings. Mew takes the following rules: + + 1. If an address is specified in `mew-safe-addresses', no warning. + 2. If the address is specified in `mew-warn-addresses', warning. + 3. If its domain is specified in `mew-safe-domains', no warning. + 4. If its domain is specified in `mew-warn-domains', warning. + 5. If either `mew-warn-addresses' or `mew-safe-domains' defined, + warning. + 6. No warning. + +Here is an example that an address whose domain is not "@example.org" +turns red. + + (setq mew-safe-domains '("example.org")) + +If you want "customers@example.org" to turn red even its domain is +"@example.org", add the following line. + + (setq mew-warn-addresses '("customers@example.org")) + + + +File: mew.info, Node: biff, Next: edit, Prev: addr-warn, Up: Tips + +Biff +==== + +The functionality to check new messages is called biff. With the +following configuration Mew sees how many new messages have arrived +every 5 minutes. + + (setq mew-use-biff t) + +If one or more new messages exist, the total number is displayed in +the mode line. + +The server and the protocol, which Mew checks, are decided according +to `mew-proto' and the "case" (`mew-case') on boot time. + +With the following configuration, Mew beeps when the number of new +messages changes from zero to one or more. + + (setq mew-use-biff-bell t) + +To change the interval time of biff, set `mew-biff-interval'. Below +is an example to set it to 10 minutes. + + (setq mew-biff-interval 10) + + + +File: mew.info, Node: edit, Next: Convention, Prev: biff, Up: Tips + +Edit +==== + +Edit mode is a mode to edit a message to generate another new message. +The followings are typical examples: + + - Saving a new message with big attachments removed + - Saving a decrypted message whose original one is encrypted with + PGP/MIME or S/MIME + +To edit a current message in Edit mode, type `M-e'. Then, a new draft +is prepared like Draft mode. In Edit mode, you can edit a message as +if you were in Draft mode. + +To save edited message to a new message, type `C-cC-c' or +`C-cC-m'. They are the exactly same command. To execute one of them, +you are asked a folder to save the new message. + +Please take care that you may confuse this command as retry sending +(*Note sum-write::). Retry seinding is to send a message after editing +while Edit mode is to save a message after modifying. + +The following is summary of commands relating to Edit mode. To enter +Edit mode from Summary mode, use the following command. + +`M-e' + Entering Edit mode with the current message. + +The following is a summary of commands in Edit mode. + +`C-cC-c' + Saving the edited message to a new message. +`C-cC-m' + The same as `C-cC-c' +`Other commands' + The same as the other commands in Edit mode + + + + +File: mew.info, Node: Convention, Next: Implementation, Prev: edit, Up: Top + +E-mail convention +***************** + +When you exchange messages with other people, you should obey minimum +manner. It gives a bad impression to the people if you violate the +manner since such messages are hard to read. We always should try to +write concise yet comprehensive explanations and make an effort to +make receivers well-understood. + +We should take good care of the following items. + +Fill To: and Cc: fields precisely + To: is for target receivers and Cc: is for those who are received + for their information. If his address is not on To:, he might + skip to read the message. We should take care not to deliver to + wrong people by mistaking the addresses. + +The number of addresses To: and Cc: should be small + It is discouraged to specify a lot of mail addresses on To: and + Cc:. You should create a mailing-list instead. Or, if necessary, + you should make the destination anonymous (*Note anonymous::). + +Write a short and clear summary of body in Subject: + There are people who decide to read contents from their + Subject:. So, they might skip messages with improper Subject:. We + should not write a long subject since it is hard to read. + +Cite only necessary sentences + You should not bother to remove unnecessary sentences. With Mew, + citation must be a piece of cake. + +Make your signature simple + A long signature is just self-satisfaction. + +Do not send prank messages + I do not want to warn this kind of stuff. Nonetheless, someone + sends Happy or Unhappy messages to others. You should understand + that people doubt your character. + +Attach data files that the receivers can read + It is text only that you can send without any agreement with the + receivers. If you want to send data files other than text, you + should make an agreement with the receivers. To mailing-list, you + should send text only. + +If you wish to learn manner on the Internet more comprehensively, +please refer to RFC1855. + + + + +File: mew.info, Node: Implementation, Next: Avail, Prev: Convention, Up: Top + +Implementation Issues +********************* + +Why are "mewl" and "mewencode" necessary? + With Mew, you can read throw messages in Summary mode while you + are retrieving messages or listing the messages again. This means + that multiple control flows of program are necessary. To make + multiple control flows by Emacs, the only way is to make a TCP + connection or to execute sub-process (Emacs Lisp does NOT provide + a feature of light weight process). For POP and SMTP, Mew makes a + TCP connection, so they are not a problem. However, to list the + messages in Summary mode again, we have to execute a + command. This is why "mewl" exists. The reason why "mewencode" + exists is just for speed. When I programmed MIME encoding by + Emacs Lisp in several ways, they are too slow to use. So, I + decided to continue to use "mewencode". (If Base64 is implemented + by Emacs, Mew uses the native function.) + +Why does the cursor jump onto the end of line when searching(`C-s', `C-r')? + Thread informations are not displayed in Summary mode. This is + because the "invisible" property is dynamically put onto them + when displayed. Strings with this property is not a target of the + string search. But, thread informations of undisplayed lines do + not have this property, so the string search targets them. Then a + matched line is displayed and the "invisible" property is + put. So, it seems to you that the string search matches the end + of the line. Mew puts the "invisible" property for all lines in + Summary mode in background while there are no user key + inputs. When this word is finished, the `*' mark in the right + side of the mode line in Summary mode disappears. In this + situation, string search works exactly as you expect. + +MS's mailers can handle file names well if I attach files with Mew 4.3 + MS's mailers use "non-standard MS original" encoding to encode + file names. MS mailers should migrate to the standard + encoding. I repeatedly asked MS to do so, but they did not. So, + Mew took the following workaround: Mew basically uses the + standard encoding. In addition, Mew add "MS original parameter" + with file names encoded with "MS original" encoding. + + + + + +File: mew.info, Node: Avail, Next: obtain, Prev: Implementation, Up: Top + +Availability and mailing-list +***************************** + +This chapter describes how to get Mew and related mailing-lists. + +* Menu: + +* obtain:: How to get Mew? +* ml:: Mailing list + + + +File: mew.info, Node: obtain, Next: ml, Prev: Avail, Up: Avail + +How to get Mew? +=============== + +The latest Mew is available from the following repository. + + http://www.Mew.org/Release/ + +If you want to know about Git versions of Mew, please refer to: + + http://www.mew.org/en/git/ + + + +File: mew.info, Node: ml, Next: Copyright, Prev: obtain, Up: Avail + +Mailing list +============ + + +If you want to receive release announcement, please subscribe yourself +to mew-release. + + http://www.mew.org/mailman/listinfo/mew-release + +If you want to ask questions and/or discuss features in English, +please subscribe yourself to mew-int. + + http://www.mew.org/mailman/listinfo/mew-int + + + + +File: mew.info, Node: Copyright, Next: Variable Index, Prev: ml, Up: Top + +Copyright +********* + +Mew conforms the following copyright. + +Copyright (C) 1994-2013 Mew developing team. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. Neither the name of the team nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +If you wish to distribute Mew in CD or something, please let me +know. I do not go mad even if you do not tell me but I'm very glad if +you do so. I never have declined requirements. + +The copyright of this manual belongs to the author. Permission is +granted to copy, modify, redistribute this manual but no warranty. + + + + +File: mew.info, Node: Variable Index, Next: Key Index, Prev: Copyright, Up: Top + +Variable Index +************** + + +* Menu: + +* mail-user-agent: Composing. (line 5) +* mail-user-agent: configuration. (line 5) +* mail-user-agent: start. (line 5) +* mew-addrbook-for-cite-label: draft-mode. (line 5) +* mew-addrbook-for-cite-prefix: draft-mode. (line 5) +* mew-addrbook-mode-hook: hooks. +* mew-addrbook-override-by-newone: auto-alias. (line 5) +* mew-ask-charset: charset. (line 5) +* mew-ask-fcc: send. (line 5) +* mew-ask-subject: send. (line 5) +* mew-auto-flush-queue: retrieving. (line 5) +* mew-auto-get: start. (line 5) +* mew-before-cite-hook: hooks. +* mew-biff-interval: biff. (line 5) +* mew-case-guess-alist: config. (line 5) +* mew-case-guess-when-composed: config. +* mew-case-guess-when-prepared: config. +* mew-case-guess-when-replied-alist: config. (line 5) +* mew-case-guess-when-replied: config. +* mew-cc: draft-mode. (line 5) +* mew-charset-latin: charset. (line 5) +* mew-charset-m17n: charset. (line 5) +* mew-cite-fields: draft-mode. (line 5) +* mew-cite-format: draft-mode. (line 5) +* mew-cite-hook: hooks. +* mew-cite-prefix: draft-mode. (line 5) +* mew-cite-prefix-function: draft-mode. (line 5) +* mew-config-alist: config. (line 5) +* mew-config-alist: config2. (line 5) +* mew-cs-samba: custom-misc. (line 5) +* mew-cursor-mark: highlight. (line 5) +* mew-dcc: draft-mode. (line 5) +* mew-debug: status-update. (line 5) +* mew-decode-broken: analysis. +* mew-decode-broken: status-update. (line 5) +* mew-decode-quoted: invalid. (line 5) +* mew-delete-unread-mark-by-mark: unread mark. (line 5) +* mew-draft-mode-edit-again-hook: hooks. +* mew-draft-mode-hook: hooks. +* mew-draft-mode-newdraft-hook: hooks. +* mew-draft-mode-reedit-draft-hook: hooks. +* mew-draft-mode-reedit-hook: hooks. +* mew-draft-mode-reedit-queue-hook: hooks. +* mew-draft-privacy-method: shortcut. (line 5) +* mew-end-of-message-string: multipart. (line 5) +* mew-end-of-part-string: multipart. (line 5) +* mew-env-hook: hooks. +* mew-field-delete-for-forwarding: forward. (line 5) +* mew-field-for-printing: custom-misc. (line 5) +* mew-fields: header. (line 5) +* mew-file-max-size: analysis. +* mew-flowed-auto-wrap: longline. (line 5) +* mew-flowed-fold-length: longline. (line 5) +* mew-flowed-fold-threshold: longline. (line 5) +* mew-from-list: cheader. (line 5) +* mew-ham-prog-args: spam2. (line 5) +* mew-ham-prog: spam2. (line 5) +* mew-header-alist: draft-mode. (line 5) +* mew-header-max-length: analysis. +* mew-header-mode-hook: hooks. +* mew-header-veil-count: features. (line 5) +* mew-highlight-body-max-size: highlight. (line 5) +* mew-imap-auth: imap. +* mew-imap-auth-list: imap. +* mew-imap-delete: imap. +* mew-imap-delete: retrieving. (line 5) +* mew-imap-header-only: imap. +* mew-imap-header-only: retrieving. (line 5) +* mew-imap-sentinel-hook: hooks. +* mew-imap-sentinel-hook: hooks. +* mew-imap-sentinel-non-biff-hook: hooks. +* mew-imap-server: configuration. (line 5) +* mew-imap-server: imap. +* mew-imap-size: imap. +* mew-imap-spam-field: spam. (line 5) +* mew-imap-spam-folder: spam. (line 5) +* mew-imap-spam-word: spam. (line 5) +* mew-imap-ssh-server: imap. +* mew-imap-ssl: imap. +* mew-imap-ssl-port: imap. +* mew-imap-trash-folder: delete mark. (line 5) +* mew-imap-trash-folder-list: delete mark. (line 5) +* mew-imap-user: imap. +* mew-inbox-action-alist: spam. (line 5) +* mew-init-hook: hooks. +* mew-lisp-max-length: auto-alias. (line 5) +* mew-lisp-max-length: by-from. (line 5) +* mew-lisp-max-length: by-thread. (line 5) +* mew-mail-address-list: reply. (line 5) +* mew-mail-domain-list: cheader. (line 5) +* mew-mailbox-type: config. (line 5) +* mew-mailbox-type: configuration. (line 5) +* mew-mailbox-type: retrieving. (line 5) +* mew-mailbox-type: start. (line 5) +* mew-make-message-hook: hooks. +* mew-mbox-command-arg: configuration. (line 5) +* mew-mbox-command: configuration. (line 5) +* mew-message-hook: hooks. +* mew-message-mode-hook: hooks. +* mew-mime-multipart-alternative-list: message-mode. (line 5) +* mew-name: configuration. (line 5) +* mew-nntp-header-only: nntp. +* mew-nntp-header-only: retrieving. (line 5) +* mew-nntp-msgid-domain: nntp. +* mew-nntp-msgid-user: nntp. +* mew-nntp-newsgroup: nntp. +* mew-nntp-sentinel-hook: hooks. +* mew-nntp-server: configuration. (line 5) +* mew-nntp-server: nntp. +* mew-nntp-size: nntp. +* mew-nntp-ssh-server: nntp. +* mew-nntp-ssl: nntp. +* mew-nntp-ssl-port: nntp. +* mew-nntp-user: nntp. +* mew-nntp2-flush-hook: hooks. +* mew-nntp2-sentinel-hook: hooks. +* mew-pack-hook: hooks. +* mew-pick-pattern-list: condition. (line 5) +* mew-pop-auth-list: pop. +* mew-pop-auth: pop. +* mew-pop-body-lines: pop. +* mew-pop-delete: pop. +* mew-pop-delete: retrieving. (line 5) +* mew-pop-header-only: pop. +* mew-pop-header-only: retrieving. (line 5) +* mew-pop-sentinel-hook: hooks. +* mew-pop-sentinel-non-biff-hook: hooks. +* mew-pop-server: pop. +* mew-pop-size: pop. +* mew-pop-ssh-server: SSH. (line 5) +* mew-pop-ssh-server: pop. +* mew-pop-ssl: SSL. (line 5) +* mew-pop-ssl: pop. +* mew-pop-ssl-port: SSL. (line 5) +* mew-pop-ssl-port: pop. +* mew-pop-user: configuration. (line 5) +* mew-pop-user: pop. +* mew-post-hook: hooks. +* mew-print-function: custom-misc. (line 5) +* mew-print-function: features. (line 5) +* mew-prog-gpg: cipher-viewing. (line 5) +* mew-prog-grep: condition. (line 5) +* mew-prog-grep-opts: condition. (line 5) +* mew-prog-msexcel-ext: message-mode. (line 5) +* mew-prog-msexcel: message-mode. (line 5) +* mew-prog-mspowerpoint-ext: message-mode. (line 5) +* mew-prog-mspowerpoint: message-mode. (line 5) +* mew-prog-msword-ext: message-mode. (line 5) +* mew-prog-msword: message-mode. (line 5) +* mew-prog-pgp: cipher-viewing. (line 5) +* mew-prog-pgp2: cipher-viewing. (line 5) +* mew-prog-pgp5: cipher-viewing. (line 5) +* mew-prog-text/html-ext: message-mode. (line 5) +* mew-protect-privacy-always: shortcut. (line 5) +* mew-protect-privacy-always-type: shortcut. (line 5) +* mew-protect-privacy-encrypted: shortcut. (line 5) +* mew-protect-privacy-encrypted-type: shortcut. (line 5) +* mew-protect-privacy-with-old-pgp-signature: shortcut. (line 5) +* mew-proto: config. (line 5) +* mew-proto: configuration. (line 5) +* mew-proto: start. (line 5) +* mew-quit-hook: hooks. +* mew-real-post-hook: hooks. +* mew-real-send-hook: hooks. +* mew-refile-auto-refile-skip-any-mark: auto-refile. (line 5) +* mew-refile-ctrl-multi: guess-rule. (line 5) +* mew-refile-guess-alist: by-alist. (line 5) +* mew-refile-guess-by-from-learn-hook: hooks. +* mew-refile-guess-control: guess-rule. (line 5) +* mew-refile-guess-from-me-is-special: by-from-folder. (line 5) +* mew-refile-guess-from-me-is-special: by-from. (line 5) +* mew-refile-guess-strip-domainpart: by-default. (line 5) +* mew-reply-all-alist: reply. (line 5) +* mew-reply-fromme-alist: reply. (line 5) +* mew-reply-sender-alist: reply. (line 5) +* mew-safe-addresses: addr-warn. (line 5) +* mew-safe-domains: addr-warn. (line 5) +* mew-scan-sentinel-hook: hooks. +* mew-search-method: dbsearch. (line 5) +* mew-send-hook: hooks. +* mew-signature-as-lastpart: cite. (line 5) +* mew-signature-file: cite. (line 5) +* mew-signature-insert-last: cite. (line 5) +* mew-smtp-auth-list: smtp. +* mew-smtp-flush-hook: hooks. +* mew-smtp-helo-domain: smtp. +* mew-smtp-mail-from: smtp. +* mew-smtp-msgid-domain: smtp. +* mew-smtp-msgid-user: smtp. +* mew-smtp-port: smtp. +* mew-smtp-sentinel-hook: hooks. +* mew-smtp-server: configuration. (line 5) +* mew-smtp-server: smtp. +* mew-smtp-ssh-server: smtp. +* mew-smtp-ssl: SSL. (line 5) +* mew-smtp-ssl-port: smtp. +* mew-smtp-ssl: smtp. +* mew-smtp-user: smtp. +* mew-sort-default-key-alist: sorting. (line 5) +* mew-sort-default-key: sorting. (line 5) +* mew-sort-hook: hooks. +* mew-sort-key-alist: sorting. (line 5) +* mew-spam-prog-args: spam2. (line 5) +* mew-spam-prog: spam2. (line 5) +* mew-spam: spam. (line 5) +* mew-ssl-cert-directory: SSL. (line 5) +* mew-ssl-verify-level: SSL. (line 5) +* mew-status-update-hook: hooks. +* mew-summary-delete-folder-hook: hooks. +* mew-summary-exec-hook: hooks. +* mew-summary-form-extract-rule: summary-mode. (line 5) +* mew-summary-form-from-me-prefix: summary-mode. (line 5) +* mew-summary-form-mark-delete: summary-mode. (line 5) +* mew-summary-form-mark-review: summary-mode. (line 5) +* mew-summary-form-mark-spam: summary-mode. (line 5) +* mew-summary-form: summary-mode. (line 5) +* mew-summary-ls-no-scan-hook: hooks. +* mew-summary-mark-direction: summary-mode. (line 5) +* mew-summary-mode-hook: hooks. +* mew-summary-rename-folder-hook: hooks. +* mew-summary-show-direction: summary-mode. (line 5) +* mew-summary-toggle-disp-msg-hook: hooks. +* mew-suspend-hook: hooks. +* mew-syntax-format-hook: hooks. +* mew-theme-file: highlight. (line 5) +* mew-thread-display-hook: hooks. +* mew-thread-separator: thread. (line 5) +* mew-trash-folder: delete mark. (line 5) +* mew-trash-folder-list: delete mark. (line 5) +* mew-use-8bit: smtp. +* mew-use-8bit: status-update. (line 5) +* mew-use-alternative: analysis. +* mew-use-biff-bell: biff. (line 5) +* mew-use-biff: biff. (line 5) +* mew-use-cached-passwd: password. (line 5) +* mew-use-cursor-mark: highlight. (line 5) +* mew-use-fast-refile: by-folder. (line 5) +* mew-use-format-flowed: longline. (line 5) +* mew-use-full-window: summary-mode. (line 5) +* mew-use-header-veil: features. (line 5) +* mew-use-header-veil: status-update. (line 5) +* mew-use-highlight-body: highlight. (line 5) +* mew-use-highlight-cursor-line: highlight. (line 5) +* mew-use-highlight-header: highlight. (line 5) +* mew-use-highlight-mark: highlight. (line 5) +* mew-use-highlight-mouse-line: highlight. (line 5) +* mew-use-highlight-url: highlight. (line 5) +* mew-use-highlight-x-face: highlight. (line 5) +* mew-use-master-passwd: password. (line 5) +* mew-use-node-folder: by-folder. (line 5) +* mew-use-old-pgp: shortcut. (line 5) +* mew-use-old-pgp: status-update. (line 5) +* mew-use-samba-encoding: custom-misc. (line 5) +* mew-use-smtp-auth: smtp. +* mew-use-text-body: analysis. +* mew-use-text/html: analysis. +* mew-use-text/xml: analysis. +* mew-use-thread-separator: thread. (line 5) +* mew-use-unread-mark: unread mark. (line 5) +* mew-user: configuration. (line 5) +* mew-virtual-mode-hook: hooks. +* mew-visit-inbox-after-setting-case: visiting. (line 5) +* mew-visit-queue-after-sending: visiting. (line 5) +* mew-warn-addresses: addr-warn. (line 5) +* mew-warn-domains: addr-warn. (line 5) +* mew-warning-field-level: status-update. (line 5) +* mew-x-pgp-key-list: cipher-viewing. (line 5) +* read-mail-command: configuration. (line 5) + + + + diff --git a/elpa/mew-20150813.2354/mew.info-5 b/elpa/mew-20150813.2354/mew.info-5 new file mode 100644 index 00000000..528af1bc --- /dev/null +++ b/elpa/mew-20150813.2354/mew.info-5 @@ -0,0 +1,277 @@ +Info file: mew.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew: (mew.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +File: mew.info, Node: Key Index, Prev: Variable Index, Up: Top + +Key Index +********* + + +* Menu: + +* A (Summary): Composing. (line 5) +* A (Summary): reply. (line 5) +* A (Summary): sum-write. (line 5) +* B (Attach): mark-b-comp. (line 5) +* B (Summary): features. (line 5) +* C (Attach): charset-guess. (line 5) +* C (Attach): mime-comp. (line 5) +* C (Summary): features. (line 5) +* C-b (Attach): mime-comp. (line 5) +* C-cC-a (Draft): mime-comp. (line 5) +* C-cC-a (Summary): addrbook. (line 5) +* C-cC-a (Summary): features. (line 5) +* C-cC-b (Draft): shortcut. (line 5) +* C-cC-c (Addrbook): addrbook. (line 5) +* C-cC-c (Draft): send. (line 5) +* C-cC-c (Edit): edit. (line 5) +* C-cC-c (Header): resend. (line 5) +* C-cC-c (Summary): off-line. (line 5) +* C-cC-c (Summary): send. (line 5) +* C-cC-e (Draft): shortcut. (line 5) +* C-cC-e (Summary): message-mode. (line 5) +* C-cC-f (Draft): longline. (line 5) +* C-cC-f (Summary): cipher-viewing. (line 5) +* C-cC-l (Draft): cite. (line 5) +* C-cC-l (Summary): invalid. (line 5) +* C-cC-m (Draft): send. (line 5) +* C-cC-m (Edit): edit. (line 5) +* C-cC-m (Header): resend. (line 5) +* C-cC-o (Draft): config. (line 5) +* C-cC-o (Summary): visiting. (line 5) +* C-cC-pC-a (Draft): shortcut. (line 5) +* C-cC-pC-e (Draft): shortcut. (line 5) +* C-cC-pC-f (Draft): longline. (line 5) +* C-cC-pC-m (Draft): shortcut. (line 5) +* C-cC-q (Addrbook): Quit. (line 5) +* C-cC-q (Addrbook): addrbook. (line 5) +* C-cC-q (Draft): Quit. (line 5) +* C-cC-q (Header): Quit. (line 5) +* C-cC-q (Summary): Quit. (line 5) +* C-cC-r (Draft): shortcut. (line 5) +* C-cC-r (Summary): features. (line 5) +* C-cC-s (Draft): shortcut. (line 5) +* C-cC-s (Summary): features. (line 5) +* C-cC-t (Draft): cite. (line 5) +* C-cC-v (Summary): cipher-viewing. (line 5) +* C-cC-v (Summary): features. (line 5) +* C-cC-y (Draft): cite. (line 5) +* C-cC-z (Summary): cipher-viewing. (line 5) +* C-cC-z (Summary): features. (line 5) +* C-cTAB (Draft): cheader. (line 5) +* C-cTAB (Draft): cite. (line 5) +* C-cTAB (Summary): analysis. (line 5) +* C-f (Attach): mime-comp. (line 5) +* C-n (Attach): mime-comp. (line 5) +* C-n (Summary): singlepart. (line 5) +* C-p (Attach): mime-comp. (line 5) +* C-p (Summary): singlepart. (line 5) +* C-u: (Summary): analysis. (line 5) +* C-u. (Summary): analysis. (line 5) +* C-u. (Summary): invalid. (line 5) +* C-u/ (Summary): search. (line 5) +* C-u? (Summary): search. (line 5) +* C-uA (Summary): reply. (line 5) +* C-uC-cC-a (Summary): addrbook. (line 5) +* C-uC-cC-e (Summary): message-mode. (line 5) +* C-uC-cC-f (Summary): cipher-viewing. (line 5) +* C-uC-cC-l (Summary): invalid. (line 5) +* C-uD (Summary): delete mark. (line 5) +* C-uD (Summary): features. (line 5) +* C-uM-n (Summary): keyword. (line 5) +* C-uM-o (Summary): auto-refile. (line 5) +* C-uM-p (Summary): keyword. (line 5) +* C-uM-x mew: start. (line 5) +* C-uSPC (Summary): singlepart. (line 5) +* C-uZ (Summary): status-update. (line 5) +* C-ua (Summary): reply. (line 5) +* C-uj (Summary): singlepart. (line 5) +* C-uk/ (Summary): search. (line 5) +* C-ukI (Summary): dialog. (line 5) +* C-umI (Summary): target mark. (line 5) +* C-un (Summary): singlepart. (line 5) +* C-up (Summary): singlepart. (line 5) +* C-us (Summary): retrieving. (line 5) +* C-utt (Summary): thread. (line 5) +* C-uw (Summary): sum-write. (line 5) +* C-x RET l: charset-guess. (line 5) +* C-xm: Composing. (line 5) +* C-xm: start. (line 5) +* D (Attach): mime-comp. (line 5) +* D (Summary): delete mark. (line 5) +* D (Summary): features. (line 5) +* DEL (Summary): singlepart. (line 5) +* E (Attach): mark-b-comp. (line 5) +* E (Summary): sum-write. (line 5) +* F (Attach): mime-comp. (line 5) +* F (Summary): Composing. (line 5) +* F (Summary): forward. (line 5) +* F (Summary): sum-write. (line 5) +* F (Summary): target mark. (line 5) +* G (Attach): mark-b-comp. (line 5) +* I (Attach): charset-guess. (line 5) +* I (Summary): retrieving. (line 5) +* J (Summary): target mark. (line 5) +* M-RET (Summary): singlepart. (line 5) +* M-\ (Summary): target mark. (line 5) +* M* (Summary): unmark. (line 5) +* M-b (Summary): target mark. (line 5) +* M-d (Summary): delete mark. (line 5) +* M-e (Attach): mark-b-comp. (line 5) +* M-e: edit. (line 5) +* M-l (Summary): features. (line 5) +* M-n (Summary): keyword. (line 5) +* M-o (Summary): auto-refile. (line 5) +* M-p (Summary): keyword. (line 5) +* M-s (Attach): mark-b-comp. (line 5) +* M-s (Summary): sorting. (line 5) +* M-t (Summary): target mark. (line 5) +* M-u: unread mark. (line 5) +* M-x mew: Viewing. (line 5) +* M-x mew-send: Composing. (line 5) +* M-x mew-send: start. (line 5) +* M-x mew: start. (line 5) +* Md (Summary): delete mark. (line 5) +* N (Summary): target mark. (line 5) +* P (Attach): mime-comp. (line 5) +* P (Summary): target mark. (line 5) +* Q (Attach): mark-b-comp. (line 5) +* Q (Summary): Quit. (line 5) +* RET (Summary): singlepart. (line 5) +* Rd (Summary): features. (line 5) +* Rr (Summary): features. (line 5) +* S (Attach): mark-b-comp. (line 5) +* S (Summary): sorting. (line 5) +* SPC (Summary): singlepart. (line 5) +* : (Summary): analysis. (line 5) +* , (Summary): analysis. (line 5) +* . (Summary): analysis. (line 5) +* ; (Summary): features. (line 5) +* = (Summary): features. (line 5) +* | (Summary): features. (line 5) +* # (Summary): features. (line 5) +* _ (Summary): features. (line 5) +* _ (Summary): longline. (line 5) +* / (Summary): search. (line 5) +* ? (Summary): search. (line 5) +* - (Summary): singlepart. (line 5) +* * (Summary): target mark. (line 5) +* T (Attach): mime-comp. (line 5) +* TAB (Draft): header. (line 5) +* U (Attach): mark-b-comp. (line 5) +* U (Summary): unmark. (line 5) +* V (Summary): dialog. (line 5) +* ) (Virtual): thread. (line 5) +* ( (Virtual): thread. (line 5) +* & (Virtual): thread. (line 5) +* ^ (Virtual): thread. (line 5) +* W (Summary): resend. (line 5) +* W (Summary): sum-write. (line 5) +* Z (Attach): mark-b-comp. (line 5) +* Z (Summary): auto-alias. (line 5) +* Z (Summary): status-update. (line 5) +* a (Attach): mime-comp. (line 5) +* a (Summary): Composing. (line 5) +* a (Summary): reply. (line 5) +* a (Summary): sum-write. (line 5) +* b (Summary): features. (line 5) +* c (Attach): mime-comp. (line 5) +* d (Attach): mime-comp. (line 5) +* d (Summary): delete mark. (line 5) +* e (Attach): mime-comp. (line 5) +* f (Attach): mime-comp. (line 5) +* f (Summary): Composing. (line 5) +* f (Summary): forward. (line 5) +* f (Summary): sum-write. (line 5) +* g (Summary): moving. (line 5) +* i (Attach): mime-comp. (line 5) +* i (Summary): retrieving. (line 5) +* i (Summary): send. (line 5) +* j (Summary): singlepart. (line 5) +* k/ (Summary): search. (line 5) +* k? (Summary): search. (line 5) +* kI (Summary): dialog. (line 5) +* kM: dbsearch. (line 5) +* kc: dbsearch. (line 5) +* km: dbsearch. (line 5) +* lc (Summary): copy-msg. (line 5) +* lh (Summary): spam2. (line 5) +* li (Summary): copy-msg. (line 5) +* ls (Summary): spam2. (line 5) +* lx: off-line. (line 5) +* m (Attach): mime-comp. (line 5) +* m* (Summary): mark change. (line 5) +* m$ (Summary): mark change. (line 5) +* m*: escape mark. (line 5) +* m$: escape mark. (line 5) +* mI (Summary): target mark. (line 5) +* mM-d (Summary): delete mark. (line 5) +* mM-d (Summary): mark change. (line 5) +* mM-u (Summary): mark change. (line 5) +* ma (Summary): target mark. (line 5) +* mc (Summary): mark change. (line 5) +* md (Summary): delete mark. (line 5) +* md (Summary): mark change. (line 5) +* mlc (Summary): copy-msg. (line 5) +* mli (Summary): copy-msg. (line 5) +* mo (Summary): mark change. (line 5) +* mr (Summary): target mark. (line 5) +* ms (Summary): mark change. (line 5) +* mt (Summary): thread. (line 5) +* mxM-d (Summary): delete mark. (line 5) +* mxd (Summary): delete mark. (line 5) +* n (Summary): singlepart. (line 5) +* o (Summary): refile mark. (line 5) +* p (Attach): mime-comp. (line 5) +* p (Attach): pgp-key. (line 5) +* p (Summary): singlepart. (line 5) +* q (Summary): Quit. (line 5) +* r (Summary): resend. (line 5) +* s (Summary): off-line. (line 5) +* s (Summary): retrieving. (line 5) +* t (Attach): mime-comp. (line 5) +* t (Virtual): thread. (line 5) +* t* (Virtual): thread. (line 5) +* tM-d (Virtual): thread. (line 5) +* tSPC (Virtual): thread. (line 5) +* ta (Virtual): thread. (line 5) +* td (Virtual): thread. (line 5) +* tg (Virtual): thread. (line 5) +* tn (Virtual): thread. (line 5) +* to (Virtual): thread. (line 5) +* tp (Virtual): thread. (line 5) +* tr (Summary): thread. (line 5) +* tt (Summary): thread. (line 5) +* tu (Virtual): thread. (line 5) +* u (Summary): unmark. (line 5) +* v (Summary): features. (line 5) +* w (Summary): Composing. (line 5) +* w (Summary): sum-write. (line 5) +* x (Summary): Marks. (line 5) +* x (Summary): delete mark. (line 5) +* x (Summary): unmark. (line 5) +* y (Attach): mime-comp. (line 5) +* y (Summary): features. (line 5) +* z8 (Summary): status-update. (line 5) +* zSPC: unread mark. (line 5) +* zc (Summary): status-update. (line 5) +* zd (Summary): status-update. (line 5) +* zo (Summary): status-update. (line 5) +* zp (Summary): status-update. (line 5) +* zv (Summary): features. (line 5) +* zv (Summary): status-update. (line 5) +* zw (Summary): status-update. (line 5) +* zz (Summary): message-mode. (line 5) + diff --git a/elpa/mew-20150813.2354/mew.ja.info b/elpa/mew-20150813.2354/mew.ja.info new file mode 100644 index 00000000..ac9a09d6 --- /dev/null +++ b/elpa/mew-20150813.2354/mew.ja.info @@ -0,0 +1,130 @@ +Info file: mew.ja.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew-J: (mew.ja.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +Indirect: +mew.ja.info-1: 285 +mew.ja.info-2: 50442 +mew.ja.info-3: 101194 + +Tag table: +(Indirect) +Node: Top288 +Node: Overview1325 +Node: characteristic1968 +Node: Emacsen2980 +Node: modes3158 +Node: folder convention3668 +Node: configuration5541 +Node: password7870 +Node: start9334 +Node: Viewing10099 +Node: singlepart11078 +Node: multipart11982 +Node: analysis14247 +Node: cipher-viewing16508 +Node: retrieving19387 +Node: moving21950 +Node: sum-write23515 +Node: features24979 +Node: status-update26553 +Node: invalid27254 +Node: Composing28550 +Node: header30058 +Node: cheader30732 +Node: addr-comp31937 +Node: addrbook32932 +Node: auto-alias35071 +Node: addr-comp136081 +Node: addr-comp237774 +Node: send39135 +Node: cite41245 +Node: mime-comp42646 +Node: charset-guess48225 +Node: longline50445 +Node: reply51581 +Node: forward54586 +Node: resend55178 +Node: shortcut56359 +Node: mark-b-comp59771 +Node: pgp-key62185 +Node: anonymous62760 +Node: Marks63735 +Node: unread mark64878 +Node: delete mark65750 +Node: refile mark67335 +Node: target mark68328 +Node: escape mark69389 +Node: unmark69904 +Node: mark change70521 +Node: sync71386 +Node: off-line72079 +Node: mew-mark73346 +Node: Refile73874 +Node: by-folder75022 +Node: by-alist76203 +Node: by-thread77857 +Node: by-from-folder78473 +Node: by-from79426 +Node: by-newsgroups80637 +Node: by-default80872 +Node: guess-rule81229 +Node: auto-refile82757 +Node: copy-msg84458 +Node: Virtual85327 +Node: selection86445 +Node: sorting86951 +Node: dialog88229 +Node: search88895 +Node: condition89532 +Node: dbsearch91270 +Node: keyword92152 +Node: thread92651 +Node: thread-op93456 +Node: Quit94772 +Node: Customize95195 +Node: summary-mode95883 +Node: message-mode98672 +Node: draft-mode101197 +Node: charset103292 +Node: highlight104918 +Node: hooks106958 +Node: pop110364 +Node: imap111446 +Node: nntp112457 +Node: smtp113576 +Node: config115313 +Node: config2119827 +Node: custom-misc120983 +Node: Tips121700 +Node: region122227 +Node: visiting122736 +Node: SSH123098 +Node: SSL123695 +Node: TLS125251 +Node: spam125962 +Node: spam2127713 +Node: addr-warn128832 +Node: biff129605 +Node: edit130087 +Node: Convention130847 +Node: Implementation131887 +Node: Avail133346 +Node: obtain133595 +Node: ml133819 +Node: Copyright133999 +Node: Variable Index135007 +Node: Key Index150266 + +End tag table diff --git a/elpa/mew-20150813.2354/mew.ja.info-1 b/elpa/mew-20150813.2354/mew.ja.info-1 new file mode 100644 index 00000000..0868d053 --- /dev/null +++ b/elpa/mew-20150813.2354/mew.ja.info-1 @@ -0,0 +1,2065 @@ +Info file: mew.ja.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew-J: (mew.ja.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +File: mew.ja.info, Node: Top, Next: Overview, Prev: (dir), Up: (dir) + +Mew 6.7 マニュアル +****************** + + 山本和彦 + 作成 1996/02/19 + 更新 2015/07/03 + +このマニュアルでは、Mew バージョン 6.7 について解説します。このマニュ +アルの他に、Mew に関する有益な情報は Mew の公式ホームページ +(http://www.Mew.org/)から得られるかもしれません。 + + +* Menu: + +* Overview:: はじめに読んでね +* Viewing:: メッセージを表示する +* Composing:: メッセージを作成する +* Marks:: 愉快なマークたち +* Refile:: 楽々整理整頓 +* Virtual:: 仮想フォルダ +* Quit:: 一休み +* Customize:: カスタマイズ +* Tips:: さらなる一歩 +* Convention:: メッセージの作法 +* Implementation:: 実装について +* Avail:: 入手方法とメーリングリスト +* Copyright:: 著作権について +* Variable Index:: 変数索引 +* Key Index:: キー索引 + + + + +File: mew.ja.info, Node: Overview, Next: characteristic, Prev: Top, Up: Top + +はじめに読んでね +**************** + +Mew とは、テキスト・メールやマルチメディア・メール(MIME)、ニュース、セ +キュリティ機能(PGP、S/MIME、SSH、SSL)を便利に利用するためのユーザイン +ターフェイスです。最新の検索サービスとも連動します。 + +Mew は 「Messaging in the Emacs World」 の略です。先頭の M は大文字で +表記し、「みゅう」と読みます。M で始まるかわいらしい単語を選んだ結果 +Mewになりました。決して漫画の題名や某アイドルの歌、あるいは、関西の会 +社に因んでいるわけではありません。:p + +* Menu: + +* characteristic:: Mew の特長 +* Emacsen:: Emacs のバージョン +* modes:: モード +* folder convention:: フォルダの種類 +* configuration:: 初期設定 +* password:: パスワード +* start:: 起動 + + + + +File: mew.ja.info, Node: characteristic, Next: Emacsen, Prev: Overview, Up: Overview + +Mew の特長 +========== + +Mew バージョン 6.7 の特長を以下に示します。 + + - 複雑な構造を持つメッセージを簡単に表示できます。メッセージを表示 + する作業は、`SPC' を押すだけです。 + - コピー程度のファイルの操作を知っている人ならだれでも簡単に複雑な + メッセージを作成できます。 + - メッセージの一覧表示が終了するまで待たなくても、メッセージを読み + 始められます。 + - Summary モードのメッセージの一覧を保存しているので、フォルダを移 + 動した場合は、更新された部分だけを一覧表示します。 + - メッセージの整頓先を賢く推測します。たくさんメッセージを受け取る + 人は、これがないと生きていけません。 + - Draft モードでは、フィールド名、メールアドレス、氏名、ドメイン名、 + フォルダ名を補完できます。 + - キーワードなどによって、探したいメッセージを簡単に検索できます。 + - PGP や S/MIME で暗号化されたメッセージを自動的に復号化します。ま + た、電子署名を自動的に検証します。 + - MIME の構造を解析したり、PGP や S/MIME の署名を検証したりするのに + は少し時間がかかります。そこで、ユーザがあるメッセージを読んでい + る間に、次のメッセージをあらかじめ処理しておくことで高速性を実現 + しています。解析されたメッセージは、しばらくの間保存されます。 + - PGP や S/MIME を使って、メッセージを簡単に暗号化したり、署名した + りできます。 + - 複数のフォルダを 1 つのフォルダに見せかけられます。 + - メッセージのやり取りの流れを可視化するセレクションやスレッドの機 + 能を備えています。特定のキーワードに合致したメッセージでセレクショ + ンを作り、さらにそのスレッドを作成できます。 + - フォルダ名を入力する場合、フォルダ名の一部をキーとして検索できま + す。 + + + + +File: mew.ja.info, Node: Emacsen, Next: modes, Prev: characteristic, Up: Overview + +Emacs のバージョン +================== + +Emacs 22.3 以降を使って下さい。これらより前のバージョンや XEmacs は、 +サポートしていません。 + + + + +File: mew.ja.info, Node: modes, Next: folder convention, Prev: Emacsen, Up: Overview + +モード +====== + +Mew には次の 7 つのモードがあります。 + +`Summary モード' + メッセージの一覧を表示し選択するモード。 +`Virtual モード' + 単数あるいは複数のフォルダからある条件に合致したメッセージを取り + 出し、仮想的に 1 つのフォルダにしたモード。Summary モードに似てい + る。セレクションやスレッドと呼ばれる。 +`Message モード' + メッセージの内容を表示するモード。 +`Draft モード' + メッセージの送信、返答、転送を準備するためのモード。 +`Header モード' + 既存のメッセージのヘッダのみを編集し送信するためのモード。 +`Edit モード' + 既存のメッセージを編集し、新しいメッセージを作成するためのモード。 +`Addrbook モード' + アドレス帳にエントリを登録するためのモード。 + + + + +File: mew.ja.info, Node: folder convention, Next: configuration, Prev: modes, Up: Overview + +フォルダの種類 +============== + +Mew の用語では、メッセージが届く場所を「メールボックス」と呼びます。メー +ルボックスの種類としては、ローカルのメールボックス、POP サーバ、IMAP +サーバ、および NNTP サーバがあります。 + +また、Mew 自身がメッセージを格納する箱のことを「フォルダ」と呼びます。 +フォルダ名は、一文字の記号からなる修飾子と文字列が連結された形式になっ +ています。たとえば、「+inbox」というフォルダの修飾子は「+」です。 + +Mew のフォルダには、「ローカル・フォルダ」と「リモート・フォルダ」の 2 +種類があります。 + +ローカル・フォルダとは、Mew が動いているコンピュータに「本物」が作られ +るフォルダです。そのフォルダに格納されるメッセージも本物です。(ですか +ら、もしそのフォルダのメッセージを消してしまうと復元できません。) + +ローカル・フォルダの修飾子は "+" です。以下に特殊なローカル・フォルダ +を挙げます。 + +`+inbox' + ローカルのメールボックスや POP サーバに届いたメッセージを、ローカ + ルに移動させて最初に保存するためのローカル・フォルダ。メッセージ + を整理する場合は、"+inbox" から他のローカル・フォルダに移動させる + ことになる。 +`+draft' + 書きかけのメッセージを保存しておくローカル・フォルダ。 +`+queue' + 書き終ってメールの配送に適した書式に変換されたメッセージが溜るロー + カル・フォルダ。"+queue" のメッセージは、いずれ SMTP によって送信 + さる。 +`+postq' + 書き終ってニュースに投稿するのに適した書式に変換されたメッセージ + が溜るローカル・フォルダ。"+postq" のメッセージは、いずれ NNTP に + よって送信される。 + +リモート・フォルダとは、サーバ側にあるフォルダをローカルにコピーしたも +のです。本物のメッセージはあくまでサーバ側にあり、ローカルにはメッセー +ジのコピーがキャッシュされます。 + +利用できるリモート・フォルダの修飾子を以下に示します。 + +`%' + IMAP のフォルダ。例:"%inbox" +`$' + POP サーバのサーバ側のフォルダ。例:"$inbox" (POP サーバのフォル + ダは 1つしかないので、"$" で始まるリモート・フォルダは "$inbox" + のみ。) +`-' + ニュースのニュースグループ。例:"-fj.mail.reader.mew" + +サーバが異なれば、リモート・フォルダの実体も異なります。複数のサーバは、 +ケースという機能を使って指定します。詳しくは、*Note config:: を参照し +て下さい。あるケースに対するリモート・フォルダは、"case:folder" のよう +に、フォルダ名の前にケース名を付けて指定します。ケースが "default" で +ある場合は、"case:" の部分を省略可能です。 + +ケースと修飾子の組は、あるメッセージが属す世界を構成しています。メッセー +ジは、それが属す世界の中を移動できます。受け取ったメッセージは、後で探 +しやすいように、適切なフォルダに移動させて保存します。この整頓の方法に +ついて、*Note Refile:: を参照して下さい。 + +なお、POP サーバには "$inbox" というフォルダしかありませんから、"$" の +世界でメッセージを移動させることはできません。また、ニュースの記事は自 +分のものではありませんから、"-" の世界でもメッセージの移動は不可能です。 + +世界を超えてメッセージを移動させたい場合は、コピーします。ただし、コピー +先はローカル・フォルダに限定されます。この方法は、*Note retrieving:: +で説明されています。 + +フォルダのリストを作成しておくと、フォルダ名に対し補完が利用できて便利 +です。フォルダのリストを作成する方法は、*Note status-update:: を参照し +て下さい。 + + + + +File: mew.ja.info, Node: configuration, Next: password, Prev: folder convention, Up: Overview + +初期設定 +======== + +Mew を起動するには、組織の設定ファイルか自分の "~/.emacs" に以下の設定 +が必要です。 + + (autoload 'mew "mew" nil t) + (autoload 'mew-send "mew" nil t) + + ;; Optional setup (Read Mail menu): + (setq read-mail-command 'mew) + + ;; Optional setup (e.g. C-xm for sending a message): + (autoload 'mew-user-agent-compose "mew" nil t) + (if (boundp 'mail-user-agent) + (setq mail-user-agent 'mew-user-agent)) + (if (fboundp 'define-mail-user-agent) + (define-mail-user-agent + 'mew-user-agent + 'mew-user-agent-compose + 'mew-draft-send-message + 'mew-draft-kill + 'mew-send-hook)) + +Latin-1 のために、Emacs を --unibyte オプション付で起動しているか、環 +境変数 EMACS_UNIBYTE と共に起動している場合、以下の設定を "~/.emacs" +に入れて下さい。 + + (set-language-environment "Latin-1") + (set-input-method "latin-1-prefix") ;; or "latin-1-postfix" + +Latin-1 のために、以下のような設定をしているなら、削って下さい。これは +Latin-1 にカスタマイズするための方法としては推奨されていませんし、この +設定では Mew は正しく動きません。 + + (standard-display-european 1) + +Mew は起動時に、"~/.mew.el" を読み込みます。Mew に関する設定は、このファ +イルに入れるとよいでしょう。 + +メールアドレスを指定するために、以下の設定が必要です。 + + ;; (setq mew-name "your name") ;; (user-full-name) + ;; (setq mew-user "user name of e-mail address") ;; (user-login-name) + (setq mew-mail-domain "domain of e-mail address") + +SMTP を使ってメッセージを送信するためには、以下の設定が必要です。 + + (setq mew-smtp-server "your SMTP server") ;; if not localhost + +POP を使ってメッセージを受信する場合は、以下の設定が必要です。 + + ;; (setq mew-pop-user "your POP account") ;; (user-login-name) + (setq mew-pop-server "your POP server") ;; if not localhost + +メッセージの受信にローカルのメールボックスを利用したい場合は、以下のよ +うな設定が必要です。 + + ;; To use local mailbox "mbox" or "maildir" instead of POP + (setq mew-mailbox-type 'mbox) + (setq mew-mbox-command "incm") + (setq mew-mbox-command-arg "-u -d /path/to/mbox") + ;; If /path/to/mbox is a file, it means "mbox". + ;; If /path/to/mbox is a directory, it means "maildir". + +IMAP を使ってメッセージを受信する場合は、以下の設定が必要です。 + + (setq mew-proto "%") + ;; (setq mew-imap-user "your IMAP account") ;; (user-login-name) + (setq mew-imap-server "your IMAP server") ;; if not localhost + +ニュースを読み書きする場合は、以下の設定が必要です。 + + ;; (setq mew-nntp-user "your NNTP account") + (setq mew-nntp-server "your NNTP server") + + + + +File: mew.ja.info, Node: password, Next: start, Prev: configuration, Up: Overview + +パスワード +========== + +メッセージを送受信したり、PGP や S/MIME を使ったりする場合には、パスワー +ドを訊かれることがあります。パスワードを入力する前に以下の条件のどちら +かが満たされていることを確認しましょう。 + + - Emacs が目の前のコンピュータで動いている + - Emacs が遠隔のコンピュータで動いているが、なんらかの暗号手段を使っ + て通信している。 + +どちらの条件も満たされない場合は、パスワードを入力しないで下さい。入力 +すると盗聴される恐れがあります。 + +パスワードを何回も入力するのが面倒な人は、パスワードを保存する機能を利 +用して下さい。2 つの方法があります。 + + 1. パスワードをメモリに一時的に蓄える。ファイルには書き出さない。 + 2. パスワードをメモリに Mew が起動している間中蓄える。Mew/Emacs の終 + 了時に、パスワードを暗号化しファイルに書き出す。 + +1. の機能を利用するには、以下のように設定します。 + + (setq mew-use-cached-passwd t) + +2. の機能を利用するには、GnuPG をインストールした後、以下のように設定 +します。(GnuPG は、バージョン 1.x、2.0、2.1に対応しています。) + + (setq mew-use-master-passwd t) + +両方の変数が `t' の場合、2. の機能が利用されます。 + +1. の機能:あらゆるパスワード(POP、PGP など)が一時的にメモリに保存され +ます。パスワードが保存されている間は、パスワードの入力を省略できます。 +保存されているパスワードは一定時間(通常は 20 分)が過ぎると消去されます。 +ただし、保存されているパスワードが内部で利用されると、保存期間が延長さ +れます(20 分に戻ります)。 + +2. の機能:Mew の起動時に、マスターパスワードを訊かれます。Mew はその +マスターパスワードで、暗号化されているパスワードを復号化し、メモリに蓄 +えます。たとえば、以前 POP のパスワードを入力していれば、それがメモリ +に蓄えられていますから、次に POP のパスワードが必要な際、POP のパスワー +ドの入力を省略できます。はじめてマスターパスワードを利用する際は、確認 +のためマスターパスワードを 2 回訊きます。また、たとえば POP のパスワー +ドも1 回だけ入力するように促されます。Mew の起動時に、間違ったマスター +パスワードを入力することもあるでしょう。その場合、1. の機能を有効にし +ているなら、1. の機能が使われます。有効でなければ、パスワードの保存機 +能は利用されません。 + +マスターパスワードを変更するには、Summary モードで `C-cC-m' と入力しま +す。 + +メモリに保存されているパスワードは、暗号化されていません。そこで、 +1. または 2. の方法を使う場合は、他の人に自分が起動した Emacs を触られ +ないように気をつけて下さい。もし席を空け、Emacs をよく知っている他の人 +にEmacs を操作された場合、パスワードを盗み取られる可能性があります。 + + + + +File: mew.ja.info, Node: start, Next: Viewing, Prev: password, Up: Overview + +起動 +==== + +Mew を起動するには、以下の方法があります。 + +`M-x mew' + Mew が起動していなければ、まず Mew を起動する。そして、メッセージ + を取得するか、あるいは単にデフォルトのフォルダへ移動する。 + + まず、「修飾子」は `mew-proto' とケースから決定される。(*Note + config:: を参照) + + 「修飾子」が `+'(ローカル・フォルダ)なら、`mew-mailbox-type' から + メールボックスが決定される。(*Note retrieving:: を参照) その他、 + すなわちリモート・フォルダなら、メッセージを取得するためのプロト + コルが修飾子に応じて決る。 + + `mew-auto-get' が `t' なら、到着したメッセージが非同期に取得され、 + Summary モードへ一覧表示される。 + + `mew-auto-get' が `nil' なら、修飾子によって決定したデフォルトの + フォルダへ単に移動する。 +`C-uM-x mew' + `mew-auto-get' の値を逆だと考えて、`M-x mew' を実行する。 +`C-xm' + `mail-user-agent' が設定されている場合、Draft モードへ移行する。 + +Emacs で Mew を起動すると可愛い 2 匹の子が猫現れます。 + +なお、Mew を終了する方法は、*Note Quit:: を参照して下さい。 + + + + +File: mew.ja.info, Node: Viewing, Next: singlepart, Prev: start, Up: Top + +メッセージを表示する +******************** + +(Mew が起動中でも、起動中ではなくても) `M-x mew' と入力すると、Mew は +メッセージを以下のように一覧表示します。 + + * 03/12 Hidenori Ohta 今週末 |日曜にストーンマジック + M03/14 ももちゃん 能登の写真 |この前撮った写真を添付 + 03/15 Neat Sumikawa Re: ワイン |じゃぁ、水曜日に例の店 + +これを Summary モードといいます。ここでは、主に Summary モードでのメッ +セージの読み方について説明します。 + +上記の例のように Summary モードは、マーク、データ型(Mew が付けるマーク)、 +日付、差出人、Subject:、本文から構成されています。 + +Summary モードを消去する方法については、*Note Quit:: を参照して下さい。 + +* Menu: + +* singlepart:: 読み方の基礎 +* multipart:: MIME を表示する +* analysis:: MIME の解析を制御する +* cipher-viewing:: 暗号メールや電子署名を表示する +* retrieving:: メッセージの取得 +* moving:: フォルダの移動 +* sum-write:: 送信、返答、転送 +* features:: 便利な機能 +* status-update:: 状態の更新 +* invalid:: 規格違反のメッセージ + + + +File: mew.ja.info, Node: singlepart, Next: multipart, Prev: Viewing, Up: Viewing + +読み方の基礎 +============ + +メッセージを上から順に読んでいくのであれば、`SPC' を適宜押すだけです。 +簡単でしょ? + +しかしそれだけではあんまりなので、以下にページを操作する基本的なコマン +ドを示します。 + +`SPC' + メッセージを読み進める。つまり、メッセージを表示し、スクロールさせ、他の + メッセージに移動して表示する。カーソルが移動する方向は、 + *Note summary-mode:: を参照のこと。 +`C-uSPC' + メッセージを先頭から再表示。 +`DEL' + 現在のメッセージを下にスクロールさせる。不必要なヘッダフィールド + は、ウインドウの上に隠れている。よって、`DEL' を入力すると、それ + らが現れる。 +`RET' + 現在のメッセージを 1 行上にスクロールする。 +`M-RET' +`-' + 現在のメッセージを 1 行下にスクロールする。 + +`C-n' + 下の行へ移動。 +`C-p' + 上の行へ移動。 +`n' + 下方向に移動し表示。対象となるのは、パート、`*' マークの付いたメッ + セージ、マークの付いていないメッセージ。 +`C-un' + 下方向に移動し表示。対象となるのは、`*' マークの付いたメッセージ、 + マークの付いていないメッセージ。 +`p' + 上方向に移動し表示。対象となるのは、パート、`*' マークの付いたメッ + セージ、マークの付いていないメッセージ。 +`C-up' + 上方向に移動し表示。対象となるのは、`*' マークの付いたメッセージ、 + マークの付いていないメッセージ。 +`j' + 入力された行番号に従ってその行へ移動。 +`C-uj' + 入力されたメッセージの番号に従ってその行へ移動。 + + + +File: mew.ja.info, Node: multipart, Next: analysis, Prev: singlepart, Up: Viewing + +MIME を表示する +=============== + +マルチパートを読むのは別に大変なことではありません。今まで通り、 +`SPC' を押していけばよいだけです。 + +マルチパートのメッセージは、以下のように日付の左に `M' というマークが +付いています。 + + * 03/12 Hidenori Ohta 今週末 |日曜にストーンマジック + M03/14 ももちゃん 能登の写真 |この前撮った写真を添付 + 03/15 Neat Sumikawa Re: ワイン |じゃぁ、水曜日に例の店 + +`M' マークの付いたメッセージで `SPC' を押すと、ヘッダを Message モード +に表示すると共に、以下のように Summary モードでマルチパートの構造を簡 +素に表示します。 + + * 03/12 Hidenori Ohta 今週末 |日曜にストーンマジック + M03/14 ももちゃん 能登の写真 |この前撮った写真を添付 + B 2 Image/Jpeg 写真1 noto1.jpg + Q 3 Application/Postscript 能登の地図 map.ps + 03/15 Neat Sumikawa Re: ワイン |じゃぁ、水曜日に例の店 + +もし、パート 1 が Text/ なら、Summary モードにはパート 1 は可視化され +ず、そのかわりパート 1 がヘッダと共に Message モードに表示されます。 + +マルチパートの各行は + + - マーク (Content-Transfer-Encoding:) + - パート番号 + - データ型 (Content-Type:) + - 説明 (Content-Description:) + - ファイル名 (Content-Disposition:) + +から構成されています。Content-Description: はパートに対する Subject: +と考えていいでしょう。この表示は Draft モードの添付領域とほとんど同じ +です。 + +`SPC' や `n' でパート 2 へ進めば、そのパートがデータ型に応じて +表示されます。たとえば、Text/Plain なら Message モードで、PostScript な +ら "ghostview" で表示されます。 + +`n' や `p' は、パート部分まで含んだ行を移動することに注意して下さい。 +パート部分を飛ばして下のメッセージを表示するには `C-un' と入力して下さ +い。また、パート部分を飛ばして 1 つ上のメッセージを表示するには `C-up' +と入力して下さい。 + +Mew は、MIME を再帰的に処理します。以下は転送されたマルチパートのメッ +セージの例です。 + + M03/15 かずくん Fw: 能登の写真 |写真が送られてきたので + 2 Message/Rfc822 能登の写真 + B 2.2 Image/Jpeg 写真1 noto1.jpg + Q 2.3 Application/Postscript 能登の地図 map.ps + +(メモ) テキスト以外のデータを、シングルパートとしてメッセージに格納す +るのは、書式としては間違いではありませんが、お勧めできません。マルチパー +トを作成し、そのパート 1 に説明のテキストを、パート 2 にテキスト以外の +データを入れる作法をお勧めします。 + +テキスト以外のデータが本文に直接格納されているメッセージに対し、Mew は +これをあたかもマルチパートのように表示します。 + +このように MIME の構造は複雑になりうるので、解析するのには時間がかかる +場合があります。しかし、Mew は次に読まれるメッセージを予想し、ユーザが +現在のメッセージを読んでいる間に、次のメッセージをあらかじめ解析してお +くことで高速性を実現しています。解析されたメッセージは、しばらくの間保 +存されます。 + +メッセージの終りの部分がはっきりと分かるように、Mew はメッセージの最後 +に "[End of message]" という文字列を表示します。また、パートの終りでは、 +"[Message is continued]" という文字列を表示します。これらの文字列はそ +れぞれ、`mew-end-of-message-string' と `mew-end-of-part-string'で指定 +できます。 + + + +File: mew.ja.info, Node: analysis, Next: cipher-viewing, Prev: multipart, Up: Viewing + +MIME の解析を制御する +===================== + +メッセージの解析を制御するために、以下の変数が用意されています。 + +`mew-file-max-size' + 解析するメッセージの大きさの上限。メッセージの大きさがこの値以下 + なら、解析し表示する。越えているなら、解析せずに生のまま表示する。 + 初期値は 100000 バイト。 +`mew-header-max-length' + 解析するメッセージのヘッダ長の上限。ヘッダの行数がこの値以下なら、 + メッセージを解析して表示する。越えているなら、解析を途中で止めて + メッセージを壊れた形で表示する。初期値は 100 行。 +`mew-decode-broken' + 規格違反のメッセージを解析する際に、寛容になるか否か。`t' なら寛 + 容に、`nil' なら厳密に解析する。寛容に解析する際に規格違反があっ + た場合は、X-Mew: フィールドに表示する。初期値は `t'。 +`mew-use-text-body' + 本文のテキストをヘッダと同時に表示するか否か。`t' なら、本文がシ + ングルのテキスト、および、本文がマルチパートで最初のパートがテキ + ストの場合、そのテキストをヘッダと同時に表示する。`nil' の場合は、 + マルチパート内のパートのように表示する。初期値は `t'。 +`mew-use-alternative' + Multipart/Alternative の取り扱い。Multipart/Alternative であるメッ + セージには`-' マークが付いている。`t' なら、 + `mew-mime-multipart-alternative-list' の優先順位に従って、1 つの + パートを表示する。`nil' なら、通常のマルチパートとして表示する。 + 初期値は `t'。 +`mew-use-text/html' + Text/Html の取扱い。`nil' の場合は HTML を解析せずに表示。それ以 + 外なら HTML を解析して表示。初期値は `nil'。 +`mew-use-text/xml' + Text/Xml の取扱い。`nil' の場合は XML を解析せずに表示。それ以外 + なら XML を解析して表示。初期値は `nil'。 + +これらの変数に関する基本的なコマンドは、`.' です。このコマンドは、以下 +のように動きます。 + +1) このコマンドがメッセージ上で実行されると、そのメッセージのキャッシュ +が削除され、メッセージが解析されて再表示されます。 + +1a) もし現在のメッセージの大きさが `mew-file-max-size' を越えているな +ら、MIME は解析されず、そのまま表示されています。この場合、このコマン +ドはこの上限に関わらずに現在のメッセージを解析し、再表示します。 + +1b) もし現在のメッセージのヘッダ長が `mew-header-max-length' を越えて +いるなら、メッセージが壊れたように表示されています。この場合、このコマ +ンドはこの上限に関わらずに現在のメッセージを解析し、再表示します。 + +1c) もし現在のメッセージが `:' で表示されているなら、マルチパートの構 +造は、通常とは違うように表示されています。この場合、このコマンドはマル +チパートの構造を通常と同じように再表示します。 + +1d) もし `mew-use-text/html' が `nil' なら、HTML は解析されず、そのま +ま表示されています。この場合、このコマンドは HTML を解析し、再表示しま +す。 + +2) もしこのコマンドがパート上で実行された場合、そのパートが再表示され +ます。 + +2a) もし `mew-use-text/html' が `nil' なら、HTML は解析されず、そのま +ま表示されています。この場合、このコマンドは HTML を解析し、再表示しま +す。 + +`.' 以外にも、以下のような便利なコマンドがあります。 + +`.' + メッセージを解析し、再表示する。 +`C-u.' + `mew-decode-broken' を逆にしてメッセージを解析し直す。 + *Note invalid:: を参照のこと。 +`:' + `mew-use-alternative' と `mew-use-text-body' を反転させた + `.'. +`C-u:' + `mew-use-alternative' と `mew-use-text-body' を反転させた + `C-u.'. +`,' + 現在のメッセージやパートを生の書式で Message モードに表示する。 +`C-cTAB' + メッセージ全体をファイルとして read only で開く。 +`C-uC-cTAB' + メッセージ全体をファイルとして開く。 + + + +File: mew.ja.info, Node: cipher-viewing, Next: retrieving, Prev: analysis, Up: Viewing + +暗号メールや電子署名を表示する +============================== + +今までと同様 `SPC' などを利用することで、Mew では暗号化や電子署名を施 +されたメッセージを簡単に表示できます。まず、簡単な例から紹介しましょう。 + + S03/18 神田パソコン館 見積書 |先日承りましたノートPC + E03/21 匿名希望 秘密のメール | + +上記のメッセージには、それぞれ `S' マークと `E' マークが付いています。 +これはそれぞれ、本文全体が署名されている、および、暗号化されていること +を意味します。 + +PGP/MIME や S/MIME では、一部のパートに電子署名を施したり、暗号化したり +できます。この場合このようなマークは付きません。`S' マークや +`E' マークが付くのは、本文全体が対象になっている場合です。 + +また、単に署名や暗号化といいましたが、これは最終的な処理が署名や暗号化 +であったことを意味しています。やや複雑な話になりますが、もしかすると前 +者は本文全体を暗号化した後、署名したのかもしれませんし、後者は一部のパー +トに署名し、さらに全体を暗号化している可能性もあります。 + +本文全体、あるいは、一部のパートが暗号化されている場合、Mew はパスフレー +ズを訊いてきます。パスフレーズを入力する際の注意事項については、*Note +start:: を参照して下さい。入力されたパスフレーズは、あなたの秘密鍵を復 +号化するのに使われます。そして、復号化された秘密鍵によって、暗号化され +ているメッセージを解くわけです。 + +暗号メッセージを表示するには、暗号化された数だけパスフレーズを入力する +必要があります。これは Mew が安全を期して、通常パスフレーズを保存しな +いからです。もしこれがわずらわしいなら、Mew にパスフレーズを保存させる +ことも可能です。詳しくは、*Note password:: を参照して下さい。 + +パスフレーズを保存しない通常の設定でも、一旦復号化されたメッセージはし +ばらく保存されるので、2 回目の表示にはパスフレーズを訊かれないかもしれ +ません。 + +一方、通信相手の署名を検証するためには相手の公開鍵が利用できればよいの +で、パスフレーズを訊かれることはありません。 + +Mew は自動的に電子署名を検証したり、入力されたパスフレーズを使って暗号 +メッセージを復号化したりして、元のメッセージを表示します。そこで、ユー +ザが署名の存在に気づかないかもしれませんし、どの部分が暗号化されていた +のか分からないかもしれません。 + +そこで、検証の結果やどの部分が暗号化されているかをユーザに通知するため +に、Mew は以下のようにヘッダに X-Mew: フィールドを挿入します。 + + X-Mew: PGP decrypted. + Good PGP sign "kazu@example.org" COMPLETE + +"<>" 内の番号は、どのパートの結果であるかを示しています。"body" は、メッ +セージの本文全体が保護されていることを意味します。この例では、メッセー +ジ全体が kazu によって署名され、受信者のために暗号化されています。Mew +はまずこれを復号化し、そして署名を検証しています。署名は正しいので、 +kazu@example.org という ID の付いた秘密鍵で署名されたときから、内容は +変更されていないと分かります。この署名の検証に使われた公開鍵の「有効性」 +は "complete" です。よって、受信者はこの公開鍵が ID が示すユーザに属し +ていると信頼していることになります。つまり、このメッセージは信頼をおい +ている公開鍵によって検証され結果が正しいので、改竄されていないというこ +とになります。 + +以下の例では、まずマルチパートである本文全体の電子署名が検証され、その +後パート 2 のメッセージ全体が復号化されています。つまり、作成時には、 +まずパート 2 が暗号化され、そして本文全体が署名されたことが分かります。 + + X-Mew: Good PGP sign "kazu@example.org" COMPLETE + X-Mew: <2 message> PGP decrypted. + +するどい人なら、悪い人があらかじめ X-Mew: フィールドを挿入しておき、あ +なたをだますかもしれないと思うかもしれません。でも大丈夫です。Mew は、 +ヘッダにある X-Mew: をあらかじめ削り、本物の X-Mew: フィールドを挿入し +ますから。 + +PGP/MIME について: + +X-Mew: フィールドは他にもさまざまな結果を伝えてくれます。たとえば、署 +名を検証するための公開鍵がないとか、復号化に失敗したなどです。以下の例 +は、鍵 ID が 0x1B8BF431 である公開鍵がないことを示しています。 + + X-Mew: No his/her public key. ID = 0x1B8BF431 + +この場合、`C-cC-f' と入力すると、Mew はこの公開鍵の入手を試みます。そ +の際、公開鍵サーバを選択できます。もし、X-Mew: フィールドがない場合は、 +`C-cC-f' は From: を ID と考えます。また、`C-uC-cC-f' は、X-Mew: フィー +ルドに加えて `mew-x-pgp-key-list' に指定されたフィールドも鍵 ID を切り +出す対象とし、公開鍵の入手を試みます。 + +Mew では PGPv2、PGPv5、GNUPG に対応しています。これらは Summary モード +において、`C-cC-v' で切替え可能です。これら複数の PGP を使いたい人は +`mew-prog-pgp2'、`mew-prog-pgp5'、`mew-prog-gpg' に対し、それぞれ +PGPv2、PGPv5、GNUPG のコマンド名を設定して下さい。また、Mew の起動直後 +に利用する PGP のコマンド名を `mew-prog-pgp' に設定して下さい。なおパ +スフレーズは、それぞれの PGP に対し独立に保存されます。 + +なお昔ながらの PGP メッセージは、自動的に処理できません。このような +PGPメッセージに対しては、`C-cC-z' で復号化や署名の検証ができます。 + + + +File: mew.ja.info, Node: retrieving, Next: moving, Prev: cipher-viewing, Up: Viewing + +メッセージの取得 +================ + +メールボックスへ到着したメッセージを +inbox へコピーし一覧表示するには、 +`i' を使います。コピー元のメールボックスは `mew-mailbox-type' によって +決ります。(`M-x mew' を実行した際に、`mew-proto' が `+' の場合も、 +`mew-mailbox-type' に従ってメッセージがコピーされます。) 以下に取りう +る値を示します。 + +`'mbox' + ローカルのメールボックス。デフォルトでは "incm" という外部コマン + ドを使い、メッセージを取得する。設定方法は、*Note configuration:: + を参照のこと。 +`'pop' + POP サーバ。POP を POP らしく使う方法。(初期値) +`'imap' + IMAP サーバ。IMAP らしくない利用方法なので、推奨されていない。 + +ローカル・フォルダでメッセージの一覧を再表示するには、`s' を使います。 + +リモート・フォルダでメッセージを取得、あるいは再取得する場合にも `s' +を使います。IMAP やニュースでは、`i' は利用せず、`s' を使うのが一般的 +です。 + +`s' を使うと範囲を訊いてきます。Mew で重要な範囲の意味を以下に示します。 + +`update' + 「Summary モードの最後のメッセージの次」から「フォルダ内の最後の + メッセージ」まで。つまり、Summary モードと実際のフォルダ内のメッ + セージの差分。 +`all' + フォルダ内のメッセージすべて。ローカル・フォルダでは、Summary モー + ドの表示がおかしくなったときに、内容を一新するために用いる。リモー + ト・フォルダでは、すべてのメッセージの再取得。 +`sync' + あるリモート・フォルダに対し、サーバ側では消えたメッセージのキャッ + シュを削除する。リモート・フォルダに対してのみ有効。 + ++draft、+queue、+postq では、デフォルトの範囲は `all' となっています。 +それ以外のフォルダでは、デフォルトの範囲が `update' となっています。で +すから、+draft、+queue、+postq 以外では、`s' の後に `RET' を押すだけで、 +現在のフォルダに対し最新の一覧を得られることになります。 + +Mew ではあまり重要ではありませんが、以下の範囲も指定できます。 + +`-' + から まで。ローカル・フォルダに対してのみ有効。 +`-' + から最後まで。ローカル・フォルダに対してのみ有効。 +`-' + 最初から まで。ローカル・フォルダに対してのみ有効。 +`last:' + 最後の 個。 + +リモート・フォルダで `s' を `C-u' 付きで呼び出すと、「ヘッダのみのコ +ピー」と「ヘッダと本文の両方のコピー」を反転できます。これらの動作は、 +POP、IMAP、NNTP に対し、それぞれ `mew-pop-header-only'、 +`mew-imap-header-only'、`mew-nntp-header-only' で定義でき、初期値はす +べて `nil' です。つまり、初期値は「ヘッダと本文の両方のコピー」になっ +ています。 + +サイズが大きなメッセージは、全体ではなく一部が取得されているかもしれま +せん。このようなメッセージには、`T' マークがついています。このメッセー +ジの全体を取得するには、そのメッセージ上で `I' と入力します。 + +たとえば、$inbox に `T' マークのついたメッセージがあるとしましょう。こ +のメッセージの上で `I' を押すと、メッセージの全体が取得できます。 + +メッセージの取得に関するコマンドを以下にまとめます。 + +`i' + ローカル・フォルダでは、+inbox フォルダに移動し、到着したメッセージを取 + 得して一覧を表示する。`mew-auto-flush-queue' が `t' なら、 + +queue にあるメッセージを送信する。詳しくは、*Note send:: を参照のこと。 + リモート・フォルダでは、そのデフォルトのフォルダに移動し、`s' + + `update' を実行する。 +`C-ui' + `mew-auto-flush-queue' の値を逆だと思って、`i' を実行する。 +`I' + `T' マークの付いている一部だけが取得されたメッセージの全体を取得 + する。 + + ローカル・フォルダで実行した場合、ケースと `mew-mailbox-type' に + より取得方法が決る。`mew-pop-delete' または `mew-imap-delete'の値 + が `t' なら、メールボックスのメッセージを削除する。 + + リモート・フォルダで実行した場合、ケースと取得方法はそのフォルダ + から決る。サーバ側のメッセージは常に保存される。 +`C-uI' + `mew-pop-delete' または `mew-imap-delete' を逆転させて `I' を実行 + する。 +`s' + フォルダの一覧を取る。 +`C-us' + リモート・フォルダにおいて、「ヘッダのみのコピー」と「ヘッダと本 + 文の両方のコピー」を反転させて、一覧を取る。 +`lc' + リモート・フォルダのメッセージをローカル・フォルダへコピーする。 + + + +File: mew.ja.info, Node: moving, Next: sum-write, Prev: retrieving, Up: Viewing + +フォルダの移動 +============== + +フォルダの移動には `g' を入力して下さい。以下のようにフォルダ名を訊か +れます。 + + Folder name (+inbox): + + +":" の右側を編集可能領域と呼ぶことにしましょう。この例では、編集可能領 +域に修飾子 "+" が表示されています。修飾子に続けて任意の文字列を入力し、 +`RET' を押せば、フォルダ名が決定されたことになり、そのフォルダへ移動し +ます。 + +フォルダを移動した際に Summary モードの一覧が古いと判断した場合は、自 +動的に差分が追加表示されます。 + +"()" 内がデフォルトのフォルダです。単に `RET' を押し "+" を入力すると、 +デフォルトのフォルダを入力したものとして扱われます。 + +補完を利用するには、`TAB' や `SPC' を押して下さい。 + +さて、話を `g' を押した直後に戻しましょう。 + + Folder name (+inbox): + + +たとえば、"+" を "%" に変更するには、通常なら "+" を削り、"%" を入力す +る必要があります。これでは面倒なので、"+" の後で "%" を入力すると、"+" +が "%" に置き換わるようになっています。このように、修飾子の直後で他の +修飾子を入力すれば、削る作業をせずに置き換え可能です。 + +リモート・フォルダを入力する場合、*Note config:: で説明するケースを指 +定したい場合もあるでしょう。ケースは、フォルダ名の前に ":" で区切って +入力します。たとえば、"home" というケースの "%inbox" に移動したいとし +ましょう。このとき、"home:%inbox" と入力する必要があります。しかしこれ +は面倒なので、任意の場所で `C-cTAB' を押すと利用可能なケースが、フォル +ダ名の前に循環的に補完されます。次の例を考えて下さい。 + + Folder name (+inbox): %inbox + +ここで `C-cTAB' を入力すると、以下のようになります。 + + Folder name (+inbox): home:%inbox + +フォルダ名の一部を指定して、フォルダを検索したいこともあるでしょう。こ +の場合には、前方検索の `C-s' か後方検索の `C-r' が利用できます。以下は、 +`C-s' を押したときのミニバッファの状態です。 + + Folder name (+inbox): () + +編集領域に現れた "()" が、検索モードに移行したことを表わしています。こ +こで文字を入力していくと、マッチした候補が "()" の中に表示されます。以 +下は "mew" で検索したときの例です。 + + Folder name (+inbox): (+work/mew-release) mew + +候補を確定する際には、`RET' を入力して下さい。そうすると検索モードを抜 +けて、編集領域にこの候補が表示されます。 + + Folder name (+inbox): +work/mew-release + +さらに `RET' を押せば、このフォルダが入力されたことになります。 + +検索対象となるフォルダの一覧は、ケースと修飾子の組で決定されます。 +`C-s' や `C-r' で検索モードに移るときに編集領域にある文字列から、ケー +スと修飾子が切り出され、フォルダの一覧が決定される訳です。 + + + +File: mew.ja.info, Node: sum-write, Next: features, Prev: moving, Up: Viewing + +送信、返答、転送 +================ + +メッセージの送信、返答、転送には、以下のコマンドを使います。 + +`w' + メッセージを書く。新しい草稿が Draft モードに用意される。 + *Note Composing:: を参照のこと。 +`C-uw' + メッセージを書く。新しい草稿が Draft モードに用意される。現在のメッ + セージの From: にあるアドレスが、草稿の To: へコピーされる。 +`W' + あるメッセージのヘッダの一部だけを編集しメッセージを送信するため + に Header モードに入る。*Note resend:: を参照のこと。 +`a' + 現在のメッセージに返答する。Draft モードに草稿が用意され、To: や + Cc: が自動的に決定される。*Note reply:: を参照のこと。 +`C-ua' + 現在のメッセージに対し送信者宛に返答する。 +`A' + 現在のメッセージに返答する。Draft モードに草稿が用意され、To: や + Cc: が自動的に決定された後、本文が引用される。*Note reply:: を参 + 照のこと。 +`C-uA' + 現在のメッセージに対し、引用付きで送信者宛に返答する。 +`f' + 現在のメッセージを第 3 者に転送する。Draft モードに草稿が用意され、 + 現在のメッセージが自動的に添付される。*Note forward:: を参照のこ + と。 +`F' + `*' マークの付いたメッセージを第 3 者に転送する。Draft モードに草 + 稿が用意され、`*' マークの付いたメッセージが自動的に添付される。 + 詳しくは *Note target mark:: を参照のこと。*Note forward:: を参照 + のこと。 + +エラーメッセージが返ってきたら、以下のコマンドで修正し再挑戦しましょう。 + +`E' + メッセージの再編集。または、MIME 形式でカプセル化されて戻ってきた + メッセージの再編集。 + + 1. +draft では、メッセージが単に編集される。 + 2. +queue と +postq では、メッセージが +draft に移動されて、編 + 集される。 + 3. それ以外では、メッセージが +draft にコピーされて、編集される。 + + +draft、+queue、+postq では、ケースが復活する。 + + 他のフォルダでは、`mew-case-guess-when-prepared' が `t' なら、 + ヘッダのそれぞれのフィールドがケースに従って置き換えられる。詳しくは + *Note config:: を参照のこと。 +`C-uE' + `E' と同じ。ただし、+draft、+queue、+postq 以外のフォルダで利用さ + れた場合は、`mew-case-guess-when-prepared' が `t' でも、オリジナ + ルのヘッダが保存される。 + + + +File: mew.ja.info, Node: features, Next: status-update, Prev: sum-write, Up: Viewing + +便利な機能 +========== + +Mew では、Summary モードに以下のような便利なコマンドが用意されています。 + +`v' + 「Summary モードのみ」と「Summary & Message モード」の切り替え。 + 「Summary モードのみ」を選んでいる場合は、`d' は次のメッセージを + 表示しないので、連続してすばやく `D' マークを付けられる。 +`zv' + `mew-use-header-veil' が `nil' でないとき、To: と Cc: で + `mew-header-veil-count' を越える行は「ベール」で隠されている。こ + のコマンドは、それらの行の見える/見えないを反転させる。 + `mew-use-header-veil' と `mew-header-veil-count' の初期値は、それ + ぞれ `t' と 4。 +`_' + 通常の行、折り返された行、長い行の順に行の表示を変える。 +`M-l' + 現在の行を Summary モードの中央に移動させる。 +`C-cC-s' + Message モードで順方向段階的検索。 +`C-cC-r' + Message モードで逆方向段階的検索。 +`y' + メッセージ、あるいは、パートを入力したファイル名で保存する。 +`b' + Message モードの内容そのものを入力したファイル名で保存する。 +`C-uy' + 保存するテキストの coding-system を指定して、メッセージ、あるいは、 + パートを入力したファイル名で保存する。 +`#' + `mew-print-function' を利用して Message モードの内容を印刷する。 +`C-u#' + プリンタ名を指定して Message モードの内容を印刷する。 +`|' + Message モードの内容をパイプで指定されたコマンドに出力する。 +`C-u|' + Message モードの本文(ヘッダを除く)をパイプで指定されたコマンドに + 出力する。 +`\' + このメッセージを引数にして、入力された外部コマンドを起動する。 +`B' + 格納されているメッセージを取り出す。 +`C-uB' + 格納されているファイルを取り出す。 +`C-cC-a' + 現在のメッセージの情報をアドレス帳に登録する(*Note addrbook::)。 +`C-cC-v' + PGP のバージョンを切替える(*Note cipher-viewing::)。 +`C-cC-z' + 昔ながらの自動処理できない PGP メッセージを PGP に復号化、検証さ + せる(*Note cipher-viewing::)。 +`C' + ケースを変更する。詳しくは、*Note config:: を参照のこと。 +`=' + フォルダ名とメッセージ番号を表示する。キャッシュ・メッセージの場 + 合は、加えて ID とサイズも表示する。メッセージへのフルパスが、ウ + インドウマネージャのカットバッファに入る。 +`;' + Received: フィールドを解析し、分りやすく Message モードに表示する。 +`Rd' + フォルダを削除する。 +`Rr' + フォルダの名前を変える。 + + + +File: mew.ja.info, Node: status-update, Next: invalid, Prev: features, Up: Viewing + +状態の更新 +========== + +いくつかの設定の変更には、その変更を反映するために、状態を更新しなけれ +ばならない場合があります。変更が反映されなかったり、変更のためにエラー +が生じるようになったりした場合は、以下のコマンドを利用して下さい。 + +`Z' + アドレス帳(*Note addrbook::)などの情報を更新する。 +`C-uZ' + 現在の世界に対するフォルダのリストの情報を更新する。 + +状態を反転させるコマンドを以下にまとめます。 + +`z8' + 8 ビット・モード(`mew-use-8bit')を反転させる。 +`zc' + 解析したメッセージのキャッシュを消去する。 +`zd' + `mew-debug' を反転させる。 +`zo' + PGP を省略方法で作成する場合、PGP/MIME なのか古い PGP の書式なの + か(`mew-use-old-pgp')を反転させる。 +`zp' + 解析、復号化のポリシ(`mew-decode-broken')を反転させる。 +`zv' + Message モードでベールを使うか否か(`mew-use-header-veil')を反転さ + せる。 +`zw' + 警告のレベル(`mew-warning-field-level')が 2 なら 1 へ、1 なら 2 + へ設定する。 + + + +File: mew.ja.info, Node: invalid, Next: Composing, Prev: status-update, Up: Viewing + +規格違反のメッセージ +==================== + +以下のようなメッセージは、Content-Type: で charset が指定されていない +ので、本来 US-ASCII と認識されてしまいます。 + + To: piglet + Subject: 規格違反のメッセージ + From: pooh + MIME-Version: 1.0 + Content-Type: Text/Plain + + 日本語の本文 + +また以下のようなヘッダも規格違反です。 + + From: "=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?=" + +上の例では "=?" と "?=" で囲まれた部分はもともと日本語でした。メッセー +ジの規格ではヘッダには ASCII のみが格納できると定められています。よっ +て、ASCII 以外の文字コードをヘッダに格納するには、ある規則に従って +ASCII に符号化する必要があります。しかし、この符号化された文字列を 「"」 +で囲むのは間違いです。「"」で囲まれた文字列は、そのままの形で取り扱わ +れます。よって、上の例の "=?" と "?=" で囲まれた部分が日本語に復号化さ +れることは本来ありません。 + +規格に無頓着な一部のメーラではこのような間違いを平気で犯します。正しい +対処方法は、このようなメーラの作者に頼んで、規格を正しく実装するように +変更してもらうことです。しかし、このようなメーラはあまりにも多いので、 +Mew ではできる限り復号化するよう試みます。そして、以下のような警告をヘッ +ダに出します。 + + X-Mew: Charset for body is not specified. + To: has encoded-words in quoted text. + +もし、規格に厳密に復号化したいのなら、`mew-decode-broken' を `nil' に +設定して下さい。この値は `C-u.' を使うと動的に反転できます(*Note +singlepart:: を参照)。 + +次のようなメッセージは、charset で指示されている文字コードと実際の文字 +が異なるため、文字化けを起こします。 + + Content-Type: Text/Plain; charset=ISO-2022-JP + + Shift_JIS で書かれた日本語の本文 + +`C-cC-l' を使えば、charset で指定された文字コードを無視し、指定した言 +語の推測規則に従って文字コードを推測し、再表示させることができます。ま +た、`C-uC-cC-l' で明示的に文字コードを指定し、再表示させることも可能で +す。 + + + + +File: mew.ja.info, Node: Composing, Next: header, Prev: invalid, Up: Top + +メッセージを作成する +******************** + +ここではメッセージの作成方法について説明します。 + +新しいメッセージを書くために、Draft モードに移行するには、次の手段があ +ります。 + + 1. `M-x mew-send' と入力する。 + 2. `mail-user-agent' が設定されている場合、`C-xm' と入力する。 + 3. Summary モードで `w' を押す。 + +すると、以下のようなバッファが用意されます。 + + To: + Subject: + From: Kazu Yamamoto + X-Mailer: Mew version 6.7 on Emacs 24.4 + ---- + +これを Draft モードといいます。Draft モードにおいて、"----" より上をヘッ +ダ、下を本文と呼びます。 + +またメッセージへの返答(`a' や `A')や転送(`f' や `F')でも Summary モー +ドから Draft モードへ移行します。 + +草稿は、+draft フォルダの下に作成されます。同時に複数の草稿を持つこと +が可能です。 + +一旦用意した草稿を削除する方法については、*Note Quit:: を参照して下さ +い。 + +以下、Draft モードの使い方を説明します。 + +* Menu: + +* header:: ヘッダの補完 +* cheader:: ヘッダの循環的な補完 +* addr-comp:: アドレスの補完 +* addrbook:: アドレス帳 +* auto-alias:: アドレスの自動学習 +* addr-comp1:: アドレスの補完(1) +* addr-comp2:: アドレスの補完(2) +* send:: メッセージの送信 +* cite:: シグニチャと引用 +* mime-comp:: マルチパートの作成 +* charset-guess:: 文字コードの決定 +* longline:: 長い行の取り扱い +* reply:: メッセージへの返答と宛先の決定 +* forward:: メッセージの転送 +* resend:: メッセージの再送 +* shortcut:: 電子署名/暗号メールを作成する +* mark-b-comp:: マークを使った電子署名/暗号メールの作成 +* pgp-key:: PGP の鍵の配布 +* anonymous:: 宛先を匿名にしたメッセージの送信 + + + +File: mew.ja.info, Node: header, Next: cheader, Prev: Composing, Up: Composing + +ヘッダの補完 +============ + +ヘッダでは `TAB' に対し、以下のように各フィールド用の補完機能が割り当 +てられています。 + + - フィールド名の補完 + - アドレスの補完 (To:、Cc: など) (*Note addr-comp:: を参照) + - フォルダ名の補完 (Fcc:) + +<フィールド名の補完> + +行頭の単語中で、しかも、上の行の最後が "," で終る継続行でなければ、 +`TAB' で `mew-fields' に定義されているフィールド名を補完できます。 + + To: kazu@example.org + R`TAB' + +上記の場所で `TAB' を押すと以下のようになります。 + + To: kazu@example.org + Reply-To: + +<フォルダ名の補完> + +Fcc: などのようにフォルダを補完すべきところでは、`TAB' でフォルダを補 +完できます。以下に例を挙げてみます。 + + Fcc: `TAB' + +"+" が補完されます。 + + Fcc: +`TAB' + +`TAB' をもう 1 度押すと候補が表示されるので、候補を見ながら適切な文字 +を入力します。 + + Fcc: +b`TAB' + +候補が一意に定まれば補完されます。 + + Fcc: +backup + + + +File: mew.ja.info, Node: cheader, Next: addr-comp, Prev: header, Up: Composing + +ヘッダの循環的な補完 +==================== + +ヘッダでは、`C-cTAB' に循環的な補完機能が割り当てられています。循環的 +な補完機能とは、あるリストのある値がそのリストの次の値に置き換えられる +ことです。リストの最後は、最初につながっていると考えます。ヘッダ中の循 +環的な補完機能は、以下のようにフィールドごとに異なります。 + + - ドメイン名の循環的な補完 (To:、Cc: など) + - From: の循環的な補完 (From:) + +<ドメイン名の循環的な補完> + +アドレスを書くべきフィールドでは、`C-cTAB' でドメインを補完します。補 +完の候補は `mew-mail-domain-list' から選ばれます。 + + To: kazu@`C-cTAB' + +上記の場所のように候補が一意に定まらない場合は、 +`mew-mail-domain-list' の最初のドメイン名が挿入されます。 + + To: kazu@example.org`C-cTAB' + +補完された後、さらに `C-cTAB' を押すと `mew-mail-domain-list' の次の候 +補に変換します。 + + To: kazu@example.jp + +また、以下の補完が一意に定まれば、その候補を挿入します。 + + To: kazu@w`C-cTAB' + +上記の例は次のようになります。 + + To: kazu@example.jp + + + +草稿には、あらかじめ "mew-name " という形式で、 +From: フィールドが挿入されています。 + + From: Kazu Yamamoto (山本和彦) + +From: フィールド上では、`C-cTAB' は `mew-from-list' の値を循環的に補完 +します。`mew-from-list' は自分で設定してもよいですし、自動的に設定する +ことも可能です。自動設定に関しては、*Note config:: を参照して下さい。 + +値の場所ならどこでも構いませんが、`C-cTAB' と入力すると、この値を +`mew-from-list' の次の値と置き換えます。たとえば、 + + From: Kazu Yamamoto (山本和彦) `C-cTAB' + +は以下のようになります。 + + From: Kazuhiko Yamamoto + + + +File: mew.ja.info, Node: addr-comp, Next: addrbook, Prev: cheader, Up: Composing + +アドレスの補完 +============== + +To: や Cc: では、アドレスを補完できます。補完には `TAB' を用います。 + + To: kazu`TAB' + +上記のように、アドレスの一部で `TAB' を押すと、以下のようにアドレスが +補完される訳です。 + + To: kazu@example.org + +アドレスの補完に利用されるアドレスの種類には、以下の 3 つがあります。 + + 1. アドレス帳の展開規則 + 2. アドレス帳の個人情報 + 3. 送信時に学習されたアドレス + +アドレスの補完には 2 つの方法が提供されています。 +`mew-use-full-alias' によって選択します(初期値は `nil')。 + +`mew-use-full-alias' が `nil' の場合、`@' の前、つまりユーザ名(短縮名) +が補完の対象となります。`TAB' を押すとユーザ名が補完され、補完しきった +ところでさらに `TAB' を押すとアドレスに「展開」されます。これをアドレ +スの補完(1)と呼びましょう。 + +アドレスの補完(1)(*Note addr-comp1::)の利点は、上に書いた 3 種類のアド +レスに対し、補完・展開が矛盾なく実行できることです。後述のように、「強 +制展開」も `TAB' で実行できます。欠点は、ユーザ名の部分が一意でなけれ +ばならないので、あるユーザ名が登録されている場合、同じユーザ名を持つ別 +のアドレスを学習できないことです。 + +`mew-use-full-alias' が `t' の場合、学習されたアドレスに関しては、アド +レスの全体が補完の対象になります。これをアドレスの補完(2)と呼びましょ +う。 + +アドレスの補完(2)(*Note addr-comp2::)の利点は、ユーザ名が一致している +複数のアドレスを学習できることです。欠点は、アドレス帳の個人情報に登録 +されているアドレスの先頭以外は利用できないことです。また、「強制展開」 +は、`M-C-e' という (`TAB' とは別の) キーを押さなければいけないことです。 + + + +File: mew.ja.info, Node: addrbook, Next: auto-alias, Prev: addr-comp, Up: Composing + +アドレス帳 +========== + +Mew ではアドレス帳("~/Mail/Addrbook")が利用できます。アドレス帳には 2 +つの書式が用意されています。一方は「展開規則」を指定する書式、他方は +「個人情報」を記述するための書式です。 + +まず、「展開規則」を記述するための書式を示します。 + + : [, , ,...] + +このように短縮名と展開すべきアドレスを `:' で区切って書きます。複数 +のアドレスに展開する場合は、それらのアドレスを `,' で区切ります。 +(これは、To: などでアドレスが `,' で区切られているのと同じです。) +`,' の後ろに空白を入れても構いません。以下に例を示します。 + + pooh: winnie-the-pooh@example.net + piglet: piglet@example.org + friends: pooh, piglet + + + +次に、「個人情報」を記述するための書式を示します。 + + [, , ,...] + +このように 4 つの要素を空白で区切ります。 が短縮名です。 + と はそれぞれニックネームと正式な氏名であり、日本 +語でも構いません。(ニックネームの使い方は *Note summary-mode:: と +*Note draft-mode:: を参照して下さい。) + +2 番目の要素はアドレスです。複数のアドレスをその人が持っている場合は、 +`,' で区切って書きます。`,' の後に空白を入れても構いません。つまり、こ +の空白は要素の区切りではありません。また、`"' で囲まれた空白も要素の区 +切りにはなりません。以下に例を示します。 + + kazu kazu@example.org, kazu@example.net Kazu-kun "Kazuhiko Yamamoto" + +「個人情報」の書式では、各要素を省略できます。中間の要素を省略する場合 +は、`*' と書いて下さい。以下に、アドレスに対してニックネームのみを定義 +する例を示します。 + + * kazu@example.org, kazu@example.net Kazu-kun + +ニックネームは Summary モードでのアドレスの置き換えと、Draft モードで +の引用記号の置き換え(*Note cite::)に利用されます。 + +アドレス帳のコメント文字は `;' と `#' です。`;' は行頭にある場合のみコ +メントとなり、その行が無視されます。`#' は任意の場所でコメントとなり、 +そこから行末までが無視されます。また、`\' は継続行を表わします。 + + + +Summary モードには、現在読んでいるメッセージの情報を Addrbook に登録す +る機能があります。展開規則を登録するには `C-cC-a' と押して下さい。以下 +に例を示します。 + + #If you want to register this entry, type 'C-c C-c'. + #If you want to NOT register this entry, type 'C-c C-q'. + Shortname: kazu + Addresses: kazu@example.org + Comments: + +個人情報を登録するには `C-uC-cC-a' と押して下さい。以下に例を示します。 + + #If you want to register this entry, type C-c C-c. + #If you want to NOT register this entry, type C-c C-q. + Shortname: kazu + Addresses: kazu@example.org + Nickname: + Name: Kazuhiko Yamamoto + Comments: + +必要であれば加筆訂正します。実際に登録するには `C-cC-c'、登録を取り止 +める場合は `C-cC-q' と入力して下さい。*Note Quit:: も参照して下さい。 + +なお、Addrbook に複数の言語の文字を使いたい場合は、以下の設定を +Addrbook の先頭に記述して下さい。 + + #-*-coding:ctext;-*- + + + + +File: mew.ja.info, Node: auto-alias, Next: addr-comp1, Prev: addrbook, Up: Composing + +アドレスの自動学習 +================== + +メッセージを送信した場合、To: と Cc: に書かれているアドレスは、自動的 +に学習されます。以下の例を考えて下さい。 + + To: kazu@example.org + +アドレスの補完(1)(*Note addr-comp1::)の場合:このメッセージを送信する +と、アドレス "kazu@example.org" に対し、短縮名 "kazu" が自動登録されま +す。ただし、すでに "kazu" という短縮名が自動登録されているなら、 +`mew-addrbook-override-by-newone' の値に応じて上書きするかを決定します。 +`nil' なら古い設定を残し、それ以外なら上書きします。展開の際は、アドレ +ス帳の方が優先されます。ですから、アドレス帳に無い短縮名のみが有効にな +ります。 + +アドレスの補完(2)(*Note addr-comp2::)の場合:このメッセージを送信する +と、アドレス "kazu@example.org" が自動登録されます。 + +自動登録されるのは通常 2000 個(`mew-lisp-max-length')のアドレスまでで +す。それを越えて登録するとアルファベット順で最後の方が消えます。これら +の情報は Mew を終了する際に、"~/Mail/.mew-alias" に保存されます。 + +自動登録ですから、不要な短縮名も登録されます。不要な短縮名を削除するに +は、以下のようにするといいでしょう。まず、`M-a' を実行し、 +"~/Mail/.mew-alias" を開きます。次に、テキストファイルを編集する要 +領で、不要な短縮名を削除します。そして、`C-xC-s' で保存して下さい。 +保存と同時に、その内容が Mew に反映されます。 + +アドレスの補完(1)とアドレスの補完(2)では、"~/Mail/.mew-alias" の書式が +異なります。`mew-use-full-alias' の値を変え、方法を切り替えたら、 +Summary モードで一回 `Z' を押して下さい。これで、書式が変換されます。 + + + +File: mew.ja.info, Node: addr-comp1, Next: addr-comp2, Prev: auto-alias, Up: Composing + +アドレスの補完(1) +================= + +アドレスの補完(1)では、アドレス帳の展開規則、アドレス帳の個人情報、お +よび送信時に学習されたアドレスで登録されたアドレスは、ユーザ名(短縮名) +が一意であることが前提となっています。 + +たとえば、以下のように「展開規則」を設定したとします。 + + pooh: winnie-the-pooh@example.net + +Draft モードのヘッダ内で、かつ、アドレスを書くべきフィールド上で、しか +も、1 文字以上の文字列が前にある場所で `TAB' を打つと、アドレスの短縮 +名が補完されます。 + + To: piglet@example.org, + po`TAB' + +このように `TAB' を押すと、(他に候補が無ければ) "pooh" まで補完されま +す。 + + To: piglet@example.org, + pooh`TAB' + +もう一度 `TAB' を押すと "winnie-the-pooh@example.net" に展開されます。 + + To: piglet@example.org, + winnie-the-pooh@example.net + +"@" で終る文字列は強制的に展開します。たとえば、以下のように似たような +短縮名があった場合を考えて下さい。 + + pooh: winnie-the-pooh@example.net + pooh-pooh: pooh-pooh@example.org + +"pooh-" まで入力すれば、"pooh-pooh" まで補完できることは明らかです。し +かし、"pooh" までだと、"pooh" を「展開」するのか、"pooh-pooh" まで補完 +するのか分りません。"pooh" を "winnie-the-pooh@example.net" に強制的に +展開するには、以下のように `@' を挿入し、`TAB' を押します。 + + To: pooh@`TAB' + +強制展開は、`@' を挿入せず、`M-C-e' を押しても実行できます。 + +上記の説明は、送信時に学習されたアドレスにもあてはまります。 + +「個人情報」の書式では、アドレスが順に置き換えられていきます。以下の例 +を考えて下さい。 + + kazu kazu@example.org, kazu@example.net Kazu-kun "Kazuhiko Yamamoto" + +kazu がどう変化するのか見てみましょう。 + + To: kazu`TAB' + +"kazu" の後で `TAB' を打つと、"kazu@example.org" に置き換わります。 + + To: kazu@example.org`TAB' + +次に "kazu@example.org" の後で `TAB' を打つと、"kazu@example.net" に置 +き換わります。 + + To: kazu@example.net`TAB' + +さらに "kazu@example.net" の後で `TAB' を打つと、"kazu@example.org" に +戻ります。このように `TAB' を押すと、アドレスが循環的に置換されます。 + +アドレスを決定した後は、正式名称が付加できます。 + + To: kazu@example.org`M-TAB' + +このように `M-TAB' を押すと、以下のように正式名称が付加されます。 + + To: Kazuhiko Yamamoto + + + +File: mew.ja.info, Node: addr-comp2, Next: send, Prev: addr-comp1, Up: Composing + +アドレスの補完(2) +================= + +アドレスの補完(2)では、学習されたアドレスに関しては、アドレス全体が補 +完の対象になります。アドレス帳の展開規則は、短縮名が補完の対象になり、 +一意に定まれば展開されます。アドレス帳の個人情報では、短縮名が補完の対 +象になり、一意に定まれば、登録されている先頭のアドレスに展開されます。 + +Draft モードのヘッダ内で、かつ、アドレスを書くべきフィールド上で、しか +も、1 文字以上の文字列が前にある場所で `TAB' を打つと、短縮名あるいは +学習されたアドレスが補完されます。 + +kazu@example.org を学習しているとしましょう。 + + To: ka`TAB' + +曖昧でないところまで入力し、`TAB' を押せば、アドレスが補完されます。 + + To: kazu@example.org + +さらに kazunori@example.jp を学習したとしましょう。kazu@example.org へ +補完するには kazu@ まで、kazunori@example.jp へ補完するには kazun まで +入力する必要があります。 + +展開規則と個人情報は、`TAB' により、まず短縮名が補完されます。短縮名が +一意に定まれば、`TAB' で展開できます。 + +たとえば、以下のように「展開規則」を設定したとします。 + + pooh: winnie-the-pooh@example.net + +短縮名 "pooh" を補完してみましょう。 + + To: po`TAB' + +このように `TAB' を押すと、(他に候補が無ければ) "pooh" まで補完されま +す。 + + To: pooh`TAB' + +もう一度 `TAB' を押すと "winnie-the-pooh@example.net" に展開されます。 + + To: winnie-the-pooh@example.net + +問題は、短縮名が一意に定まらない場合の展開です。以下の展開規則を考えて +下さい。 + + pooh: winnie-the-pooh@example.net + pooh-pooh: pooh-pooh@example.org + +"pooh-" まで入力すれば、"pooh-pooh" まで補完できることは明らかです。し +かし、"pooh" までだと、"pooh" を「展開」するのか、"pooh-pooh" まで補完 +するのか分りません。"pooh" を "winnie-the-pooh@example.net" に強制的に +展開するには、`M-C-e' を利用します。(`TAB' で強制展開する方法はありま +せん。) + + To: pooh`M-C-e' + +この例は、以下のように強制展開されます。 + + To: winnie-the-pooh@example.net + + + + +File: mew.ja.info, Node: send, Next: cite, Prev: addr-comp2, Up: Composing + +メッセージの送信 +================ + +メッセージを書き上げ、いよいよ送信するには、以下の 2 つのコマンドのど +ちらかを選んで下さい。 + +`C-cC-m' + メッセージを作成し +queue または +postq に入れ、送信待ち状態にす + る。 +`C-cC-c' + メッセージを作成し送信する。"Really send this message? (y or n) " + と訊かれる。`y' を押せば、送信される。 + +メッセージが送信される際にどう加工されるか説明します。以下のようなメッ +セージを考えて下さい。 + + To: pooh + Subject: 明日の日曜日 + From: Piglet + X-Mailer: Mew version 6.7 on Emacs 24.4 + ---- + 明日の日曜日、遊びませんか? + + // ピグレット + +たとえば、`C-cC-m' でこのメッセージを +queue あるいは +postq に入れる +と、メッセージは以下のように加工されています。 + + Date: Mon, 13 Mar 2000 19:49:50 +0900 (JST) + Message-Id: <20000313.194950.59499544.piglet@example.org> + To: winnie-the-pooh@example.net + Subject: =?iso-2022-jp?B?GyRCTEBGfCRORnxNS0Z8GyhC?= + From: Piglet + X-Mailer: Mew version 6.7 on Emacs 24.4 + Mime-Version: 1.0 + Content-Type: Text/Plain; charset=iso-2022-jp + Content-Transfer-Encoding: 7bit + + 明日の日曜日、遊びませんか? + + // ピグレット + +Date: や Message-Id: が付加されたのはお分かりになるでしょう。Subject: +にあった日本語は、配送に安全となるよう ASCII コードに変換されています。 +また、本文のデータ型や文字コードが推測され、正しく付加されていることは +特筆すべきでしょう。 + +`C-cC-m' や `C-cC-c' でメッセージを作成するとき、ヘッダに不備があった +場合に注意を促してくれる機能があります。 + +`mew-ask-subject' を `t' にしておけば、Subject: が空のときに値を尋ねて +くれます。空のままにしたい場合は単純に `RET' を押して下さい。この変数 +の初期値は `nil' です。 + +`mew-ask-fcc' を `t' にしておけば、Fcc: に存在しないフォルダが指定して +ある場合、そのフォルダを作成するか尋ねてくれます。作るなら `y'、作らな +いなら `n' を押して下さい。`n' を押すと、送信が中止され、カーソルは草 +稿に戻ります。この変数の初期値は `nil' です。 + +Mew は、サーバがユーザ認証を要求すると、送信のためのパスワードをユーザ +に訊きます。長い間、メールの送信にはパスワードが必要ありませんでした。 +これが、メールアドレスを詐称できる原因の一つとなっています。これからは、 +メールの送信の際は、受信のときと同じように、パスワードが必要な時代にな +ります。 + ++queue に溜っているメッセージを送信するには、以下の 2 つの方法がありま +す。どちらも Summary モードのコマンドであることに注意しましょう。 + +`i' + `mew-auto-flush-queue' が `t' の場合は、メッセージを受信した後 + に、+queue にあるメッセージを送信する。ダイアルアップ環境において、接続 + 料金を節約する意味でも、送信のための認証という意味でも、これはよい方法。 + `mew-auto-flush-queue' の初期値は `t'。 +`C-cC-c' + +queue にあるメッセージを送信する。+queue に行って、できあがったメッセー + ジを見た後に、このコマンドを使うと便利。`mew-ask-flush-queue' が + `t' なら、"Flush queue? (y or n) " と訊かれる。 + `mew-ask-flush-queue' の初期値は `nil'。 + + + +File: mew.ja.info, Node: cite, Next: mime-comp, Prev: send, Up: Composing + +シグニチャと引用 +================ + +ここでは、本文のテキストを便利に処理するコマンドについて述べます。 + +まずシグニチャについてです。カーソルのある場所に "~/.signature" を挿入 +するコマンドは `C-cTAB' です。シグニチャファイルは、 +`mew-signature-file' で設定できます。`mew-signature-as-lastpart' や +`mew-signature-insert-last' を設定することで、`C-cTAB' の動作をカスタ +マイズできます。 + +`C-cTAB' + カーソルの位置に "~/.signature" を挿入する。 + +次に引用についてです。Summary モードの `a' や `A' を使ってメッセージに +返答するための草稿を用意すると、Emacs が 3 分割されます。上が現在の +Summary モード、中が Message モード、下が Draft モードです。 + +Message モードのテキストを引用するコマンドを以下に示します。 + +`C-cC-y' + Message モードからメッセージの一部をコピーし、引用ラベルと引用記 + 号付で貼り付ける。 + 1. おおまかにいえば、Message モードの本文がコピーされる。たとえ + ば、Text/Plain が表示されていると、Message モード全体がコピー + される。Message/Rfc822 が表示されている場合は、ヘッダを除い + た本文がコピーされる。 + 2. `C-uC-cC-y' では、ヘッダがあればヘッダをコピーする。 + 3. Emacs のマークがあると、そのマークとカーソルの間が対象となる。 +`C-cC-t' + Message モードからメッセージの一部をコピーし、引用ラベルと引用記 + 号なしで貼り付ける。 + +引用ラベルと引用記号の初期値は、以下のようになります。 + + From: SUMIKAWA Munechika + Subject: Wine + Date: Wed, 23 Jul 1997 11:40:50 +0900 + + > おはようからおやすみまでニートでおなじみの角川です。 + > + > さて、とろけるワイン作戦ですが、定石通り '90 のボルドーの + > カベルネ・ソービニョンを狙いたいと思います。 + +Draft モードでは Message モードに表示されているものならなんでも引用で +きます。つまり、複数のメッセージを簡単に引用できるのです。引用したいメッ +セージを表示させて、本文を引用する手順を、引用したいメッセージの回数だ +け繰り返して下さい。そのための 3 分割です。 + + +本文やヘッダの色付けがおかしくなった場合、`C-cC-l' を実行することで、 +色付けをやり直すことができます。 + + + +File: mew.ja.info, Node: mime-comp, Next: charset-guess, Prev: cite, Up: Composing + +マルチパートの作成 +================== + +さて、ここでマルチパートの作り方を披露しましょう。 + +たとえば、+draft/1 でメッセージを書いているときに、`C-cC-a' と入力する +と、草稿の一番下に + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + 2 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +という行が挿入されます。"1/" はマルチパートを構築するための一時的なディ +レクトリで、実体は "~/Mail/attach/1" です。パート 1 の CoverPage は本 +文を意味します。ここで Draft モードは次のようになっているでしょう。 + + To: mew-dist + Subject: ここがヘッダ + From: Kazu Yamamoto + X-Mailer: Mew version 6.7 on Emacs 24.4 + ---- + 本文だよ。 + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + 2 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +3 つの領域を以下のように呼ぶことにします。 + + * "----" より上を 「ヘッダ」 + * "----" から "attachments" までを「本文」 + * "attachments" より下を「添付領域」 + +Draft モードでは、リージョンによってキー割当が違います。 + +たとえば、`TAB' は以下のようになります。 + +ヘッダ + さまざまな補完。 +本文 + TAB の挿入。 +添付領域 + なにもしない。 + +`c' だと以下のようになります。 + +ヘッダ + c を挿入。 +本文 + c を挿入。 +添付領域 + ファイルのコピー。 + +以下、添付領域でのキー割当です。 + +`C-p' + 現在のディレクトリの前のファイルへ移動。 +`C-n' + 現在のディレクトリの後のファイルへ移動。 +`C-f' + 1 番目のサブディレクトリに移動。 +`C-b' + 親ディレクトリに移動。 +`c' + ファイルのコピー。"." 上で有効。ネットワーク経由でも可。リモート + のファイルをコピーする場合は、"/[user@]hostname:/filepath" の形式 + でファイルを指定。 +`l' + ファイルへシンボッリクリンクを張る。"." 上で有効。添付ファイルを + `f' を使って読み込んで編集する場合は、実体を編集してしまわないよ + うに、`l' ではなく `c' でコピーすべき。 +`d' + ファイルとディレクトリの消去。 +`m' + サブディレクトリ(つまりマルチパート)の作成。"." 上で有効。 +`f' + ファイルをバッファに読み込む。 +`F' + 新規ファイルをバッファに読み込む。"." 上で有効。 +`y' + Message モードに表示されているメッセージにリンクを張る。"." 上で + 有効。 +`e' + external-body の入力。"." 上で有効。 +`a' + 音をサンプリングしオーディオファイルとして挿入。"." 上で有効。 +`p' + 入力されたユーザの PGP 公開鍵を取り出す。"." 上で有効。 +`D' + ちょっとした説明(Content-Description:)の入力。 +`T' + データ型(Content-Type:)の変更。 +`t' + データ型に関し、テキストとバイナリを反転させる。 +`I' + Text/* 型の入力 coding-system を指定する。 +`C' + Text/* 型の出力 coding-system を指定する。 +`P' + 受信側でこのパートを保存する際のファイル名(Content-Disposition:) + の変更。ファイル名の入力の際に、単に `RET' を押すと値が消える。そ + して、送信側のファイル名が `*' と共に表示される。 + +添付領域では、ファイルの拡張子によってデータを取り扱います。現在サポー +トしている拡張子は以下の通りです。 + + .txt Text/Plain + .html Text/Html + .xml Text/Xml + .rtf Text/Enriched + .css Text/Css + .sgml Text/Sgml + [0-9]+ Message/Rfc822 + .ps Application/Postscript + .pdf Application/Pdf + .doc Application/Msword + .xls Application/Vnd.Ms-Execl + .ppt Application/Vnd.Ms-Powerpoint + .vsd Application/Vnd.Visio + .dat Application/Ms-Tnef + .tar|.tar.|.gz|.Z|.taz|.tgz|.bz2?|.lzh|.zip|.bin|.pgp|.gpg|.exe|.dll + Application/Octet-Stream + .gif Image/Gif + .tiff Image/Tiff + .jpe?g Image/Jpeg + .png Image/Png + .xwd Image/X-Xwd + .xbm Image/X-Xbm + .xpm Image/X-Xpm + .bmp Image/X-Bmp + .pcx Image/X-Pcx + .tga Image/X-Tga + .au Audio/Basic + .wav Audio/X-Wav + .aif?f Auido/X-Aiff + .midi? Auido/X-Midi + .mpga|.mp[23] Audio/X-Mpeg + .mpe?g Video/Mpeg + .mov Video/Quicktime + .avi Video/X-Msvideo + +コピーするときのファイル名は、適切なデータ型を推測できるよう拡張子に気 +を付ければなんでもよいです。もし、該当する拡張子がない場合、 +`mew-content-type' で指定されるデータ型が選ばれます。初期値は、 +Text/Plain(テキスト)です。 + + +`c' でファイルをコピーすると、たとえば次のようになります。 + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + B 2 Image/Gif MagicPoint のロゴ mgp.gif + Q 3 Application/Postscript 資料 ohp.ps + 4 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +各行は、 + + - マーク (Content-Transfer-Encoding:) + - パート番号 + - データ型 (Content-Type:) + - 説明 (Content-Description:) + - ファイル名 (Content-Disposition:) + +から構成されています。 + +データ型(Content-Type:)は `T' によって変えられます。データ型がテキスト +(Text/Plain)かバイナリ(Application/Octet-Stream)の場合は、`t' によって +一方を他方へ反転できます。 + +マーク(Content-Transfer-Encoding:)を変更する方法は、*Note +mark-b-comp:: を参照して下さい。説明(Content-Description:)は `D' で入 +力できます。この説明のカラムは、*Note mark-b-comp:: で説明する暗号化の +際に上書きされます。 + +第 5 カラムに表示されるのは、実際にはコピーしたファイル名か +Content-Disposition:、つまり、受信者がそのパートを保存する際のファイル +名です。Content-Disposition: の値があれば、それが表示されます。なけれ +ば、コピーしたファイル名に `*' を付加して表示します。ファイルをコ +ピーした際の Content-Disposition: の値は、コピーしたファイル名が指定さ +れています。ただし、Message/* と Multipart/* には Content-Disposition: +は設定されません。Message/* の Content-Disposition: を指定するには、 +`P' を利用して下さい。 + +ファイルはシングルパートに、ディレクトリはマルチパートに対応します。で +すから、ファイル構造を作っていく感覚で複雑なマルチパートを作成できます。 +簡単でしょ? + +ディレクトリに対するデータ型の初期値は、一般的なマルチパート +(Multipart/Mixed)です。これも `T' によって変更できます。 + +お好みのマルチパートが作成できたら、前節で述べたように `C-cC-m' か +`C-cC-c' を利用してメッセージを送信して下さい。 + +パートの実体が外部にある external-body を作成するコマンド `e' について +説明しましょう。access-type に ftp か anon-ftp を入力するときは、 +ange-ftp のおかげでリモートのファイル名が補完できます。access-type が +local-file の場合は、もちろんファイル名を補完できます。 + +もし、マルチパートの作成途中でやっぱりシングルパートに戻したくなったら、 +一番上のマルチパート部分で `d' を押して下さい。 + + + +File: mew.ja.info, Node: charset-guess, Next: longline, Prev: mime-comp, Up: Composing + +文字コードの決定 +================ + +Mew はシングルパートとマルチパートの両方に対し、配送時の文字コードを決 +定する機能を持っています。 + +<シングルパート> + +Draft モードで `C-cC-m' や `C-cC-c' と入力しメッセージを作成すると、 +Mew は本文の内部表現から配送時の文字コードを決定します。バイリンガル +Emacs では、7 ビットの文字コードに対し US-ASCII を選び、8 ビットの文字 +コードに対し ISO-8859-1 を選択します。国際化 Emacs では、内部表現から +Mew が定めた規則に従って、配送時の文字コードを決定します。 + +<マルチパート> + +マルチパートの一部として添付するデータは、ファイルですからディスク上に +存在します。そこで、メッセージの作成の際に、配送時の文字コードを決定す +るためには、まず Emacs のバッファに取り込み、内部表現に直す必要があり +ます。内部表現に直した後は、シングルパートと同様の方法で、配送時の文字 +コードを決定します。 + +バイリンガル Emacs では、Mew はファイルをそのままの形式で読み込みます。 +ですから、7 ビットのファイルには US-ASCII が、8 ビットのファイルには +ISO-8859-1 が選ばれます。 + +国際化 Emacs では、Mew は環境(つまり auto conversion)に従って、文字コー +ドを推測しながらファイルを読み込みます。国際化 Emacs でこの環境を決定 +するコマンドは、`C-x RET l' です。 + +たとえば、日本語の環境では、国際化 Emacs は ISO-2022-JP、EUC-JP、そし +て、Shift_JIS を見事に推測し、日本語用の内部表現に変換してバッファに格 +納します。Mew はこの内部表現から、配送時の文字コードとして ISO-2022-JP +を選択します。つまり、ファイルの文字コードが EUC-JP や Shift-JIS であっ +ても、配送用の ISO-2022-JP に自動的に変換されます。そこでユーザは、添 +付するファイルの文字コードを気にすることなしに、ファイルを添付可能です。 + +もし、ディスク上のファイルの coding-system を明示的に指定したいなら`I' +を使って下さい。これを入力文字コードと呼ぶことにします。また、配送時の +coding-system を明示的に指示したいなら、`C' を利用して下さい。 + +文字コードの情報は、添付領域において、丸括弧の内側に表示されます。もし、 +配送時の文字コードが明示的に指定されていれば、それが表示されます。そう +でなくて、入力文字コードが明示的に指定されていれば、それが "*" と共に +表示されます。そうでなければ、"guess" と表示されます。 + +以下の例の見て下さい。パート 1 は、本文ですからあらかじめバッファ内に +あります。"guess" と表示されていますから、配送時の文字コードを Mew が +定めた規則に従って決定します。 + +パート 2 は、入力文字コードとして iso-8859-1 が指定されていますので、 +ファイルの文字コードを iso-8859-1 であるとして読み込み、内部表現に変換 +します。配送時の文字コードは Mew が定めた規則に従って決定します。 + +パート 3 の入力文字コードは、この例だけからだと明示的に指定されている +か分かりません。(しかし、ユーザ自身はは実際に指定したか分かっているは +ずです。) とにかく、ファイルは内部表現に直され、配送時の文字コードに指 +定されている EUC-JP に変換されます。 + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + 2 Text/Plain(*iso-8859-1) text1 + B 3 Text/Plain(euc-jp) text2 + 4 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +バイリンガル Emacs では `C' と `I' は利用できません。 + + + diff --git a/elpa/mew-20150813.2354/mew.ja.info-2 b/elpa/mew-20150813.2354/mew.ja.info-2 new file mode 100644 index 00000000..6bc83997 --- /dev/null +++ b/elpa/mew-20150813.2354/mew.ja.info-2 @@ -0,0 +1,2135 @@ +Info file: mew.ja.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew-J: (mew.ja.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +File: mew.ja.info, Node: longline, Next: reply, Prev: charset-guess, Up: Composing + +長い行の取り扱い +================ + +長い間、メッセージに書く文章は、自分自身で各行を(英文字で)70文字程度に +折り返すべきだとされてきました。RFC 3676 で Text/Plain が拡張され、 +format パラメータに flowed という値が定義されました。 + +このおかげで、送り側で長い行を目印を付けて折り返し、受け取り側で長い行 +に戻せるようになりました。ユーザの目から見れば、メッセージに長い行を気 +軽に書いてもよくなったということです。 + +Mew で、長い行を flowed で折り返すには 2 つの方法があります。 + +1) 明示的に折り返すには、`C-cC-f'を実行します。 + +このコマンドは、草稿に長い行があるかを調べます。 +`mew-flowed-fold-threshold' を越える行が見つかったら、flowed で折り返 +しを実行します。この変数の値は 78 です。 + +折り返した行が、何文字以内になるかを制御する変数が +`mew-flowed-fold-length'です。初期値は 70 です。 + +折り返す方法は、文字コードによって変わります。分かち書きをする文字コー +ドでは、既存の空白文字の後に改行文字を入れて折り返します(delsp=no)。分 +かち書きをしない文字コードでは、適切な場所に空白文字と改行文字の両方を +挿入して折り返します(delsp=yes)。 + +もう一度 `C-cC-f' を実行すると、折り返された行が元に戻ります。 + +2) `mew-use-format-flowed' が `t' の場合は、`C-cC-c'や`C-cC-m'でメッセー +ジを作成するときに、この機能が働きます。この変数の初期値は `nil' です。 + +3) `C-cC-pC-f' で、`mew-use-format-flowed' の値を反転できます。 + + +なお、メッセージを表示する際は、`mew-use-format-flowed' の値に関係なく +flowed で折り返された行は、元に戻されます。長い行が見にくい場合は、 +Summary モードで `_' を利用しましょう。 + +`mew-flowed-auto-wrap' が `t' の場合、メッセージを表示すると、元に戻さ +れた行に一回 `_' が実行され、折り返された状態で表示されます。 +`mew-flowed-auto-wrap' のデフォルトの値は `t' です。 + + + +File: mew.ja.info, Node: reply, Next: forward, Prev: longline, Up: Composing + +メッセージへの返答と宛先の決定 +============================== + +新規にメッセージを書く場合は、To:、Cc:、および Newsgroups: を自分で書 +くことになります。一方 Summary モードで `a' や `A' を使って、あるメッ +セージに返答しようとすると、To:、Cc:、Newsgroups: は自動的に用意されま +す。 + +Summary モードで `a' や `A' を使うと、新しい草稿が Draft modeに用意さ +れます。To:、Cc:、Newsgroups: の値は、以下の三つの alist に従って用意 +されます。 + + 1. もし `C-u' 付きで呼び出された場合、送信者/投稿者のみに返答する。 + この場合、`mew-reply-sender-alist' が利用される。 + 2. もし対象が自分自身で送ったメッセージなら、そのヘッダを加工せずに + 返答したいのであろう。この場合、`mew-reply-fromme-alist' が利用さ + れる。 + 3. そうでなければ、すべての人に返答する。この場合、 + `mew-reply-all-alist' が利用される。 + +`mew-reply-sender-alist' の初期値は以下の通りです。 + + '(("Reply-To:" + ("To:" "Reply-To:" "From:")) + (t + ("To:" "From:"))) + +これは、次のように解釈します。 + + 1. Reply-To: が存在すれば、Reply-To: と From: の値を新しい To: へコ + ピーする。 + 2. そうでなければ、From: の値を新しい To: へコピーする。 + +もし、Reply-To: で指定されたアドレスのみに返答したい場合は、 +`mew-reply-sender-alist' を以下のように設定するとよいでしょう。 + + (setq mew-reply-sender-alist + '(("Reply-To:" + ("To:" "Reply-To:")) + (t + ("To:" "From:")))) + +`mew-reply-fromme-alist' の初期値は以下の通りです。 + + '((t + ("To:" "To:") + ("Cc:" "Cc:") + ("Newsgroups:" "Newsgroups:")))) + +これは、次のように解釈します。 + + 1. To: の値を新しい To: へ、Cc: の値を新しい Cc: へ、Newsgroups: の + 値を新しい Newsgroups: へコピーする。 + +`mew-reply-all-alist' の初期値は以下の通りです。 + + '((("Followup-To:" "poster") + ("To:" "From:")) + ("Followup-To:" + ("Newsgroups:" "Followup-To:" "Newsgroups:")) + ("Newsgroups:" + ("Newsgroups:" "Newsgroups:")) + ("Reply-To:" + ("To:" "Reply-To:" "From:") + ("Cc:" "To:" "Cc:" "Apparently-To:")) + (t + ("To:" "From:") + ("Cc:" "To:" "Cc:" "Apparently-To:"))) + +これは、次のように解釈します。 + + 1. Follwup-To: の値が "poster" であれば、From: の値を新しい To: へコ + ピーする。 + 2. Follwup-To: が存在すれば、Follwup-To: と Newsgroups: の値を新しい + Newsgroups: へコピーする。 + 3. Newsgroups: が存在すれば、Newsgroups: の値を新しい Newsgroups: へ + コピーする。 + 4. Reply-To: が存在すれば、Reply-To: と From: の値を新しい To: へコ + ピーする。また、To:、Cc:、Apparently-To: の値を新しい Cc: へコピー + する。 + 5. そうでなければ、From: の値を新しい To: へコピーする。また、To:、 + Cc:、Apparently-To: の値を新しい Cc: へコピーする。 + +`mew-reply-all-alist' を以下のように設定したいと思う人もいるかもしれま +せん。 + + (setq mew-reply-all-alist + '((("Followup-To:" "poster") + ("To:" "From:")) + ("Followup-To:" + ("Newsgroups:" "Followup-To:")) + ("Newsgroups:" + ("Newsgroups:" "Newsgroups:")) + ("Reply-To:" + ("To:" "Reply-To:")) + (t + ("To:" "From:") + ("Cc:" "To:" "Cc:" "Apparently-To:")))) + +あるアドレスが複数ある場合は、自動的に 1 つになります。また、匿名の宛 +先を表す ":;" で終るアドレスも、自動的に消去されます。 + +自分のアドレスは自動的に消去されます。自分のアドレスは、 +`mew-config-alist' などから `mew-mail-address-list' に自動設定されます。 +この値が気に入らないなら、以下のように明示的に設定することも可能です。 + + (setq mew-mail-address-list + '("^pooh@[a-z]*.example.org$" + "^pooh@example.net$" + "^winnie@example.jp$")) + + + +File: mew.ja.info, Node: forward, Next: resend, Prev: reply, Up: Composing + +メッセージの転送 +================ + +メッセージを転送するには、Summary モードで `f' や `F' を利用します。す +ると、Draft モードに移行し、あらかじめメッセージが添付領域に添付された +草稿が準備されます。 + +また Draft モードで添付領域を用意し、メッセージをコピー(`c')したりメッ +セージにリンク(`l')を張ったりしても、メッセージを転送できます。ファイ +ル名が数字([0-9]+)の場合は、自動的にメッセージだと判断されます。また、 +添付領域で `y' を使うと、Message モードに表示しているメッセージにリン +クを張るので便利です。 + +通常は添付したメッセージの全体が転送されます。もし、ヘッダの一部を削りた +い場合は、`mew-field-delete-for-forwarding' を定義して下さい。以下 +に "Received:" と "Return-Path:" を転送時に削るための設定例を示します。 + + (setq mew-field-delete-for-forwarding '("Received:" "Return-Path:")) + + + +File: mew.ja.info, Node: resend, Next: shortcut, Prev: forward, Up: Composing + +メッセージの再送 +================ + +メッセージのヘッダの一部のみを変更して、送信したい場合があります。 + +たとえば、同じ内容のメッセージを、複数の宛先に独立して送りたい場合です。 +pooh 宛のメッセージを作成して、+queue に入れ、すぐさまそのメッセージを +コピーし、宛先だけを piglet に変更したい場合を想像して下さい。これを、 +メッセージの再利用による送信と呼びましょう。 + +また、メッセージに Resent-To: というフィールドを付けて再送したいことも +あります。これは、転送の一種です。こちらはヘッダだけ書き直すので、ヘッ +ダ変換といいます。前節で説明した転送は、メッセージを新規のメッセージに +包み込んで転送するため、カプセル化と呼ばれています。 + +ヘッダの一部だけを編集し、メッセージを送信したり、キューに入れたりする +モードとして、Header モードが用意されています。本文が編集できない +Draft モードだと思えばいいでしょう。 + +Header モードに入るために、Summary モードには以下のコマンドが用意され +ています。 + +`W' + メッセージの再利用による送信。対象となるメッセージの To:、Cc:、 + From: などを書き換えるために、Header モードに移行する。典型的には、 + +queue または +postq に入っているメッセージに対して利用する。 +`r' + メッセージの再送。対象となるメッセージのヘッダに、Resent-To:、 + Resent-Cc:、Resent-From: などを追加するために、Header モードに移 + 行する。再送によるメッセージの転送は、受信者を混乱させることがあ + るので、よく考えてから利用すること。 + +Header モードでは、Draft モードのように、補完や循環的な補完が利用でき +ます。ヘッダの入力が終わったら、以下のどちらかのコマンドを用いて、メッ +セージを送信して下さい。本文が表示されていないので不安かもしれませんが、 +ちゃんと対象となっているメッセージの本文とヘッダの一部が再利用されます。 + +`C-cC-m' + メッセージを作成し +queue または +postq に入れ、送信待ち状態にす + る。 +`C-cC-c' + メッセージを作成し送信する。"Really send this message? (y or n) " + と訊かれる。`y' を押せば送信される。 + + + +File: mew.ja.info, Node: shortcut, Next: mark-b-comp, Prev: resend, Up: Composing + +電子署名/暗号メールを作成する +============================= + +ここでは、テキストである本文を PGP や S/MIME で署名したり暗号化したり +する方法について説明します。紹介するコマンドは以下の通りです。 + +`C-cC-s' + 草稿全体を署名する。パスフレーズを入力すること。 +`C-cC-e' + 草稿全体を暗号化する。 +`C-cC-b' + 草稿全体を署名後暗号化する。パスフレーズを入力すること。 +`C-cC-r' + 草稿全体を暗号化後署名する。パスフレーズを入力すること。 + +メッセージを暗号化するには受信者の公開鍵を使用します。逆に署名するには +自分の秘密鍵を使います。よって、署名するためにはパスフレーズを入力する +必要があります。ただし、パスフレーズの保存機能やマスターパスワードを使っ +ており、パスフレーズが保存されている場合は、パスフレーズを入力する必要 +はありません(*Note password::)。 + +これらのコマンドは、通常 PGP/MIME を作成します。S/MIME を作成したい場 +合は、以下のように設定して下さい。 + + (setq mew-draft-privacy-method 'smime) + +この変数の値は、Draft モードの `C-cC-pC-m' でも変更できます。 + +上記4つのコマンドは、次節で説明するマークを使った作成方法の省略方法に +当たります。 + +メッセージに署名を施すには、`C-cC-s' と入力します。署名の際には、自分 +の秘密鍵を復号化する必要がありますので、パスフレーズがキャッシュされて +いなければ、入力を促されます。署名が施されたメッセージは、+queue また +は+postq に格納されます。 + +自分の秘密鍵は、From: にあるアドレスを元に特定されます。From: がない場 +合は、デフォルトの秘密鍵が選択されます。From: にあるアドレスとは違うア +ドレスで秘密鍵を指定したい場合は、`C-uC-cC-s' と入力して下さい。 + +メッセージを暗号化するには、`C-cC-e' とタイプして下さい。To: や Cc: か +らアドレスを切り出して、その受信者が復号化できるよう暗号化します。暗号 +化するだけのなので、パスフレーズを訊かれることはありません。作成された +メッセージは、+queue に格納されます。 + +このメッセージは、受信者の公開鍵に加えて、自分の公開鍵でも暗号化されて +います。ですから、作成したメッセージを復号化できます。たとえば、`g' で ++queue に移動し、念のため復号化して確認することが可能です。 + +署名後暗号化するには、`C-cC-b' と入力します。暗号化後署名するには、 +`C-cC-r' とタイプします。どちらの場合も作成されたメッセージは、+queue +に蓄えられます。 + +署名を施したり、暗号化したりしてメッセージを送ろうと思っていても、うっ +かり忘れることがあります。これを防ぐために、メッセージを作成するコマン +ド `C-cC-m' や `C-cC-c' を実行すると、自動的に署名や暗号化を施す機能が +あります。 + +作成するすべてのメッセージのプライバシを保護したいなら、 +`mew-protect-privacy-always' を `t' にして、 +`mew-protect-privacy-always-type' に利用したいサービスを設定します。 + +暗号化されたメッセージに対する返答メッセージのプライバシを保護したいな +ら、`mew-protect-privacy-encrypted' を `t' にして、 +`mew-protect-privacy-encrypted-type' に利用したいサービスを設定します。 +この設定は、暗号化されたメッセージへの返答する場合、上記のすべてのメー +ルに対する設定よりも優先されます。 + +以下に利用できるサービスを示します。かっこ内はそれぞれのサービスを表す +シンボルです。`C-cC-m' や `C-cC-c' と入力する際に利用されるサービスは、 +モードラインに表示されます。 + +pgp-signature (PS) + PGP で署名 +pgp-encryption (PE) + PGP で暗号化 +pgp-signature-encryption (PSPE) + PGP で署名後暗号化 +pgp-encryption-signature (PEPS) + PGP で暗号化後署名 +smime-signature (SS) + S/MIME で署名 +smime-encryption (SE) + S/MIME で暗号化 +smime-signature-encryption (SSSE) + S/MIME で署名後暗号化 +smime-encryption-signature (SESS) + S/MIME で暗号化後署名 + +以下の例は、すべてのメッセージに対し署名する設定です。 + + (setq mew-protect-privacy-always t) + (setq mew-protect-privacy-always-type 'pgp-signature) + +以下の例は、暗号化されたメッセージへの返答メッセージに対し、PGP で暗号 +化する設定です。 + + (setq mew-protect-privacy-encrypted t) + (setq mew-protect-privacy-encrypted-type 'pgp-encryption) + +Draft モードでは、`C-cC-pC-a' で `mew-protect-privacy-always'、 +`C-cC-pC-e' で `mew-protect-privacy-encrypted' の値を反転できます。 + +Draft モードにおいて現在書いている草稿に対してのみあらかじめサービスを +指定しておき、送信時にサービスを施すことを忘れないようにできます。現在 +の草稿に対し `C-cC-m' や `C-cC-c' で施されるサービスを指定するには、 +`C-cC-pC-d' に続いて上記のサービスの 1 つを入力して下さい。現在のサー +ビスをキャンセルするには、サービス名の代りに単に `RET' を押して下さい。 + +`C-cC-c' や `C-cC-m' でメッセージを作成する際、署名や暗号化に +失敗したら、草稿に戻ります。このとき指定していたサービスはキャンセルされ +ます。続けて `C-cC-c' や `C-cC-m' でメッセージを作成すると、普 +通のメッセージが作成されるので気をつけて下さい。問題を取り除いた後、同じ +サービスを望むなら、明示的に `C-cC-pC-d' でサービスを指定するか、 +`C-cC-s'、`C-cC-e' などを用いて下さい。 + + +`mew-use-old-pgp' を `t' に設定すれば(初期値は `nil')、`C-cC-s' や +`C-cC-e' は PGP/MIME の代りに、古い PGP の書式に従ってメッセージを生成 +します。添付領域がある場合は、エラーになります。 + +上記で説明した `mew-protect-privacy-*' は、PGP/MIME のみに有効であり、 +古い PGP には機能しません。`C-cC-m' や `C-cC-c' で常に古い PGP の署名 +を施すには、`mew-protect-privacy-with-old-pgp-signature'を `t' にして +下さい。 + +PGP/MIME や S/MIME のために Mew は GnuPG 1.x と 2.0 をサポートしていま +すが、2.1 はサポートしていません。 + + + +File: mew.ja.info, Node: mark-b-comp, Next: pgp-key, Prev: shortcut, Up: Composing + +マークを使った電子署名/暗号メールの作成 +======================================= + +PGP/MIME、S/MIME、および ZIP をサポートするために、マークを使った作成 +方法が提供されています。以前の例を思い出してみましょう。 + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + B 2 Image/Gif MagicPoint のロゴ mgp.gif + Q 3 Application/Postscript 資料 ohp.ps + 4 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +行頭に `B' や `Q' といったマークがあります。このマークは符号化を意味し +ています。Mew では、新しい概念「符号化」を導入しています。符号化には、 +Base64、Quoted-Printable、Gzip64 (Gzip + Base64)、署名、暗号化などがあ +ります。 + +現在次の 8 つのマークがサポートされています。 + +`" "' + 符号化しない。ただし、8 ビットのテキストは符号化されるかもしれな + い。 +`B' + Base64 +`Q' + Quoted-Printable +`G' + Gzip64(gzip 圧縮し Base64 で符号化する。Mew が実験的に採用してい + る。相手が Mew を使っていない場合は、使用すべきではない。) +`PS' + PGP で電子署名。 +`PE' + PGP で暗号化。 +`SS' + S/MIME で電子署名。 +`SE' + S/MIME で暗号化。 + +添付領域でのマークに関係する新しいキー割当は以下の通りです。 + +`B' + Base64 で符号化するため `B' マークを付ける。 +`Q' + Quoted-Printable で符号化するため `Q' マークを付ける。 +`G' + Gzip64 で符号化するため `G' マークを付ける。ただし、Text/Plain と + Application/Postscript でしか実行できない。これ以外の型には圧縮は + 無意味である。なぜなら、jpeg などはあらかじめ圧縮されているから。 +`S' + PGP で署名するため `PS' マークを付ける。 +`E' + PGP で暗号化するため `PE' マークを付ける。受信者のアドレスを入力 + する。 +`M-s' + S/MIME で署名するため `SS' マークを付ける。 +`M-e' + S/MIME で暗号化するため `SE' マークを付ける。受信者のアドレスを入 + 力する。 +`Z' + ZIP で直ちに暗号化する。暗号化された後は、`B'マークが付く。 +`U' + 符号化を元に戻す。元々のマークに戻る。 + +次の例を考えてみましょう。パート 2 は PGP で署名され、"kazu" 用に PGP +で暗号化されます。安心して下さい。説明の部分は上書きされていますが、保 +存されています。パート 3 は Gzip64 で符号化されます。 + + ----------------------------- attachments ----------------------------- + Multipart/Mixed 1/ + 1 Text/Plain(guess) CoverPage* + PSPE 2 Image/Gif kazu@example.org mgp.gif + G 3 Application/Postscript 資料 ohp.ps + 4 . + --------0-1-2-3-4-5-6-7-8-9-------------------------------------------- + +マークを付けた後は、`C-cC-m' や `C-cC-c' を使って、メッセージを作成し +て下さい。 + + + +File: mew.ja.info, Node: pgp-key, Next: anonymous, Prev: mark-b-comp, Up: Composing + +PGP の鍵の配布 +============== + +PGP の公開鍵を配布するには、Draft モードの添付領域で `p' を押して下さ +い。だれの公開鍵を配布するか尋ねられます。自分の公開鍵であれば、単に +`RET' と入力して下さい。他人の公開鍵であれば、補完を利用しながらその人 +のアドレスを入力して下さい。PGP の公開鍵は、Application/Pgp-Keys とい +うデータ型で配送されます。 + +Summary モード、あるいは、Virtual モードでメッセージを読んでいる際に、 +あるパートのデータ型が Application/Pgp-Keys であれば、Mew は PGP の公 +開鍵リングにそれを登録しようとします。Mew は、「信用度」と「有効性」を +全く考慮しないことに注意して下さい。これらの値を設定するのは、あなた自 +身です。設定は Mew が表示する説明に従って下さい。もし、「信用度」と +「有効性」の意味が分からなければ、PGP を使って自分のプライバシを保護し +ようとする前に、PGP が提供する「信用の輪」とは何かを学ぶべきです。 + + + +File: mew.ja.info, Node: anonymous, Next: Marks, Prev: pgp-key, Up: Composing + +宛先を匿名にしたメッセージの送信 +================================ + +宛先を匿名にして、複数の受信者にメッセージを送信したいことがあります。 + +たとえば、pooh がパーティーへのお誘いを複数の友達に送ることを考えて下 +さい。パーティーへ参加するという piglet からの返事は、pooh のみに送る +べきです。しかし、To: にたくさんの友達を列挙していると、piglet は誤っ +て多くの人に返答を送りつけてしまうかもしれません。そもそも、pooh は誰 +を誘ったのか、当日までふせておきたいこともあるでしょう。 + +このような要望を実現するために、Mew では匿名の宛先として、":;" を利用 +します。以下の例を見て下さい。 + + To: party:piglet@example.org,roo@example.org; + From: Pooh + +"party" という説明文字列の後に ":" があります。そして、いくつかアドレ +スが "," で区切られながら列挙され、";" で終端されています。このような +形式でアドレスを書くと、Mew は ":" と ";" のアドレスにメッセージを届け +ますが、ヘッダからは削り取ります。この例では、piglet と roo は以下のよ +うなメッセージを受け取ります。 + + To: party:; + From: Pooh + +受信者はこのヘッダから、送信者は pooh であることは分かりますが、自分以 +外の誰に送られたのかは、想像するほかありません。また、"party:;" という +文字列は、アドレスではありませんから、ここに返答することも不可能です。 + +なお、To: や Cc: にたくさんのアドレスを列挙することは、本質的によいこ +とではありません。特定の人にメッセージを何度も送信する機会があるなら、 +通常メーリングリストを作成します。 + + + + +File: mew.ja.info, Node: Marks, Next: unread mark, Prev: anonymous, Up: Top + +愉快なマークたち +**************** + +ここでは、Summary モードでユーザが付けたり消したりできるマークについて +説明します。このマークは以下のように、行頭に付きます。(Mew が付けるマー +クは日付の左に付くことに注意。) + + D 03/12 Hidenori Ohta 今週末 |日曜にストーンマジック + oM03/14 ももちゃん 能登の写真 |この前撮った写真を添付 + * 03/15 Neat Sumikawa Re: ワイン |じゃぁ、水曜日に例の店 + +現在利用できるマークは以下の 6 つです。 + +`U' + 未読マーク。 +`D' + 消去のマーク。 +`X' + 消去のマーク。 +`o' + 整頓、つまり、フォルダを移動させるマーク。 +`*' + 処理の対象とするマーク。 +`$' + マークを一時的に待避するためのマーク。 + +マークを付けるだけでは、メッセージがなくなったりすることはありません。 +`o'、`D'、`X' といったマークを実際に処理するコマンドは、`x' です。マー +クを付けるのは気軽にできますが、`x' を押すときは慎重にお願いします。 + +以下それぞれについて説明します。また、Mew が表示するマークについてもま +とめます。 + +* Menu: + +* unread mark:: 未読 `U' +* delete mark:: 消去 `D'、`X' +* refile mark:: 整頓 `o' +* target mark:: 対象 `*' +* escape mark:: 待避 `$' +* unmark:: マークの消去 +* mark change:: マークの変換 +* sync:: IMAP サーバとのマークの整合性 +* off-line:: IMAP のためのマークのオフライン処理 +* mew-mark:: Mew が表示するマーク + + + +File: mew.ja.info, Node: unread mark, Next: delete mark, Prev: Marks, Up: Marks + +未読 `U' +======== + +以下のように設定すると、メッセージを一覧表示する際に、未読マーク +`U' がメッセージに付きます。 + + (setq mew-use-unread-mark t) + +`SPC'、`n'、および `p' などでメッセージを読むと +`U' マークは消えます。 + +この三つのコマンドは、通常 `*' マーク、`U' マーク、およびマー +クの付いていないメッセージを読み進みます。`zSPC' を押すと、これら +は `*' マークと `U' マークの付いたメッセージのみを読み進めま +す。これは、未読のメッセージを読み進める場合に便利です。もう一度 +`zSPC' を実行すると、対象とするメッセージが元に戻ります。 + +前のメッセージにマークを付けて、現在のメッセージに移動して来ると、`U' +マークは消えます。`SPC'、`n'、および `p' で移動して来た場合は、このメッ +セージを読むことを意図しているはずですが、マークを付けることで移動した +場合はメッセージを読むことを意図していないかもしれません。その場合、 +`U' マークが消えると少し不便です。マークを付けることで移動した際に、 +`U' マークを消したくないのであれば、以下のように設定するとよいでしょう。 + + (setq mew-delete-unread-mark-by-mark nil) + +以下に `U' マークに関するコマンドをまとめます。 + +`zSPC' + `SPC'、`n'、および `p' が読み進める対象とするメッセージを反転させ + る。反転とは、「`U' マーク、`*' マーク、およびマークなし」と「`U' + マークおよび `*' マーク」に対し、一方を他方へ変えること。 +`M-u' + `U' マークを付ける。 + + + + +File: mew.ja.info, Node: delete mark, Next: refile mark, Prev: unread mark, Up: Marks + +消去 `D'、`X' +============= + +メッセージを消去するには、まず Summary モードで `d' を押して、 +`D' マークを付けます。マークを付けただけでは何も起こらないので、間 +違って `d' を押しても大丈夫です。デフォルトでは、`x' を押すと +`D' マークの付いたメッセージがゴミ箱に移動します。 + +ローカル・フォルダのためのゴミ箱は +trash です。IMAP のためのゴミ箱は、 +%trash です。 + +ゴミ箱の中のメッセージを実際に消去するには、以下の 2 つの方法がありま +す。 + + 1. Summary モードで `D' を実行する。 + 2. ゴミ箱で `D' マークを付けて、`x' を押す。 + +もう少し正確に言うと、ローカル・フォルダでは以下のルールが適用されます。 +(`mew-trash-folder' の初期値は +trash。 +`mew-trash-folder-list' の初期値は `nil'。) + + - `mew-trash-folder' が `nil' なら、`D' マークの付いたメッセージは + 消去される。 + - `mew-trash-folder-list' が定義されていたら、それらのフォルダ + で `D' マークを付けたメッセージは消去される。それ以外のフォルダからは + `mew-trash-folder' へ。 + - `mew-trash-folder-list' が `nil' なら、 `mew-trash-folder' で `D' + マークを付けたメッセージは消去される。それ以外のフォルダからは + `mew-trash-folder' へ。(これが初期値。) + +IMAP に対しては、`mew-imap-trash-folder' と +`mew-imap-trash-folder-list' に従って、同じ規則が適用されます。 + +すべての `*' マークを `D' マークに変換できれば、一度にたくさんの `D' +マークを付けられて便利です。これには、`md' を利用して下さい。 + +また、`Md' を使うと、現在のフォルダ内で同じ Message-Id: を持つメッセー +ジがある場合、1 つを残して他のメッセージに `D' が付きます。 + +`D' マークに似たものに `X' マークがあります。このマークの付けられたメッ +セージは、`x' を押した際に必ず消去されます。`X' マークは、`M-d' で付け +ることができます。 + +`mxM-d' で、`X' マークが付いたメッセージだけを処理できます。 +すべての `*' マークを `X' マークに変換するコマンドは、 +`mM-d' です。 + + +以下に、`D' マークと `X' マークに関するコマンドをまとめます。 + +`d' + `D' マークを付ける。 +`M-d' + `X' マークを付ける。 +`md' + `*' マークを `D' マークへ変換する。 +`mM-d' + `*' マークを `X' マークへ変換する。 +`x' + マークの付いたメッセージを処理する。 +`mxd' + `D' マークの付いたメッセージのみを処理する。 +`mxM-d' + `X' マークの付いたメッセージのみを消去する。 +`D' + ゴミ箱の中のメッセージを全部消去する。 +`C-uD' + 指定されたフォルダのメッセージを全部消去する。 + + + +File: mew.ja.info, Node: refile mark, Next: target mark, Prev: delete mark, Up: Marks + +整頓 `o' +======== + +メッセージを整頓するには `o' を押して、移動先のフォルダを入力し、 +`o' マークを付けます。移動先のフォルダは、賢く推測してくれるので、 +ほどんどの場合はフォルダ名を入力する代わりに `RET' を押すだけです。 +"," で区切って複数のフォルダを入力することもできます。もちろん、 +`TAB' で補完できます。詳しくは *Note Refile:: を参照して下さい。 + +`o' マークの付いたメッセージの上で `o' を押すと、移動先を追加したり変 +更したりできます。また、実際の移動は `x' と入力されたときに実行されま +す。 + +複数のフォルダを指定し、移動させたときのことを考えましょう。ハードリン +クの機能を持つファイルシステムを使っている場合、そのメッセージは最初の +フォルダに移動され、その他のフォルダからはハードリンクが張られます。そ +うでないファイルシステムの場合は、最初のフォルダに移動後、その他のフォ +ルダへ複製されます。 + +指定したフォルダが 1 つで、しかもそれが現在のフォルダである場合、整頓 +してもなにも起こりません。指定したフォルダが複数で、現在のフォルダが含 +まれる場合、現在のフォルダ内での番号を保ったまま、その他のフォルダから +ハードリンクが張られるか、その他のフォルダへ複製されます。 + +`o' に似ていますが、かならず現在のフォルダも候補として提示する +`c' というコマンドも用意されています。 + +以下に、`o' マークに関するコマンドをまとめます。 + +`o' + `o' マークを付ける。 +`c' + `o' マークを付ける。推測したフォルダに加えて、現在のフォルダも候 + 補として提示する。 +`x' + `o' マークの付いたメッセージを移動させる。 +`mxo' + `o' マークの付いたメッセージのみを移動させる。他のマークは処理しない。 +`C-umxo' + `o' マークの付いたメッセージの中で、現在のメッセージと同じ移動先 + を持つもののみを移動させる。 + + + +File: mew.ja.info, Node: target mark, Next: escape mark, Prev: refile mark, Up: Marks + +対象 `*' +======== + +後から読み返したいメッセージには、`*' で `*' マークを付けて下さい。ま +た、選択コマンド `?' を使うと、入力した条件にマッチするメッセージに +`*' マークが付きます(詳しくは、*Note search:: を参照して下さい)。`N' +や `P' で `*' マークの付いたメッセージに移動し表示できます。 + +以下に、`*' に関連するコマンドを示します。 + +`*' + `*' マークを付ける。 +`N' + 下方向の `*' マークの付いたメッセージへ移動し表示。 +`P' + 上方向の `*' マークの付いたメッセージへ移動し表示。 +`ma' + マークの付いていないメッセージすべてに `*' マークを付ける。 +`mr' + 入力した正規表現にマッチしたメッセージに `*' マークを付ける。 + +`*' マークは、複数のメッセージを処理するためにも利用します。以下に複数 +のメッセージを処理するコマンドを示します。 + +`F' + `*' マークの付いたメッセージを MIME 形式で転送するための草稿を準備。 +`J' + 大きなメッセージは Message/Partial として複数に分割されている場合 + がある。これらのメッセージには、Mew によって `P' マークが付けられ + ている。ここで、ユーザがそれらのメッセージに `*' マークを付け、こ + のコマンドを実行すれば、元のメッセージが復元される。 +`mI' + `*' マークの付いている一部だけが取得されたメッセージ群(`T')を取得 + する。 +`C-umI' + `mI' を実行する。 +`M-b' + `*' マークの付いたメッセージに格納されているメッセージを取り出す。 +`M-\' + `*' マークの付いたメッセージを引数として、外部コマンドを起動する。 +`M-t' + `*' マークの付いたメッセージを "uudecode" する。 + +`M-t' では、`*' マークの付いたメッセージがきちんと分割順になっている必 +要があります。順番がくるっているなら、`S' でソートするとよいかもしれま +せん。 + + + +File: mew.ja.info, Node: escape mark, Next: unmark, Prev: target mark, Up: Marks + +待避 `$' +======== + +たとえば `/' などを使いパターンに合致したメッセージに `*' を付けること +を考えて下さい。`*' マークの付いたメッセージがすでにあるなら、これらの +メッセージは `/' の結果と混ざってしまいます。そこで、現在の `*' マーク +を一時的に保存したくなります。 + +この目的のために、待避マーク `$' が提供されています。典型的な使い方は、 +以下のようになります。 + + 1. `m$' で `*' マークを一旦 `$' マークに待避 + 2. `/' などで `*' マークを付け、`*' マークのついたメッセージを処理 + 3. `U*' で `*' マークを消去 + 4. `m*' で `$' マークを `*' マークへ戻す + +`$' マークに関するコマンドを以下にまとめます。 + +`m$' + `*' マークを `$' マークへ変換。 +`m*' + `$' マークを `*' マークへ変換。 + + + +File: mew.ja.info, Node: unmark, Next: mark change, Prev: escape mark, Up: Marks + +マークの消去 +============ + +`o' マークや `D' マークが付いたメッセージは、マーク実行コマンド `x' を +押さない限り処理されません。よって、`x' を押す前に、マークを取り止める +コマンド `u' でマークを消せば、誤ってメッセージを消すことはありません。 + +以下にマークを消去するコマンドをまとめます。 + +`u' + 現在のメッセージのマークを消す。 +`U' + 入力したマークが付いているすべてのメッセージのマークを消す。 + +`$' マークを使って `*' マークを待避し、なんらかの操作をし、元に戻す方 +法は、目に見えるので分りやすいです。しかしながら、`$' マークが付いてい +るメッセージは、マークが付いているので目的の操作の対象外になるかもしれ +ません。 + +このため `U*' で消去した `*' マークを復活させるコマンドがあります。そ +れは、`M*' です。この方法は、復活できるマークは目に見えないので分りに +くいかもしれません。しかしながら、マークが消えているので、そのメッセー +ジは確実に目的の操作の対象になります。 + +`M*' + 一番最後の `U*' で消した `*' マークを復活させる。 + + + + +File: mew.ja.info, Node: mark change, Next: sync, Prev: unmark, Up: Marks + +マークの変換 +============ + +マークには強さのレベルがあります。同じレベルのマークは上書きできます。 +強いマークは弱いマークを上書きできます。 + +マークを強い順に示します。 + +`o'、`D'、`X' + 新たにマークしたときは、次のメッセージを表示。上書きした場合は、 + その行に留まる。 +`*' と `$' + マークを付けた後は、その行に留まる。 +`U' + マークを付けた後は、その行に留まる。 + +強いマークを付けた後にカーソルが動く方向については、*Note +summary-mode:: を参照して下さい。 + +マークは以下のように交換できます。 + +`m$' + `*' -> `$' :: `*' マークを一時的に保存。 +`m*' + `$' -> `*' :: `*' マークを元に戻す。 +`ms' + `$' <-> `*' +`mM-u' + `*' -> `U' :: 選択コマンド `?' で選んだメッセージを未読にするとき + に便利。 +`md' + `*' -> `D' :: 選択コマンド `?' で選んだメッセージを消去するときに + 便利。 +`mM-d' + `*' -> `X' :: 選択コマンド `?' で選んだメッセージを消去するときに + 便利。 +`mo' + `*' -> `o' :: 選択コマンド `?' で選んだメッセージをあるフォルダに + 移動させる場合に便利。 +`mc' + `*' -> `o' :: 選択コマンド `?' で選んだメッセージをあるフォルダに + コピーする場合に便利。 +`e' + 最初に入力したマークを次に入力したマークへ変換する。ただし、`o' + マークは対象外。 + + + +File: mew.ja.info, Node: sync, Next: off-line, Prev: mark change, Up: Marks + +IMAP サーバとのマークの整合性 +============================= + +Mew では、以下のマークに対し、IMAP サーバと整合性を確保できます。 + +`U' + メッセージを読んだか否か。IMAP のフラグは \Seen。通常は %inbox の + みで有効。 +`*' + 注目しているメッセージ。IMAP のフラグは \Flagged。 + +オフラインの操作を許すために、Mew ではユーザが動作を起こすたびに IMAP +サーバとマークの整合性を取ります。定期的に整合性を取ることはしません。 +Mew がマークの整合性を取る方法を以下に示します。 + + 1. `s' + 'update + - 既存のメッセージに対して変更したマークをサーバ側へ反映 + - 新着メッセージに対しては、サーバ側のフラグをマークへ反映 + + 2. `x' + - 既存のメッセージに対して変更したマークをサーバ側へ反映 + + 3. `s' + 'sync + - 既存のメッセージに対して変更したマークをサーバ側へ反映 + - 既存のメッセージの `*',`U', `$', ` ' マークを一旦クリア + - サーバ側のフラグを既存のメッセージにマークとして反映 + - サーバ側で削除されたメッセージを削除 + + + +File: mew.ja.info, Node: off-line, Next: mew-mark, Prev: sync, Up: Marks + +IMAP のためのマークのオフライン処理 +=================================== + +IMAP ユーザは、フォルダ A のメッセージをキャッシュし、出先で `o'マーク +や `D' マークを付け、その場でそれらのマークを処理したくなることがあり +ます。この場合、その後ネットワークに接続したときに、それらの処理が +IMAP サーバに反映されて欲しいと思います。 + +通常 IMAP では、メッセージをフォルダ A からフォルダ B へ移動させた場合、 +フォルダ A にキャッシュされているそのメッセージを削除し、IMAP サーバか +らネットワークを通じ、フォルダ B へそのメッセージをキャッシュし直す必 +要があります。なぜなら、フォルダ A にキャッシュされているメッセージに +付随する IMAP の情報は、フォルダ A 内でのみ有効だからです。 + +出先でフォルダ A のメッセージをフォルダ B へ整理したとしましょう。仮に、 +そのメッセージをフォルダ B で読むためには、ネットワークに接続してその +処理を IMAP サーバに反映し、IMAP サーバから取り直さないといけないとす +ると不便です。欲を言えば、出先でフォルダ B へ整理したメッセージは、 +IMAP サーバから取り直さなくとも、フォルダ B へ移動すれば読めるようになっ +ていて欲しいと思います。 + +Mew では、メッセージ処理を後から IMAP サーバへ反映することと、IMAP サー +バからメッセージを再取得しなくても移動先のフォルダでメッセージを読める +ことの両方を実現しています。ネットワークに接続していない状況で、マーク +を処理するには、`lx' を使用して下さい。`lx' を実行すると、以下の処理が +なされます。 + + 1. `o' マークや `D' マークのついたメッセージがフォルダ A からなくな + る。 + 2. この処理はメッセージ形式で、%queue に溜る。 + 3. `o' マークのついたメッセージは、ローカルでフォルダ B へ移動され、 + 無効なメッセージとして扱われる。 + +無効なメッセージとは、読むことはできるが、`o' マークや `D' マークをつ +けられないものをいいます。無効なメッセージには、`#' マークが付いていま +す。`g' を使って、フォルダ B へ行くと、無効なメッセージの一覧が自動的 +に表示されます。 + +ネットワークに接続した後に、%queue に溜っている処理を IMAP サーバに反 +映させるには、%queue で `C-cC-c' と入力して下さい。 + +IMAP サーバに処理を反映した後に、フォルダ B で `s' を押すと、無効なメッ +セージが削除され、有効なメッセージがキャッシュされます。 + + + +File: mew.ja.info, Node: mew-mark, Next: Refile, Prev: off-line, Up: Marks + +Mew が表示するマーク +==================== + +以下に Mew が表示するマークをまとめます。 + +`M' + マルチパートを表すマーク。*Note multipart:: を参照のこと。 +`-' + Multipart/Alternative を表すマーク。*Note analysis:: を参照のこと。 +`T' + メッセージが切り詰められたことを表すマーク。*Note retrieving:: を + 参照のこと。 +`S' + 署名を表すマーク。*Note cipher-viewing:: を参照のこと。 +`E' + 暗号化を表すマーク。*Note cipher-viewing:: を参照のこと。 +`P' + 分割されていることを示すマーク。*Note target mark:: を参照のこと。 +`#' + メッセージが無効であることを示すマーク。*Note off-line:: を参照の + こと。 + + + + +File: mew.ja.info, Node: Refile, Next: by-folder, Prev: mew-mark, Up: Top + +楽々整理整頓 +************ + +1 日に数百のメッセージを受け取るようになると整理整頓が大変になります +(え、そんなに受け取らないですって? 幸せですね :) 。Mew では、`o' でメッ +セージを整頓する際に、整頓先を推測し初期値として表示してくれます。たと +えば、次のようになります。 + + Folder name (+work/mew-dist): + + +もし、() の中の初期値が自分の希望通りであれば、`RET' を押すだけでよい +のです。整頓先が決定しているメッセージには、`o' マークが付きます。 + +メッセージを移動できるのは、そのメッセージが属している「世界」の中での +みです。前述のように世界はケースと修飾子によって定まります。整頓先のフォ +ルダを指定する場合には、ケースを付けず、同じ修飾子を持つフォルダ名を入 +力する必要があります。ケースを付けない理由は、そのメッセージのケースは +すでに定まっているからです。ミニバッファからフォルダ名を入力する際、ケー +スが "default" でないにも関わらずケースを明示的に入力しないのは、整頓 +先を指定する場合のみです。 + +`o' に似たコマンドに `c' があります。両者の違いは、 +*Note refile mark:: を参照して下さい。 + +この整頓先の推測が賢ければ賢い程ユーザは楽になります。Mew では以下のよ +うな規則が用意されています。 + +* Menu: + +* by-folder:: メーリングリスト用のフォルダから推測 +* by-alist:: 指定した規則から推測 +* by-thread:: 対話関係から推測 +* by-from-folder:: 個人用のフォルダから推測 +* by-from:: From: から推測 +* by-newsgroups:: Newsgroups: から推測 +* by-default:: デフォルトの規則 +* guess-rule:: 規則の制御 +* auto-refile:: 自動で整理整頓 +* copy-msg:: 世界を越えたメッセージのコピー + + + +File: mew.ja.info, Node: by-folder, Next: by-alist, Prev: Refile, Up: Refile + +メーリングリスト用のフォルダから推測 +==================================== + +あるメーリングリスト宛のメッセージを、そのメーリングリスト名のフォルダ +に整理することは多いと思います。Mew ではメーリングリスト宛に届いたメッ +セージに対して、それ用のフォルダを推測する機能があります。 + +たとえば、+misc/pooh-lovers というフォルダがあったとしましょう。次のよ +うなメッセージは、このフォルダに整頓すればよい可能性が高いといえます。 + + To: pooh-lovers@example.org + +このように、To: や Cc: のアドレスが、フォルダ名の一番右側にマッチする +ものがないか探すわけです。フォルダを階層化していない人が多いようですが、 +Mew を使う限り、階層化しない手はありません。 + +さて、鋭い人は次のように個人のアドレスが To: や Cc: にある場合、困るの +ではないかと思うでしょう。 + + To: piglet@example.org + Cc: pooh-lovers@example.org + +たとえば、pooh は pooh-lovers の一員ですから、このメッセージが届きます。 +しかし、piglet と仲がいいので、+from/piglet にマッチしてしまいます。 + +そこで、Mew では無視するフォルダを設定できるようになっています。デフォ +ルトでは、+from 以下を無視します。ですから、個人からのメッセージは ++from 以下に収めて下さい + +候補が決定できたら + + Folder name (+misc/pooh-lovers): + + +と訊いてきます。あっていれば `RET' を、違っていればお望みのフォルダを +入力して下さい。 + +`o' で新しいフォルダを指定すると、そのフォルダが自動的に作成され、次か +らは推測用の候補にも加わります。便利でしょ? + +この機能を提供する関数は `mew-refile-guess-by-folder' です。 + +もし、フォルダ名に大文字を使っていないなら、以下の設定により、この関数 +が高速になります。 + + (setq mew-use-fast-refile t) + +デフォルトでは、末端のフォルダと中間のフォルダが候補の対象となっていま +す。もし、中間のフォルダではなく、末端のフォルダだけを選びたい場合は、 +以下のように設定して下さい。 + + (setq mew-use-node-folder nil) + + + +File: mew.ja.info, Node: by-alist, Next: by-thread, Prev: by-folder, Up: Refile + +指定した規則から推測 +==================== + +フォルダ名から推測する機能だけでは、思うようなフォルダを推測してくれな +い場合があります。たとえば、To: が staff@example.jp であるメッセージと +To: が staff@example.net であるメッセージに対し、フォルダ名からの推測 +では同じフォルダ(たとえば、"+net/staff")が選ばれてしまいます。そこで、 +Mew では、変数 `mew-refile-guess-alist' に明示的に規則を設定できます。 +(`mew-refile-guess-alist' は、必ず新しい書式で書いて下さい。詳しくは +*Note config2:: を参照のこと。) + +1 つ例を挙げてみましょう。 + + (setq mew-refile-guess-alist + '(("To:" + ("staff@example.jp" "+jp/staff") + ("staff@example.net" "+net/staff")))) + +これは、メッセージヘッダ中の To: の横の文字列に staff@example.jp があ +れば +jp/staff へ、staff@example.net があれば +net/staff へ整頓すると +いう意味です。 + +規則は、以下のように書きます。 + + rule ::= ' + ::= (( ) ( ) ... []) + +全体は ( ) のリストです。 はフィールド名を書きます。 + は以下のようになります。 + + ::= ( |) ( |) ... + + は で示したフィールドにくる値です。 は に +マッチした際にどのフォルダに整頓するかを意味しています。 の代 +りに を再帰的に記述することもできます。 + +特殊な として `nil' と `t' があります。`nil' は、何も推測できな +かった場合に返す を指定するために用います。`t' は、推測した値 +に加えて返す を指示するために使います。 + + ::= (t ) | (nil ) + +正規表現を知っている人は、以下のような複雑な規則を設定できます。 + + (setq mew-refile-guess-alist + '(("Newsgroups:" + ("^nifty\\.\\([^ ]+\\)" "+Nifty/\\1") + (".*" "+rec/news")) + ("To:" + ("\\(inet\\|wide\\)@wnoc-fuk" "+wide/\\1-wnoc-fuk")) + ("From:" + ("uucp@" "+adm/uucp") + ("ftpsync@" "+adm/ftpsync")) + (nil "+unknown"))) + +この機能を提供する関数は `mew-refile-guess-by-alist' です。 + + + +File: mew.ja.info, Node: by-thread, Next: by-from-folder, Prev: by-alist, Up: Refile + +対話関係から推測 +================ + +Mew には、整頓しようとしているメッセージの親のメッセージが以前整頓され +たフォルダを選択してくれる機能があります。 + +たとえば、pooh、piglet、roo との間で、蜂蜜を取りに行こうという話題が盛 +り上がったとしましょう。pooh は、+project/honey というフォルダを作って、 +最初のメッセージをそこに整頓したとしましょう。以降、3 人の間のメッセー +ジがきちんとした返答であるかぎり、+project/honey を推測してくれます。 + +あるメッセージをどこに保存したかという情報は、 +"~/Mail/.mew-refile-msgid-alist" に保存されています。この情報を過去 +何通のメッセージに関して保存するかは、`mew-lisp-max-length' で決定 +します。初期値は 2000 通です。3000 通にしたい場合は "~/.mew.el" 中で以 +下のように設定して下さい。 + + (setq mew-lisp-max-length 3000) + +この機能を提供する関数は `mew-refile-guess-by-thread' です。 + + + +File: mew.ja.info, Node: by-from-folder, Next: by-from, Prev: by-thread, Up: Refile + +個人用のフォルダから推測 +======================== + +*Note by-folder:: で説明したメーリングリスト用のフォルダを推測するに加 +えて、個人用のフォルダを推測する機能があります。個人用のフォルダは ++from 以下にありますから、+from 以下のフォルダを選択する機能だともいえ +ます。以下の例を考えてみましょう。 + + To: pooh@example.net + From: piglet@example.org + +piglet から pooh にメッセージが来ました。pooh がこの機能を使うと、 +From: を手がかりに +from/piglet が選択されます。(+from 以下は階層化さ +れていても構いません。また、フォルダ名はユーザ名だけではなくアドレス全 +体でも OK です。) + +この機能を提供する関数は、`mew-refile-guess-by-from-folder' といいます。 + +次に、pooh が piglet に返答した場合を考えましょう。pooh は自分自身に +Cc: していたので、自分にメッセージが戻ってきました。 + + To: piglet@example.org + Cc: pooh@example.net + From: pooh@example.net + +pooh の立場になって考えてみて下さい。このメッセージを +from/pooh に整 +頓するか、あるいは +from/piglet に整頓するのかは、好みが分かれるところ +でしょう。そこで、どちらを選択するのかカスタマイズできるようになってい +ます。 + +`mew-refile-guess-from-me-is-special' が `t' なら、 +`mew-refile-guess-by-from-folder' は、From: が自分のアドレスの場合に、 +To: と Cc: にあるアドレスをもとに、+from 以下のフォルダを選択します。 + + + +File: mew.ja.info, Node: by-from, Next: by-newsgroups, Prev: by-from-folder, Up: Refile + +From: から推測 +============== + +From: に同一のアドレスを持つメッセージが、かつてどこに整頓されたかによっ +て推測する機能があります。 + +たとえば、piglet は piglet@example.org と p-p-p@example.org の 2 つの +アドレスを持っているとしましょう。どちらのアドレスからメッセージが届い +ても、pooh はそれらを +from/piglet に整頓したいと思っています。もちろ +ん、以下のように明示的に規則を書けば実現できます。 + + (setq mew-refile-guess-alist + '(("From:" + ("piglet@example.org" "+from/piglet") + ("p-p-p@example.org" "+from/piglet")))) + +しかし、いちいち規則を書くのは面倒です。そこで、まず From: が +piglet@example.org であるメッセージを +from/piglet に整頓します。これ +でフォルダ +from/piglet が作成されます。次に、From: が +p-p-p@example.org であるメッセージを +from/piglet に整頓したとします。 +ここで Mew は、p-p-p@example.org が +from/piglet に整頓されたことを学 +習します。以後 From: が p-p-p@example.org であるメッセージを整頓しよう +とすると、+from/piglet を選択するようになります。 + +その他、機械からくるメッセージは、いつも +adm/misc に入れることにした +い場合なども、明示的な規則を書かずに済ませられます。 + +From: とフォルダの情報は、"~/Mail/.mew-refile-from-alist" に保存されてい +ます。この情報を過去何通のメッセージに関して保存するかは、 +*Note by-thread:: と同様に `mew-lisp-max-length' で決定します。 + +この機能を提供する関数は `mew-refile-guess-by-from' です。 + +`mew-refile-guess-from-me-is-special' が `t' の場合、 +`mew-refile-guess-by-from' は `mew-refile-guess-by-from-folder'(*Note +by-from-folder::)と同様な動きをします。 + + + +File: mew.ja.info, Node: by-newsgroups, Next: by-default, Prev: by-from, Up: Refile + +Newsgroups: から推測 +==================== + +ニュースをメールとして受信して Mew で読んでいる人のために、Newsgroups: +からフォルダを推測する機能を用意しました。関数名は +`mew-refile-guess-by-newsgroups' です。 + + + +File: mew.ja.info, Node: by-default, Next: guess-rule, Prev: by-newsgroups, Up: Refile + +デフォルトの規則 +================ + +デフォルトの規則は、From: からユーザ名を切り出して、`+from/user' +を選ぶようになっています。ただし、 +`mew-refile-guess-strip-domainpart' が `nil' ならアドレスを切 +り出すので、`+from/user@domain' が選択されます。 +`mew-refile-guess-strip-domainpart' の初期値は `t' です。 + +関数名は、`mew-refile-guess-by-default' です。 + + + +File: mew.ja.info, Node: guess-rule, Next: auto-refile, Prev: by-default, Up: Refile + +規則の制御 +========== + +Mew では、フォルダ推測の規則を 2 つの変数、`mew-refile-guess-control' +と `mew-refile-ctrl-multi' で制御します。`mew-refile-guess-control' は、 +呼び出す関数を順に定義します。候補を複数にしたい場合は +`mew-refile-ctrl-multi' を `t' に、単数にしたい場合は `nil' に設定しま +す。 + +標準では、`mew-refile-guess-control' は以下のように宣言されています(宣 +言なので `defvar' が使われています)。 + + (defvar mew-refile-guess-control + '(mew-refile-guess-by-alist + mew-refile-ctrl-throw + mew-refile-guess-by-newsgroups + mew-refile-guess-by-folder + mew-refile-ctrl-throw + mew-refile-ctrl-auto-boundary + mew-refile-guess-by-thread + mew-refile-ctrl-throw + mew-refile-guess-by-from-folder + mew-refile-ctrl-throw + mew-refile-guess-by-from + mew-refile-ctrl-throw + mew-refile-guess-by-default)) + +Mew は `mew-refile-guess-control' に並べられた関数を順番にすべて実行し +ます。各々の関数が複数の候補を推測することがあります。 + +`mew-refile-guess-control' の動作例として以下を考えてみましょう。 + +`mew-refile-guess-by-alist' + が +aaa、+bbb を推測。 +`mew-refile-guess-by-folder' + が +ccc、+ddd を推測。 +`mew-refile-guess-by-default' + が +eee を推測。 + ++aaa 〜 +eee すべてをユーザに提示して欲しい場合は、 +`mew-refile-ctrl-multi' を `t' に、+aaa だけを提示して欲しい場合は、 +`nil' に設定します。 + +また、+aaa 〜 +ddd は提示して欲しいけれどもそれ以降はいらない、つまり、 ++eee を提示するのは先に実行された関数群が何も推測できなかったときだけ +にしたい場合は、`mew-refile-ctrl-multi' を `t' にして、 +`mew-refile-guess-by-folder' と `mew-refile-guess-by-default' の間に +`mew-refile-ctrl-throw' を入れて下さい。 + +`C-uo' は、この推測の流れを Message バッファに表示します。 + + + +File: mew.ja.info, Node: auto-refile, Next: copy-msg, Prev: guess-rule, Up: Refile + +自動で整理整頓 +============== + +毎日メッセージをたくさんもらう人は、まだ整頓していないメッセージを ++inbox (あるいは %inbox) フォルダに大量に溜めてしまうことがあります。 +そんなときは、「メッセージ達よ、とにかくこのフォルダからどこかに行って +しまえ」と叫びたくなることがあるでしょう。Mew は、そんなわがままな人を +満足させるための自動整理整頓関数を提供しています。:) `M-o' がその呪文 +です。 + +この関数を実行すると、現在のフォルダ内の特定のメッセージに対して、自動的 +に `o' マークを付けてくれます。特定のメッセージとは、 +`mew-refile-auto-refile-skip-any-mark' が `nil' なら、`o' +や `D' マークが付いていないメッセージです。 +`mew-refile-auto-refile-skip-any-mark' が `t' なら、なにもマー +クが付いてない(既読)メッセージです。 +`mew-refile-auto-refile-skip-any-mark' の初期値は `nil' です。 + +`C-uM-o' は、`mew-refile-auto-refile-skip-any-mark' の値とは関係なく +`*' マークの付いたメッセージを対象にします。 + +整頓先の決定には、先に説明した推測関数群が働くようになっています。この +関数は、`o' を付けるだけですので、`x' を押さない限り実際にメッセージが +どこかに行ってしまうことはありません。 + +Mew の整頓先推測はあまりにも賢すぎるので、この機能には仇となってしまい +ます。というのは、Mew が推測機能をフルに使って勝手に整頓してしまうと、 +大抵のユーザはどこにメッセージが整頓されたか分からなくなってしまうから +です。:) そのために、Mew が使う推測関数を制限する機能が提供されていま +す。前に出てきた宣言をもう一度思い出して下さい。 + + (defvar mew-refile-guess-control + '(mew-refile-guess-by-alist + mew-refile-ctrl-throw + mew-refile-guess-by-newsgroups + mew-refile-guess-by-folder + mew-refile-ctrl-throw + mew-refile-ctrl-auto-boundary + mew-refile-guess-by-thread + mew-refile-ctrl-throw + mew-refile-guess-by-from-folder + mew-refile-ctrl-throw + mew-refile-guess-by-from + mew-refile-ctrl-throw + mew-refile-guess-by-default)) + +`mew-refile-guess-control' の中に `mew-refile-ctrl-auto-boundary' とい +う関数があります。これがその仕掛です。自動整理整頓のときに限り、Mew は +この関数より下に記述してある推測を無視します。 +`mew-refile-ctrl-auto-boundary' より上に記述している関数が何も推測でき +なかった場合は、そのメッセージには `o' が付きません。破滅が訪れる前に +`mew-refile-ctrl-auto-boundary' の御札を貼って下さい。 + + + + +File: mew.ja.info, Node: copy-msg, Next: Virtual, Prev: auto-refile, Up: Refile + +世界を越えたメッセージのコピー +============================== + +これまで説明した整頓とは、同じ世界の中でメッセージを移動させることでし +た。これに対し、ある世界から他の世界へメッセージを移動させたいこともあ +るでしょう。これは、ある世界から他の世界へメッセージへコピーし、その後 +元のメッセージを削除することで実現できます。ここでは、ある世界から他の +世界へメッセージへコピーする方法について説明します。 + +あるフォルダのメッセージをローカルフォルダへコピーしたくなることがあり +ます。この場合 `lc' を利用して下さい。`lc' は、リモート・フォルダで実 +行された場合、キャッシュされたメッセージから、そのリモート・フォルダに +特有の情報をヘッダから取り除き、ローカル・フォルダへコピーします。 +(`lc' は、ローカルフォルダでも実行できます。この場合、同じ世界内でのコ +ピーになります。) + +あるフォルダのメッセージを IMAP のフォルダ(サーバ側)へコピーするには、 +`li' を利用します。 + +`*' の付いた複数のメッセージをローカル・フォルダへコピーするには`mlc' +を使います。また、`*' の付いた複数のメッセージを IMAPフォルダへコピー +するには `mli' を利用して下さい。 + +ある世界から他の世界へメッセージへコピーするコマンドを以下にまとめます。 + +`lc' + あるフォルダのメッセージをローカルフォルダへコピーする。 +`mlc' + `*' の付いた複数のメッセージをローカル・フォルダへコピーする。 +`li' + あるフォルダのメッセージを IMAP のフォルダへコピーする。 +`mli' + `*' の付いた複数のメッセージを IMAP フォルダへコピーする。 + + + + +File: mew.ja.info, Node: Virtual, Next: selection, Prev: copy-msg, Up: Top + +仮想フォルダ +************ + +Virtual モードは、必要なメッセージを表示するための仮想的なフォルダであ +り、「セレクション」と「スレッド」の2種類に分類できます。 + +`セレクション' + いろいろなフォルダから必要なメッセージだけを集めた仮想フォルダで + す。フォルダ名の左側に "*" が付きます。 +`スレッド' + フォルダ(Summary)やセレクション(Virtual)を基に、対話関係を行頭揃 + えによって可視化した仮想フォルダです。フォルダ名の両側に "*" が付 + きます。 + +Summary モードで利用できるコマンドの多くが、Virtual モードで利用できま +す。 + +Virtual モードでメッセージにマークを付けると、対応する Summary モード +があれば、そちらのメッセージにもマークが付きます。逆に、Summary モード +であるメッセージにマークを付けても、Virtual モードの対応するメッセージ +にはマークは付きません。 + +Virtual モードからマークを処理することはできません。`x' を押しマークを +処理しようとすると、対応する Summary モードがあれば、そちらに移動し、 +もう一度 `x' を押すよう促されます。 + +仮想フォルダはまさしく仮想であり、ファイルシステムなどには存在しないこ +とに注意して下さい。Emacs を終了すると、仮想フォルダはなくなります。 +Virtual モードを消去する方法については、*Note Quit:: を参照して下さい。 + +* Menu: + +* selection:: セレクション +* sorting:: ソート +* dialog:: 対話 +* search:: 検索 +* condition:: 検索条件の入力方法 +* dbsearch:: 検索エンジン +* keyword:: キーワードの強調 +* thread:: スレッド +* thread-op:: スレッドの操作 + + + +File: mew.ja.info, Node: selection, Next: sorting, Prev: Virtual, Up: Virtual + +セレクション +============ + +セレクションは、いろいろなフォルダから必要なメッセージだけを集めた仮想 +フォルダです。セレクションの作り方には、以下の 5 つがあります。 + +`m/' + あるフォルダで、"*" マークが付いているメッセージのみを表示する。 +`S' + あるフォルダで、メッセージをソートして表示する。(元のフォルダには、 + 何の影響もない。) *Note sorting:: を参照のこと。 +`V' + 現在のメッセージと対話関係にあるメッセージを表示する。*Note + dialog:: を参照のこと。 +`/' + あるフォルダから、検索条件に合致するメッセージを表示する。*Note + search:: を参照のこと。 +`k/' + すべてのフォルダから、検索条件に合致するメッセージを表示する。 + *Note dbsearch:: を参照のこと。 + + + + +File: mew.ja.info, Node: sorting, Next: dialog, Prev: selection, Up: Virtual + +ソート +====== + +メッセージをソートしセレクションを作成するには `S' を使います。このと +き次のようにどのフィールドでソートするか訊いてくるので、ソートしたい +フィールド名を入力して下さい。 + + Sort by? (default date): + +指定したフィールドに書かれている文字列は単純に文字列比較でソートするべ +きではありません。たとえば、Subject: はテキストと考えてよいのですが、 +Date: は日付、X-Mail-Count: は数字と考えてソートすべきです。このように +文字列をどう取り扱うかをモードといいます。ソートによく指定されるフィー +ルド名に対するモードは `mew-sort-key-alist' で設定されています。 + +ソートのモードを明示的に指定、変更したい場合には `:' で区切って指定し +ます。たとえば X-Mail-Count: フィールドの内容を(テキストとしてではなく) +数値とみなしてソートしたい場合には、次のように入力します。 + + x-mail-count:num + +フィールド名やモードは `TAB' で補完できます。 + +モードには、以下の 4 つがあります。 + +`text' + 先頭の "Re: " や "Fw: " を取り除いた文字列。 +`ml' + text と同じであるが、さらにメーリングリスト特有の文字列も取り除く。 +`num' + 数値。 +`date' + 日付。 + +"Sort by?" と訊かれる際のフィールド名の初期値は、 +`mew-sort-default-key' で設定できます。以下は、初期値である"date" +を "x-ml-count" に変更する例です。 + + (setq mew-sort-default-key "x-ml-count") + +`mew-sort-default-key-alist' で、フォルダごとにフィールド名の初期 +値を設定することもできます。ここで指定しなかったフォルダでは、フィール +ド名の初期値として `mew-sort-default-key' の値が使われます。以下は、 ++inbox フォルダでの初期値を "subject" に、+mew-dist フォルダでの初期値 +を "x-mail-count" に変更する例です。 + + (setq mew-sort-default-key-alist + '(("+inbox" "subject") + ("+mew-dist" "x-mail-count"))) + +なお、ローカル・フォルダでメッセージを本当にソートするためには`M-s' を +使って下さい。このコマンドは、リモート・フォルダでは利用できません。 + + + +File: mew.ja.info, Node: dialog, Next: search, Prev: sorting, Up: Virtual + +対話 +==== + +Mew では、あるメッセージに関係するメッセージをさまざまなフォルダから集 +めて仮想フォルダに一覧表示できます。これを「対話」と呼びましょう。後ほ +ど説明するスレッド(*Note thread::)とは、以下の点で異なります。 + + + - スレッドは、1つのフォルダ/仮想フォルダに対してのみ作成できる。対 + 話は、関連するメッセージが複数のフォルダに散らばっていてもよい。 + + - スレッドは、行頭揃えによって木構造を可視化する。対話は、日付順に + 一覧表示する。 + +対話の機能を使うには、まず `kI' を実行し、データベースを作る必要が +あります。新しく届くメッセージはデータベースに入らないので、`kI' +は定期的に実行して下さい。`kI' は、データベースを差分更新します。 +この方式は早いのですが、ゴミが残ることは避けられないので、ときどき +`C-ukI' を実行し、データベースを一から作り直して下さい。 + +対話を作成するには、注目しているメッセージの上で `V' を押します。 +このコマンドは、自分の子孫と、自分の先祖、そして自分だけを表示します。 +自分の兄弟などは表示しません。一族全体を表示したいなら、一旦作った仮想 +フォルダの一番上にあるメッセージ、すなわち一族の祖の上で、もう一度 +`V' を実行して下さい。 + + + +File: mew.ja.info, Node: search, Next: condition, Prev: dialog, Up: Virtual + +検索 +==== + +Mew では、以下のようなメッセージの検索機能を提供しています。 + +`?' + 現在のフォルダで、条件に合致したメッセージに `*' マークを付ける。 + 入力された条件によって、`mewl' か `grep' のどちらかが呼ばれる。 +`C-u?' + リージョンを指定した `?'。 +`/' + 現在のフォルダで、条件に合致したメッセージからセレクションを作る。 + 入力された条件によって、`mewl' か `grep' のどちらかが呼ばれる。 +`C-u/' + リージョンを指定した `/'。 + +また、Spotlight や Windows Desktop Search などの検索エンジンを利用した +検索も可能です。これには、以下のコマンドがあります。 + +`k?' + 現在のフォルダで、条件に合致したメッセージに `*' マークを付ける。 +`k/' + 全フォルダに対し、条件に合致したメッセージからセレクションを作る。 +`C-uk/' + 指定されたフォルダに対し、条件に合致したメッセージからセレクショ + ンを作る。フォルダを複数指定するには "," で区切る。ワイルドカード + として、"*"を利用できる。 + + + +File: mew.ja.info, Node: condition, Next: dbsearch, Prev: search, Up: Virtual + +検索条件の入力方法 +================== + +`?' や `/' を実行すると、Mew はユーザに対し以下のように検索のパターン +を訊きます。 + + mewl/grep pick pattern: + +単純に「文字列」を 1 つ入力すると、Mew は `grep' を呼び出します。また、 +「条件式」を入力すると、`mewl' を呼び出します。 + +条件式の書式を以下に示します。(結合力の強い順に並んでいます。) + +`field=string' + フィールド field に文字列 string が含まれているときマッチ(大文字 + 小文字を区別しない)。field に "head" を指定した場合は、ヘッダ全体 + を意味する。 +`field==string' + フィールド field に文字列 string が含まれているときマッチ(大文字 + 小文字を区別する)。field に "head" を指定した場合は、ヘッダ全体を + 意味する。 +`field!=string' + フィールド field に文字列 string が含まれていないときマッチ(大文 + 字小文字を区別しない)。field に "head" を指定した場合は、ヘッダ全 + 体を意味する。 +`field!==string' + フィールド field に文字列 string が含まれていないときマッチ(大文 + 字小文字を区別する)。field に "head" を指定した場合は、ヘッダ全体 + を意味する。 +`( )' + の内容を先に評価。 +`! ' + でないときマッチ。 +` & ' + かつ のときマッチ。省略可能。 +` | ' + または のときマッチ。 + +以下に例を示します。 + +(a) From: に kazu が含まれるメッセージ + + from=kazu + +(b) To: が mew、または、Cc: が mew であるメッセージ + + to=mew | cc=mew + +(c) To: が mew、または、Cc: が mew で、かつ、from が kazu であるメッセー +ジ + + (to=mew | cc=mew) & from=kazu + +`?' や `/' で、パターンに入力の際に単純に `RET' を押すと、以下のように +利用するコマンドまで入力できるようになります。 + + Cmd opts pattern: grep -l -e + +`k?' や `k/' で検索エンジンを利用する場合は、上記のパターン(文字列や条 +件式)が自動的に検索エンジンの書式に変換されます。 + +たとえば、kazu から来たメールで、「wine」を含み、かつ「bordeaux」を含 +まないという条件式は以下のように書きます。 + + from=kazu wine ! bordeaux + +なお、`mew-pick-pattern-list' にパターンのリストを定義しておくと、 +`C-cTAB' で各要素を循環的に補完できます。この場合、リストの先頭がデフォ +ルトとして表示されます。 + +日本語の全文検索をしたい場合は、("grep" の代わりに) "mg" をインストー +ルし、以下のように設定して下さい。 + + (setq mew-prog-grep "mg") + (setq mew-prog-grep-opts '("-j" "jis" "-l" "-e" "-x" "&mime")) + + + +File: mew.ja.info, Node: dbsearch, Next: keyword, Prev: condition, Up: Virtual + +検索エンジン +============ + +検索エンジンを操作するために以下のコマンドが用意されています。 + +`km' + そのフォルダのインデックスを作る。 +`kM' + 全体のフォルダのインデックスを作る。あるいは、作るために初期化す + る。 +`kc' + 検索エンジンを切り替える。 + +以下に、それぞれの検索エンジンの説明を示します。 + +`Hyper Estraier' + 定期的に `kM' を実行する必要があります。コマンドラインで、 + "mewest" を実行しても構いません。あるフォルダのインデックスを急い + で更新したいなら `km' でもよいでしょう。`k?' と`k/' の両方が利用 + できます。`C-uk/'でフォルダを指定すると、サブディレクトリも検索に + なります。 +`Spotlight' + 一度だけ `kM' を実行する必要があります。`km' は必要ありません。 + `k?' と `k/' の両方が利用できます。 +`Windows Desktop Search' + 一度だけ `kM' を実行する必要があります。`km' は必要ありません。 +`Google Desktop' + 一度だけ `kM' を実行する必要があります。`km' は必要ありません。 + `k/' のみが利用できます。 + +検索エンジンの初期値は、最初に見つかった利用できるものに自動的に設定さ +れます。明示的に指定したい場合は、 +`mew-search-method'に'est、'spotlight、'wds, 'google のどれかを指定し +て下さい。以下は、Hyper Estraier に設定する例です。 + + (setq mew-search-method 'est) + + + +File: mew.ja.info, Node: keyword, Next: thread, Prev: dbsearch, Up: Virtual + +キーワードの強調 +================ + +検索に使ったキーワードは、バッファに保存されています。メッセージを表示 +し、さらにキーワードをハイライトすることができます。この機能を提供する +コマンドは以下の通りです。 + +`M-n' + 下方向のメッセージへ移動しキーワードをハイライトして表示。Summary + モードでは `*' マークのついたメッセージが、Virtual モードではすべ + てのメッセージが対象となる。このコマンドを繰り返し利用すると、キー + ワードの付近が次々と表示されていく。キーワードが設定されていない + なら、ユーザにキーワードを訊く。 +`C-uM-n' + キーワードを明示的に設定できること以外は、`M-n' に同じ。 +`M-p' + `M-n' を逆方向にしたコマンド。 +`C-uM-p' + `C-uM-n' を逆方向にしたコマンド。 + + + +File: mew.ja.info, Node: thread, Next: thread-op, Prev: keyword, Up: Virtual + +スレッド +======== + +メッセージをやりとりしていると、対話の流れは木構造になります。これを行 +頭揃えにより可視化したものをスレッドと呼びます。以下にスレッドの例を示 +します。 + + 03/12 Hidenori Ohta 今週末 |日曜にストーンマジック + 03/13 かずくん ┣Re: 今週末 |雨なので、中にしますか + 03/15 Hidenori Ohta ┃┗Re: 今週末 |それでは、12:00 に集合 + 03/14 おだちゃん ┗Re: 今週末 |いいねぇ。次はあれを落 + +スレッドは仮想フォルダとして実現されています。たとえば、+inbox に対し +スレッドを作ると、*+inbox* というバッファが用意されます。 + +スレッドを作るために、以下のコマンドが用意されています。 + +`tt' + Summary モード、あるは、セレクションからスレッドを作る。そして、 + カーソルを現在のメッセージに移動する。もし、対応するスレッドがす + でに存在しているなら、スレッドに表示を切り替える。スレッドで使用 + された際は、元のフォルダへ移り、カーソルを現在のメッセージへ移動 + する。 +`C-utt' + リージョンに対し、スレッドを作る。 +`mt' + `*' マークの付いているメッセージに対し、スレッドを作る。 +`tr' + 正規表現に合致したメッセージに対し、スレッドを作る。 + + + +File: mew.ja.info, Node: thread-op, Next: Quit, Prev: thread, Up: Virtual + +スレッドの操作 +============== + +スレッドに特化した移動コマンドを以下に示します。 + +`tp' + 現在のスレッドの頭に移動する。もし、あるスレッドの頭にカーソルが + ある場合は、前のスレッドの頭に移動する。 +`tn' + 次のスレッドの頭に移動する。 +`^' + 親のメッセージに移動する。(スレッドでなくても利用可能) +`&' + 長男のメッセージに移動する。(スレッドでなくても利用可能) +`(' + 兄のメッセージに移動する。 +`)' + 弟のメッセージに移動する。 + + +スレッドにマークを付けるコマンドを以下に示します。 + +`t*' + 現在のメッセージを頭とする部分木に属するメッセージすべてに `*' マー + クを付ける。詳しくは *Note target mark:: を参照のこと。 +`t$' + 現在のメッセージを頭とする部分木に属するメッセージすべてに `$' マー + クを付ける。詳しくは *Note escape mark:: を参照のこと。 +`td' + 現在のメッセージを頭とする部分木に属するメッセージすべてに `D' マー + クを付ける。詳しくは *Note delete mark:: を参照のこと。 +`tM-d' + 現在のメッセージを頭とする部分木に属するメッセージすべてに `X' マー + クを付ける。詳しくは *Note delete mark:: を参照のこと。 +`to' + 現在のメッセージを頭とする部分木に属するメッセージすべてに `o' マー + クを付ける。詳しくは *Note refile mark:: を参照のこと。 + +スレッドからマークを消すコマンドは、`tu' です。 + + +以下に、スレッドを加工するコマンドを示します。 + +`tSPC' + 子供以下を隠して親だけにする。子供以下が隠れている親メッセージに + は、"+" が付く。また、子供以下が隠れている親メッセージでこのコマ + ンドを実行すると、子供以下が現れる。 +`ta' + すべてのスレッドに対し、子供の表示を反転させる。 +`tg' + あるスレッドをあるメッセージに接ぎ木する。接ぎ木するスレッドは、 + `C-SPC' で指定する。目的のスレッドの一番上のメッセージで、`C-SPC' + を押すと、そのスレッドが選択されたことになる。そして目的のメッセー + ジへ移動し、`tg' を押すと、スレッドがこのメッセージの子供として接 + ぎ木される。 + + +なお、`mew-use-thread-separator' を `t' にすると、スレッド間に境界文字 +列として `mew-thread-separator' (初期値は "--") が挿入されます。 + + + + +File: mew.ja.info, Node: Quit, Next: Customize, Prev: thread-op, Up: Top + +一休み +****** + +Mew を終了させたり、一時中断させたり、そのモード(正確にはバッファ)を消 +去する方法を以下に示します。 + + + +`q' + Mew を一時中断し、他のバッファに切り替える。Mew 用のバッファはす + べて残っているので、バッファ操作で選べば再開できる。 +`Q' + Mew を終了。Mew が使ったすべてのバッファを消去する。 +`C-cC-q' + そのモード(正確にはバッファ)を消去する。 + + + +`C-cC-q' + その草稿を消去する。 + + + +`C-cC-q' + そのバッファを消去する。 + + + + +File: mew.ja.info, Node: Customize, Next: summary-mode, Prev: Quit, Up: Top + +カスタマイズ +************ + +ここでは、Mew のデフォルトの動作を変更し、自分好みの Mew にする方法を +説明します。主に "~/.mew.el" で設定して下さい。 + +* Menu: + +* summary-mode:: Summary mode +* message-mode:: Message mode +* draft-mode:: Draft mode +* charset:: 文字コード +* highlight:: 色付け +* hooks:: フック +* pop:: POP +* imap:: IMAP +* nntp:: NNTP +* smtp:: SMTP +* config:: 送受信の動作変化 +* config2:: 設定の書式 +* custom-misc:: その他 + + + +File: mew.ja.info, Node: summary-mode, Next: message-mode, Prev: Customize, Up: Customize + +Summary mode +============ + +Summary モードの書式は、`mew-summary-form' で指定できます。以下に初期 +値を示します。 + + (setq mew-summary-form '(type (5 date) " " (14 from) " " t (30 subj) "|" (0 body))) + +このように、`mew-summary-form' は、リスト、シンボル、文字列のリストで +す。 + + 1. 文字列はそのまま出力される + 2. リストは、整数とシンボルから構成される。シンボルは、呼び出す関数 + を意味する。関数名は、"mew-summary-form-" とシンボル名を連結する + ことで作られる。(例: 'date というシンボルは、 + `mew-summary-form-date' という関数名になる) あらかじめ定義されて + いるシンボルに + は、'type、'time、'date、'year、'size、'from、'subj、'body がある。 + 詳細は、`mew-summary-form-' という名を持つ関数の説明を参 + 照のこと。整数は、関数が返す文字列が埋めるフィールドの幅を指定す + る。正の数は、左詰めを意味する。負の数は、右詰めを意味する。もし、 + 負の数を指定する場合、対応する関数は ASCII 文字列を返す必要がある。 + 0 は、行の残りを意味し、左詰めとなる。 + 3. `t' 以外のシンボルは、(1 シンボル) に等しい。 + 4. `mew-summary-form' は、利用される際に先頭に (mark) が付け加えられる。 + 5. `t' は、スレッドの際に段付けする位置を意味する。 + +例を以下に示します。 + + (setq mew-summary-form + '(type (5 date) " " (-4 size) " " (14 from) " " t (30 subj) "|" (0 body))) + +`mew-summary-form-from-me-prefix' は、自分から送信されたメッセージの宛 +先の先頭に加えられる文字列です。初期値は "To:" です。 + +`mew-summary-form-extract-rule' は、From: フィールドからどの部分を切り +出すか指定するためのリストです。要素 +は、'name、'comment、'address、'nickname、あるいは正規表現である必要が +あります。初期値は '(nickname) です。 + + +次の例を考えて下さい。 + + A: Kazu Yamamoto + B: kazu@example.org (Kazu Yamamoto) + C: Kazuhiko Yamamoto (Kazu) + +それぞの要素は、以下のような意味を持ちます。 + + 1. 'name:: 名前の部分 + A. Kazu Yamamoto + B. (No match) + C. Kazuhiko Yamamoto (Kazu) + 2. 'comment:: コメントの部分 + A: (No match) + B: Kazu Yamamoto + C: (Kazu) + 3. 'address:: アドレスの部分 + A: kazu@example.org + B: kazu@example.org + C: kazu@example.org + 4. 'nickname:: `mew-addrbook-for-summary' の値に応じたアドレス帳の個 + 人情報のある要素。`mew-addrbook-for-summary' の初期値は + `'nickname' なので、通常はニックネームに変換される。何が指定でき + るかは、*Note draft-mode:: を参照のこと。 + 5. (regex):: 最初に合致した文字列 + +ある要素が合致しない場合、次の要素が評価されます。どの要素も From: フィー +ルドに合致しない場合か、この値が `nil' の場合、From: フィールド全体が +利用されます。 + + +`mew-summary-form-mark-delete' が `t' の場合、重複しているメッセージに +自動的に `D' マークが付きます。初期値は `nil' です。 + + +`mew-summary-form-mark-spam' が `t' の場合、本文の一部に対する MD5 チェッ +クサムが一致しているメッセージに自動的に `D' マークが付きます。初期値 +は `nil' です。 + +`mew-summary-form-mark-review' が `t' の場合、自分宛てのメッセージに自 +動的に `*' マークが付きます。初期値は `nil' です。 + + +いつも Emacs のフレーム全体で Mew を使いたい人は、以下の設定をして下さ +い。 + + (setq mew-use-full-window t) + + +Summary モードの `SPC' は、`mew-summary-show-direction' によって、次の +メッセージの表示の仕方が変わります。また同様に、強いマークを付けた後カー +ソルが動く方向は `mew-summary-mark-direction' により指定できます。以下 +の値を設定できます。 + +`up' + 上のメッセージを表示する。 +`down' + 下のメッセージを表示する。 +`next' + 読み進めている方向の次のメッセージを表示する。 +`stop' + 次は表示しない。 + +両方とも初期値は `next' です。いつもメッセージを下から読む人は、以下の +ようにすればよいでしょう。 + + (setq mew-summary-show-direction 'up) + + + +File: mew.ja.info, Node: message-mode, Next: draft-mode, Prev: summary-mode, Up: Customize + +Message mode +============ + +Emacs がサポートしてないデータ型のファイルは、Message バッファに直接表 +示できません。そのデータをテキストに整形する外部コマンドをインストール +すれば、Message バッファに表示可能になります。 + +"w3m" と "emacs-w3m" をインストールすると、Text/Html を Message バッ +ファに表示できるようになります。(以下で説明する "wvHtml"、"xlhtml"、 +"ppthtml" は、単なる "w3m" ではなく、国際化された "w3m-m17n" が必要で +す。) 両者をインストールしたら、"~/.mew.el" に以下の設定を加えて下さい。 + + (condition-case nil + (require 'mew-w3m) + (file-error nil)) + +これで、あたかも Text/Plain であるかのように、Text/Html を Message バッ +ファに表示できるようになります。この際も、以下で説明する `C-cC-e'の操 +作は有効です。 + +"wvHtml"、"xlhtml"、"ppthtml" というコマンドをインストールすれば、それ +ぞれ WORD、Excel、PowerPoint ファイルのテキスト部分を、Message バッファ +に表示可能です。これらのコマンドは、HTML を利用するので、上記の +Text/Html の設定を完了させて下さい。これで、たとえば WORD ファイルをあ +たかもテキストのように、Message バッファに表示可能になります。 + +外部のプログラムの整形結果を Message バッファに表示する代わりに、外部の +プログラム自身にそのデータを表示させることもできます。これには +`C-cC-e' を使います。 + +Message バッファに画像を表示することもできます。また `C-cC-e' を使い、 +外部のプログラムに表示させることも可能です。 + +HTML は `C-cC-e' を使って外部のブラウザに表示できます。Windows やMac +ではデフォルトのブラウザが利用されます。Unix では、以下のように +"mozilla" が初期値となっています。 + + (defvar mew-prog-text/html-ext '("mozilla" ("-remote" "openFile(%s)") t)) + +たとえば、これを "firefox" に変更するには以下のようにします。 + + (setq mew-prog-text/html-ext + '("firefox" ("-a" "firefox" "-remote" "openFile(%s)") t)) + +Office 関連のファイルも、`C-cC-e' を使えば、それぞれのアプリケーション +で表示可能です。Windows や Mac では、文字通り Office のアプリケーショ +ンが起動されます。Unix では、以下のように "ooffice" が初期値となってい +ます。 + + (defvar mew-prog-msword-ext "ooffice") + (defvar mew-prog-msexcel-ext "ooffice") + (defvar mew-prog-mspowerpoint-ext "ooffice") + +これを "soffice" に変更するには以下のようにします。 + + (setq mew-prog-msword-ext "soffice") + (setq mew-prog-msexcel-ext "soffice") + (setq mew-prog-mspowerpoint-ext "soffice") + +また Office 関連のアプリケーションに対し、`SPC' などでは内容を表示せず、 +`C-cC-e' では "wvHtml" などを使って Message バッファに表示するには、以 +下のように設定します。 + + (setq mew-prog-msword '(nil mew-mime-application/msword)) + (setq mew-prog-msexcel '(nil mew-mime-application/msexcel)) + (setq mew-prog-mspowerpoint '(nil mew-mime-application/mspowerpoint)) + +あらかじめ定められているコマンドではなく、任意の外部コマンドを呼び出し +たい場合は、`C-uC-cC-e' と入力して下さい。 + +最近、Multipart/Alternative の中に Text/Plain と Text/Html の両方が入っ +ており、どちらかを選ぶようになっているメッセージを多く見掛けます。Mew +は、標準では Text/Plain の方を優先して表示します。"emacs-w3m" をインス +トールすれば、Text/Html の方を優先したくなるかもしれません。その場合、 +以下の設定を "~/.mew.el" に加えて下さい。(ここで *Note multipart:: を +読み、`:' の使い方も思い出しておきましょう。) + + (setq mew-mime-multipart-alternative-list + '("Text/Html" "Text/Plain" ".*")) + +ZIP で暗号化された添付ファイルは、`zz' で復号化し表示できます。 + + + diff --git a/elpa/mew-20150813.2354/mew.ja.info-3 b/elpa/mew-20150813.2354/mew.ja.info-3 new file mode 100644 index 00000000..a4c6c36b --- /dev/null +++ b/elpa/mew-20150813.2354/mew.ja.info-3 @@ -0,0 +1,1886 @@ +Info file: mew.ja.info, -*-Text-*- +produced by `texinfo-format-buffer' +from file `mew.texi' +using `texinfmt.el' version 2.42 of 7 Jul 2006. + +INFO-DIR-SECTION Message User Agent +START-INFO-DIR-ENTRY +* Mew-J: (mew.ja.info). Messaging in the Emacs World. +END-INFO-DIR-ENTRY + + + + + + +File: mew.ja.info, Node: draft-mode, Next: charset, Prev: message-mode, Up: Customize + +Draft mode +========== + +自分へ Cc: したい人は `mew-cc' を設定して下さい。返答の際には、対象の +メッセージから、別途 Cc: が用意される場合があります。複数の Cc: がある +場合、送信時に 1 つにまとめられます。 + +バックアップのため、自分が送るメッセージを受け取りたいと考え、しかもヘッ +ダに自分のアドレスを残したくないなら、Dcc: を使って下さい。 +`mew-dcc' に自分のアドレスを設定しましょう。 + +いつも入れて欲しいヘッダは、`mew-header-alist' に連想リスト形式で定義 +して下さい。以下に例を示します。 + + (setq mew-header-alist + '(("X-fingerprint:" "6B 63 38 88 67 5E 96 8E CE A4 62 73 3F 11 64 94") + ("X-URL:" "http://www.example.org/~kazu/"))) + +引用ラベルは、引用するフィールドを `mew-cite-fields'、ラベルの書式 +を `mew-cite-format' に定義します。引用記号は +`mew-cite-prefix' に指定します。初期値は、以下のようになっています。 + + (defvar mew-cite-fields '("From:" "Subject:" "Date:")) + (defvar mew-cite-format "From: %s\nSubject: %s\nDate: %s\n\n") + (defvar mew-cite-prefix "> ") + +引用ラベルに Message-ID: を加えるには以下のようにします。 + + (setq mew-cite-fields '("From:" "Subject:" "Date:" "Message-ID:")) + (setq mew-cite-format "From: %s\nSubject: %s\nDate: %s\nMessage-ID: %s\n\n") + +引用記号にアドレスのユーザ部分が付くようにするには以下のようにします。 + + (setq mew-cite-prefix-function (function mew-cite-prefix-username)) + +これで引用記号は以下のようになります。 + + From: SUMIKAWA Munechika + Subject: Wine + Date: Wed, 23 Jul 1997 11:40:50 +0900 + + sumikawa> おはようからおやすみまでニートでおなじみの角川です。 + sumikawa> + sumikawa> さて、とろけるワイン作戦ですが、定石通り '89 のボルドーの + sumikawa> カベルネ・ソービニョンを狙いたいと思います。 + +引用ラベルの From: の部分と、引用記号は、アドレス帳の個人情報の要素に変 +換できます。それぞれ、`mew-addrbook-for-cite-label'、 +`mew-addrbook-for-cite-prefix' で指定できます。初期値はそれぞれ +`nil' と `'username' です。以下のような値が設定できます。 + +'shortname + 短縮名 +'address + アドレス +'username + アドレスのユーザ部分 +'nickname + ニックネーム +'name + 正式な氏名 + +例として以下のような設定を考えてみましょう。 + + (setq mew-addrbook-for-cite-label 'nickname) + (setq mew-addrbook-for-cite-prefix 'nickname) + +最初の設定でラベルの中のアドレスがニックネームに変わります。また、次の +設定で引用記号もニックネームに置き換わります。 + + From: すみっち + Subject: Wine + Date: Wed, 23 Jul 1997 11:40:50 +0900 + + すみっち> おはようからおやすみまでニートでおなじみの角川です。 + すみっち> + すみっち> さて、とろけるワイン作戦ですが、定石通り '89 のボルドーの + すみっち> カベルネ・ソービニョンを狙いたいと思います。 + + + +File: mew.ja.info, Node: charset, Next: highlight, Prev: draft-mode, Up: Customize + +文字コード +========== + +*Note charset-guess:: で説明したように、Mew ではメッセージを作成する際 +に適切な文字コードを自動的に選択します。 + +もし複数の言語の文字が混在しており、国際化された文字コードを選択する必 +要がある場合は、`mew-charset-m17n' の値を利用します。初期値は、"utf-8" +(Unicode と理解してよい)です。"iso-2022-jp-2" にしたい人は、以下のよう +に設定するとよいでしょう。 + + (setq mew-charset-m17n "iso-2022-jp-2") + +メッセージを作成した際に、推測された文字コードを確認したい場合は、 +`mew-ask-charset' を設定して下さい。 + +`nil' + どのような文字コードが利用されても確認なし +`文字コードのリスト' + このリストに存在しない文字コードが利用された場合に確認 +`t' + `mew-charset-m17n' が利用された場合に確認 + +たとえば、US-ASCII と ISO-2022-JP 以外の文字コードが選ばれた場合確認し +たいのであれば、以下のように設定して下さい。 + + (setq mew-ask-charset '("us-ascii" "iso-2022-jp")) + +こう設定しているとき、たとえば "utf-8" が選択されると、以下のように訊 +かれます。 + + utf-8 is used. OK? (y or n) + +`y' を押すと、メッセージが送信されます(あるいは、キューに溜ります)。 +`n' を押すと、草稿が元の状態に戻ります。 + +ヨーロッパでは、Latin 1 (ISO-8859-1) の代りに、ユーロ記号を含む Latin +9 (ISO-8859-15、通称 Latin 0) が使われ始めています。草稿に、Latin 1 の +文字と Latin 9 の文字が混在していると、以下の手順によって、文字コード +が決定されます。 + + 1. `unify-8859-on-decoding-mode' を利用している場合: + 1. ISO-8859-1 に収まるなら "iso-8859-1" を利用 + 2. そうでないなら "utf-8" を利用 + 2. `unify-8859-on-decoding-mode' を利用していない場合: + 1. ISO-8859-1 と ISO-8859-15 のどちらにも収まる場合、"ISO-8859-1" + 2. ISO-8859-1 に収まるなら "iso-8859-1" を利用 + 3. ISO-8859-15 に収まるなら "iso-8859-15" を利用 + 4. そうでないなら、"utf-8" を利用 + +`mew-charset-latin' の初期値は、"iso-8859-15" です。"iso-8859-1" にし +たい場合は、以下のように設定します。 + + (setq mew-charset-latin "iso-8859-1") + +もし、US-ASCII 以外の文字に対し、必ず UTF-8 を使いたいなら、以下のよう +に設定して下さい。 + + (setq mew-cs-database-for-encoding + `(((ascii) nil "7bit" "7bit") + (nil utf-8 "base64" "B"))) + + + +File: mew.ja.info, Node: highlight, Next: hooks, Prev: charset, Up: Customize + +色付け +====== + +`mew-use-highlight-mark' が `t' の場合、マークの付いたメッセージに色が +付きます。初期値は `t' です。 + +`mew-use-highlight-header' が `t' の場合、メッセージのヘッダに色が付き +ます。初期値は `t' です。 + +`mew-use-highlight-body' が `t' の場合、メッセージの本文に色が付きます。 +初期値は `t' です。色を付ける上限は、`mew-highlight-body-max-size' で +指定できます。初期値は 10000 バイトです。 + +`mew-use-highlight-url' が `t' の場合、メッセージ中の URL に仕 +掛けが施されて、マウスを持っていくと光るようになります。初期値は +`t' です。 + +`mew-use-cursor-mark' が `t' の場合、Summary モードにおいて、現在表示 +しているメッセージの行頭に、`mew-cursor-mark' で指定された目印が付きま +す。初期値は `nil' です。`mew-cursor-mark' の初期値は ">" です。 + +`mew-use-highlight-cursor-line' が `t' の場合、Summary モードでカーソ +ルのある行に下線が引かれます。初期値は `t' です。 + +`mew-use-highlight-mouse-line' が `t' の場合、Emacs がマウスの色付けを +サポートしていれば、Summary モードでマウスのある行に色がつきます。真中 +のボタンをクリックしながら、マウスだけでメッセージを読む際にはとても便 +利です。初期値は `nil' になっています。 + +`mew-use-highlight-x-face' が `t' で、ヘッダ中の X-Face: が +Message モードでアイコン化されます。初期値は `t' です。この機能を +利用するには、"netpbm" と "compface" パッケージをインストールして下 +さい。 + +色を変更するには、Mew のソースと一緒に配布されている "dot.theme" を +適当な名前でコピーし内容を変更します。ここでは、そのファイル名を +"~/.mew-theme.el" としましょう。まず、この名前を ".mew.el" で +`mew-theme-file' に指定して下さい。 + + (setq mew-theme-file "~/.mew-theme.el") + +次に中身を変更します。たとえば、以下のような設定が見つかります。 + + (mew-setface-bold header-subject + :tty "red" :light "Firebrick" :dark "OrangeRed") + +シンボル `header-subject' は、ヘッダの "Subject:" の値を意味していま +す。:tty は Emacs をカラーの端末で起動した場合、:light と :dark は、そ +れぞれ Emacs をウインドウで起動したときの背景が白と黒の場合を意味して +います。 + +端末では green 、背景が白なら ForestGreen、背景が黒なら LimeGreen と設 +定するには、以下のようにします。 + + (mew-setface-bold header-subject + :tty "green" :light "ForestGreen" :dark "LimeGreen") + +シンボルに何があるのかは、"dot.mew" を見て下さい。 + +上記の方法では、ヘッダのすべてのフィールド名やフィールド値に対してシン +ボルが定義されている訳ではありません。そこで、どんなフィールドの色でも +簡単に変更できるように、`mew-header-color' と`mew-header-color-bold' +という関数が用意されています。後者を使うと太字に、前者を使うと普通の文 +字になります。たとえば、以下のように使います。 + + (mew-header-color-bold "Subject:" "LimeGreen" "OrangeRed") + +この設定では、"Subject:" が LimeGreen の太字に、その値が OrangeRed の +太字になります。 + +この方法では、端末や背景の色を考慮した設定はできません。また、フィール +ド値の色を省略すると、フィールド名と同じ色が使用されます。 + + + +File: mew.ja.info, Node: hooks, Next: pop, Prev: highlight, Up: Customize + +フック +====== + +Mew で用意されているフックをまとめます。 + +`mew-env-hook' + Mew の起動時の環境が設定される前に評価される。 +`mew-init-hook' + Mew の起動時に評価される。 +`mew-status-update-hook' + 状態の更新(`Z')のときに評価される。 +`mew-summary-mode-hook' + Summary モードに入るときに評価される。 +`mew-virtual-mode-hook' + Virtual モードに入るときに評価される。 +`mew-thread-display-hook' + スレッドが表示された後に評価される。 +`mew-header-mode-hook' + Header モードに入るときに評価される。 +`mew-draft-mode-hook' + Draft モードに入るときに評価される。 +`mew-draft-mode-newdraft-hook' + 新しい草稿が用意された際に、Draft モードにおいて評価される。 +`mew-draft-mode-reedit-hook' + +draft でないフォルダにある古い草稿を再編集した際に、Draft モード + において評価される。 +`mew-draft-mode-reedit-draft-hook' + +draft でないフォルダにある草稿を再編集した際に、Draft モードにお + いて評価される。 +`mew-draft-mode-reedit-queue-hook' + +queue または +postq フォルダにあるメッセージを再編集した際に、 + Draft モードにおいて評価される。 +`mew-draft-mode-edit-again-hook' + 古い形式で戻ってきたメッセージを再編集した際に、Draft モードにお + いて評価される。 +`mew-message-mode-hook' + Message モードに入るときに評価される。 +`mew-message-hook' + メッセージが Message モードで表示される度に評価される。 +`mew-make-message-hook' + Draft モードで MIME メッセージを作る前、つまり `C-cC-m' の際の最 + 初に評価される。例:(add-hook 'mew-make-message-hook + 'ispell-message) +`mew-send-hook' + メッセージを SMTP で送信/キューイングする前に評価される。メッセー + ジの最終形が作られる前に評価されることに注意。 +`mew-post-hook' + メッセージを NNTP で投稿/キューイングする前に評価される。メッセー + ジの最終形が作られる前に評価されることに注意。 +`mew-real-send-hook' + メッセージを SMTP で送信/キューイングする前に評価される。メッセー + ジの最終形が作られた後に評価されることに注意。 +`mew-real-post-hook' + メッセージを NNTP で送信/キューイングする前に評価される。メッセー + ジの最終形が作られた後に評価されることに注意。 +`mew-smtp-flush-hook' + +queue フォルダにメッセージがある場合に、SMTP が起動される前に評 + 価される。 +`mew-nntp2-flush-hook' + +postq フォルダにメッセージがある場合に、NNTP が起動される前に評 + 価される。 +`mew-smtp-sentinel-hook' + SMTP が終了する際に評価される。 +`mew-nntp-sentinel-hook' + 受信用の NNTP が終了する際に評価される。 +`mew-nntp2-sentinel-hook' + 送信用の NNTP が終了する際に評価される。 +`mew-pop-sentinel-hook' + POP が終了する際に評価される。 +`mew-pop-sentinel-non-biff-hook' + Biff ではない POP が終了する際に評価される。 +`mew-imap-sentinel-hook' + IMAP が終了する際に評価される。 +`mew-imap-sentinel-non-biff-hook' + Biff ではない IMAP が終了する際に評価される。 +`mew-scan-sentinel-hook' + Summary モードの `s' が終了する際に評価される。 +`mew-summary-ls-no-scan-hook' + Summary モードの `s' がフォルダの一覧を取らなかった場合に評価され + る。 +`mew-summary-exec-hook' + Summary モードの `x' の実行が終了する際に評価される。 +`mew-refile-guess-by-from-learn-hook' + mew-refile-guess-by-from-learn が実行される際に評価される。 +`mew-sort-hook' + Summary モードの `M-s' の実行が終了する際に評価される。 +`mew-pack-hook' + Summary モードの `O' の実行が終了する際に評価される。 +`mew-summary-delete-folder-hook' + フォルダが削除されるときに評価される。 +`mew-summary-rename-folder-hook' + フォルダ名が変更されるときに評価される。 +`mew-summary-toggle-disp-msg-hook' + Summary モードの `v' の実行が終了する際に評価される。 +`mew-syntax-format-hook' + マルチパートの書式を作成する関数 `mew-syntax-format' が呼ばれた際 + に評価される。 +`mew-addrbook-mode-hook' + アドレス帳の登録モードに入るときに評価される。 +`mew-cite-hook' + Draft モードで引用する際に呼ばれる。通常 supercite を設定するため + に使う。 +`mew-before-cite-hook' + Draft モードでメッセージを引用する直前に呼ばれる。 +`mew-suspend-hook' + Mew を一時中断した際に評価される。 +`mew-quit-hook' + Mew の終了時に評価される。 + +以下にフックの設定例を示します。 + +Draft モードでは、フックを `text-mode-hook'、`mew-draft-mode-hook' の +順で評価します。`text-mode-hook' で `auto-fill-mode' を設定していない +人は、 `mew-draft-mode-hook' を以下のように設定するのがよいかもしれま +せん。 + + (add-hook 'mew-draft-mode-hook + (lambda () + (auto-fill-mode 1) + (set-fill-column 70))) + +この例では、折り返しのカラム数を70に設定しています。 + + + +File: mew.ja.info, Node: pop, Next: imap, Prev: hooks, Up: Customize + +POP +=== + +Mew では、メッセージを受信する際に POP を利用できます。ここでは、POP +を制御するための以下の変数についてまとめます。 + +`mew-pop-server' + POP サーバの名前。 +`mew-pop-ssh-server' + POP を SSH 経由で取得する場合の SSH サーバの名前。 +`mew-pop-ssl' + POP over SSL を使うか否か。 +`mew-pop-ssl-port' + POP over SSL のポート番号。 +`mew-pop-user' + POP のアカウント名。初期値はログイン名。 +`mew-pop-auth' + POP の認証方式。`'pass' は USER/PASS (生パスワード)、`'apop' は + APOP、`t' は `mew-pop-auth-list' に従った SASL を意味する。初期値 + は `'apop'。 +`mew-pop-auth-list' + SASL で利用する認証方式のリスト。優先順位の高い順に並べる。現在、 + "CRAM-MD5" が利用可能。 +`mew-pop-delete' + POP サーバからメッセージを取得後、POP サーバにあるメッセージを削 + 除するか否か。`t' なら削除。`nil' なら削除しない。数値 N なら、最 + 初のアクセスから N 日後に削除する。初期値は `t'。 +`mew-pop-size' + POP サーバから取得するメッセージの大きさの上限。初期値は 55296 バ + イト。0 に設定すると、上限なしの意味になり、すべてのメッセージを + 取得する。上限に引っ掛かったメッセージの全体を取得する方法につい + ては、*Note retrieving:: を参照のこと。 +`mew-pop-body-lines' + 大きさの上限にひっかかったメッセージの本文を何行取得するかという + 値。初期値は 40。 +`mew-pop-header-only' + POP でメッセージを取得する際に、ヘッダのみにするか、本文も取得するか。 + `nil' でなければ、ヘッダのみを取得。初期値は `nil'。 + + + +File: mew.ja.info, Node: imap, Next: nntp, Prev: pop, Up: Customize + +IMAP +==== + +Mew では、メッセージを受信する際に IMAP を利用できます。ここでは、IMAP +を制御するための以下の変数についてまとめます。 + +`mew-imap-server' + IMAP サーバの名前。 +`mew-imap-ssh-server' + IMAP を SSH 経由で取得する場合の SSH サーバの名前。 +`mew-imap-ssl' + IMAP over SSL を使うか否か。 +`mew-imap-ssl-port' + IMAP over SSL のポート番号。 +`mew-imap-user' + IMAP のアカウント名。初期値はログイン名。 +`mew-imap-auth' + IMAP の認証方式。`nil' は LOGIN (生パスワード)、`t' は + `mew-imap-auth-list' に基づいた SASL を意味する。初期値は `t'。 +`mew-imap-auth-list' + SASL で利用する認証方式のリスト。優先順位の高い順に並べる。現在、 + "CRAM-MD5" と "LOGIN" が利用可能。 +`mew-imap-delete' + IMAP サーバからメッセージを取得後、IMAP サーバにあるメッセージを + 削除するか否か。`t' なら削除。`nil' なら削除しない。数値 N なら、 + 最初のアクセスから N 日後に削除する。初期値は `t'。 +`mew-imap-size' + IMAP サーバから取得するメッセージの大きさの上限。初期値は 55296 バイト。 + 0 に設定すると、上限なしの意味になり、すべてのメッセージを取得する。上限 + に引っ掛かったメッセージの全体を取得する方法については、 + *Note retrieving:: を参照のこと。 +`mew-imap-header-only' + IMAP でメッセージを取得する際に、ヘッダのみにするか、本文も取得するか。 + `nil' でなければ、ヘッダのみを取得。初期値は `nil'。 + + + +File: mew.ja.info, Node: nntp, Next: smtp, Prev: imap, Up: Customize + +NNTP +==== + +Mew では、ニュースを読み書きする際に NNTP を利用します。ここでは、NNTP +を制御するための以下の変数についてまとめます。 + +`mew-nntp-server' + NNTP サーバの名前。 +`mew-nntp-ssh-server' + NNTP を SSH 経由で取得する場合の SSH サーバの名前。 +`mew-nntp-ssl' + NNTP over SSL を使うか否か。 +`mew-nntp-ssl-port' + NNTP over SSL のポート番号。 +`mew-nntp-user' + NNTP のアカウント名。もし `nil' でなければ、認証の手続きが実行さ + れる。(mew-nntp-auth という変数はないことに注意。) +`mew-nntp-newsgroup' + ニュースグループ名の初期値。 +`mew-nntp-size' + NNTP サーバから取得するメッセージの大きさの上限。初期値は 55296 バイト。 + 0 に設定すると、上限なしの意味になり、すべてのメッセージを取得する。上限 + に引っ掛かったメッセージの全体を取得する方法については、 + *Note retrieving:: を参照のこと。 +`mew-nntp-header-only' + NNTP でメッセージを取得する際に、ヘッダのみにするか、本文も取得するか。 + `nil' でなければ、ヘッダのみを取得。初期値は `nil'。 +`mew-nntp-msgid-user' + Message-Id: を作成するためのユーザ名。`nil' であれば `mew-user' + の値が利用される。初期値は `nil'。Message-Id: の書式は以下を参照。 +`mew-nntp-msgid-domain' + Message-Id: を作成するためのドメイン名。`nil' であれば + `mew-mail-domain' の値が利用される。初期値は `nil'。Message-Id: + の書式は以下を参照。 + +なお、NNTP 用の Message-Id: の値は以下のように作成されます。 + + message-id = *random*.nntp-msgid-user@nntp-msgid-domain + + + +File: mew.ja.info, Node: smtp, Next: config, Prev: nntp, Up: Customize + +SMTP +==== + +Mew では、メッセージを送信する際に SMTP を利用します。SMTP サーバが認 +証を要求した場合、Mew は自動的にユーザにバスワードの入力を求めます。こ +こでは、SMTP を制御するための以下の変数についてまとめます。 + +`mew-smtp-server' + SMTP サーバの名前。 +`mew-smtp-port' + SMTP ポート番号。 +`mew-smtp-ssh-server' + SSH 経由でメッセージを送る際の SSH サーバの名前。 +`mew-smtp-ssl' + SMTP over SSL を使うか否か。 +`mew-smtp-ssl-port' + SMTP over SSL のポート番号。 +`mew-smtp-user' + SMTP AUTH で利用されるアカウント名。設定されない場合は、自動的に + メールアドレスに設定される。 +`mew-smtp-auth-list' + SMTP AUTH で利用する認証方式のリスト。優先順位の高い順に並べる。 + 初期値は、'("CRAM-MD5" "PLAIN" "LOGIN")。 +`mew-smtp-helo-domain' + SMTP HELO コマンドで使われるサーバ名。初期値は "localhost"。 +`mew-smtp-mail-from' + SMTP MAIL FROM コマンドで指定されるアドレス。`nil' の場合は、 + From: フィールドのアドレスが指定される。初期値は `nil'。 +`mew-smtp-msgid-user' + Message-Id: を作成するためのユーザ名。`nil' であれば `mew-user' + の値が利用される。初期値は `nil'。Message-Id: の書式は以下を参照。 +`mew-smtp-msgid-domain' + Message-Id: を作成するためのドメイン名。`nil' であれば + `mew-mail-domain' の値が利用される。初期値は `nil'。Message-Id: + の書式は以下を参照。 +`mew-use-8bit' + 8 ビットテキストを符号化せずにそのまま送るか否か。`nil' の場合は、 + 適切な MIME 符号化が施される。初期値は `nil'。 + +なお、SMTP 用の Message-Id: の値は以下のように作成されます。 + + message-id = *random*.smtp-msgid-user@smtp-msgid-domain + +Message Submission (ポート番号が 587 である送信用の SMTP)を使いたい場 +合は、以下のように設定して下さい。 + + (setq mew-smtp-port "submission") + +SSL (*Note SSL::)や TLS (*Note TLS::) の章も参考にして下さい。 + +SMTP サーバの中には、認証なし、つまりパスワードを送られるとエラーと見 +なす設定であるにも関わらず、認証を要求してくるものがあります。Mew は、 +SMTP サーバが認証を要求すると、ユーザにパスワードを尋ねて、入力された +パスワードをサーバへ送ります。上記のようなおかしな SMTP サーバに対処す +るには、以下のように設定し、認証を要求されてもパスワードを送らなくすれ +ばよいでしょう。 + + (setq mew-use-smtp-auth nil) + +`mew-use-smtp-auth' + SMTP サーバが認証を要求したとき、パスワードを送るかどうか。デフォルトは + `t'。`nil' にすると、SMTP サーバが認証を要求しても無視する。 + + + +File: mew.ja.info, Node: config, Next: config2, Prev: smtp, Up: Customize + +送受信の動作変化 +================ + +`mew-config-alist' を使うと、メッセージの送受信に関する動作に変化をつ +けられます。以下の設定例を使って説明します。 + + (setq mew-config-alist + '((home + (inbox-folder "+inbox-home") + (pop-server "pop.iij4u.or.jp")) + (ext + (pop-ssh-server "ssh.example.org")) + (default + (proto "%") + (imap-server "imap.example.org") + (pop-server "pop.example.org")))) + +この例では、"home"、"ext"、"default" という 3 つのケースを定めています。 +それぞれのケースに対して、いくつかのキーと値の対が設定されています。 + +この例を使って、`mew-config-alist' の意味を説明します。ケースを +"home" にして "pop-server" を索くと、"pop.iij4u.or.jp" が得られます。ケー +スを "ext" にして "pop-server" を索くと、"ext" には該当するキーがな +いので、"default" を見て、"pop.example.org" が得られます。ケースを +"default" にして "pop-server" を索くと、"pop.example.org" が得られます。 + +ケースを "home" にして "inbox-folder" を索くと、"+inbox-home" が得られ +ます。ケースを "ext" にして "inbox-folder" を索くと、"ext" には該当す +るキーがなく、さらに "default" にもないので、`mew-inbox-folder' という +変数の値が得られます。ケースを "default" にして "inbox-folder" を索い +た場合も、`mew-inbox-folder' の値が得られます。 + +"proto" (`mew-proto')は、`M-x mew' と入力された際に、どのフォルダに移 +動するか指定するために使います。(Mew を起動するために`M-x mew' と入力 +する場合、"default" ケースの "proto" が利用されます。Mew が起動してい +る際に、`M-x mew' と入力するとケースに従って、"proto" が選ばれます。) + +値の候補は、"+"、"$"、"%"、"-" です。これらは標準では、"+inbox"、 +"$inbox"、"%inbox"、"-fj.mail.reader.mew" を意味します。 + +`mew-config-alist' で設定できるキーは、`mew-"キー"' という変数に対応し +ています。以下に設定できる項目を列挙します。 + + name, user, mail-domain, + cc, fcc, dcc, reply-to, organization, header-alist, proto, + smtp-server, smtp-port, smtp-ssh-server, smtp-ssl, smtp-ssl-port, + smtp-user, smtp-auth-list, + smtp-msgid-user, smtp-msgid-domain, smtp-helo-domain, smtp-mail-from, + pop-server, pop-port, pop-ssh-server, pop-ssl, pop-ssl-port, + pop-user, pop-auth, pop-auth-list, + pop-size, pop-header-only, pop-delete, pop-body-lines, + pop-proxy-server, pop-proxy-port, + imap-server, imap-port, imap-ssh-server, imap-ssl, imap-ssl-port, + imap-user, imap-auth, imap-auth-list, + imap-size, imap-header-only, imap-delete, + imap-trash-folder, imap-queue-folder, imap-spam-field, imap-spam-word, + imap-proxy-server, imap-proxy-port, + nntp-server, nntp-port, nntp-ssh-server, nntp-ssl, nntp-ssl-port, + nntp-user, nntp-size, nntp-header-only, + nntp-msgid-user, nntp-msgid-domain, + ssl-cert-directory, ssl-verify-level, + inbox-folder, queue-folder, postq-folder, + mailbox-type, mbox-command, mbox-command-arg, + signature-file, content-type, refile-guess-alist, + spam-prog, spam-prog-args, ham-prog, ham-prog-args, + use-old-pgp, pgp-signer, smime-signer, privacy-method, + protect-privacy-always, protect-privacy-always-type, + protect-privacy-encrypted, protect-privacy-encrypted-type, + protect-privacy-with-old-pgp-signature, + use-format-flowed + +name、user、mail-domain は以下の規則にしたがって、From: の値になります。 + + from = name + +自分で `mew-from-list' を設定していない場合は、上記のルールに従い各 +ケースの from を集めて、`mew-from-list' が自動的に設定されます。 +*Note cheader:: を参照のこと。 + +`mew-config-alist' に設定したケース名をケースに指定できます。Mewの起動 +時のケースは、"default" になっています。 + +Summary モードにおいて、ケースを変更するには `C' を利用します。ケース +には、`TAB' で補完、`C-cTAB' で循環的な補完が効きます。 + +ケースが "default" 以外の値をとった場合は、Summary モードのモードライ +ンに表示されます。以下はケースが "home" となっている場合の例です。 + + (Summary home) + + +Draft モードでは、ケースが "default" でない場合、モードラインにその値 +が表示されます。以下は、ケースが "home" である場合の例です。 + + (Draft home) + +Draft モードにおいて、その草稿のケースを変更するには、`C-cC-o' を用い +ます。mail-domain キーや header-alist キーに対応する値に応じて、ヘッダ +が動的に変更されます。なお、このケースは、その Draft モードに固有にな +ります。 + +Draft モードでは、ケースを自動的に設定することもできます。 + +`mew-case-guess-when-prepared' + この変数が `t' の場合、草稿が用意されたときに、 + `mew-case-guess-alist' に従ってケースが設定される。初期値は + `t'。 +`mew-case-guess-when-composed' + この変数が `t' の場合、メッセージが作成されたときに、 + `mew-case-guess-alist' に従ってケースが設定される。初期値は + `nil' +`mew-case-guess-when-replied' + この変数が `t' の場合、返答によって草稿が用意されたときに、 + `mew-case-guess-when-replied-alist' に従ってケースが設定される。 + 初期値は `t'。 + +`mew-case-guess-alist' と `mew-case-guess-when-replied-alist' +の書式は、`mew-refile-guess-alist' と同じです。詳しくは、 +*Note by-alist:: を参照して下さい。 + +Draft モードで草稿を送信するために `C-cC-c' を使うと、Draft モードのケー +スが SMTP/NNTP サーバなどを決定するために利用されます。Summary モード +で +queue/+postq のメッセージを送り出すために `C-cC-c' を利用すると、 +Summary モードのケースが利用されます。たとえ、そのケースが Draftモード +で指定されていたケースと違ってもです。Summary モードで`C-uC-cC-c' を使 +うと、+queue/+postq のメッセージを送り出すためのケースが指定できます。 + + +以下にケースに関するコマンドをまとめます。 + +`C' + Summary モードにおいて、ケースを設定する。 +`C-cC-o' + Draft モードにおいて、その草稿のケースを設定する。 + + + +File: mew.ja.info, Node: config2, Next: custom-misc, Prev: config, Up: Customize + +設定の書式 +========== + +Mew 6.1 から ".mew.el" の設定方法が改善されました。古い書式も有効です +が、より簡単な新しい書式も利用できます。 + + - 古い書式ではリストの中に "." が現れる場合がありました。新しい書式 + では、"." はまったく使われません。たとえば、("foo" . "bar") と書 + いていたところは、("foo" "bar") と書けます。 + - 古い書式では、ポート番号は文字列で書いていました。たとえば、"25" + です。新しい書式では、数値で書いてもよくなりました。たとえば、25 + です。文字列も有効です。たとえば、"smtp" です。 + - 古い書式では、`mew-config-alist' のケースやキーを文字列で書いてい + ました。新しい書式では、シンボルで書けます。 + +以下に mew-config-alist を新しい書式で書いた例を示します。 + + (setq mew-config-alist + '((home + (imap-server "imap.example.org") + (imap-ssl t) + (imap-ssl-port 993) + (smtp-server "smtp.example.org") + (smtp-port "submission")))) + +以下の古い書式と見比べて下さい。 + + (setq mew-config-alist + '(("home" + ("imap-server" . "imap.example.org") + ("imap-ssl" . t) + ("imap-ssl-port" . "993") + ("smtp-server" . "smtp.example.org") + ("smtp-port" . "submission")))) + +繰り返しますが、Mew 6.1 では古い書式も有効です。古い書式と新しい書式を +混ぜて書いても構いません。 + + + +File: mew.ja.info, Node: custom-misc, Next: Tips, Prev: config2, Up: Customize + +その他 +====== + +環境によっては、添付ファイルをセーブする際に、ファイル名を SAMBA 形式に +すると便利なことがあります。この場合、`mew-use-samba-encoding' を +`t' にして下さい。ファイル名として、どの文字コードを利用するかは、 +`mew-cs-samba' で指定できます。初期値は `shift_jis' です。 + +Summary モードで `#' と押すと、現在のメッセージを印刷できます。印刷に +利用する関数は `mew-print-function' で定義します。初期値は、 +`ps-print-buffer' ですから、PostScript に変換されて印刷されます。自分 +の作成した関数を利用するには、以下のように設定します。 + + (setq mew-print-function 'my-print-function) + +ヘッダ中のどのフィールドを印刷するかは、`mew-field-for-printing'で指定 +できます。初期値は、以下のようになっています。 + + '("Subject:" "From:" "To:" "Cc:" "Date:") + +たとえば、Subject:、From:、Date: のみを印刷するには、以下のように設定 +しましょう。 + + (setq mew-field-for-printing '("Subject:" "From:" "Date:")) + + + + +File: mew.ja.info, Node: Tips, Next: region, Prev: custom-misc, Up: Top + +さらなる一歩 +************ + +* Menu: + +* region:: リージョン +* visiting:: 移動 +* SSH:: Secure SHell +* SSL:: Secure Socket Layer +* TLS:: Transport Layer Security +* spam:: スパム +* spam2:: スパム(2) +* addr-warn:: アドレスの警告 +* biff:: Biff +* edit:: Edit モード + + + +File: mew.ja.info, Node: region, Next: visiting, Prev: Tips, Up: Tips + +リージョン +========== + +Summary モードには、`C-u' 付きで呼び出すと、リージョンに作用するコマン +ドがあります。これらのコマンドは、ビジブルなリージョンが指定されている +場合は、`C-u' なしでもそのリージョンに作用します。 + +Emacs では、以下の設定を "~/.emacs" に入れると、ビジブルなリージョンが +利用できるようになります。 + + (transient-mark-mode 1) + +以下に、該当するコマンドを列挙しておきます。 + + `?', `/', `tt', `x', `lx', `ma', `Md', `S', `mlc', `mli', `*', `$', `d', `u' + +`*', `$', `d', `u' は、直前に数字を入力することで、繰り返しの回数を指 +定することもできます。たとえば、`3*' は 3 つのメールに `*' マークを付 +けます。数字の前に `C-u' は不要です。 + + + +File: mew.ja.info, Node: visiting, Next: SSH, Prev: region, Up: Tips + +移動 +==== + +Draft モードにおいて、`C-cC-m' でメッセージを作成し送信キューに入 +れた後、+queue に移動したい場合は、 +`mew-visit-queue-after-sending' を `t' に設定して下さい。 + +Summary モードにおいて、`C' でケースを設定した後に、各 inbox に移動し +たい場合は、`mew-visit-inbox-after-setting-case' を `t'に設定しましょ +う。 + +Summary モードから、一番数字の小さい草稿(Draft モード)に移動するには、 +`C-cC-o' が利用できます。 + + + +File: mew.ja.info, Node: SSH, Next: SSL, Prev: visiting, Up: Tips + +Secure SHell +============ + +Mew は SSH として、SSH バージョン 1、2 および OpenSSH をサポートしてい +ます。Mew から SSH を利用する前に、必ずコマンド・ラインで "ssh" を実行 +し、SSH サーバの公開鍵を取得して下さい。すなわち、ユーザのパスワードか、 +ローカルのマシンの秘密鍵を復号化するためのパスワードを入力すれば、サー +バにログインできる状態にして下さい。なお、"ssh-agent" を利用すれば、秘 +密鍵を復号化するためのパスワードの入力を省略できます。 + +後は、各プロトコルの SSH に関する変数を設定して下さい。たとえば、POP +over SSH を利用する場合は、`mew-pop-ssh-server' に SSH サーバの名前を +設定しましょう。 + +SSH で通信が保護されている場合、モードラインに錠前の絵が表示されます。 + +Mew の実装では、SSH と SSL/TLS を同時には使えません。SSH トンネルの中 +でSSL/TLS を使う必要がある場合、Mew では SSL/TLS だけを設定し、SSH ト +ンネルはコマンドラインから張るようにして下さい。 + + + +File: mew.ja.info, Node: SSL, Next: TLS, Prev: SSH, Up: Tips + +Secure Socket Layer +=================== + +SSL を使うには、認証局方式の信用モデルを理解している必要があります。現 +在、Mew は SSL のために "stunnel" バージョン 3 とバージョン 4 をサポー +トしています。 + +Mew で利用する前に、SSL サーバに対して "stunnel" で SSL のコネクション +が張れるか確かめて下さい。"stunnel" は、"openssl" のライブラリをリンク +しているので、"openssl" の知識が必要です。 + +信用する証明書を保存しておくディレクトリを "~/.certs" だとしましょう。 +ここに "openssl" の "certs" ディレクトリに付いてくる PEM 形式の証明書 +を"<ハッシュ>.0" という名前でコピーします。 + +ここでは、PEM 形式の証明書のファイル名を "ca.pem" だとしましょう。「< +ハッシュ>」は以下のように計算できます。 + + % openssl x509 -hash -noout -in ca.pem + +"~/.certs/" へコピーするには、以下のようにします。 + + % cp ca.pem ~/.certs/`openssl x509 -hash -noout -in ca.pem`.0 + +"openssl" に付いてくる証明書は、世の中で使われている CA すべてを網羅で +きていません。あなたが利用するサーバの証明書が、他の CA から発行された +場合、その CA の証明書を同様にコピーしておく必要があります。以下のペー +ジに CA の証明書がたくさん置いてあります。 + + http://www.columbia.edu/~ariel/good-certs/ns45/ + +Mew で "stunnel" を制御する重要な変数は 2 つです。 +`mew-ssl-cert-directory' は、信用する CA の証明書を置いておくディレク +トリであり、初期値は "~/.certs" です。また、`mew-ssl-verify-level' で、 +証明書を検証するレベルを指定できます。レベルの初期値は 1 です。この意 +味は、以下の通りです。 + +0 + 検証しない +1 + サーバの証明書があれば検証する。検証結果が失敗なら、SSL/TSL コネ + クションは作られない。証明書がなければ、SSL/TLS コネクションを作 + 成する。 +2 + サーバの証明書を検証する。検証結果が失敗なら、SSL/TSL コネクショ + ンは作られない。証明書がなければ、SSL/TLS コネクションを作成しな + い。 +3 + サーバが送ってきたものではなく、ローカルにインストールされている + 証明書で検証する。 + +後は各プロトコルの SSL に関する変数を設定して下しさい。たとえば、POP +over SSL を利用するには、`mew-pop-ssl' を `t' にします。また、ポート番 +号が標準と異なる場合には、`mew-pop-ssl-port' を設定して下さい。 + + (setq mew-pop-ssl t) + +SMTP で SSL を利用する場合は、以下のようにします。 + + (setq mew-smtp-ssl t) + +SSL で通信が保護されている場合、モードラインに錠前の絵が表示されます。 + + + +File: mew.ja.info, Node: TLS, Next: spam, Prev: SSL, Up: Tips + +Transport Layer Security +======================== + +Mew では SSL の代りに TLS を利用することもできます。TLS の実現は、SSL +と同様 "stunnel" に頼っています。ですので、TLS を利用する際には、 +*Note SSL:: の説明に従って設定して下さい。 + +次に、SSL のポート番号を守りたいプロトコルと同じポート番号に設定します。 +たとえば、POP では以下のようにします。 + + ;; mew-pop-port is default to "pop3" (110) + (setq mew-pop-ssl t) + (setq mew-pop-ssl-port mew-pop-port) ;; The default is "pop3s" (995) + +すなわち、SSL のポート番号と保護したいプロトコルのポートが同じであれば +TLS、異なれば SSL が利用されます。 + +以下は、Message Submission を TLS で守るための設定例です。 + + (setq mew-smtp-port "submission") ;; The default is "smtp" (25) + (setq mew-smtp-ssl t) + (setq mew-smtp-ssl-port mew-smtp-port) ;; The default is 465 + + + +File: mew.ja.info, Node: spam, Next: spam2, Prev: TLS, Up: Tips + +スパム +====== + +(1) スパムのフィルタが POP サーバや IMAP サーバ側で動いている場合: + +POP で +inbox にメッセージを取得したり、$inbox や %inbox でメッセージ +の一覧を取ったりする場合に、スパムに自動的に `D' マークを付けることが +できます。 + +Bogofilter を利用している場合は、以下の設定を "~/.mew.el" に入れて下さ +い。 + + (defun mew-spam-bogofilter (val) + (let ((case-fold-search t)) + (if (string-match "yes" val) ?D))) + + (setq mew-inbox-action-alist + '(("X-Bogosity:" mew-spam-bogofilter))) + +`D' マークを付ける代わりに、+spam フォルダへリファイルするように `o' +マークを付けるようにするには、関数を以下のように記述します。 + + (defun mew-spam-bogofilter (val) + (let ((case-fold-search t)) + (if (string-match "yes" val) "+spam"))) + +Spamassassin の場合は、以下の設定を "~/.mew.el" に入れて下さい。 + + (setq mew-spam: "X-Spam-Flag:") + (defun mew-spam-assassin (val) + (let ((case-fold-search t)) + (if (string-match "yes" val) ?D))) + + (setq mew-inbox-action-alist + '(("X-Spam-Flag:" mew-spam-assassin))) + +bsfilter を使う場合は、bsfilter に含まれているマニュアルを参照して下さ +い。 + + +(2) スパムのフィルタが IMAP サーバ側で動いている場合: + +%inbox でメッセージの一覧を取る際に、IMAP サーバの中でスパムを消去、ま +たは、他のフォルダへ移動させることができます。Bogofilter を利用してい +る場合は、以下のような設定を "~/.mew.el" に加えて下さい。 + + (setq mew-imap-spam-field "X-Bogosity") + (setq mew-imap-spam-word "Yes") + +`mew-imap-spam-folder' あるいは `mew-imap-trash-folder' が定義されてい +れば、そのフォルダへスパムが移動します。そうでなければ、スパムは消去さ +れます。 + +(3) ローカルで bogofilter を動かして、一括して `*' マークを付ける方法 +もあります。まず、以下のスクリプトをインストールして下さい。 + + #!/bin/sh + + bogofilter -v -T -B $* | grep S + +このスクリプト名を "bogo" だとしましょう。Summary モードで `?' を実行 +し、`RET' を入力し、コマンド名に "bogo" を指定すれば、スパムに`*' マー +クが付きます。あとは、`md' + `x' などで処理するといいでしょう。 + +(4) POP サーバを利用しており、サーバ側ではスパムのフィルタを動かせない +が、メッセージの取得時にマークを付けたい場合: + +bsfilter は、POP の代理サーバとなる機能があるので、これを実現できます。 +詳しくは bsfilter に含まれているマニュアルを参照して下さい。 + + + +File: mew.ja.info, Node: spam2, Next: addr-warn, Prev: spam, Up: Tips + +スパム(2) +========= + +Summary モードで読んでいる現在のメッセージを、フィルターにスパムとして +学習させるには `ls' を使います。同様に、ハム(スパムでないメッセージ)と +して学習させるには `lh' を利用して下さい。 + +両者のコマンドを使用するためには、4 つの変数を設定しておく必要がありま +す。ここでは bogofilter を例題にとり、3 つの場合について説明します。 + +(1) ローカルのフィルターに学習させる場合: + + (setq mew-spam-prog "bogofilter") + (setq mew-spam-prog-args '("-s" "-N" "-v")) + (setq mew-ham-prog "bogofilter") + (setq mew-ham-prog-args '("-n" "-S" "-v"))) + +(2) サーバ()側のフィルターに SSH 経由で学習させる場合: + + (setq mew-spam-prog "ssh") + (setq mew-spam-prog-args '("" "bogofilter" "-s" "-N" "-v")) + (setq mew-ham-prog "ssh") + (setq mew-ham-prog-args '("" "bogofilter" "-n" "-S" "-v"))) + +(3) ファイアウォール()の先のサーバ()のフィルターに多 +段の SSH 経由で学習させる場合: + + (setq mew-spam-prog "ssh") + (setq mew-spam-prog-args '("-A" "" "ssh" "" "bogofilter" "-s" "-N" "-v")) + (setq mew-ham-prog "ssh") + (setq mew-ham-prog-args '("-A" "" "ssh" "" "bogofilter" "-n" "-S" "-v"))) + +なお SSH を利用する場合、関連するホストには、パスワードなしでログイン +できるように設定しておく必要があります。 + + + +File: mew.ja.info, Node: addr-warn, Next: biff, Prev: spam2, Up: Tips + +アドレスの警告 +============== + +社内で閉じるべきメッセージの宛先に、うっかり社外の人のアドレスを書いて +しまうことがあります。Mew では、たとえば社内のドメイン名を列挙しておく +と、社外のアドレスを赤色にして警告してくれます。 + +どのアドレスを警告するのかを決定する変数は 4 つあり、すべて文字列のリ +ストになります。Mew は以下のルールに従って、警告するアドレスを決めます。 + + 1. アドレスが `mew-safe-addresses' で指定されていれば警告しない。 + 2. アドレスが `mew-warn-addresses' で指定されていれば警告する。 + 3. ドメインが `mew-safe-domains' で指定されていれば警告しない。 + 4. ドメインが `mew-warn-domains' で指定されていれば警告する。 + 5. `mew-warn-addresses' か `mew-safe-domains' が定義されていれば警告 + する。 + 6. 警告しない。 + +以下に "@example.org" 以外のドメインを持つアドレスを警告する例を示しま +す。 + + (setq mew-safe-domains '("example.org")) + +ドメインは "@example.org" ですが、"customers@example.org" は警告したい +場合は、さらに以下のように設定します。 + + (setq mew-warn-addresses '("customers@example.org")) + + + +File: mew.ja.info, Node: biff, Next: edit, Prev: addr-warn, Up: Tips + +Biff +==== + +メッセージが到着したか定期的に調べる機能を biff といいます。Mew では、 +以下の設定をすると、5 分ごとに新規メッセージが何個あるか調べるようにな +ります。 + + (setq mew-use-biff t) + +新規メッセージがあれば、その数がモードラインに表示されます。 + +Biff の対象となるサーバとプロトコルは、Mew の起動時に `mew-proto'とケー +ス(`mew-case')から決定されます。 + +以下の設定をすると、新規メッセージがない状態からある状態に変った際に、 +ビープ音が鳴ります。 + + (setq mew-use-biff-bell t) + +メッセージの到着を調べる間隔を変えるには、`mew-biff-interval' を設定し +て下さい。以下は、10 分にする例です。 + + (setq mew-biff-interval 10) + + + +File: mew.ja.info, Node: edit, Next: Convention, Prev: biff, Up: Tips + +Edit モード +=========== + +Edit モードは、既存のメッセージを編集し、新しいメッセージを作成するた +めのモードです。用途の典型例を以下に示します。 + + - 大きな添付ファイルを削除して保存する + - PGP/MIME や S/MIME で暗号化されたメッセージを復号化した状態で保存 + する + +現在のメッセージを Edit モードで編集するには、`M-e'を押します。すると、 +Draft モードに似た形で草稿が用意されます。Edit モードでは、Draftモード +と同様の操作で、メッセージを編集できます。 + +編集したメッセージを新しいメッセージとして保存するには、`C-cC-c'か +`C-cC-m'を使います。両者は、まったく同じコマンドです。これらのコマンド +を実行すると、どのフォルダに保存するかを訊いてきます。 + +なお、この機能は再編集(*Note sum-write::)と混同しやすいので注意して下 +さい。再編集は編集後に送信するのに対し、Edit モードでは編集の後に保存 +します。 + +以下に Edit モードのまとめを示します。Summary モードから Edit モードに +入るには以下のコマンドを使います。 + +`M-e' + 現在のメッセージを元に Edit モードに入る。 + +Edit モードでのコマンドをまとめます。 + +`C-cC-c' + 編集したメッセージを新しいメッセージに保存。 +`C-cC-m' + `C-cC-c'に同じ。 +`その他' + Draft モードと同じ。 + + + + +File: mew.ja.info, Node: Convention, Next: Implementation, Prev: edit, Up: Top + +メッセージの作法 +**************** + +メッセージをやりとりする際には、最低限のマナーがあります。マナーを守っ +ていないメッセージは読みにくいため、大変損します。簡潔かつ適切な文章を +書き、なるべく相手に理解してもらえるよう努力しましょう。 + +メッセージを書く際に気を付けるべき項目を以下に示します。 + +To: と Cc: を正しく書く + To: が目的の人で、Cc: は参考までに送り付ける人です。自分のアドレ + スが Cc: の場合は、読み飛ばす人がいますから注意して下さい。また、 + 不必要なアドレスを To: や Cc: に書いて、相手に迷惑をかけてしまう + ことがないようにしましょう。 + +To: と Cc: に書くアドレスの数は少なくする + アドレスをたくさん To: や Cc: に書くのはよくないことです。面倒で + もメーリングリストを作りましょう。あるいは、必要に応じて宛先を匿 + 名にしましょう(*Note anonymous::)。 + +Subject: には本文の内容を的確に短く書く + Subject: を見て読むか決める人がいますから、不適切な Subject: だと + 読んでもらえないかもしれません。長い Subject: は読みにくいので止 + めましょう。 + +必要な部分だけを引用する + 面倒でも不要な部分は削りましょう。Mew を使っていれば、引用は楽勝 + のはずです。 + +シグニチャは簡素にする + 長いシグニチャは単なる自己満足です。 + +いたずらメッセージを送らない + こんなことは注意したくありませんが、それでも不幸のメッセージなど + を送ってくる人がいます。人格を疑われることを理解すべきです。 + +相手の読めるデータのみを添付する + なんの合意もなしに送ってよいデータはテキストのみです。それ以外の + データを送る場合は、あらかじめ相手に送ってよいか確認をとりましょ + う。メーリングリストには、テキストのみを投稿するのが無難でしょう。 + +また、インターネットのマナーは RFC1855 を読むといいでしょう。 + + + + +File: mew.ja.info, Node: Implementation, Next: Avail, Prev: Convention, Up: Top + +実装について +************ + +"mewl" と "mewencode" が必要なのはなぜ? + Mew では、Summary mode でメッセージを取得している間や、一覧を再表 + 示している間に、メッセージを読み進めることができます。これは、プ + ログラムの制御の流れが複数必要であることを意味しています。Emacs + で制御の流れを複数にするには、サブプロセスを作るか、TCP コネクショ + ンを張るしか方法がありません(Emacs Lisp には light weight process + がありません)。POP や SMTP には、TCP コネクションを使うので問題あ + りません。しかし、Summary mode の一覧を再表示するためには、何かコ + マンドを起動しないといけません。これが、"mewl" が存在する理由です。 + "mewencode" が存在する理由は、単に速度のためです。MIME の符号化を + Emacs Lisp で実装したところ、使い物にならないぐらい遅かったので、 + "mewencode" を使い続けています。(ただし、Base64 が Emacs で実装さ + れていれば、そちらを使います。) + +文字列検索(`C-s'、`C-r')すると、行末にカーソルが飛ぶのはなぜ? + Summary mode において、スレッド情報は表示されません。これは、 + Summary mode で表示されている行に関しては、表示する瞬間にスレッド + 情報に非表示の属性を付けるからです。非表示の属性がついている部分 + は文字列検索の対象にはなりません。しかし、Summary mode に表示され + ていない行のスレッド情報は、非表示の属性がついていないため、検索 + の対象となります。そして、合致した行が表示される際に非表示の属性 + がついて、あたかも行末に合致したかのような錯覚を受けます。Summary + mode 全体の行のスレッド情報には、キーの入力がない時間に非表示の属 + 性が付きます。全体に非表示の属性が付くと、Summary mode のモードラ + インの右端にある `*' マークが消えます。この状態では、文字列検索が + 直感通りに働きます。 + +Mew 4.3 でファイルを添付すると MS のメールリーダでファイル名が認識できるようになりました + MS のメールリーダは、ファイル名を符号化する際に、標準化されてない + 独自の方法を使います。MS のメールリーダが、標準化されている符号化 + 方式に移行すればいいのですが、何度お願いしても無理でした。そこで、 + Mew では以下のような方法で、この問題を解決しました。すなわち、Mew + は基本的には標準化されている方法で、ファイル名を符号化します。そ + れに加えて、MS のメールリーダが参照する標準化されてないパラメータ + に対して、ファイル名を MS 独自の方法で符号化し、付加します。 + + + + + +File: mew.ja.info, Node: Avail, Next: obtain, Prev: Implementation, Up: Top + +入手方法とメーリングリスト +************************** + +ここでは、Mew の入手方法とメーリングリストについて触れます。 + +* Menu: + +* obtain:: Mew の入手方法 +* ml:: メーリングリスト + + + +File: mew.ja.info, Node: obtain, Next: ml, Prev: Avail, Up: Avail + +Mew の入手方法 +============== + +Mew の最新バージョンは以下から入手できます。 + + http://www.Mew.org/Release/ + +Mew の Git 版について知りたければ、以下を参照して下さい。 + + http://www.mew.org/ja/git/ + + + +File: mew.ja.info, Node: ml, Next: Copyright, Prev: obtain, Up: Avail + +メーリングリスト +================ + +Mew に関するメーリングリストについては、以下を参照して下さい。 + + http://www.mew.org/mailman/listinfo + + + + + +File: mew.ja.info, Node: Copyright, Next: Variable Index, Prev: ml, Up: Top + +著作権について +************** + +Mew は以下の著作権に従います。 + +Copyright (C) 1994-2013 Mew developing team. +All rights reserved. + +変更の有無にかかわらず、ソースおよびバイナリ形式の再配布および利用は、 +以下の条件を満たしていれば、これを許可する。 + + 1. ソース・コードの再配布は、上記の著作権表示、この条件項目、および、 + 以下の免責事項を保存しなければならない。 + 2. バイナリ形式の再配布は、上記の著作権表示、この条件項目、および、 + 以下の免責事項を、その配布に付随する説明書、あるいはその他の資料 + のいずれかに明記しなければならない。 + 3. 前もって特別に許諾を得ない限り、このソフトウェアから派生した製品 + の推奨や販売促進のために、このチーム名と貢献者達の名前を利用して + はならない。 + +このソフトウェアは「このままの形で」提供され、明示的あるいは言外の保証 +は、商用利用および特定目的への適合に対する言外の保証も含み、またこれら +だけに限らず、存在しない。たとえ以下のような損害の可能性を示唆されてい +たとしても、どのような形にしろこのソフトウェアの利用から発生した問題に +おいて、このチームと貢献者達は、(代替製品やサービスの調達; 利用権、デー +タ、あるいは利益の損失; あるいは営業の中断を含む、またこれらだけに限ら +ず)直接的に、間接的に、偶然に、特別に、懲罰上、あるいは、必然的に生じ +てしまった損害に対し責任はなく、いかなる責任理論上でも契約の有無に係わ +らず厳密な責任はなく、また(過失あるいはその他を含む)不法行為に対しても +責任はない。 + +CD ROM に入れて配布したいという方は、できるだけ教えて下さい。教えてく +れなくても怒りませんが、教えて頂けるとありがたいです。配布を断ったこと +はありません。 + +このマニュアルの著作権は、著者に属します。複製、改変、再配布は自由です +が、無保証です。また、このマニュアルから発生した被害に対し、著者は一切 +責任を負いません。 + + + + +File: mew.ja.info, Node: Variable Index, Next: Key Index, Prev: Copyright, Up: Top + +変数索引 +******** + + +* Menu: + +* mail-user-agent: Composing. (line 5) +* mail-user-agent: configuration. (line 5) +* mail-user-agent: start. (line 5) +* mew-addrbook-for-cite-label: draft-mode. (line 5) +* mew-addrbook-for-cite-prefix: draft-mode. (line 5) +* mew-addrbook-mode-hook: hooks. +* mew-addrbook-override-by-newone: auto-alias. (line 5) +* mew-ask-charset: charset. (line 5) +* mew-ask-fcc: send. (line 5) +* mew-ask-subject: send. (line 5) +* mew-auto-flush-queue: retrieving. (line 5) +* mew-auto-get: start. (line 5) +* mew-before-cite-hook: hooks. +* mew-biff-interval: biff. (line 5) +* mew-case-guess-alist: config. (line 5) +* mew-case-guess-when-composed: config. +* mew-case-guess-when-prepared: config. +* mew-case-guess-when-replied-alist: config. (line 5) +* mew-case-guess-when-replied: config. +* mew-cc: draft-mode. (line 5) +* mew-charset-latin: charset. (line 5) +* mew-charset-m17n: charset. (line 5) +* mew-cite-fields: draft-mode. (line 5) +* mew-cite-format: draft-mode. (line 5) +* mew-cite-hook: hooks. +* mew-cite-prefix: draft-mode. (line 5) +* mew-cite-prefix-function: draft-mode. (line 5) +* mew-config-alist: config. (line 5) +* mew-config-alist: config2. (line 5) +* mew-cs-samba: custom-misc. (line 5) +* mew-cursor-mark: highlight. (line 5) +* mew-dcc: draft-mode. (line 5) +* mew-debug: status-update. (line 5) +* mew-decode-broken: analysis. +* mew-decode-broken: status-update. (line 5) +* mew-decode-quoted: invalid. (line 5) +* mew-delete-unread-mark-by-mark: unread mark. (line 5) +* mew-draft-mode-edit-again-hook: hooks. +* mew-draft-mode-hook: hooks. +* mew-draft-mode-newdraft-hook: hooks. +* mew-draft-mode-reedit-draft-hook: hooks. +* mew-draft-mode-reedit-hook: hooks. +* mew-draft-mode-reedit-queue-hook: hooks. +* mew-draft-privacy-method: shortcut. (line 5) +* mew-end-of-message-string: multipart. (line 5) +* mew-end-of-part-string: multipart. (line 5) +* mew-env-hook: hooks. +* mew-field-delete-for-forwarding: forward. (line 5) +* mew-field-for-printing: custom-misc. (line 5) +* mew-fields: header. (line 5) +* mew-file-max-size: analysis. +* mew-flowed-auto-wrap: longline. (line 5) +* mew-flowed-fold-length: longline. (line 5) +* mew-flowed-fold-threshold: longline. (line 5) +* mew-from-list: cheader. (line 5) +* mew-ham-prog-args: spam2. (line 5) +* mew-ham-prog: spam2. (line 5) +* mew-header-alist: draft-mode. (line 5) +* mew-header-max-length: analysis. +* mew-header-mode-hook: hooks. +* mew-header-veil-count: features. (line 5) +* mew-highlight-body-max-size: highlight. (line 5) +* mew-imap-auth: imap. +* mew-imap-auth-list: imap. +* mew-imap-delete: imap. +* mew-imap-delete: retrieving. (line 5) +* mew-imap-header-only: imap. +* mew-imap-header-only: retrieving. (line 5) +* mew-imap-sentinel-hook: hooks. +* mew-imap-sentinel-non-biff-hook: hooks. +* mew-imap-server: configuration. (line 5) +* mew-imap-server: imap. +* mew-imap-size: imap. +* mew-imap-spam-field: spam. (line 5) +* mew-imap-spam-folder: spam. (line 5) +* mew-imap-spam-word: spam. (line 5) +* mew-imap-ssh-server: imap. +* mew-imap-ssl: imap. +* mew-imap-ssl-port: imap. +* mew-imap-trash-folder: delete mark. (line 5) +* mew-imap-trash-folder-list: delete mark. (line 5) +* mew-imap-user: imap. +* mew-inbox-action-alist: spam. (line 5) +* mew-init-hook: hooks. +* mew-lisp-max-length: auto-alias. (line 5) +* mew-lisp-max-length: by-from. (line 5) +* mew-lisp-max-length: by-thread. (line 5) +* mew-mail-address-list: reply. (line 5) +* mew-mail-domain-list: cheader. (line 5) +* mew-mailbox-type: config. (line 5) +* mew-mailbox-type: configuration. (line 5) +* mew-mailbox-type: retrieving. (line 5) +* mew-mailbox-type: start. (line 5) +* mew-make-message-hook: hooks. +* mew-mbox-command-arg: configuration. (line 5) +* mew-mbox-command: configuration. (line 5) +* mew-message-hook: hooks. +* mew-message-mode-hook: hooks. +* mew-mime-multipart-alternative-list: message-mode. (line 5) +* mew-name: configuration. (line 5) +* mew-nntp-header-only: nntp. +* mew-nntp-header-only: retrieving. (line 5) +* mew-nntp-msgid-domain: nntp. +* mew-nntp-msgid-user: nntp. +* mew-nntp-newsgroup: nntp. +* mew-nntp-sentinel-hook: hooks. +* mew-nntp-server: configuration. (line 5) +* mew-nntp-server: nntp. +* mew-nntp-size: nntp. +* mew-nntp-ssh-server: nntp. +* mew-nntp-ssl: nntp. +* mew-nntp-ssl-port: nntp. +* mew-nntp-user: nntp. +* mew-nntp2-flush-hook: hooks. +* mew-nntp2-sentinel-hook: hooks. +* mew-pack-hook: hooks. +* mew-pick-pattern-list: condition. (line 5) +* mew-pop-auth-list: pop. +* mew-pop-auth: pop. +* mew-pop-body-lines: pop. +* mew-pop-delete: pop. +* mew-pop-delete: retrieving. (line 5) +* mew-pop-header-only: pop. +* mew-pop-header-only: retrieving. (line 5) +* mew-pop-sentinel-hook: hooks. +* mew-pop-sentinel-non-biff-hook: hooks. +* mew-pop-server: pop. +* mew-pop-size: pop. +* mew-pop-ssh-server: SSH. (line 5) +* mew-pop-ssh-server: pop. +* mew-pop-ssl: SSL. (line 5) +* mew-pop-ssl: pop. +* mew-pop-ssl-port: SSL. (line 5) +* mew-pop-ssl-port: pop. +* mew-pop-user: configuration. (line 5) +* mew-pop-user: pop. +* mew-post-hook: hooks. +* mew-print-function: custom-misc. (line 5) +* mew-print-function: features. (line 5) +* mew-prog-gpg: cipher-viewing. (line 5) +* mew-prog-grep: condition. (line 5) +* mew-prog-grep-opts: condition. (line 5) +* mew-prog-msexcel-ext: message-mode. (line 5) +* mew-prog-msexcel: message-mode. (line 5) +* mew-prog-mspowerpoint-ext: message-mode. (line 5) +* mew-prog-mspowerpoint: message-mode. (line 5) +* mew-prog-msword-ext: message-mode. (line 5) +* mew-prog-msword: message-mode. (line 5) +* mew-prog-pgp: cipher-viewing. (line 5) +* mew-prog-pgp2: cipher-viewing. (line 5) +* mew-prog-pgp5: cipher-viewing. (line 5) +* mew-prog-text/html-ext: message-mode. (line 5) +* mew-protect-privacy-always: shortcut. (line 5) +* mew-protect-privacy-always-type: shortcut. (line 5) +* mew-protect-privacy-encrypted: shortcut. (line 5) +* mew-protect-privacy-encrypted-type: shortcut. (line 5) +* mew-protect-privacy-with-old-pgp-signature: shortcut. (line 5) +* mew-proto: config. (line 5) +* mew-proto: configuration. (line 5) +* mew-proto: start. (line 5) +* mew-quit-hook: hooks. +* mew-real-post-hook: hooks. +* mew-real-send-hook: hooks. +* mew-refile-auto-refile-skip-any-mark: auto-refile. (line 5) +* mew-refile-ctrl-multi: guess-rule. (line 5) +* mew-refile-guess-alist: by-alist. (line 5) +* mew-refile-guess-by-from-learn-hook: hooks. +* mew-refile-guess-control: guess-rule. (line 5) +* mew-refile-guess-from-me-is-special: by-from-folder. (line 5) +* mew-refile-guess-from-me-is-special: by-from. (line 5) +* mew-refile-guess-strip-domainpart: by-default. (line 5) +* mew-reply-all-alist: reply. (line 5) +* mew-reply-fromme-alist: reply. (line 5) +* mew-reply-sender-alist: reply. (line 5) +* mew-safe-addresses: addr-warn. (line 5) +* mew-safe-domains: addr-warn. (line 5) +* mew-scan-sentinel-hook: hooks. +* mew-search-method: dbsearch. (line 5) +* mew-send-hook: hooks. +* mew-signature-as-lastpart: cite. (line 5) +* mew-signature-file: cite. (line 5) +* mew-signature-insert-last: cite. (line 5) +* mew-smtp-auth-list: smtp. +* mew-smtp-flush-hook: hooks. +* mew-smtp-helo-domain: smtp. +* mew-smtp-mail-from: smtp. +* mew-smtp-msgid-domain: smtp. +* mew-smtp-msgid-user: smtp. +* mew-smtp-port: smtp. +* mew-smtp-sentinel-hook: hooks. +* mew-smtp-server: configuration. (line 5) +* mew-smtp-server: smtp. +* mew-smtp-ssh-server: smtp. +* mew-smtp-ssl: SSL. (line 5) +* mew-smtp-ssl-port: smtp. +* mew-smtp-ssl: smtp. +* mew-smtp-user: smtp. +* mew-sort-default-key-alist: sorting. (line 5) +* mew-sort-default-key: sorting. (line 5) +* mew-sort-hook: hooks. +* mew-sort-key-alist: sorting. (line 5) +* mew-spam-prog-args: spam2. (line 5) +* mew-spam-prog: spam2. (line 5) +* mew-spam: spam. (line 5) +* mew-ssl-cert-directory: SSL. (line 5) +* mew-ssl-verify-level: SSL. (line 5) +* mew-status-update-hook: hooks. +* mew-summary-delete-folder-hook: hooks. +* mew-summary-exec-hook: hooks. +* mew-summary-form-extract-rule: summary-mode. (line 5) +* mew-summary-form-from-me-prefix: summary-mode. (line 5) +* mew-summary-form-mark-delete: summary-mode. (line 5) +* mew-summary-form-mark-review: summary-mode. (line 5) +* mew-summary-form-mark-spam: summary-mode. (line 5) +* mew-summary-form: summary-mode. (line 5) +* mew-summary-ls-no-scan-hook: hooks. +* mew-summary-mark-direction: summary-mode. (line 5) +* mew-summary-mode-hook: hooks. +* mew-summary-rename-folder-hook: hooks. +* mew-summary-show-direction: summary-mode. (line 5) +* mew-summary-toggle-disp-msg-hook: hooks. +* mew-suspend-hook: hooks. +* mew-syntax-format-hook: hooks. +* mew-theme-file: highlight. (line 5) +* mew-thread-display-hook: hooks. +* mew-thread-separator: thread. (line 5) +* mew-trash-folder: delete mark. (line 5) +* mew-trash-folder-list: delete mark. (line 5) +* mew-use-8bit: smtp. +* mew-use-8bit: status-update. (line 5) +* mew-use-alternative: analysis. +* mew-use-biff-bell: biff. (line 5) +* mew-use-biff: biff. (line 5) +* mew-use-cached-passwd: password. (line 5) +* mew-use-cursor-mark: highlight. (line 5) +* mew-use-fast-refile: by-folder. (line 5) +* mew-use-format-flowed: longline. (line 5) +* mew-use-full-window: summary-mode. (line 5) +* mew-use-header-veil: features. (line 5) +* mew-use-header-veil: status-update. (line 5) +* mew-use-highlight-body: highlight. (line 5) +* mew-use-highlight-cursor-line: highlight. (line 5) +* mew-use-highlight-header: highlight. (line 5) +* mew-use-highlight-mark: highlight. (line 5) +* mew-use-highlight-mouse-line: highlight. (line 5) +* mew-use-highlight-url: highlight. (line 5) +* mew-use-highlight-x-face: highlight. (line 5) +* mew-use-master-passwd: password. (line 5) +* mew-use-node-folder: by-folder. (line 5) +* mew-use-old-pgp: shortcut. (line 5) +* mew-use-old-pgp: status-update. (line 5) +* mew-use-samba-encoding: custom-misc. (line 5) +* mew-use-smtp-auth: smtp. +* mew-use-text-body: analysis. +* mew-use-text/html: analysis. +* mew-use-text/xml: analysis. +* mew-use-thread-separator: thread. (line 5) +* mew-use-unread-mark: unread mark. (line 5) +* mew-user: configuration. (line 5) +* mew-virtual-mode-hook: hooks. +* mew-visit-inbox-after-setting-case: visiting. (line 5) +* mew-visit-queue-after-sending: visiting. (line 5) +* mew-warn-addresses: addr-warn. (line 5) +* mew-warn-domains: addr-warn. (line 5) +* mew-warning-field-level: status-update. (line 5) +* mew-x-pgp-key-list: cipher-viewing. (line 5) +* read-mail-command: configuration. (line 5) + + + + +File: mew.ja.info, Node: Key Index, Prev: Variable Index, Up: Top + +キー索引 +******** + + +* Menu: + +* A (Summary): Composing. (line 5) +* A (Summary): reply. (line 5) +* A (Summary): sum-write. (line 5) +* B (Attach): mark-b-comp. (line 5) +* B (Summary): features. (line 5) +* C (Attach): charset-guess. (line 5) +* C (Attach): mime-comp. (line 5) +* C (Summary): features. (line 5) +* C-b (Attach): mime-comp. (line 5) +* C-cC-a (Draft): mime-comp. (line 5) +* C-cC-a (Summary): addrbook. (line 5) +* C-cC-a (Summary): features. (line 5) +* C-cC-b (Draft): shortcut. (line 5) +* C-cC-c (Addrbook): addrbook. (line 5) +* C-cC-c (Draft): send. (line 5) +* C-cC-c (Edit): edit. (line 5) +* C-cC-c (Header): resend. (line 5) +* C-cC-c (Summary): off-line. (line 5) +* C-cC-c (Summary): send. (line 5) +* C-cC-e (Draft): shortcut. (line 5) +* C-cC-e (Summary): message-mode. (line 5) +* C-cC-f (Draft): longline. (line 5) +* C-cC-f (Summary): cipher-viewing. (line 5) +* C-cC-l (Draft): cite. (line 5) +* C-cC-l (Summary): invalid. (line 5) +* C-cC-m (Draft): send. (line 5) +* C-cC-m (Edit): edit. (line 5) +* C-cC-m (Header): resend. (line 5) +* C-cC-o (Draft): config. (line 5) +* C-cC-o (Summary): visiting. (line 5) +* C-cC-pC-a (Draft): shortcut. (line 5) +* C-cC-pC-e (Draft): shortcut. (line 5) +* C-cC-pC-f (Draft): longline. (line 5) +* C-cC-pC-m (Draft): shortcut. (line 5) +* C-cC-q (Addrbook): Quit. (line 5) +* C-cC-q (Addrbook): addrbook. (line 5) +* C-cC-q (Draft): Quit. (line 5) +* C-cC-q (Header): Quit. (line 5) +* C-cC-q (Summary): Quit. (line 5) +* C-cC-r (Draft): shortcut. (line 5) +* C-cC-r (Summary): features. (line 5) +* C-cC-s (Draft): shortcut. (line 5) +* C-cC-s (Summary): features. (line 5) +* C-cC-t (Draft): cite. (line 5) +* C-cC-v (Summary): cipher-viewing. (line 5) +* C-cC-v (Summary): features. (line 5) +* C-cC-y (Draft): cite. (line 5) +* C-cC-z (Summary): cipher-viewing. (line 5) +* C-cC-z (Summary): features. (line 5) +* C-cTAB (Draft): cheader. (line 5) +* C-cTAB (Draft): cite. (line 5) +* C-cTAB (Summary): analysis. (line 5) +* C-f (Attach): mime-comp. (line 5) +* C-n (Attach): mime-comp. (line 5) +* C-n (Summary): singlepart. (line 5) +* C-p (Attach): mime-comp. (line 5) +* C-p (Summary): singlepart. (line 5) +* C-u: (Summary): analysis. (line 5) +* C-u. (Summary): analysis. (line 5) +* C-u. (Summary): invalid. (line 5) +* C-u/ (Summary): search. (line 5) +* C-u? (Summary): search. (line 5) +* C-uA (Summary): reply. (line 5) +* C-uC-cC-a (Summary): addrbook. (line 5) +* C-uC-cC-e (Summary): message-mode. (line 5) +* C-uC-cC-f (Summary): cipher-viewing. (line 5) +* C-uC-cC-l (Summary): invalid. (line 5) +* C-uD (Summary): delete mark. (line 5) +* C-uD (Summary): features. (line 5) +* C-uM-n (Summary): keyword. (line 5) +* C-uM-o (Summary): auto-refile. (line 5) +* C-uM-p (Summary): keyword. (line 5) +* C-uM-x mew: start. (line 5) +* C-uSPC (Summary): singlepart. (line 5) +* C-uZ (Summary): status-update. (line 5) +* C-ua (Summary): reply. (line 5) +* C-uj (Summary): singlepart. (line 5) +* C-uk/ (Summary): search. (line 5) +* C-ukI (Summary): dialog. (line 5) +* C-umI (Summary): target mark. (line 5) +* C-un (Summary): singlepart. (line 5) +* C-up (Summary): singlepart. (line 5) +* C-us (Summary): retrieving. (line 5) +* C-utt (Summary): thread. (line 5) +* C-uw (Summary): sum-write. (line 5) +* C-x RET l: charset-guess. (line 5) +* C-xm: Composing. (line 5) +* C-xm: start. (line 5) +* D (Attach): mime-comp. (line 5) +* D (Summary): delete mark. (line 5) +* D (Summary): features. (line 5) +* DEL (Summary): singlepart. (line 5) +* E (Attach): mark-b-comp. (line 5) +* E (Summary): sum-write. (line 5) +* F (Attach): mime-comp. (line 5) +* F (Summary): Composing. (line 5) +* F (Summary): forward. (line 5) +* F (Summary): sum-write. (line 5) +* F (Summary): target mark. (line 5) +* G (Attach): mark-b-comp. (line 5) +* I (Attach): charset-guess. (line 5) +* I (Summary): retrieving. (line 5) +* J (Summary): target mark. (line 5) +* M-RET (Summary): singlepart. (line 5) +* M-\ (Summary): target mark. (line 5) +* M* (Summary): unmark. (line 5) +* M-b (Summary): target mark. (line 5) +* M-d (Summary): delete mark. (line 5) +* M-e (Attach): mark-b-comp. (line 5) +* M-e: edit. (line 5) +* M-l (Summary): features. (line 5) +* M-n (Summary): keyword. (line 5) +* M-o (Summary): auto-refile. (line 5) +* M-p (Summary): keyword. (line 5) +* M-s (Attach): mark-b-comp. (line 5) +* M-s (Summary): sorting. (line 5) +* M-t (Summary): target mark. (line 5) +* M-u: unread mark. (line 5) +* M-x mew: Viewing. (line 5) +* M-x mew-send: Composing. (line 5) +* M-x mew-send: start. (line 5) +* M-x mew: start. (line 5) +* Md (Summary): delete mark. (line 5) +* N (Summary): target mark. (line 5) +* P (Attach): mime-comp. (line 5) +* P (Summary): target mark. (line 5) +* Q (Attach): mark-b-comp. (line 5) +* Q (Summary): Quit. (line 5) +* RET (Summary): singlepart. (line 5) +* Rd (Summary): features. (line 5) +* Rr (Summary): features. (line 5) +* S (Attach): mark-b-comp. (line 5) +* S (Summary): sorting. (line 5) +* SPC (Summary): singlepart. (line 5) +* : (Summary): analysis. (line 5) +* , (Summary): analysis. (line 5) +* . (Summary): analysis. (line 5) +* ; (Summary): features. (line 5) +* = (Summary): features. (line 5) +* | (Summary): features. (line 5) +* # (Summary): features. (line 5) +* _ (Summary): features. (line 5) +* _ (Summary): longline. (line 5) +* / (Summary): search. (line 5) +* ? (Summary): search. (line 5) +* - (Summary): singlepart. (line 5) +* * (Summary): target mark. (line 5) +* T (Attach): mime-comp. (line 5) +* TAB (Draft): header. (line 5) +* U (Attach): mark-b-comp. (line 5) +* U (Summary): unmark. (line 5) +* V (Summary): dialog. (line 5) +* ) (Virtual): thread. (line 5) +* ( (Virtual): thread. (line 5) +* & (Virtual): thread. (line 5) +* ^ (Virtual): thread. (line 5) +* W (Summary): resend. (line 5) +* W (Summary): sum-write. (line 5) +* Z (Attach): mark-b-comp. (line 5) +* Z (Summary): auto-alias. (line 5) +* Z (Summary): status-update. (line 5) +* a (Attach): mime-comp. (line 5) +* a (Summary): Composing. (line 5) +* a (Summary): reply. (line 5) +* a (Summary): sum-write. (line 5) +* b (Summary): features. (line 5) +* c (Attach): mime-comp. (line 5) +* d (Attach): mime-comp. (line 5) +* d (Summary): delete mark. (line 5) +* e (Attach): mime-comp. (line 5) +* f (Attach): mime-comp. (line 5) +* f (Summary): Composing. (line 5) +* f (Summary): forward. (line 5) +* f (Summary): sum-write. (line 5) +* g (Summary): moving. (line 5) +* i (Attach): mime-comp. (line 5) +* i (Summary): retrieving. (line 5) +* i (Summary): send. (line 5) +* j (Summary): singlepart. (line 5) +* k/ (Summary): search. (line 5) +* k? (Summary): search. (line 5) +* kI (Summary): dialog. (line 5) +* kM: dbsearch. (line 5) +* kc: dbsearch. (line 5) +* km: dbsearch. (line 5) +* lc (Summary): copy-msg. (line 5) +* lh (Summary): spam2. (line 5) +* li (Summary): copy-msg. (line 5) +* ls (Summary): spam2. (line 5) +* lx: off-line. (line 5) +* m (Attach): mime-comp. (line 5) +* m* (Summary): mark change. (line 5) +* m$ (Summary): mark change. (line 5) +* m*: escape mark. (line 5) +* m$: escape mark. (line 5) +* mI (Summary): target mark. (line 5) +* mM-d (Summary): delete mark. (line 5) +* mM-d (Summary): mark change. (line 5) +* mM-u (Summary): mark change. (line 5) +* ma (Summary): target mark. (line 5) +* mc (Summary): mark change. (line 5) +* md (Summary): delete mark. (line 5) +* md (Summary): mark change. (line 5) +* mlc (Summary): copy-msg. (line 5) +* mli (Summary): copy-msg. (line 5) +* mo (Summary): mark change. (line 5) +* mr (Summary): target mark. (line 5) +* ms (Summary): mark change. (line 5) +* mt (Summary): thread. (line 5) +* mxM-d (Summary): delete mark. (line 5) +* mxd (Summary): delete mark. (line 5) +* n (Summary): singlepart. (line 5) +* o (Summary): refile mark. (line 5) +* p (Attach): mime-comp. (line 5) +* p (Attach): pgp-key. (line 5) +* p (Summary): singlepart. (line 5) +* q (Summary): Quit. (line 5) +* r (Summary): resend. (line 5) +* s (Summary): off-line. (line 5) +* s (Summary): retrieving. (line 5) +* t (Attach): mime-comp. (line 5) +* t (Virtual): thread. (line 5) +* t* (Virtual): thread. (line 5) +* tM-d (Virtual): thread. (line 5) +* tSPC (Virtual): thread. (line 5) +* ta (Virtual): thread. (line 5) +* td (Virtual): thread. (line 5) +* tg (Virtual): thread. (line 5) +* tn (Virtual): thread. (line 5) +* to (Virtual): thread. (line 5) +* tp (Virtual): thread. (line 5) +* tr (Summary): thread. (line 5) +* tt (Summary): thread. (line 5) +* tu (Virtual): thread. (line 5) +* u (Summary): unmark. (line 5) +* v (Summary): features. (line 5) +* w (Summary): Composing. (line 5) +* w (Summary): sum-write. (line 5) +* x (Summary): Marks. (line 5) +* x (Summary): delete mark. (line 5) +* x (Summary): unmark. (line 5) +* y (Attach): mime-comp. (line 5) +* y (Summary): features. (line 5) +* z8 (Summary): status-update. (line 5) +* zSPC: unread mark. (line 5) +* zc (Summary): status-update. (line 5) +* zd (Summary): status-update. (line 5) +* zo (Summary): status-update. (line 5) +* zp (Summary): status-update. (line 5) +* zv (Summary): features. (line 5) +* zv (Summary): status-update. (line 5) +* zw (Summary): status-update. (line 5) +* zz (Summary): message-mode. (line 5) + diff --git a/elpa/mew-readme.txt b/elpa/mew-readme.txt new file mode 100644 index 00000000..866278c7 --- /dev/null +++ b/elpa/mew-readme.txt @@ -0,0 +1,4 @@ +The updated version is available from: + http://www.Mew.org/ + +See info for configuring a site file/.emacs/.mew.el. -- 2.47.3