remaster engine, divide into 2 IM: preedit, classic
authorMr.LeQuocTuan <Mr.LeQuocTuan@79bd180b-0a32-48ee-ac55-ada8cae9df61>
Fri, 31 Jul 2009 08:02:10 +0000 (08:02 +0000)
committerMr.LeQuocTuan <Mr.LeQuocTuan@79bd180b-0a32-48ee-ac55-ada8cae9df61>
Fri, 31 Jul 2009 08:02:10 +0000 (08:02 +0000)
git-svn-id: svn://localhost/trunk@50 79bd180b-0a32-48ee-ac55-ada8cae9df61

src/Makefile.am
src/im_engine.cpp [new file with mode: 0644]
src/im_engine.h [new file with mode: 0644]
src/scim_unikey_const.h
src/scim_unikey_imengine.h [deleted file]
src/unikey_instance.cpp [moved from src/scim_unikey_imengine.cpp with 77% similarity]
src/utils.cpp [moved from src/scim_unikey_utils.cpp with 100% similarity]
src/utils.h [moved from src/scim_unikey_utils.h with 100% similarity]

index a1999c0..9b564ad 100644 (file)
@@ -1,19 +1,24 @@
 INCLUDES = \
-       -I$(top_srcdir)/ukengine \
-       -DSCIM_ICONDIR=\"@SCIM_ICONDIR@\" \
-       -DSCIM_UNIKEY_VERSION=\"@PACKAGE_VERSION@\" \
-    -DLIBEXECDIR=\"$(libexecdir)\"
+    -I$(top_srcdir)/ukengine \
+    -DSCIM_ICONDIR=\"@SCIM_ICONDIR@\" \
+    -DSCIM_UNIKEY_VERSION=\"@PACKAGE_VERSION@\" \
+    -DLIBEXECDIR=\"$(libexecdir)\" \
+    -Wall
 
-imenginedir                = @SCIM_MODULEDIR@/IMEngine
-imengine_LTLIBRARIES       = unikey.la
-unikey_la_SOURCES          = scim_unikey_imengine.cpp \
-                              scim_unikey_imengine.h \
-                              scim_unikey_const.h \
-                              scim_unikey_utils.cpp \
-                              scim_unikey_utils.h
+imenginedir             = @SCIM_MODULEDIR@/IMEngine
+imengine_LTLIBRARIES    = unikey.la
+unikey_la_SOURCES       = \
+    im_engine.cpp \
+    unikey_instance.cpp \
+    utils.cpp
 
-unikey_la_LIBADD           = $(top_builddir)/ukengine/libunikey-scim.la
-unikey_la_CFLAGS           = @SCIM_CFLAGS@ @SCIM_DEBUG_FLAGS@
-unikey_la_CXXFLAGS         = @SCIM_CFLAGS@ @SCIM_DEBUG_FLAGS@
-unikey_la_LDFLAGS          = -avoid-version -rpath $(imenginedir) -module @LIBTOOL_EXPORT_OPTIONS@ @SCIM_LIBS@
+noinst_HEADERS = \
+    im_engine.h \
+    scim_unikey_const.h \
+    utils.h
+
+unikey_la_LIBADD        = $(top_builddir)/ukengine/libunikey-scim.la
+unikey_la_CFLAGS        = @SCIM_CFLAGS@ @SCIM_DEBUG_FLAGS@
+unikey_la_CXXFLAGS      = @SCIM_CFLAGS@ @SCIM_DEBUG_FLAGS@
+unikey_la_LDFLAGS       = -avoid-version -rpath $(imenginedir) -module @LIBTOOL_EXPORT_OPTIONS@ @SCIM_LIBS@
 
diff --git a/src/im_engine.cpp b/src/im_engine.cpp
new file mode 100644 (file)
index 0000000..3717ca2
--- /dev/null
@@ -0,0 +1,130 @@
+/**
+   Scim-Unikey Input Method
+
+   Copyright (C) 2008-2009 Ubuntu-VN <http://www.ubuntu-vn.org>
+   Author: Le Quoc Tuan <mr.lequoctuan@gmail.com>
+   Home: http://scim-unikey.googlecode.com
+   License: GNU LESSER GENERAL PUBLIC LICENSE v2.1
+*/
+
+#define Uses_SCIM_IMENGINE
+#define Uses_SCIM_ICONV
+#define Uses_SCIM_CONFIG_BASE
+#define Uses_SCIM_CONFIG_PATH
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libintl.h>
+#define _(String) dgettext(PACKAGE_NAME,String)
+
+#include <scim.h>
+#include "scim_unikey_const.h"
+#include "im_engine.h"
+
+#include <string.h>
+#include "unikey.h"
+
+#define scim_module_init                            unikey_LTX_scim_module_init
+#define scim_module_exit                            unikey_LTX_scim_module_exit
+#define scim_imengine_module_init                   unikey_LTX_scim_imengine_module_init
+#define scim_imengine_module_create_factory         unikey_LTX_scim_imengine_module_create_factory
+
+ConfigPointer   __config;
+
+using namespace scim;
+
+extern "C"
+{
+    void scim_module_init(void)
+    {
+        UnikeySetup();
+    }
+
+    void scim_module_exit(void)
+    {
+        UnikeyCleanup();
+    }
+
+    unsigned int scim_imengine_module_init(ConfigPointer &config)
+    {
+        if (config.null())
+            return 0;
+        __config = config;
+
+        return 2;
+    }
+
+    IMEngineFactoryPointer scim_imengine_module_create_factory(unsigned int index)
+    {
+        return new UnikeyFactory(index);
+    }
+}
+
+UnikeyFactory::UnikeyFactory(int id)
+{
+    m_id = id;
+    set_languages("vi_VN");
+}
+UnikeyFactory::~UnikeyFactory()
+{
+}
+WideString UnikeyFactory::get_name() const
+{
+    return utf8_mbstowcs(m_id==0?"Unikey":"Unikey Classic");
+}
+String UnikeyFactory::get_uuid() const
+{
+    return String("16ef5139-de02-494f-8d98-ddfcd60bbae1-") + String(m_id==0?"PREEDIT":"CLASSIC");
+}
+WideString UnikeyFactory::get_authors() const
+{
+    return utf8_mbstowcs("Le Quoc Tuan <mr.lequoctuan@gmail.com>");
+}
+WideString UnikeyFactory::get_credits() const
+{
+    return utf8_mbstowcs(String("Scim-Unikey Input Method\n"
+                                "Version: " SCIM_UNIKEY_VERSION "\n"
+                                "Copyright © 2008-2009 Ubuntu-VN\n"
+                                "http://www.ubuntu-vn.org\n\n"
+                                "Thanks to Pham Kim Long for ukengine")
+        );
+}
+WideString UnikeyFactory::get_help() const
+{
+    return utf8_mbstowcs(_("This IME work best when environment variable are\n"
+                           "- GTK_IM_MODULE=scim-bridge\n"
+                           "- QT_IM_MODULE=xim\n\n"
+
+                           "Some time, in some application, you \"must\"\n"
+                           "use Preedit to input properly\n\n"
+
+                           "In some application, scim can't enable,\n"
+                           "this is not a bug of scim-unikey.\n"
+                           "You can try this in terminal: app_name | scim\n\n"
+
+                           "This IME come into being not intend to\n"
+                           "replace scim-m17n, just a choose, I recommend\n"
+                           "use this combine with scim-m17n\n\n"
+
+                           "For other support goto:\n"
+                           "  http://code.google.com/p/scim-unikey/wiki/Support"));
+}
+String UnikeyFactory::get_icon_file() const
+{
+    return String(SCIM_ICONDIR SCIM_UNIKEY_ICON_MAIN);
+}
+
+IMEngineInstancePointer UnikeyFactory::create_instance(const String & encoding, int id)
+{
+    if (m_id==0)
+    {
+        return new UnikeyInstancePreedit(this, encoding, id);
+    }
+    else
+    {
+        return new UnikeyInstanceClassic(this, encoding, id);
+    }
+}
+
diff --git a/src/im_engine.h b/src/im_engine.h
new file mode 100644 (file)
index 0000000..1f453e1
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+   Scim-Unikey Input Method
+
+   Copyright (C) 2008-2009 Ubuntu-VN <http://www.ubuntu-vn.org>
+   Author: Le Quoc Tuan <mr.lequoctuan@gmail.com>
+   Home: http://scim-unikey.googlecode.com
+   License: GNU LESSER GENERAL PUBLIC LICENSE v2.1
+*/
+
+#if !defined (__SCIM_UNIKEY_IMENGINE_H)
+#define __SCIM_UNIKEY_IMENGINE_H
+
+#include "unikey.h"
+
+using namespace scim;
+
+class UnikeyFactory : public IMEngineFactoryBase
+{
+public:
+    UnikeyFactory(int id);
+    virtual ~UnikeyFactory();
+
+    virtual WideString  get_name() const;
+    virtual WideString  get_authors() const;
+    virtual WideString  get_credits() const;
+    virtual WideString  get_help() const;
+    virtual String      get_uuid() const;
+    virtual String      get_icon_file() const;
+
+    virtual IMEngineInstancePointer create_instance(const String& encoding, int id = -1);
+
+private:
+    int m_id;
+};
+
+
+class UnikeyInstance : public IMEngineInstanceBase
+{
+    friend class UnikeyInstancePreedit;
+    friend class UnikeyInstanceClassic;
+
+public:
+    UnikeyInstance(UnikeyFactory *factory, const String& encoding, int id);
+    ~UnikeyInstance();
+
+    virtual void reset();
+    virtual void focus_in();
+    virtual void trigger_property(const String &property);
+
+private:
+    PropertyList CreatePropertyList();
+
+    int m_im;                             // input method
+    int m_oc;                             // output charset
+    UnikeyOptions m_ukopt;                // Unikey Options
+    bool m_process_w_AtBeginWord;         // process W at Begin Word?
+    bool m_lastkey_with_shift;            // last press key with modifier is shift
+};
+
+
+class UnikeyInstancePreedit : public UnikeyInstance
+{
+public:
+    UnikeyInstancePreedit(UnikeyFactory *factory, const String& encoding, int id = -1);
+    ~UnikeyInstancePreedit();
+
+    virtual void reset();
+    virtual void focus_in();
+    virtual void focus_out();
+    virtual bool process_key_event(const KeyEvent& key);
+    virtual void trigger_property(const String &property);
+
+private:
+    bool unikey_process_key_event(const KeyEvent& key);
+    void unikey_update_preedit_string(const WideString s, const bool visible);
+    PropertyList CreatePropertyList();
+
+    WideString m_preeditstring;           // store PreEdit String
+    bool m_auto_commit;                   // auto commit?
+};
+
+
+class UnikeyInstanceClassic : public UnikeyInstance
+{
+public:
+    UnikeyInstanceClassic(UnikeyFactory *factory, const String& encoding, int id = -1);
+    ~UnikeyInstanceClassic();
+
+    virtual void reset();
+    virtual void focus_in();
+    virtual void focus_out();
+    virtual bool process_key_event(const KeyEvent& key);
+    virtual void trigger_property(const String &property);
+
+private:
+    bool unikey_process_key_event(const KeyEvent& key);
+    void unikey_send_backspace(int nBackspace);
+    void unikey_commit_key_event(const KeyEvent& key);
+    PropertyList CreatePropertyList();
+};
+
+#endif
+
index db9a796..18c8242 100644 (file)
@@ -17,8 +17,6 @@
 #define SCIM_IMENGINE_UNIKEY_MACROPATH                  "/.scim/scim-unikey/macro"
 
 /** define the config string off the unikey engine */
