diff --git a/Config/Default.hs b/Config/Default.hs
--- a/Config/Default.hs
+++ b/Config/Default.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Config/IrcClient.hs b/Config/IrcClient.hs
--- a/Config/IrcClient.hs
+++ b/Config/IrcClient.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Daemon.hs b/Daemon.hs
--- a/Daemon.hs
+++ b/Daemon.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Main.hs b/Main.hs
--- a/Main.hs
+++ b/Main.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Manatee/Extension/IrcClient.hs b/Manatee/Extension/IrcClient.hs
--- a/Manatee/Extension/IrcClient.hs
+++ b/Manatee/Extension/IrcClient.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Manatee/Extension/IrcClient/DBus.hs b/Manatee/Extension/IrcClient/DBus.hs
--- a/Manatee/Extension/IrcClient/DBus.hs
+++ b/Manatee/Extension/IrcClient/DBus.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Manatee/Extension/IrcClient/Daemon.hs b/Manatee/Extension/IrcClient/Daemon.hs
--- a/Manatee/Extension/IrcClient/Daemon.hs
+++ b/Manatee/Extension/IrcClient/Daemon.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Manatee/Extension/IrcClient/HighlightNick.hs b/Manatee/Extension/IrcClient/HighlightNick.hs
--- a/Manatee/Extension/IrcClient/HighlightNick.hs
+++ b/Manatee/Extension/IrcClient/HighlightNick.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Manatee/Extension/IrcClient/IrcBuffer.hs b/Manatee/Extension/IrcClient/IrcBuffer.hs
--- a/Manatee/Extension/IrcClient/IrcBuffer.hs
+++ b/Manatee/Extension/IrcClient/IrcBuffer.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
 
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell #-}
 module Manatee.Extension.IrcClient.IrcBuffer where
 
 import Config.Import
@@ -26,14 +27,17 @@
 import Control.Monad
 import DBus.Client hiding (Signal)
 import Data.Array
+import Data.Binary
+import Data.DeriveTH
 import Data.Map (Map)
 import Data.Maybe
 import Data.Set (Set)
 import Data.Typeable
-import Graphics.UI.Gtk hiding (Language, eventButton, eventClick)
+import Graphics.UI.Gtk hiding (Language, eventButton, eventClick, get)
 import Graphics.UI.Gtk.Gdk.Events
 import Graphics.UI.Gtk.SourceView.SourceBuffer
 import Language.Translate.Google
+import Manatee.Core.Config
 import Manatee.Core.DBus
 import Manatee.Core.Dynload
 import Manatee.Core.Types
@@ -45,7 +49,6 @@
 import Manatee.Toolkit.General.Basic
 import Manatee.Toolkit.General.ByteString
 import Manatee.Toolkit.General.DBus
-import Manatee.Toolkit.General.List
 import Manatee.Toolkit.General.Map
 import Manatee.Toolkit.General.Maybe
 import Manatee.Toolkit.General.Process
@@ -62,6 +65,7 @@
 import qualified Data.ByteString.UTF8 as UTF8
 import qualified Data.Map as M
 import qualified Data.Set as S
+import qualified Graphics.UI.Gtk as Gtk
 
 data IrcBuffer = 
     IrcBuffer {ircBufferServer            :: Server
@@ -84,6 +88,7 @@
               ,ircBufferBroadcastChannel  :: TChan IrcBufferSignal
               ,ircBufferSmilePixbufs      :: Map String Pixbuf
               ,ircBufferCustomize         :: IrcCustomize
+              ,ircBufferState             :: TVar IrcState
               }
     deriving Typeable
 
@@ -91,6 +96,15 @@
                      | BufferChanged
                        deriving (Show, Eq, Ord)
 
+data IrcState =
+    IrcState {ircStateCursor              :: Maybe (Int, Int)
+             ,ircStateScrolledPosition    :: (Double, Double)}
+
+-- | Init state.
+ircInitState :: IrcState
+ircInitState =
+    IrcState (Just (1, 0)) (0, 0)
+
 -- | Create buffer new.
 ircBufferNew :: String -> [String] -> Client -> PageId -> CustomizeWrap -> IO IrcBuffer
 ircBufferNew info _ client pageId c = do
@@ -169,13 +183,16 @@
   -- Get smile pixbufs.
   smilePixbufs <- createSmilePixbufs
 
+  -- Init state.
+  state <- newTVarIO ircInitState
+
   -- Create buffer.
   let buffer = IrcBuffer server port channel
                          client pageId ircMode
                          sourceBuffer insertMark promptMark scrollMark 
                          textTag messageTag 
                          timeStamp nick nickSet nickColorMap lang
