diff -urN tiarra-20050327/.svnversion tiarra-20050330/.svnversion
--- tiarra-20050327/.svnversion	2005-03-27 21:22:41.000000000 +0900
+++ tiarra-20050330/.svnversion	2005-03-31 00:54:35.000000000 +0900
@@ -1 +1 @@
-872
+886
diff -urN tiarra-20050327/ChangeLog.svn tiarra-20050330/ChangeLog.svn
--- tiarra-20050327/ChangeLog.svn	2005-03-27 21:23:05.000000000 +0900
+++ tiarra-20050330/ChangeLog.svn	2005-03-31 00:55:00.000000000 +0900
@@ -1,4 +1,113 @@
 ------------------------------------------------------------------------
+r886 | topia | 2005-03-30 21:59:54 +0900 (Wed, 30 Mar 2005) | 2 lines
+Changed paths:
+   M /trunk/main/Mask.pm
+
+* drop support of number (channel match fail...).
+
+------------------------------------------------------------------------
+r885 | topia | 2005-03-30 20:27:24 +0900 (Wed, 30 Mar 2005) | 2 lines
+Changed paths:
+   M /trunk/main/Tiarra/Socket/Lined.pm
+
+* fix typo.
+
+------------------------------------------------------------------------
+r884 | topia | 2005-03-30 16:14:01 +0900 (Wed, 30 Mar 2005) | 6 lines
+Changed paths:
+   M /trunk/main/IrcIO.pm
+   M /trunk/main/Module.pm
+   M /trunk/main/Tiarra/IRC/Message.pm
+
+* add message_encoding_hook.
+
+* add POD to Tiarra::IRC::Message.
+
+* implement item delete to remark.
+
+------------------------------------------------------------------------
+r883 | topia | 2005-03-29 23:32:04 +0900 (Tue, 29 Mar 2005) | 2 lines
+Changed paths:
+   M /trunk/main/Multicast.pm
+
+* global_to_local on nick notice.
+
+------------------------------------------------------------------------
+r882 | topia | 2005-03-29 21:53:35 +0900 (Tue, 29 Mar 2005) | 1 line
+Changed paths:
+   M /trunk/tiarra
+
+* show termination progress.
+------------------------------------------------------------------------
+r881 | topia | 2005-03-29 21:33:43 +0900 (Tue, 29 Mar 2005) | 1 line
+Changed paths:
+   M /trunk/module/Log/Raw.pm
+
+* fix destruction/sync bug.
+------------------------------------------------------------------------
+r880 | topia | 2005-03-28 17:23:16 +0900 (Mon, 28 Mar 2005) | 1 line
+Changed paths:
+   M /trunk/main/IrcIO.pm
+   M /trunk/main/Tiarra/IRC/Message.pm
+
+* add "remark" encoding.
+------------------------------------------------------------------------
+r879 | topia | 2005-03-28 17:09:10 +0900 (Mon, 28 Mar 2005) | 4 lines
+Changed paths:
+   M /trunk/module/Client/GetVersion.pm
+
+* convert to new CTCP interface.
+
+* use constant pragma.
+
+------------------------------------------------------------------------
+r878 | topia | 2005-03-28 13:16:13 +0900 (Mon, 28 Mar 2005) | 2 lines
+Changed paths:
+   M /trunk/main/Module.pm
+   A /trunk/main/Tiarra/Mixin/AttachPackage.pm (from /trunk/main/Tiarra/Mixin/AttachPackage.pm:876)
+
+* revert r877.
+  - want to use constant FOOBAR => __PACKAGE__->attached_package(qw(baz)).
+------------------------------------------------------------------------
+r877 | topia | 2005-03-28 12:34:35 +0900 (Mon, 28 Mar 2005) | 3 lines
+Changed paths:
+   M /trunk/main/Module.pm
+   D /trunk/main/Tiarra/Mixin/AttachPackage.pm
+
+* remove Tiarra::Mixin::AttachPackage.
+  - this is not bad idea to source cleanup, but not optimized.
+  - want to use sub () { __PACKAGE__."/...." } instead.
+------------------------------------------------------------------------
+r876 | topia | 2005-03-28 04:07:29 +0900 (Mon, 28 Mar 2005) | 3 lines
+Changed paths:
+   M /trunk/main/Module.pm
+
+* import Tiarra::Mixin::AttachPackage.
+
+* refrect renaming Tiarra::Mixin::NewIRCMessage.
+------------------------------------------------------------------------
+r875 | topia | 2005-03-28 04:05:46 +0900 (Mon, 28 Mar 2005) | 1 line
+Changed paths:
+   M /trunk/main/CTCP.pm
+
+* call load_stubs.
+------------------------------------------------------------------------
+r874 | topia | 2005-03-28 04:04:59 +0900 (Mon, 28 Mar 2005) | 1 line
+Changed paths:
+   R /trunk/main/Tiarra/IRC/NewMessageMixin.pm
+   A /trunk/main/Tiarra/Mixin/NewIRCMessage.pm (from /trunk/main/Tiarra/IRC/NewMessageMixin.pm:872)
+
+* rename Tiarra::IRC::NewMessageMixin to Tiarra::Mixin::NewIRCMessage.
+------------------------------------------------------------------------
+r873 | topia | 2005-03-28 04:04:11 +0900 (Mon, 28 Mar 2005) | 3 lines
+Changed paths:
+   A /trunk/main/Tiarra/Mixin
+   A /trunk/main/Tiarra/Mixin/AttachPackage.pm
+
+* add new mixin directory.
+
+* add new mixin "attach_package".
+------------------------------------------------------------------------
 r872 | topia | 2005-03-27 21:16:02 +0900 (Sun, 27 Mar 2005) | 2 lines
 Changed paths:
    M /trunk/module/System/PrivTranslator.pm