-#define SCIM_IMENGINE_UNIKEY_PREEDIT                    "/IMEngine/Unikey/preEdit"
-#define SCIM_IMENGINE_UNIKEY_PREEDIT_SWITCH_KEY         "/IMEngine/Unikey/preEditSwitchKey"
 #define SCIM_IMENGINE_UNIKEY_PROCESSWATWORDBEGIN        "/IMEngine/Unikey/processWAtBeginWord"
 
 #define SCIM_IMENGINE_UNIKEY_FREEMARKING                "/IMEngine/Unikey/freeMarking"
@@ -33,8 +31,6 @@
 /** define the default value off the unikey engine */
 #define SCIM_IMENGINE_UNIKEY_PROCESSWATWORDBEGIN_DEF    true
 
-#define SCIM_IMENGINE_UNIKEY_PREEDIT_DEF                true
-#define SCIM_IMENGINE_UNIKEY_PREEDIT_SWITCH_KEY_DEF     "Control+Alt+backslash"
 #define SCIM_IMENGINE_UNIKEY_FREEMARKING_DEF            true
 #define SCIM_IMENGINE_UNIKEY_MODERNSTYLE_DEF            false
 #define SCIM_IMENGINE_UNIKEY_MACROENABLED_DEF           false
diff --git a/src/scim_unikey_imengine.h b/src/scim_unikey_imengine.h
deleted file mode 100644 (file)
index 2226c7b..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
-   Scim-Unikey Input Method
-
-   Copyright (C) 2008-2009 Ubuntu-VN <http://www.ubuntu-vn.org>
-   Author: Le Quoc Tuan <mr.lequoctuan@gmail.com>
-   Home: http://scim-unikey.googlecode.com
-   License: GNU LESSER GENERAL PUBLIC LICENSE v2.1
-*/
-
-#if !defined (__SCIM_UNIKEY_IMENGINE_H)
-#define __SCIM_UNIKEY_IMENGINE_H
-
-#include "unikey.h"
-
-using namespace scim;
-
-class UnikeyFactory : public IMEngineFactoryBase
-{
-    friend class UnikeyInstance;
-
-public:
-    UnikeyFactory();
-    virtual ~UnikeyFactory ();
-
-    virtual WideString  get_name () const;
-    virtual WideString  get_authors () const;
-    virtual WideString  get_credits () const;
-    virtual WideString  get_help () const;
-    virtual String      get_uuid () const;
-    virtual String      get_icon_file () const;
-
-    virtual IMEngineInstancePointer create_instance (const String& encoding, int id = -1);
-};
-
-class UnikeyInstance : public IMEngineInstanceBase
-{
-public:
-    UnikeyInstance(UnikeyFactory *factory, const String& encoding, int id = -1);
-    virtual ~UnikeyInstance ();
-
-    virtual bool process_key_event(const KeyEvent& key);
-    virtual void reset();
-    virtual void focus_in();
-    virtual void focus_out();
-    virtual void trigger_property(const String &property);
-
-private:
-    bool Unikey_process_key_event_direct(const KeyEvent& key);
-    bool Unikey_process_key_event_preedit(const KeyEvent& key);
-    void Unikey_send_backspace(int nBackspace);
-    void Unikey_update_preedit_string(const WideString s, const bool visible);
-    void Unikey_commit_key_event(const KeyEvent& key);
-    PropertyList CreatePropertyList();
-
-    int m_im;                             // input method
-    int m_oc;                             // output charset
-    UnikeyOptions m_ukopt;                // Unikey Options
-    WideString m_preeditstring;           // store PreEdit String
-    bool m_preedit;                       // is PreEdit On?
-    bool m_process_w_AtBeginWord;         // process W at Begin Word?
-    bool m_auto_commit;                   // auto commit?
-    std::vector<KeyEvent> m_preeditskey;  // keys to switch preedit and non preedit mode
-    bool m_lastkey_with_shift;            // last press key with modifier is shift
-};
-
-#endif
-
similarity index 77%
rename from src/scim_unikey_imengine.cpp
rename to src/unikey_instance.cpp
index a73220f..9e1a7fc 100644 (file)
 
 #include <scim.h>
 #include "scim_unikey_const.h"
