Takuro Ashie
ashie****@homa*****
2004年 2月 16日 (月) 20:01:44 JST
足永です。 英数字が2重に変換される問題 http://www.homa.ne.jp/~ashie/diary/board.cgi?act=read&msgid=542 で、かなり以前にEBView作者の須藤さんからパッチを頂いています。 中身はまだまったく検討していないのですが(かなり忘れてしまっています)、 CVS版はデフォルトがon the spot形式になってコードか少々変更されているので、 このままでは適用できない可能性がありますし、正しい対応かどうかもまったく 検討しておりません。 これから時間を作って読み直してみます。 Begin forwarded message: Date: Sun, 18 Jan 2004 16:09:58 +0900 From: Kenichi Suto <ksuto****@ybb*****> To: "ashie****@homa*****" <ashie****@homa*****> Subject: imime-0.0.6 と GTK+-2.2.4 須藤@EBView作者です。 こんにちは。 imime を使わせていただいていますが,最近 GTK+-2.2.4 (tml版) にしたとこ ろ,正常に入力できなくなってしまいました。現象としては,無変換の状態で英 文字を入力すると,同じ文字が2つずつ入力されます。IME のウィンドウもテキ ストボックスに重ならず,少し右にずれてしまっており,同じ文字が GTK と IME で 2重に表示されたようになります。また,確定しても何も入力されませ ん。さらに,アプリケーション起動時に次のメッセージが表示されます。 ----------- ** (ebview.exe:13192): CRITICAL **: file gtkimcontextime.c: line 404 (get_utf8_p reedit_string): assertion `himc' failed ** (ebview.exe:13192): CRITICAL **: file gtkimcontextime.c: line 500 (get_pango_ attr_list): assertion `himc' failed ** (ebview.exe:13192): CRITICAL **: file gtkimcontextime.c: line 404 (get_utf8_p reedit_string): assertion `himc' failed ** (ebview.exe:13192): CRITICAL **: file gtkimcontextime.c: line 500 (get_pango_ attr_list): assertion `himc' failed ------------ そこでいろいろといじってみたところ,添付のパッチで外見上は正常っぽく動く ようになりました。変更点は次のとおりです。 1. キーリリースイベントは無視する。 英字が 2 重に入力される件の対応です。 2. 上記のエラーへの対処。 3. 入力中の文字を保持しておくようにして,確定したところでこれを comit す る。gtk_im_context_ime_get_preedit_string()の都度 ImmGetCompositionString() を呼ぶと空文字列が返ることがあったため,IME か らメッセージがきたタイミングでだけ文字列を取りに行くようにしました。また この結果,cursor_pos は完全に無視しています。cursor_pos を 0 にしない と,入力するたびに IME のウィンドウがどんどん右にずれていく現象も出まし た(本来はウィンドウ位置の計算方法を変えるべきか)。 このあたりほとんど理解していないのでこれで正しいとは思えませんが,個人的 には使えているので,とりあえずお送りしておきます。 先日 EBView 0.3.3 をリリースしましたが,暫定的に imime をはずした状態に しています。Pango が新しくなって Windows でも表示がかなり高速になったの で,日本語入力がきちんとできればいい感じになりそうです。 動作環境: ・Windows 2000 ・ATOK 16 ・tml 版 GTK+-2.2.4 ・cygwin (ただし -mno-cygwin なので Windows ネイティブ) ・imime-0.0.6 ----- パッチここから ----- *** gtkimcontextime.h.orig Thu Jul 24 21:04:57 2003 --- gtkimcontextime.h Sun Jan 18 13:25:59 2004 *************** *** 57,62 **** --- 57,63 ---- GdkRectangle cursor_location; gint preedit_change; + gchar *str; GtkIMContextIMEPrivate *priv; }; *** gtkimcontextime.c.orig Sun Jul 27 22:49:52 2003 --- gtkimcontextime.c Sun Jan 18 15:40:44 2004 *************** *** 208,213 **** --- 208,215 ---- context_ime->cursor_location.height = 0; context_ime->preedit_change = GTK_IM_CONTEXT_IME_PREEDIT_ALWAYS; context_ime->priv = g_malloc0 (sizeof (GtkIMContextIMEPrivate)); + context_ime->str = NULL; + } *************** *** 339,344 **** --- 341,353 ---- g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context), FALSE); g_return_val_if_fail (event, FALSE); + if(event->type == GDK_KEY_RELEASE) + return retval; + + if(event->keyval == GDK_Return ) { + return retval; + } + context_ime = GTK_IM_CONTEXT_IME (context); if (!context_ime->focus) return FALSE; if (!GDK_IS_WINDOW (context_ime->client_window)) return FALSE; *************** *** 485,490 **** --- 495,604 ---- } + static gchar * + get_utf8_result_string (GtkIMContextIME *context_ime, gint *pos_ret) + { + gchar *utf8str = NULL; + HWND hwnd; + HIMC himc; + gint pos = 0; + + if (pos_ret) + *pos_ret = 0; + + /* + g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context_ime), + g_strdup ("")); + */ + + hwnd = GDK_WINDOW_HWND (context_ime->client_window); + himc = ImmGetContext (hwnd); + + /* shouldn't return NULL */ + g_return_val_if_fail (himc, g_strdup ("")); + + if (context_ime->preediting) { + gpointer buf; + glong len; + GError *error = NULL; + + #ifdef UNICODE + len = ImmGetCompositionString (himc, GCS_RESULTSTR, NULL, 0); + buf = g_malloc (len); + if (len > 0 && buf) { + ImmGetCompositionString (himc, GCS_RESULTSTR, buf, len); + len /= sizeof (gunichar2); + utf8str = g_utf16_to_utf8 (buf, len, NULL, NULL, &error); + if (error) { + g_warning ("%s", error->message); + g_error_free (error); + } + + if (pos_ret) { + pos = ImmGetCompositionString(himc, GCS_CURSORPOS, NULL, 0); + if (pos < 0 || len < pos) { + g_warning ("ImmGetCompositionString: " + "Invalid cursor position!"); + pos = 0; + } + } + g_free (buf); + } + #else /* not UNICODE */ + len = ImmGetCompositionString (himc, GCS_RESULTSTR, NULL, 0); + buf = g_malloc (len); + if (len > 0 && buf) { + ImmGetCompositionString (himc, GCS_RESULTSTR, buf, len); + utf8str = g_locale_to_utf8 (buf, len, NULL, NULL, &error); + if (error) { + g_warning ("%s", error->message); + g_error_free (error); + } + + if (pos_ret) { + pos = ImmGetCompositionString(himc, GCS_CURSORPOS, NULL, 0); + /* get cursor position by offset */ + if (pos < len && utf8str) { + gchar *tmpstr; + + tmpstr = g_locale_to_utf8 (buf, pos, NULL, NULL, &error); + if (error) { + g_warning ("%s", error->message); + g_error_free (error); + } + if (tmpstr) { + pos = g_utf8_strlen (tmpstr, -1); + } else { + pos = 0; + } + g_free (tmpstr); + } else if (pos == len && utf8str) { + pos = g_utf8_strlen(utf8str, -1); + } else { + g_warning ("ImmGetCompositionString: " + "Invalid cursor position!"); + pos = 0; + } + } + g_free (buf); + } + #endif /* not UNICODE */ + } + + if (!utf8str) { + utf8str = g_strdup(""); + pos = 0; + } + + if (pos_ret) + *pos_ret = pos; + + ImmReleaseContext (hwnd, himc); + + return utf8str; + } + + static PangoAttrList * get_pango_attr_list (GtkIMContextIME *context_ime, const gchar *utf8str) { *************** *** 495,500 **** --- 609,617 ---- /* g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context_ime), attr); */ hwnd = GDK_WINDOW_HWND (context_ime->client_window); + if(hwnd == NULL) + return attrs; + himc = ImmGetContext (hwnd); g_return_val_if_fail (himc, attrs); *************** *** 613,619 **** context_ime = GTK_IM_CONTEXT_IME (context); ! utf8str = get_utf8_preedit_string (context_ime, &pos); if (attrs) *attrs = get_pango_attr_list (context_ime, utf8str); --- 730,744 ---- context_ime = GTK_IM_CONTEXT_IME (context); ! if(context_ime->preediting == FALSE) { ! utf8str = g_strdup(""); ! } else { ! if(context_ime->str) { ! utf8str = g_strdup(context_ime->str); ! } else { ! utf8str = g_strdup(""); ! } ! } if (attrs) *attrs = get_pango_attr_list (context_ime, utf8str); *************** *** 954,965 **** switch (msg->message) { case WM_IME_COMPOSITION: ! if ((msg->lParam & GCS_COMPSTR) && PREEDIT_IS_ACTIVE (context_ime)) g_signal_emit_by_name (context, "preedit_changed"); break; case WM_IME_STARTCOMPOSITION: context_ime->preediting = TRUE; gtk_im_context_ime_set_cursor_location (context, NULL); if (PREEDIT_IS_ACTIVE (context_ime)) g_signal_emit_by_name (context, "preedit_start"); --- 1079,1102 ---- switch (msg->message) { case WM_IME_COMPOSITION: ! if (msg->lParam & GCS_RESULTSTR) { ! context_ime->str = get_utf8_result_string(context_ime, NULL); ! break; ! } ! ! if ((msg->lParam & GCS_COMPSTR) && PREEDIT_IS_ACTIVE (context_ime)) { ! context_ime->str = get_utf8_preedit_string (context_ime, NULL); g_signal_emit_by_name (context, "preedit_changed"); + } break; case WM_IME_STARTCOMPOSITION: context_ime->preediting = TRUE; + + if(context_ime->str) { + g_free(context_ime->str); + context_ime->str = NULL; + } gtk_im_context_ime_set_cursor_location (context, NULL); if (PREEDIT_IS_ACTIVE (context_ime)) g_signal_emit_by_name (context, "preedit_start"); *************** *** 970,975 **** --- 1107,1116 ---- if (PREEDIT_IS_ACTIVE (context_ime)) { g_signal_emit_by_name (context, "preedit_changed"); g_signal_emit_by_name (context, "preedit_end"); + if(context_ime->str){ + g_signal_emit_by_name (G_OBJECT (context_ime), + "commit", context_ime->str); + } } break; ----- パッチここまで ----- ======================================= 須藤 賢一 (Kenichi Suto) =======================================