diff -urN tiarra-20050327/main/CTCP.pm tiarra-20050330/main/CTCP.pm
--- tiarra-20050327/main/CTCP.pm	2005-03-27 21:22:42.000000000 +0900
+++ tiarra-20050330/main/CTCP.pm	2005-03-31 00:54:36.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: CTCP.pm 866 2005-03-26 16:57:29Z topia $
+# $Id: CTCP.pm 875 2005-03-27 19:05:46Z topia $
 # -----------------------------------------------------------------------------
 # IRCMessage中からCTCPメッセージを取り出したり、CTCPメッセージを持つIRCMessageを作ったり。
 # -----------------------------------------------------------------------------
@@ -11,6 +11,7 @@
 use base qw(Tiarra::IRC::NewMessageMixin);
 
 use SelfLoader;
+SelfLoader->load_stubs;
 1;
 __DATA__
 
diff -urN tiarra-20050327/main/IrcIO.pm tiarra-20050330/main/IrcIO.pm
--- tiarra-20050327/main/IrcIO.pm	2005-03-27 21:22:41.000000000 +0900
+++ tiarra-20050330/main/IrcIO.pm	2005-03-31 00:54:35.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: IrcIO.pm 866 2005-03-26 16:57:29Z topia $
+# $Id: IrcIO.pm 884 2005-03-30 07:14:01Z topia $
 # -----------------------------------------------------------------------------
 # IrcIOはIRCサーバー又はクライアントと接続し、IRCメッセージをやり取りする抽象クラスです。
 # -----------------------------------------------------------------------------
@@ -68,15 +68,20 @@
 	# message_io_hook
 	my $filtered = $this->_runloop->apply_filters(
 	    [$msg], 'message_io_hook', $this, 'out');
+
+	# message_encoding_hook
+	$filtered = $this->_runloop->apply_filters(
+	    $filtered, 'message_encoding_hook', $this, 'out', $encoding);
+
 	foreach (@$filtered) {
-	    $data_to_send .= $_->serialize($encoding)."\x0d\x0a";
+	    $data_to_send .= $_->serialize("remark,$encoding")."\x0d\x0a";
 	}
-	#$data_to_send = $msg->serialize($encoding)."\x0d\x0a";
+
     }
     else {
 	die "IrcIO::send_message : parameter msg was invalid; $msg\n";
     }
-    
+
     if ($this->connected) {
 	$this->append($data_to_send);
     }
@@ -114,12 +119,17 @@
 	    next;
 	}
 
-	# message_io_hook
 	my $msg = $this->construct_irc_message(
 	    Line => $current_line,
 	    Encoding => $encoding);