-#include "scim_unikey_utils.h"
-#include "scim_unikey_imengine.h"
+#include "utils.h"
+#include "im_engine.h"
 
 #include <string.h>
 #include "unikey.h"
 #include "vnconv.h"
 
-#define scim_module_init                            unikey_LTX_scim_module_init
-#define scim_module_exit                            unikey_LTX_scim_module_exit
-#define scim_imengine_module_init                   unikey_LTX_scim_imengine_module_init
-#define scim_imengine_module_create_factory         unikey_LTX_scim_imengine_module_create_factory
-
 static unsigned char WordBreakSyms[] =
 {
-    ',', ';', ':', '.', '\"', '\'', '!', '?', ' ',
-    '<', '>', '=', '+', '-', '*', '/', '\\',
-    '_', '~', '`', '@', '#', '$', '%', '^', '&', '(', ')', '{', '}', '[', ']',
-    '|'
+    ',', ';', ':', '.', '!', '?', ' ', '<', '>', '=', '+', '-', '*', '/', '_', '~',
+    '`', '@', '#', '$', '%', '^', '&', '(', ')', '{', '}', '[', ']', '|', '\"', '\'', '\\',
 };
 
 static unsigned char WordAutoCommit[] =
@@ -49,7 +42,6 @@ static unsigned char WordAutoCommit[] =
     'B', 'C', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N',
     'P', 'Q', 'R', 'S', 'T', 'V', 'X', 'Z'
 };
-
 const String          Unikey_IMNames[]    = {"Telex", "Vni", "STelex", "STelex2"};
 const UkInputMethod   Unikey_IM[]         = {UkTelex, UkVni, UkSimpleTelex, UkSimpleTelex2};
 const unsigned int    NUM_INPUTMETHOD     = sizeof(Unikey_IM)/sizeof(Unikey_IM[0]);
@@ -61,7 +53,6 @@ const String          Unikey_OCNames[]    = {"Unicode",
                                              "CString",
                                              "NCR Decimal",
                                              "NCR Hex"};
