\documentstyle[a4j]{jreport}

\title{tm 説明書}
\author{守岡 知彦\\
  morioka@jaist.ac.jp}
\date{\verb$Id: tm-jp.tex,v 5.5 1994/10/20 01:42:29 morioka Exp $}

\begin{document}

\maketitle
\tableofcontents

\chapter{はじめに}

tm は GNU Emacs で MIME を楽しむための package です。tm を使うと、

\begin{itemize}
\item mime/viewer-mode を使った MIME message の閲覧・再生
\item 多言語 header の encode/decode
\item mh-e, GNUS, RMAIL での MIME 機能の強化
\end{itemize}

\noindent が行なえます。


\section{Module 一覧}

tm は以下の module からなります。

\begin{itemize}
\item {\bf tiny-mime} : MIME header encoder/decoder
\item {\bf tm-view} : MIME viewer
\item {\bf tm-misc} : tm-MUA の共通 module
\item {\bf tm-MUAs} : MUA の MIME 機能強化 module
  \begin{itemize}
  \item {\bf tm-mh-e} : mh-e 用の tm-MUA
  \item {\bf tm-gnus} : GNUS 用の tm-MUA
  \item {\bf tm-rmail} : RMAIL 用の tm-MUA
  \item {\bf tm-vm} : vm 用の tm-MUA
  \end{itemize}
\item {\bf tm-setup} tm-MUA の設定 module
\item {\bf mime-setup} MIME 関係の設定 module
\end{itemize}


\chapter{Emacs version 別の機能および制限}

\section{Emacs (original)}

Original の Emacs では、US-ASCII と ISO-8859-1 が使えます。


\section{NEmacs, NEpoch}

NEmacs では、ISO-2022-JP および US-ASCII が使えます。


\section{Mule}

ISO-2022-JP, ISO-2022-JP-2, US-ASCII, ISO-8859-1..9, ISO-2022-CN,
ISO-2022-KR, EUC-KR などの多言語 header が使えます。また、関数 
mime/set-charset-and-encoding で追加・変更ができます。


\chapter{Install と設定}

\section{Install}

Install は次の手順で行ないます。

\begin{enumerate}
\item Makefile の bindir を自分の環境に合わせて書き換える。
\item methods/ 以下にある method script を \ref{sec:method} 節を参照し
  て、自分の環境に合うように書き換える。
\item make all する。
\item make install する。
\item *.el を Emacs の変数 load-path で指定された directory に copy する。
\end{enumerate}

\noindent{\bf [注意]}
\begin{itemize}
\item tm-mh-e3.el を byte-compile する場合は、mh-e version 3.* を load 
  した状態で行なって下さい。
\item tm-gnus3.el を byte-compile する場合は、GNUS 3 が load された状
  態で行なって下さい。
\item tl-18.el を byte-compile する場合は、Emacs 18 で行なって下さい。
\item tl-orig.el を byte-compile する場合は、original Emacs で行なって
  下さい。
\item tl-nemacs.el を byte-compile する場合は、NEmacs で行なって下さい。
\item tl-mule.el を byte-compile する場合は、Mule で行なって下さい。
\item Emacs 19 で byte-compile した module は Emacs 18 では動きません。
\end{itemize}


\section{設定}

この package には mime-setup.el と tm-setup.el という簡易設定 file が
附属しています。mime-setup.el では encoding も含めた設定を行ない、
tm-setup では tm-MUA に関する設定のみを行ないます。

\subsection{mime-setup}

\begin{verbatim}
(load "mime-setup")
\end{verbatim}

\noindent とすると MIME に関する各種設定を行ないます。mime-setup は 
tm-setup を読んでいるので、mime-setup を使う場合、tm-setup を load す
る必要はありません。

mime-setup では signature の自動切替え tool も附属しています。
message header の field に合わせて signature の自動切替を行ないたい場
合は .emacs に以下のようなものを入れて下さい。（詳しくは signature.el 
の説明書を参照して下さい）

\begin{verbatim}
(setq signature-file-alist
      '((("Newsgroups" . "jokes")       . "~/.signature-jokes")
        (("Newsgroups" . ("zxr" "nzr")) . "~/.signature-sun")
        (("To" . ("ishimaru" "z-suzuki")) . "~/.signature-sun")
        (("To" . "tea")                 . "~/.signature-jokes")
        (("To" . ("sim" "oku" "takuo")) . "~/.signature-formal")
        ))
\end{verbatim}

mime-setup を使う場合は、mime.el が必要です。また、SuperCite を使う場
合は、SuperCite も必要です。


\subsection{tm-setup}

tm-setup は tm-MUA の設定のみを行なう module です。mime-setup を load 
している場合、これを陽に load する必要はありませんが、mime-setup を使
いたくない場合、以下のようにこれを load して下さい。

\begin{verbatim}
(load "tm-setup")
\end{verbatim}


\subsection{vm}

vm を使う場合は .vm か .emacs に

\begin{verbatim}
(load "tm-vm")
\end{verbatim}

\noindent を入れて下さい。


\subsection{設定 file を使わない場合}

tm-setup.el を参考にして下さい。


\subsection{MH の設定}

また、MH が MH-6.8JP2 の場合、.mh\_profile に

\begin{verbatim}
scan:   -form scan.mime
inc:    -form inc.mime
repl:   -form replcomps.mime
showproc: mhl
\end{verbatim}

\noindent を追加してください。また、それ以外の MH の処理は Emacs の側
で取り仕切るので、MH の設定はしないようにしてください。


\chapter{tm-MUA}

``tm-MUA'' というのは、mh-e, GNUS, RMAIL などの MUA のための MIME 機能
強化 module の総称です。

現在、tm-MUA には、

\begin{itemize}
\item {\bf tm-mh-e} : mh-e 用の tm-MUA
\item {\bf tm-gnus} : GNUS 用の tm-MUA
\item {\bf tm-rmail} : RMAIL 用の tm-MUA
\item {\bf tm-vm} : VM 用の tm-MUA
\end{itemize}

\noindent があります。この章ではこれらの module に関して説明します。


\section{Summary mode}

tm-MUA を使うと、元の MUA の Summary mode に対して以下の機能が追加され
ます。

\medskip
\begin{center}
  \begin{tabular}{|l|l|}\hline
    key & 機能 \\ \hline
    M-t & MIME header の decode に関する toggle \\
    v   & 本文に入り、mime/view-mode に移る \\ \hline
  \end{tabular}
\end{center}
\medskip


\section{mime/viewer-mode}
\label{sec:mime/viewer-mode}

tm-MUA を使うと、Summary mode で {\bf v} （vm では {\bf Z}）を押すこと
によって、mime/viewer-mode という MIME message を閲覧するための mode 
に入ります。mime/viewer-mode には以下の機能があります。

\medskip
\begin{center}
  \begin{tabular}{|l|l|}\hline
    key     & 機能 \\ \hline
    u       & 上の content に戻る \\
            & message の一番上の content でこれを行なうと Summary mode 
              に戻る (*1) \\
    p       & 前の content に移動する \\
    n       & 次の content に移動する \\
    SPC     & scroll up する \\
    M-SPC   & scroll down する \\
    DEL     & scroll down する \\
    RET     & 次の行に移動する \\
    M-RET   & 前の行に移動する \\
    v       & content を再生する           (*2) \\
    e       & content から file を取り出す (*2) \\
    C-c C-p & content を印刷する           (*2) \\ \hline
  \end{tabular}
\end{center}
\medskip

\bigskip

