diff --git a/scim-wnn/src/preeditor.cpp b/scim-wnn/src/preeditor.cpp
index 6333f51..1a1e661 100644
--- a/scim-wnn/src/preeditor.cpp
+++ b/scim-wnn/src/preeditor.cpp
@@ -164,6 +164,42 @@
 
 
 /*!
+    \fn PreEditor::convHanZen(WideString &t)
+ */
+void PreEditor::convHanZen(WideString &t)
+{
+    WideString start_c,end_c,conv_c;
+    iconvert.convert(start_c,String("!"));
+    iconvert.convert(end_c,String("~"));
+    iconvert.convert(conv_c,String("��"));
+    for(unsigned int i = 0;i < t.size();i ++) {
+        if ((t[i] >= start_c[0]) && (t[i] <= end_c[0]))
+            t[i] = t[i] - start_c[0] + conv_c[0];
+    }
+    return;
+
+}
+
+
+/*!
+    \fn PreEditor::convZenHan(WideString &t)
+ */
+void PreEditor::convZenHan(WideString &t)
+{
+    WideString start_c,end_c,conv_c;
+    iconvert.convert(start_c,String("��"));
+    iconvert.convert(end_c,String("��"));
+    iconvert.convert(conv_c,String("!"));
+    for(unsigned int i = 0;i < t.size();i ++) {
+        if ((t[i] >= start_c[0]) && (t[i] <= end_c[0]))
+            t[i] = t[i] - start_c[0] + conv_c[0];
+    }
+    return;
+
+}
+
+
+/*!
     \fn PreEditor::hiraKata()
  */
 void PreEditor::hiraKata()
@@ -208,3 +244,4 @@
 {
     return(false);
 }
+
diff --git a/scim-wnn/src/preeditor.h b/scim-wnn/src/preeditor.h
index 57af0ba..b9788a9 100644
--- a/scim-wnn/src/preeditor.h
+++ b/scim-wnn/src/preeditor.h
@@ -56,6 +56,8 @@
     virtual String getModeName();
     static void convHiraKata(WideString &t);
     static void convKataHira(WideString &t);
+    static void convHanZen(WideString &t);
+    static void convZenHan(WideString &t);
     virtual bool cancelEvent();
 
 protected:
diff --git a/scim-wnn/src/romkan.cpp b/scim-wnn/src/romkan.cpp
index 513e45a..cb52511 100644
--- a/scim-wnn/src/romkan.cpp
+++ b/scim-wnn/src/romkan.cpp
@@ -78,25 +78,46 @@
  */
 WideString Romkan::insert(char k)
 {
-    if (k == 0) return(text);
-    if ((mode == ROMA) && (k == 'q')) {
-        mode = LATIN;
-        buf.clear();
-        return(text);
-    }
-    buf += k;
     String s;
     s = k;
-    text = text.substr(0,pos) + utf8_mbstowcs(s) + text.substr(pos);
-    pos ++;
-    if (mode == LATIN) {
-        buf.clear();
-        return(text);
+    if (k == 0) return(text);
+    switch(mode) {
+        case LATIN: {
+            buf.clear();
+            text = text.substr(0,pos) + utf8_mbstowcs(s) + text.substr(pos);
+            pos ++;
+            return(text);
+            break;
+        }
+        case WLATIN: {
+            buf.clear();
+            WideString w = utf8_mbstowcs(s);
+            convHanZen(w);
+            text = text.substr(0,pos) + w + text.substr(pos);
+            pos ++;
+            return(text);
+            break;
+        }
+        case ROMA: {
+            if (k == 'q') {
+                mode = LATIN;
+                buf.clear();
+                return(text);
+                break;
+            } else if (k == 'Q') {
+                mode = WLATIN;
+                buf.clear();
+                return(text);
+                break;
+            }
+            buf += k;
+            text = text.substr(0,pos) + utf8_mbstowcs(s) + text.substr(pos);
+            pos ++;
+            return(eval());
+            break;
+        }
     }
-
-
-    //return(text);
-    return(eval());
+    return(text);
 }
 
 
@@ -234,7 +255,7 @@
  */
 bool Romkan::keyEventHook(const KeyEvent &key)
 {
-    if ((isprint(key.code)) && (mode == LATIN)) {
+    if ((isprint(key.code)) && ((mode == LATIN) || (mode == WLATIN))) {
         if (!(key.mask & (SCIM_KEY_AltMask | SCIM_KEY_ControlMask))) {
             insert(key.get_ascii_code());
             return(true);