-
 const unsigned int    Unikey_OC[]         = {CONV_CHARSET_XUTF8,
                                              CONV_CHARSET_TCVN3,
                                              CONV_CHARSET_VNIWIN,
@@ -71,103 +62,16 @@ const unsigned int    Unikey_OC[]         = {CONV_CHARSET_XUTF8,
                                              CONV_CHARSET_UNIREF_HEX};
 const unsigned int    NUM_OUTPUTCHARSET   = sizeof(Unikey_OC)/sizeof(Unikey_OC[0]);
 
-ConfigPointer   __config;
-
-using namespace scim;
-
-extern "C"
-{
-    void scim_module_init(void)
-    {
-        UnikeySetup();
-    }
-
-    void scim_module_exit(void)
-    {
-        UnikeyCleanup();
-    }
-
-    unsigned int scim_imengine_module_init(ConfigPointer &config)
-    {
-        if (config.null())
-            return 0;
-        __config = config;
-
-        return 1;
-    }
-
-    IMEngineFactoryPointer scim_imengine_module_create_factory(unsigned int index)
-    {
-        return new UnikeyFactory();
-    }
-}
-
-UnikeyFactory::UnikeyFactory()
-{
-    set_languages("vi_VN");
-}
-UnikeyFactory::~UnikeyFactory()
-{
-}
-WideString UnikeyFactory::get_name() const
-{
-    return utf8_mbstowcs("Unikey");
-}
-String UnikeyFactory::get_uuid() const
-{
-    return String(String("16ef5139-de02-494f-8d98-ddfcd60bbae1"));
-}
-WideString UnikeyFactory::get_authors() const
-{
-    return utf8_mbstowcs("Le Quoc Tuan <mr.lequoctuan@gmail.com>");
-}
-WideString UnikeyFactory::get_credits() const
-{
-    return utf8_mbstowcs(String("Scim-Unikey Input Method\n"
-                                "Version: " SCIM_UNIKEY_VERSION "\n"
-                                "Copyright © 2008-2009 Ubuntu-VN\n"
-                                "http://www.ubuntu-vn.org\n\n"
-                                "Thanks to Pham Kim Long for ukengine")
-        );
-}
-WideString UnikeyFactory::get_help() const
-{
-    return utf8_mbstowcs(_("This IME work best when environment variable are\n"
-                           "- GTK_IM_MODULE=scim-bridge\n"
-                           "- QT_IM_MODULE=xim\n\n"
-
-                           "Some time, in some application, you \"must\"\n"
-                           "enable Preedit to input properly\n\n"
-
-                           "In some application, scim can't enable,\n"
-                           "this is not a bug of scim-unikey.\n"
-                           "You can try this in terminal: app_name | scim\n\n"
-
-                           "This IME come into being not intend to\n"
-                           "replace scim-m17n, just a choose, I recommend\n"
-                           "use this combine with scim-m17n\n\n"
-
-                           "For other support goto:\n"
-                           "  http://forum.ubuntu-vn.org/viewforum.php?f=85"));
-}
-String UnikeyFactory::get_icon_file() const
-{
-    return String(SCIM_ICONDIR SCIM_UNIKEY_ICON_MAIN);
-}
-
-IMEngineInstancePointer UnikeyFactory::create_instance(const String & encoding, int id)
-{
-    return new UnikeyInstance(this, encoding, id);
-}
+extern ConfigPointer __config;
 
-UnikeyInstance::UnikeyInstance(UnikeyFactory *factory, const String &encoding, int id)
-    :IMEngineInstanceBase(factory, encoding, id),
-     m_auto_commit(false)
+/*************************************************
+**************** Unikey Instance *****************
+*************************************************/
+UnikeyInstance::UnikeyInstance(UnikeyFactory *factory, const String& encoding, int id)
+        :IMEngineInstanceBase(factory, encoding, id)
 {
     static bool t, o;  //temp variable
 
-    m_preeditstring.clear();
-
     CreateDefaultUnikeyOptions(&m_ukopt);
 
     /* Read config
@@ -179,29 +83,6 @@ UnikeyInstance::UnikeyInstance(UnikeyFactory *factory, const String &encoding, i
     t = __config->read(SCIM_IMENGINE_UNIKEY_OUTPUTCHARSET, &m_oc);
     if (!t) m_oc = 0;
 
-    t = __config->read(SCIM_IMENGINE_UNIKEY_PREEDIT, &m_preedit);
-    if (!t) m_preedit = SCIM_IMENGINE_UNIKEY_PREEDIT_DEF;
-
-    // read preedit switch key
-    m_preeditskey.clear();
-    String s;
-    int i = 0, j;
-    t = __config->read(SCIM_IMENGINE_UNIKEY_PREEDIT_SWITCH_KEY, &s);
-    if (!t) s=SCIM_IMENGINE_UNIKEY_PREEDIT_SWITCH_KEY_DEF;
-    if (s.length())
-    {
-        while (true)
-        {
-            j=s.find(',', i);
-            if (j!=String::npos)
-                m_preeditskey.push_back(KeyEvent(s.substr(i, j-i)));
-            else
-                break;
-            i = j+1;
-        }
-        m_preeditskey.push_back(KeyEvent(s.substr(i)));
-    } // end read preedit switch key
-
     t = __config->read(SCIM_IMENGINE_UNIKEY_PROCESSWATWORDBEGIN, &o);
     m_process_w_AtBeginWord = t?o:SCIM_IMENGINE_UNIKEY_PROCESSWATWORDBEGIN_DEF;
 
@@ -227,254 +108,357 @@ UnikeyInstance::UnikeyInstance(UnikeyFactory *factory, const String &encoding, i
     {
         UnikeyLoadMacroTable(getMacroFile());
     }
-
-    reset();
-}
+};
 
 UnikeyInstance::~UnikeyInstance()
 {
+};
+
+void UnikeyInstance::reset()
+{
+    UnikeyResetBuf();
+
+    m_lastkey_with_shift = false;
 }
 
 void UnikeyInstance::focus_in()
 {
-    register_properties(CreatePropertyList());
-
     UnikeySetInputMethod(Unikey_IM[m_im]);
     UnikeySetOutputCharset(Unikey_OC[m_oc]);
     UnikeySetOptions(&m_ukopt);
 }
 
-void UnikeyInstance::focus_out()
+PropertyList UnikeyInstance::CreatePropertyList()
 {
-    reset();
-}
+    PropertyList props;
+    uint i;
 
-void UnikeyInstance::reset()
-{
-    UnikeyResetBuf();
+    Property prop("", "", "", "");
 
-    m_lastkey_with_shift = false;
+// input method
+    prop.set_key("/Unikey/InputMethod");
+    prop.set_label(Unikey_IMNames[m_im]);
+    prop.set_icon("");
+    prop.set_tip(_("Choose input method"));
+    props.push_back(prop);
 
-    if (m_preedit)
+    for (i=0; i<NUM_INPUTMETHOD; i++)
     {
-        if (m_preeditstring.length())
-        {
-            commit_string(m_preeditstring);
-            hide_preedit_string();
-            m_preeditstring.clear();
-        }
-        m_auto_commit = false;
+        prop.set_key(String("/Unikey/InputMethod/") + Unikey_IMNames[i] + String((uint)m_im==i?"-Checked":""));
+        prop.set_label(Unikey_IMNames[i]);
+        prop.set_icon((uint)m_im==i?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
+        prop.set_tip("");
+        props.push_back(prop);
     }
-}
-
-void UnikeyInstance::Unikey_send_backspace(int nBackspace)
-{
-    static WideString ws;
-    static int n;
 
-    //  if surrounding text was provided, use it instead of send backspace
-    if (get_surrounding_text(ws, n, nBackspace, 0))
-    {
-        // for type in Auto Complete in OpenOffice
-        // Hope this not rise bugs in others application
-        // not use SCIM_KEY_NullKey, because GTK application crash when GTK_IM_MODULE=scim
+// output charset
 
-        forward_key_event(SCIM_KEY_VoidSymbol);
+    prop.set_key("/Unikey/OutputCharset");
+    prop.set_label(Unikey_OCNames[m_oc]);
+    prop.set_icon("");
+    prop.set_tip(_("Choose output charset"));
+    props.push_back(prop);
 
-        delete_surrounding_text(-ws.length(), ws.length());
-    }
-    else
+    for (i=0; i<NUM_OUTPUTCHARSET; i++)
     {
-        for (int i=0; i < nBackspace; i++)
-            forward_key_event(SCIM_KEY_BackSpace);
+        prop.set_key(String("/Unikey/OutputCharset/") + Unikey_OCNames[i] + String((uint)m_oc==i?"-Checked":""));
+        prop.set_label(Unikey_OCNames[i]);
+        prop.set_icon((uint)m_oc==i?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
+        prop.set_tip("");
+        props.push_back(prop);
     }
-}
 
-void UnikeyInstance::Unikey_update_preedit_string(const WideString s, const bool visible)
-{
-    AttributeList attlist;
-    Attribute att;
+// unikey options
+    // menu
+    prop.set_key("/Unikey/Options");
+    prop.set_label(_("Options"));
+    prop.set_icon(SCIM_ICONDIR SCIM_UNIKEY_ICON_CONFIGURE);
+    prop.set_tip(_("Configure Unikey here"));
+    props.push_back(prop);
 
-    // underline preedit string
-    att = Attribute(0, s.length(), SCIM_ATTR_DECORATE, SCIM_ATTR_DECORATE_UNDERLINE);
-    attlist.push_back(att);
+    // spellcheck
+    prop.set_key(m_ukopt.spellCheckEnabled?
+                 "/Unikey/Options/SpellCheck/Disable":"/Unikey/Options/SpellCheck/Enable");
+    prop.set_label(_("Enable spell check"));
+    prop.set_icon(m_ukopt.spellCheckEnabled?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
+    prop.set_tip(_("If enable, you can decrease mistake when typing"));
+    props.push_back(prop);
+    
+    // auto restore keystroke
+    prop.set_key(m_ukopt.autoNonVnRestore?
+                 "/Unikey/Options/AutoRestoreKeys/Disable":"/Unikey/Options/AutoRestoreKeys/Enable");
+    prop.set_label(_("Auto restore keys with invalid words"));
+    prop.set_icon(m_ukopt.autoNonVnRestore?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
+    prop.set_tip(_("When typing a word not in Vietnamese,\n"
+                   "it will auto restore keystroke into original"));
+    props.push_back(prop);
 
-    if (m_ukopt.spellCheckEnabled==1 && UnikeyLastWordIsNonVn())
-    {
-        // red preedit string
-        att = Attribute(0, s.length(), SCIM_ATTR_FOREGROUND, 0xff0000);
-        attlist.push_back(att);
-    }
+    // modern style
+    prop.set_key(m_ukopt.modernStyle?
+                 "/Unikey/Options/ModernStyle/Disable":"/Unikey/Options/ModernStyle/Enable");
+    prop.set_label(_("Use oà, uý (instead of òa, úy)"));
+    prop.set_icon(m_ukopt.modernStyle?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
+    prop.set_tip("");
+    props.push_back(prop);
 
-    update_preedit_string(s, attlist);
-    update_preedit_caret(s.length());
+    // freeMarking
+    prop.set_key(m_ukopt.freeMarking?
+                 "/Unikey/Options/FreeMarking/Disable":"/Unikey/Options/FreeMarking/Enable");
+    prop.set_label(_("Allow type with more freedom"));
+    prop.set_icon(m_ukopt.freeMarking?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
+    prop.set_tip("");
+    props.push_back(prop);
 
-    if (visible == true)
-    {
-        show_preedit_string();
-    }
-    else
-    {
-        hide_preedit_string();
-    }
-}
+    // macro
+    prop.set_key(m_ukopt.macroEnabled?
+                 "/Unikey/Options/EnabledMacro/Disable":"/Unikey/Options/EnabledMacro/Enable");
+    prop.set_label(_("Enable Macro"));
+    prop.set_icon(m_ukopt.macroEnabled?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
+    prop.set_tip("");
+    props.push_back(prop);
 
-void UnikeyInstance::Unikey_commit_key_event(const KeyEvent& key)
-{
-    static WideString s;
+    // process w at begin
+    prop.set_key(m_process_w_AtBeginWord?
+                 "/Unikey/Options/ProcessWAtBegin/Disable":"/Unikey/Options/ProcessWAtBegin/Enable");
+    prop.set_label(_("Process W at word begin"));
+    prop.set_icon(m_process_w_AtBeginWord?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
+    prop.set_tip(_("If enable, type W at begin\n"
+                   "of word will change to Ư."));
+    props.push_back(prop);
 
-    s.clear();
-    s.push_back(key.code);
-    commit_string(s);
+    // config gui
+    prop.set_key("/Unikey/Options/RunSetup");
+    prop.set_label(_("Launch Unikey-setup"));
+    prop.set_icon(SCIM_ICONDIR SCIM_UNIKEY_ICON_MAIN);
+    prop.set_tip("");
+    props.push_back(prop);
+
+    return props;
 }
 
-bool UnikeyInstance::process_key_event(const KeyEvent& key)
+void UnikeyInstance::trigger_property(const String &property)
 {
-    bool tmp;
+    bool change = false;
+    uint i;
 
-    for (int i = 0; i<m_preeditskey.size(); i++)
+// input method
+    if (!property.compare(0, strlen("/Unikey/InputMethod/"), "/Unikey/InputMethod/"))
     {
-        if (key==m_preeditskey.at(i))
-        {
-            reset();
-            m_preedit=!m_preedit;
-            register_properties(CreatePropertyList());
-            return true;
-        }
+        for (i=0; i<NUM_INPUTMETHOD; i++)
+            if (!property.compare(strlen("/Unikey/InputMethod/"),
+                                  property.length() - strlen("/Unikey/InputMethod/"),
+                                  Unikey_IMNames[i]))
+            {
+                m_im = i;
+                __config->write(SCIM_IMENGINE_UNIKEY_INPUTMETHOD, m_im);
+                change = true;
+                break;
+            }
     }
 
-    tmp = m_preedit?Unikey_process_key_event_preedit(key)
-        :Unikey_process_key_event_direct(key);
+// output charset
+    else if (!property.compare(0, strlen("/Unikey/OutputCharset/"), "/Unikey/OutputCharset/"))
+    {
+        for (i=0; i<NUM_OUTPUTCHARSET; i++)
+            if (!property.compare(strlen("/Unikey/OutputCharset/"),
+                                  property.length() - strlen("/Unikey/OutputCharset/"),
+                                  Unikey_OCNames[i]))
+            {
+                m_oc = i;
+                __config->write(SCIM_IMENGINE_UNIKEY_OUTPUTCHARSET, m_oc);
+                change = true;
+                break;
+            }
+    }
 
-    if ((key.code >= SCIM_KEY_space && key.code <= SCIM_KEY_asciitilde)
-        || (key.code >= SCIM_KEY_KP_Multiply && key.code <= SCIM_KEY_KP_9))
+// spellcheck
+    else if (property == "/Unikey/Options/SpellCheck/Enable")
     {
-        m_lastkey_with_shift = key.is_shift_down();
+        m_ukopt.spellCheckEnabled = true;
+        __config->write(SCIM_IMENGINE_UNIKEY_SPELLCHECKENABLED, true);
+        change = true;
     }
-    else
+    else if (property == "/Unikey/Options/SpellCheck/Disable")
     {
-        m_lastkey_with_shift = false;
+        m_ukopt.spellCheckEnabled = false;
+        __config->write(SCIM_IMENGINE_UNIKEY_SPELLCHECKENABLED, false);
+        change = true;
     }
 
-    return tmp;
-}
+// auto restore keystroke
+    else if (property == "/Unikey/Options/AutoRestoreKeys/Enable")
+    {
+        m_ukopt.autoNonVnRestore = true;
+        __config->write(SCIM_IMENGINE_UNIKEY_AUTONONVNRESTORE, true);
+        change = true;
+    }
+    else if (property == "/Unikey/Options/AutoRestoreKeys/Disable")
+    {
+        m_ukopt.autoNonVnRestore = false;
+        __config->write(SCIM_IMENGINE_UNIKEY_AUTONONVNRESTORE, false);
+        change = true;
+    }
 
-/** This method not use preedit string */
-bool UnikeyInstance::Unikey_process_key_event_direct(const KeyEvent& key)
-{
-    if (key.is_key_release())
+// modern style
+    else if (property == "/Unikey/Options/ModernStyle/Enable")
     {
-        return false;
+        m_ukopt.modernStyle = true;
+        __config->write(SCIM_IMENGINE_UNIKEY_MODERNSTYLE, true);
+        change = true;
+    }
+    else if (property == "/Unikey/Options/ModernStyle/Disable")
+    {
+        m_ukopt.modernStyle = false;
+        __config->write(SCIM_IMENGINE_UNIKEY_MODERNSTYLE, false);
+        change = true;
     }
 
-    if (key.is_control_down() || key.mask & SCIM_KEY_AltMask)
+// free Marking
+    else if (property == "/Unikey/Options/FreeMarking/Enable")
     {
-        reset();
-        return false;
+        m_ukopt.freeMarking = true;
+        __config->write(SCIM_IMENGINE_UNIKEY_FREEMARKING, true);
+        change = true;
+    }
+    else if (property == "/Unikey/Options/FreeMarking/Disable")
+    {
+        m_ukopt.freeMarking = false;
+        __config->write(SCIM_IMENGINE_UNIKEY_FREEMARKING, false);
+        change = true;
+    }
+// macro 
+    else if (property == "/Unikey/Options/EnabledMacro/Enable")
+    {
+        m_ukopt.macroEnabled = true;
+        UnikeyLoadMacroTable(getMacroFile());
+        __config->write(SCIM_IMENGINE_UNIKEY_MACROENABLED, true);
+        change = true;
+    }
+    else if (property == "/Unikey/Options/EnabledMacro/Disable")
+    {
+        m_ukopt.macroEnabled = false;
+        __config->write(SCIM_IMENGINE_UNIKEY_MACROENABLED, false);
+        change = true;
     }
 
-    if (key.code >= SCIM_KEY_Shift_L && key.code <= SCIM_KEY_Hyper_R)
+// process w at begin
+    else if (property == "/Unikey/Options/ProcessWAtBegin/Enable")
     {
-        return false;
+        m_process_w_AtBeginWord = true;
+        __config->write(SCIM_IMENGINE_UNIKEY_PROCESSWATWORDBEGIN, true);
+        change = true;
+    }
+    else if (property == "/Unikey/Options/ProcessWAtBegin/Disable")
+    {
+        m_process_w_AtBeginWord = false;
+        __config->write(SCIM_IMENGINE_UNIKEY_PROCESSWATWORDBEGIN, false);
+        change = true;
     }
 
-    if (key.code == SCIM_KEY_BackSpace)
+// run setup
+    else if (property == "/Unikey/Options/RunSetup")
     {
-        UnikeyBackspacePress();     // xu ly phim backspace
-        if (UnikeyBackspaces==0)    // neu ukengine bao khong can xoa ky tu nao,
-            return false;  // thi tra lai backspace cho chuong trinh khach
-        else
-        {
-            Unikey_send_backspace(UnikeyBackspaces);
+        system(LIBEXECDIR "/scim-setup-unikey &");
+    }
 
-            // append key that need change tone pos after press backspace
-            if (UnikeyBufChars)
-            {
-                if (Unikey_OC[m_oc] == CONV_CHARSET_XUTF8)
-                    commit_string(utf8_mbstowcs((const char*)UnikeyBuf, UnikeyBufChars));  // send the solved string to client
-                else
-                {
-                    static unsigned char buf[1024];
-                    int bufSize=sizeof(buf)/sizeof(buf[0]);
+    if (change)
+    {
+        __config->flush();
+        focus_out();
+        focus_in();
+    }
+}
 
-                    latinToUtf(buf, UnikeyBuf, UnikeyBufChars, &bufSize);
-                    commit_string(utf8_mbstowcs((const char*)buf, sizeof(buf)/sizeof(buf[0]) - bufSize));
-                }
-            }
+/*********************************************************
+**************** Unikey Instance Preedit *****************
+*********************************************************/
 
-            return true;
-        }
-    }
+UnikeyInstancePreedit::UnikeyInstancePreedit(UnikeyFactory *factory, const String &encoding, int id)
+    :UnikeyInstance(factory, encoding, id),
+     m_auto_commit(false)
+{
+    reset();
+}
 
-    if (key.code >= SCIM_KEY_space && key.code <= SCIM_KEY_asciitilde)
+UnikeyInstancePreedit::~UnikeyInstancePreedit()
+{
+}
+
+void UnikeyInstancePreedit::focus_in()
+{
+    UnikeyInstance::focus_in();
+    register_properties(CreatePropertyList());
+}
+
+void UnikeyInstancePreedit::focus_out()
+{
+    reset();
+}
+
+void UnikeyInstancePreedit::reset()
+{
+    UnikeyInstance::reset();
+
+    if (m_preeditstring.length())
     {
-        UnikeySetCapsState(key.mask & SCIM_KEY_ShiftMask,
-                           key.mask & SCIM_KEY_CapsLockMask);
+        commit_string(m_preeditstring);
+        hide_preedit_string();
+        m_preeditstring.clear();
+    }
+    m_auto_commit = false;
+}
 
-        // shift + space to restore keystroke
-        if (m_lastkey_with_shift == false
-            && key.mask & SCIM_KEY_ShiftMask
-            && key.code == SCIM_KEY_space
-            && !UnikeyAtWordBeginning())
-        {
-            UnikeyRestoreKeyStrokes();
-            if (UnikeyBackspaces == 0)
-            {
-                UnikeyPutChar(key.code);
-            }
-        }
+void UnikeyInstancePreedit::unikey_update_preedit_string(const WideString s, const bool visible)
+{
+    AttributeList attlist;
+    Attribute att;
 
-        else if ((Unikey_IM[m_im] == UkTelex || Unikey_IM[m_im] == UkSimpleTelex2)
-                 && m_process_w_AtBeginWord == false
-                 && UnikeyAtWordBeginning()
-                 && (key.code == SCIM_KEY_w || key.code == SCIM_KEY_W))
-        {
-            UnikeyPutChar(key.code);
-        }
+    // underline preedit string
+    att = Attribute(0, s.length(), SCIM_ATTR_DECORATE, SCIM_ATTR_DECORATE_UNDERLINE);
+    attlist.push_back(att);
 
-        else
-        {
-            UnikeyFilter(key.code);
-        }
+    if (m_ukopt.spellCheckEnabled==1 && UnikeyLastWordIsNonVn())
+    {
+        // red preedit string
+        att = Attribute(0, s.length(), SCIM_ATTR_FOREGROUND, 0xff0000);
+        attlist.push_back(att);
+    }
 
-        if (UnikeyBackspaces)
-        {
-            Unikey_send_backspace(UnikeyBackspaces);
-        }
+    update_preedit_string(s, attlist);
+    update_preedit_caret(s.length());
 
-        if (UnikeyBufChars)
-        {
-            if (Unikey_OC[m_oc] == CONV_CHARSET_XUTF8)
-            {
-                commit_string(utf8_mbstowcs((const char*)UnikeyBuf, UnikeyBufChars));  // send the solved string to client
-            }
-            else
-            {
-                static unsigned char buf[1024];
-                int bufSize=sizeof(buf)/sizeof(buf[0]);
+    if (visible == true)
+    {
+        show_preedit_string();
+    }
+    else
+    {
+        hide_preedit_string();
+    }
+}
 
-                latinToUtf(buf, UnikeyBuf, UnikeyBufChars, &bufSize);
-                commit_string(utf8_mbstowcs((const char*)buf, sizeof(buf)/sizeof(buf[0]) - bufSize));
-            }
-        }
-        else
-        {
-            Unikey_commit_key_event(key);
-            return true;
-        }
+bool UnikeyInstancePreedit::process_key_event(const KeyEvent& key)
+{
+    bool tmp;
 
-        return true;
+    tmp = unikey_process_key_event(key);
+
+    if ((key.code >= SCIM_KEY_space && key.code <= SCIM_KEY_asciitilde)
+        || (key.code >= SCIM_KEY_KP_Multiply && key.code <= SCIM_KEY_KP_9))
+    {
+        m_lastkey_with_shift = key.is_shift_down();
+    }
+    else
+    {
+        m_lastkey_with_shift = false;
     }
 
-    // else
-    reset();
-    return false;
+    return tmp;
 }
 
-/** This method use preedit string */
-bool UnikeyInstance::Unikey_process_key_event_preedit(const KeyEvent& key)
+bool UnikeyInstancePreedit::unikey_process_key_event(const KeyEvent& key)
 {
-    static int i;
+    static uint i;
 
     if (key.code == SCIM_KEY_Tab
         || key.mask & SCIM_KEY_ControlMask
@@ -537,7 +521,7 @@ bool UnikeyInstance::Unikey_process_key_event_preedit(const KeyEvent& key)
             else
             {
                 m_preeditstring.erase(len - UnikeyBackspaces, UnikeyBackspaces);
-                Unikey_update_preedit_string(m_preeditstring, true);
+                unikey_update_preedit_string(m_preeditstring, true);
             }
 
             // append key that need change tone pos after press backspace
@@ -555,7 +539,7 @@ bool UnikeyInstance::Unikey_process_key_event_preedit(const KeyEvent& key)
                 }
 
                 m_auto_commit = false;
-                Unikey_update_preedit_string(m_preeditstring, true);
+                unikey_update_preedit_string(m_preeditstring, true);
             }
         }
 
