diff -Naur bottler-1.0.12/Makefile bottler-1.0.12-gentoo/Makefile
--- bottler-1.0.12/Makefile	2002-03-06 15:21:40.000000000 +0900
+++ bottler-1.0.12-gentoo/Makefile	2004-02-01 22:00:51.000000000 +0900
@@ -20,7 +20,7 @@
 
 install-lib:
 	mkdir -p $(libdir)
-	cp -r lib/* $(libdir)
+	cp -r lib/{bottler,bottlelib,SakuraScript}.py $(libdir)
 	(cd $(libdir) ; $(python) -c 'import compileall; compileall.compile_dir(".")')
 
 sed_dirs = sed -e "s,@python,$(python),g" -e "s,@libdir,$(exec_libdir),g"
@@ -38,6 +38,5 @@
 	$(RM) MANIFEST *~
 
 archive:
-	ln -sf $$HOME/python/kanjilib/kanjilib.py lib
 	ln -sf $$HOME/python/SakuraScript.py lib
 	$(python) setup.py sdist -f
diff -Naur bottler-1.0.12/lib/SakuraScript.py bottler-1.0.12-gentoo/lib/SakuraScript.py
--- bottler-1.0.12/lib/SakuraScript.py	2002-02-26 15:43:06.000000000 +0900
+++ bottler-1.0.12-gentoo/lib/SakuraScript.py	2004-02-01 02:21:16.000000000 +0900
@@ -250,25 +250,25 @@
 
 testcases = [
     # legal cases
-    r"\s[4]¤Á¤ã¤ó¤ÈÁª¤ó¤Ç¤è¤¦¡Á¤Ã¡£\w8\u¤Þ¤¢¡¢¥æ¡¼¥¶¤µ¤ó¤âË»¤·¤¤¤ó¤ä¤í¡Å¡Å\e",
-    r"%selfname¤È%keroname\e",
-    r"¥¨¥¹¥±¡¼¥×¤Î¥Æ¥¹¥È \\, \%, [, ], \] ¤É¡¼¤«¤Ê?\e",
+    r"\s[4]ã�¡ã‚ƒã‚“ã�¨é�¸ã‚“ã�§ã‚ˆã�†ã€œã�£ã€‚\w8\uã�¾ã�‚ã€�ãƒ¦ãƒ¼ã‚¶ã�•ã‚“ã‚‚å¿™ã�—ã�„ã‚“ã‚„ã‚�â€¥â€¥\e",
+    r"%selfnameã�¨%keroname\e",
+    r"ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—ã�®ãƒ†ã‚¹ãƒˆ \\, \%, [, ], \] ã�©ãƒ¼ã�‹ã�ª?\e",
     r"\j[http://www.asahi.com]\e",
     r"\j[http://www.asahi.com/[escape\]/\%7Etest]\e",
     r"\j[http://www.asahi.com/%7Etest/]\e",
-    r"\h\s[0]%username¤µ¤ó¤Ïº£¤É¤ó¤Ê´¶¤¸¡©\n\n\q0[#temp0][¤Þ¤¢¤Þ¤¢]\q1[#temp1][º£¤Ò¤È¤Ä]\z",
-    r"\q0[#temp0][º£Æü¤Ï%month·î%dayÆü¤À¤è]\e",
-    r"\q0[#cancel][¹Ô¤«¤Ê¤¤]\q1[http://www.asahi.com/%7Etest/][¹Ô¤¯]\e",
-    r"\q[¥Æ¥¹¥È,test]\q[%month·î%dayÆü,date]\e",
-    r"\q[¥Æ¥¹¥È,http://www.asahi.com/]\e",
-    r"\q[¥Æ¥¹¥È,http://www.asahi.com/%7Etest/]\e",
+    r"\h\s[0]%usernameã�•ã‚“ã�¯ä»Šã�©ã‚“ã�ªæ„Ÿã�˜ï¼Ÿ\n\n\q0[#temp0][ã�¾ã�‚ã�¾ã�‚]\q1[#temp1][ä»Šã�²ã�¨ã�¤]\z",
+    r"\q0[#temp0][ä»Šæ—¥ã�¯%monthæœˆ%dayæ—¥ã� ã‚ˆ]\e",
+    r"\q0[#cancel][è¡Œã�‹ã�ªã�„]\q1[http://www.asahi.com/%7Etest/][è¡Œã��]\e",
+    r"\q[ãƒ†ã‚¹ãƒˆ,test]\q[%monthæœˆ%dayæ—¥,date]\e",
+    r"\q[ãƒ†ã‚¹ãƒˆ,http://www.asahi.com/]\e",
+    r"\q[ãƒ†ã‚¹ãƒˆ,http://www.asahi.com/%7Etest/]\e",
     r"\h\s[0]%j[#temp0]\e",
     r"\URL[http://www.asahi.com/]\e",
     r"\URL[http://www.asahi.com/%7Etest/]\e",
-    r"\URL[¹Ô¤«¤Ê¤¤][http://www.asahi.com/][¥È¥Ã¥×][http://www.asahi.com/%7Etest/][¥Æ¥¹¥È]\e",
-    r"\_s\s5\w44¤¨¤ó¤¤¡¼%c\e",
+    r"\URL[è¡Œã�‹ã�ªã�„][http://www.asahi.com/][ãƒˆãƒƒãƒ—][http://www.asahi.com/%7Etest/][ãƒ†ã‚¹ãƒˆ]\e",
+    r"\_s\s5\w44ã�ˆã‚“ã�„ãƒ¼%c\e",
     r"\h%m?\e",
-    r"20%½ªÎ» (%hour»þ%minuteÊ¬%secondÉÃ)",
+    r"20%çµ‚äº† (%houræ™‚%minuteåˆ†%secondç§’)",
     r"\URL[http://www.foo.jp/%7Ebar/]",
     r"\b[0]\b[normal]\i[0]\i[eyeblink]",
     r"\c\x\t\_q\*\1\2\4\5\-\+\_+\a\__c\__t\_n",
@@ -287,9 +287,9 @@
     r"\q0[#temp0]\e",
     r"\q[test]\e",
     r"\q[foo,bar,test]\e",
-    r"\q[µ¯Æ°»þ´Ö,%exh»þ´Ö]\e",
+    r"\q[èµ·å‹•æ™‚é–“,%exhæ™‚é–“]\e",
     r"\q[,]\e",
-    r"\URL[¤·¤ó¤Ö¡¼¤ó][http://www.asahi.com/]\e",
+    r"\URL[ã�—ã‚“ã�¶ãƒ¼ã‚“][http://www.asahi.com/]\e",
     ]
 
 def test_tokenizer():
diff -Naur bottler-1.0.12/lib/bottlelib.py bottler-1.0.12-gentoo/lib/bottlelib.py
--- bottler-1.0.12/lib/bottlelib.py	2002-01-06 17:42:28.000000000 +0900
+++ bottler-1.0.12-gentoo/lib/bottlelib.py	2004-02-01 20:53:16.000000000 +0900
@@ -2,6 +2,7 @@
 #
 #  bottlelib.py - SSTP Bottle (SLPP 2.0) client library
 #                 Tamito KAJIYAMA <28 May 2001>
+#                 Atzm WATANABE   <01 Feb 2004>
 #
 #  $Id: bottlelib.py,v 1.8 2002/01/06 08:42:28 kajiyama Exp $
 #
@@ -15,8 +16,6 @@
 import StringIO
 import sys
 
-import kanjilib
-
 AGENT_NAME = os.path.basename(sys.argv[0])
 
 HOST = "bottle.mikage.to"
@@ -35,14 +34,9 @@
 class BottleClient:
     MessageClass = mimetools.Message
 
-    def __init__(self, kanjicode, kanjierror="replace"):
-        if kanjicode not in ["EUC-JP", "Shift_JIS", "ISO-2022-JP"]:
-            raise ValueError, "unsupported kanji code (%s)" % str(kanjicode)
-        # select application-specific kanji code converters
-        # stoc() = server to client
-        # ctos() = client to server
-        self.stoc = kanjilib.get_converter("Shift_JIS", kanjicode)
-        self.ctos = kanjilib.get_converter(kanjicode, "Shift_JIS")
+    def __init__(self, kanjierror="replace"):
+        self.stoc = lambda x: unicode(x, "sjis")
+        self.ctos = lambda x: x.encode("sjis")
         self.luid = ""
         self.initialized = self.connected = 0
         self.sock_buffer = []
@@ -390,7 +384,7 @@
         print "LUID:", client.luid
         print "Users:", client.users
     if list_channels:
-        perm = {0: "", 1: " (¼õ¿®¤Î¤ß)"}
+        perm = {0: "", 1: " (å�—ä¿¡ã�®ã�¿)"}
         for i in range(len(client.channels)):
             dict = client.channels[i]
             print "%d: %s%s" % (i, dict["name"], perm[dict["nopost"]])
diff -Naur bottler-1.0.12/lib/bottler.py bottler-1.0.12-gentoo/lib/bottler.py
--- bottler-1.0.12/lib/bottler.py	2002-03-06 15:12:38.000000000 +0900
+++ bottler-1.0.12-gentoo/lib/bottler.py	2004-02-05 18:08:44.923313192 +0900
@@ -2,8 +2,7 @@
 #
 #  bottler.py - an SSTP Bottle client in Python
 #               Tamito KAJIYAMA <30 May 2001>
-#
-#  NOTE: This file contains Japanese characters (EUC-JP).
+#               Atzm WATANABE   <01 Feb 2004>
 #
 #  $Id: bottler.py,v 1.18 2002/03/06 06:12:38 kajiyama Exp $
 #
@@ -12,6 +11,7 @@
 
 from Tkinter import *
 from Dialog  import Dialog
+from types   import UnicodeType, StringType
 
 import fcntl
 import getopt
@@ -21,35 +21,119 @@
 import string
 import StringIO
 import time
+import re
+import tkFont
 
 from bottlelib import BottleClient, BottleClientError
 
 import SakuraScript
-import kanjilib
 
 LIBDIR = "~/.bottlecase"
 
-# platform-specific kanji code (used for application's internal,
-# GUI, and log file codes.  These must be identical.)
-KANJICODE = "EUC-JP"
-
 # vote types
 VOTE = "Vote"
 AGREE = "Agree"
 
+class FontManager:
+    FILE = "font.cfg"
+    def __init__(self, app):
+        self.logdir = open_bottlecase()
+        self.app = app
+        self.fonts = []
+        self.DEFAULT = None
+        # lock file
+        # self.lockfile = open(os.path.join(self.logdir, ".fontlock"), "w")
+        #try:
+        #    fcntl.flock(self.lockfile.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
+        #except IOError:
+        #    self.disabled = 1
+        #    return
+        #self.disabled = 0
+        # load file
+        self.dbpath = os.path.join(self.logdir, self.FILE)
+        self.load_file()
+    def load_file(self):
+        try:
+            file = open(self.dbpath)
+        except IOError:
+            pass
+        else:
+            while 1:
+                line = file.readline()
+                line = re.split("\s*#\s*", line)[0]
+                if not line:
+                    break
+                if line[-2] == '\r':
+                    line = line[:-2]
+                elif line[-1] == '\n':
+                    line = line[:-1] # chomp :-(
+                try:
+                    aliases = re.split('\s*:\s*', line)
+                except AttributeError:
+                    pass
+                else:
+                    self.fonts.append({unicode(aliases[0], "utf-8"): aliases[1]})
+    def find_font(self):
+        fonts = tkFont.names()
+        if fonts:
+            return tkFont.Font(font=fonts[0])
+        if self.DEFAULT:
+            return tkFont.Font(family=self.DEFAULT, size=10, weight=NORMAL, slant="roman",
+                               underline=0, overstrike=0, name=self.DEFAULT)
+        for reg in ["ms", "aqua", "kochi", "mikachan", "marumoji", "gothic", "mincho"]:
+            reg = re.compile(reg, re.IGNORECASE)
+            for fm in tkFont.families():
+                if reg.match(fm):
+                    self.DEFAULT = fm
+                    return tkFont.Font(family=fm, size=10, weight=NORMAL, slant="roman",
+                                       underline=0, overstrike=0, name=fm)
+        self.DEFAULT = "fixed"
+        return tkFont.Font(family="fixed", size=16, weight=NORMAL, slant="roman",
+                           underline=0, overstrike=0, name="fixed")
+    def changeFont(self, font):
+        for i in range(len(self.app.all_item)):
+            self.app.all_item[i].config(font=font)
+    def fontlist(self):
+        if not self.fonts:
+            self.fonts = [{"Fixed": "-*-fixed-medium-r-normal-*-*-*-*-*-*-*-*-*"},
+                          {"Marumoji": "-*-marumoji-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Aqua": "-*-aquafont-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Aqua(P)": "-*-aqua_pfont-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Mikachan": "-*-mikachan-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Mikachan(P)": "-*-mikachan P-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Mikachan(PB)": "-*-mikachan PB-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Mikachan(PS)": "-*-mikachan PS-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Mincho": "-*-mincho-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Minsho(Kochi)": "-*-kochi mincho-medium-r-normal-*-*-*-*-*-*-*-*-*"},
+                          {"Mincho(Ricoh)": "-ricoh-ms mincho-medium-r-normal-*-*-*-*-*-*-*-*-*"},
+                          {"Gothic": "-*-gothic-medium-r-normal-*-*-*-*-*-*-*-jisx0208.1983-0"},
+                          {"Gothic(Kochi)": "-*-kochi gothic-medium-r-normal-*-*-*-*-*-*-*-*-*"},
+                          {"Gothic(Ricoh)": "-ricoh-ms gothic-medium-r-normal-*-*-*-*-*-*-*-*-*"},
+                          {"Gothic(Ricoh,P)": "-ricoh-ms pgothic-medium-r-normal-*-*-*-*-*-*-*-*-*"},
+                          {"Gothic(Ricoh,UI)": "-ricoh-ms ui gothic-medium-r-normal-*-*-*-*-*-*-*-*-*"}]
+        return self.fonts
+
 class Bottler(BottleClient):
-    def __init__(self, app, kanjicode):
-        if kanjicode not in ["EUC-JP", "Shift_JIS", "ISO-2022-JP"]:
-            raise ValueError, "unsupported kanji code (%s)" % str(kanjicode)
-        BottleClient.__init__(self, kanjicode)
+    def __init__(self, app):
+        BottleClient.__init__(self)
         self.app = app
-        self.kanjicode = kanjicode
     def handle_sstp_message(self, message, unicast, forced):
         if not message:
             return
         # dispatch SSTP message to local SSTP server
+        ifghost = ""
+        for cmd in message.split("\r\n"):
+            if cmd[:9] == "IfGhost: ":
+                ifghost = unicode(cmd[9:], "sjis")
+                break
         if self.app.forward.get():
-            BottleClient.handle_sstp_message(self, message, unicast, forced)
+            if not self.app.acceptAll.get():
+                if self.app.sakuraname == ifghost or \
+                       self.app.target_ghost.get() == ifghost or \
+                       self.app.target_ghost.get() == Application.DEFAULT_TARGET:
+                    BottleClient.handle_sstp_message(self, message, unicast, forced)
+            else:
+                BottleClient.handle_sstp_message(self, message, unicast, forced)
         # parse SSTP message
         file = StringIO.StringIO(message)
         request = file.readline()
@@ -63,18 +147,18 @@
                 channel = "broadcast"
             else:
                 channel = self.headers["channel"]
-        func = kanjilib.get_converter(charset, self.kanjicode)
-        if func is None:
-            self.app.monitor_clear()
-            self.app.monitor_insert("Warning: unsupported kanji code (%s) - "
-                                    "skipped.\nMID: %s" % (charset, mid))
-            self.app.window.bell()
-            return
-        script = func(headers["script"], "replace")
+        script = ""
+        try:
+            script = unicode(headers["script"], "sjis")
+        except UnicodeDecodeError:
+            script = unicode(headers["script"], "utf-8")
         # log message
-        self.app.log_message(mid, channel, script)
+        self.app.log_message(mid, channel, ifghost, script)
         # ring bell
         self.app.bell(channel, script)
+        # log: auto update view
+        if self.app.log_window and self.app.log_window.auto_var.get():
+            self.app.log_window.update_view()
     def handle_dialog_message(self, message):
         self.app.monitor_clear()
         self.app.monitor_insert(message)
@@ -92,7 +176,9 @@
         self.app.close_channel(channel)
 
 class ChannelDialog(Toplevel):
-    def __init__(self, master, channels):
+    DEFAULT_FONT = None
+    def __init__(self, app, master, channels):
+        DEFAULT_FONT = app.fontmanager.find_font()
         Toplevel.__init__(self, master)
         self.transient(master)
         self.title("Bottler: Select Channels")
@@ -101,14 +187,14 @@
         self.protocol('WM_DELETE_WINDOW', self.cancel)
         frame = Frame(self)
         frame.pack(side=BOTTOM, fill=X)
-        Button(frame, text="Join", command=self.ok).pack(side=LEFT)
-        Button(frame, text="Cancel", command=self.cancel).pack(side=RIGHT)
-        self.text = Text(self, width=40, height=5)
+        Button(frame, text="Join", command=self.ok, font=DEFAULT_FONT).pack(side=LEFT)
+        Button(frame, text="Cancel", command=self.cancel, font=DEFAULT_FONT).pack(side=RIGHT)
+        self.text = Text(self, width=40, height=5, font=DEFAULT_FONT)
         self.text.pack(side=BOTTOM, fill=BOTH, expand=1)
         self.channels = channels
         self.selection = []
         for n in range(len(channels)):
-            cb = Checkbutton(self, text=channels[n]["name"], anchor=W)
+            cb = Checkbutton(self, text=channels[n]["name"], font=DEFAULT_FONT, anchor=W)
             cb.pack(side=TOP, fill=X)
             cb.bind("<Button-1>", lambda e, n=n, f=self.selected: f(n))
     def selected(self, n):
@@ -119,7 +205,7 @@
             self.selection.sort()
         self.text.config(state=NORMAL)
         self.text.delete("1.0", END)
-        self.text.insert(END, "¥´¡¼¥¹¥È: ")
+        self.text.insert(END, unicode("ã‚´ãƒ¼ã‚¹ãƒˆ: ", "utf-8"))
         self.text.insert(END, self.channels[n]["ghost"])
         self.text.insert(END, "\n")
         self.text.insert(END, self.channels[n]["info"])
@@ -138,11 +224,13 @@
         self.selection = None
         self.quit()
 
-def ScrolledText(parent, width=80, height=25):
+def ScrolledText(parent, width=80, height=25, font=None):
+    if font == None:
+        font = FontManager.find_font()
     frame = Frame(parent)
     sb = Scrollbar(frame, orient=VERTICAL)
     sb.pack(side=RIGHT, fill=Y)
-    text = Text(frame, width=width, height=height, yscrollcommand=sb.set)
+    text = Text(frame, width=width, height=height, yscrollcommand=sb.set, font=font)
     text.pack(side=LEFT, fill=BOTH, expand=1)
     sb.config(command=text.yview)
     return frame, text
@@ -169,7 +257,6 @@
     0xd0, 0x0f, 0xd0, 0x0f, 0xd0, 0x0f, 0xd0, 0x0f,
     0xd0, 0x0f, 0xd0, 0x0f, 0xd0, 0x0f, 0xf0, 0x0f};
 """
-
 class BottleIcon(Label):
     def __init__(self, master, life, color="black"):
         self.life = life
@@ -188,6 +275,7 @@
 
 class Application:
     DEFAULT_TARGET = "default"
+    DEFAULT_FONT = None
     def __init__(self, port=9801):
         self.host = ""
         self.port = port
@@ -201,22 +289,32 @@
         menubar.pack(side=TOP, fill=X)
         buttonbar = Frame(self.window)
         buttonbar.pack(side=TOP, fill=X)
-        Button(buttonbar, text="Check", command=self.check).pack(side=LEFT)
-        Button(buttonbar, text="Test", command=self.test).pack(side=LEFT)
-        self.send_button = Button(buttonbar, text="Send", command=self.send)
-        self.send_button.pack(side=LEFT)
-        Label(buttonbar, text="Channel:").pack(side=LEFT)
+        self.fontmanager = FontManager(self)
+        DEFAULT_FONT = self.fontmanager.find_font()
+        self.all_item = [] # all items which have font
+        self.all_item.append(Button(buttonbar, text="Check", command=self.check, font=DEFAULT_FONT))
+        self.all_item.append(Button(buttonbar, text="Test", command=self.test, font=DEFAULT_FONT))
+        self.send_button = Button(buttonbar, text="Send", command=self.send, font=DEFAULT_FONT)
+        self.all_item.append(self.send_button)
+
+        self.all_item.append(Label(buttonbar, text="Channel:", font=DEFAULT_FONT))
         self.channel = StringVar(self.window)
-        Label(buttonbar, textvariable=self.channel).pack(side=LEFT)
-        Label(buttonbar, text="Users:").pack(side=LEFT)
-        self.users = Label(buttonbar)
-        self.users.pack(side=LEFT)
+        self.all_item.append(Label(buttonbar, textvariable=self.channel, font=DEFAULT_FONT))
+        self.channel_ghost = StringVar(self.window)
+        self.target_font = StringVar(self.window)
+        self.all_item.append(Label(buttonbar, textvariable=self.channel_ghost, font=DEFAULT_FONT))
+        self.all_item.append(Label(buttonbar, text="Users:", font=DEFAULT_FONT))
+        self.users = Label(buttonbar, font=DEFAULT_FONT)
+        self.all_item.append(self.users)
+
         self.bottle_icon = BottleIcon(buttonbar, 30)
         self.bottle_icon.pack(side=RIGHT, padx=2)
         self.target_ghost = StringVar(self.window)
-        frame, self.monitor = ScrolledText(self.window, height=5)
+        frame, self.monitor = ScrolledText(self.window, height=5, font=DEFAULT_FONT)
+        self.all_item.append(self.monitor)
         frame.pack(side=BOTTOM, fill=X)
-        frame, self.editor = ScrolledText(self.window, height=12)
+        frame, self.editor = ScrolledText(self.window, height=12, font=DEFAULT_FONT)
+        self.all_item.append(self.editor)
         frame.pack(side=BOTTOM, fill=BOTH, expand=1)
         self.monitor.config(state=DISABLED)
         self.editor.focus_set()
@@ -237,12 +335,15 @@
                          ("c", "Clear All", self.edit_clear_all)]),
             ("Channel", []),
             ("Ghost", []),
+            ("Font", []),
             ("Window",  [("c", "Logs",      self.open_logs),
                          ("c", "Phrases",   self.open_phrases)]),
             ("Help",    [("c", "About...",  self.about)])]:
-            menubutton = Menubutton(menubar, text=text)
-            menubutton.pack(side=LEFT)
-            menu = Menu(menubutton, tearoff=0)
+            menubutton = Menubutton(menubar, text=text, font=DEFAULT_FONT)
+            self.all_item.append(menubutton)
+
+            menu = Menu(menubutton, tearoff=0, font=DEFAULT_FONT)
+            self.all_item.append(menu)
             menubutton.config(menu=menu)
             for item in itemlist:
                 if item[0] == "c":
@@ -250,93 +351,103 @@
                 elif item[0] == "s":
                     menu.add_separator()
             self.menubar.append((menu, menubutton))
-        menubutton.pack(side=RIGHT) # Help
+        self.build_font()
+
         # popup menus for editor
-        self.command_menu = Menu(title="Shortcuts")
-        for item in [("m", "¥»¥Ã¥·¥ç¥ó", [
-                          ("¥¿¥¤¥à¥¯¥ê¥Æ¥£¥«¥ë", self.insert_t),
-                          ("¥¯¥¤¥Ã¥¯",           self.insert_q),
-                          ("¥·¥ó¥¯¥í¥Ê¥¤¥º¥É",   self.insert_s)]),
+        self.command_menu = Menu(title="Shortcuts", font=DEFAULT_FONT)
+        self.all_item.append(self.command_menu)
+        for item in [("m", unicode("ã‚»ãƒƒã‚·ãƒ§ãƒ³", "utf-8"), [
+                          (unicode("ã‚¿ã‚¤ãƒ ã‚¯ãƒªãƒ†ã‚£ã‚«ãƒ«", "utf-8"), self.insert_t),
+                          (unicode("ã‚¯ã‚¤ãƒƒã‚¯", "utf-8"),           self.insert_q),
+                          (unicode("ã‚·ãƒ³ã‚¯ãƒ­ãƒŠã‚¤ã‚ºãƒ‰", "utf-8"),   self.insert_s)]),
                      ("s",),
-                     ("c", "¤µ¤¯¤é", self.insert_h),
-                     ("m", "É½¾ð", [("[0] ÁÇ",         self.insert_s0),
-                                    ("[1] ¾È¤ì",       self.insert_s1),
-                                    ("[2] ¶Ã¤­",       self.insert_s2),
-                                    ("[3] ÉÔ°Â",       self.insert_s3),
-                                    ("[4] Íî¤Á¹þ¤ß",   self.insert_s4),
-                                    ("[5] Èù¾Ð¤ß",     self.insert_s5),
-                                    ("[6] ÌÜÊÄ¤¸",     self.insert_s6),
-                                    ("[7] ÅÜ¤ê",       self.insert_s7),
-                                    ("[8] Îä¾Ð",       self.insert_s8),
-                                    ("[20] ¤Ä¤¯¤ê´ÇÈÄ", self.insert_s20),
-                                    ("[25] ²Î",         self.insert_s25)]),
+                     ("c", unicode("ã�•ã��ã‚‰", "utf-8"), self.insert_h),
+                     ("m", unicode("è¡¨æƒ…", "utf-8"), [(unicode("[0] ç´ ", "utf-8"), self.insert_s0),
+                                    (unicode("[1] ç…§ã‚Œ", "utf-8"),       self.insert_s1),
+                                    (unicode("[2] é©šã��", "utf-8"),       self.insert_s2),
+                                    (unicode("[3] ä¸�å®‰", "utf-8"),       self.insert_s3),
+                                    (unicode("[4] è�½ã�¡è¾¼ã�¿", "utf-8"),   self.insert_s4),
+                                    (unicode("[5] å¾®ç¬‘ã�¿", "utf-8"),     self.insert_s5),
+                                    (unicode("[6] ç›®é–‰ã�˜", "utf-8"),     self.insert_s6),
+                                    (unicode("[7] æ€’ã‚Š", "utf-8"),       self.insert_s7),
+                                    (unicode("[8] å†·ç¬‘", "utf-8"),       self.insert_s8),
+                                    (unicode("[20] ã�¤ã��ã‚Šçœ‹æ�¿", "utf-8"), self.insert_s20),
+                                    (unicode("[25] æ­Œ", "utf-8"),         self.insert_s25)]),
                      ("s",),
-                     ("c", "¤¦¤Ë¤å¤¦", self.insert_u),
-                     ("m", "É½¾ð", [("[10] ÁÇ",   self.insert_s10),
-                                    ("[11] ÑéÌÜ", self.insert_s11),
-                                    ("[19] ²Î",   self.insert_s19)]),
+                     ("c", unicode("ã�†ã�«ã‚…ã�†", "utf-8"), self.insert_u),
+                     ("m", unicode("è¡¨æƒ…", "utf-8"), [(unicode("[10] ç´ ", "utf-8"),   self.insert_s10),
+                                    (unicode("[11] åˆ®ç›®", "utf-8"), self.insert_s11),
+                                    (unicode("[19] æ­Œ", "utf-8"),   self.insert_s19)]),
                      ("s",),
-                     ("m", "¥¦¥§¥¤¥È", [("0.1ÉÃ", self.insert_w2),
-                                        ("0.2ÉÃ", self.insert_w4),
-                                        ("0.3ÉÃ", self.insert_w6),
-                                        ("0.4ÉÃ", self.insert_w8),
-                                        ("0.5ÉÃ", self.insert_w10),
-                                        ("0.6ÉÃ", self.insert_w12),
-                                        ("0.8ÉÃ", self.insert_w16),
-                                        ("1.0ÉÃ", self.insert_w20),
-                                        ("1.2ÉÃ", self.insert_w24),
-                                        ("1.5ÉÃ", self.insert_w30),
-                                        ("2.0ÉÃ", self.insert_w40),
-                                        ("2.5ÉÃ", self.insert_w50),
-                                        ("3.0ÉÃ", self.insert_w60)]),
-                     ("m", "¥á¥¿Ê¸»úÎó", [
-                         ("¥æ¡¼¥¶¤Î¸Æ¤ÓÌ¾",  self.insert_username),
-                         ("¼«Ê¬¤ÎÌ¾Á° (Àµ)", self.insert_selfname),
-                         ("¼«Ê¬¤ÎÌ¾Á° (¸í)", self.insert_selfname2),
-                         ("¤¦¤Ë¤å¤¦¤ÎÌ¾Á°",  self.insert_keroname)]),
+                     ("m", unicode("ã‚¦ã‚§ã‚¤ãƒˆ", "utf-8"), [(unicode("0.1ç§’", "utf-8"), self.insert_w2),
+                                        (unicode("0.2ç§’", "utf-8"), self.insert_w4),
+                                        (unicode("0.3ç§’", "utf-8"), self.insert_w6),
+                                        (unicode("0.4ç§’", "utf-8"), self.insert_w8),
+                                        (unicode("0.5ç§’", "utf-8"), self.insert_w10),
+                                        (unicode("0.6ç§’", "utf-8"), self.insert_w12),
+                                        (unicode("0.8ç§’", "utf-8"), self.insert_w16),
+                                        (unicode("1.0ç§’", "utf-8"), self.insert_w20),
+                                        (unicode("1.2ç§’", "utf-8"), self.insert_w24),
+                                        (unicode("1.5ç§’", "utf-8"), self.insert_w30),
+                                        (unicode("2.0ç§’", "utf-8"), self.insert_w40),
+                                        (unicode("2.5ç§’", "utf-8"), self.insert_w50),
+                                        (unicode("3.0ç§’", "utf-8"), self.insert_w60)]),
+                     ("m", unicode("ãƒ¡ã‚¿æ–‡å­—åˆ—", "utf-8"), [
+                         (unicode("ãƒ¦ãƒ¼ã‚¶ã�®å‘¼ã�³å��", "utf-8"),  self.insert_username),
+                         (unicode("è‡ªåˆ†ã�®å��å‰� (æ­£)", "utf-8"), self.insert_selfname),
+                         (unicode("è‡ªåˆ†ã�®å��å‰� (èª¤)", "utf-8"), self.insert_selfname2),
+                         (unicode("ã�†ã�«ã‚…ã�†ã�®å��å‰�", "utf-8"),  self.insert_keroname)]),
                      ("s",),
-                     ("c", "²þ¹Ô",   self.insert_n),
-                     ("c", "¥¯¥ê¥¢", self.insert_c),
+                     ("c", unicode("æ”¹è¡Œ", "utf-8"),   self.insert_n),
+                     ("c", unicode("ã‚¯ãƒªã‚¢", "utf-8"), self.insert_c),
                      ("c", "URL",    self.insert_url),
-                     ("m", "ÁªÂò½èÍý", [("ÁªÂò»è0", self.insert_q0),
-                                        ("ÁªÂò»è1", self.insert_q1),
-                                        ("ÁªÂò»è2", self.insert_q2),
-                                        ("ÁªÂò»è3", self.insert_q3),
-                                        ("ÁªÂò»è4", self.insert_q4),
-                                        ("ÁªÂò»è5", self.insert_q5),
-                                        ("ÁªÂò»è6", self.insert_q6),
-                                        ("ÁªÂò»è7", self.insert_q7),
-                                        ("ÁªÂò»è8", self.insert_q8),
-                                        ("ÁªÂò»è9", self.insert_q9),
-                                        ("³«»Ï",    self.insert_z),
-                                        ("³«»Ï (¥¹¥¯¥í¡¼¥ë¤Ê¤·)",
+                     ("m", unicode("é�¸æŠžå‡¦ç�†", "utf-8"), [(unicode("é�¸æŠžè‚¢0", "utf-8"), self.insert_q0),
+                                        (unicode("é�¸æŠžè‚¢1", "utf-8"), self.insert_q1),
+                                        (unicode("é�¸æŠžè‚¢2", "utf-8"), self.insert_q2),
+                                        (unicode("é�¸æŠžè‚¢3", "utf-8"), self.insert_q3),
+                                        (unicode("é�¸æŠžè‚¢4", "utf-8"), self.insert_q4),
+                                        (unicode("é�¸æŠžè‚¢5", "utf-8"), self.insert_q5),
+                                        (unicode("é�¸æŠžè‚¢6", "utf-8"), self.insert_q6),
+                                        (unicode("é�¸æŠžè‚¢7", "utf-8"), self.insert_q7),
+                                        (unicode("é�¸æŠžè‚¢8", "utf-8"), self.insert_q8),
+                                        (unicode("é�¸æŠžè‚¢9", "utf-8"), self.insert_q9),
+                                        (unicode("é–‹å§‹", "utf-8"),    self.insert_z),
+                                        (unicode("é–‹å§‹ (ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«ã�ªã�—)", "utf-8"),
                                          self.insert_y)]),
-                     ("c", "½ªÎ»",       self.insert_e)]:
+                     ("c", unicode("çµ‚äº†", "utf-8"),       self.insert_e)]:
             if item[0] == "s":
                 self.command_menu.add_separator()
             elif item[0] == "c":
                 self.command_menu.add_command(label=item[1], command=item[2])
             elif item[0] == "m":
-                submenu = Menu(self.command_menu, tearoff=0)
+                submenu = Menu(self.command_menu, tearoff=0, font=DEFAULT_FONT)
+                self.all_item.append(submenu)
                 self.command_menu.add_cascade(label=item[1], menu=submenu)
                 for label, command in item[2]:
                     submenu.add_command(label=label, command=command)
+        for i in range(len(self.all_item)):
+            try:
+                self.all_item[i].pack(side=LEFT)
+            except TclError:
+                pass
         self.window.bind("<Button-3>", self.popup_command_menu)
         # Sakura Script parser
         self.parser = SakuraScript.Parser()
         # SSTP Bottle client
-        self.client = Bottler(self, KANJICODE)
+        self.client = Bottler(self)
         self.client.debug = 2
-        self.to_sjis = kanjilib.get_converter(KANJICODE, "Shift_JIS")
-        self.sjis_to = kanjilib.get_converter("Shift_JIS", KANJICODE)
+        self.to_sjis = lambda x: x.encode("sjis")
+        self.sjis_to = lambda x: unicode(x, "sjis")
         try:
             luid = open(os.path.join(open_bottlecase(), "luid")).read()
         except IOError:
             luid = None
         if luid and len(luid) == 82:
             self.client.luid = luid
+        self.sakuraname = ""
+        self.keroname = ""
         # log manager
-        self.logger = LogManager(KANJICODE)
+        self.logger = LogManager()
         self.log_window = LogWindow(self, self.logger)
         if self.logger.is_disabled():
             menu, menubutton = self.menubar[3] # Windows
@@ -355,11 +466,27 @@
         self.path_helpers = os.path.join(open_bottlecase(), "helpers")
         self.load_helpers()
         # ghost log
+        self.acceptAll = BooleanVar()
+        self.acceptAll.set(1)
         self.local_ghost = None
         self.local_ghost_last_notified = 0
+        self.send_ghost_names()
         # initialize
         self.disable_channel()
         self.edit_clear()
+    def build_font(self):
+        menu, menubutton = self.menubar[4] # Font
+        menu.delete(0, END)
+        menu.add_radiobutton(label="Default", variable=self.target_font,
+                             command=lambda : self.fontmanager.changeFont(self.fontmanager.find_font()))
+        for f in self.fontmanager.fontlist():
+            menu.add_radiobutton(label=f.keys()[0], variable=self.target_font,
+                                 command=self.update_font)
+        self.target_font.set("Default")
+    def update_font(self):
+        for f in self.fontmanager.fontlist():
+            if f.has_key(self.target_font.get()):
+                self.fontmanager.changeFont(f[self.target_font.get()])
     def popup_command_menu(self, event):
         self.command_menu.tk_popup(event.x_root, event.y_root)
     def mainloop(self):
@@ -380,9 +507,10 @@
         if handled:
             self.bottle_icon.show()
         now = time.time()
-        if now - self.local_ghost_last_notified > 600:
+        if now - self.local_ghost_last_notified > 30: # about 30 seconds
             self.local_ghost_last_notified = now
             self.send_ghost_names()
+            self.rebuild_ghostmenu()
         self.window.after(100, self.handle_event) # 0.1s
     def quit(self, event=None):
         self.client.close()
@@ -407,7 +535,7 @@
             except IOError:
                 self.monitor_insert("\nWarning: cannot write " + filename)
                 self.window.bell()
-        channels = ChannelDialog(self.window, self.client.channels).go()
+        channels = ChannelDialog(self, self.window, self.client.channels).go()
         self.monitor_clear()
         if channels is None:
             return
@@ -436,13 +564,21 @@
             if not self.channel.get():
                 self.channel.set(name)
             menu.add_radiobutton(label=name, variable=self.channel,
-                                 command=self.check_channel_permission)
+                                 command=self.rebuild_ghostmenu)
         menu.add_separator()
         menu.add_checkbutton(label="Forward", variable=self.forward)
         menu.add_checkbutton(label="Bell", variable=self.use_bell)
         menubutton.config(state=NORMAL)
+        self.rebuild_ghostmenu()
+        self.log_window.vote_button.config(state=NORMAL)
+        self.log_window.agree_button.config(state=NORMAL)
+        self.show_users()
+    def rebuild_ghostmenu(self):
         # rebuild Ghost menu
+        current = self.target_ghost.get()
         ghosts = [self.DEFAULT_TARGET]
+        ghosts.append(self.sakuraname)
+        name = ""
         for n in range(len(self.client.channels)):
             name = self.client.channels[n]["ghost"]
             if name and name not in ghosts:
@@ -450,12 +586,24 @@
         menu, menubutton = self.menubar[3] # Ghost
         menu.delete(0, END)
         for name in ghosts:
-            menu.add_radiobutton(label=name, variable=self.target_ghost)
+            menu.add_radiobutton(label=name, variable=self.target_ghost,
+                                 command=self.update_ghost)
+        if current in ghosts:
+            self.target_ghost.set(current)
+            self.channel_ghost.set("(" + current + ")")
+        else:
+            if current != self.DEFAULT_TARGET and current != name:
+                self.target_ghost.set(self.sakuraname)
+                self.channel_ghost.set("(" + self.sakuraname + ")")
+            else:
+                self.target_ghost.set(self.DEFAULT_TARGET)
+                self.channel_ghost.set("(" + self.DEFAULT_TARGET + ")")
+        menu.add_separator()
+        menu.add_checkbutton(label="Accept all message", variable=self.acceptAll)
         menubutton.config(state=NORMAL)
-        self.log_window.vote_button.config(state=NORMAL)
-        self.log_window.agree_button.config(state=NORMAL)
         self.check_channel_permission()
-        self.show_users()
+    def update_ghost(self):
+        self.channel_ghost.set("(" + self.target_ghost.get() + ")")
     def disable_channel(self):
         menu, menubutton = self.menubar[2] # Channel
         menubutton.config(state=DISABLED)
@@ -465,6 +613,7 @@
         self.log_window.vote_button.config(state=DISABLED)
         self.log_window.agree_button.config(state=DISABLED)
         self.channel.set("")
+        self.channel_ghost.set("")
         self.target_ghost.set(self.DEFAULT_TARGET)
         self.users.config(text="")
     def get_channel_id(self):
@@ -509,7 +658,7 @@
             else:
                 break
     def assign_helpers(self, event=None):
-        result = HelperDialog(self.window, self.helpers).go()
+        result = HelperDialog(self, self.window, self.helpers).go()
         if result is None:
             return
         self.helpers = result
@@ -526,14 +675,14 @@
         file.close()
     def edit_copy(self, event=None):
         try:
-            data = self.editor.get("sel.first", "sel.last")
+            data = self.editor.get("sel.first", "sel.last").encode("euc-jp")
         except TclError:
             return
         self.window.clipboard_clear()
         self.window.clipboard_append(data)
     def edit_cut(self, event=None):
         try:
-            data = self.editor.get("sel.first", "sel.last")
+            data = self.editor.get("sel.first", "sel.last").encode("euc-jp")
         except TclError:
             return
         self.window.clipboard_clear()
@@ -544,6 +693,10 @@
             data = self.window.selection_get(selection="CLIPBOARD")
         except TclError:
             return
+        try:
+            data = unicode(data.encode("raw-unicode-escape"), "euc-jp")
+        except UnicodeDecodeError:
+            data = unicode(data, "euc-jp")
         self.editor.insert("insert", data)
     def edit_clear(self, event=None):
         self.edit_clear_all()
@@ -630,7 +783,7 @@
     def send(self, event=None):
         if self.check():
             return
-        d = Dialog(title="Bottler: Send", text="Á÷¿®¤·¤Þ¤¹¤«?",
+        d = Dialog(title="Bottler: Send", text="Send?",
                    bitmap="question", strings=("OK", "Cancel"), default=0)
         if d.num:
             return
@@ -651,7 +804,7 @@
             error = str(e)
         if error is not None:
             self.monitor_insert("failed!!\nError: ")
-            self.monitor_insert(error)
+            self.monitor_insert(unicode(error))
             self.window.bell()
         else:
             self.monitor_insert("done.\nUsers: ")
@@ -670,6 +823,7 @@
         Dialog(title="Bottler: About",
                text="bottler.py %s\n" % VERSION +
                     "(c) Tamito KAJIYAMA\n"
+                    "(c) Atzm WATANABE\n"
                     "License: GNU GPL2",
                bitmap="info", strings=("OK",), default=0)
     def bell(self, channel, script):
@@ -689,8 +843,8 @@
             command = string.replace(command, "%channel", channel)
             command = string.replace(command, "%script", script)
             os.system(command)
-    def log_message(self, mid, channel, script):
-        self.logger.log_message(mid, channel, script)
+    def log_message(self, mid, channel, ifghost, script):
+        self.logger.log_message(mid, channel, ifghost, script)
     def log_votes(self, mid, type, num):
         self.logger.log_votes(mid, type, num)
     SSTP_SEND = (
@@ -733,7 +887,14 @@
         pos = string.find(data, "\r\n\r\n")
         if pos < 0:
             return
-        name = self.sjis_to(string.strip(data[pos:]))
+
+        resdata = data[pos:]
+        try:
+            resdata = unicode(resdata, "utf8").encode("sjis")
+        except UnicodeError:
+            pass
+
+        name = self.sjis_to(string.strip(resdata))
         if not name or self.local_ghost == name:
             return
         try:
@@ -741,6 +902,7 @@
         except BottleClientError, e:
             return
         self.local_ghost = name
+        [self.sakuraname, self.keroname] = self.local_ghost.split("\n")[0].split(",")
     def monitor_clear(self):
         self.monitor.config(state=NORMAL)
         self.monitor.delete("1.0", END)
@@ -833,6 +995,7 @@
     DBWRITEFREQ = 10 # write database to file per 10 votes
     # channel
     ALL_CHANNELS = "-"
+    ALL_GHOSTS   = "-"
     # ranges
     RANGE_TODAY     = 1
     RANGE_YESTERDAY = 2
@@ -844,10 +1007,7 @@
     ORDER_BY_NEWNESS  = 100
     ORDER_BY_DATETIME = 101
     ORDER_BY_VOTES    = 102
-    def __init__(self, kanjicode):
-        if kanjicode not in ["EUC-JP", "Shift_JIS", "ISO-2022-JP"]:
-            raise ValueError, "unsupported kanji code (%s)" % str(kanjicode)
-        self.han2zen = kanjilib.get_han2zen_converter(kanjicode)
+    def __init__(self):
         self.logdir = open_bottlecase()
         # lock database
         self.lockfile = open(os.path.join(self.logdir, ".lock"), "w")
@@ -863,8 +1023,9 @@
         self.load_database()
         # defaults
         self.channel = None # all channels
-        self.range = self.RANGE_TODAY
-        self.order = self.ORDER_BY_NEWNESS
+        self.ghost   = None
+        self.range   = self.RANGE_TODAY
+        self.order   = self.ORDER_BY_NEWNESS
     def is_disabled(self):
         return self.disabled
     def load_database(self):
@@ -878,6 +1039,7 @@
             nchannels = int(file.readline())
             for n in range(nchannels):
                 channel, alias = string.split(file.readline())
+                channel = unicode(channel, "utf-8")
                 self.aliases[channel] = alias
             while 1:
                 line = file.readline()
@@ -903,7 +1065,7 @@
         else:
             file.write("%d\n" % len(self.channels))
             for channel, alias in self.aliases.items():
-                file.write("%s %s\n" % (channel, alias))
+                file.write("%s %s\n" % (channel.encode("utf-8"), alias))
             for mid, dict in self.votes.items():
                 v = dict.get(VOTE,  0)
                 a = dict.get(AGREE, 0)
@@ -914,10 +1076,11 @@
             return
         self.save_database()
         fcntl.flock(self.lockfile.fileno(), fcntl.LOCK_UN)
-    def log_message(self, mid, channel, script):
+    def log_message(self, mid, channel, ifghost, script):
         if self.disabled:
             return
         # register an alias to channel if necessary
+
         if channel not in self.channels:
             self.channels.append(channel)
             self.channels.sort()
@@ -927,8 +1090,10 @@
         datetime = time.strftime("%Y%m%d%H%M%S", now)
         filename = "%s-%s.log" % (datetime[:8], self.aliases[channel])
         file = open(os.path.join(self.logdir, filename), "a")
-        file.write("%s\t%s\t%s\t%s\n" % (datetime, mid, channel,
-                                         self.han2zen(script)))
+        file.write("%s\t%s\t%s\t%s\t%s\n" % (datetime, mid.encode("utf-8"),
+                                             channel.encode("utf-8"),
+                                             ifghost.encode("utf-8"),
+                                             script.encode("utf-8")))
         file.close()
     def log_votes(self, mid, type, num):
         if self.disabled:
@@ -946,16 +1111,16 @@
         buffer = []
         file = open(path)
         while 1:
-            line = file.readline()
+            line = unicode(file.readline(), "utf-8")
             if not line:
                 break
-            datetime, mid, channel, script = string.split(line, "\t", 3)
+            datetime, mid, channel, ifghost, script = string.split(line, "\t", 4)
             assert(len(datetime) == 14)
             dict = self.votes.get(mid, {})
             v = dict.get(VOTE,  0)
             a = dict.get(AGREE, 0)
             buffer.append((datetime, mid, v, a,
-                           channel, string.rstrip(script)))
+                           channel, ifghost, string.rstrip(script)))
         return buffer
     def reload(self):
         if self.disabled:
@@ -1017,22 +1182,29 @@
                 c = max(c, len(channel))
         else:
             c = len(self.channel)
-        format = "%%s/%%s/%%s %%s:%%s:%%s %%%dd %%%dd  %%-%ds  %%s" % (v, a, c)
+        g = 0
+        for ghost in self.log:
+            g = max(g, len(ghost[5].encode("iso-2022-jp")) / 2)
         self.formatted_log = []
-        for datetime, mid, votes, agreements, channel, script in self.log:
+        for datetime, mid, votes, agreements, channel, ifghost, script in self.log:
+            format = "%%s/%%s/%%s %%s:%%s:%%s %%%dd %%%dd  %%-%ds  %%-%ds %%s" % (v, a, c + c - len(channel), g + g - len(ifghost.encode("iso-2022-jp")) / 2)
             self.formatted_log.append(format % (datetime[0:4],   # year
                                                 datetime[4:6],   # month
                                                 datetime[6:8],   # day
                                                 datetime[8:10],  # hour
                                                 datetime[10:12], # minute
                                                 datetime[12:14], # second
-                                                votes, agreements,
-                                                channel, script))
+                                                votes, agreements,  channel,
+                                                ifghost, script))
         return 0
     def set_channel(self, channel):
         self.channel = channel
     def get_channel(self):
         return self.channel
+    def set_ghost(self, ghost):
+        self.ghost = ghost
+    def get_ghost(self):
+        return self.ghost
     def set_range(self, range, range_start=None, range_end=None):
         self.range = range
         if range == self.RANGE_SPECIFIED:
@@ -1057,10 +1229,12 @@
     def get_script(self, index):
         if self.disabled or index >= len(self.log):
             return None
-        return self.log[index][5]
+        return self.log[index][6]
 
 class DateRangeDialog(Toplevel):
-    def __init__(self, master):
+    DEFAULT_FONT = None
+    def __init__(self, app, master):
+        DEFAULT_FONT = app.fontmanager.find_font()
         Toplevel.__init__(self, master)
         self.transient(master)
         self.title("Bottler: Select Dates")
@@ -1069,36 +1243,44 @@
         self.protocol('WM_DELETE_WINDOW', self.cancel)
         frame = Frame(self)
         frame.pack(side=BOTTOM, fill=X)
-        Button(frame, text="OK", command=self.ok).pack(side=LEFT)
-        Button(frame, text="Cancel", command=self.cancel).pack(side=RIGHT)
+        ba = Button(frame, text="OK", command=self.ok, font=DEFAULT_FONT)
+        ba.pack(side=LEFT)
+        bb = Button(frame, text="Cancel", command=self.cancel, font=DEFAULT_FONT)
+        bb.pack(side=RIGHT)
         frame = Frame(self)
         frame.pack(side=BOTTOM, fill=X, padx=2, pady=2)
         y1, m1, d1 = time.localtime(master.range_start or time.time())[0:3]
         y2, m2, d2 = time.localtime(master.range_end   or time.time())[0:3]
-        self.y1 = Entry(frame, width=5)
+        self.y1 = Entry(frame, width=5, font=DEFAULT_FONT)
         self.y1.insert(END, str(y1))
         self.y1.pack(side=LEFT)
-        Label(frame, text="Ç¯").pack(side=LEFT)
-        self.m1 = Entry(frame, width=3)
+        la = Label(frame, text=unicode("å¹´", "utf-8"), font=DEFAULT_FONT)
+        la.pack(side=LEFT)
+        self.m1 = Entry(frame, width=3, font=DEFAULT_FONT)
         self.m1.insert(END, str(m1))
         self.m1.pack(side=LEFT)
-        Label(frame, text="·î").pack(side=LEFT)
-        self.d1 = Entry(frame, width=3)
+        lb = Label(frame, text=unicode("æœˆ", "utf-8"), font=DEFAULT_FONT)
+        lb.pack(side=LEFT)
+        self.d1 = Entry(frame, width=3, font=DEFAULT_FONT)
         self.d1.insert(END, str(d1))
         self.d1.pack(side=LEFT)
-        Label(frame, text="Æü¡Á").pack(side=LEFT)
-        self.y2 = Entry(frame, width=5)
+        lc = Label(frame, text=unicode("æ—¥ã€œ", "utf-8"), font=DEFAULT_FONT)
+        lc.pack(side=LEFT)
+        self.y2 = Entry(frame, width=5, font=DEFAULT_FONT)
         self.y2.insert(END, str(y2))
         self.y2.pack(side=LEFT)
-        Label(frame, text="Ç¯").pack(side=LEFT)
-        self.m2 = Entry(frame, width=3)
+        ld = Label(frame, text=unicode("å¹´", "utf-8"), font=DEFAULT_FONT)
+        ld.pack(side=LEFT)
+        self.m2 = Entry(frame, width=3, font=DEFAULT_FONT)
         self.m2.insert(END, str(m2))
         self.m2.pack(side=LEFT)
-        Label(frame, text="·î").pack(side=LEFT)
-        self.d2 = Entry(frame, width=3)
+        le = Label(frame, text=unicode("æœˆ", "utf-8"), font=DEFAULT_FONT)
+        le.pack(side=LEFT)
+        self.d2 = Entry(frame, width=3, font=DEFAULT_FONT)
         self.d2.insert(END, str(d2))
         self.d2.pack(side=LEFT)
-        Label(frame, text="Æü").pack(side=LEFT)
+        lf = Label(frame, text=unicode("æ—¥", "utf-8"), font=DEFAULT_FONT)
+        lf.pack(side=LEFT)
     def go(self):
         try:
             self.grab_set()
@@ -1130,64 +1312,74 @@
                 self.quit()
                 return
         Dialog(title="Bottler: Invalid Dates",
-               text="ÆüÉÕ¤ÎÈÏ°Ï¤¬ÉÔÀµ¤Ç¤¹¡£\nÆþÎÏ¤·Ä¾¤·¤Æ²¼¤µ¤¤¡£",
+               text=unicode("æ—¥ä»˜ã�®ç¯„å›²ã�Œä¸�æ­£ã�§ã�™ã€‚\nå…¥åŠ›ã�—ç›´ã�—ã�¦ä¸‹ã�•ã�„ã€‚", "utf-8"),
                bitmap="error", strings=("OK",), default=0)
     def cancel(self, event=None):
         self.selection = None
         self.quit()
 
 class LogWindow(SubWindow):
+    DEFAULT_FONT = None
     def __init__(self, app, logger):
         self.app = app
         self.logger = logger
         # create GUI
+        DEFAULT_FONT = app.fontmanager.find_font()
         SubWindow.__init__(self, self.app.window)
         self.title("Bottler: Logs")
         menubar = Frame(self, relief=RAISED, border=2)
         menubar.pack(side=TOP, fill=X)
         buttonbar = Frame(self)
         buttonbar.pack(side=TOP, fill=X)
-        self.play_button = Button(buttonbar, text="Play", command=self.play)
+        self.play_button = Button(buttonbar, text="Play", command=self.play, font=DEFAULT_FONT)
         self.play_button.pack(side=LEFT)
-        self.vote_button = Button(buttonbar, text="Vote", command=self.vote)
+        self.vote_button = Button(buttonbar, text="Vote", command=self.vote, font=DEFAULT_FONT)
         self.vote_button.pack(side=LEFT)
-        self.agree_button = Button(buttonbar, text="Agree", command=self.agree)
+        self.agree_button = Button(buttonbar, text="Agree", command=self.agree, font=DEFAULT_FONT)
         self.agree_button.pack(side=LEFT)
-        Label(buttonbar, text="Channel:").pack(side=LEFT)
-        self.channel = Label(buttonbar)
+        la = Label(buttonbar, text="Channel:", font=DEFAULT_FONT)
+        la.pack(side=LEFT)
+        self.channel = Label(buttonbar, font=DEFAULT_FONT)
         self.channel.pack(side=LEFT)
-        Label(buttonbar, text="Range:").pack(side=LEFT)
-        self.range = Label(buttonbar)
+        lb = Label(buttonbar, text="Range:", font=DEFAULT_FONT)
+        lb.pack(side=LEFT)
+        self.range = Label(buttonbar, font=DEFAULT_FONT)
         self.range.pack(side=LEFT)
-        Label(buttonbar, text="Order:").pack(side=LEFT)
-        self.order = Label(buttonbar)
+        lc = Label(buttonbar, text="Order:", font=DEFAULT_FONT)
+        lc.pack(side=LEFT)
+        self.order = Label(buttonbar, font=DEFAULT_FONT)
         self.order.pack(side=LEFT)
-        frame, self.viewer = ScrolledText(self, height=8)
+        self.auto_var = BooleanVar()
+        frame, self.viewer = ScrolledText(self, height=8, font=DEFAULT_FONT)
         frame.pack(side=BOTTOM, fill=X)
         frame, self.listbox = ScrolledListbox(self, height=12)
         frame.pack(side=BOTTOM, fill=BOTH, expand=1)
+        for tmp in [la, lb, lc, self.play_button, self.vote_button, self.agree_button,
+                    self.channel, self.range, self.order, self.viewer, self.listbox]:
+            app.all_item.append(tmp)
         self.viewer.config(state=DISABLED)
-        self.listbox.config(font="fixed") # XXX
+        self.listbox.config(font=DEFAULT_FONT) # XXX
         self.listbox.config(selectmode=SINGLE)
         self.listbox.bind("<ButtonRelease-1>", self.show_script)
         # menus
         self.labels = {
-            LogManager.ALL_CHANNELS:      "¤¹¤Ù¤Æ",
-            LogManager.RANGE_TODAY:       "º£Æü",
-            LogManager.RANGE_YESTERDAY:   "ºòÆü",
-            LogManager.RANGE_LAST3DAYS:   "²áµî»°Æü´Ö",
-            LogManager.RANGE_LAST7DAYS:   "²áµî°ì½µ´Ö",
-            LogManager.RANGE_SPECIFIED:   "»ØÄê´ü´Ö",
-            LogManager.RANGE_ALL:         "¤¹¤Ù¤Æ",
-            LogManager.ORDER_BY_NEWNESS:  "¿·Ãå½ç",
-            LogManager.ORDER_BY_DATETIME: "ÆüÉÕ½ç",
-            LogManager.ORDER_BY_VOTES:    "ÆÀÉ¼½ç",
+            LogManager.ALL_CHANNELS:      unicode("ã�™ã�¹ã�¦", "utf-8"),
+            LogManager.RANGE_TODAY:       unicode("ä»Šæ—¥", "utf-8"),
+            LogManager.RANGE_YESTERDAY:   unicode("æ˜¨æ—¥", "utf-8"),
+            LogManager.RANGE_LAST3DAYS:   unicode("é�ŽåŽ»ä¸‰æ—¥é–“", "utf-8"),
+            LogManager.RANGE_LAST7DAYS:   unicode("é�ŽåŽ»ä¸€é€±é–“", "utf-8"),
+            LogManager.RANGE_SPECIFIED:   unicode("æŒ‡å®šæœŸé–“", "utf-8"),
+            LogManager.RANGE_ALL:         unicode("ã�™ã�¹ã�¦", "utf-8"),
+            LogManager.ORDER_BY_NEWNESS:  unicode("æ–°ç�€é †", "utf-8"),
+            LogManager.ORDER_BY_DATETIME: unicode("æ—¥ä»˜é †", "utf-8"),
+            LogManager.ORDER_BY_VOTES:    unicode("å¾—ç¥¨é †", "utf-8"),
             }
         self.view = []
         for text, itemlist in [
             ("File", [("c", "Close",     self.close)]),
             ("Edit", [("c", "Copy",      self.edit_copy)]),
             ("View", [("c", "Update",    self.update_view),
+                      ("cb", "Auto Update", self.auto_var, 1),
                       ("s",),
                       ("m", "Range",   "i", [
                           LogManager.RANGE_TODAY,
@@ -1203,17 +1395,23 @@
                           LogManager.ORDER_BY_DATETIME,
                           LogManager.ORDER_BY_VOTES])]),
             ("Help", [("c", "About...",  self.app.about)])]:
-            menubutton = Menubutton(menubar, text=text)
+            menubutton = Menubutton(menubar, text=text, font=DEFAULT_FONT)
+            app.all_item.append(menubutton)
             menubutton.pack(side=LEFT)
-            menu = Menu(menubutton, tearoff=0)
+            menu = Menu(menubutton, tearoff=0, font=DEFAULT_FONT)
+            app.all_item.append(menu)
             menubutton.config(menu=menu)
             for item in itemlist:
                 if item[0] == "c":
                     menu.add_command(label=item[1], command=item[2])
                 elif item[0] == "s":
                     menu.add_separator()
+                elif item[0] == "cb":
+                    item[2].set(item[3])
+                    menu.add_checkbutton(label=item[1], variable=item[2])
                 elif item[0] == "m":
-                    submenu = Menu(menu, tearoff=0)
+                    submenu = Menu(menu, tearoff=0, font=DEFAULT_FONT)
+                    app.all_item.append(submenu)
                     menu.add_cascade(label=item[1], menu=submenu)
                     if item[2] == "s":
                         variable = StringVar(self)
@@ -1237,12 +1435,14 @@
         selected_range   = self.view[0][1].get()
         selected_channel = self.view[1][1].get()
         selected_order   = self.view[2][1].get()
+        #selected_ghost   = self.view[3][1].get()
         range_changed = (selected_channel == self.logger.get_channel() and
-                         selected_order   == self.logger.get_order())
+                         selected_order   == self.logger.get_order())#   and
+        #                 selected_ghost   == self.logger.get_ghost())
         if selected_range != LogManager.RANGE_SPECIFIED:
             self.range_start = self.range_end = None
         elif from_menu and range_changed:
-            selection = DateRangeDialog(self).go()
+            selection = DateRangeDialog(self.app, self).go()
             if selection is None:
                 submenu, variable = self.view[0] # Range
                 variable.set(self.logger.get_range())
@@ -1254,7 +1454,7 @@
         if selected_range == LogManager.RANGE_SPECIFIED:
             s = time.strftime("%Y/%m/%d", time.localtime(self.range_start))
             e = time.strftime("%Y/%m/%d", time.localtime(self.range_end))
-            self.range.config(text="%s¡Á%s" % (s, e))
+            self.range.config(text="%sã€œ%s" % (s, e))
         else:
             self.range.config(text=self.labels[selected_range])
         self.channel.config(text=self.labels[selected_channel])
@@ -1285,7 +1485,7 @@
         # update channel menu
         submenu, variable = self.view[1] # Channel
         submenu.delete(0, END)
-        submenu.add_radiobutton(label="¤¹¤Ù¤Æ", value=LogManager.ALL_CHANNELS,
+        submenu.add_radiobutton(label=unicode("ã�™ã�¹ã�¦", "utf-8"), value=LogManager.ALL_CHANNELS,
                                 variable=variable,
                                 command=self.update_view)
         for channel in self.logger.get_selected_channels():
@@ -1310,7 +1510,7 @@
         mid = self.logger.get_mid(self.listbox.index("anchor"))
         if mid is None:
             return
-        d = Dialog(title="Bottler: Vote", text="ÅêÉ¼¤·¤Þ¤¹¤«?",
+        d = Dialog(title="Bottler: Vote", text="Vote?",
                    bitmap="question", strings=("OK", "Cancel"), default=0)
         if d.num:
             return
@@ -1319,14 +1519,14 @@
         mid = self.logger.get_mid(self.listbox.index("anchor"))
         if mid is None:
             return
-        d = Dialog(title="Bottler: Agree", text="Æ±°Õ¤·¤Þ¤¹¤«?",
+        d = Dialog(title="Bottler: Agree", text="Agree?",
                    bitmap="question", strings=("OK", "Cancel"), default=0)
         if d.num:
             return
         self.app.vote_message(mid, AGREE)
     def edit_copy(self, event=None):
         try:
-            data = self.viewer.get("sel.first", "sel.last")
+            data = self.viewer.get("sel.first", "sel.last").encode("euc-jp")
         except TclError:
             return
         self.clipboard_clear()
@@ -1348,7 +1548,7 @@
         except IOError:
             return
         while 1:
-            line = file.readline()
+            line = unicode(file.readline(), "utf-8")
             if not line:
                 break
             elif line[0] == "#":
@@ -1368,7 +1568,7 @@
         file.write("# This is an auto-generated file.\n")
         file.write("# Don't edit this file while running bottler.py!\n")
         for line in self.phrases:
-            file.write(line + "\n")
+            file.write(line.encode("utf-8") + "\n")
         file.close()
     def close(self):
         self.save_database()
@@ -1426,10 +1626,12 @@
 """
 
 class PhraseWindow(SubWindow):
+    DEFAULT_FONT = None
     def __init__(self, app, manager):
         self.app = app
         self.manager = manager
         # create GUI
+        DEFAULT_FONT = app.fontmanager.find_font()
         SubWindow.__init__(self, self.app.window)
         self.title("Bottler: Phrases")
         menubar = Frame(self, relief=RAISED, border=2)
@@ -1440,24 +1642,34 @@
         frame.pack(side=RIGHT)
         self.image1 = BitmapImage(data=CURSOR_UP)
         self.image2 = BitmapImage(data=CURSOR_DOWN)
-        Button(frame, image=self.image1, command=self.move_up).pack(side=TOP)
-        Button(frame, image=self.image2, command=self.move_down).pack(side=TOP)
+        ba = Button(frame, image=self.image1, command=self.move_up, font=DEFAULT_FONT)
+        ba.pack(side=TOP)
+        bb = Button(frame, image=self.image2, command=self.move_down, font=DEFAULT_FONT)
+        bb.pack(side=TOP)
         frame = Frame(toolbar)
         frame.pack(side=LEFT, fill=X, expand=1)
         self.editor = Entry(frame)
-        self.editor.config(font="fixed") # XXX
+        app.all_item.append(self.editor)
+        self.editor.config(font=DEFAULT_FONT) # XXX
         self.editor.pack(side=TOP, fill=X, expand=1)
         self.editor.bind("<Return>", self.add)
         self.editor.focus_set()
-        Button(frame, text="Clear", command=self.clear).pack(side=LEFT)
-        Button(frame, text="Add", command=self.add).pack(side=LEFT)
-        Button(frame, text="Modify", command=self.modify).pack(side=LEFT)
-        Button(frame, text="Delete", command=self.delete).pack(side=LEFT)
+        bc = Button(frame, text="Clear", command=self.clear, font=DEFAULT_FONT)
+        bc.pack(side=LEFT)
+        bd = Button(frame, text="Add", command=self.add, font=DEFAULT_FONT)
+        bd.pack(side=LEFT)
+        be = Button(frame, text="Modify", command=self.modify, font=DEFAULT_FONT)
+        be.pack(side=LEFT)
+        bf = Button(frame, text="Delete", command=self.delete, font=DEFAULT_FONT)
+        bf.pack(side=LEFT)
         frame, self.listbox = ScrolledListbox(self, width=40, height=20)
+        app.all_item.append(self.listbox)
         frame.pack(side=TOP, fill=BOTH, expand=1)
-        self.listbox.config(font="fixed") # XXX
+        self.listbox.config(font=DEFAULT_FONT) # XXX
         self.listbox.bind("<ButtonRelease-1>", self.selected)
         self.listbox.bind("<Double-Button-1>", self.insert)
+        for tmp in [ba, bb, bc, bd, be, bf]:
+            app.all_item.append(tmp)
         # menus
         for text, itemlist in [
             ("File", [("c", "Close",     self.close)]),
@@ -1465,9 +1677,11 @@
                       ("c", "Copy",      self.edit_copy),
                       ("c", "Paste",     self.edit_paste)]),
             ("Help", [("c", "About...",  self.app.about)])]:
-            menubutton = Menubutton(menubar, text=text)
+            menubutton = Menubutton(menubar, text=text, font=DEFAULT_FONT)
+            app.all_item.append(menubutton)
             menubutton.pack(side=LEFT)
-            menu = Menu(menubutton, tearoff=0)
+            menu = Menu(menubutton, tearoff=0, font=DEFAULT_FONT)
+            app.all_item.append(menu)
             menubutton.config(menu=menu)
             for item in itemlist:
                 if item[0] == "c":
@@ -1482,18 +1696,22 @@
         if not self.editor.selection_present():
             return
         self.clipboard_clear()
-        self.clipboard_append(self.selection_get())
+        self.clipboard_append(self.selection_get().encode("euc-jp"))
     def edit_cut(self, event=None):
         if not self.editor.selection_present():
             return
         self.clipboard_clear()
-        self.clipboard_append(self.selection_get())
+        self.clipboard_append(self.selection_get().encode("euc-jp"))
         self.editor.delete("sel.first", "sel.last")
     def edit_paste(self, event=None):
         try:
             data = self.selection_get(selection="CLIPBOARD")
         except TclError:
             return
+        try:
+            data = unicode(data.encode("raw-unicode-escape"), "euc-jp")
+        except UnicodeDecodeError:
+            data = unicode(data, "euc-jp")
         self.editor.insert("insert", data)
     def selected(self, event=None):
         selection = self.listbox.curselection()
@@ -1566,32 +1784,40 @@
         self.listbox.selection_set(index-1)
 
 class HelperDialog(Toplevel):
-    def __init__(self, master, helpers):
+    DEFAULT_FONT = None
+    def __init__(self, app, master, helpers):
+        DEFAULT_FONT = app.fontmanager.find_font()
         Toplevel.__init__(self, master)
         self.transient(master)
         self.title("Bottler: Helpers")
         self.bind("<Return>", self.ok)
         self.bind("<Escape>", self.cancel)
         self.protocol('WM_DELETE_WINDOW', self.cancel)
-        label = Label(self, text="Channel")
+        label = Label(self, text="Channel", font=DEFAULT_FONT)
+
         label.grid_configure(column=0, row=0, sticky=W)
-        label = Label(self, text="Command")
+        label = Label(self, text="Command", font=DEFAULT_FONT)
+
         label.grid_configure(column=1, row=0, sticky=W)
         self.helpers = []
         for i in range(10):
             pattern = Entry(self, width=15)
-            pattern.config(font="fixed") # XXX
+
+            pattern.config(font=DEFAULT_FONT) # XXX
             pattern.grid_configure(column=0, row=i+1, sticky=EW)
             command = Entry(self, width=65)
-            command.config(font="fixed") # XXX
+
+            command.config(font=DEFAULT_FONT) # XXX
             command.grid_configure(column=1, row=i+1, sticky=EW)
             if i < len(helpers):
                 pattern.insert(0, helpers[i][0])
                 command.insert(0, helpers[i][1])
             self.helpers.append((pattern, command))
-        button = Button(self, text="OK", command=self.ok)
+        button = Button(self, text="OK", command=self.ok, font=DEFAULT_FONT)
+
         button.grid_configure(column=0, row=11, sticky=W)
-        button = Button(self, text="Cancel", command=self.cancel)
+        button = Button(self, text="Cancel", command=self.cancel, font=DEFAULT_FONT)
+
         button.grid_configure(column=1, row=11, sticky=E)
     def go(self):
         try:
