diff -urN tiarra-20040309/ChangeLog tiarra-20040313/ChangeLog
--- tiarra-20040309/ChangeLog	2004-03-09 17:03:45.000000000 +0900
+++ tiarra-20040313/ChangeLog	2004-03-13 22:23:39.000000000 +0900
@@ -1,3 +1,26 @@
+2004-03-13  phonohawk  <phonohawk@ps.sakura.ne.jp>
+
+	* main/Hook.pm (Hook::call, HookTarget::call_hooks):
+	フック関数に引数を渡せるように変更。
+
+	* main/RunLoop.pm:
+	Hook.pmで一般化したためにコメントアウトしてあったフック関連のコードを削除。
+
+	* main/IrcIO/Client.pm (inform_joinning_channels):
+	チャンネル情報一つ転送される度に呼ばれるフック channel-info を定義。
+	このフックには引数としてIrcIO::Client自身とチャンネル名が渡される。
+	フッククラスは同ファイルで定義されるIrcIO::Client::Hook。
+
+	* module/Log/Recent/pm:
+	クライアントに送られるチャンネルと同じ順番でログも送るように変更。
+	この動作はIrcIO::Clientのフックを利用している。
+
+	* main/RunLoop.pm (run):
+	Tiarra暴走検出のコードにバグがあったので修正。
+	0秒selectに2秒以上の間隔が開いた場合にはカウンタをリセットする意図があったと思うが
+	2秒*以下*の間隔でリセットしていた。
+	ついでなので警告の閾値も300まで引き上げ。
+
 2004-03-09  Topia  <topia@clovery.jp>
 
 	* module/Client/Cache.pm:
@@ -1454,7 +1477,7 @@
 
 	* これ以前のログは書いていません。
 
