/*
- * gtkimmoduleime
+ * gtkimcontextime.c
* Copyright (C) 2003 Takuro Ashie
* Copyright (C) 2003-2004 Kazuki IWAMOTO
*
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
- * $Id$
*/
/*
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/appendix/hh/appendix/imeimes2_35ph.asp
*/
+#ifdef GTK_DISABLE_DEPRECATED
+#undef GTK_DISABLE_DEPRECATED
+#endif
+
#include "gtkimcontextime.h"
#include "imm-extra.h"
#include "gdk/win32/gdkwin32.h"
#include "gdk/gdkkeysyms.h"
-#include "gtk/gtkwidget.h"
+
+#include <pango/pango.h>
/* avoid warning */
#ifdef STRICT
gboolean use_preedit);
/* GtkIMContextIME's private functions */
-static void gtk_im_context_ime_set_preedit_font (GtkIMContext *context,
- PangoFont *font);
+static void gtk_im_context_ime_set_preedit_font (GtkIMContext *context);
+
static GdkFilterReturn
- gtk_im_context_ime_message_filter (GdkXEvent *xevent,
+gtk_im_context_ime_message_filter (GdkXEvent *xevent,
GdkEvent *event,
gpointer data);
static void get_window_position (GdkWindow *win,
void
gtk_im_context_ime_register_type (GTypeModule *type_module)
{
- static const GTypeInfo im_context_ime_info = {
+ const GTypeInfo im_context_ime_info = {
sizeof (GtkIMContextIMEClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
GdkWindow *client_window)
{
GtkIMContextIME *context_ime;
- HWND hwnd = NULL;
g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context));
context_ime = GTK_IM_CONTEXT_IME (context);
if (client_window)
{
HIMC himc;
+ HWND hwnd;
hwnd = GDK_WINDOW_HWND (client_window);
-
- /* get default ime context */
himc = ImmGetContext (hwnd);
- context_ime->opened = ImmGetOpenStatus (himc);
- ImmGetConversionStatus (himc,
- &context_ime->priv->conversion_mode,
- &context_ime->priv->sentence_mode);
- ImmReleaseContext (hwnd, himc);
-
+ if (himc)
+ {
+ context_ime->opened = ImmGetOpenStatus (himc);
+ ImmGetConversionStatus (himc,
+ &context_ime->priv->conversion_mode,
+ &context_ime->priv->sentence_mode);
+ ImmReleaseContext (hwnd, himc);
+ }
}
else if (context_ime->focus)
{
GdkEventKey *event)
{
GtkIMContextIME *context_ime;
- HWND hwnd;
- HIMC himc;
gboolean retval = FALSE;
+ guint32 c;
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;
+ return FALSE;
+
+ if (event->state & GDK_CONTROL_MASK)
+ return FALSE;
context_ime = GTK_IM_CONTEXT_IME (context);
+
if (!context_ime->focus)
return FALSE;
+
if (!GDK_IS_WINDOW (context_ime->client_window))
return FALSE;
- hwnd = GDK_WINDOW_HWND (context_ime->client_window);
- himc = ImmGetContext (hwnd);
-
- /* FIXME!! event->string is deprecated */
- if (event->string && *event->string
- && !g_unichar_iscntrl (g_utf8_get_char_validated (event->string,
- strlen (event->string))))
+ c = gdk_keyval_to_unicode (event->keyval);
+ if (c)
{
- g_signal_emit_by_name (G_OBJECT (context_ime), "commit", event->string);
+ guchar utf8[10];
+ int len = g_unichar_to_utf8 (c, utf8);
+ utf8[len] = 0;
+
+ g_signal_emit_by_name (context_ime, "commit", utf8);
retval = TRUE;
}
- ImmReleaseContext (hwnd, himc);
-
return retval;
}
HWND hwnd;
HIMC himc;
+ if (!context_ime->client_window)
+ return;
+
hwnd = GDK_WINDOW_HWND (context_ime->client_window);
himc = ImmGetContext (hwnd);
if (!himc)
ImmNotifyIME (himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
context_ime->preediting = FALSE;
- g_signal_emit_by_name (context, "preedit_changed");
+ g_signal_emit_by_name (context, "preedit-changed");
ImmReleaseContext (hwnd, himc);
}
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 (!himc)
+ return g_strdup ("");
if (context_ime->preediting)
{
- gpointer buf;
glong len;
- GError *error = NULL;
-#ifdef UNICODE
- len = ImmGetCompositionString (himc, GCS_COMPSTR, NULL, 0);
- buf = g_malloc (len);
- if (len > 0 && buf)
- {
- ImmGetCompositionString (himc, GCS_COMPSTR, 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_COMPSTR, NULL, 0);
- buf = g_malloc (len);
- if (len > 0 && buf)
- {
- ImmGetCompositionString (himc, GCS_COMPSTR, 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 */
+ len = ImmGetCompositionStringW (himc, GCS_COMPSTR, NULL, 0);
+ if (len > 0)
+ {
+ GError *error = NULL;
+ gpointer buf = g_alloca (len);
+
+ ImmGetCompositionStringW (himc, GCS_COMPSTR, buf, len);
+ len /= 2;
+ 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 = ImmGetCompositionStringW (himc, GCS_CURSORPOS, NULL, 0);
+ if (pos < 0 || len < pos)
+ {
+ g_warning ("ImmGetCompositionString: "
+ "Invalid cursor position!");
+ pos = 0;
+ }
+ }
+ }
}
if (!utf8str)
HWND hwnd;
HIMC himc;
- /* g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context_ime), attr); */
-
hwnd = GDK_WINDOW_HWND (context_ime->client_window);
himc = ImmGetContext (hwnd);
-
- g_return_val_if_fail (himc, attrs);
+ if (!himc)
+ return attrs;
if (context_ime->preediting)
{
/*
* get attributes list of IME.
*/
- len = ImmGetCompositionString (himc, GCS_COMPATTR, NULL, 0);
- buf = g_malloc (len);
- ImmGetCompositionString (himc, GCS_COMPATTR, buf, len);
+ len = ImmGetCompositionStringW (himc, GCS_COMPATTR, NULL, 0);
+ buf = g_alloca (len);
+ ImmGetCompositionStringW (himc, GCS_COMPATTR, buf, len);
/*
* schr and echr are pointer in utf8str.
/*
* spos and epos are buf(attributes list of IME) position by
* bytes.
- * If UNICODE is defined, this value is same with UTF-8 offset.
- * If it's not defined, this value is same with bytes position
- * of locale encoded preedit string.
- *
+ * Using the wide-char API, this value is same with UTF-8 offset.
*/
-#ifdef UNICODE
- epos = g_utf8_pointer_to_offset (utf8str, echr);
-#else /* not UNICODE */
- gchar *tmpstr;
- GError *error = NULL;
-
- epos = spos;
- tmpstr = g_locale_from_utf8 (schr, echr - schr, NULL, NULL, &error);
- if (error)
- {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
- if (tmpstr)
- {
- epos += strlen (tmpstr);
- g_free (tmpstr);
- }
-#endif /* not UNICODE */
+ epos = g_utf8_pointer_to_offset (utf8str, echr);
+
/*
* sidx and eidx are positions in utf8str by bytes.
*/
sidx = eidx;
}
}
- g_free (buf);
}
ImmReleaseContext (hwnd, himc);
if (!GDK_IS_WINDOW (context_ime->client_window))
return;
+ /* swtich current context */
+ context_ime->focus = TRUE;
+
hwnd = GDK_WINDOW_HWND (context_ime->client_window);
himc = ImmGetContext (hwnd);
if (!himc)
gdk_window_get_user_data (context_ime->client_window, (gpointer) & widget);
if (GTK_IS_WIDGET (widget))
{
- g_signal_connect (G_OBJECT (widget), "hierarchy-changed",
+ g_signal_connect (widget, "hierarchy-changed",
G_CALLBACK (cb_client_widget_hierarchy_changed),
context_ime);
}
/* warning? */
}
- /* swtich current context */
- context_ime->focus = TRUE;
-
/* restore preedit context */
ImmSetConversionStatus (himc,
context_ime->priv->conversion_mode,
ImmSetOpenStatus (himc, TRUE);
if (context_ime->preediting)
{
- ImmSetCompositionString (himc,
- SCS_SETSTR,
- context_ime->priv->comp_str,
- context_ime->priv->comp_str_len, NULL, 0);
+ ImmSetCompositionStringW (himc,
+ SCS_SETSTR,
+ context_ime->priv->comp_str,
+ context_ime->priv->comp_str_len, NULL, 0);
FREE_PREEDIT_BUFFER (context_ime);
}
}
if (!GDK_IS_WINDOW (context_ime->client_window))
return;
+ /* swtich current context */
+ context_ime->focus = FALSE;
+
hwnd = GDK_WINDOW_HWND (context_ime->client_window);
himc = ImmGetContext (hwnd);
if (!himc)
FREE_PREEDIT_BUFFER (context_ime);
context_ime->priv->comp_str_len
- = ImmGetCompositionString (himc, GCS_COMPSTR, NULL, 0);
+ = ImmGetCompositionStringW (himc, GCS_COMPSTR, NULL, 0);
context_ime->priv->comp_str
= g_malloc (context_ime->priv->comp_str_len);
- ImmGetCompositionString (himc, GCS_COMPSTR,
- context_ime->priv->comp_str,
- context_ime->priv->comp_str_len);
+ ImmGetCompositionStringW (himc, GCS_COMPSTR,
+ context_ime->priv->comp_str,
+ context_ime->priv->comp_str_len);
context_ime->priv->read_str_len
- = ImmGetCompositionString (himc, GCS_COMPREADSTR, NULL, 0);
+ = ImmGetCompositionStringW (himc, GCS_COMPREADSTR, NULL, 0);
context_ime->priv->read_str
= g_malloc (context_ime->priv->read_str_len);
- ImmGetCompositionString (himc, GCS_COMPREADSTR,
- context_ime->priv->read_str,
- context_ime->priv->read_str_len);
+ ImmGetCompositionStringW (himc, GCS_COMPREADSTR,
+ context_ime->priv->read_str,
+ context_ime->priv->read_str_len);
}
ImmSetOpenStatus (himc, FALSE);
"cannot find toplevel window.");
}
- /* swtich current context */
- context_ime->focus = FALSE;
-
/* clean */
ImmReleaseContext (hwnd, himc);
}
context_ime->use_preedit = use_preedit;
if (context_ime->preediting)
{
- /* FIXME */
HWND hwnd;
HIMC himc;
himc = ImmGetContext (hwnd);
if (!himc)
return;
+
+ /* FIXME: What to do? */
+
+ ImmReleaseContext (hwnd, himc);
}
}
static void
-gtk_im_context_ime_set_preedit_font (GtkIMContext *context, PangoFont *font)
+gtk_im_context_ime_set_preedit_font (GtkIMContext *context)
{
GtkIMContextIME *context_ime;
GtkWidget *widget = NULL;
HWND hwnd;
HIMC himc;
+ HKL ime = GetKeyboardLayout (0);
+ const gchar *lang;
+ gunichar wc;
PangoContext *pango_context;
+ PangoFont *font;
LOGFONT *logfont;
g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context));
if (!pango_context)
goto ERROR_OUT;
- if (!font)
- font = pango_context_load_font (pango_context, widget->style->font_desc);
+ /* Try to make sure we use a font that actually can show the
+ * language in question.
+ */
+
+ switch (PRIMARYLANGID (LOWORD (ime)))
+ {
+ case LANG_JAPANESE:
+ lang = "ja"; break;
+ case LANG_KOREAN:
+ lang = "ko"; break;
+ case LANG_CHINESE:
+ switch (SUBLANGID (LOWORD (ime)))
+ {
+ case SUBLANG_CHINESE_TRADITIONAL:
+ lang = "zh_TW"; break;
+ case SUBLANG_CHINESE_SIMPLIFIED:
+ lang = "zh_CN"; break;
+ case SUBLANG_CHINESE_HONGKONG:
+ lang = "zh_HK"; break;
+ case SUBLANG_CHINESE_SINGAPORE:
+ lang = "zh_SG"; break;
+ case SUBLANG_CHINESE_MACAU:
+ lang = "zh_MO"; break;
+ default:
+ lang = "zh"; break;
+ }
+ break;
+ default:
+ lang = ""; break;
+ }
+
+ if (lang[0])
+ {
+ /* We know what language it is. Look for a character, any
+ * character, that language needs.
+ */
+ PangoLanguage *pango_lang = pango_language_from_string (lang);
+ PangoFontset *fontset =
+ pango_context_load_fontset (pango_context,
+ gtk_widget_get_style (widget)->font_desc,
+ pango_lang);
+ gunichar *sample =
+ g_utf8_to_ucs4 (pango_language_get_sample_string (pango_lang),
+ -1, NULL, NULL, NULL);
+ wc = 0x4E00; /* In all CJK languages? */
+ if (sample != NULL)
+ {
+ int i;
+
+ for (i = 0; sample[i]; i++)
+ if (g_unichar_iswide (sample[i]))
+ {
+ wc = sample[i];
+ break;
+ }
+ g_free (sample);
+ }
+ font = pango_fontset_get_font (fontset, wc);
+ g_object_unref (fontset);
+ }
+ else
+ font = pango_context_load_font (pango_context, gtk_widget_get_style (widget)->font_desc);
+
if (!font)
goto ERROR_OUT;
if (logfont)
ImmSetCompositionFont (himc, logfont);
+ g_object_unref (font);
+
ERROR_OUT:
/* clean */
ImmReleaseContext (hwnd, himc);
ImmSetCandidateWindow (himc, &cf);
if ((msg->lParam & GCS_COMPSTR))
- g_signal_emit_by_name (context, "preedit_changed");
+ g_signal_emit_by_name (context, "preedit-changed");
if (msg->lParam & GCS_RESULTSTR)
{
gsize len;
- gpointer buf;
gchar *utf8str = NULL;
GError *error = NULL;
- len = ImmGetCompositionString (himc, GCS_RESULTSTR, NULL, 0);
- buf = g_alloca (len);
- if (len > 0 && buf)
+ len = ImmGetCompositionStringW (himc, GCS_RESULTSTR, NULL, 0);
+
+ if (len > 0)
{
- ImmGetCompositionString (himc, GCS_RESULTSTR, buf, len);
-#ifdef UNICODE
- len /= sizeof (gunichar2);
- utf8str = g_utf16_to_utf8 (buf, len, NULL, NULL, &error);
-#else /* not UNICODE */
- utf8str = g_locale_to_utf8 (buf, len, NULL, NULL, &error);
-#endif /* not UNICODE */
+ gpointer buf = g_alloca (len);
+ ImmGetCompositionStringW (himc, GCS_RESULTSTR, buf, len);
+ len /= 2;
+ utf8str = g_utf16_to_utf8 (buf, len, NULL, NULL, &error);
if (error)
{
g_warning ("%s", error->message);
if (utf8str)
{
- g_signal_emit_by_name (G_OBJECT (context), "commit", utf8str);
+ g_signal_emit_by_name (context, "commit", utf8str);
g_free (utf8str);
+ retval = TRUE;
}
}
case WM_IME_STARTCOMPOSITION:
context_ime->preediting = TRUE;
gtk_im_context_ime_set_cursor_location (context, NULL);
- g_signal_emit_by_name (context, "preedit_start");
+ g_signal_emit_by_name (context, "preedit-start");
if (context_ime->use_preedit)
retval = TRUE;
break;
case WM_IME_ENDCOMPOSITION:
context_ime->preediting = FALSE;
- g_signal_emit_by_name (context, "preedit_changed");
- g_signal_emit_by_name (context, "preedit_end");
+ g_signal_emit_by_name (context, "preedit-changed");
+ g_signal_emit_by_name (context, "preedit-end");
if (context_ime->use_preedit)
retval = TRUE;
break;
{
case IMN_SETOPENSTATUS:
context_ime->opened = ImmGetOpenStatus (himc);
- gtk_im_context_ime_set_preedit_font (context, NULL);
+ gtk_im_context_ime_set_preedit_font (context);
break;
default: