minttyでIMEが動くようにしてみた

自作のTERMでも作れないかと思ってck, ckw, rxvtあたりを調べていたところ
cygwinputtyベースのminttyを発見。
http://code.google.com/p/mintty/

ソースが小さくて読みやすそうな予感がしたのでさっそく試してみたのだが
ほとんどputtyそのままでいい感じだった。
しかし、puttyベースなのにIMEが動かないという弱点があったので、
ちょうどいいのでコード読むついでにckのソースを見ながらやってみることにした。
修正箇所は少なくてすぐ終わりそうだったのだがIME
起動した後のメッセージがさっぱり届かないことに悩む。
CreateWindow時などに事前に仕込みが必要なのかと
いろいろ調べてみたが特にそれらしいところはない。
仕方なく、putty本体の方のソースに探索範囲を拡げてみた。
そこで変なところでTranslateMessageを呼んでいるのを発見。
周囲のコメントからもこれらしいと目星をつけたところそこが当たりだった。
要するに、
WM_IME_COMPOSITIONが届くにはTranslateMessageが必要だったんだよw


というわけでこんな感じになった。

diff --git a/winmain.c b/winmain.c
index cffe681..532c4a1 100644
--- a/winmain.c
+++ b/winmain.c
@@ -631,12 +631,23 @@ win_proc(HWND wnd, UINT message, WPARAM wp, LPARAM lp)
     when WM_MOUSEWHEEL: win_mouse_wheel(wp, lp);
     when WM_KEYDOWN or WM_SYSKEYDOWN: if (win_key_down(wp, lp)) return 0;
     when WM_KEYUP or WM_SYSKEYUP: if (win_key_up(wp, lp)) return 0;
+    /*
     when WM_CHAR or WM_SYSCHAR: { // TODO: handle wchar and WM_UNICHAR
       char c = (uchar) wp;
       term_seen_key_event();
       lpage_send(CP_ACP, &c, 1, 1);
       return 0;
     }
+    */
+    when WM_IME_COMPOSITION:
+      if(lp & GCS_RESULTSTR) {
+        HIMC hImc = ImmGetContext(wnd);
+        LONG byteCount=ImmGetCompositionString(hImc, GCS_RESULTSTR, NULL, 0);
+        CHAR mb_buf[byteCount];
+        ImmGetCompositionString(hImc, GCS_RESULTSTR, mb_buf, byteCount);
+        lpage_send(CP_OEMCP, mb_buf, byteCount, 1);
+        ImmReleaseContext(wnd, hImc);
+      }
     when WM_INPUTLANGCHANGE:
       sys_cursor_update();
     when WM_IME_STARTCOMPOSITION: {
@@ -772,6 +783,17 @@ win_proc(HWND wnd, UINT message, WPARAM wp, LPARAM lp)
   * Any messages we don't process completely above are passed through to
   * DefWindowProc() for default processing.
   */
+
+  if (wp == VK_PROCESSKEY) { /* IME PROCESS key */
+    if (message == WM_KEYDOWN) {
+      MSG m;
+      m.hwnd = wnd;
+      m.message = WM_KEYDOWN;
+      m.wParam = wp;
+      m.lParam = lp & 0xdfff;
+      TranslateMessage(&m);
+    }
+  }
   return DefWindowProc(wnd, message, wp, lp);
 }

Cygwin-1.7上で環境変数CYGWIN=codepage:utf-8での動作しか試していないので
従来のSJISだと動くかわからないが、
UTF8環境においてはcygterm+puttyと同じような使用感になった。
とおもったが、
w3mとか使うとずれる。
UNICODEambiguous widthくさいな。


ちなみに
minttyの設定は起動してから右クリックのコンテキストメニューからできる。
設定結果は~/.minttyrcに保存される。