-#       Id: $Id: ChangeLog,v 1.136 2004/03/09 07:48:12 topia Exp $
-#   Author: $Author: topia $
-#     Date: $Date: 2004/03/09 07:48:12 $
-# Revision: $Revision: 1.136 $
+#       Id: $Id: ChangeLog,v 1.138 2004/03/13 07:17:33 admin Exp $
+#   Author: $Author: admin $
+#     Date: $Date: 2004/03/13 07:17:33 $
+# Revision: $Revision: 1.138 $
diff -urN tiarra-20040309/doc/default.css tiarra-20040313/doc/default.css
--- tiarra-20040309/doc/default.css	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/default.css	2004-03-13 22:23:40.000000000 +0900
@@ -0,0 +1,86 @@
+/* $Id: default.css,v 1.1 2003/08/04 09:29:21 admin Exp $ */
+
+body {
+  background-color: #ffac6a;
+  color: #000000;
+  font-style: normal;
+  font-size: 14px;
+  text-align: left;
+  text-indent: 0px;
+  padding: 20px 30px;
+  margin: 0px;
+}
+
+/* general */
+a {
+    text-decoration: underline;
+}
+a:link {
+    color: #c70800;
+}
+a:visited {
+    color: #a25a4e;
+}
+a:active {
+    text-decoration: none;
+}
+a:hover {
+    font-weight: bold;
+    text-decoration: underline;
+}
+
+/* toc-group */
+.toc-group {
+  font-size: 18px;
+}
+
+.toc-group .group-description {
+  font-size: 14px;
+}
+
+.toc-group .toc-individual {
+    font-size: 16px;
+}
+
+.toc-group .toc-individual .module-description {
+    font-size: 12px;
+}
+
+/* doc-element */
+.element {
+    /* border-style: double;
+    border-width: 3px; */
+    border-color: #ffffff;
+    padding: 7px;
+}
+
+.element .element-name {
+    font-size: 24px;
+    font-style: bold;
+}
+
+.element .description {
+    font-style: bold;
+}
+
+.element .doc-content {
+    margin: 5px 0 0 0;
+}
+
+.element .comment {
+    font-size: 12px;
+
+    /*border-style: solid;
+    border-width: 2px;*/
+    margin: 10px 0 0 0;
+}
+
+.element .key {
+    color: #880000;
+    font-size: 16px;
+}
+
+.element .value {
+    color: #880000;
+    font-size: 16px;
+}
\ ファイル末尾に改行がありません
diff -urN tiarra-20040309/doc/module/Auto.html tiarra-20040313/doc/module/Auto.html
--- tiarra-20040309/doc/module/Auto.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module/Auto.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,580 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>Auto</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+
+    
+    <div id="Auto::Alias" class="element">
+      <span class="element-name">Auto::Alias</span> <span class="description">ユーザエイリアス情報の管理を行ないます。</span>
+      <div class="content">
+	<p class="comment">
+エイリアスは基本的にname,userの二つのフィールドから成っており、<br />
+それぞれユーザー名、ユーザーマスクを表します。<br />
+</p>
+<p class="comment">
+&nbsp;エイリアス定義ファイルのパスと、そのエンコーディング。<br />
+&nbsp;このファイルは次のようなフォーマットである。<br />
+&nbsp;1. それぞれの行は「<キー>: <値>」の形式である。<br />
+&nbsp;2. 空の行で、各ユーザーを区切る。<br />
+&nbsp;3. <値>はカンマで区切られて複数の値とされる。<br />
+<br />
+&nbsp;エイリアス定義ファイルの例:<br />
+<br />
+&nbsp;name: sample<br />
+&nbsp;user: *!*sample@*.sample.net<br />
+<br />
+&nbsp;name: sample2,[sample2]<br />
+&nbsp;user: *!sample2@*.sample.net,*!sample2@*.sample2.net<br />
+<br />
+</p>
+<span class="key">alias</span>:<span class="value">alias.txt</span><br />
+<span class="key">alias-encoding</span>:<span class="value">euc</span><br />
+<p class="comment">
+この発言をした人のエイリアスが登録されていれば、それをprivで送る。<br />
+</p>
+<span class="key">confirm</span>:<span class="value">エイリアス確認</span><br />
+<p class="comment">
+「<addで指定したキーワード> user *!*user@*.user.net」のようにして情報を追加。<br />
+発言をした人のエイリアスが未登録だった場合は、userのみ受け付けて新規追加とする。<br />
+</p>
+<span class="key">add</span>:<span class="value">エイリアス追加</span><br />
+<p class="comment">
+「<removeで指定したキーワード> name ユーザー」のようにして情報を削除。<br />
+userを全て削除されたエイリアスは他の情報(name等)も含めて消滅する。<br />
+</p>
+<span class="key">remove</span>:<span class="value">エイリアス削除</span><br />
+<p class="comment">
+メッセージが追加されたときの反応を指定します。<br />
+ランダムなメッセージを発言する際のフォーマットを指定します。<br />
+エイリアス置換が有効です。#(nick.now)、#(channel)は<br />
+それぞれ相手のnick、チャンネル名に置換されます。<br />
+#(key)、#(value)は、追加されたキーと値に置換されます。<br />
+</p>
+<span class="key">added-format</span>:<span class="value">#(name|nick.now): エイリアス #(key) に #(value) を追加しました。</span><br />
+<p class="comment">
+メッセージが削除されたときの反応を指定します。<br />
+added-formatで指定できるものと同じです。<br />
+</p>
+<span class="key">removed-format</span>:<span class="value">#(name|nick.now): エイリアス #(key) から #(value) を削除しました。</span><br />
+<p class="comment">
+エイリアスの追加や削除が許されている人。省略された場合は「*!*@*」と見做される。<br />
+</p>
+<span class="key">modifier</span>:<span class="value">*!*@*</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Auto::Answer" class="element">
+      <span class="element-name">Auto::Answer</span> <span class="description">特定の発言に反応して対応する発言をする。</span>
+      <div class="content">
+	<p class="comment">
+Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。<br />
+</p>
+<p class="comment">
+&nbsp;反応する発言と、それに対する返事を定義します。<br />
+&nbsp;エイリアス置換が有効です。#(nick.now)と$(channel)はそれぞれ<br />
+&nbsp;相手の現在のnickとチャンネル名に置換されます。<br />
+<br />
+&nbsp;書式: <反応する発言のマスク> <それに対する返事><br />
+&nbsp;例:<br />
+</p>
+<span class="key">reply</span>:<span class="value">こんにちは* こんにちは、#(name|nick.now)さん。</span><br />
+<p class="comment">
+この例では誰かが「こんにちは」で始まる発言をすると、<br />
+発言した人のエイリアスを参照して「こんにちは、○○さん。」のように発言します。<br />
+</p>
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Auto::ChannelWithoutOper" class="element">
+      <span class="element-name">Auto::ChannelWithoutOper</span> <span class="description">チャンネルオペレータ権限がなくなってしまったときに発言する。</span>
+      <div class="content">
+	<p class="comment">
++で始まらない特定のチャンネルで、+aモードでも+rモードでもないのに<br />
+誰もチャンネルオペレータ権限を持っていない状態になっている時、<br />
+そこに誰かがJOINする度に特定のメッセージを発言するモジュールです。<br />
+</p>
+<p class="comment">
+書式: <チャンネル名> <メッセージ><br />
+</p>
+<span class="key">channel</span>:<span class="value">#IRC談話室@ircnet なると消失しました。</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Auto::Joined" class="element">
+      <span class="element-name">Auto::Joined</span> <span class="description">特定のチャンネルに誰かがJOINする度に特定のメッセージを発言する。</span>
+      <div class="content">
+	<p class="comment">
+Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。<br />
+</p>
+<p class="comment">
+&nbsp;発言を行なうチャンネルと、その内容を定義します。<br />
+&nbsp;#(nick.now)と$(channel)は、それぞれ相手の現在のnickとチャンネル名に置換されます。<br />
+<br />
+&nbsp;書式: <チャンネル名> <発言内容><br />
+</p>
+<span class="key">channel</span>:<span class="value">#チャンネル@ircnet   「#ちゃんねる」に移転しました。</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Auto::MesMail" class="element">
+      <span class="element-name">Auto::MesMail</span> <span class="description">伝言をメールとして送信する。</span>
+      <div class="content">
+	<p class="comment">
+メールアドレスはエイリアスの mail を参照します。<br />
+</p>
+<p class="comment">
+Fromアドレス。[default: OSのユーザ名]<br />
+</p>
+<span class="key">from</span>:<span class="value">example1@example.jp</span><br />
+<p class="comment">
+送信用のキーワード [default: mesmail_send]<br />
+</p>
+<span class="key">send</span>:<span class="value">速達伝言</span><br />
+<p class="comment">
+使用を許可する人&チャンネルのマスク。<br />
+例はTiarraモード時。 [default: なし]<br />
+</p>
+<span class="key">mask</span>:<span class="value">* +*!*@*</span><br />
+<p class="comment">
+[plum-mode] mask: +*!*@*<br />
+</p>
+<p class="comment">
+maskで拒否されたときのメッセージ [default: なし]<br />
+</p>
+<span class="key">deny</span>:<span class="value">伝言したくない。</span><br />
+<p class="comment">
+一度に送れる宛先の量 [default: 無制限]<br />
+</p>
+<span class="key">max-send-address</span>:<span class="value">5</span><br />
+<p class="comment">
+宛先を探すエイリアスエントリ [default: なし]<br />
+</p>
+<span class="key">alias-key</span>:<span class="value">name</span><br />
+<span class="key">alias-key</span>:<span class="value">nick</span><br />
+<p class="comment">
+宛先の人を判別出来なかったときのメッセージ [default: なし]<br />
+</p>
+<span class="key">unknown</span>:<span class="value">#(who)さんと言うのは誰ですか?</span><br />
+<p class="comment">
+メールの日付形式<br />
+</p>
+<span class="key">date</span>:<span class="value">%H:%M:%S</span><br />
+<p class="comment">
+エイリアスは見付かったけれどメールアドレスが登録されていなかったときのメッセージ。 [default: なし]<br />
+</p>
+<span class="key">none-address</span>:<span class="value">#(who)さんはアドレスを登録していません。</span><br />
+<p class="comment">
+SMTPのホスト [default: localhost]<br />
+</p>
+<span class="key">smtphost</span>:<span class="value">localhost</span><br />
+<p class="comment">
+SMTPのポート [default: smtp(25)]<br />
+</p>
+<span class="key">smtpport</span>:<span class="value">25</span><br />
+<p class="comment">
+SMTPで自ホストのFQDN [default: localhost]<br />
+</p>
+<span class="key">smtpfqdn</span>:<span class="value">localhost</span><br />
+<p class="comment">
+送信するメールの既定件名(エイリアス使用不可) [default: Message from IRC]<br />
+</p>
+<span class="key">subject</span>:<span class="value">Message from IRC</span><br />
+<p class="comment">
+送信するメールの本文 [default: #(date) << #(from.name|from.nick|from.nick.now) >> #(message)]<br />
+</p>
+<span class="key">format</span>:<span class="value">#(date)に#(from.name|from.nick|from.nick.now)さんから#(message)という伝言です。</span><br />
+<p class="comment">
+送信したときのメッセージ。 [default: なし]<br />
+</p>
+<span class="key">accept</span>:<span class="value">#(who)さんに#(message)と伝言しておきました。</span><br />
+<p class="comment">
+---- POP before SMTP の指定 ----<br />
+POP before SMTPを使う。 [default: no]<br />
+</p>
+<span class="key">use-pop3</span>:<span class="value">yes</span><br />
+<p class="comment">
+POP before SMTPのタイムアウト時間(分)。分からない場合は指定しなくて良い。 [default: 0]<br />
+</p>
+<span class="key">pop3-expire</span>:<span class="value">4</span><br />
+<p class="comment">
+POPのホスト。 [default: localhost]<br />
+</p>
+<span class="key">pop3host</span>:<span class="value">localhost</span><br />
+<p class="comment">
+POPのポート。 [default: pop(110)]<br />
+</p>
+<span class="key">pop3port</span>:<span class="value">110</span><br />
+<p class="comment">
+POPのユーザ [default: OSのユーザ名]<br />
+</p>
+<span class="key">pop3user</span>:<span class="value">example1</span><br />
+<p class="comment">
+POPのパスワード [default: 空パスワード('')]<br />
+</p>
+<span class="key">pop3pass</span>:<span class="value">test-password</span><br />
+<p class="comment">
+---- エラーメッセージの設定 ----<br />
+</p>
+<p class="comment">
+一般エラー。<br />
+error-[state] と言う形式で詳細エラーメッセージを指定できる。<br />
+[state]は、<br />
+&nbsp;&nbsp;&nbsp;* mailfrom(メールの送信者を指定しようとしてエラー)<br />
+&nbsp;&nbsp;&nbsp;* rcptto(メールの送信先を指定しようとしてエラー)<br />
+&nbsp;&nbsp;&nbsp;* norcptto(メールの送信先が全部無くなった)<br />
+&nbsp;&nbsp;&nbsp;* data(メールの中身を送信しようとしてエラー)<br />
+&nbsp;&nbsp;&nbsp;* finish(メールの中身を送信したらエラー)<br />
+がある。特に欲しくなければerror-[state]は指定しなくても構わない。<br />
+メッセージを出したくないなら中身の無いエントリを指定すれば良い。<br />
+error-[state]が指定されてない場合は代わりに error を使う。 [default: 未定義]<br />
+</p>
+<span class="key">error-rcptto</span>:<span class="value"></span><br />
+<span class="key">error-norcptto</span>:<span class="value">#(who)さんには送れませんでした。送信できるメールアドレスがありません。</span><br />
+<span class="key">error-data</span>:<span class="value">メールが送信できません。DATAコマンドに失敗しました。#(line;サーバ応答:%s|;)</span><br />
+<span class="key">error</span>:<span class="value">メール送信エラーです。#(line;サーバ応答:%s|;)#(state; on %s|;)</span><br />
+<p class="comment">
+致命的なエラー。メールに個別なエラーではないので送信者(のprefix)毎に1メッセージ送られる。<br />
+fatalerror-[state]<br />
+[state]:<br />
+&nbsp;&nbsp;&nbsp;* first(接続エラー)<br />
+&nbsp;&nbsp;&nbsp;* helo(SMTPセッションを開始出来ない)<br />
+がある。特に欲しくなければfatalerror-[state]は指定しなくても構わない。<br />
+メッセージを出したくないなら中身の無いエントリを指定すれば良い。<br />
+fatalerror-[state]が指定されてない場合は代わりに fatalerror を使う。 [default: 未定義]<br />
+</p>
+<span class="key">fatalerror-first</span>:<span class="value">SMTPサーバに接続できません。</span><br />
+<span class="key">fatalerror</span>:<span class="value">SMTPセッションで致命的なエラーがありました。#(line; サーバ応答:%s|;)#(state; on %s|;)</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Auto::Oper" class="element">
+      <span class="element-name">Auto::Oper</span> <span class="description">特定の文字列を発言した人を+oする。</span>
+      <div class="content">
+	<p class="comment">
+Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。<br />
+</p>
+<p class="comment">
++oを要求する文字列(マスク)を指定します。<br />
+</p>
+<span class="key">request</span>:<span class="value">なると寄越せ</span><br />
+<p class="comment">
+チャンネルオペレータ権限を要求した人と要求されたチャンネルが<br />
+ここで指定したマスクに一致しなかった場合は<br />
+denyで指定した文字列を発言し、+oをやめます。<br />
+省略された場合は誰にも+oしません。<br />
+書式は「チャンネル 発言者」です。<br />
+マッチングのアルゴリズムは次の通りです。<br />
+1. チャンネル名にマッチするmask定義を全て集める<br />
+2. 集まった定義の発言者マスクを、定義された順にカンマで結合する<br />
+3. そのようにして生成されたマスクで発言者のマッチングを行ない、結果を+o可能性とする。<br />
+例1:<br />
+mask: *@2ch* *!*@*<br />
+mask: #*@ircnet* *!*@*.hoge.jp<br />
+この例ではネットワーク 2ch の全てのチャンネルで誰にでも +o し、<br />
+ネットワーク ircnet の # で始まる全てのチャンネルでホスト名 *.hoge.jp の人に+oします。<br />
+#*@ircnetだと「#hoge@ircnet:*.jp」などにマッチしなくなります。<br />
+例2:<br />
+mask: #hoge@ircnet -*!*@*,+*!*@*.hoge.jp<br />
+mask: *            +*!*@*<br />
+基本的に全てのチャンネルで誰にでも +o するが、例外的に#hoge@ircnetでは<br />
+ホスト名 *.hoge.jp の人にしか +o しない。<br />
+この順序を上下逆にすると、全てのチャンネルで全ての人を +o する事になります。<br />
+何故なら最初の* +*!*@*が全ての人にマッチするからです。<br />
+</p>
+<span class="key">mask</span>:<span class="value">* *!*@*</span><br />
+<p class="comment">
++oを要求した人を実際に+oする時、ここで指定した発言をしてから+oします。<br />
+#(name|nick)のようなエイリアス置換を行います。<br />
+エイリアス以外でも、#(nick.now)を相手のnickに、#(channel)を<br />
+そのチャンネル名にそれぞれ置換します。<br />
+</p>
+<span class="key">message</span>:<span class="value">了解</span><br />
+<p class="comment">
++oを要求されたが+oすべき相手ではなかった場合の発言。<br />
+省略されたら何も喋りません。<br />
+</p>
+<span class="key">deny</span>:<span class="value">断わる</span><br />
+<p class="comment">
++oを要求されたが相手は既にチャンネルオペレータ権限を持っていた場合の発言。<br />
+省略されたらdenyに設定されたものを使います。<br />
+</p>
+<span class="key">oper</span>:<span class="value">既に@を持っている</span><br />
+<p class="comment">
++oを要求されたが自分はチャンネルオペレータ権限を持っていなかった場合の発言。<br />
+省略されたらdenyに設定されたものを使います。<br />
+</p>
+<span class="key">not-oper</span>:<span class="value">@が無い</span><br />
+<p class="comment">
+チャンネルに対してでなく自分に対して+oの要求を行なった場合の発言。<br />
+省略されたらdenyに設定されたものを使います。<br />
+</p>
+<span class="key">private</span>:<span class="value">チャンネルで要求せよ</span><br />
+<p class="comment">
+チャンネルの外から+oを要求された場合の発言。+nチャンネルでは起こりません。<br />
+省略されたらdenyに設定されたものを使います。<br />
+</p>
+<span class="key">out</span>:<span class="value">チャンネルに入っていない</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Auto::Random" class="element">
+      <span class="element-name">Auto::Random</span> <span class="description">特定の発言に反応してランダムな発言をします。</span>
+      <div class="content">
+	<p class="comment">
+Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。<br />
+</p>
+<p class="comment">
+使用するブロックの定義。<br />
+</p>
+<span class="key">blocks</span>:<span class="value">wimikuji</span><br />
+<span class="key">wimikuji</span>
+<div class="block">
+<p class="comment">
+ランダムに発言するメッセージの書かれたファイルと、その文字コードを指定します。<br />
+ファイルの中では一行に一つのメッセージを書いて下さい。<br />
+</p>
+<span class="key">file</span>:<span class="value">random.txt</span><br />
+<span class="key">file-encoding</span>:<span class="value">euc</span><br />
+<p class="comment">
+反応する発言を表すマスクを指定します。<br />
+</p>
+<span class="key">request</span>:<span class="value">ゐみくじ</span><br />
+<p class="comment">
+メッセージの登録数を返答するキーワードを指定します。<br />
+</p>
+<span class="key">count-query</span>:<span class="value">ゐみくじ登録数</span><br />
+<p class="comment">
+メッセージの登録数を返答するときの反応を指定します。<br />
+formatで指定できるものと同じです。#(count)は登録数になります。<br />
+</p>
+<span class="key">count-format</span>:<span class="value">ゐみくじは#(count)件登録されています。</span><br />
+<p class="comment">
+ランダムなメッセージを発言する際のフォーマットを指定します。<br />
+エイリアス置換が有効です。#(message)、#(nick.now)、#(channel)は<br />
+それぞれメッセージ内容、相手のnick、チャンネル名に置換されます。<br />
+何も登録されていないときのために、#(message|;無登録)のように指定すると良いでしょう。<br />
+</p>
+<span class="key">format</span>:<span class="value">#(name|nick.now)の運命は#(message)</span><br />
+<p class="comment">
+反応する人のマスク。<br />
+</p>
+<span class="key">mask</span>:<span class="value">* *!*@*</span><br />
+<p class="comment">
+plum: mask: *!*@*<br />
+</p>
+<p class="comment">
+メッセージが追加されたときの反応を指定します。<br />
+formatで指定できるものと同じです。#(message)は追加されたメッセージになります。<br />
+</p>
+<span class="key">added-format</span>:<span class="value">#(name|nick.now): ゐみくじ #(message) を追加しました。</span><br />
+<p class="comment">
+メッセージが削除されたときの反応を指定します。<br />
+formatで指定できるものと同じです。#(message)は削除されたメッセージになります。<br />
+</p>
+<span class="key">removed-format</span>:<span class="value">#(name|nick.now): ゐみくじ #(message) を削除しました。</span><br />
+<p class="comment">
+発言に反応する確率を指定します。百分率です。省略された場合は100と見做されます。<br />
+</p>
+<span class="key">rate</span>:<span class="value">100</span><br />
+<p class="comment">
+メッセージを追加するキーワードを指定します。<br />
+ここで指定したキーワードを発言すると、新しいメッセージを追加します。<br />
+実際の追加方法は「<addで指定したキーワード> <追加するメッセージ>」です。<br />
+</p>
+<span class="key">add</span>:<span class="value">ゐみくじ追加</span><br />
+<p class="comment">
+メッセージを削除するキーワードを指定します。<br />
+実際の削除方法は「<removeで指定したキーワード> <削除するキーワード>」です。<br />
+</p>
+<span class="key">remove</span>:<span class="value">ゐみくじ削除</span><br />
+<p class="comment">
+addとremoveを許可する人。省略された場合は誰も変更できません。<br />
+</p>
+<span class="key">modifier</span>:<span class="value">* *!*@*</span><br />
+<p class="comment">
+plum: modifier: *!*@*<br />
+</p>
+</div>
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Auto::Reply" class="element">
+      <span class="element-name">Auto::Reply</span> <span class="description">特定の発言に反応して発言をします。</span>
+      <div class="content">
+	<p class="comment">
+Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。<br />
+</p>
+<p class="comment">
+使用するブロックの定義。<br />
+</p>
+<span class="key">blocks</span>:<span class="value">std</span><br />
+<span class="key">std</span>
+<div class="block">
+<p class="comment">
+データファイルと文字コードを指定します。<br />
+ファイルの中では一行に一つの"反応:メッセージ"を書いて下さい。<br />
+</p>
+<span class="key">file</span>:<span class="value">reply.txt</span><br />
+<span class="key">file-encoding</span>:<span class="value">euc</span><br />
+<p class="comment">
+反応チェックを行うキーワードを指定します。<br />
+実際の指定方法は、「<requestで指定したキーワード> <チェックしたい発言>」です。<br />
+</p>
+<span class="key">request</span>:<span class="value">反応チェック</span><br />
+<p class="comment">
+request に反応するときのフォーマットを指定します。<br />
+#(key) がキーワード、 #(message) が発言に置換されます。<br />
+</p>
+<span class="key">reply-format</span>:<span class="value">「#(key)」という発言に「#(message)」と反応します。</span><br />
+<p class="comment">
+request に反応する最大個数を指定します。<br />
+あまり大きな値を指定すると、アタックが可能になったり、ログが流れて邪魔なので注意してください。<br />
+</p>
+<span class="key">max-reply</span>:<span class="value">5</span><br />
+<p class="comment">
+メッセージの登録数を返答するキーワードを指定します。<br />
+</p>
+<span class="key">count-query</span>:<span class="value">反応登録数</span><br />
+<p class="comment">
+メッセージの登録数を返答するときの反応を指定します。<br />
+formatで指定できるものと同じです。#(count)は登録数になります。<br />
+</p>
+<span class="key">count-format</span>:<span class="value">反応は#(count)件登録されています。</span><br />
+<p class="comment">
+反応する人のマスク。<br />
+</p>
+<span class="key">mask</span>:<span class="value">* *!*@*</span><br />
+<p class="comment">
+plum: mask: *!*@*<br />
+</p>
+<p class="comment">
+反応が追加されたときの反応を指定します。<br />
+formatで指定できるものと同じです。#(message)は追加されたメッセージになります。<br />
+</p>
+<span class="key">added-format</span>:<span class="value">#(name|nick.now): #(key) に対する反応 #(message) を追加しました。</span><br />
+<p class="comment">
+メッセージが削除されたときの反応を指定します。<br />
+formatで指定できるものと同じです。#(message)は削除されたメッセージになります。<br />
+</p>
+<span class="key">removed-format</span>:<span class="value">#(name|nick.now): #(key) #(message;に対する反応 %s|;) を #(count) 件削除しました。</span><br />
+<p class="comment">
+発言に反応する確率を指定します。百分率です。省略された場合は100と見做されます。<br />
+</p>
+<span class="key">rate</span>:<span class="value">100</span><br />
+<p class="comment">
+メッセージを追加するキーワードを指定します。<br />
+ここで指定したキーワードを発言すると、新しいメッセージを追加します。<br />
+実際の追加方法は「<addで指定したキーワード> <追加するメッセージ>」です。<br />
+</p>
+<span class="key">add</span>:<span class="value">反応追加</span><br />
+<p class="comment">
+メッセージを削除するキーワードを指定します。<br />
+実際の削除方法は「<removeで指定したキーワード> <削除するキーワード>」です。<br />
+</p>
+<span class="key">remove</span>:<span class="value">反応削除</span><br />
+<p class="comment">
+addとremoveを許可する人。省略された場合は「*!*@*」と見做します。<br />
+</p>
+<span class="key">modifier</span>:<span class="value">*!*@*</span><br />
+<p class="comment">
+正規表現拡張を許可するか。省略された場合は許可します。<br />
+</p>
+<span class="key">use-re</span>:<span class="value">1</span><br />
+</div>
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Auto::Response" class="element">
+      <span class="element-name">Auto::Response</span> <span class="description">データファイルの指定にしたがって反応する。</span>
+      <div class="content">
+	<p class="comment">
+大量の反応データを定義するのに向いています。<br />
+</p>
+<p class="comment">
+データファイルのフォーマット<br />
+| pattern: re:^(こん(に)?ちは)<br />
+| rate: 90<br />
+| mask: * *!*@*<br />
+| #plum: mask: *!*@*<br />
+| response: こんにちは。<br />
+| response: いらっしゃいませ。<br />
+|<br />
+| pattern: おやすみ<br />
+| rate: 20<br />
+| response: おやすみなさい。<br />
+patternは一行しか書けません。(手抜き<br />
+maskもrateも省略できます。省略した場合はmaskは全員、rateは100となります。<br />
+responseは複数書いておけばランダムに選択されます。<br />
+</p>
+<p class="comment">
+データファイル<br />
+</p>
+<span class="key">file</span>:<span class="value">response.txt</span><br />
+<p class="comment">
+文字コード<br />
+</p>
+<span class="key">charset</span>:<span class="value">euc</span><br />
+<p class="comment">
+使用を許可する人&チャンネルのマスク。<br />
+</p>
+<span class="key">mask</span>:<span class="value">* *!*@*</span><br />
+<p class="comment">
+plum: mask: +*!*@*<br />
+</p>
+
+      </div>
+    </div>
+
+    
+    
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc/module/CTCP.html tiarra-20040313/doc/module/CTCP.html
--- tiarra-20040309/doc/module/CTCP.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module/CTCP.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>CTCP</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+
+    
+    <div id="CTCP::ClientInfo" class="element">
+      <span class="element-name">CTCP::ClientInfo</span> <span class="description">CTCP CLIENTINFOに応答する。</span>
+      <div class="content">
+	<p class="comment">
+CTCP::Versionのintervalと同じ。<br />
+</p>
+<span class="key">interval</span>:<span class="value">3</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="CTCP::Ping" class="element">
+      <span class="element-name">CTCP::Ping</span> <span class="description">CTCP PINGに応答する。</span>
+      <div class="content">
+	<p class="comment">
+CTCP::Versionのintervalと同じ。<br />
+</p>
+<span class="key">interval</span>:<span class="value">3</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="CTCP::Time" class="element">
+      <span class="element-name">CTCP::Time</span> <span class="description">CTCP TIMEに応答する。</span>
+      <div class="content">
+	<p class="comment">
+CTCP::Versionのintervalと同じ。<br />
+</p>
+<span class="key">interval</span>:<span class="value">3</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="CTCP::UserInfo" class="element">
+      <span class="element-name">CTCP::UserInfo</span> <span class="description">CTCP USERINFOに応答する。</span>
+      <div class="content">
+	<p class="comment">
+CTCP::Versionのintervalと同じ。<br />
+</p>
+<span class="key">interval</span>:<span class="value">3</span><br />
+<p class="comment">
+USERINFOとして返すメッセージ。<br />
+</p>
+<span class="key">message</span>:<span class="value">テスト</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="CTCP::Version" class="element">
+      <span class="element-name">CTCP::Version</span> <span class="description">CTCP VERSIONに応答する。</span>
+      <div class="content">
+	<p class="comment">
+&nbsp;連続したCTCPリクエストに対する応答の間隔。単位は秒。<br />
+&nbsp;例えば3秒に設定した場合、一度応答してから3秒間は<br />
+&nbsp;CTCPに一切応答しなくなる。デフォルトは3。<br />
+<br />
+&nbsp;なお、CTCP受信時刻の記録は、全てのCTCPモジュールで共有される。<br />
+&nbsp;例えばCTCP VERSIONを送った直後にCTCP CLIENTINFOを送ったとしても、<br />
+&nbsp;CTCP::ClientInfoのintervalで設定された時間を過ぎていなければ<br />
+&nbsp;後者は応答しない。<br />
+</p>
+<span class="key">interval</span>:<span class="value">3</span><br />
+
+      </div>
+    </div>
+
+    
+    
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc/module/Channel.html tiarra-20040313/doc/module/Channel.html
--- tiarra-20040309/doc/module/Channel.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module/Channel.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>Channel</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+
+    
+    <div id="Channel::Freeze" class="element">
+      <span class="element-name">Channel::Freeze</span> <span class="description">特定のチャンネルの発言を、一時的に受信するのをやめる。</span>
+      <div class="content">
+	<p class="comment">
+ログを取っているなら、ログには記録される。<br />
+</p>
+<p class="comment">
+チャンネルの凍結に用いるコマンド名。<br />
+省略時は freeze であり、/freeze #channel@network のように使う。<br />
+チャンネル名を省略すると、現在フリーズされているチャンネルのリストを表示する。<br />
+</p>
+<span class="key">freeze-command</span>:<span class="value">freeze</span><br />
+<p class="comment">
+凍結解除に用いるコマンド名。<br />
+省略時は defrost であり、/defrost #channel@network のように使う。<br />
+</p>
+<span class="key">defrost-command</span>:<span class="value">defrost</span><br />
+<p class="comment">
+凍結しているチャンネルが存在する時、一定時間毎にその旨を報告する事も可能。<br />
+この機能は凍結した事を忘れないようにする為にある。<br />
+単位は分、デフォルトはゼロ(報告しない)。<br />
+</p>
+<span class="key">reminder-interval</span>:<span class="value">30</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Channel::Join::Connect" class="element">
+      <span class="element-name">Channel::Join::Connect</span> <span class="description">サーバーに初めて接続した時、指定したチャンネルに入るモジュール。</span>
+      <div class="content">
+	<p class="comment">
+&nbsp;書式: <チャンネル1>[,<チャンネル2>,...] [<チャンネル1のキー>,...]<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;コンマの直後のスペースは無視されます。<br />
+<br />
+&nbsp;例:<br />
+&nbsp;&nbsp;&nbsp;「#aaaaa@ircnet」に「aaaaa」というキーで入る。<br />
+</p>
+<span class="key">channel</span>:<span class="value">#aaaaa@ircnet aaaaa</span><br />
+<p class="comment">
+<br />
+&nbsp;&nbsp;&nbsp;「#aaaaa@ircnet」、「#bbbbb@ircnet:*.jp」、「#ccccc@ircnet」、「#ddddd@ircnet」の4つのチャンネルに入る。<br />
+</p>
+<span class="key">channel</span>:<span class="value">#aaaaa@ircnet,#bbbbb@ircnet:*.jp, #ccccc@ircnet</span><br />
+<span class="key">channel</span>:<span class="value">#ddddd@ircnet</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Channel::Join::Invite" class="element">
+      <span class="element-name">Channel::Join::Invite</span> <span class="description">招待されたらそのチャンネルに入る。</span>
+      <div class="content">
+	<p class="comment">
+許可するユーザ/チャンネルのマスク。<br />
+</p>
+<span class="key">mask</span>:<span class="value">* *!*@*</span><br />
+<p class="comment">
+plum: *!*@*<br />
+</p>
+<p class="comment">
+招待されたチャンネルに流すメッセージのフォーマット。<br />
+</p>
+<span class="key">message</span>:<span class="value">こんばんわ〜。</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Channel::Join::Kicked" class="element">
+      <span class="element-name">Channel::Join::Kicked</span> <span class="description">特定のチャンネルからkickされた時に、自動で入りなおす。</span>
+      <div class="content">
+	<p class="comment">
+対象となるチャンネル名のマスク<br />
+</p>
+<span class="key">channel</span>:<span class="value">*</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Channel::Mode::Get" class="element">
+      <span class="element-name">Channel::Mode::Get</span> <span class="description">チャンネルにJOINした時、そのチャンネルのモードを取得します。</span>
+      <div class="content">
+	<p class="comment">
+Channel::Mode::Set等が正しく動くためには<br />
+チャンネルのモードをTiarraが把握しておく必要があります。<br />
+自動的にモードを取得するクライアントであれば必要ありませんが、<br />
+そうでなければこのモジュールを使うべきです。<br />
+</p>
+<p class="comment">
+設定項目は無し。<br />
+</p>
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Channel::Mode::Oper::Grant" class="element">
+      <span class="element-name">Channel::Mode::Oper::Grant</span> <span class="description">特定のチャンネルに特定の人間がjoinした時に、自分がチャンネルオペレータ権限を持っていれば+oする。</span>
+      <div class="content">
+	<p class="comment">
+splitからの復帰などで+o対象の人が一度に大量に入って来ても+oは少しずつ実行します。<br />
+Excess Floodにはならない筈ですが、本格的な防衛BOTに使える程の物ではありません。<br />
+</p>
+<p class="comment">
+対象の人間がjoinしてから実際に+oするまで何秒待つか。<br />
+省略されたら待ちません。<br />
+</p>
+<span class="key">wait</span>:<span class="value">0</span><br />
+<p class="comment">
+チャンネルと人間のマスクを定義。Auto::Operと同様。<br />
+</p>
+<span class="key">mask</span>:<span class="value">* example!~example@*.example.ne.jp</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Channel::Mode::Set" class="element">
+      <span class="element-name">Channel::Mode::Set</span> <span class="description">チャンネルを作成した時に自動的にモードを設定するモジュール。</span>
+      <div class="content">
+	<p class="comment">
+書式は<チャンネル名にマッチするマスク> <設定するモード>[,<設定するモード>,...]です。<br />
+#IRC談話室@ircnetなら+t+nを、それ以外なら+nを設定する例。<br />
+</p>
+<span class="key">channel</span>:<span class="value">#IRC談話室@ircnet +t</span><br />
+<span class="key">channel</span>:<span class="value">*                +n</span><br />
+<p class="comment">
+LimeChat 標準設定を模倣する設定例。<br />
+</p>
+<span class="key">channel</span>:<span class="value">* +sn</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Channel::Rejoin" class="element">
+      <span class="element-name">Channel::Rejoin</span> <span class="description">チャンネルオペレータ権限を無くしたとき、一人ならjoinし直す。</span>
+      <div class="content">
+	<p class="comment">
++チャンネルや+aされているチャンネル以外でチャンネルオペレータ権限を持たずに<br />
+一人きりになった時、そのチャンネルの@を復活させるために自動的にjoinし直すモジュール。<br />
+トピック、モード、banリスト等のあらゆるチャンネル属性をも保存します。<br />
+</p>
+<p class="comment">
++b,+I,+eリストの復旧を行なうかどうか。<br />
+あまりに長いリストを取得するとMax Send-Q Exceedで落とされるかも知れません。<br />
+</p>
+<span class="key">save-lists</span>:<span class="value">1</span><br />
+
+      </div>
+    </div>
+
+    
+    
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc/module/Client.html tiarra-20040313/doc/module/Client.html
--- tiarra-20040309/doc/module/Client.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module/Client.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>Client</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+
+    
+    <div id="Client::Cache" class="element">
+      <span class="element-name">Client::Cache</span> <span class="description">データをキャッシュしてサーバに問い合わせないようにする</span>
+      <div class="content">
+	<p class="comment">
+キャッシュを使用しても、使われるのは接続後最初の一度だけです。<br />
+二度目からは通常通りにサーバに問い合わせます。<br />
+また、クライアントオプションの no-cache を指定すれば動きません。<br />
+</p>
+<p class="comment">
+mode キャッシュを使用するか<br />
+</p>
+<span class="key">use-mode-cache</span>:<span class="value">1</span><br />
+<p class="comment">
+who キャッシュを使用するか<br />
+</p>
+<span class="key">use-who-cache</span>:<span class="value">1</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Client::Eval" class="element">
+      <span class="element-name">Client::Eval</span> <span class="description">クライアントから Perl 式を実行できるようにする。</span>
+      <div class="content">
+	<p class="comment">
+eval を実行するコマンド名。省略されるとコマンドを追加しません。<br />
+この時コマンドはTiarraが握り潰すので、IRCプロトコル上で定義された<br />
+コマンド名を設定すべきではありません。<br />
+</p>
+<span class="key">command</span>:<span class="value">eval</span><br />
+
+      </div>
+    </div>
+
+    
+    
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc/module/Debug.html tiarra-20040313/doc/module/Debug.html
--- tiarra-20040309/doc/module/Debug.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module/Debug.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>Debug</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+
+    
+    <div id="Debug::RawLog" class="element">
+      <span class="element-name">Debug::RawLog</span> <span class="description">標準出力にクライアントやサーバとの通信をダンプする。</span>
+      <div class="content">
+	<p class="comment">
+0 または省略で表示しない。 1 で表示する。<br />
+クライアントオプションの logname によって、ダンプに使う名前を指定できます。<br />
+</p>
+<p class="comment">
+サーバからの入力<br />
+</p>
+<span class="key">enable-server-in</span>:<span class="value">1</span><br />
+<p class="comment">
+サーバへの出力<br />
+</p>
+<span class="key">enable-server-out</span>:<span class="value">1</span><br />
+<p class="comment">
+クライアントからの入力<br />
+</p>
+<span class="key">enable-client-in</span>:<span class="value">0</span><br />
+<p class="comment">
+クライアントへの出力<br />
+</p>
+<span class="key">enable-client-out</span>:<span class="value">0</span><br />
+<p class="comment">
+PING/PONG を無視する<br />
+</p>
+<span class="key">ignore-ping</span>:<span class="value">1</span><br />
+<p class="comment">
+NumericReply の名前を解決して表示する(ちゃんとした dump では無くなります)<br />
+</p>
+<span class="key">resolve-numeric</span>:<span class="value">1</span><br />
+
+      </div>
+    </div>
+
+    
+    
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc/module/Log.html tiarra-20040313/doc/module/Log.html
--- tiarra-20040309/doc/module/Log.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module/Log.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>Log</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+
+    
+    <div id="Log::Channel" class="element">
+      <span class="element-name">Log::Channel</span> <span class="description">チャンネルやprivのログを取るモジュール。</span>
+      <div class="content">
+	<p class="comment">
+Log系のモジュールでは、以下のように日付や時刻の置換が行なわれる。<br />
+%% : %<br />
+%Y : 年(4桁)<br />
+%m : 月(2桁)<br />
+%d : 日(2桁)<br />
+%H : 時間(2桁)<br />
+%M : 分(2桁)<br />
+%S : 秒(2桁)<br />
+</p>
+<p class="comment">
+ログを保存するディレクトリ。Tiarraが起動した位置からの相対パス。~指定は使えない。<br />
+</p>
+<span class="key">directory</span>:<span class="value">log</span><br />
+<p class="comment">
+ログファイルの文字コード。省略されたらjis。<br />
+</p>
+<span class="key">charset</span>:<span class="value">sjis</span><br />
+<p class="comment">
+各行のヘッダのフォーマット。省略されたら'%H:%M'。<br />
+</p>
+<span class="key">header</span>:<span class="value">%H:%M:%S</span><br />
+<p class="comment">
+ファイル名のフォーマット。省略されたら'%Y.%m.%d.txt'<br />
+</p>
+<span class="key">filename</span>:<span class="value">%Y.%m.%d.txt</span><br />
+<p class="comment">
+ログファイルのモード(8進数)。省略されたら600<br />
+</p>
+<span class="key">mode</span>:<span class="value">600</span><br />
+<p class="comment">
+ログディレクトリのモード(8進数)。省略されたら700<br />
+</p>
+<span class="key">dir-mode</span>:<span class="value">700</span><br />
+<p class="comment">
+ログを取るコマンドを表すマスク。省略されたら記録出来るだけのコマンドを記録する。<br />
+</p>
+<span class="key">command</span>:<span class="value">privmsg,join,part,kick,invite,mode,nick,quit,kill,topic,notice</span><br />
+<p class="comment">
+PRIVMSGとNOTICEを記録する際に、自分の発言と他人の発言でフォーマットを変えるかどうか。1/0。デフォルトで1。<br />
+</p>
+<span class="key">distinguish-myself</span>:<span class="value">1</span><br />
+<p class="comment">
+各ログファイルを開きっぱなしにするかどうか。<br />
+このオプションは多くの場合、ディスクアクセスを抑えて効率良くログを保存しますが<br />
+ログを記録すべき全てのファイルを開いたままにするので、50や100のチャンネルを<br />
+別々のファイルにログを取るような場合には使うべきではありません。<br />
+</p>
+<span class="key">keep-file-open</span>:<span class="value">1</span><br />
+<p class="comment">
+keep-file-openを有効にした場合、発言の度にログファイルに追記するのではなく<br />
+一定の分量が溜まってから書き込まれる。そのため、ファイルを開いても<br />
+最近の発言はまだ書き込まれていない可能性がある。<br />
+syncを設定すると、即座にログをディスクに書き込むためのコマンドが追加される。<br />
+省略された場合はコマンドを追加しない。<br />
+</p>
+<span class="key">sync</span>:<span class="value">sync</span><br />
+<p class="comment">
+各チャンネルの設定。チャンネル名の部分はマスクである。<br />
+個人宛てに送られたPRIVMSGやNOTICEはチャンネル名"priv"として検索される。<br />
+記述された順序で検索されるので、全てのチャンネルにマッチする"*"などは最後に書かなければならない。<br />
+指定されたディレクトリが存在しなかったら、Log::Channelはそれを勝手に作る。<br />
+フォーマットは次の通り。<br />
+channel: <ディレクトリ名> (<チャンネル名> / 'priv')<br />
+例:<br />
+filename: %Y.%m.%d.txt<br />
+channel: IRCDanwasitu #IRC談話室@ircnet<br />
+channel: others *<br />
+この例では、#IRC談話室@ircnetのログはIRCDanwasitu/%Y.%m.%d.txtに、<br />
+それ以外(privも含む)のログはothers/%Y.%m.%d.txtに保存される。<br />
+</p>
+<span class="key">channel</span>:<span class="value">priv priv</span><br />
+<span class="key">channel</span>:<span class="value">others *</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="Log::Recent" class="element">
+      <span class="element-name">Log::Recent</span> <span class="description">クライアントを接続した時に、保存しておいた最近のメッセージを送る。</span>
+      <div class="content">
+	<p class="comment">
+クライアントオプションの no-recent-logs が指定されていれば送信しません。<br />
+</p>
+<p class="comment">
+各行のヘッダのフォーマット。省略されたら'%H:%M'。<br />
+</p>
+<span class="key">header</span>:<span class="value">%H:%M:%S</span><br />
+<p class="comment">
+ログをチャンネル毎に何行まで保存するか。省略されたら10。<br />
+</p>
+<span class="key">line</span>:<span class="value">15</span><br />
+<p class="comment">
+PRIVMSGとNOTICEを記録する際に、自分の発言と他人の発言でフォーマットを変えるかどうか。1/0。デフォルトで1。<br />
+</p>
+<span class="key">distinguish-myself</span>:<span class="value">1</span><br />
+<p class="comment">
+どのメッセージを保存するか。省略されたら保存可能な全てのメッセージを保存する。<br />
+</p>
+<span class="key">command</span>:<span class="value">privmsg,notice,topic,join,part,quit,kill</span><br />
+
+      </div>
+    </div>
+
+    
+    
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc/module/System.html tiarra-20040313/doc/module/System.html
--- tiarra-20040309/doc/module/System.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module/System.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>System</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+
+    
+    <div id="System::Macro" class="element">
+      <span class="element-name">System::Macro</span> <span class="description">新規にコマンドを追加し、そのコマンドが使われた時に特定の動作をまとめて実行します。</span>
+      <div class="content">
+	<p class="comment">
+書式: <コマンド> <動作><br />
+コマンド"switch"を追加して、それが使われると<br />
+#a@ircnet,#b@ircnet,#c@ircnetにjoinして、<br />
+#d@ircnet,#e@ircnet,#f@ircnetからpartする例。<br />
+</p>
+<span class="key">macro</span>:<span class="value">switch join #a@ircnet,#b@ircnet,#c@ircnet</span><br />
+<span class="key">macro</span>:<span class="value">switch part #d@ircnet,#e@ircnet,#f@ircnet</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="System::Pong" class="element">
+      <span class="element-name">System::Pong</span> <span class="description">サーバーからのPINGメッセージに対し、自動的にPONGを返す。</span>
+      <div class="content">
+	<p class="comment">
+これをoffにするとクライアントが自らPINGに応答せざるを得なくなりますが、<br />
+クライアントからのPONGメッセージはデフォルトのサーバーへ送られるので<br />
+デフォルト以外のサーバーからはPing Timeoutで落とされるなど<br />
+全く良い事がありません。<br />
+&nbsp;&nbsp;設定項目はありません。<br />
+</p>
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="System::PrivTranslator" class="element">
+      <span class="element-name">System::PrivTranslator</span> <span class="description">クライアントからの個人的なprivが相手に届かなくなる現象を回避する。</span>
+      <div class="content">
+	<p class="comment">
+このモジュールは個人宛てのprivmsgの送信者のnickにネットワーク名を付加します。<br />
+設定項目はありません。<br />
+</p>
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="System::Raw" class="element">
+      <span class="element-name">System::Raw</span> <span class="description">マスクで指定したサーバーにIRCメッセージを加工せずに直接送る。</span>
+      <div class="content">
+	<p class="comment">
+例えばQUITを送る事で一時的な切断が可能。<br />
+</p>
+<p class="comment">
+この機能を利用するためのコマンド名。デフォルトは「raw」。<br />
+「/raw ircnet quit」のようにして使う。<br />
+一つ目のパラメータは送り先のネットワーク名。ワイルドカード使用可能。<br />
+CHOCOA の場合、 raw がクライアントで使われてしまうので、<br />
+コマンド名を変えるか、 /raw raw ircnet quit のようにする必要がある。<br />
+</p>
+<span class="key">command</span>:<span class="value">raw</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="System::Reload" class="element">
+      <span class="element-name">System::Reload</span> <span class="description">confファイルやモジュールの更新をリロードするコマンドを追加する。</span>
+      <div class="content">
+	<p class="comment">
+リロードを実行するコマンド名。省略されるとコマンドを追加しません。<br />
+例えば"load"を設定すると、"/load"と発言しようとした時にリロードを実行します。<br />
+この時コマンドはTiarraが握り潰すので、IRCプロトコル上で定義された<br />
+コマンド名を設定すべきではありません。<br />
+</p>
+<span class="key">command</span>:<span class="value">load</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="System::RemoteControl" class="element">
+      <span class="element-name">System::RemoteControl</span> <span class="description">特定の発言が送られてきたとき、それに反応してIRCコマンドを実行します。</span>
+      <div class="content">
+	<p class="comment">
+実行を許可する人間を表すマスク。<br />
+</p>
+<span class="key">mask</span>:<span class="value">*!*example@example.net</span><br />
+<p class="comment">
+&nbsp;構文: + <nick> <IRC Message><br />
+&nbsp;<nick>は反応するbotのnickを表すマスク。<br />
+&nbsp;<IRCMessage>はサーバーに向けて発行するIRCメッセージ。<br />
+<br />
+&nbsp;例:<br />
+&nbsp;+ hoge NICK [hoge]<br />
+&nbsp;hogeというBOTが[hoge]にnickを変更する。<br />
+</p>
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="System::Shutdown" class="element">
+      <span class="element-name">System::Shutdown</span> <span class="description">Tiarraを終了させる。</span>
+      <div class="content">
+	<p class="comment">
+クライアントから特定のコマンドが実行された時や、<br />
+誰かから個人的に(privで)特定の発言が送られた時に<br />
+Tiarra を終了させます。<br />
+</p>
+<p class="comment">
+追加するコマンド。省略された場合はコマンドでのシャットダウンは無効になります。<br />
+</p>
+<span class="key">command</span>:<span class="value">shutdown</span><br />
+<p class="comment">
+Tiarraをシャットダウンさせるprivの発言。<br />
+省略された場合はprivでのシャットダウンは無効になります。<br />
+</p>
+<span class="key">message</span>:<span class="value">shutdown</span><br />
+<p class="comment">
+privでのシャットダウンを許可する人。<br />
+省略された場合はprivでのシャットダウンは無効になります。<br />
+複数のマスクを指定した場合は、一つでもマッチするものがあればシャットダウンします。<br />
+</p>
+<span class="key">mask</span>:<span class="value">example!example@*.example.jp</span><br />
+
+      </div>
+    </div>
+
+    
+    
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc/module/User.html tiarra-20040313/doc/module/User.html
--- tiarra-20040309/doc/module/User.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module/User.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>User</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+
+    
+    <div id="User::Away::Client" class="element">
+      <span class="element-name">User::Away::Client</span> <span class="description">クライアントが一つも接続されていない時にAWAYを設定します。</span>
+      <div class="content">
+	<p class="comment">
+どのようなAWAYメッセージを設定するか。省略された場合はAWAYを設定しません。<br />
+</p>
+<span class="key">away</span>:<span class="value">居ない。</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="User::Away::Nick" class="element">
+      <span class="element-name">User::Away::Nick</span> <span class="description">ニックネーム変更に応じて AWAY を設定します。</span>
+      <div class="content">
+	<p class="comment">
+ニックネームを変更したときに、そのニックネームに対応するAWAYが<br />
+設定されていれば、そのAWAYを設定します。そうでなければAWAYを取り消します。<br />
+</p>
+<p class="comment">
+&nbsp;書式: <nickのマスク> <設定するAWAYメッセージ><br />
+<br />
+&nbsp;nickをhoge_zzzに変更すると、「寝ている」というAWAYを設定する。<br />
+&nbsp;hoge_workまたはhoge_zzzに変更した場合は、「仕事中」というAWAYを設定する。<br />
+&nbsp;それ以外のnickに変更した場合はAWAYを取り消す。<br />
+&nbsp;後者は正規表現を利用して「away: re:hoge_(work|zzz) 仕事中」としても良い。<br />
+</p>
+<span class="key">away</span>:<span class="value">hoge_zzz           寝ている</span><br />
+<span class="key">away</span>:<span class="value">hoge_work,hoge_zzz 仕事中</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="User::Filter" class="element">
+      <span class="element-name">User::Filter</span> <span class="description">指定された人物からのPRIVMSGやNOTICEを書き換える。</span>
+      <div class="content">
+	<p class="comment">
+人物のマスクと、置換パターンを定義。<br />
+置換パターン中の#(message)は、発言内容に置換されます。<br />
+人物が複数のマスクに一致する場合は、最初に一致したものが使われます。<br />
+</p>
+<span class="key">pattern</span>:<span class="value">*!*@* #(message)</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="User::Ignore" class="element">
+      <span class="element-name">User::Ignore</span> <span class="description">指定された人間からのPRIVMSGやNOTICEを破棄してクライアントへ送らないようにするモジュール。</span>
+      <div class="content">
+	<p class="comment">
+対象となるコマンドのマスク。省略時には"privmsg,notice"が設定されている。<br />
+ただしprivmsgとnotice以外を破棄してしまうと、(Tiarraは平気でも)クライアントが混乱する。<br />
+</p>
+<span class="key">command</span>:<span class="value">privmsg,notice</span><br />
+<p class="comment">
+maskは複数定義可能。定義された順番でマッチングが行なわれます。<br />
+</p>
+<span class="key">mask</span>:<span class="value">example!*@*.example.net</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="User::Nick::Detached" class="element">
+      <span class="element-name">User::Nick::Detached</span> <span class="description">クライアントが接続されていない時に、特定のnickに変更します。</span>
+      <div class="content">
+	<p class="comment">
+クライアントが接続されていない時のnick。<br />
+このnickが既に使われていたら、適当に変更が加えられて使用されます。<br />
+クライアントが再び接続されると、切断前のローカルnickに戻ります。<br />
+</p>
+<span class="key">detached</span>:<span class="value">PHO_d</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="User::ServerOper" class="element">
+      <span class="element-name">User::ServerOper</span> <span class="description">特定のネットワークに接続した時、OPERコマンドを発行してします。</span>
+      <div class="content">
+	<p class="comment">
+&nbsp;書式: <ネットワーク名> <オペレータ名> <オペレータパスワード><br />
+<br />
+&nbsp;ネットワーク"local"に接続した時、オペレータ名oper、<br />
+&nbsp;オペレータパスワードoper-passでOPERコマンドを発行する例。<br />
+</p>
+<span class="key">oper</span>:<span class="value">local oper oper-pass</span><br />
+
+      </div>
+    </div>
+
+    
+    <hr />
+    
+    
+    <div id="User::Vanish" class="element">
+      <span class="element-name">User::Vanish</span> <span class="description">指定された人物の存在を、様々なメッセージから消去する。</span>
+      <div class="content">
+	<p class="comment">
+対象となった人物の発行したJOIN、PART、INVITE、QUIT、NICKは消去され、NAMESの返すネームリストからも消える。<br />
+また、対象となった人物のNJOINも消去される。<br />
+</p>
+<p class="comment">
+Vanish対象が発行したMODEを消去するかどうか。デフォルトで0。<br />
+消去するとは云え、本当にMODEそのものを消してしまうのではなく、<br />
+そのユーザーの代わりに"HIDDEN!HIDDEN@HIDDEN.BY.USER.VANISH"がMODEを実行した事にする。<br />
+</p>
+<span class="key">drop-mode-by-target</span>:<span class="value">1</span><br />
+<p class="comment">
+Vanish対象を対象とするMODE +o/-o/+v/-vを消去するかどうか。デフォルトで1。<br />
+</p>
+<span class="key">drop-mode-switch-for-target</span>:<span class="value">1</span><br />
+<p class="comment">
+Vanish対象が発行したKICKを消去するかどうか。デフォルトで0。<br />
+本当に消すのではなく、"HIDDEN!HIDDEN@HIDDEN"がKICKを実行した事にする。<br />
+</p>
+<span class="key">drop-kick-by-target</span>:<span class="value">1</span><br />
+<p class="comment">
+Vanish対象を対象とするKICKを消去するかどうか。デフォルトで0。<br />
+</p>
+<span class="key">drop-kick-for-target</span>:<span class="value">0</span><br />
+<p class="comment">
+Vanish対象が発行したTOPICを消去するかどうか。デフォルトで0。<br />
+本当に消すのでは無いが、他の設定と同じ。<br />
+</p>
+<span class="key">drop-topic-by-target</span>:<span class="value">1</span><br />
+<p class="comment">
+チャンネルとVanish対象の定義。<br />
+特定のチャンネルでのみ対象とする、といった事が可能。<br />
+また、privの場合は「#___priv___@ネットワーク名」という文字列をチャンネル名の代わりとしてマッチングを行なう。<br />
+書式: mask: <チャンネルのマスク> <ユーザーのマスク><br />
+</p>
+<span class="key">mask</span>:<span class="value">#example@example  example!exapmle@example.com</span><br />
+
+      </div>
+    </div>
+
+    
+    
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc/module-toc.html tiarra-20040313/doc/module-toc.html
--- tiarra-20040309/doc/module-toc.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc/module-toc.html	2004-03-13 22:23:47.000000000 +0900
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: module-toc.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>モジュール</title>
+    <link rel="stylesheet" type="text/css" href="default.css" />
+  </head>
+  <body>
+    
+    <h1>モジュール</h1>
+
+    <p>[ここにモジュール全般についての説明を入れる]</p>
+
+    <ul class="toc-group">
+      
+      <li>
+	<a href="module/Auto.html">Auto</a> <span class="group-description">自動反応</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/Auto.html#Auto::Alias">Auto::Alias</a> <span class="module-description">ユーザエイリアス情報の管理を行ないます。</span></li>
+	  
+	  <li><a href="module/Auto.html#Auto::Answer">Auto::Answer</a> <span class="module-description">特定の発言に反応して対応する発言をする。</span></li>
+	  
+	  <li><a href="module/Auto.html#Auto::ChannelWithoutOper">Auto::ChannelWithoutOper</a> <span class="module-description">チャンネルオペレータ権限がなくなってしまったときに発言する。</span></li>
+	  
+	  <li><a href="module/Auto.html#Auto::Joined">Auto::Joined</a> <span class="module-description">特定のチャンネルに誰かがJOINする度に特定のメッセージを発言する。</span></li>
+	  
+	  <li><a href="module/Auto.html#Auto::MesMail">Auto::MesMail</a> <span class="module-description">伝言をメールとして送信する。</span></li>
+	  
+	  <li><a href="module/Auto.html#Auto::Oper">Auto::Oper</a> <span class="module-description">特定の文字列を発言した人を+oする。</span></li>
+	  
+	  <li><a href="module/Auto.html#Auto::Random">Auto::Random</a> <span class="module-description">特定の発言に反応してランダムな発言をします。</span></li>
+	  
+	  <li><a href="module/Auto.html#Auto::Reply">Auto::Reply</a> <span class="module-description">特定の発言に反応して発言をします。</span></li>
+	  
+	  <li><a href="module/Auto.html#Auto::Response">Auto::Response</a> <span class="module-description">データファイルの指定にしたがって反応する。</span></li>
+	  
+	</ul>
+      </li>
+      
+      <li>
+	<a href="module/CTCP.html">CTCP</a> <span class="group-description">CTCP 関連</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/CTCP.html#CTCP::ClientInfo">CTCP::ClientInfo</a> <span class="module-description">CTCP CLIENTINFOに応答する。</span></li>
+	  
+	  <li><a href="module/CTCP.html#CTCP::Ping">CTCP::Ping</a> <span class="module-description">CTCP PINGに応答する。</span></li>
+	  
+	  <li><a href="module/CTCP.html#CTCP::Time">CTCP::Time</a> <span class="module-description">CTCP TIMEに応答する。</span></li>
+	  
+	  <li><a href="module/CTCP.html#CTCP::UserInfo">CTCP::UserInfo</a> <span class="module-description">CTCP USERINFOに応答する。</span></li>
+	  
+	  <li><a href="module/CTCP.html#CTCP::Version">CTCP::Version</a> <span class="module-description">CTCP VERSIONに応答する。</span></li>
+	  
+	</ul>
+      </li>
+      
+      <li>
+	<a href="module/Channel.html">Channel</a> <span class="group-description">チャンネルに対する操作</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/Channel.html#Channel::Freeze">Channel::Freeze</a> <span class="module-description">特定のチャンネルの発言を、一時的に受信するのをやめる。</span></li>
+	  
+	  <li><a href="module/Channel.html#Channel::Join::Connect">Channel::Join::Connect</a> <span class="module-description">サーバーに初めて接続した時、指定したチャンネルに入るモジュール。</span></li>
+	  
+	  <li><a href="module/Channel.html#Channel::Join::Invite">Channel::Join::Invite</a> <span class="module-description">招待されたらそのチャンネルに入る。</span></li>
+	  
+	  <li><a href="module/Channel.html#Channel::Join::Kicked">Channel::Join::Kicked</a> <span class="module-description">特定のチャンネルからkickされた時に、自動で入りなおす。</span></li>
+	  
+	  <li><a href="module/Channel.html#Channel::Mode::Get">Channel::Mode::Get</a> <span class="module-description">チャンネルにJOINした時、そのチャンネルのモードを取得します。</span></li>
+	  
+	  <li><a href="module/Channel.html#Channel::Mode::Oper::Grant">Channel::Mode::Oper::Grant</a> <span class="module-description">特定のチャンネルに特定の人間がjoinした時に、自分がチャンネルオペレータ権限を持っていれば+oする。</span></li>
+	  
+	  <li><a href="module/Channel.html#Channel::Mode::Set">Channel::Mode::Set</a> <span class="module-description">チャンネルを作成した時に自動的にモードを設定するモジュール。</span></li>
+	  
+	  <li><a href="module/Channel.html#Channel::Rejoin">Channel::Rejoin</a> <span class="module-description">チャンネルオペレータ権限を無くしたとき、一人ならjoinし直す。</span></li>
+	  
+	</ul>
+      </li>
+      
+      <li>
+	<a href="module/Client.html">Client</a> <span class="group-description">クライアントとの入出力</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/Client.html#Client::Cache">Client::Cache</a> <span class="module-description">データをキャッシュしてサーバに問い合わせないようにする</span></li>
+	  
+	  <li><a href="module/Client.html#Client::Eval">Client::Eval</a> <span class="module-description">クライアントから Perl 式を実行できるようにする。</span></li>
+	  
+	</ul>
+      </li>
+      
+      <li>
+	<a href="module/Debug.html">Debug</a> <span class="group-description">Tiarraや、Tiarraモジュールのデバッグ用</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/Debug.html#Debug::RawLog">Debug::RawLog</a> <span class="module-description">標準出力にクライアントやサーバとの通信をダンプする。</span></li>
+	  
+	</ul>
+      </li>
+      
+      <li>
+	<a href="module/Log.html">Log</a> <span class="group-description">ログの記録</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/Log.html#Log::Channel">Log::Channel</a> <span class="module-description">チャンネルやprivのログを取るモジュール。</span></li>
+	  
+	  <li><a href="module/Log.html#Log::Recent">Log::Recent</a> <span class="module-description">クライアントを接続した時に、保存しておいた最近のメッセージを送る。</span></li>
+	  
+	</ul>
+      </li>
+      
+      <li>
+	<a href="module/System.html">System</a> <span class="group-description">Tiarra自身の動作に関するもの</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/System.html#System::Macro">System::Macro</a> <span class="module-description">新規にコマンドを追加し、そのコマンドが使われた時に特定の動作をまとめて実行します。</span></li>
+	  
+	  <li><a href="module/System.html#System::Pong">System::Pong</a> <span class="module-description">サーバーからのPINGメッセージに対し、自動的にPONGを返す。</span></li>
+	  
+	  <li><a href="module/System.html#System::PrivTranslator">System::PrivTranslator</a> <span class="module-description">クライアントからの個人的なprivが相手に届かなくなる現象を回避する。</span></li>
+	  
+	  <li><a href="module/System.html#System::Raw">System::Raw</a> <span class="module-description">マスクで指定したサーバーにIRCメッセージを加工せずに直接送る。</span></li>
+	  
+	  <li><a href="module/System.html#System::Reload">System::Reload</a> <span class="module-description">confファイルやモジュールの更新をリロードするコマンドを追加する。</span></li>
+	  
+	  <li><a href="module/System.html#System::RemoteControl">System::RemoteControl</a> <span class="module-description">特定の発言が送られてきたとき、それに反応してIRCコマンドを実行します。</span></li>
+	  
+	  <li><a href="module/System.html#System::Shutdown">System::Shutdown</a> <span class="module-description">Tiarraを終了させる。</span></li>
+	  
+	</ul>
+      </li>
+      
+      <li>
+	<a href="module/User.html">User</a> <span class="group-description">特定の人間に対する動作や自分自身についての動作</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/User.html#User::Away::Client">User::Away::Client</a> <span class="module-description">クライアントが一つも接続されていない時にAWAYを設定します。</span></li>
+	  
+	  <li><a href="module/User.html#User::Away::Nick">User::Away::Nick</a> <span class="module-description">ニックネーム変更に応じて AWAY を設定します。</span></li>
+	  
+	  <li><a href="module/User.html#User::Filter">User::Filter</a> <span class="module-description">指定された人物からのPRIVMSGやNOTICEを書き換える。</span></li>
+	  
+	  <li><a href="module/User.html#User::Ignore">User::Ignore</a> <span class="module-description">指定された人間からのPRIVMSGやNOTICEを破棄してクライアントへ送らないようにするモジュール。</span></li>
+	  
+	  <li><a href="module/User.html#User::Nick::Detached">User::Nick::Detached</a> <span class="module-description">クライアントが接続されていない時に、特定のnickに変更します。</span></li>
+	  
+	  <li><a href="module/User.html#User::ServerOper">User::ServerOper</a> <span class="module-description">特定のネットワークに接続した時、OPERコマンドを発行してします。</span></li>
+	  
+	  <li><a href="module/User.html#User::Vanish">User::Vanish</a> <span class="module-description">指定された人物の存在を、様々なメッセージから消去する。</span></li>
+	  
+	</ul>
+      </li>
+      
+    </ul>
+
+    <p>[ここにも適当になんか入れとく]</p>
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc-src/README tiarra-20040313/doc-src/README
--- tiarra-20040309/doc-src/README	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc-src/README	2004-03-13 22:23:41.000000000 +0900
@@ -0,0 +1,115 @@
+-*- mode: outline; mode: auto-fill; -*-
+
+* tdoc形式について
+
+次のような形式を持つ=podと=cutに囲まれた範囲が、TiarraDoc(tdoc)として
+認識されます。
+
+=pod
+ヘッダのキー: ヘッダの値
+ヘッダのキー: ヘッダの値
+...
+
+内容
+=cut
+
+このように、"キー: 値"の行が一つ以上続き、その後に空行が来るような形を
+していないpodはtdocパーサによって無視されます。
+
+tdocデータはファイル内の何処にあっても構いませんが、そのtdocが説明する
+パッケージ内の範囲に無ければなりません。つまり、複数のパッケージを持
+つ*.pmファイルの中では、パッケージFooについてのtdocはパッケージFoo内に
+置く必要があります。
+tdocパーサはperlのpackage文を認識し、どのパッケージについての説明であ
+るかを判断します。
+
+tdocデータはsample.confの生成とhtmlドキュメントの生成の両方に使われま
+す。また、将来これ以外の使い方がされる可能性もあります。
+
+** ヘッダ
+
+ヘッダに記述すべき内容は、通常のモジュール(module下のもの)、内部モジュー
+ル(main下のもの)、そしてドキュメント生成元データ(doc-src下の*.tdoc)そ
+れぞれに於て異なります。
+
+*** 通常のモジュールのヘッダ(module下のもの)
+
+通常のモジュールは、ヘッダとして"info"と"default"を持ちます。
+infoはモジュールの簡単な説明(一行)、defaultは値として"on"または"off"を
+持つ真偽値で、それぞれsample.conf内でデフォルトで"+"になっているか"-"
+になっているかを示します。
+
+例(System::Reload):
+
+=pod
+info: confファイルやモジュールの更新をリロードするコマンドを追加する。
+default: on
+
+# リロードを実行するコマンド名。省略されるとコマンドを追加しません。
+# 例えば"load"を設定すると、"/load"と発言しようとした時にリロードを実行します。
+# この時コマンドはTiarraが握り潰すので、IRCプロトコル上で定義された
+# コマンド名を設定すべきではありません。    
+command: load
+=cut
+
+*** 内部モジュール(main下のもの)
+
+未定
+
+*** ドキュメント生成元データ(doc-src下の*.tdoc)
+
+未定
+
+
+** 内容
+
+ドキュメント内容もヘッダと同じように、通常モジュール、内部モジュール、
+ドキュメント生成元データのそれぞれに於て異ります。
+
+*** 通常モジュール
+
+通常モジュールは、"#"で始まる行と"key: value"の形そしている行、そして
+"-key: value"の形をしている行の三種類の形式で記述します。
+空の行やこれらの形を持たない行は、パーサによって無視されます。
+
+"#"で始まる行は、後述する"key: value"の説明の為にあります。
+連続する"#"行はtdocパーサによって一つに纏められ、先頭の空白が削除され
+た後にsample.conf、htmlの各形式に整形されます。
+纏められた"#"行の先頭に共通する空白は全て削除されますが、共通*しない*
+空白は残されます。
+
+例:
+#  foo
+#  bar
+#  baz
+
+以上の三行は纏められ、先頭の空白が削除される。sample.confでの整形結果
+は結果は次の通り。
+
+# foo
+# bar
+# baz
+
+例:
+#  foo
+#    bar
+#  baz
+
+以上の三行は纏められ、全ての行に存在する空白が削除される。結果は次の通
+り。
+
+# foo
+#   bar
+# baz
+
+"key: value"形式の行は、そのモジュールの設定項目を表します。
+同様に、"-key: value"形式の行は、そのモジュールの設定項目ではあっても、
+sample.confではデフォルトでコメントアウトされている項目を表します。
+
+*** 内部モジュール(main下のもの)
+
+未定
+
+*** ドキュメント生成元データ(doc-src下の*.tdoc)
+
+未定
diff -urN tiarra-20040309/doc-src/conf-main.tdoc tiarra-20040313/doc-src/conf-main.tdoc
--- tiarra-20040309/doc-src/conf-main.tdoc	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc-src/conf-main.tdoc	2004-03-13 22:23:41.000000000 +0900
@@ -0,0 +1,224 @@
+-*- outline -*-
+$Id: conf-main.tdoc,v 1.4 2004/02/23 02:46:18 topia Exp $
+
+perlのソースに使うpodパーサを流用しているので、package文と=pod〜=cutで書く必要があります。
+ヘッダのinfo-is-ommitedとno-switchはどちらも値を真に定義しなければなりません。
+
+* general
+package general;
+=pod
+info: conf自身の文字コードやユーザー情報などを指定する
+info-is-omitted: 1
+no-switch: 1
+
+# tiarra.conf自身の文字コード
+# コード名はjis,sjis,euc,utf8,utf16,utf32等。(この値はUnicode::Japaneseにそのまま渡されます)
+# autoが指定された、または省略された場合は自動判別します。
+conf-encoding: euc
+
+# ユーザー情報
+# 省略不能です。
+nick: tiarra
+user: tiarra
+name: Tiarra the "Aeon"
+
+# どのようなユーザーモードでログインするか。+iwや+iのように指定する。
+# 省略された場合はユーザーモードを特に設定しない。
+-user-mode: +i
+  
+# Tiarraへの接続を許可するホスト名を表わすマスク。
+# 制限をしないのであれば"*"を指定するか省略する。
+client-allowed: *
+
+# Tiarraが開くポート。ここに指定したポートへクライアントに接続させる。
+# 省略されたらポートを開かない。
+tiarra-port: 6667
+
+# Tiarraがポートtiarra-portを開く際、IPv6とIPv4のどちらでリスニングを行なうか。
+# 'v4'または'v6'で指定します。デフォルトは'v4'です。
+# IPv6を使うためにはSocket6.pmが利用可能である必要があります。
+-tiarra-ip-version: v4
+
+# Tiarraがポートtiarra-portを開く際のローカルアドレス。
+# 意味が分からなければ省略して下さい。
+# デフォルトは、IPv4のはINADDR_ANY、IPv6のはin6addr_anyになります。
+-tiarra-ipv4-bind-addr: 0.0.0.0
+-tiarra-ipv6-bind-addr: ::0
+
+# Tiarraにクライアントが接続する際に要求するパスワードをcryptした文字列。
+# 空の文字列が指定されたり省略された場合はパスワードを要求しない。
+tiarra-password: xl7cflIcH9AwE
+
+# 外部プログラムからtiarraをコントロールする為のUNIXドメインソケットの名前。
+# 例えば"foo"を指定した場合、ソケット/tmp/tiarra-control/fooが作られる。
+# 省略された場合はこの機能を無効とする。
+# また、非UNIX環境ではそもそもUNIXドメインソケットが利用可能でないため、
+# そのような場合にもこの機能は無効となる。
+-control-socket-name: test
+  
+# IRCサーバーから送られる文字のコードと、IRCサーバーへ送る文字のコード
+# どちらも省略された場合はjis。
+server-in-encoding: jis
+server-out-encoding: jis
+  
+# クライアントから受け取る文字のコードと、クライアントへ伝える文字のコード
+# どちらも省略された場合はjis。
+client-in-encoding: jis
+client-out-encoding: jis
+  
+# Tiarraは標準出力に様々なメッセージを出力するが、その文字コードを指定する。省略時にはeucとなる。
+# ただしtiarra.confのパースが完了するまでは文字コードの変換は行なわれない(つまりこの設定が有効にならない)ことに注意して下さい。
+stdout-encoding: euc
+  
+# Tiarraはエラーメッセージを標準出力に出力するが、その時に接続しているクライアントがあればクライアントにもNOTICEで送る事が出来る。
+# この値を1にすると、その機能が有効になる。省略するか0を指定するとこの機能は無効になる。
+notice-error-messages: 1
+
+# Tiarraでチャンネルとユーザーのマスクを指定するときの形式。
+# plum形式とTiarra形式が選択できます。
+#-----------------
+# plum形式: (channelには+や-は使えない。channelは省略すると*とみなす。)
+#   + syntax: user[ channel[ channel[ ...]]]
+#
+#  mask: +*!*@*.example.com #{example}@ircnet +{example3}@ircnet
+#  mask: -*!*@*.example.com #{example2}@2ch,+{example4}@2ch
+#  mask: -*!*@*
+#-----------------
+# Tiarra形式: (channelにも+や-を使える。)
+#   + syntax: channel user
+#
+#  mask: #{example}@ircnet,-#{example2}@2ch    +*!*@*.example.com
+#  mask: ++{example3}@ircnet,-+{example4}@2ch  +*!*@*.example.com # +で始まるチャンネル。
+#  mask: *                                     -*!*@*
+#-----------------
+# となります。 この二つはまったく同じマスクを表しています。
+
+# この値をplumにすると、plum形式、省略するかtiarraを指定すると、Tiarra形式になります。
+chanmask-mode: tiarra
+
+# サーバーに接続する際、ローカル側のどのアドレスにバインドするか。
+# 意味が分からなければ省略して下さい。
+# デフォルトは、IPv4のはINADDR_ANY、IPv6のはin6addr_anyになります。
+-ipv4-bind-addr: 0.0.0.0
+-ipv6-bind-addr: ::0
+
+# tiarra が、 001 や 002 や、 recent log を送信するときなどに使う prefix
+# を指定します。 hostname や fqdn っぽいものを指定すると良いかもしれません。
+# デフォルトは tiarra です。普通変える必要はありません。
+-sysmsg-prefix: tiarra
+
+sysmsg-prefix-use-masks {
+  # sysmsg-prefix を使用する場所を指定する。
+
+  # システムメッセージ(NumericReply など)。デフォルトは * です。
+  # ふつうこれを変更する必要はありません。
+  system: *
+
+  # 個人宛メッセージ(Notice,Privmsg の中で)。デフォルトはなし。
+  -priv:
+
+  # チャンネル宛メッセージ(Notice,Privmsg の中で)。デフォルトは * です。
+  # Ziciz などのクライアントを接続する場合は、
+  # -*::log を指定しておくといいかもしれません。
+  channel: *
+}
+=cut
+
+* networks
+package networks;
+=pod
+info: Tiarraから接続するネットワークの定義、その他
+info-is-omitted: 1
+no-switch: 1
+
+# 複数のサーバーへの接続を可能にするかどうか。1(オン)と0(オフ)で指定。
+# これを1にすると、次のnameを複数個定義する事が可能になり、
+# 複数のサーバーに同時に接続出来るようになります。
+# その一方、これを1にしている時は、チャンネル名にネットワーク名が付加される等、
+# IRCの大部分のメッセージがTiarraによる改変を受けます。
+# これを0にしている間は、次のnameを複数個定義する事は出来なくなります。
+# マルチサーバーモードの設定を起動中に変えると、クライアントから見たチャンネル名が
+# 変更になる為、全クライアントが一時的に全てのチャンネルからpartしたように見え、
+# その直後にjoinし直したように見えます。
+# デフォルトでは1です。
+multi-server-mode: 1
+
+# 接続するIRCネットワークに名前を付けます。この名前は後で使用します。
+# 複数のネットワークに接続したい場合は多重定義して下さい。
+name: ircnet
+name: 2ch
+  
+# 通常Tiarraではチャンネル名を「#Tiarra@ircnet」のように表現します。
+# これはネットワークircnet内の#Tiarraというチャンネルを表わします。
+# @以降は省略可能ですが、省略された場合のデフォルトのネットワーク名をここで指定します。
+# 省略した場合は最も始めに定義されたnameがデフォルトになります。
+# (そしてnameが一つも無かった場合はmainがデフォルトになります)
+default: ircnet
+  
+# 上に述べた通り、デフォルトではTiarraはチャンネル名とネットワーク名を@で区切ります。
+# この区切り文字は任意の文字に変更する事が出来ます。省略された場合は@になります。
+channel-network-separator: @
+
+# 接続先のサーバーから切断された時に、joinしていたそのサーバーのチャンネルをどうするか。
+# 1. "part-and-join"の場合は、切断されるとクライアントにはチャンネルからpartしたように見せ掛け、
+#    再接続に成功すると再びjoinしたように見せ掛ける。最も負荷が高い。(これはplumに似た動作である)
+# 2. "one-message"の場合は、切断されるとクライアントに宛ててTiarraがNOTICEでその旨を報告する。
+#    再接続に成功すると再びNOTICEで報告する。JOINやPARTはしないので、
+#    クライアントからはまだそのチャンネルに残っているかのように見える。
+# 3. "message-for-each"の場合は、切断されるとクライアントに宛ててTiarraが
+#    到達不能になった全てのチャンネルにNOTICEでその旨を報告する。
+#    再接続に成功すると再びNOTICEで報告する。JOINやPARTはしない。
+# デフォルトはpart-and-joinです。
+action-when-disconnected: message-for-each
+
+# NICKを変更する度に、変更したサーバーでの新しいNICKをNOTICEで常に通知するかどうか。
+# 1なら必ず通知し、0なら変更後のnickがローカルnick(クライアントが見る事の出来るnick)と違っている場合のみ通知する。
+# デフォルトは0です。
+always-notify-new-nick: 0
+=cut
+
+
+* ircnet
+package ircnet;
+=pod
+info: ネットワーク定義例 (IRCnet)
+info-is-omitted: 1
+no-switch: 1
+
+# サーバーのホストとポート。省略不可。
+host: irc.nara.wide.ad.jp
+port: 6663
+
+# general/userで設定したユーザ名を使わずに、各ネットワークで独自のユーザ名を使用する事も可能。
+# 省略されたら当然、general/userで設定したものが使われる。
+-user: hoge
+
+# general/nameで設定した本名(建前上)を使わずに、各ネットワークで独自の本名を使用可能。
+-name: hoge
+
+# このサーバーの要求するパスワード。省略可能。
+-password: hoge
+
+# general/setver-in/out-encodingで設定したエンコーディングを使わずに、
+# 各ネットワークで独自のエンコーディングを使用する事も可能。
+# 省略されたら当然、generalで設定したものが使われる。
+-in-encoding: jis
+-out-encoding: jis
+
+# general/(ipv4|ipv6)bind-addrで設定したローカルアドレスを使わずに、
+# 各ネットワークで独自のbind_addrを使用する事も可能。
+# 省略されたらgeneralで設定したものが使われる。
+-ipv4-bind-addr: 0.0.0.0
+-ipv6-bind-addr: ::0
+=cut
+
+* 2ch
+package 2ch;
+=pod
+info: ネットワーク定義例 (2ch)
+info-is-omitted: 1
+no-switch: 1
+
+host: irc.2ch.net
+port: 6667
+=cut
diff -urN tiarra-20040309/doc-src/contents.html tiarra-20040313/doc-src/contents.html
--- tiarra-20040309/doc-src/contents.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc-src/contents.html	2004-03-13 22:23:41.000000000 +0900
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title><&group-name></title>
+    <link rel="stylesheet" type="text/css" href="<&css-path>" />
+  </head>
+  <body>
+
+    <!begin:element>
+    <div id="<&content-name>" class="element">
+      <span class="element-name"><&content-name></span> <span class="description"><&description></span>
+      <div class="content">
+	<&content>
+      </div>
+    </div>
+
+    <!begin:hr>
+    <hr />
+    <!end:hr>
+    <!end:element>
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc-src/module-group.tdoc tiarra-20040313/doc-src/module-group.tdoc
--- tiarra-20040309/doc-src/module-group.tdoc	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc-src/module-group.tdoc	2004-03-13 22:23:41.000000000 +0900
@@ -0,0 +1,56 @@
+-*- outline -*-
+$Id: module-group.tdoc,v 1.2 2004/02/23 02:46:18 topia Exp $
+
+各モジュールの分類名(= グループ名)と、その説明。
+グループ名とは、モジュール名のm/^(.+?)::/で与えられる部分を指す。
+
+この分類表で定義されていないモジュールは、グループ `UNCLASSIFIED' に属するものと見做される。
+
+* Auto
+package Auto;
+=pod
+description: 自動反応
+=cut
+
+* Channel
+package Channel;
+=pod
+description: チャンネルに対する操作
+=cut
+
+* Client
+package Client;
+=pod
+description: クライアントとの入出力
+=cut
+
+* CTCP
+package CTCP;
+=pod
+description: CTCP 関連
+=cut
+
+* Debug
+package Debug;
+=pod
+description: Tiarraや、Tiarraモジュールのデバッグ用
+=cut
+
+* Log
+package Log;
+=pod
+description: ログの記録
+=cut
+
+* System
+package System;
+=pod
+description: Tiarra自身の動作に関するもの
+=cut
+
+* User
+package User;
+=pod
+description: 特定の人間に対する動作や自分自身についての動作
+=cut
+
diff -urN tiarra-20040309/doc-src/module-toc.html tiarra-20040313/doc-src/module-toc.html
--- tiarra-20040309/doc-src/module-toc.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc-src/module-toc.html	2004-03-13 22:23:41.000000000 +0900
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="EUC-JP"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: module-toc.html,v 1.1 2003/08/04 09:29:21 admin Exp $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
+    <title>モジュール</title>
+    <link rel="stylesheet" type="text/css" href="default.css" />
+  </head>
+  <body>
+    
+    <h1>モジュール</h1>
+
+    <p>[ここにモジュール全般についての説明を入れる]</p>
+
+    <ul class="toc-group">
+      <!begin:toc-group>
+      <li>
+	<a href="<&group-path>"><&group-name></a> <span class="group-description"><&description></span>
+	<ul class="toc-individual">
+	  <!begin:toc-individual>
+	  <li><a href="<&group-path>#<&mod-name>"><&mod-name></a> <span class="module-description"><&description></span></li>
+	  <!end:toc-individual>
+	</ul>
+      </li>
+      <!end:toc-group>
+    </ul>
+
+    <p>[ここにも適当になんか入れとく]</p>
+
+  </body>
+</html>
diff -urN tiarra-20040309/doc-src/sample.conf.in tiarra-20040313/doc-src/sample.conf.in
--- tiarra-20040309/doc-src/sample.conf.in	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/doc-src/sample.conf.in	2004-03-13 22:23:40.000000000 +0900
@@ -0,0 +1,112 @@
+# -*- tiarra-conf -*-
+# -----------------------------------------------------------------------------
+# $Id: sample.conf.in,v 1.2 2004/02/23 02:46:18 topia Exp $
+# -----------------------------------------------------------------------------
+# tiarra.conf サンプル
+#
+# tiarraは起動時に全ての設定をこのファイルから取得します。
+# このファイルの文字コードは任意ですが、改行コードはLFもしくはCRLFでなければなりません。
+#
+# 半角の#で始まる行はコメントとして無視されます。
+# 行の途中に#を置いた場合はコメントにはなりません。
+#
+# 設定行は「設定名 : 値」の形式で指定されます。
+# 行の先頭及び末尾、コロンの前後の空白は無視されます。
+#
+# 特に指定が無い場合、同じ設定を二度以上繰り返した時は最初に定義された設定が有効になります。
+#
+# ブロックごと省略した場合は、そのブロックの全ての値が省略されたものとみなします。
+# ただし省略不可能な設定もありますので御注意下さい。
+#
+# 「@include foo.conf」という行があると、foo.confがその場所に
+#  挿入されたかのように処理します。
+#
+# {}記号の位置には、それなりの自由度があります。
+# 次の例は全て有効です。
+# block {
+#   foo: bar
+# }
+#
+# block {}
+#
+# block
+# {}
+#
+# 次の例は全て無効です。
+# block {foo: bar}
+#
+# block
+# {foo: bar}
+# 
+# block {
+# foo: bar}
+# 
+# block
+# {foo: bar
+# }
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# generalブロック
+#
+# tiarra.conf自身の文字コードやユーザー情報などを指定するブロックです。
+# -----------------------------------------------------------------------------
+<&general>
+
+# -----------------------------------------------------------------------------
+# networksブロック
+#
+# Tiarraから接続するIRCネットワークの名称です。
+# 一つも定義しなかった場合やこのブロックを省略した場合は、
+# "main"というネットワークが一つだけ指定されたものと見做します。
+# -----------------------------------------------------------------------------
+<&networks>
+
+# -----------------------------------------------------------------------------
+# 各ネットワークの設定
+#
+# networksブロックで定義した全てのネットワークについて、
+# そのアドレス、ポート、(必要なら)パスワードを定義します。
+# -----------------------------------------------------------------------------
+<&ircnet>
+
+<&2ch>
+
+# -----------------------------------------------------------------------------
+# 必須の設定は以上です。以下はモジュール(プラグイン)の設定です。
+# -----------------------------------------------------------------------------
+
+# +または-で始まる行はモジュール設定行と見做されます。
+# +で記述されたモジュールが使用され、-で記述されたモジュールは使用されません。
+# +や-の後の空白は幾つあっても無視されます。
+
+#   メッセージが各モジュールを通過する順番は、このconfファイルで記述された
+# 順番の通りになります。ログを取るモジュールなどはconfでも後の方に
+# 記述した方が良いということになります。
+
+#   モジュール名はperlのそれと同じようにディレクトリ区切り文字を「::」としたパスで表現されます。
+# 例えばモジュールChannel::Auto::Operの実体はファイルmodule/Channel/Auto/Oper.pm
+# でなければならず、そのpackage宣言もChannel::Auto::Operでなければなりません。
+#   Tiarraモジュールの名称は、perl標準モジュール群やmain/下の.pmファイルと重複しないように
+# 気を付けて下さい。Tiarraはモジュールが本当にModuleのサブクラスかどうかをチェックするので
+# 例えばIO::Socket::INETといったモジュールを置いても誤動作はしませんが、
+# そのようなモジュールはロード時にエラーを出して使用中止になります。
+
+# 一つのモジュールを複数回定義して、何度も同じモジュールをメッセージが通過するようには出来ません。
+
+# 幾つかのモジュールはパラメータとしてチャンネル名を必要とします。
+# ここで指定するチャンネル名は、ネットワーク名も含めた文字列でなければなりません。
+# 「#チャンネル」では駄目で「#チャンネル@ネットワーク」などとする必要があります。
+
+# マスクの書式:
+# ['+' / '-'] ( <マスク文字列> / "re:" 正規表現 )
+# これはカンマで幾つでも継ぐ事が出来ます。"\,"でカンマそのものを表します。
+# 先頭が+なら、それに続く部分にマッチするものが選ばれ、-なら除外されます。省略されたら+と見做されます。
+# マスク文字列とは"*"で0文字以上の任意の文字列を、"?"で1文字の任意の文字列を表す文字列です。
+# 例:
+# tiarra*  これはtiarraで始まる文字列を表す。
+# +*!*tiarra@*.jp,-re:\d  これは*!*tiarra@*.jpにマッチして、かつ文字列中に数字を含まないものを表す。
+
+<!begin:modules>
+<&module>
+<!end:modules>
diff -urN tiarra-20040309/main/Hook.pm tiarra-20040313/main/Hook.pm
--- tiarra-20040309/main/Hook.pm	2004-03-09 17:03:45.000000000 +0900
+++ tiarra-20040313/main/Hook.pm	2004-03-13 22:23:39.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Hook.pm,v 1.1 2003/08/12 01:45:35 admin Exp $
+# $Id: Hook.pm,v 1.2 2004/03/13 07:17:34 admin Exp $
 # -----------------------------------------------------------------------------
 # Hook: あらゆるフックのベースクラス
 # HookTarget: あらゆるフック先のベースクラス
@@ -23,7 +23,7 @@
 #
 # $HOOK_TARGET_DEFAULT:
 #   フックを掛ける対象のオブジェクトが省略された場合のデフォルト値。
-#   これは省略可能で、
+#   これは省略可能で、省略した場合はinstall時にターゲットの省略が出来なくなる。
 #
 # これらの変数を定義し、Hookを@ISAに入れたパッケージを作る。
 # -----------------------------------------------------------------------------
@@ -31,6 +31,8 @@
 #
 # HookTargetを@ISAに入れたクラスを作る。コンストラクタでの配慮は不要。
 # $obj->call_hooks($hook_name)で、インストールされた全てのフックを呼ぶ。
+# $obj->call_hooks($hook_name, $foo, $bar, $baz)のように任意の個数の引数を
+# 渡す事が可能で、その場合はそれらを引数としてフック関数が呼ばれる。
 #
 # 現在の実装では、HookTargetはオブジェクトをハッシュで持つクラスでのみ使用可能。
 # また、`installed-hooks'と云うキーを勝手に使う。
@@ -149,14 +151,15 @@
 }
 
 sub call {
-    my $this = shift;
+    my ($this, @args) = @_;
 
     my ($caller_pkg) = caller(2);
     if ($caller_pkg->isa(ref $this->{target})) {
-	$this->{code}->($this);
+	$this->{code}->($this, @args);
     }
     else {
-	croak "Only ${\ref($this->{target})} can call ${\ref($this)}->call\n";
+	croak "Only ${\ref($this->{target})} can call ${\ref($this)}->call\n".
+	  "$caller_pkg is not allowed to do so.\n";
     }
 }
 
@@ -205,12 +208,12 @@
 }
 
 sub call_hooks {
-    my ($this, $hook_name) = @_;
+    my ($this, $hook_name, @args) = @_;
     my $array = $this->_get_hooks_array($hook_name);
 
     foreach my $hook (@$array) {
 	eval {
-	    $hook->call;
+	    $hook->call(@args);
 	}; if ($@) {
 	    die ref($this)."->call_hooks, exception occured: $@\n";
 	}
diff -urN tiarra-20040309/main/IrcIO/Client.pm tiarra-20040313/main/IrcIO/Client.pm
--- tiarra-20040309/main/IrcIO/Client.pm	2004-03-09 17:03:45.000000000 +0900
+++ tiarra-20040313/main/IrcIO/Client.pm	2004-03-13 22:23:39.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Client.pm,v 1.26 2004/02/23 05:41:21 topia Exp $
+# $Id: Client.pm,v 1.27 2004/03/13 07:17:34 admin Exp $
 # -----------------------------------------------------------------------------
 # IrcIO::Clientはクライアントからの接続を受け、
 # IRCメッセージをやり取りするクラスです。
@@ -9,6 +9,7 @@
 use warnings;
 use Carp;
 use base qw(IrcIO);
+use IrcIO;
 use Net::hostent;
 use Crypt;
 use Configuration;
@@ -17,10 +18,11 @@
 use LocalChannelManager;
 use NumericReply;
 
-use SelfLoader;
-SelfLoader->load_stubs; # このクラスには親クラスがあるから。(SelfLoaderのpodを参照)
-1;
-__DATA__
+# 複数のパッケージを混在させてるとSelfLoaderが使えない…？
+#use SelfLoader;
+#SelfLoader->load_stubs; # このクラスには親クラスがあるから。(SelfLoaderのpodを参照)
+#1;
+#__DATA__
 
 sub new {
     my ($class,$sock) = @_;
@@ -460,6 +462,9 @@
 	    my $ch_name = $_;
 	    if (Mask::match($mask, $ch_name)) {
 		$send_channelinfo->(@{$channels{$ch_name}});
+		# channel-infoフックの引数は (IrcIO::Client, チャンネル名)
+		IrcIO::Client::HookTarget->shared->call(
+		    'channel-info', $this, $ch_name);
 		delete $channels{$ch_name};
 		last;
 	    }
@@ -467,9 +472,55 @@
     }
 
     # のこりを出力
-    map {
-	$send_channelinfo->(@$_);
-    } values %channels;
+    while (my ($ch_name, $pair) = each %channels) {
+	$send_channelinfo->(@$pair);
+	IrcIO::Client::HookTarget->shared->call(
+	    'channel-info', $this, $ch_name);
+    }
+}
+
+# -----------------------------------------------------------------------------
+# クライアントにチャンネル情報(JOIN,TOPIC,NAMES等)を渡した直後に呼ばれるフック。
+# チャンネル名(multi server modeならネットワーク名付き)を引数として、
+# チャンネル一つにつき一度ずつ呼ばれる。
+#
+# my $hook = IrcIO::Client::Hook->new(sub {
+#     my $hook_itself = shift;
+#     # 何らかの処理を行なう。
+# })->install('channel-info'); # チャンネル情報転送時にこのフックを呼ぶ。
+# -----------------------------------------------------------------------------
+package IrcIO::Client::Hook;
+use FunctionalVariable;
+use base 'Hook';
+
+our $HOOK_TARGET_NAME = 'IrcIO::Client::HookTarget';
+our @HOOK_NAME_CANDIDATES = qw/channel-info/;
+our $HOOK_NAME_DEFAULT = 'channel-info';
+our $HOOK_TARGET_DEFAULT;
+FunctionalVariable::tie(
+    \$HOOK_TARGET_DEFAULT,
+    FETCH => sub {
+	IrcIO::Client::HookTarget->shared;
+    },
+   );
+
+# -----------------------------------------------------------------------------
+package IrcIO::Client::HookTarget;
+use Hook;
+our @ISA = 'HookTarget';
+our $_shared;
+
+sub shared {
+    my $class = shift;
+    if (!defined $_shared) {
+	$_shared = bless {} => $class; # 繼承するなら問題になるが…
+    }
+    $_shared;
+}
+
+sub call {
+    my ($this, $name, @args) = @_;
+    $this->call_hooks($name, @args);
 }
 
 1;
diff -urN tiarra-20040309/main/RunLoop.pm tiarra-20040313/main/RunLoop.pm
--- tiarra-20040309/main/RunLoop.pm	2004-03-09 17:03:46.000000000 +0900
+++ tiarra-20040313/main/RunLoop.pm	2004-03-13 22:23:40.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: RunLoop.pm,v 1.54 2004/02/23 06:24:20 topia Exp $
+# $Id: RunLoop.pm,v 1.56 2004/03/13 07:17:34 admin Exp $
 # -----------------------------------------------------------------------------
 # このクラスはTiarraのメインループを実装します。
 # select()を実行し、サーバーやクライアントとのI/Oを行うのはこのクラスです。
@@ -88,8 +88,6 @@
 
 	timers => [], # インストールされている全てのTimer
 	external_sockets => [], # インストールされている全てのExternalSocket
-	#hooks_before_select => [], # インストールされている全てのbefore-selectフック
-	#hooks_after_select => [], # インストールされている全てのafter-selectフック
 
 	conf_reloaded_hook => undef, # この下でインストールするフック
     };
@@ -666,67 +664,6 @@
     undef;
 }
 
-=pod
-sub install_hook {
-    my ($this,$hook_name,$hook) = @_;
-    my $array = do {
-	if ($hook_name eq 'before-select') {
-	    $this->{hooks_before_select};
-	}
-	elsif ($hook_name eq 'after-select') {
-	    $this->{hooks_after_select};
-	}
-	else {
-	    croak "RunLoop->install_hook, hook name '$hook_name' is invalid.\n";
-	}
-    };
-    push @$array,$hook;
-    $this;
-}
-
-sub uninstall_hook {
-    my ($this,$hook_name,$hook) = @_;
-    my $array = do {
-	if ($hook_name eq 'before-select') {
-	    $this->{hooks_before_select};
-	}
-	elsif ($hook_name eq 'after-select') {
-	    $this->{hooks_after_select};
-	}
-	else {
-	    croak "RunLoop->uninstall_hook, hook name '$hook_name' is invalid.\n";
-	}
-    };
-    @$array = grep {
-	$_ != $hook;
-    } @$array;
-    $this;
-}
-
-sub call_hooks {
-    my ($this,$hook_name) = @_;
-    my $array = do {
-	if ($hook_name eq 'before-select') {
-	    $this->{hooks_before_select};
-	}
-	elsif ($hook_name eq 'after-select') {
-	    $this->{hooks_after_select};
-	}
-	else {
-	    croak "RunLoop->call_hooks, hook name '$hook_name' is invalid.\n";
-	}
-    };
-    foreach my $hook (@$array) {
-	eval {
-	    $hook->call;
-	}; if ($@) {
-	    die "RunLoop: Exception in calling hook.\n$@\n";
-	}
-    }
-}
-
-=cut
-
 sub install_timer {
     my ($this,$timer) = @_;
     push @{$this->{timers}},$timer;
@@ -883,7 +820,7 @@
     }
 
     my $zerotime = {
-	limit => 100,
+	limit => 300,
 	minimum_to_reset => 2,
 	interval => 10,
 
@@ -905,7 +842,7 @@
 		}
 	    }
 	}
