Adding context to GtkIMContextIM
- From: Owen Taylor <otaylor redhat com>
- To: gtk-i18n-list gnome org, gtk-devel-list gnome org
- Cc: thep links nectec or th, hideki hiura sun com
- Subject: Adding context to GtkIMContextIM
- Date: 31 Oct 2001 22:06:29 -0500
Figuring that any feature that MS Office has is clearly essential for
the GTK+-2.0 release, I went ahead and created a patch for retrieving
and deleting context to GtkIMContext, so that we can have ultra-cool
Thai input methods. I'll send the patch adding a talking paperclip
next.
I went with names like gtk_im_context_get_surrounding() rather
than gtk_im_context_get_context(), because the latter is clearly
too confusing.
The patch adds to GtkIMContext:
- A ::retrieve_surrounding signal. In response to this, the
application/widget, if it chooses to handle the signal, should call
gtk_im_context_set_surrounding() with as much context as available
and return TRUE.
- A ::delete_surrounding signal. In response to this, the
application/widget, if it chooses to handle the signal, should
delete the text specified as arguments to the signal and return
TRUE.
- A function gtk_im_context_get_surrounding() which emits
::retrieve_surrounding and returns any text set.
- A function gtk_im_context_set_surrounding()
- A wrapper function gtk_im_context_delete_surrounding for the
::delete_surrounding signal.
Elsewhere:
- Support for this in GtkIMMultiContext
- Support for both signal for GtkEntry and GtkTextView
And:
- A change to GtkIMContextSimple so that any time the word "own" is
typed, it changes it to "Owen". I know that some people will find
this a bit inconvenient, but it's very useful for me.
I think this works pretty well. It's going to only bridge to a very
limited subset of the XIM context and reconversion API, but it should
handle the needs of context-sensitive input well.
Some possible questions about the details of the patch:
- Does it make sense to have a boolean return from the
::retrieve_surrounding signal, or should the boolean return from
gtk_im_context_get_surrounding() be based only on whether
gtk_im_context_set_surrounding() was called during the emission?
Having the boolean return value (with a TRUE-stops-emit signal
collector) means that we get a first-handler-wins policy rather
than a last-handler-wins situation; multiple handlers for this
signal could be considered somewhat pathological.
- Right now a ::delete_surrounding handler is supposed to return TRUE
if it supports deletion of surrounding text, without regard to what
it deletes in this particular instance. An alternate possibility
would be that the handler should only delete text and return TRUE
if it can delete exactly what is specified as arguments to the
signal.
- Is it too strange to make the arguments to ::delete_surrounding a
character offset and character count rather then byte offset and
byte length, as elsewhere used in GtkIMContext? The reason why I
used characters rather than bytes was so that widgets/applications
didn't have to deal with the possibility of the specified deletion
not properly corresponding to character boundaries.
Regards,
Owen
? gmenu
? gmenu.tar
? docs/reference/gtk/tmpl/gtkaccessible.sgml
Index: gtk/gtkentry.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v
retrieving revision 1.162
diff -u -p -r1.162 gtkentry.c
--- gtk/gtkentry.c 2001/10/31 23:49:09 1.162
+++ gtk/gtkentry.c 2001/11/01 02:39:55
@@ -232,11 +232,18 @@ static void gtk_entry_keymap_direction_c
GtkEntry *entry);
/* IM Context Callbacks
*/
-static void gtk_entry_commit_cb (GtkIMContext *context,
- const gchar *str,
- GtkEntry *entry);
-static void gtk_entry_preedit_changed_cb (GtkIMContext *context,
- GtkEntry *entry);
+static void gtk_entry_commit_cb (GtkIMContext *context,
+ const gchar *str,
+ GtkEntry *entry);
+static void gtk_entry_preedit_changed_cb (GtkIMContext *context,
+ GtkEntry *entry);
+static gboolean gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
+ GtkEntry *entry);
+static gboolean gtk_entry_delete_surrounding_cb (GtkIMContext *context,
+ gint offset,
+ gint n_chars,
+ GtkEntry *entry);
+
/* Internal routines
*/
static void gtk_entry_set_positions (GtkEntry *entry,
@@ -919,6 +926,10 @@ gtk_entry_init (GtkEntry *entry)
G_CALLBACK (gtk_entry_commit_cb), entry);
g_signal_connect (G_OBJECT (entry->im_context), "preedit_changed",
G_CALLBACK (gtk_entry_preedit_changed_cb), entry);
+ g_signal_connect (G_OBJECT (entry->im_context), "retrieve_surrounding",
+ G_CALLBACK (gtk_entry_retrieve_surrounding_cb), entry);
+ g_signal_connect (G_OBJECT (entry->im_context), "delete_surrounding",
+ G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
}
static void
@@ -2270,6 +2281,31 @@ gtk_entry_preedit_changed_cb (GtkIMConte
g_free (preedit_string);
gtk_entry_recompute (entry);
+}
+
+static gboolean
+gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
+ GtkEntry *entry)
+{
+ gtk_im_context_set_surrounding (context,
+ entry->text,
+ entry->n_bytes,
+ g_utf8_offset_to_pointer (entry->text, entry->current_pos) - entry->text);
+
+ return TRUE;
+}
+
+static gboolean
+gtk_entry_delete_surrounding_cb (GtkIMContext *slave,
+ gint offset,
+ gint n_chars,
+ GtkEntry *entry)
+{
+ gtk_editable_delete_text (GTK_EDITABLE (entry),
+ entry->current_pos + offset,
+ entry->current_pos + offset + n_chars);
+
+ return TRUE;
}
/* Internal functions
Index: gtk/gtkimcontext.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimcontext.c,v
retrieving revision 1.17
diff -u -p -r1.17 gtkimcontext.c
--- gtk/gtkimcontext.c 2001/10/19 19:28:26 1.17
+++ gtk/gtkimcontext.c 2001/11/01 02:39:55
@@ -18,13 +18,17 @@
*/
#include "gtkimcontext.h"
+#include "gtkmain.h" /* For _gtk_boolean_handled_accumulator */
#include "gtksignal.h"
+#include "string.h"
enum {
PREEDIT_START,
PREEDIT_END,
PREEDIT_CHANGED,
COMMIT,
+ RETRIEVE_SURROUNDING,
+ DELETE_SURROUNDING,
LAST_SIGNAL
};
@@ -33,12 +37,19 @@ static guint im_context_signals[LAST_SIG
static void gtk_im_context_class_init (GtkIMContextClass *class);
static void gtk_im_context_init (GtkIMContext *im_context);
-static void gtk_im_context_real_get_preedit_string (GtkIMContext *context,
- gchar **str,
- PangoAttrList **attrs,
- gint *cursor_pos);
-static gboolean gtk_im_context_real_filter_keypress (GtkIMContext *context,
- GdkEventKey *event);
+static void gtk_im_context_real_get_preedit_string (GtkIMContext *context,
+ gchar **str,
+ PangoAttrList **attrs,
+ gint *cursor_pos);
+static gboolean gtk_im_context_real_filter_keypress (GtkIMContext *context,
+ GdkEventKey *event);
+static gboolean gtk_im_context_real_get_surrounding (GtkIMContext *context,
+ gchar **text,
+ gint *cursor_index);
+static void gtk_im_context_real_set_surrounding (GtkIMContext *context,
+ const char *text,
+ gint len,
+ gint cursor_index);
GtkType
gtk_im_context_get_type (void)
@@ -77,6 +88,8 @@ gtk_im_context_class_init (GtkIMContextC
klass->get_preedit_string = gtk_im_context_real_get_preedit_string;
klass->filter_keypress = gtk_im_context_real_filter_keypress;
+ klass->get_surrounding = gtk_im_context_real_get_surrounding;
+ klass->set_surrounding = gtk_im_context_real_set_surrounding;
im_context_signals[PREEDIT_START] =
gtk_signal_new ("preedit_start",
@@ -110,6 +123,25 @@ gtk_im_context_class_init (GtkIMContextC
gtk_marshal_VOID__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
+
+ im_context_signals[RETRIEVE_SURROUNDING] =
+ g_signal_new ("retrieve_surrounding",
+ GTK_CLASS_TYPE (object_class),
+ GTK_RUN_LAST,
+ GTK_SIGNAL_OFFSET (GtkIMContextClass, retrieve_surrounding),
+ _gtk_boolean_handled_accumulator, NULL,
+ gtk_marshal_BOOLEAN__VOID,
+ GTK_TYPE_BOOL, 0);
+ im_context_signals[DELETE_SURROUNDING] =
+ g_signal_new ("delete_surrounding",
+ GTK_CLASS_TYPE (object_class),
+ GTK_RUN_LAST,
+ GTK_SIGNAL_OFFSET (GtkIMContextClass, delete_surrounding),
+ _gtk_boolean_handled_accumulator, NULL,
+ gtk_marshal_BOOLEAN__INT_INT,
+ GTK_TYPE_BOOL, 2,
+ GTK_TYPE_INT,
+ GTK_TYPE_INT);
}
static void
@@ -138,6 +170,67 @@ gtk_im_context_real_filter_keypress (Gtk
return FALSE;
}
+typedef struct
+{
+ gchar *text;
+ gint cursor_index;
+} SurroundingInfo;
+
+static void
+gtk_im_context_real_set_surrounding (GtkIMContext *context,
+ const gchar *text,
+ gint len,
+ gint cursor_index)
+{
+ SurroundingInfo *info = g_object_get_data (G_OBJECT (context), "gtk-im-surrounding-info");
+
+ if (info)
+ {
+ g_free (info->text);
+ info->text = g_strndup (text, len);
+ info->cursor_index = cursor_index;
+ }
+}
+
+static gboolean
+gtk_im_context_real_get_surrounding (GtkIMContext *context,
+ gchar **text,
+ gint *cursor_index)
+{
+ gboolean result;
+ gboolean info_is_local = FALSE;
+ SurroundingInfo local_info = { NULL, 0 };
+ SurroundingInfo *info;
+
+ info = g_object_get_data (G_OBJECT (context), "gtk-im-surrounding-info");
+ if (!info)
+ {
+ info = &local_info;
+ g_object_set_data (G_OBJECT (context), "gtk-im-surrounding-info", info);
+ info_is_local = TRUE;
+ }
+
+ g_signal_emit (context,
+ im_context_signals[RETRIEVE_SURROUNDING], 0,
+ &result);
+
+ if (result)
+ {
+ *text = g_strdup (info->text ? info->text : "");
+ *cursor_index = info->cursor_index;
+ }
+ else
+ {
+ *text = NULL;
+ *cursor_index = 0;
+ }
+
+ if (info_is_local)
+ g_free (info->text);
+
+ return result;
+}
+
/**
* gtk_im_context_set_client_window:
* @context: a #GtkIMContext
@@ -324,3 +417,133 @@ gtk_im_context_set_use_preedit (GtkIMCon
if (klass->set_use_preedit)
klass->set_use_preedit (context, use_preedit);
}
+
+/**
+ * gtk_im_context_set_surrounding:
+ * @context: a #GtkIMContext
+ * @text: text surrounding the insertion point, as UTF-8.
+ * the preedit string should not be included within
+ * @text.
+ * @len: the length of @text, or -1 if @text is nul-terminated
+ * @cursor_index: the byte index of the insertion cursor within @text.
+ *
+ * Sets surrounding context around the insertion point and preedit
+ * string. This function is expected to be called in response to the
+ * GtkIMContext::retrieve_context signal, and will likely have no
+ * effect if called at other times.
+ **/
+void
+gtk_im_context_set_surrounding (GtkIMContext *context,
+ const gchar *text,
+ gint len,
+ gint cursor_index)
+{
+ GtkIMContextClass *klass;
+
+ g_return_if_fail (GTK_IS_IM_CONTEXT (context));
+ g_return_if_fail (text != NULL || len == 0);
+
+ if (text == NULL && len == 0)
+ text = "";
+ if (len < 0)
+ len = strlen (text);
+
+ g_return_if_fail (cursor_index >= 0 && cursor_index <= len);
+
+ klass = GTK_IM_CONTEXT_GET_CLASS (context);
+ if (klass->set_surrounding)
+ klass->set_surrounding (context, text, len, cursor_index);
+}
+
+/**
+ * gtk_im_context_get_surrounding:
+ * @context: a #GtkIMContext
+ * @text: location to store a UTF-8 encoded string of text
+ * holding context around the insertion point.
+ * If the function returns %TRUE, then you must free
+ * the result stored in this location with g_free().
+ * @cursor_index: location to store byte index of the insertion cursor
+ * within @text.
+ *
+ * Retrieves context around the insertion point. Input methods
+ * typically want context in order to constrain input text based on
+ * existing text; this is important for languages such as Thai where
+ * only some sequences of characters are allowed.
+ *
+ * This function is implemented by emitting the
+ * GtkIMContext::retrieve_context signal on the input method; in
+ * response to this signal, a widget should provide as much context as
+ * is available, up to an entire paragraph, by calling
+ * gtk_im_context_set_surrounding. Note that there is no obligation
+ * for a widget to respond to the ::retrieve_context signal, so input
+ * methods must be prepared to function without context.
+ *
+ * Return value: %TRUE if surrounding text was provided; in this case
+ * you must free the result stored in *text.
+ **/
+gboolean
+gtk_im_context_get_surrounding (GtkIMContext *context,
+ gchar **text,
+ gint *cursor_index)
+{
+ GtkIMContextClass *klass;
+ gchar *local_text = NULL;
+ gint local_index;
+ gboolean result = FALSE;
+
+ g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
+
+ klass = GTK_IM_CONTEXT_GET_CLASS (context);
+ if (klass->get_surrounding)
+ result = klass->get_surrounding (context,
+ text ? text : &local_text,
+ cursor_index ? cursor_index : &local_index);
+
+ if (result)
+ g_free (local_text);
+
+ return result;
+}
+
+/**
+ * gtk_im_context_delete_surrounding:
+ * @context: a #GtkIMContext
+ * @offset: offset from cursor position in chars;
+ * a negative value means start before the cursor.
+ * @n_chars: number of characters to delete.
+ *
+ * Asks the widget that the input context is attached to to delete
+ * characters around the cursor position by emitting the
+ * GtkIMContext::delete_context signal. Note that @offset and @n_chars
+ * are in characters not in bytes, which differs from the usage other
+ * places in #GtkIMContext.
+ *
+ * In order to use this function, you should first call
+ * gtk_im_context_get_surrounding() to get the current context, and
+ * call this function immediately afterwards to make sure that you
+ * know what you are deleting. You should also account for the fact
+ * that even if the signal was handled, the input context might not
+ * have deleted all the characters that were requested to be deleted.
+ *
+ * This function is used by an input method that wants to make
+ * subsitutions in the existing text in response to new input. It is
+ * not useful for applications.
+ *
+ * Return value: %TRUE if the signal was handled.
+ **/
+gboolean
+gtk_im_context_delete_surrounding (GtkIMContext *context,
+ gint offset,
+ gint n_chars)
+{
+ gboolean result;
+
+ g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
+
+ g_signal_emit (context,
+ im_context_signals[DELETE_SURROUNDING], 0,
+ offset, n_chars, &result);
+
+ return result;
+}
+
Index: gtk/gtkimcontext.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimcontext.h,v
retrieving revision 1.9
diff -u -p -r1.9 gtkimcontext.h
--- gtk/gtkimcontext.h 2001/10/28 14:17:49 1.9
+++ gtk/gtkimcontext.h 2001/11/01 02:39:55
@@ -50,10 +50,14 @@ struct _GtkIMContextClass
GtkObjectClass parent_class;
/* Signals */
- void (*preedit_start) (GtkIMContext *context);
- void (*preedit_end) (GtkIMContext *context);
- void (*preedit_changed) (GtkIMContext *context);
- void (*commit) (GtkIMContext *context, const gchar *str);
+ void (*preedit_start) (GtkIMContext *context);
+ void (*preedit_end) (GtkIMContext *context);
+ void (*preedit_changed) (GtkIMContext *context);
+ void (*commit) (GtkIMContext *context, const gchar *str);
+ gboolean (*retrieve_surrounding) (GtkIMContext *context);
+ gboolean (*delete_surrounding) (GtkIMContext *context,
+ gint offset,
+ gint n_chars);
/* Virtual functions */
void (*set_client_window) (GtkIMContext *context,
@@ -71,25 +75,43 @@ struct _GtkIMContextClass
GdkRectangle *area);
void (*set_use_preedit) (GtkIMContext *context,
gboolean use_preedit);
+ void (*set_surrounding) (GtkIMContext *context,
+ const gchar *text,
+ gint len,
+ gint cursor_index);
+ gboolean (*get_surrounding) (GtkIMContext *context,
+ gchar **text,
+ gint *cursor_index);
};
GtkType gtk_im_context_get_type (void) G_GNUC_CONST;
-void gtk_im_context_set_client_window (GtkIMContext *context,
- GdkWindow *window);
-void gtk_im_context_get_preedit_string (GtkIMContext *context,
- gchar **str,
- PangoAttrList **attrs,
- gint *cursor_pos);
-gboolean gtk_im_context_filter_keypress (GtkIMContext *context,
- GdkEventKey *event);
-void gtk_im_context_focus_in (GtkIMContext *context);
-void gtk_im_context_focus_out (GtkIMContext *context);
-void gtk_im_context_reset (GtkIMContext *context);
-void gtk_im_context_set_cursor_location (GtkIMContext *context,
- GdkRectangle *area);
-void gtk_im_context_set_use_preedit (GtkIMContext *context,
- gboolean use_preedit);
+void gtk_im_context_set_client_window (GtkIMContext *context,
+ GdkWindow *window);
+void gtk_im_context_get_preedit_string (GtkIMContext *context,
+ gchar **str,
+ PangoAttrList **attrs,
+ gint *cursor_pos);
+gboolean gtk_im_context_filter_keypress (GtkIMContext *context,
+ GdkEventKey *event);
+void gtk_im_context_focus_in (GtkIMContext *context);
+void gtk_im_context_focus_out (GtkIMContext *context);
+void gtk_im_context_reset (GtkIMContext *context);
+void gtk_im_context_set_cursor_location (GtkIMContext *context,
+ GdkRectangle *area);
+void gtk_im_context_set_use_preedit (GtkIMContext *context,
+ gboolean use_preedit);
+void gtk_im_context_set_surrounding (GtkIMContext *context,
+ const gchar *text,
+ gint len,
+ gint cursor_index);
+gboolean gtk_im_context_get_surrounding (GtkIMContext *context,
+ gchar **text,
+ gint *cursor_index);
+gboolean gtk_im_context_delete_surrounding (GtkIMContext *context,
+ gint offset,
+ gint n_chars);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Index: gtk/gtkimcontextsimple.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimcontextsimple.c,v
retrieving revision 1.18
diff -u -p -r1.18 gtkimcontextsimple.c
--- gtk/gtkimcontextsimple.c 2001/10/28 21:15:33 1.18
+++ gtk/gtkimcontextsimple.c 2001/11/01 02:39:55
@@ -854,6 +854,45 @@ gtk_im_context_simple_commit_char (GtkIM
}
g_signal_emit_by_name (context, "commit", &buf);
+
+ /* Check if the result left the cursor pointing within the word
+ * "owned", and if so, change to "owen".
+ */
+ {
+ gchar *surrounding;
+ gint pos;
+
+ if (gtk_im_context_get_surrounding (context, &surrounding, &pos))
+ {
+ const char *start = surrounding + pos;
+ const char *end;
+
+ while (start > surrounding)
+ {
+ const char *prev = g_utf8_prev_char (start);
+ if (!g_unichar_isalpha (g_utf8_get_char (prev)))
+ break;
+ start = prev;
+ }
+
+ end = start;
+
+ while (*end)
+ {
+ if (!g_unichar_isalpha (g_utf8_get_char (end)))
+ break;
+ end = g_utf8_next_char (end);
+ }
+
+ if (end - start == 3 && !g_ascii_strncasecmp (start, "own", 3))
+ {
+ if (gtk_im_context_delete_surrounding (context, start - (surrounding + pos), end - start))
+ g_signal_emit_by_name (context, "commit", "Owen");
+ }
+
+ g_free (surrounding);
+ }
+ }
}
static int
Index: gtk/gtkimmulticontext.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimmulticontext.c,v
retrieving revision 1.14
diff -u -p -r1.14 gtkimmulticontext.c
--- gtk/gtkimmulticontext.c 2001/10/28 21:15:33 1.14
+++ gtk/gtkimmulticontext.c 2001/11/01 02:39:55
@@ -45,17 +45,29 @@ static void gtk_im_multicontext_focu
static void gtk_im_multicontext_reset (GtkIMContext *context);
static void gtk_im_multicontext_set_cursor_location (GtkIMContext *context,
GdkRectangle *area);
-
-static void gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
- GtkIMMulticontext *multicontext);
-static void gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
- GtkIMMulticontext *multicontext);
-static void gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
- GtkIMMulticontext *multicontext);
-void gtk_im_multicontext_commit_cb (GtkIMContext *slave,
- const gchar *str,
- GtkIMMulticontext *multicontext);
-
+static gboolean gtk_im_multicontext_get_surrounding (GtkIMContext *context,
+ gchar **text,
+ gint *cursor_index);
+static void gtk_im_multicontext_set_surrounding (GtkIMContext *context,
+ const char *text,
+ gint len,
+ gint cursor_index);
+
+static void gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
+ GtkIMMulticontext *multicontext);
+static void gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
+ GtkIMMulticontext *multicontext);
+static void gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
+ GtkIMMulticontext *multicontext);
+static void gtk_im_multicontext_commit_cb (GtkIMContext *slave,
+ const gchar *str,
+ GtkIMMulticontext *multicontext);
+static gboolean gtk_im_multicontext_retrieve_surrounding_cb (GtkIMContext *slave,
+ GtkIMMulticontext *multicontext);
+static gboolean gtk_im_multicontext_delete_surrounding_cb (GtkIMContext *slave,
+ gint offset,
+ gint n_chars,
+ GtkIMMulticontext *multicontext);
static GtkIMContextClass *parent_class;
static const gchar *global_context_id = NULL;
@@ -103,6 +115,8 @@ gtk_im_multicontext_class_init (GtkIMMul
im_context_class->focus_out = gtk_im_multicontext_focus_out;
im_context_class->reset = gtk_im_multicontext_reset;
im_context_class->set_cursor_location = gtk_im_multicontext_set_cursor_location;
+ im_context_class->set_surrounding = gtk_im_multicontext_set_surrounding;
+ im_context_class->get_surrounding = gtk_im_multicontext_get_surrounding;
gobject_class->finalize = gtk_im_multicontext_finalize;
}
@@ -174,6 +188,12 @@ gtk_im_multicontext_set_slave (GtkIMMult
g_signal_connect (multicontext->slave, "commit",
G_CALLBACK (gtk_im_multicontext_commit_cb),
multicontext);
+ g_signal_connect (multicontext->slave, "retrieve_surrounding",
+ G_CALLBACK (gtk_im_multicontext_retrieve_surrounding_cb),
+ multicontext);
+ g_signal_connect (multicontext->slave, "delete_surrounding",
+ G_CALLBACK (gtk_im_multicontext_delete_surrounding_cb),
+ multicontext);
if (multicontext->client_window)
gtk_im_context_set_client_window (slave, multicontext->client_window);
@@ -301,7 +321,41 @@ gtk_im_multicontext_set_cursor_location
gtk_im_context_set_cursor_location (slave, area);
}
+static gboolean
+gtk_im_multicontext_get_surrounding (GtkIMContext *context,
+ gchar **text,
+ gint *cursor_index)
+{
+ GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
+ GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
+
+ if (slave)
+ return gtk_im_context_get_surrounding (context, text, cursor_index);
+ else
+ {
+ if (text)
+ *text = NULL;
+ if (cursor_index)
+ *cursor_index = 0;
+
+ return FALSE;
+ }
+}
+
static void
+gtk_im_multicontext_set_surrounding (GtkIMContext *context,
+ const char *text,
+ gint len,
+ gint cursor_index)
+{
+ GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
+ GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
+
+ if (slave)
+ gtk_im_context_set_surrounding (slave, text, len, cursor_index);
+}
+
+static void
gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext)
{
@@ -322,12 +376,37 @@ gtk_im_multicontext_preedit_changed_cb (
g_signal_emit_by_name (multicontext, "preedit_changed");
}
-void
+static void
gtk_im_multicontext_commit_cb (GtkIMContext *slave,
const gchar *str,
GtkIMMulticontext *multicontext)
{
g_signal_emit_by_name (multicontext, "commit", str);;
+}
+
+static gboolean
+gtk_im_multicontext_retrieve_surrounding_cb (GtkIMContext *slave,
+ GtkIMMulticontext *multicontext)
+{
+ gboolean result;
+
+ g_signal_emit_by_name (multicontext, "retrieve_surrounding", &result);
+
+ return result;
+}
+
+static gboolean
+gtk_im_multicontext_delete_surrounding_cb (GtkIMContext *slave,
+ gint offset,
+ gint n_chars,
+ GtkIMMulticontext *multicontext)
+{
+ gboolean result;
+
+ g_signal_emit_by_name (multicontext, "delete_surrounding",
+ offset, n_chars, &result);
+
+ return result;
}
static void
Index: gtk/gtkmarshal.list
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmarshal.list,v
retrieving revision 1.39
diff -u -p -r1.39 gtkmarshal.list
--- gtk/gtkmarshal.list 2001/09/25 16:44:38 1.39
+++ gtk/gtkmarshal.list 2001/11/01 02:39:55
@@ -27,6 +27,7 @@ BOOLEAN:ENUM
BOOLEAN:OBJECT,INT,INT,UINT
BOOLEAN:OBJECT,STRING,STRING,BOXED
BOOLEAN:OBJECT,BOXED,BOXED
+BOOLEAN:INT,INT
BOOLEAN:VOID
BOOLEAN:BOOLEAN
ENUM:ENUM
Index: gtk/gtktextview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextview.c,v
retrieving revision 1.138
diff -u -p -r1.138 gtktextview.c
--- gtk/gtktextview.c 2001/10/31 23:49:09 1.138
+++ gtk/gtktextview.c 2001/11/01 02:39:56
@@ -257,13 +257,19 @@ static void gtk_text_view_check_curs
static void gtk_text_view_pend_cursor_blink (GtkTextView *text_view);
static void gtk_text_view_stop_cursor_blink (GtkTextView *text_view);
-static void gtk_text_view_value_changed (GtkAdjustment *adj,
- GtkTextView *view);
-static void gtk_text_view_commit_handler (GtkIMContext *context,
- const gchar *str,
- GtkTextView *text_view);
-static void gtk_text_view_preedit_changed_handler (GtkIMContext *context,
- GtkTextView *text_view);
+static void gtk_text_view_value_changed (GtkAdjustment *adj,
+ GtkTextView *view);
+static void gtk_text_view_commit_handler (GtkIMContext *context,
+ const gchar *str,
+ GtkTextView *text_view);
+static void gtk_text_view_preedit_changed_handler (GtkIMContext *context,
+ GtkTextView *text_view);
+static gboolean gtk_text_view_retrieve_surrounding_handler (GtkIMContext *context,
+ GtkTextView *text_view);
+static gboolean gtk_text_view_delete_surrounding_handler (GtkIMContext *context,
+ gint offset,
+ gint n_chars,
+ GtkTextView *text_view);
static void gtk_text_view_mark_set_handler (GtkTextBuffer *buffer,
const GtkTextIter *location,
@@ -956,9 +962,12 @@ gtk_text_view_init (GtkTextView *text_vi
g_signal_connect (G_OBJECT (text_view->im_context), "commit",
G_CALLBACK (gtk_text_view_commit_handler), text_view);
-
g_signal_connect (G_OBJECT (text_view->im_context), "preedit_changed",
G_CALLBACK (gtk_text_view_preedit_changed_handler), text_view);
+ g_signal_connect (G_OBJECT (text_view->im_context), "retrieve_surrounding",
+ G_CALLBACK (gtk_text_view_retrieve_surrounding_handler), text_view);
+ g_signal_connect (G_OBJECT (text_view->im_context), "delete_surrounding",
+ G_CALLBACK (gtk_text_view_delete_surrounding_handler), text_view);
text_view->cursor_visible = TRUE;
@@ -5307,6 +5316,51 @@ gtk_text_view_preedit_changed_handler (G
pango_attr_list_unref (attrs);
g_free (str);
+}
+
+static gboolean
+gtk_text_view_retrieve_surrounding_handler (GtkIMContext *context,
+ GtkTextView *text_view)
+{
+ GtkTextIter start;
+ GtkTextIter end;
+ gint pos;
+ gchar *text;
+
+ gtk_text_buffer_get_iter_at_mark (text_view->buffer, &start,
+ gtk_text_buffer_get_insert (text_view->buffer));
+ end = start;
+
+ pos = gtk_text_iter_get_line_index (&start);
+ gtk_text_iter_set_line_offset (&start, 0);
+ gtk_text_iter_forward_to_line_end (&end);
+
+ text = gtk_text_iter_get_slice (&start, &end);
+ gtk_im_context_set_surrounding (context, text, -1, pos);
+ g_free (text);
+
+ return TRUE;
+}
+
+static gboolean
+gtk_text_view_delete_surrounding_handler (GtkIMContext *context,
+ gint offset,
+ gint n_chars,
+ GtkTextView *text_view)
+{
+ GtkTextIter start;
+ GtkTextIter end;
+
+ gtk_text_buffer_get_iter_at_mark (text_view->buffer, &start,
+ gtk_text_buffer_get_insert (text_view->buffer));
+ end = start;
+
+ gtk_text_iter_forward_chars (&start, offset);
+ gtk_text_iter_forward_chars (&end, offset + n_chars);
+
+ gtk_text_buffer_delete (text_view->buffer, &start, &end);
+
+ return TRUE;
}
static void
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]