@@ -593,7 +577,7 @@ bool UnikeyInstance::Unikey_process_key_event_preedit(const KeyEvent& key)
             else
             {
                 m_preeditstring.push_back(key.code);
-                Unikey_update_preedit_string(m_preeditstring, true);
+                unikey_update_preedit_string(m_preeditstring, true);
             }
 
             m_auto_commit = true;
@@ -661,7 +645,7 @@ bool UnikeyInstance::Unikey_process_key_event_preedit(const KeyEvent& key)
             }
         }
 
-        Unikey_update_preedit_string(m_preeditstring, true);
+        unikey_update_preedit_string(m_preeditstring, true);
         return true;
     }
 
@@ -670,266 +654,216 @@ bool UnikeyInstance::Unikey_process_key_event_preedit(const KeyEvent& key)
     return false;
 }
 
-PropertyList UnikeyInstance::CreatePropertyList()
+PropertyList UnikeyInstancePreedit::CreatePropertyList()
 {
-    PropertyList props;
-    int i;
+    return UnikeyInstance::CreatePropertyList();
+}
 
-    Property prop("", "", "", "");
+void UnikeyInstancePreedit::trigger_property(const String &property)
+{
+    UnikeyInstance::trigger_property(property);
+}
 
-// input method
-    prop.set_key("/Unikey/InputMethod");
-    prop.set_label(Unikey_IMNames[m_im]);
-    prop.set_icon("");
-    prop.set_tip(_("Choose input method"));
-    props.push_back(prop);
 
-    for (i=0; i<NUM_INPUTMETHOD; i++)
-    {
-        prop.set_key(String("/Unikey/InputMethod/") + Unikey_IMNames[i] + String(m_im==i?"-Checked":""));
-        prop.set_label(Unikey_IMNames[i]);
-        prop.set_icon(m_im==i?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-        prop.set_tip("");
-        props.push_back(prop);
-    }
+/*********************************************************
+**************** Unikey Instance Classic *****************
+*********************************************************/
 
-// output charset
+UnikeyInstanceClassic::UnikeyInstanceClassic(UnikeyFactory *factory, const String &encoding, int id)
+    :UnikeyInstance(factory, encoding, id)
+{
+    reset();
+}
 
-    prop.set_key("/Unikey/OutputCharset");
-    prop.set_label(Unikey_OCNames[m_oc]);
-    prop.set_icon("");
-    prop.set_tip(_("Choose output charset"));
-    props.push_back(prop);
+UnikeyInstanceClassic::~UnikeyInstanceClassic()
+{
+}
 
-    for (i=0; i<NUM_OUTPUTCHARSET; i++)
-    {
-        prop.set_key(String("/Unikey/OutputCharset/") + Unikey_OCNames[i] + String(m_oc==i?"-Checked":""));
-        prop.set_label(Unikey_OCNames[i]);
-        prop.set_icon(m_oc==i?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-        prop.set_tip("");
-        props.push_back(prop);
-    }
+void UnikeyInstanceClassic::focus_in()
+{
+    UnikeyInstance::focus_in();
+    register_properties(CreatePropertyList());
+}
 
-// unikey options
-    // menu
-    prop.set_key("/Unikey/Options");
-    prop.set_label(_("Options"));
-    prop.set_icon(SCIM_ICONDIR SCIM_UNIKEY_ICON_CONFIGURE);
-    prop.set_tip(_("Configure Unikey here"));
-    props.push_back(prop);
+void UnikeyInstanceClassic::focus_out()
+{
+    reset();
+}
 
-    // spellcheck
-    prop.set_key(m_ukopt.spellCheckEnabled?
-                 "/Unikey/Options/SpellCheck/Disable":"/Unikey/Options/SpellCheck/Enable");
-    prop.set_label(_("Enable spell check"));
-    prop.set_icon(m_ukopt.spellCheckEnabled?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-    prop.set_tip(_("If enable, you can decrease mistake when typing"));
-    props.push_back(prop);
-    
-    // auto restore keystroke
-    prop.set_key(m_ukopt.autoNonVnRestore?
-                 "/Unikey/Options/AutoRestoreKeys/Disable":"/Unikey/Options/AutoRestoreKeys/Enable");
-    prop.set_label(_("Auto restore keys with invalid words"));
-    prop.set_icon(m_ukopt.autoNonVnRestore?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-    prop.set_tip(_("When typing a word not in Vietnamese,\n"
-                   "it will auto restore keystroke into original"));
-    props.push_back(prop);
-
-    // modern style
-    prop.set_key(m_ukopt.modernStyle?
-                 "/Unikey/Options/ModernStyle/Disable":"/Unikey/Options/ModernStyle/Enable");
-    prop.set_label(_("Use oà, uý (instead of òa, úy)"));
-    prop.set_icon(m_ukopt.modernStyle?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-    prop.set_tip("");
-    props.push_back(prop);
+void UnikeyInstanceClassic::reset()
+{
+    UnikeyInstance::reset();
+}
 
-    // freeMarking
-    prop.set_key(m_ukopt.freeMarking?
-                 "/Unikey/Options/FreeMarking/Disable":"/Unikey/Options/FreeMarking/Enable");
-    prop.set_label(_("Allow type with more freedom"));
-    prop.set_icon(m_ukopt.freeMarking?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-    prop.set_tip("");
-    props.push_back(prop);
+void UnikeyInstanceClassic::unikey_send_backspace(int nBackspace)
+{
+    static WideString ws;
+    static int n;
 
-    // macro
-    prop.set_key(m_ukopt.macroEnabled?
-                 "/Unikey/Options/EnabledMacro/Disable":"/Unikey/Options/EnabledMacro/Enable");
-    prop.set_label(_("Enable Macro"));
-    prop.set_icon(m_ukopt.macroEnabled?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-    prop.set_tip("");
-    props.push_back(prop);
+    //  if surrounding text was provided, use it instead of send backspace
+    if (get_surrounding_text(ws, n, nBackspace, 0))
+    {
+        // for type in Auto Complete in OpenOffice
+        // Hope this not rise bugs in others application
+        // not use SCIM_KEY_NullKey, because GTK application crash when GTK_IM_MODULE=scim
 
-    // preedit
-    prop.set_key(m_preedit?"/Unikey/Options/Preedit/Disable":"/Unikey/Options/Preedit/Enable");
-    prop.set_label(_("Enable PreEdit"));
-    prop.set_icon(m_preedit?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-    prop.set_tip(_("This option is best for most application\n"
-                   "But you may don't like it because it have an underline when typing"));
-    props.push_back(prop);
+        forward_key_event(SCIM_KEY_VoidSymbol);
 
-    // process w at begin
-    prop.set_key(m_process_w_AtBeginWord?
-                 "/Unikey/Options/ProcessWAtBegin/Disable":"/Unikey/Options/ProcessWAtBegin/Enable");
-    prop.set_label(_("Process W at word begin"));
-    prop.set_icon(m_process_w_AtBeginWord?SCIM_ICONDIR SCIM_UNIKEY_ICON_CHECK:"");
-    prop.set_tip(_("If enable, type W at begin\n"
-                   "of word will change to Ư."));
-    props.push_back(prop);
+        delete_surrounding_text(-ws.length(), ws.length());
+    }
+    else
+    {
+        for (int i=0; i < nBackspace; i++)
+            forward_key_event(SCIM_KEY_BackSpace);
+    }
+}
 
-    // config gui
-    prop.set_key("/Unikey/Options/RunSetup");
-    prop.set_label(_("Launch Unikey-setup"));
-    prop.set_icon(SCIM_ICONDIR SCIM_UNIKEY_ICON_MAIN);
-    prop.set_tip("");
-    props.push_back(prop);
+void UnikeyInstanceClassic::unikey_commit_key_event(const KeyEvent& key)
+{
+    static WideString s;
 
-    return props;
+    s.clear();
+    s.push_back(key.code);
+    commit_string(s);
 }
 
-void UnikeyInstance::trigger_property(const String &property)
+bool UnikeyInstanceClassic::process_key_event(const KeyEvent& key)
 {
-    bool change = false;
-    int i;
-
-// input method
-    if (!property.compare(0, strlen("/Unikey/InputMethod/"), "/Unikey/InputMethod/"))
-    {
-        for (i=0; i<NUM_INPUTMETHOD; i++)
-            if (!property.compare(strlen("/Unikey/InputMethod/"),
-                                  property.length() - strlen("/Unikey/InputMethod/"),
-                                  Unikey_IMNames[i]))
-            {
-                m_im = i;
-                __config->write(SCIM_IMENGINE_UNIKEY_INPUTMETHOD, m_im);
-                change = true;
-                break;
-            }
-    }
+    bool tmp;
 
-// output charset
-    else if (!property.compare(0, strlen("/Unikey/OutputCharset/"), "/Unikey/OutputCharset/"))
-    {
-        for (i=0; i<NUM_OUTPUTCHARSET; i++)
-            if (!property.compare(strlen("/Unikey/OutputCharset/"),
-                                  property.length() - strlen("/Unikey/OutputCharset/"),
-                                  Unikey_OCNames[i]))
-            {
-                m_oc = i;
-                __config->write(SCIM_IMENGINE_UNIKEY_OUTPUTCHARSET, m_oc);
-                change = true;
-                break;
-            }
-    }
+    tmp = unikey_process_key_event(key);
 
-// spellcheck
-    else if (property == "/Unikey/Options/SpellCheck/Enable")
+    if ((key.code >= SCIM_KEY_space && key.code <= SCIM_KEY_asciitilde)
+        || (key.code >= SCIM_KEY_KP_Multiply && key.code <= SCIM_KEY_KP_9))
     {
-        m_ukopt.spellCheckEnabled = true;
-        __config->write(SCIM_IMENGINE_UNIKEY_SPELLCHECKENABLED, true);
-        change = true;
+        m_lastkey_with_shift = key.is_shift_down();
     }
-    else if (property == "/Unikey/Options/SpellCheck/Disable")
+    else
     {
-        m_ukopt.spellCheckEnabled = false;
-        __config->write(SCIM_IMENGINE_UNIKEY_SPELLCHECKENABLED, false);
-        change = true;
+        m_lastkey_with_shift = false;
     }
 
-// auto restore keystroke
-    else if (property == "/Unikey/Options/AutoRestoreKeys/Enable")
-    {
-        m_ukopt.autoNonVnRestore = true;
-        __config->write(SCIM_IMENGINE_UNIKEY_AUTONONVNRESTORE, true);
-        change = true;
-    }
-    else if (property == "/Unikey/Options/AutoRestoreKeys/Disable")
-    {
-        m_ukopt.autoNonVnRestore = false;
-        __config->write(SCIM_IMENGINE_UNIKEY_AUTONONVNRESTORE, false);
-        change = true;
-    }
+    return tmp;
+}
 
-// modern style
-    else if (property == "/Unikey/Options/ModernStyle/Enable")
-    {
-        m_ukopt.modernStyle = true;
-        __config->write(SCIM_IMENGINE_UNIKEY_MODERNSTYLE, true);
-        change = true;
-    }
-    else if (property == "/Unikey/Options/ModernStyle/Disable")
+bool UnikeyInstanceClassic::unikey_process_key_event(const KeyEvent& key)
+{
+    if (key.is_key_release())
     {
-        m_ukopt.modernStyle = false;
-        __config->write(SCIM_IMENGINE_UNIKEY_MODERNSTYLE, false);
-        change = true;
+        return false;
     }
 
-// free Marking
-    else if (property == "/Unikey/Options/FreeMarking/Enable")
-    {
-        m_ukopt.freeMarking = true;
-        __config->write(SCIM_IMENGINE_UNIKEY_FREEMARKING, true);
-        change = true;
-    }
-    else if (property == "/Unikey/Options/FreeMarking/Disable")
-    {
-        m_ukopt.freeMarking = false;
-        __config->write(SCIM_IMENGINE_UNIKEY_FREEMARKING, false);
-        change = true;
-    }
-// macro 
-    else if (property == "/Unikey/Options/EnabledMacro/Enable")
-    {
-        m_ukopt.macroEnabled = true;
-        UnikeyLoadMacroTable(getMacroFile());
-        __config->write(SCIM_IMENGINE_UNIKEY_MACROENABLED, true);
-        change = true;
-    }
-    else if (property == "/Unikey/Options/EnabledMacro/Disable")
+    if (key.is_control_down() || key.mask & SCIM_KEY_AltMask)
     {
-        m_ukopt.macroEnabled = false;
-        __config->write(SCIM_IMENGINE_UNIKEY_MACROENABLED, false);
-        change = true;
+        reset();
+        return false;
     }
 
-// preedit
-    else if (property == "/Unikey/Options/Preedit/Enable")
-    {
-        m_preedit = true;
-        __config->write(SCIM_IMENGINE_UNIKEY_PREEDIT, true);
-        change = true;
-    }
-    else if (property == "/Unikey/Options/Preedit/Disable")
+    if (key.code >= SCIM_KEY_Shift_L && key.code <= SCIM_KEY_Hyper_R)
     {
-        m_preedit = false;
-        __config->write(SCIM_IMENGINE_UNIKEY_PREEDIT, false);
-        change = true;
+        return false;
     }
 
-// process w at begin
-    else if (property == "/Unikey/Options/ProcessWAtBegin/Enable")
-    {
-        m_process_w_AtBeginWord = true;
-        __config->write(SCIM_IMENGINE_UNIKEY_PROCESSWATWORDBEGIN, true);
-        change = true;
-    }
-    else if (property == "/Unikey/Options/ProcessWAtBegin/Disable")
+    if (key.code == SCIM_KEY_BackSpace)
     {
-        m_process_w_AtBeginWord = false;
-        __config->write(SCIM_IMENGINE_UNIKEY_PROCESSWATWORDBEGIN, false);
-        change = true;
-    }
+        UnikeyBackspacePress();     // xu ly phim backspace
+        if (UnikeyBackspaces==0)    // neu ukengine bao khong can xoa ky tu nao,
+            return false;  // thi tra lai backspace cho chuong trinh khach
+        else
+        {
+            unikey_send_backspace(UnikeyBackspaces);
 
-// run setup
-    else if (property == "/Unikey/Options/RunSetup")
-    {
-        system(LIBEXECDIR "/scim-setup-unikey &");
+            // append key that need change tone pos after press backspace
+            if (UnikeyBufChars)
+            {
+                if (Unikey_OC[m_oc] == CONV_CHARSET_XUTF8)
+                    commit_string(utf8_mbstowcs((const char*)UnikeyBuf, UnikeyBufChars));  // send the solved string to client
+                else
+                {
+                    static unsigned char buf[1024];
+                    int bufSize=sizeof(buf)/sizeof(buf[0]);
+
+                    latinToUtf(buf, UnikeyBuf, UnikeyBufChars, &bufSize);
+                    commit_string(utf8_mbstowcs((const char*)buf, sizeof(buf)/sizeof(buf[0]) - bufSize));
+                }
+            }
+
+            return true;
+        }
     }
 
-    if (change)
+    if (key.code >= SCIM_KEY_space && key.code <= SCIM_KEY_asciitilde)
     {
-        __config->flush();
-        focus_out();
-        focus_in();
+        UnikeySetCapsState(key.mask & SCIM_KEY_ShiftMask,
+                           key.mask & SCIM_KEY_CapsLockMask);
+
+        // shift + space to restore keystroke
+        if (m_lastkey_with_shift == false
+            && key.mask & SCIM_KEY_ShiftMask
+            && key.code == SCIM_KEY_space
+            && !UnikeyAtWordBeginning())
+        {
+            UnikeyRestoreKeyStrokes();
+            if (UnikeyBackspaces == 0)
+            {
+                UnikeyPutChar(key.code);
+            }
+        }
+
+        else if ((Unikey_IM[m_im] == UkTelex || Unikey_IM[m_im] == UkSimpleTelex2)
+                 && m_process_w_AtBeginWord == false
+                 && UnikeyAtWordBeginning()
+                 && (key.code == SCIM_KEY_w || key.code == SCIM_KEY_W))
+        {
+            UnikeyPutChar(key.code);
+        }
+
+        else
+        {
+            UnikeyFilter(key.code);
+        }
+
+        if (UnikeyBackspaces)
+        {
+            unikey_send_backspace(UnikeyBackspaces);
+        }
+
+        if (UnikeyBufChars)
+        {
+            if (Unikey_OC[m_oc] == CONV_CHARSET_XUTF8)
+            {
+                commit_string(utf8_mbstowcs((const char*)UnikeyBuf, UnikeyBufChars));  // send the solved string to client
+            }
+            else
+            {
+                static unsigned char buf[1024];
+                int bufSize=sizeof(buf)/sizeof(buf[0]);
+
+                latinToUtf(buf, UnikeyBuf, UnikeyBufChars, &bufSize);
+                commit_string(utf8_mbstowcs((const char*)buf, sizeof(buf)/sizeof(buf[0]) - bufSize));
+            }
+        }
+        else
+        {
+            unikey_commit_key_event(key);
+            return true;
+        }
+
+        return true;
     }
+
+    // else
+    reset();
+    return false;
+}
+
+PropertyList UnikeyInstanceClassic::CreatePropertyList()
+{
+    return UnikeyInstance::CreatePropertyList();
+}
+
+void UnikeyInstanceClassic::trigger_property(const String &property)
+{
+    UnikeyInstance::trigger_property(property);
 }
 
similarity index 100%
rename from src/scim_unikey_utils.cpp
rename to src/utils.cpp
similarity index 100%
rename from src/scim_unikey_utils.h
rename to src/utils.h