-	elsif ($elapsed < $zerotime->{minimum_to_reset}) {
+	elsif ($elapsed > $zerotime->{minimum_to_reset}) {
 	    $zerotime->{count} = 0;
 	}
     };
@@ -1286,9 +1223,6 @@
 # })->install('after-select'); # select実行直後にこのフックを呼ぶ。
 # -----------------------------------------------------------------------------
 package RunLoop::Hook;
-#use strict;
-#use warnings;
-#use Carp;
 use FunctionalVariable;
 use base 'Hook';
 
@@ -1303,67 +1237,4 @@
     },
    );
 
-=pod
-sub new {
-    my ($class,$code) = @_;
-    my $this = {
-	runloop => undef,
-	hook_name => undef,
-
-	code => $code,
-    };
-
-    if (!defined $code) {
-	croak "RunLoop::Hook->new, Arg[0] was undef.\n";
-    }
-    elsif (ref($code) ne 'CODE') {
-	croak "RunLoop::Hook->new, Arg[0] was bad type.\n";
-    }
-
-    bless $this,$class;
-}
-
-sub install {
-    # $hook_name: 'before-select' または 'after-select'。
-    #             それぞれselect直前か直後に呼ばれる。省略されたりundefが渡された場合はafter-selectになる。
-    # $runloop:   インストールするRunLoop。省略された場合はRunLoop->shared。
-    my ($this,$hook_name,$runloop) = @_;
-    $hook_name = 'after-select' if !defined $hook_name;
-    $runloop = RunLoop->shared if !defined $runloop;
-
-    if (defined $this->{runloop}) {
-	croak "RunLoop::Hook->install, this hook is already installed.\n";
-    }
-
-    $this->{runloop} = $runloop;
-    $this->{hook_name} = $hook_name;
-    $runloop->install_hook($hook_name,$this);
-
-    $this;
-}
-
-sub uninstall {
-    my $this = shift;
-
-    $this->{runloop}->uninstall_hook($this->{hook_name},$this);
-    $this->{runloop} = undef;
-    $this->{hook_name} = undef;
-
-    $this;
-}
-
-sub call {
-    my $this = shift;
-
-    my ($caller_pkg) = caller;
-    if ($caller_pkg->isa('RunLoop')) {
-	$this->{code}->($this);
-    }
-    else {
-	croak "Only RunLoop can call RunLoop::Hook->call\n";
-    }
-}
-
-=cut
-
 1;