-                         broadcastChannel smilePixbufs customize
+                         broadcastChannel smilePixbufs customize state
 
   -- Add self in nick map.
   ircBufferAddNick buffer (B.pack mynick)
@@ -278,9 +295,7 @@
 
 -- | Receive private message.
 ircBufferReceivePrivate :: IrcBuffer -> NickName -> CommandArg -> IO ()
-ircBufferReceivePrivate buffer@(IrcBuffer {ircBufferClient           = client
-                                          ,ircBufferPageId           = pageId
-                                          ,ircBufferCustomize = 
+ircBufferReceivePrivate buffer@(IrcBuffer {ircBufferCustomize = 
                                             IrcCustomize 
                                             {ircCustomizeSelfColorTag     = selfColorTag
                                             ,ircCustomizeOtherColorTag    = otherColorTag
@@ -318,14 +333,6 @@
   -- Insert private message.
   ircBufferReceiveMsg buffer msg msgHeadLen messageColor
 
-  -- Notify user when some call. 
-  let myNickName = B.pack mynickname
-  unless (nick == myNickName) $ 
-    when (B.isInfixOf myNickName msg) $
-      mkDaemonSignal client 
-                     ShowTooltip 
-                     (ShowTooltipArgs (init_ (UTF8.toString msg)) Nothing 8000 Nothing Nothing False (Just pageId))
-
 -- | Receive quit message.
 ircBufferReceiveQuit :: IrcBuffer -> NickName -> UserName -> HostName -> B.ByteString -> IO ()
 ircBufferReceiveQuit buffer@(IrcBuffer {ircBufferNickSet = nickSet
@@ -467,7 +474,7 @@
   insertIter<- textBufferGetIterAtMark buffer insertMark
   line      <- textIterGetLine insertIter
   timeStamp <- getTimeStamp "[%H:%M:%S]"
-  color <- get colorTag textTagForegroundGdk
+  color <- Gtk.get colorTag textTagForegroundGdk
   modifyTVarIO stamp $ \s -> 
       M.insert line (timeStamp, color) s
 
@@ -658,4 +665,18 @@
   colorTag <- textTagNew Nothing
   set colorTag [textTagForegroundGdk := color]
   return colorTag
+
+-- | Write state.
+ircBufferWriteState :: IrcBuffer -> FilePath -> IO ()
+ircBufferWriteState buffer path = do
+  state <- readTVarIO $ ircBufferState buffer
+  writeConfigPath path state
+
+-- | Read state.
+ircBufferReadState :: IrcBuffer -> FilePath -> IO ()  
+ircBufferReadState buffer path = do
+  state <- readConfigPath path ircInitState
+  writeTVarIO (ircBufferState buffer) state
+  
+$(derive makeBinary ''IrcState)
 
diff --git a/Manatee/Extension/IrcClient/IrcView.hs b/Manatee/Extension/IrcClient/IrcView.hs
--- a/Manatee/Extension/IrcClient/IrcView.hs
+++ b/Manatee/Extension/IrcClient/IrcView.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
@@ -23,14 +23,14 @@
 import Control.Applicative
 import Control.Concurrent.STM
 import Control.Monad
-import Data.Map (Map)
 import Data.ByteString (ByteString)
+import Data.Map (Map)
 import Data.Text.Lazy (Text)
 import Data.Typeable
 import Graphics.UI.Gtk hiding (Statusbar, statusbarNew, get, Language)
-import Graphics.UI.Gtk.Gdk.SerializedEvent
 import Graphics.UI.Gtk.SourceView
 import Language.Translate.Google
+import Manatee.Core.Config
 import Manatee.Core.DBus
 import Manatee.Core.PageFrame
 import Manatee.Core.PageView
@@ -47,7 +47,6 @@
 import Manatee.Toolkit.General.STM
 import Manatee.Toolkit.General.String
 import Manatee.Toolkit.Gtk.Concurrent
-import Manatee.Toolkit.Gtk.Gtk
 import Manatee.Toolkit.Gtk.Multiline
 import Network.FastIRC.Messages
 import Paths_manatee_ircclient
@@ -77,19 +76,24 @@
     pageBufferPackageName _     = fmap takeFileName getDataDir
 
 instance PageView IrcView where
-    pageViewBuffer              = PageBufferWrap . ircViewBuffer
-    pageViewPlugId              = ircViewPlugId
-    pageViewBox                 = pageFrameBox . ircViewFrame
-    pageViewScrolledWindow      = ircViewScrolledWindow
-    pageViewFocus               = widgetGrabFocus . ircViewView
-    pageViewCut                 = ircViewCut
-    pageViewCopy                = ircViewCopy
-    pageViewPaste               = ircViewPaste
-    pageViewHandleKeyAction     = ircViewHandleKeyAction
-    pageViewScrollToTop         = ircViewScrollToTop
-    pageViewScrollToBottom      = ircViewScrollToBottom
-    pageViewScrollVerticalPage  = ircViewScrollVerticalPage
-    pageViewScrollVerticalStep  = ircViewScrollVerticalStep
+    pageViewBuffer               = PageBufferWrap . ircViewBuffer
+    pageViewPlugId               = ircViewPlugId
+    pageViewFrame                = ircViewFrame
+    pageViewLocalKeymap _        = ircViewLocalKeymap
+    pageViewLocalCommandMap _    = ircViewLocalCommandMap
+    pageViewFocus                = widgetGrabFocus . ircViewView
+    pageViewPropagateWidget      = castToWidget . ircViewView
+    pageViewSaveState view       = ircViewSaveState view Nothing
+    pageViewRestoreState view    = ircViewRestoreState view Nothing
+    pageViewWriteState view path = ircViewSaveState view (Just path)
+    pageViewReadState view path  = ircViewRestoreState view (Just path)
+    pageViewCut                  = ircViewCut
+    pageViewCopy                 = ircViewCopy
+    pageViewPaste                = ircViewPaste
+    pageViewScrollToTop          = ircViewScrollToTop
+    pageViewScrollToBottom       = ircViewScrollToBottom
+    pageViewScrollVerticalPage   = ircViewScrollVerticalPage
+    pageViewScrollVerticalStep   = ircViewScrollVerticalStep
 
 -- | Create new irc view.
 ircViewNew :: IrcBuffer -> PagePlugId -> IO IrcView
@@ -158,7 +162,7 @@
         SwitchTranslateLanguage -> do
           -- Update language status
           lang <- readTVarIO $ ircBufferTranslateLanguage $ ircViewBuffer view
-          pageFrameUpdateStatusbar (ircViewFrame view) "Translate" ("Translate to (" ++ show lang ++ ")")
+          pageViewUpdateStatusbar view "Translate" ("Translate to (" ++ show lang ++ ")")
         BufferChanged -> do
           -- Scroll screen if prompt mark at left of insert mark.
           -- Otherwise don't screen, because user screen download to read old messages.
@@ -186,15 +190,6 @@
                     else targetLanguage
   writeTChanIO (viewChannel channel) SwitchTranslateLanguage
 
--- | Handle key action.
-ircViewHandleKeyAction :: IrcView -> Text -> SerializedEvent -> IO ()
-ircViewHandleKeyAction view keystoke sEvent = 
-  case M.lookup keystoke ircViewKeymap of
-    -- Execute action when found in keymap.
-    Just action -> action view
-    -- Otherwise propagate event.
-    Nothing -> widgetPropagateEvent (ircViewView view) sEvent 
-
 -- | Begin.
 ircViewScrollToTop :: IrcView -> IO ()
 ircViewScrollToTop a = do
@@ -246,7 +241,7 @@
 
   if isBlankString text
      -- Avoid send blank string, server will ignore blank message.
-     then pageFrameShowOutputbar (ircViewFrame view) "Ignored blank ..." Nothing
+     then pageViewShowOutputbar view "Ignored blank ..." Nothing
      -- Otherwise send message to server.
      else ircViewSend view (UTF8.fromString $ encodeMorse text)
 
@@ -267,25 +262,25 @@
 
   if isBlankByteString text
      -- Avoid send blank string, server will ignore blank message.
-     then pageFrameShowOutputbar (ircViewFrame view) "Ignored blank ..." Nothing
+     then pageViewShowOutputbar view "Ignored blank ..." Nothing
      -- Otherwise send message to server.
      else 
        if isTranslate 
           -- Try get translation.
           then 
             forkGuiIO_ (do
-                         pageFrameShowOutputbar (ircViewFrame view) "Translation ..." Nothing
+                         pageViewShowOutputbar view "Translation ..." Nothing
                          lang <- readTVarIO $ ircBufferTranslateLanguage buffer
                          translate text Nothing lang)
                        $ \result -> 
                            case result of
                              -- Send original message if translate failed.
                              Left _ -> do
-                               pageFrameShowOutputbar (ircViewFrame view) "Get translation failed, send original message." Nothing
+                               pageViewShowOutputbar view "Get translation failed, send original message." Nothing
                                ircViewSend view text
                              -- Otherwise send translation.
                              Right translation -> do
-                                 pageFrameShowOutputbar (ircViewFrame view) "Translation ... completed." Nothing
+                                 pageViewShowOutputbar view "Translation ... completed." Nothing
                                  ircViewSend view translation
           -- Send original message.
           else ircViewSend view text
@@ -298,7 +293,7 @@
 ircViewWrapDeleteAction :: IrcView -> IO Bool -> IO ()
 ircViewWrapDeleteAction view action =
   unlessM action $ 
-    pageFrameShowOutputbar (ircViewFrame view) "Can't delete uneditable area." Nothing
+    pageViewShowOutputbar view "Can't delete uneditable area." Nothing
 
 -- | Delete lines.
 ircViewDelLines :: IrcView -> IO ()
@@ -410,8 +405,8 @@
 ircViewToggleSelectionMark :: IrcView -> IO ()
 ircViewToggleSelectionMark view = 
   ifM (textViewToggleSelectionMark $ ircViewView view)
-      (pageFrameUpdateStatusbar (ircViewFrame view) "Selection" "Selection (Active)")
-      (pageFrameUpdateStatusbar (ircViewFrame view) "Selection" "Selection (Inactive)")
+      (pageViewUpdateStatusbar view "Selection" "Selection (Active)")
+      (pageViewUpdateStatusbar view "Selection" "Selection (Inactive)")
 
 -- | Exchange selection mark.
 ircViewExchangeSelectionMark :: IrcView -> IO ()
@@ -494,7 +489,7 @@
   textBufferGetTagByteStringWithIter buffer iter messageTag
      >?>= \ text -> 
          forkGuiIO_ (do
-                      pageFrameShowOutputbar (ircViewFrame view) "Fetch translation ..." Nothing
+                      pageViewShowOutputbar view "Fetch translation ..." Nothing
                       -- Translate reverse. :)
                       lang <- readTVarIO language
                       let customize = ircBufferCustomize ircBuffer
@@ -506,18 +501,11 @@
                      $ \result -> 
                          case result of
                            Left _ -> 
-                               pageFrameShowOutputbar (ircViewFrame view) "Fetch translation ... failed." Nothing
+                               pageViewShowOutputbar view "Fetch translation ... failed." Nothing
                            Right translation -> do
-                               pageFrameShowOutputbar (ircViewFrame view) "Fetch translation ... completed." Nothing
-                               -- Get rectangle around cursor.
+                               pageViewShowOutputbar view "Fetch translation ... completed." Nothing
                                point <- ircViewGetTooltipPoint view
-                               -- Show translation with tooltip.
-                               mkDaemonSignal (pageViewClient view)
-                                              ShowTooltip 
-                                              (ShowTooltipArgs (UTF8.toString translation) 
-                                                               (Just point) 10000
-                                                               Nothing (Just (Color 0 65535 0)) 
-                                                               True Nothing)
+                               pageViewShowTooltip view (UTF8.toString translation) (Just point)
 
 -- | Translate morse code.
 ircViewTranslateMorse :: IrcView -> IO ()
@@ -529,14 +517,8 @@
   textIterBackwardChar iter
   textBufferGetTagTextWithIter buffer iter messageTag
        >?>= \ text -> do
-           -- Get rectangle around cursor.
            point <- ircViewGetTooltipPoint view
-           mkDaemonSignal (pageViewClient view)
-                          ShowTooltip
-                          (ShowTooltipArgs (decodeMorse text)
-                                           (Just point) 10000
-                                           Nothing (Just (Color 65535 65535 0)) 
-                                           True Nothing)
+           pageViewShowTooltip view (decodeMorse text) (Just point)
                           
 -- | Read message around pointer.
 ircViewReadMessage :: IrcView -> IO ()
@@ -554,7 +536,7 @@
 ircViewReadText view text = 
   execute "festival" ("echo " ++ show text ++ " | %s --tts") True
           >?>= \ failedReason ->
-              pageFrameShowOutputbar (ircViewFrame view) failedReason Nothing
+              pageViewShowOutputbar view failedReason Nothing
 
 -- | Get tooltip coordinate.
 ircViewGetTooltipPoint :: IrcView -> IO Point
@@ -569,43 +551,122 @@
 ircViewScrolledWindow =
   pageFrameScrolledWindow . ircViewFrame
 
+-- | Join channel.
+ircViewJoinChannel :: IrcView -> IO ()
+ircViewJoinChannel view = 
+  interactive view [(IString, "Server : ", "irc.freenode.net")
+                   ,(INum, "Port : ", "6667")
+                   ,(IString, "Channel : ", "#")
+                   ,(IString, "Nickname : ", "")] $ \ [server, port, channel, user] -> do
+    let info = "irc://" ++ user ++ "@" ++ server ++ ":" ++ port ++ "/" ++ channel
+    mkDaemonSignal (pageViewClient view) NewTab (NewTabArgs "PageIrc" info [])
+
 -- | Keymap.
-ircViewKeymap :: Map Text (IrcView -> IO ())
-ircViewKeymap = 
-    M.fromList [("Return",   ircViewSendMessage False)
-               ,("M-m",      ircViewSendMessage False)
-               ,("C-m",      ircViewSendMessage True)
-               ,("C-n",      ircViewSwitchTranslateLanguage)
-               ,("C-N",      ircViewSendMorse)
-               ,("M-M",      ircViewMoveToPrompt)
-               ,("M-N",      ircViewCleanInput)
-               ,("M-a",      ircViewSelectAll)
-               ,("M-d",      ircViewDelLines)
-               ,("M-D",      ircViewDelete)
-               ,("M-,",      ircViewDeleteBackwardChar)
-               ,("M-.",      ircViewDeleteForwardChar)
-               ,("M-<",      ircViewDeleteBackwardWord)
-               ,("M->",      ircViewDeleteForwardWord)
-               ,("M-C-,",    ircViewDeleteToLineStart)
-               ,("M-C-.",    ircViewDeleteToLineEnd)
-               ,("M-j",      ircViewForwardLine)
-               ,("M-k",      ircViewBackwardLine)
-               ,("M-l",      ircViewForwardChar)
-               ,("M-h",      ircViewBackwardChar)
-               ,("Down",     ircViewForwardLine)
-               ,("Up",       ircViewBackwardLine)
-               ,("Right",    ircViewForwardChar)
-               ,("Left",     ircViewBackwardChar)
-               ,("S-Return", ircViewNewline)
-               ,("M-L",      ircViewForwardWord)
-               ,("M-H",      ircViewBackwardWord)
-               ,("M-P-h",    ircViewSmartHome)
-               ,("M-P-l",    ircViewSmartEnd)
-               ,("C-c",      ircViewToggleSelectionMark)
-               ,("C-C",      ircViewExchangeSelectionMark)
-               ,("C-o",      ircViewOpenUrl)
-               ,("C-j",      ircViewTranslateMessage)
-               ,("C-J",      ircViewTranslateMorse)
-               ,("C-k",      ircViewReadMessage)
+ircViewLocalKeymap :: Map Text Text
+ircViewLocalKeymap = 
+    M.fromList [("Return",   "Send original message")
+               ,("M-m",      "Send original message")
+               ,("C-m",      "Send translate message")
+               ,("C-n",      "Switch translate language")
+               ,("C-N",      "Send morse code")
+               ,("M-M",      "Move to prompt")
+               ,("M-N",      "Clean input")
+               ,("M-a",      "Select all")
+               ,("M-d",      "Delete lines")
+               ,("M-D",      "Delete")
+               ,("M-,",      "Delete backward char")
+               ,("M-.",      "Delete forward char")
+               ,("M-<",      "Delete backward word")
+               ,("M->",      "Delete forward word")
+               ,("M-C-,",    "Delete to line start")
+               ,("M-C-.",    "Delete to line end")
+               ,("M-j",      "Forward line")
+               ,("M-k",      "Backward line")
+               ,("M-l",      "Forward char")
+               ,("M-h",      "Backward char")
+               ,("Down",     "Forward line")
+               ,("Up",       "Backward line")
+               ,("Right",    "Forward char")
+               ,("Left",     "Backward char")
+               ,("S-Return", "New line")
+               ,("M-L",      "Forward word")
+               ,("M-H",      "Backward word")
+               ,("M-P-h",    "Smart home")
+               ,("M-P-l",    "Smart end")
+               ,("C-c",      "Toggle selection mark")
+               ,("C-C",      "Exchange selection mark")
+               ,("C-o",      "Open url around point")
+               ,("C-,",      "Translate message")
+               ,("C-.",      "Translate morse")
+               ,("C-k",      "Read message")
+               ,("C-j",      "Join channel")
                ]
+
+-- | Keymap.
+ircViewLocalCommandMap :: Map Text (IrcView -> IO ())
+ircViewLocalCommandMap = 
+    M.fromList [("Send original message",       ircViewSendMessage False)
+               ,("Send translate message",      ircViewSendMessage True)
+               ,("Switch translate language",   ircViewSwitchTranslateLanguage)
+               ,("Send morse code",             ircViewSendMorse)
+               ,("Move to prompt",              ircViewMoveToPrompt)
+               ,("Clean input",                 ircViewCleanInput)
+               ,("Select all",                  ircViewSelectAll)
+               ,("Delete lines",                ircViewDelLines)
+               ,("Delete",                      ircViewDelete)
+               ,("Delete backward char",        ircViewDeleteBackwardChar)
+               ,("Delete forward char",         ircViewDeleteForwardChar)
+               ,("Delete backward word",        ircViewDeleteBackwardWord)
+               ,("Delete forward word",         ircViewDeleteForwardWord)
+               ,("Delete to line start",        ircViewDeleteToLineStart)
+               ,("Delete to line end",          ircViewDeleteToLineEnd)
+               ,("Forward line",                ircViewForwardLine)
+               ,("Backward line",               ircViewBackwardLine)
+               ,("Forward char",                ircViewForwardChar)
+               ,("Backward char",               ircViewBackwardChar)
+               ,("New line",                    ircViewNewline)
+               ,("Forward word",                ircViewForwardWord)
+               ,("Backward word",               ircViewBackwardWord)
+               ,("Smart home",                  ircViewSmartHome)
+               ,("Smart end",                   ircViewSmartEnd)
+               ,("Toggle selection mark",       ircViewToggleSelectionMark)
+               ,("Exchange selection mark",     ircViewExchangeSelectionMark)
+               ,("Open url around point",       ircViewOpenUrl)
+               ,("Translate message",           ircViewTranslateMessage)
+               ,("Translate morse",             ircViewTranslateMorse)
+               ,("Read message",                ircViewReadMessage)
+               ,("Join channel",                ircViewJoinChannel)
+               ]
+
+-- | Save state.
+ircViewSaveState :: IrcView -> Maybe FilePath -> IO ()
+ircViewSaveState view@(IrcView {ircViewBuffer  = buffer})  
+                 statePath = do
+  -- Get scroll position.
+  scrolledWindowPosition <- textViewGetCursorAlign (ircViewView view)
+
+  -- Save state.
+  let state = IrcState Nothing scrolledWindowPosition
+  case statePath of
+    Nothing   -> writeTVarIO (ircBufferState buffer) state
+    Just path -> writeConfigPath path state
+
+-- | Restore state.
+ircViewRestoreState :: IrcView -> Maybe FilePath -> IO ()
+ircViewRestoreState IrcView {ircViewBuffer  = buffer
+                            ,ircViewView    = textView} 
+                    statePath = do
+  bufferState <- readTVarIO (ircBufferState buffer)
+  (IrcState cursor scrolledWindowPosition) <- 
+      case statePath of
+        Just path -> readConfigPath path bufferState
+        Nothing   -> return bufferState
+
+  -- Restore cursor.
+  cursor ?>= \ (line, column) -> do
+    textViewGotoLine textView line
+    textViewGotoColumn textView column
+
+  -- Restore cursor alignment.
+  textViewSetCursorAlign textView scrolledWindowPosition
 
diff --git a/Manatee/Extension/IrcClient/PageMode.hs b/Manatee/Extension/IrcClient/PageMode.hs
--- a/Manatee/Extension/IrcClient/PageMode.hs
+++ b/Manatee/Extension/IrcClient/PageMode.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Manatee/Extension/IrcClient/Smile.hs b/Manatee/Extension/IrcClient/Smile.hs
--- a/Manatee/Extension/IrcClient/Smile.hs
+++ b/Manatee/Extension/IrcClient/Smile.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
@@ -95,7 +95,7 @@
 createSmilePixbufs :: IO (Map String Pixbuf)
 createSmilePixbufs = do
   dir <- getDataDir
-  let imagePath imageName = dir </> "icons" </> (imageName ++ ".png")
+  let imagePath imageName = dir </> "data/icons" </> (imageName ++ ".png")
       paths = map (second imagePath) 
               [("x(", "angry")
               ,(":/", "confused")
diff --git a/Manatee/Extension/IrcClient/Types.hs b/Manatee/Extension/IrcClient/Types.hs
--- a/Manatee/Extension/IrcClient/Types.hs
+++ b/Manatee/Extension/IrcClient/Types.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,7 +1,7 @@
 -- Author:     Andy Stewart <lazycat.manatee@gmail.com>
 -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
 -- 
--- Copyright (C) 2010 Andy Stewart, all rights reserved.
+-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
 -- 
 -- This program is free software: you can redistribute it and/or modify
 -- it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
 import Manatee.Core.Config
 import Manatee.Core.Dynload
 import Manatee.Core.Types
+import Manatee.Toolkit.Cabal.Utils
 import Manatee.Extension.IrcClient.PageMode
 
 import qualified Data.Map as M
@@ -40,7 +41,7 @@
               
              return emptyHookedBuildInfo
          -- Update PageTypeRule after install successful.
-        ,postInst = \ _ _ _ _ -> do
+        ,postInst = \ _ _ pack_des lbi -> do
              (PageTypeRule rule) <- readConfig pageTypeRulePath (PageTypeRule M.empty)
              writeConfig pageTypeRulePath (PageTypeRule (M.insert "PageIrc" "manatee-ircclient" rule))
              -- Update PageModeRule.
@@ -50,6 +51,15 @@
              -- Update ExtensionGloalKeymap.
              (ExtensionGloalKeymap keymap) <- readConfig extensionGlobalKeymapPath (ExtensionGloalKeymap M.empty)
              writeConfig extensionGlobalKeymapPath (ExtensionGloalKeymap
-                                                    (M.insert "F6" ("PageIrc", "irc://", []) keymap))
+                                                    (M.insert "F6" ("Irc Client",
+                                                                    ("PageIrc", "irc://", [])) keymap))
+             -- Update Application info.
+             let snapshotPath = getDataFilePath pack_des lbi "data/welcome/snapshot.png"
+             (WelcomeApplication apps) <- readConfig welcomeApplicationPath (WelcomeApplication M.empty)
+             writeConfig welcomeApplicationPath (WelcomeApplication
+                                                 (M.insert 
+                                                       ("Irc Client", snapshotPath)
+                                                       ("PageIrc", "irc://", [])
+                                                       apps))
        }
 
diff --git a/data/icons/angry.png b/data/icons/angry.png
new file mode 100644
Binary files /dev/null and b/data/icons/angry.png differ
diff --git a/data/icons/confused.png b/data/icons/confused.png
new file mode 100644
Binary files /dev/null and b/data/icons/confused.png differ
diff --git a/data/icons/crying.png b/data/icons/crying.png
new file mode 100644
Binary files /dev/null and b/data/icons/crying.png differ
diff --git a/data/icons/embarrassed.png b/data/icons/embarrassed.png
new file mode 100644
Binary files /dev/null and b/data/icons/embarrassed.png differ
diff --git a/data/icons/inlove.png b/data/icons/inlove.png
new file mode 100644
Binary files /dev/null and b/data/icons/inlove.png differ
diff --git a/data/icons/kiss.png b/data/icons/kiss.png
new file mode 100644
Binary files /dev/null and b/data/icons/kiss.png differ
diff --git a/data/icons/laugh.png b/data/icons/laugh.png
new file mode 100644
Binary files /dev/null and b/data/icons/laugh.png differ
diff --git a/data/icons/sad.png b/data/icons/sad.png
new file mode 100644
Binary files /dev/null and b/data/icons/sad.png differ
diff --git a/data/icons/sleepy.png b/data/icons/sleepy.png
new file mode 100644
Binary files /dev/null and b/data/icons/sleepy.png differ
diff --git a/data/icons/smile.png b/data/icons/smile.png
new file mode 100644
Binary files /dev/null and b/data/icons/smile.png differ
diff --git a/data/icons/surprised.png b/data/icons/surprised.png
new file mode 100644
Binary files /dev/null and b/data/icons/surprised.png differ
diff --git a/data/icons/tired.png b/data/icons/tired.png
new file mode 100644
Binary files /dev/null and b/data/icons/tired.png differ
diff --git a/data/icons/tongue.png b/data/icons/tongue.png
new file mode 100644
Binary files /dev/null and b/data/icons/tongue.png differ
diff --git a/data/icons/whistling.png b/data/icons/whistling.png
new file mode 100644
Binary files /dev/null and b/data/icons/whistling.png differ
diff --git a/data/icons/wink.png b/data/icons/wink.png
new file mode 100644
Binary files /dev/null and b/data/icons/wink.png differ
diff --git a/data/welcome/snapshot.png b/data/welcome/snapshot.png
new file mode 100644
Binary files /dev/null and b/data/welcome/snapshot.png differ
diff --git a/icons/angry.png b/icons/angry.png
deleted file mode 100644
Binary files a/icons/angry.png and /dev/null differ
diff --git a/icons/confused.png b/icons/confused.png
deleted file mode 100644
Binary files a/icons/confused.png and /dev/null differ
diff --git a/icons/crying.png b/icons/crying.png
deleted file mode 100644
Binary files a/icons/crying.png and /dev/null differ
diff --git a/icons/embarrassed.png b/icons/embarrassed.png
deleted file mode 100644
Binary files a/icons/embarrassed.png and /dev/null differ
diff --git a/icons/inlove.png b/icons/inlove.png
deleted file mode 100644
Binary files a/icons/inlove.png and /dev/null differ
diff --git a/icons/kiss.png b/icons/kiss.png
deleted file mode 100644
Binary files a/icons/kiss.png and /dev/null differ
diff --git a/icons/laugh.png b/icons/laugh.png
deleted file mode 100644
Binary files a/icons/laugh.png and /dev/null differ
diff --git a/icons/sad.png b/icons/sad.png
deleted file mode 100644
Binary files a/icons/sad.png and /dev/null differ
diff --git a/icons/sleepy.png b/icons/sleepy.png
deleted file mode 100644
Binary files a/icons/sleepy.png and /dev/null differ
diff --git a/icons/smile.png b/icons/smile.png
deleted file mode 100644
Binary files a/icons/smile.png and /dev/null differ
diff --git a/icons/surprised.png b/icons/surprised.png
deleted file mode 100644
Binary files a/icons/surprised.png and /dev/null differ
diff --git a/icons/tired.png b/icons/tired.png
deleted file mode 100644
Binary files a/icons/tired.png and /dev/null differ
diff --git a/icons/tongue.png b/icons/tongue.png
deleted file mode 100644
Binary files a/icons/tongue.png and /dev/null differ
diff --git a/icons/whistling.png b/icons/whistling.png
deleted file mode 100644
Binary files a/icons/whistling.png and /dev/null differ
diff --git a/icons/wink.png b/icons/wink.png
deleted file mode 100644
Binary files a/icons/wink.png and /dev/null differ
diff --git a/manatee-ircclient.cabal b/manatee-ircclient.cabal
--- a/manatee-ircclient.cabal
+++ b/manatee-ircclient.cabal
@@ -1,9 +1,9 @@
 name:			manatee-ircclient
-version:		0.0.8
+version:		0.1.0
 Cabal-Version:	>= 1.6
 license:		GPL-3
 license-file:	LICENSE
-copyright:		(c) 2009 ~ 2010 Andy Stewart
+copyright:		(c) 2010 ~ 2011 Andy Stewart
 synopsis:		IRC client extension for Manatee.
 description:    manatee-ircclient is IRC client extension for Manatee (Haskell/Gtk+ Integrated Live Environment)
  .
@@ -11,7 +11,7 @@
  .
  Note, you need re-install package to start the configuration file take effect the next time,
  .
- Video at (Select 720p HD) at : <http://www.youtube.com/watch?v=weS6zys3U8k> <http://www.youtube.com/watch?v=A3DgKDVkyeM> <http://v.youku.com/v_show/id_XMjI2MDMzODI4.html>
+ Video (Select 720p HD) at : <http://www.youtube.com/watch?v=weS6zys3U8k> <http://www.youtube.com/watch?v=A3DgKDVkyeM> <http://v.youku.com/v_show/id_XMjI2MDMzODI4.html>
  .
  Screenshots at : <http://goo.gl/MkVw>
  .
@@ -26,26 +26,28 @@
 stability:		provisional
 category:		Manatee, IRC Client, IRC
 
-tested-with:	GHC==6.12.3
+tested-with:	GHC==7.0.2
 build-type:		Custom
 
 data-dir: ""
-data-files: icons/angry.png
-            icons/confused.png
-            icons/crying.png
-            icons/embarrassed.png
-            icons/inlove.png
-            icons/kiss.png
-            icons/sleepy.png
-            icons/sad.png
-            icons/laugh.png
-            icons/smile.png
-            icons/surprised.png
-            icons/tired.png
-            icons/tongue.png
-            icons/whistling.png
-            icons/wink.png
+data-files: data/icons/angry.png
+            data/icons/confused.png
+            data/icons/crying.png
+            data/icons/embarrassed.png
+            data/icons/inlove.png
+            data/icons/kiss.png
+            data/icons/sleepy.png
+            data/icons/sad.png
+            data/icons/laugh.png
+            data/icons/smile.png
+            data/icons/surprised.png
+            data/icons/tired.png
+            data/icons/tongue.png
+            data/icons/whistling.png
+            data/icons/wink.png
             
+            data/welcome/snapshot.png
+
             Config/IrcClient.hs            
 
 Source-Repository head
@@ -53,8 +55,8 @@
   location:     http://patch-tag.com/r/AndyStewart/manatee-ircclient
   
 Library
-     build-depends: base >= 4 && < 5, manatee-core >= 0.0.8, dbus-client >= 0.3 && < 0.4, stm >= 2.1.2.0,
-                    containers >= 0.3.0.0, gtk-serialized-event >= 0.12.0, gtk >= 0.12.0, 
+     build-depends: base >= 4 && < 5, manatee-core >= 0.1.0, dbus-client >= 0.3 && < 0.4, stm >= 2.1.2.0,
+                    containers >= 0.3.0.0, gtk >= 0.12.0, derive, binary,
                     text >= 0.7.1.0, bytestring >= 0.9.1.5,
                     dbus-core, template-haskell, gtksourceview2 >= 0.12.0, unix >= 2.4.0.0,
                     network, groom, fastirc >= 0.2.0, split >= 0.1.2, nano-md5 >= 0.1.2, filepath,