+
+	# message_encoding_hook
 	my $filtered = $this->_runloop->apply_filters(
-	    [$msg], 'message_io_hook', $this, 'in');
+	    [$msg], 'message_encoding_hook', $this, 'out', $encoding);
+
+	# message_io_hook
+	$filtered = $this->_runloop->apply_filters(
+	    $filtered, 'message_io_hook', $this, 'in');
 
 	foreach (@$filtered) {
 	    $_->purge_raw_params;
diff -urN tiarra-20050327/main/Mask.pm tiarra-20050330/main/Mask.pm
--- tiarra-20050327/main/Mask.pm	2005-03-27 21:22:41.000000000 +0900
+++ tiarra-20050330/main/Mask.pm	2005-03-31 00:54:36.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Mask.pm 866 2005-03-26 16:57:29Z topia $
+# $Id: Mask.pm 886 2005-03-30 12:59:54Z topia $
 # -----------------------------------------------------------------------------
 package Mask;
 use strict;
@@ -261,7 +261,7 @@
     my $regex = quotemeta($mask);
     $regex =~ s/\\\?/./g;
     $regex =~ s/\\\*/.*/g;
-    $regex =~ s/\\\#/\\d*/g;
+    #$regex =~ s/\\\#/\\d*/g;
     $regex = "^$regex\$";
     if ($consider_case) {
 	qr/$regex/;
diff -urN tiarra-20050327/main/Module.pm tiarra-20050330/main/Module.pm
--- tiarra-20050327/main/Module.pm	2005-03-27 21:22:41.000000000 +0900
+++ tiarra-20050330/main/Module.pm	2005-03-31 00:54:36.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Module.pm 866 2005-03-26 16:57:29Z topia $
+# $Id: Module.pm 884 2005-03-30 07:14:01Z topia $
 # -----------------------------------------------------------------------------
 # Tiarraモジュール(プラグイン)を表わす抽象クラスです。
 # 全てのTiarraモジュールはこのクラスを継承し、
@@ -11,7 +11,8 @@
 use Carp;
 use Tiarra::ShorthandConfMixin;
 use Tiarra::Utils;
-use base qw(Tiarra::IRC::NewMessageMixin);
+use base qw(Tiarra::Mixin::NewIRCMessage);
+use base qw(Tiarra::Mixin::AttachPackage);
 # our @USES = ();
 Tiarra::Utils->define_attr_getter(0, [qw(_runloop runloop)]);
 
@@ -128,6 +129,33 @@
     return $message;
 }
 
+sub message_encoding_hook {
+    my ($this,$message,$io,$type,$encoding) = @_;
+    # サーバーから受け取ったメッセージ、サーバーに送ったメッセージ、
+    # クライアントから受け取ったメッセージ、クライアントに送ったメッセージは
+    # このメソッドで各モジュールに通知される。メッセージの変更も可能で、
+    # 戻り値のルールはmessage_arrivedと同じ。このメソッドでメッセージの
+    # エンコーディングを制御することを意図している。 message_io_hook よりも I/O
+    # よりで呼び出される。送信時なら ->remark/encoding を、受信時は
+    # ->encoding_params を呼び出すことにより制御してください。
+    #
+    # 通常のモジュールはこのメソッドを実装する必要は無い。
+    #
+    # $message :
+    #    内容: Tiarra::IRC::Messageオブジェクト
+    #         送受信されたメッセージ
+    # $io :
+    #    内容: IrcIO::Server又はIrcIO::Clientオブジェクト
+    #         送受信が行なわれたIrcIO
+    # $type :
+    #    内容: 文字列
+    #         'in'なら受信、'out'なら送信。知らないタイプがきたら無視しなければならない。
+    # $encoding :
+    #    内容: 文字列
+    #         送信を予定しているエンコーディング。
+    return $message;
+}
+
 sub control_requested {
     my ($this,$request) = @_;
     # 外部コントロールプログラムからのメッセージが来た。
diff -urN tiarra-20050327/main/Multicast.pm tiarra-20050330/main/Multicast.pm
--- tiarra-20050327/main/Multicast.pm	2005-03-27 21:22:42.000000000 +0900
+++ tiarra-20050330/main/Multicast.pm	2005-03-31 00:54:36.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Multicast.pm 866 2005-03-26 16:57:29Z topia $
+# $Id: Multicast.pm 883 2005-03-29 14:32:04Z topia $
 # -----------------------------------------------------------------------------
 # サーバーからクライアントにメッセージが流れるとき、このクラスはフィルタとして
 # ネットワーク名を付加します。
@@ -195,9 +195,11 @@
 
     my $target = $message->params->[0];
     if (channel_p($target)) {
-	# nick(つまり自分)の場合はそのままクライアントに配布。
 	# この場合はチャンネルなので、ネットワーク名を付加。
 	$message->params->[0] = attach($target,$sender->network_name);
+    } else {
+	# nick(つまり自分)の場合は global_to_local を行う。
+	$message->param(0, global_to_local($message->param(0),$sender));
     }
     return $message;
 }
diff -urN tiarra-20050327/main/Tiarra/IRC/Message.pm tiarra-20050330/main/Tiarra/IRC/Message.pm
--- tiarra-20050327/main/Tiarra/IRC/Message.pm	2005-03-27 21:22:41.000000000 +0900
+++ tiarra-20050330/main/Tiarra/IRC/Message.pm	2005-03-31 00:54:36.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Message.pm 871 2005-03-27 10:43:26Z topia $
+# $Id: Message.pm 884 2005-03-30 07:14:01Z topia $
 # -----------------------------------------------------------------------------
 # Tiarra::IRC::MessageはIRCのメッセージを表わすクラスです。実際のメッセージはUTF-8で保持します。
 # 生のメッセージのパース、シリアライズ、そしてメッセージの生成をサポートします。
@@ -23,7 +23,7 @@
 #                       Host => 'hogehoge.net', # 以上３つのパラメータの代わりにPrefix => 'foo!~bar@hogehoge.net'でも良い。
 #                       Command => 'NICK',
 #                       Params => 'huga', # Paramsは要素が一つだけならスカラー値でも良い。(この時、ParamsでなくParamでも良い。)
-#                       Remarks => {'saitama' => 'SAITAMA'}, # 備考欄。シリアライズには影響しない。
+#                       Remarks => {'saitama' => 'SAITAMA'}, # 備考欄。
 # print $msg->serialize('jis'); # ":foo!~bar@hogehoge.net NICK :huga"を表示
 #
 # $msg = new Tiarra::IRC::Message(Command => 'NOTICE',
@@ -34,25 +34,146 @@
 use strict;
 use warnings;
 use Carp;
-use overload;
 use Tiarra::OptionalModules;
 use Tiarra::Utils;
 use Tiarra::IRC::Prefix;
 use Tiarra::Encoding;
 use enum qw(PREFIX COMMAND PARAMS REMARKS TIME RAW_PARAMS GENERATOR);
 
+=head1 NAME
+
+Tiarra::IRC::Message - Tiarra IRC Message class
+
+=head1 SYNOPSIS
+
+  use Tiarra::IRC::Message;
+  my $msg = Tiarra::IRC::Message->new(
+      Line => ':foo!bar@baz PRIVMSG qux :some text',
+      Encoding => 'UTF-8');
+  $msg = Tiarra::IRC::Message->new(
+      Prefix => 'foo!bar@baz',
+      Command => 'PRIVMSG',
+      Params => ['qux', 'some text']);
+  $msg->serialize('jis');
+
+  package SomePackage;
+  use base qw(Tiarra::Mixin::NewIRCMessage);
+  my $msg = __PACKAGE__->construct_irc_message(
+      Server => 'irc.foo.example.com',
+      Command => 'ERROR',
+      Params => ['bar', 'Closing Link: [foo_user!foo@baz.example.org] (Bad Password)'],
+      Remarks => {
+          'foo-remark' => 'bar',
+      });
+  $msg->serialize('remark', 'jis');
+
+=head1 DESCRIPTION
+
+Tiarra IRC Message class.
+
+=head1 CONSTANT METHODS
+
+=over 4
+
+=cut
+
+=item MAX_MIDDLES
+
+max middles count.
+
+=item MAX_PARAMS
+
+max params count.
+
+=back
+
+=cut
+
 # constants
 use constant MAX_MIDDLES => 14;
 use constant MAX_PARAMS => MAX_MIDDLES + 1;
 # max params = (middles[14] + trailing[1]) = 15
 
-utils->define_array_attr_accessor(0, qw(time generator));
-utils->define_array_attr_translate_accessor(
-    0, sub {
-	my ($from, $to) = @_;
-	"($to = $from) =~ tr/a-z/A-Z/";
-    }, qw(command));
-utils->define_proxy('prefix', 0, qw(nick name host));
+=head1 CONSTRUCTOR
+
+=over 4
+
+=cut
+
+=item new
+
+  # parse
+  my $msg = Tiarra::IRC::Message->new(
+      Line => ':foo BAR baz :qux quux', # required
+      Encoding => 'jis');
+  # construct
+  $msg = Tiarra::IRC::Message->new(
+      Server => 'foo',
+      Command => 'BAR',
+      Params => ['baz', 'qux quux']);
+
+Construct IRC Message from line or parts.
+
+=over 4
+
+=item * parse mode
+
+=over 4
+
+=item * Line
+
+line to parse.
+
+=item * Encoding
+
+encoding of line. if omitted, use 'auto' (autodetect).
+
+=back
+
+=item * parts mode
+
+=over 4
+
+=item * Prefix or Server
+
+prefix (on IRC), parsed by Tiarra::IRC::Prefix. optional.
+
+=item * Nick, User, Host
+
+nick, user, host. passed to Tiarra::IRC::Prefix. optional.
+
+=item * Command
+
+command. required.
+
+=item * Params
+
+if arrayref, copy and store as params. otherwise, store as single param. optional.
+
+=item * Param
+
+store as single param. optional.
+
+=back
+
+=item * common
+
+=over 4
+
+=item * Remarks
+
+remarks. only permit hashref, copy and store.
+
+=item * Generator
+
+Some package name or instance. please be able to call UNIVERSAL method,
+such as ->isa, ->can.
+
+=back
+
+=back
+
+=cut
 
 sub new {
     my ($class,%args) = @_;
@@ -102,11 +223,10 @@
 	    # Paramsがあった。型はスカラーもしくは配列リファ
 	    my $params = $args{'Params'};
 	    my $type = ref($params);
-	    if ($type eq '') {
-		$obj->[PARAMS] = [$params];
-	    }
-	    elsif ($type eq 'ARRAY') {
+	    if (defined $type && $type eq 'ARRAY') {
 		$obj->[PARAMS] = [@$params]; # コピーを格納
+	    } else {
+		$obj->[PARAMS] = [$params];
 	    }
 	}
 	elsif (exists $args{'Param'}) {
@@ -123,6 +243,66 @@
     $obj;
 }
 
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item time
+
+accessor for message generate time.
+
+=item generate
+
+accessor for message generator.
+
+=item command
+
+accessor for message command.
+
+=item nick
+
+=item name
+
+=item host
+
+accessor for nick, name, host. passed to Tiarra::IRC::Prefix
+
+=cut
+
+utils->define_array_attr_accessor(0, qw(time generator));
+utils->define_array_attr_translate_accessor(
+    0, sub {
+	my ($from, $to) = @_;
+	"($to = $from) =~ tr/a-z/A-Z/";
+    }, qw(command));
+utils->define_proxy('prefix', 0, qw(nick name host));
+
+=item clone
+
+  $msg->remark('a', 'foo');
+  $msg->remark('b', {
+      bar => 'baz',
+  });
+
+  # deep clone
+  $deep_clone = $msg->clone(deep => 1);
+  $deep_clone->remark('a', 'qux');         # still $msg->remark('a') is 'foo'
+  $deep_clone->remark('b')->{bar} = 'qux'; # still $msg->remark('b')->{bar} is 'baz'
+  # shallow clone
+  $shallow_clone = $msg->clone;
+  $shallow_clone->remark('a', 'qux');          # still $msg->remark('a') is 'foo'
+  $shallow_clone->remark('b')->{bar} = 'quux'; # now $msg->remark('b')->{bar} is 'quux'
+
+clone message.
+
+generator will NOT copy.
+
+even if shallow copy mode, prefix, params, remarks will clone themeselves.
+
+=cut
+
 sub clone {
     my ($this, %args) = @_;
     if ($args{deep}) {
@@ -219,10 +399,40 @@
     }
 }
 
+=item serialize
+
+  $msg->serialize('jis');
+  # remark
+  $msg->remark('encoding', 'utf8');
+  $msg->serialize('remark,jis'); # serialize and encode to utf8
+
+serialize with specified encoding.
+probe encoding flow:
+
+ specified 'remark' or 'remark,[some-fallback]'
+  - use remark/encoding.
+  - use [some-fallback] if specified.
+  - utf8
+
+ specified some encoding
+  - use this
+
+ otherwise(not specified)
+  - use utf8
+
+=cut
+
 sub serialize {
     # encodingを省略するとutf8になる。
+    # encodingをremarkで始めた場合は remark による設定を優先
     my ($this,$encoding) = @_;
-    $encoding = 'utf8' unless defined $encoding;
+
+    if (defined $encoding && $encoding =~ /^remark(?:,(.*))$/) {
+	local $_ = $this->remark('encoding');
+	$encoding = (defined && length) ? $_ : $1;
+    }
+    $encoding = 'utf8' unless defined $encoding && length $encoding;
+
     my $result = '';
 
     if ($this->prefix) {
@@ -247,7 +457,7 @@
 		# また、 remark/always-use-colon-on-last-param が付いていた場合も
 		# コロンを付ける。
 		$arg = $unicode->from_to($arg, 'utf8', $encoding);
-		if (length($arg) > 0 and
+		if (CORE::length($arg) > 0 and
 		      index($arg, ' ') == -1 and
 			index($arg, ':') != 0 and
 			    !$this->remark('always-use-colon-on-last-param')) {
@@ -269,11 +479,27 @@
     return $result;
 }
 
+=item length
+
+  $msg->length('jis');
+
+return serialized message length.
+
+=cut
+
 sub length {
     my ($this) = shift;
     CORE::length($this->serialize(@_));
 }
 
+=item params
+
+  $msg->params->[0] = ...;
+
+access to params with hashref form. not recommended.
+
+=cut
+
 sub params {
     croak "Parameter specified to params(). You must mistaked with param().\n" if (@_ > 1);
     my $this = shift;
@@ -281,10 +507,29 @@
     $this->[PARAMS];
 }
 
+=item n_params
+
+  my $param_count = $msg->n_params;
+
+return message counts (1 origin).
+
+=cut
+
 sub n_params {
     scalar @{shift->params};
 }
 
+=item param
+
+  # get
+  my $param = $msg->param($idx);
+  # set
+  $msg->param($idx, $param);
+
+access to param item (index is 0 origin).
+
+=cut
+
 sub param {
     my ($this,$index,$new_value) = @_;
     croak "Parameter index wasn't specified to param(). You must be mistaken with params().\n" if (@_ <= 1);
@@ -294,11 +539,27 @@
     $this->[PARAMS]->[$index];
 }
 
+=item push
+
+  $msg->push($fooval);
+
+append value to tail of params.
+
+=cut
+
 sub push {
     my $this = shift;
     CORE::push(@{$this->params}, @_);
 }
 
+=item pop
+
+  $msg->pop;
+
+fetch and delete last params.
+
+=cut
+
 sub pop {
     CORE::pop(@{shift->params});
 }
@@ -309,6 +570,14 @@
     $this->[RAW_PARAMS];
 }
 
+=item purge_raw_params
+
+  $this->purge_raw_params;
+
+drop raw params from parsed line.
+
+=cut
+
 sub purge_raw_params {
     shift->[RAW_PARAMS] = [];
 }
@@ -326,32 +595,83 @@
     scalar @{shift->_raw_params};
 }
 
+=item have_raw_params
+
+  if ($msg->have_raw_params) {
+      # maybe we can call ->encoding_params.
+  }
+
+we have raw params, return true. otherwise false.
+
+=cut
+
 sub have_raw_params {
     shift->_n_raw_params > 0;
 }
 
+=item remark
+
+  # return remarks hash
+  my $remarks = $msg->remark;
+  # return remark item
+  my $foo_remark = $msg->remark('foo');
+  # set remark item
+  $msg->remark('foo', $foo_remark);
+
+handle remark.
+
+=over 4
+
+=item * no argument
+
+return remarks hashref.
+
+=item * one argument ($key)
+
+return hash item of $key.
+
+=item * two argument ($key, $value)
+
+set hash item of $key to $value.
+
+=item * three argument ($key, undef, 'delete')
+
+delete hash item.
+
+=back
+
+=cut
+
 sub remark {
-    my ($this,$key,$value) = @_;
+    my $this = shift;
     # remark() -> HASH*
     # remark('key') -> SCALAR
     # remark('key','value') -> 'value'
-    if (!defined($key)) {
-	$this->[REMARKS] || {};
-    }
-    else {
-	if (defined $value) {
-	    if (defined $this->[REMARKS]) {
-		$this->[REMARKS]->{$key} = $value;
-	    }
-	    else {
-		$this->[REMARKS] = {$key => $value};
-	    }
+    $this->[REMARKS] = {} unless defined $this->[REMARKS];
+    if (@_ <= 0) {
+	$this->[REMARKS];
+    } else {
+	my $key = shift;
+	if (@_ > 2) {
+	    # have 3rd argument 'delete'
+	    delete $this->[REMARKS]->{$key};
+	} elsif (@_ > 1) {
+	    # have value
+	    $this->[REMARKS]->{$key} = shift;
+	} else {
+	    $this->[REMARKS]->{$key};
 	}
-	defined $this->[REMARKS] ?
-	    $this->[REMARKS]->{$key} : undef;
     }
 }
 
+=item encoding_params
+
+  $msg->encoding_params('utf8');
+
+re-interpret encoding of params.
+
+=cut
+
 sub encoding_params {
     my ($this, $encoding) = @_;
 
@@ -381,6 +701,12 @@
     }
 }
 
+=item prefix
+
+accessor of prefix.
+
+=cut
+
 sub prefix {
     my $this = shift;
     $this->[PREFIX] ||= Tiarra::IRC::Prefix->new;
@@ -389,3 +715,29 @@
 }
 
 1;
+
+__END__
+=back
+
+=head1 SEE ALSO
+
+L<Tiarra::IRC::Prefix>,
+L<Tiarra::Mixin::NewIRCMessage>
+
+=head1 AUTHOR
+
+originally developed by phonohawk E<lt>phonohawk@ps.sakura.ne.jpE<gt>.
+
+now maintained by Topia E<lt>topia@clovery.jpE<gt>.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2004 by phonohawk.
+
+Copyright (C) 2005 by Topia.
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.6 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut
diff -urN tiarra-20050327/main/Tiarra/IRC/NewMessageMixin.pm tiarra-20050330/main/Tiarra/IRC/NewMessageMixin.pm
--- tiarra-20050327/main/Tiarra/IRC/NewMessageMixin.pm	2005-03-27 21:22:41.000000000 +0900
+++ tiarra-20050330/main/Tiarra/IRC/NewMessageMixin.pm	2005-03-31 00:54:36.000000000 +0900
@@ -1,60 +1,21 @@
 # -----------------------------------------------------------------------------
-# $Id: NewMessageMixin.pm 866 2005-03-26 16:57:29Z topia $
+# $Id: NewMessageMixin.pm 874 2005-03-27 19:04:59Z topia $
 # -----------------------------------------------------------------------------
 # copyright (C) 2005 Topia <topia@clovery.jp>. all rights reserved.
 package Tiarra::IRC::NewMessageMixin;
-use strict;
-use warnings;
-use Tiarra::IRC::Message;
+use base qw(Tiarra::Mixin::NewIRCMessage);
 
 =head1 NAME
 
-Tiarra::IRC::NewMessageMixin - Tiarra::IRC::Message Construction Interface Mixin
-=head1 SYNOPSIS
-
-  package foo::class; 
-  use base qw(Tiarra::IRC::NewMessageMixin); # use this
-  $this->irc_message_class->foo_class_method;
-  $this->construct_irc_message(Command => ...);
+Tiarra::IRC::NewMessageMixin - deprecated by Tiarra::Mixin::NewIRCMessage
 
 =head1 DESCRIPTION
 
-Tiarra::IRC::NewMessageMixin is define Tiarra::IRC::NewMessageMixin Construction Interface as Mixin.
-
-=head1 METHODS
-
-=over 4
-
-=cut
-
-=item irc_message_class
-
-  __PACKAGE__->irc_message_class; # return Tiarra::IRC::Message
-  $this->irc_message_class; # likewise.
-
-return Tiarra::IRC::Message class. you can change class to override this.
+Tiarra::IRC::NewMessageMixin is deprecated by L<Tiarra::Mixin::NewIRCMessage> (renamed).
+please see L<Tiarra::Mixin::NewIRCMessage>.
 
 =cut
 
-sub irc_message_class () { 'Tiarra::IRC::Message' }
-
-=item construct_irc_message
-
-  __PACKAGE__->construct_irc_message(...);
-  $this->construct_irc_message(...); # likewise.
-
-constraction Tiarra::IRC::Message(or specified by ->irc_message_class).
-
-=cut
-
-sub construct_irc_message {
-    my $this = shift;
-
-    $this->irc_message_class->new(
-	Generator => $this,
-	@_);
-}
-
 1;
 
 __END__
@@ -62,7 +23,7 @@
 
 =head1 SEE ALSO
 
-L<Tiarra::IRC::Message>
+L<Tiarra::Mixin::NewIRCMessage>
 
 =head1 AUTHOR
 
diff -urN tiarra-20050327/main/Tiarra/Mixin/AttachPackage.pm tiarra-20050330/main/Tiarra/Mixin/AttachPackage.pm
--- tiarra-20050327/main/Tiarra/Mixin/AttachPackage.pm	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20050330/main/Tiarra/Mixin/AttachPackage.pm	2005-03-31 00:54:36.000000000 +0900
@@ -0,0 +1,65 @@
+# -----------------------------------------------------------------------------
+# $Id: AttachPackage.pm 878 2005-03-28 04:16:13Z topia $
+# -----------------------------------------------------------------------------
+# copyright (C) 2005 Topia <topia@clovery.jp>. all rights reserved.
+package Tiarra::Mixin::AttachPackage;
+use strict;
+use warnings;
+
+=head1 NAME
+
+Tiarra::Mixin::AttachPackage - generate package-attached name.
+
+=head1 SYNOPSIS
+
+  package SomePackage;
+  use base qw(Tiarra::Mixin::AttachPackage); # define
+  __PACKAGE__->attach_package("foo");  # SomePackage/foo
+  $this->attach_package("bar", "baz"); # SomePackage/bar/baz
+
+=head1 DESCRIPTION
+
+generate package attached name.
+
+=head1 METHODS
+
+=over 4
+
+=cut
+
+=item attach_package
+
+  __PACKAGE__->attach_package("foo", "bar", "baz");
+  $this->attach_package("foo", "bar", "baz");
+
+generate package attached name.
+
+=cut
+
+sub attach_package {
+    my $this = shift;
+    if (ref($this)) {
+	# fetch package name
+	$this = ref($this);
+    }
+    join('/', $this, @_);
+}
+
+1;
+
+__END__
+=back
+
+=head1 AUTHOR
+
+Topia E<lt>topia@clovery.jpE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2005 by Topia.
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.6 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut
diff -urN tiarra-20050327/main/Tiarra/Mixin/NewIRCMessage.pm tiarra-20050330/main/Tiarra/Mixin/NewIRCMessage.pm
--- tiarra-20050327/main/Tiarra/Mixin/NewIRCMessage.pm	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20050330/main/Tiarra/Mixin/NewIRCMessage.pm	2005-03-31 00:54:36.000000000 +0900
@@ -0,0 +1,79 @@
+# -----------------------------------------------------------------------------
+# $Id: NewIRCMessage.pm 874 2005-03-27 19:04:59Z topia $
+# -----------------------------------------------------------------------------
+# copyright (C) 2005 Topia <topia@clovery.jp>. all rights reserved.
+package Tiarra::Mixin::NewIRCMessage;
+use strict;
+use warnings;
+use Tiarra::IRC::Message;
+
+=head1 NAME
+
+Tiarra::Mixin::NewIRCMessage - Tiarra::IRC::Message Construction Interface Mixin
+=head1 SYNOPSIS
+
+  package foo::class; 
+  use base qw(Tiarra::Mixin::NewIRCMessage); # use this
+  $this->irc_message_class->foo_class_method;
+  $this->construct_irc_message(Command => ...);
+
+=head1 DESCRIPTION
+
+Tiarra::Mixin::NewIRCMessage is define Tiarra::IRC::Message Construction Interface as Mixin.
+
+=head1 METHODS
+
+=over 4
+
+=cut
+
+=item irc_message_class
+
+  __PACKAGE__->irc_message_class; # return Tiarra::IRC::Message
+  $this->irc_message_class; # likewise.
+
+return Tiarra::IRC::Message class. you can change class to override this.
+
+=cut
+
+sub irc_message_class () { 'Tiarra::IRC::Message' }
+
+=item construct_irc_message
+
+  __PACKAGE__->construct_irc_message(...);
+  $this->construct_irc_message(...); # likewise.
+
+constraction Tiarra::IRC::Message(or specified by ->irc_message_class).
+
+=cut
+
+sub construct_irc_message {
+    my $this = shift;
+
+    $this->irc_message_class->new(
+	Generator => $this,
+	@_);
+}
+
+1;
+
+__END__
+=back
+
+=head1 SEE ALSO
+
+L<Tiarra::IRC::Message>
+
+=head1 AUTHOR
+
+Topia E<lt>topia@clovery.jpE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2005 by Topia.
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.6 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut
diff -urN tiarra-20050327/main/Tiarra/Socket/Lined.pm tiarra-20050330/main/Tiarra/Socket/Lined.pm
--- tiarra-20050327/main/Tiarra/Socket/Lined.pm	2005-03-27 21:22:41.000000000 +0900
+++ tiarra-20050330/main/Tiarra/Socket/Lined.pm	2005-03-31 00:54:36.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Lined.pm 661 2004-10-15 12:09:10Z topia $
+# $Id: Lined.pm 885 2005-03-30 11:27:24Z topia $
 # -----------------------------------------------------------------------------
 # Lined Socket
 # -----------------------------------------------------------------------------
@@ -21,7 +21,7 @@
     $this->eol(utils->get_first_defined(
 	$opts{eol},
 	"\x0d\x0a"));
-    $this->{recvqueue} = [];
+    $this->{recv_queue} = [];
     $this;
 }
 
diff -urN tiarra-20050327/module/Client/GetVersion.pm tiarra-20050330/module/Client/GetVersion.pm
--- tiarra-20050327/module/Client/GetVersion.pm	2005-03-27 21:22:42.000000000 +0900
+++ tiarra-20050330/module/Client/GetVersion.pm	2005-03-31 00:54:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: GetVersion.pm 866 2005-03-26 16:57:29Z topia $
+# $Id: GetVersion.pm 879 2005-03-28 08:09:10Z topia $
 # -----------------------------------------------------------------------------
 # copyright (C) 2004 Topia <topia@clovery.jp>. all rights reserved.
 package Client::GetVersion;
@@ -8,17 +8,24 @@
 use base qw(Module);
 use CTCP;
 
-sub CTCP_VERSION_EXPIRE_TIME (){5 * 60;}
+use constant ({
+    EXPIRE_TIME => 5 * 60,
+    FETCH_EXPIRE_KEY => __PACKAGE__->attach_package('fetching-version-expire'),
+});
 
 sub client_attached {
     my ($this,$client) = @_;
 
-    my $msg = CTCP::make('VERSION', RunLoop->shared_loop->current_nick, 'PRIVMSG');
-    $msg->prefix(RunLoop->shared_loop->sysmsg_prefix(qw(system)));
-
-    $client->send_message($msg);
-    $client->remark(__PACKAGE__.'/fetching-version-expire',
-		    time() + CTCP_VERSION_EXPIRE_TIME);
+    $client->send_message(
+	$this->construct_irc_message(
+	    Prefix => $this->_runloop->sysmsg_prefix(qw(system)),
+	    Command => 'PRIVMSG',
+	    Params => [
+		$this->_runloop->current_nick,
+		CTCP->make_text('VERSION'),
+	       ],
+	   ));
+    $client->remark(FETCH_EXPIRE_KEY, time() + EXPIRE_TIME);
 }
 
 sub message_io_hook {
@@ -28,20 +35,20 @@
 	if ($type eq 'in' && $msg->command eq 'NOTICE' &&
 		!Multicast::channel_p($msg->param(0)) &&
 		    defined $msg->param(1) &&
-			defined $io->remark(__PACKAGE__.'/fetching-version-expire')) {
-	    if ($io->remark(__PACKAGE__.'/fetching-version-expire')
+			defined $io->remark(FETCH_EXPIRE_KEY)) {
+	    if ($io->remark(FETCH_EXPIRE_KEY)
 		    >= time()) {
-		my $ctcp = CTCP::extract($msg);
+		my $ctcp = CTCP->extract_from_text($msg->param(1));
 		if (defined $ctcp) {
 		    my ($command, $text) = split(/ /, $ctcp, 2);
 		    if ($command eq 'VERSION') {
 			$io->remark('client-version', $text);
-			$io->remark(__PACKAGE__.'/fetching-version-expire', undef, 'delete');
+			$io->remark(FETCH_EXPIRE_KEY, undef, 'delete');
 			return undef;
 		    }
 		}
 	    } else {
-		$io->remark(__PACKAGE__.'/fetching-version-expire', undef, 'delete');
+		$io->remark(FETCH_EXPIRE_KEY, undef, 'delete');
 	    }
 	}
     }
diff -urN tiarra-20050327/module/Log/Raw.pm tiarra-20050330/module/Log/Raw.pm
--- tiarra-20050327/module/Log/Raw.pm	2005-03-27 21:22:42.000000000 +0900
+++ tiarra-20050330/module/Log/Raw.pm	2005-03-31 00:54:36.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Raw.pm 837 2005-03-12 09:24:24Z topia $
+# $Id: Raw.pm 881 2005-03-29 12:33:43Z topia $
 # -----------------------------------------------------------------------------
 package Log::Raw;
 use strict;
@@ -232,6 +232,27 @@
     }
 }
 
+sub flush_all_file_handles {
+    my $this = shift;
+    foreach my $cached_elem (values %{$this->{writer_cache}}) {
+	eval {
+	    $cached_elem->flush;
+	};
+    }
+}
+
+sub destruct {
+    my $this = shift;
+    # 開いている全てのLog::Writerを閉じて、キャッシュを空にする。
+    foreach my $cached_elem (values %{$this->{writer_cache}}) {
+	eval {
+	    $cached_elem->flush;
+	    $cached_elem->unregister;
+	};
+    }
+    %{$this->{writer_cache}} = ();
+}
+
 1;
 
 =pod
diff -urN tiarra-20050327/tiarra tiarra-20050330/tiarra
--- tiarra-20050327/tiarra	2005-03-27 21:22:41.000000000 +0900
+++ tiarra-20050330/tiarra	2005-03-31 00:54:35.000000000 +0900
@@ -5,7 +5,7 @@
 # This is free software; you can redistribute it and/or modify it
 #   under the same terms as Perl itself.
 # -----------------------------------------------------------------------------
-# $Id: tiarra 803 2005-02-28 22:41:29Z topia $
+# $Id: tiarra 882 2005-03-29 12:53:35Z topia $
 # -----------------------------------------------------------------------------
 require 5.006;
 use strict;
@@ -423,8 +423,12 @@
     } elsif ($terminated == 2) {
 	printmsg("Second Terminate Request; Force Exit! [$msg]");
 	# force
+	print "cleanup ModuleManager...";
 	ModuleManager->shared_manager->terminate;
+	print "done.\n";
+	print "cleanup TerminateManager...";
 	Tiarra::TerminateManager->terminate('main');
+	print "done.\n";
 	exit;
     } else {
 	printmsg("Third Terminate Request; Fatal Exit! [$msg]");
@@ -434,5 +438,7 @@
 }
 
 my $exitval = main;
+print "cleanup TerminateManager...";
 Tiarra::TerminateManager->terminate('main');
+print "done.\n";
 exit $exitval;