diff -urN tiarra-20040309/makedoc tiarra-20040313/makedoc
--- tiarra-20040309/makedoc	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20040313/makedoc	2004-03-13 22:23:39.000000000 +0900
@@ -0,0 +1,313 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------
+# $Id: makedoc,v 1.2 2004/02/23 02:46:17 topia Exp $
+# ------------------------------------------------------------------------
+use strict;
+use warnings;
+use lib qw(main);
+use Unicode::Japanese;
+use IO::File;
+use File::Find;
+use Template;
+use TiarraDoc;
+my $unijp_init = Unicode::Japanese->new;
+
+my $conf_output = 'sample.conf';
+
+my $stdout_charset = 'euc';
+my $conf_charset = 'euc';
+my $html_charset = 'euc';
+
+if (!-f 'tiarra' || !-d 'main' || !-d 'module') {
+    die "run this script on tiarra's directory.\n";
+}
+
+mkdir 'doc';
+
+&makeconf;
+&makehtml_mods_toc;
+&makehtml_mods;
+exit;
+
+sub makeconf {
+    print "*** Generating $conf_output... ***\n";
+
+    my $unijp = Unicode::Japanese->new;
+    my $t = Template->new('doc-src/sample.conf.in');
+
+    foreach my $conf (DocParser::Module->new('doc-src/conf-main.tdoc')->makeconf) {
+	print $conf->[0]." : ".$unijp->set($conf->[1])->$stdout_charset."\n";
+	$t->expand($conf->[0] => $unijp->set($conf->[2])->$conf_charset);
+    }
+
+    # module下の.pmを検索
+    my @modules;
+    find(sub {
+	if (-f $_ && $_ =~ m/\.pm$/) {
+	    push @modules, $File::Find::name;
+	}
+    },'module');
+
+    map {
+	my @confs = DocParser::Module->new($_)->makeconf;
+	foreach my $conf (@confs) {
+	    print $conf->[0]." : ".$unijp->set($conf->[1])->$stdout_charset."\n";
+	    $t->modules->add(module => $unijp->set($conf->[2])->$conf_charset);
+	}
+    } sort @modules;
+
+    my $fh = IO::File->new($conf_output,'w');
+    $fh->print($t->str);
+}
+
+our $classify_modules_CACHE;
+sub classify_modules {
+    # 一度実行したら、その結果がキャッシュされる。
+    if (defined($_ = $classify_modules_CACHE)) {
+	return $_;
+    }
+    
+    my $classified = {}; # {グループ名 => [それに含まれるモジュールのDocPod]}
+    my $classify = sub {
+	my $doc = shift;
+	
+	my $groupname = do {
+	    if ($doc->pkg_name =~ m/^(.+?)::/) {
+		$1;
+	    }
+	    else {
+		'';
+	    }
+	};
+	
+	my $vec = $classified->{$groupname};
+	if (!defined $vec) {
+	    $vec = $classified->{$groupname} = [];
+	}
+	push @$vec,$doc;
+    };
+
+    # module下の.pmを検索
+    find(sub {
+	if (-f $_ && $_ =~ m/\.pm$/) {
+	    my $parser = DocParser->new($_);
+	    my $doc = eval {
+		$parser->getdoc;
+	    }; if ($@) {
+		die "ERROR[$_]: $@\n";
+	    }
+
+	    # 分類
+	    $classify->($doc) if defined $doc;
+	}
+    },'module');
+
+    # ソート
+    foreach (keys %$classified) {
+	@{$classified->{$_}} = 
+	    map { $_->[1] } 
+		sort { $a->[0] cmp $b->[0] }
+		    map { [$_->pkg_name, $_]; } @{$classified->{$_}};
+    }
+
+    $classify_modules_CACHE = $classified;
+    $classified;
+}
+
+sub makehtml_mods {
+    # ファイルはグループ毎に作られる点に注意。
+    # すなわち、まず最初に全てのモジュールをグループに分類する必要がある。
+    my $classified = &classify_modules; # {グループ名 => [それに含まれるモジュールのDocPod]}
+
+    mkdir 'doc/module';
+
+    my $unijp = Unicode::Japanese->new;
+    my $t = Template->new('doc-src/contents.html');
+
+    while (my ($groupname,$docpods) = each %$classified) {
+	my $group_path =
+	    join('',
+		 'module/',
+		 $groupname eq '' ? 'UNCLASSIFIED' : $groupname,
+		 '.html');
+	print "*** Generating doc/$group_path... ***\n";
+
+	$t->reset;
+	$t->expand(
+	    group_name => $groupname,
+	    css_path => '../default.css',
+	);
+
+	my $last_docpod = $docpods->[-1];
+	foreach my $docpod (@$docpods) {
+	    print "  parsing and translating ".$docpod->pkg_name."\n";
+	    # 空行はそのまま出力。
+	    # key: valueの行は、<span id="key">と<span id="value">で出力。
+	    # そのkeyの頭に'-'が付いていたら、単にその'-'を消す。
+	    #
+	    # '#'で始まる行は、<p id="comment">で出力するが、以下の特殊なルールに従う。
+	    # 1. '#'の行が連続している場合、それらの行を一つのグループにまとめる。
+	    # 2. 各グループ内で'#'に後続する共通の数のスペースを取り除く。
+	    # 3. 取り除いた後、'#'後にスペースがまだ残っているなら、それを&nbsp;に置換する。
+	    #
+	    # 例:
+	    # # foo
+	    # # bar {
+	    # #   baz
+	    # # }
+	    # ↓
+	    # <p id="comment">
+	    #   foo<br />
+	    #   bar {<br />
+	    #   &nbsp;&nbsp;baz<br />
+	    #   }<br />
+	    # </p>
+	    my $html = ''; # 文字コードはUTF-8
+	    
+	    my @lines = split /\n/,$docpod->content;
+	    for (my $i = 0; $i < @lines; $i++) {
+		my $line = $lines[$i];
+
+		if ($line eq '') {
+		    #$html .= "<br />\n";
+		}
+		elsif ($line =~ m/^\s*#/) {
+		    # グループ作成
+		    my @group;
+		    for (; $i < @lines; $i++) {
+			if ($lines[$i] =~ m/^\s*#/) {
+			    # これはブロックの続き。
+			    (my $stripped = $lines[$i]) =~ s/^\s*#//;
+			    
+			    # タブは4つのスペースに変換。この動作は後で修正するかも知れない。
+			    $stripped =~ s/\t/    /g;
+			    
+			    push @group,$stripped;
+			}
+			else {
+			    $i--;
+			    last; # ここで終わり
+			}
+		    }
+		    
+		    # 共通する先頭のスペースを除去。すなわち各行について先頭のスペースの個数を数え、
+		    # その最小値を削るべきスペースの数とする。
+		    my $spaces_to_remove;
+		    foreach (@group) {
+			m/^(\s*)/;
+			if (defined $1) {
+			    my $n_spaces = length($1);
+			    if (defined $spaces_to_remove) {
+				$spaces_to_remove = $n_spaces
+				    if $spaces_to_remove > $n_spaces;
+			    }
+			    else {
+				$spaces_to_remove = $n_spaces;
+			    }
+			}
+		    }
+		    if (defined $spaces_to_remove) {
+			@group = map {
+			    s/^\s{$spaces_to_remove}//; $_;
+			} @group;
+		    }
+
+		    # それでも残っている先頭のスペースを&nbsp;に置換。
+		    @group = map {
+			s/^(\s+)/'&nbsp;' x length($1) if defined $1/e; $_;
+		    } @group;
+
+		    $html .= qq{<p class="comment">\n};
+		    $html .= join('',
+				  map {
+				      "$_<br />\n";
+				  } @group);
+		    $html .= qq{</p>\n};
+		}
+		elsif ($line =~ m/^-?(.+?)\s*:\s*(.*)$/) {
+		    my ($key,$value) = ($1,$2);
+		    $html .= qq{<span class="key">$key</span>:<span class="value">$value</span><br />\n};
+		} elsif ($line =~ m/^(.+?)\s*{\s*$/) {
+		    $html .= qq{<span class="key">$1</span>\n};
+		    $html .= qq{<div class="block">\n};
+		} elsif ($line =~ m/^}\s*$/) {
+		    $html .= qq{</div>\n};
+		}
+	    }
+
+	    # テンプレを展開
+	    $t->element->expand(
+		content_name => $docpod->pkg_name,
+		description => $unijp->set($docpod->header('info'))->$html_charset,
+		content => $unijp->set($html)->$html_charset);
+
+	    # これが最後の要素でなければ、hrを追加する。
+	    if ($docpod != $last_docpod) {
+		$t->element->hr->add;
+	    }
+
+	    $t->element->add;
+	}
+
+	# ファイルに出力
+	my $fh = IO::File->new("doc/$group_path",'w');
+	$fh->print($t->str);
+    }
+}
+
+sub makehtml_mods_toc {
+    print "*** Generating doc/module-toc.html... ***\n";
+
+    my $t = Template->new('doc-src/module-toc.html');
+
+    my $classified = &classify_modules; # {グループ名 => [それに含まれるモジュールのDocPod]}
+
+    # module-group.tdocを読んで、各グループの説明を取得する。
+    my $groups = DocParser->new('doc-src/module-group.tdoc');
+
+    foreach my $groupname (sort {$a cmp $b} keys %$classified) {
+	my $description = do {
+	    # このグループに対して、説明が定義されているか？
+	    my $groupdoc = $groups->getdoc($groupname);
+	    if (defined $groupdoc) {
+		my $description = $groupdoc->header->{description};
+		defined $description ? $description : '';
+	    }
+	    else {
+		'';
+	    }
+	};
+	if ($description eq '') {
+	    warn "group $groupname don't have description.";
+	}
+
+	my $unijp = Unicode::Japanese->new;
+
+	my $group_path =
+	    join('',
+		 'module/',
+		 $groupname eq '' ? 'UNCLASSIFIED' : $groupname,
+		 '.html');
+	
+	$t->toc_group->expand(
+	    group_path => $unijp->set($group_path)->$html_charset,
+	    group_name => $unijp->set($groupname)->$html_charset,
+	    description => $unijp->set($description)->$html_charset,
+	);
+
+	# 各モジュール名とその説明を展開〜
+	foreach my $moddoc (@{$classified->{$groupname}}) {
+	    print $moddoc->pkg_name." belongs to the group `".$groupname."'\n";
+	    $t->toc_group->toc_individual->add(
+		group_path => $unijp->set($group_path)->$html_charset,
+		mod_name => $unijp->set($moddoc->pkg_name)->$html_charset,
+		description => $unijp->set($moddoc->header->{info} || '')->$html_charset,
+	    );
+	}
+
+	$t->toc_group->add;
+    }
+
+    my $fh = IO::File->new('doc/module-toc.html','w');
+    $fh->print($t->str);
+}
diff -urN tiarra-20040309/module/Log/Recent.pm tiarra-20040313/module/Log/Recent.pm
--- tiarra-20040309/module/Log/Recent.pm	2004-03-09 17:03:46.000000000 +0900
+++ tiarra-20040313/module/Log/Recent.pm	2004-03-13 22:23:40.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Recent.pm,v 1.9 2004/02/23 02:46:19 topia Exp $
+# $Id: Recent.pm,v 1.10 2004/03/13 07:17:35 admin Exp $
 # -----------------------------------------------------------------------------
 # Local: $Clovery: tiarra/module/Log/Recent.pm,v 1.5 2003/02/11 07:59:32 topia Exp $
 package Log::Recent;