\newcounter{asteriskcount}
\noindent{\bf ［注意］}
\vspace{-1ex}
{\list{(*\arabic{asteriskcount})}{\usecounter{asteriskcount}\leftmargin=8ex}
\item tm-mh-e, tm-gnus, tm-rmail などで tm-view の設定をしていない場合、
  Summary mode には戻りません。
\item 実際の動作は対応する method に依ります。
\endlist}


\section{tm-gnus の customize}

\subsection{article を save する時 decoding しない}

article を save する時、保存される message はその時表示されているよう
に、その時の MIME header decoding mode に応じて save されます。

しかし、article を save する時、常に、MIME header decoding を行なわな
い、生の message で保存したい場合は、変数 
tm-gnus/set-mime-header-decoding-mode の値を nil にして、MIME header
decoding を行なわない mode にして、article save 関数を実行するように設
定して下さい。

Save の実行後、MIME header decoding mode を前の状態に戻したい場合は、
以下のように、一時変数に MIME header decoding mode を保存しておけば OK
です。

\begin{verbatim}
        (let ((mm mime/header-decoding-mode))
          (tm-gnus/set-mime-header-decoding-mode nil)
          (article save 関数)
          (tm-gnus/set-mime-header-decoding-mode mm)
          )
\end{verbatim}

以下に、mh-e の folder に save する場合の例を示します。

\begin{verbatim}
(add-hook 'gnus-Startup-hook
          (function
           (lambda ()
             (setq gnus-default-article-saver
                   (function
                    (lambda ()
                      (interactive)
                      (let ((mm mime/header-decoding-mode))
                        (tm-gnus/set-mime-header-decoding-mode nil)
                        (gnus-Subject-save-in-folder)
                        (tm-gnus/set-mime-header-decoding-mode mm)
                        )))))))
(add-hook 'gnus-startup-hook
          (function
           (lambda ()
             (setq gnus-default-article-saver
                   (function
                    (lambda ()
                      (interactive)
                      (let ((mm mime/header-decoding-mode))
                        (tm-gnus/set-mime-header-decoding-mode nil)
                        (gnus-summary-save-in-folder)
                        (tm-gnus/set-mime-header-decoding-mode mm)
                        )))))))
\end{verbatim}

\subsection{reply する時 Subject の encoding 法を reply 元に合わせる}

Reply する時、reply 元の Subject に ASCII 以外の文字集合の入っている
場合、reply 元が MIME encode されていたら encode し、そうでなかったら
生で入れたい場合は、次のように設定します。