@@ -25,9 +25,34 @@
 	    },
 	    $this,
 	    'S_PRIVMSG','C_PRIVMSG','S_NOTICE','C_NOTICE');
+    $this->{hook} = IrcIO::Client::Hook->new(
+	sub {
+	    my ($hook, $client, $ch_name) = @_;
+	    my $ch = RunLoop->shared->channel($ch_name);
+	    # ログはあるか？
+	    my $vec = $ch->remarks('recent-log');
+	    if (defined $vec) {
+		my $ch_name;
+		foreach my $elem (@$vec) {
+		    $ch_name =
+			RunLoop->shared->multi_server_mode_p ?
+			    $elem->[0] : $ch->name;
+		    $client->send_message(
+			IRCMessage->new(
+			    Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(channel log)),
+			    Command => 'NOTICE',
+			    Params => [$ch_name,$elem->[1]]));
+		}
+	    }
+	})->install('channel-info');
     $this;
 }
 
+sub destruct {
+    my $this = shift;
+    $this->{hook} and $this->{hook}->uninstall;
+}
+
 sub message_arrived {
     my ($this,$msg,$sender) = @_;
     # Log::Recent/commandにマッチするか？
@@ -50,26 +75,27 @@
 		Command => 'NOTICE',
 		Params => [$local_nick,$elem->[1]])); # $elem->[0]は常に'priv'
     }
+
     # 次に各チャンネル
-    foreach my $network (values %{RunLoop->shared->networks}) {
-	foreach my $ch (values %{$network->channels}) {
-	    # ログはあるか？
-	    my $vec = $ch->remarks('recent-log');
-	    if (defined $vec) {
-		my $ch_name;
-		foreach my $elem (@$vec) {
-		    $ch_name =
-			RunLoop->shared->multi_server_mode_p ?
-			    $elem->[0] : $ch->name;
-		    $client->send_message(
-			IRCMessage->new(
-			    Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(channel log)),
-			    Command => 'NOTICE',
-			    Params => [$ch_name,$elem->[1]]));
-		}
-	    }
-	}
-    }
+#    foreach my $network (values %{RunLoop->shared->networks}) {
+#	foreach my $ch (values %{$network->channels}) {
+#	    # ログはあるか？
+#	    my $vec = $ch->remarks('recent-log');
+#	    if (defined $vec) {
+#		my $ch_name;
+#		foreach my $elem (@$vec) {
+#		    $ch_name =
+#			RunLoop->shared->multi_server_mode_p ?
+#			    $elem->[0] : $ch->name;
+#		    $client->send_message(
+#			IRCMessage->new(
+#			    Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(channel log)),
+#			    Command => 'NOTICE',
+#			    Params => [$ch_name,$elem->[1]]));
+#		}
+#	    }
+#	}
+#    }
 }
 
 *S_PRIVMSG = \&PRIVMSG_or_NOTICE;
diff -urN tiarra-20040309/sample.conf tiarra-20040313/sample.conf
--- tiarra-20040309/sample.conf	2004-03-09 17:03:45.000000000 +0900
+++ tiarra-20040313/sample.conf	2004-03-13 22:23:44.000000000 +0900
@@ -1,6 +1,6 @@
 # -*- tiarra-conf -*-
 # -----------------------------------------------------------------------------
-# $Id: sample.conf,v 1.65 2004/02/23 08:27:11 topia Exp $
+# $Id: sample.conf.in,v 1.2 2004/02/23 02:46:18 topia Exp $
 # -----------------------------------------------------------------------------
 # tiarra.conf サンプル
 #