\begin{verbatim}
(add-hook 'gnus-article-prepare-hook
          (function
           (lambda ()
             (if (mime/exist-encoded-word-in-subject)
                 (setq mime/no-encoding-header-fields '("X-Nsubject"))
               (setq mime/no-encoding-header-fields '("X-Nsubject" "Subject"))
               ))))
\end{verbatim}


\chapter{tm-view}

tm-view は MIME message を閲覧するための機能を提供する module です。
tm-view は mime/viewer-mode という mode を提供します。

mime/viewer-mode の機能に関しては、\ref{sec:mime/viewer-mode} 節を参照
して下さい。

\section{content の decode 条件の設定}

変数 mime/content-decoding-condition は decode 時の method を指定する
ための変数で、tm-view 4 の変数 mime/content-decoding-method-alist に相
当します。

変数 mime/content-decoding-method-alist では、単に 
content-type/subtype に対する method を指定することしかできませんでし
たが、変数 mime/content-decoding-condition では decode 時の制約条件を
書くことができます。

変数 mime/content-decoding-condition は、

\begin{eqnarray*}
  (条件_1 \;\; 条件_2 \;\; ...)
\end{eqnarray*}

\noindent という形をした list で、各条件は

\begin{eqnarray*}
  ((field-type_1 \; . \; value_1) \;\;
  (field-type_2 \; . \; value_2) \;\; ...)
\end{eqnarray*}

\noindent という形の連想 list になっています。

例えば、text/plain の時、tm-plain を起動する時、

\begin{quote}
  ((type . "text/plain")
  (method "tm-plain" nil 'file 'type 'encoding 'mode 'name))
\end{quote}

\noindent という条件を書きます。見ての通り、外部 method の引数が書ける
ようになりました。詳しくは \ref{sec:method-arguments} 節で述べます。

この条件は text/plain である content なら全ての decoding-mode で有効で
す。しかし、

\begin{quote}
  ((type . "text/plain")
  (method "tm-plain" nil 'file 'type 'encoding 'mode 'name)
  (mode . "play"))
\end{quote}

\noindent なら、play mode 以外では有効ではありません。

逆に、

\begin{quote}
  ((method "metamail" t "-m" "tm" "-x" "-d" "-z" "-e" 'file)
  (mode . "play"))
\end{quote}

\noindent なら、全ての content-type の play mode で有効になります。

こうして各条件を前から見て行き、最初に有効になった条件が実行されます。


\subsection{method の引数の指定の仕方}
\label{sec:method-arguments}

条件の method field は

\begin{eqnarray*}
  (method \; . \; SYMBOL)
\end{eqnarray*}

\noindent か

\begin{eqnarray*}
  (method \; 文字列 \; FLAG \; 引数_1 \; 引数_2 \; ...)
\end{eqnarray*}

\noindent という形をしています。

method field の値が symbol である場合は、内部 method として起動されま
す。

method field の値が list である場合、外部 method として起動されます。
この場合、

\begin{quote}
  \begin{tabular}{lcl}
    文字列&:&外部 method の名前 \\
    FLAG&:& t なら content header も外部 method に渡す。
    nil なら content body のみを渡す。\\
    引数列&:&外部 method の引数
  \end{tabular}
\end{quote}

\noindent と解釈されます。

また、外部 method の引数は次のような形式で書きます。

\begin{quote}
  \begin{tabular}{lcl}
    文字列&:&その文字列を渡す \\
    'SYMBOL&:&SYMBOL を key とした値を渡す\\
    '文字列&:&文字列を key とした値を渡す
  \end{tabular}
\end{quote}

'SYMBOL で指定できるものには、

\begin{quote}
  \begin{tabular}{lcl}
    'file&:&content を渡すための file 名 \\
    'type&:&content-type/sub-type 名 \\
    'encoding&:&content-transfer-encoding \\
    'mode&:&decoding mode \\
    'name&:&file に落す場合の file 名
  \end{tabular}
\end{quote}

\noindent などがあり、'文字列 では Content-Type field の parameter の
値が指定できます。


\subsection{例}

初期値は以下になっています。

\begin{verbatim}
(defvar mime/content-decoding-condition
  '(((type . "text/plain")
     (method "tm-plain" nil 'file 'type 'encoding 'mode 'name))
    ((type . "text/x-latex")
     (method "tm-latex" nil 'file 'type 'encoding 'mode 'name))
    ((type . "audio/basic")
     (method "tm-au"    nil 'file 'type 'encoding 'mode 'name))
    ((type . "image/gif")
     (method "tm-image" nil 'file 'type 'encoding 'mode 'name))
    ((type . "image/jpeg")
     (method "tm-image" nil 'file 'type 'encoding 'mode 'name))
    ((type . "image/tiff")
     (method "tm-image" nil 'file 'type 'encoding 'mode 'name))
    ((type . "image/x-tiff")
     (method "tm-image" nil 'file 'type 'encoding 'mode 'name))
    ((type . "image/x-xbm")
     (method "tm-image" nil 'file 'type 'encoding 'mode 'name))
    ((type . "image/x-pic")
     (method "tm-image" nil 'file 'type 'encoding 'mode 'name))
    ((type . "video/mpeg")`
     (method "tm-mpeg"  nil 'file 'type 'encoding 'mode 'name))
    ((type . "application/octet-stream")
     (method "tm-file"  nil 'file 'type 'encoding 'mode 'name))
    ((type . "message/partial")
     (method . mime/decode-message/partial-region))
    ((method "metamail" t
             "-m" "tm" "-x" "-d" "-z" "-e" 'file)(mode . "play"))
    ))
\end{verbatim}

例えば、「全部 metamail 使うんや」という場合、

\begin{verbatim}
(setq mime/content-decoding-condition
      '(
        ((method "metamail" t "-m" "tm" "-x" "-d" "-z" "-e" 'file))
       ))
\end{verbatim}

\noindent とすれば OK です。

工夫すれば、かなり複雑な条件が書けるでしょう。


\section{method script}
\label{sec:method}

各 method は shell script で書きます。tm-verw.el から渡される引数は、
変数 mime/content-decoding-condition で指定できますが、標準的な引数列
は以下の通りです。

\medskip
\begin{center}
  \begin{tabular}{|c|l|} \hline
    引数 & \multicolumn{1}{|c|}{ 値 }\\ \hline
    \$1  & decode 前の file 名          \\
    \$2  & Content-Type (type/sub-type) \\
    \$3  & encoding
    \{7bit / quoted-printable / base64 / 8bit / binary / ...\}\\
    \$4  & decoding-mode \{play / extract / print\}           \\
    \$5  & file 名                                            \\ \hline
  \end{tabular}
\end{center}
\medskip

また、message/partial だけは tm-view.el 自身で復元します。


\section{表示}

mime/viewer-mode に入ると、各 content は preview buffer に

\begin{verbatim}
[1 (text/plain)]

本文
\end{verbatim}

\noindent のように加工されて表示されます。tm-view では content を表示
する際、

\begin{itemize}
\item content subject
\item content header
\item content body
\end{itemize}

\noindent という３つの部分に分けて扱われます。


\subsection{content subject}

content subject は preview buffer で content の先頭を表すための部分で、
標準では、

\begin{quote}
  [cid 題名 (型)]
\end{quote}

\noindent のように表示されます。cid は message の中での content の位置
を表すもので、節番号のようなものです。題名は、Subject や 
Content-Description などに書かれた文字列から作られます。型は 
Content-Type に書かれた type/subtype のことです。

この content subject の表示は変数 mime/make-content-subject-function 
によって設定できます。既定値は、

\begin{verbatim}
(defvar mime/make-content-subject-function
  (function
   (lambda (cid subj ctype)
     (insert
      (format "[%s %s (%s)]\n"
              (if (listp cid)
                  (mapconcat (function
                              (lambda (num)
                                (format "%s" (+ num 1))
                                ))
                             cid ".")
                "0")
              subj (car ctype)))
     )))
\end{verbatim}

\noindent となっていますが、例えば、

\begin{verbatim}
(setq mime/make-content-subject-function
      (function
       (lambda (cid subj ctype)
         (if (not (member (car ctype) mime/default-showing-Content-Type-list))
             (insert
              (format "[%s %s (%s)]\n"
                      (if (listp cid)
                          (mapconcat (function
                                      (lambda (num)
                                        (format "%s" (+ num 1))
                                        ))
                                     cid ".")
                        "0")
                      subj (car ctype))))
         )))
\end{verbatim}

\noindent とすれば隠された content だけ content subject を表示するよう
にできます。


\subsection{content header}

content header は preview buffer で content header を表示するための部
分です。標準では空行になります。

この content header の表示は変数 mime/make-content-header-filter によっ
て設定できます。既定値は、

\begin{verbatim}
(defvar mime/make-content-header-filter
  (function
   (lambda (cid)
     (if (listp cid)
         (delete-region (goto-char (point-min))
                        (or (and (re-search-forward "^$" nil t)
                                 (match-end 0))
                            (point-max))
                        )
       )
     )))
\end{verbatim}

\noindent となっており、content header を body との境の空行まで削除す
るという風になっています。例えば、

\begin{verbatim}
(setq mime/make-content-header-filter
  (function
   (lambda (cid)
    )))
\end{verbatim}

\noindent とすれば、全ての content header field を表示できます。


\subsection{content body}

preview buffer に content body を表示する際、content-type 毎に

\begin{enumerate}
\item 隠蔽
\item 加工
\end{enumerate}

\noindent という処理が行なわれます。

隠蔽は非 text part を隠すための処理で、変数 
mime/default-showing-Content-Type-list に設定された content-type 以外
の content が隠蔽されます。この変数の既定値は、

\begin{verbatim}
(defvar mime/default-showing-Content-Type-list
  '("text/plain" "text/richtext" "text/enriched" "text/x-latex" nil))
\end{verbatim}

\noindent で、text/plain, text/richtext, text/enriched, text/x-latex, 
及び、非 MIME content のみが表示され、それ以外は、隠蔽されます。

隠蔽されなかった content に対して、加工処理が行なわれます。その 
content の content-type を key にして変数 mime/content-filter-alist を
引き、その値部に書かれた関数が実行されます。

変数 mime/content-filter-alist の既定値は nil ですが、tm-rich.el を 
load すると、

\begin{verbatim}
(aput 'mime/content-filter-alist
      "text/enriched" (function mime/decode-text/enriched-body))
\end{verbatim}

\noindent のように text/enriched に対する加工処理が設定されます。


\section{制限}

附属の BASE64 decoder である decode-b.c はいい加減な作りなので、動かな
かったら、短いプログラムなので、意を汲んで修正して下さい。
(\verb+^+\_\verb+^+;

また、metamail 附属の mmencode を使って decode しても良いでしょう。

また、Quoted-Printable の decoder は附属しませんので、mmencode を使っ
て下さい。


\chapter{tiny-mime}

tiny-mime は Mule, NEmacs, NEpoch 上で動作する MIME header の 
encoder/decoder です。tiny-mime は、昔、えなみ つぐとも さんが 
fj.editor.emacs に投稿された ISO-2022-JP MIME header decoder を元にし
ています。

現在では、当時のものに比べ、

\begin{itemize}
\item decoding 時における unfolding 機能の追加
\item ISO-2022-JP に加え、ISO-2022-KR, ISO-8859-*, US-ASCII などの多言
  語 header の encode/decode 機能の追加
\item Q-encoding の追加
\item RFC 1522 への対応
\end{itemize}

\noindent といった機能強化が行なわれています。

tiny-mime は tm における MIME header encoder/decoder であり、tm-view,
tm-MUA がこれを利用しています。


\section{mime/decode-message-header}

{\tt mime/decode-message-header} は MIME header を decode するための命
令です。tiny-mime が load されている状態で、decode したい buffer の上
で、

{\list{}{\leftmargin=8ex}\item[]
\par
M-x {\tt mime/decode-message-header}
\endlist}

\noindent を実行すると、その buffer 上の MIME header が decode されま
す。

tm-MUA や tm-view はこの命令を呼んでいるので、これらを利用している場合、
陽にこの命令を実行する必要は無いでしょう。


\section{mime/decode-region}

region に対して、

{\list{}{\leftmargin=8ex}\item[]
\par
M-x {\tt mime/decode-region}
\endlist}

\noindent を実行することで、引用などで buffer に残った MIME header を 
decode できます。


\chapter{バグ報告の仕方}

tm のバグを見つけたら fj.editor.emacs に post するか、tm ML
$<$tm@chamonix.jaist.ac.jp$>$ に mail を送って下さい。

tm ML では tm のバグ情報の交換や最新版の配布、tm の改良に関する議論を
行なっています。tm ML に参加したい方は

\begin{center}
  tm-admin@chamonix.jaist.ac.jp
\end{center}

\noindent まで mail を送って下さい。登録は手動ですので、できれば、自然
言語で書いて下さい。(\verb+^+\_\verb+^+)

\end{document}
