aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorSuresh Chandrasekharan <suresh.chandrasekharan@sun.com>2003-10-15 02:20:18 +0800
committerSuresh Chandrasekharan <kcsuresh@src.gnome.org>2003-10-15 02:20:18 +0800
commit0517e6655c44fde264965dc7221f597471846cef (patch)
treec825bb39da5ad0ea86a782a80386a4f6d9d93fb8 /widgets
parenta267d0a153a33621c6d51710d370ab2b90278b2b (diff)
downloadgsoc2013-evolution-0517e6655c44fde264965dc7221f597471846cef.tar
gsoc2013-evolution-0517e6655c44fde264965dc7221f597471846cef.tar.gz
gsoc2013-evolution-0517e6655c44fde264965dc7221f597471846cef.tar.bz2
gsoc2013-evolution-0517e6655c44fde264965dc7221f597471846cef.tar.lz
gsoc2013-evolution-0517e6655c44fde264965dc7221f597471846cef.tar.xz
gsoc2013-evolution-0517e6655c44fde264965dc7221f597471846cef.tar.zst
gsoc2013-evolution-0517e6655c44fde264965dc7221f597471846cef.zip
Support for preedit in e-text widgets.
2003-10-14 Suresh Chandrasekharan <suresh.chandrasekharan@sun.com> * Support for preedit in e-text widgets. * gal/gal/e-text/e-text.c: Added e_text_preedit_changed_cb and insert_preedit_text. * Modified the following functions. (e_text_draw) Calls insert_preedit_text also cursor pos @ the end of text->selection_start + text->preedit_len (e_text_event) Added hooks for preedit_cb (e_text_init) Inits text->preedit_len (e_text_retrieve_surrounding_cb) Removed printf (e_text_delete_surrounding_cb) Correct params for gtk_editable_delete_text to make it work. * gal/gal/e-text/e-text.h: Added preedit_len in struct _EText 2003-09-25 Suresh Chandrasekharan <suresh.chandrasekharan@sun.com> * Fix for "44222 task summary entry widget not i18ned". The following files are changed. * gal/gal/e-table/e-cell-text.c: Lots of changes for i18n selection/input support. Added these functions for input method support. (e_cell_text_preedit_changed_cb) (e_cell_text_commit_cb) (e_cell_text_retrieve_surrounding_cb) (e_cell_text_delete_surrounding_cb) (layout_with_preedit) This function inserts the preedit string with the right attribs to the layout text. (build_attr_list) Creates the PangoAttrList with bold/stikeout/underline as applicable for the current ECellText. The following functions are modified. (ect_stop_editing): disconnect signal handlers when editing stops (ect_draw): Changes for including the preedit only to the currently selected row/col. Also display the cursor at the end of preedit text. (ect_event): Connects the IM callbacks to the key press event. Disconnect when not in editing mode. Also a special flag to see when Enter key pressed in preedit mode, the text is committed only not a new row is created. This woks in conjunction with the changes made in the eti_event in e-table-item.c file and e-cell.h. (ect_height): Changes due to parameters changing for generate_layout (ect_enter_edit): Initialization of im_context for a cell text and assoociated flags. (ect_max_width): Changes due to parameters changing for generate_layout. (ect_max_width_by_row): Changes due to parameters changing for generate_layout. (ect_show_tooltip): Changes due to parameters changing for generate_layout. (e_cell_text_construct): check whether paramters are NULL. (get_position_from_xy): Changes due to parameters changing for generate_layout. (_insert): Set the selection_start as the minimum of strlen(edit->text) and selection_start. Used to correct the preedit_string length which may have added to the selection_start. (e_cell_text_view_command): When inserting, if in the preedit mode do not delete the selection. (_selection_get): Set utf8 data instead of string data. (_selection_received): Take in UTF8_ATOM inaddition to GDK_SELECTION_TYPE_STRING. (e_cell_text_view_get_selection): Make utf8 data when acting as a selection source. * gal/e-table/e-cell-text.h : Included <gtk/gtkmenu.h> * gal/e-table/e-cell.h: Added enum E_CELL_PREEDIT to ECellFlags * gal/e-table/e-table-item.c: (eti_event) Changes for not committing the edited text as a seperate row in preedit mode. * gal/e-table/e-table.c: (table_canvas_focus_event_cb) To have proper im_context focus for the ecanvas holding the e-table. svn path=/trunk/; revision=22882
Diffstat (limited to 'widgets')
-rw-r--r--widgets/table/e-cell-text.c314
-rw-r--r--widgets/table/e-cell-text.h2
-rw-r--r--widgets/table/e-cell.h4
-rw-r--r--widgets/table/e-table-item.c13
-rw-r--r--widgets/table/e-table.c10
-rw-r--r--widgets/text/e-text.c92
-rw-r--r--widgets/text/e-text.h1
7 files changed, 376 insertions, 60 deletions
diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c
index 9151fcc26e..a4a8aa8085 100644
--- a/widgets/table/e-cell-text.c
+++ b/widgets/table/e-cell-text.c
@@ -96,6 +96,8 @@ static GdkAtom clipboard_atom = GDK_NONE;
#define PARENT_TYPE e_cell_get_type ()
+#define UTF8_ATOM gdk_atom_intern ("UTF8_STRING", FALSE)
+
#define TEXT_PAD 4
typedef struct {
@@ -177,6 +179,11 @@ struct _CellEdit {
guint pointer_in : 1;
guint default_cursor_shown : 1;
+ GtkIMContext *im_context;
+ gboolean need_im_reset;
+ gboolean im_context_signals_registered;
+
+ guint16 preedit_length; /* length of preedit string, in bytes */
ECellActions actions;
};
@@ -193,6 +200,13 @@ static gboolean _blink_scroll_timeout (gpointer data);
static void ect_free_color (gchar *color_spec, GdkColor *color, GdkColormap *colormap);
static GdkColor* e_cell_text_get_color (ECellTextView *cell_view, gchar *color_spec);
+static void e_cell_text_preedit_changed_cb (GtkIMContext *context, ECellTextView *text_view);
+static void e_cell_text_commit_cb (GtkIMContext *context, const gchar *str, ECellTextView *text_view);
+static gboolean e_cell_text_retrieve_surrounding_cb (GtkIMContext *context, ECellTextView *text_view);
+static gboolean e_cell_text_delete_surrounding_cb (GtkIMContext *context, gint offset, gint n_chars, ECellTextView *text_view);
+static void _insert (ECellTextView *text_view, char *string, int value);
+static void _delete_selection (ECellTextView *text_view);
+static PangoAttrList* build_attr_list (ECellTextView *text_view, int row, int text_length);
static ECellClass *parent_class;
@@ -290,6 +304,11 @@ ect_stop_editing (ECellTextView *text_view, gboolean commit)
g_timer_destroy (edit->timer);
edit->timer = NULL;
}
+
+ g_signal_handlers_disconnect_matched (
+ edit->im_context,
+ G_SIGNAL_MATCH_DATA, 0, 0,
+ NULL, NULL, text_view);
if (edit->layout)
g_object_unref (edit->layout);
@@ -424,16 +443,16 @@ ect_free_color (gchar *color_spec, GdkColor *color, GdkColormap *colormap)
}
}
-static PangoLayout *
-build_layout (ECellTextView *text_view, int row, const char *text, gint width)
+
+static PangoAttrList*
+build_attr_list (ECellTextView *text_view, int row, int text_length)
{
+
ECellView *ecell_view = (ECellView *) text_view;
ECellText *ect = E_CELL_TEXT (ecell_view->ecell);
- PangoLayout *layout;
+ PangoAttrList *attrs = pango_attr_list_new ();
gboolean bold, strikeout, underline;
- layout = gtk_widget_create_pango_layout (GTK_WIDGET (((GnomeCanvasItem *)ecell_view->e_table_item_view)->canvas), text);
-
bold = ect->bold_column >= 0 &&
row >= 0 &&
e_table_model_value_at(ecell_view->e_table_model, ect->bold_column, row);
@@ -445,33 +464,107 @@ build_layout (ECellTextView *text_view, int row, const char *text, gint width)
e_table_model_value_at(ecell_view->e_table_model, ect->underline_column, row);
if (bold || strikeout || underline) {
- PangoAttrList *attrs;
- int length = strlen (text);
- attrs = pango_attr_list_new ();
if (bold) {
PangoAttribute *attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
attr->start_index = 0;
- attr->end_index = length;
+ attr->end_index = text_length;
pango_attr_list_insert_before (attrs, attr);
}
if (strikeout) {
PangoAttribute *attr = pango_attr_strikethrough_new (TRUE);
attr->start_index = 0;
- attr->end_index = length;
+ attr->end_index = text_length;
pango_attr_list_insert_before (attrs, attr);
}
if (underline) {
PangoAttribute *attr = pango_attr_underline_new (TRUE);
attr->start_index = 0;
- attr->end_index = length;
+ attr->end_index = text_length;
pango_attr_list_insert_before (attrs, attr);
}
- pango_layout_set_attributes (layout, attrs);
- pango_attr_list_unref (attrs);
}
+ return attrs;
+}
+
+static PangoLayout *
+layout_with_preedit (ECellTextView *text_view, int row, const char *text, gint width)
+{
+ ECellView *ecell_view = (ECellView *) text_view;
+ ECellText *ect = E_CELL_TEXT (ecell_view->ecell);
+ CellEdit *edit = text_view->edit;
+ PangoAttrList *attrs ;
+ PangoLayout *layout;
+ GString *tmp_string = g_string_new (NULL);
+ PangoAttrList *preedit_attrs = NULL;
+ gchar *preedit_string = NULL;
+ gint preedit_length = 0;
+ gint text_length = strlen (text);
+ gint mlen = MIN(edit->selection_start,text_length);
+
+
+ gtk_im_context_get_preedit_string (edit->im_context,
+ &preedit_string,&preedit_attrs,
+ NULL);
+ preedit_length = edit->preedit_length = strlen (preedit_string);;
+
+ layout = edit->layout;
+
+ g_string_prepend_len (tmp_string, text,text_length);
+
+ if (preedit_length) {
+
+ /* mlen is the text_length in bytes, not chars
+ * check whether we are not inserting into
+ * the middle of a utf8 character
+ */
+
+ if (mlen < text_length) {
+ if (!g_utf8_validate (text+mlen, -1, NULL)) {
+ gchar *tc;
+ tc = g_utf8_find_next_char (text+mlen,NULL);
+ if (tc) {
+ mlen = (gint) (tc - text);
+ }
+ }
+ }
+
+ g_string_insert (tmp_string, mlen, preedit_string);
+ }
+
+ pango_layout_set_text (layout, tmp_string->str, tmp_string->len);
+
+ attrs = (PangoAttrList *) build_attr_list (text_view, row, text_length);
+
+ if (preedit_length)
+ pango_attr_list_splice (attrs, preedit_attrs, mlen, preedit_length);
+ pango_layout_set_attributes (layout, attrs);
+ g_string_free (tmp_string, TRUE);
+ if (preedit_string)
+ g_free (preedit_string);
+ if (preedit_attrs)
+ pango_attr_list_unref (preedit_attrs);
+ pango_attr_list_unref (attrs);
+ return layout;
+}
+
+static PangoLayout *
+build_layout (ECellTextView *text_view, int row, const char *text, gint width)
+{
+ ECellView *ecell_view = (ECellView *) text_view;
+ ECellText *ect = E_CELL_TEXT (ecell_view->ecell);
+ PangoAttrList *attrs ;
+ PangoLayout *layout;
+ gboolean bold, strikeout, underline;
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (((GnomeCanvasItem *)ecell_view->e_table_item_view)->canvas), text);
+
+ attrs = (PangoAttrList *) build_attr_list (text_view, row, text ? strlen (text) : 0);
+
+ pango_layout_set_attributes (layout, attrs);
+ pango_attr_list_unref (attrs);
if (text_view->edit || width <= 0)
return layout;
@@ -533,6 +626,7 @@ generate_layout (ECellTextView *text_view, int model_col, int view_col, int row,
return layout;
}
+
static void
draw_pango_rectangle (GdkDrawable *drawable, GdkGC *gc, int x1, int y1, PangoRectangle rect)
{
@@ -648,6 +742,10 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
layout = generate_layout (text_view, model_col, view_col, row, x2 - x1);
+ if (edit && edit->view_col == view_col && edit->row == row) {
+ layout = layout_with_preedit (text_view, row, edit->text ? edit->text : "?", x2 - x1);
+ }
+
gdk_draw_layout (drawable, text_view->gc,
x_origin, y_origin,
layout);
@@ -713,7 +811,8 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
} else {
if (edit->show_cursor) {
PangoRectangle strong_pos, weak_pos;
- pango_layout_get_cursor_pos (layout, edit->selection_start, &strong_pos, &weak_pos);
+ pango_layout_get_cursor_pos (layout, edit->selection_start + edit->preedit_length, &strong_pos, &weak_pos);
+
draw_pango_rectangle (drawable, text_view->gc, x_origin, y_origin, strong_pos);
if (strong_pos.x != weak_pos.x ||
strong_pos.y != weak_pos.y ||
@@ -749,6 +848,7 @@ ect_get_bg_color(ECellView *ecell_view, int row)
/*
* Selects the entire string
*/
+
static void
ect_edit_select_all (ECellTextView *text_view)
{
@@ -774,8 +874,10 @@ static gint
ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row, ECellFlags flags, ECellActions *actions)
{
ECellTextView *text_view = (ECellTextView *) ecell_view;
+ ECellText *ect = (ECellText *) ((ECellView *)text_view)->ecell;
ETextEventProcessorEvent e_tep_event;
gboolean edit_display = FALSE;
+ gint preedit_len;
CellEdit *edit = text_view->edit;
GtkWidget *canvas = GTK_WIDGET (text_view->canvas);
gint return_val = 0;
@@ -793,7 +895,70 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col,
case GDK_FOCUS_CHANGE:
break;
case GDK_KEY_PRESS: /* Fall Through */
+ if (edit_display) {
+ if (edit->im_context &&
+ !edit->im_context_signals_registered) {
+
+ g_signal_connect (edit->im_context,
+ "preedit_changed",
+ G_CALLBACK (\
+ e_cell_text_preedit_changed_cb),
+ text_view);
+
+ g_signal_connect (edit->im_context,
+ "commit",
+ G_CALLBACK (\
+ e_cell_text_commit_cb),
+ text_view);
+
+ g_signal_connect (edit->im_context,
+ "retrieve_surrounding",
+ G_CALLBACK (\
+ e_cell_text_retrieve_surrounding_cb),
+ text_view);
+
+ g_signal_connect (edit->im_context,
+ "delete_surrounding",
+ G_CALLBACK (\
+ e_cell_text_delete_surrounding_cb),
+ text_view);
+
+ edit->im_context_signals_registered = TRUE;
+ }
+
+ edit->show_cursor = FALSE;
+
+ } else {
+ if (edit->im_context) {
+ g_signal_handlers_disconnect_matched (
+ edit->im_context,
+ G_SIGNAL_MATCH_DATA, 0, 0,
+ NULL, NULL, edit);
+ edit->im_context_signals_registered = FALSE;
+ }
+
+ ect_stop_editing (text_view, TRUE);
+ if (edit->timeout_id) {
+ g_source_remove(edit->timeout_id);
+ edit->timeout_id = 0;
+ }
+ }
+ return_val = TRUE;
+ /* Fallthrough */
case GDK_KEY_RELEASE:
+ preedit_len = edit->preedit_length;
+ if (edit_display && edit->im_context &&
+ gtk_im_context_filter_keypress (\
+ edit->im_context,
+ (GdkEventKey*)event)) {
+
+ edit->need_im_reset = TRUE;
+ if (preedit_len && flags & E_CELL_PREEDIT)
+ return FALSE;
+ else
+ return TRUE;
+ }
+
if (event->key.keyval == GDK_Escape){
ect_cancel_edit (text_view);
return_val = TRUE;
@@ -829,12 +994,10 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col,
e_tep_event.key.length = 0;
}
#endif
-
_get_tep (edit);
- edit->actions = 0;
return_val = e_text_event_processor_handle_event (edit->tep, &e_tep_event);
- *actions = edit->actions;
- if (e_tep_event.key.string) g_free (e_tep_event.key.string);
+ if (e_tep_event.key.string)
+ g_free (e_tep_event.key.string);
break;
}
}
@@ -944,15 +1107,7 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col,
break;
}
- if (return_val)
- return return_val;
-#if 0
- if (GNOME_CANVAS_ITEM_CLASS(parent_class)->event)
- return GNOME_CANVAS_ITEM_CLASS(parent_class)->event (item, event);
-#endif
- else
- return 0;
-
+ return return_val;
}
/*
@@ -985,6 +1140,9 @@ ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row)
edit = g_new0 (CellEdit, 1);
text_view->edit = edit;
+ edit->im_context = E_CANVAS (text_view->canvas)->im_context;
+ edit->need_im_reset = FALSE;
+ edit->im_context_signals_registered = FALSE;
edit->view_col = -1;
edit->model_col = -1;
edit->row = -1;
@@ -1045,7 +1203,6 @@ ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row)
}
}
#endif
-
ect_queue_redraw (text_view, view_col, row);
return NULL;
@@ -1566,6 +1723,77 @@ e_cell_text_class_init (GObjectClass *object_class)
}
}
+
+/* IM Context Callbacks */
+
+static void
+e_cell_text_preedit_changed_cb (GtkIMContext *context,
+ ECellTextView *tv)
+{
+ gchar *preedit_string;
+ gint cursor_pos;
+ CellEdit *edit=tv->edit;
+ gtk_im_context_get_preedit_string (edit->im_context, &preedit_string,
+ NULL, &cursor_pos);
+
+ edit->preedit_length = strlen (preedit_string);
+ cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1));
+ g_free (preedit_string);
+ ect_queue_redraw (tv, edit->view_col, edit->row);
+}
+
+static void
+e_cell_text_commit_cb (GtkIMContext *context,
+ const gchar *str,
+ ECellTextView *tv)
+{
+ CellEdit *edit = tv->edit;
+ ECellText *ect = (ECellText *) ((ECellView *)tv)->ecell;
+ ETextEventProcessorCommand command;
+
+ if (g_utf8_validate (str, strlen (str), NULL)) {
+ command.action = E_TEP_INSERT;
+ command.position = E_TEP_SELECTION;
+ command.string = (gchar *)str;
+ command.value = strlen(str);
+ e_cell_text_view_command (edit->tep, &command, edit);
+ }
+
+}
+
+static gboolean
+e_cell_text_retrieve_surrounding_cb (GtkIMContext *context,
+ ECellTextView *tv)
+{
+ int cur_pos = 0;
+ CellEdit *edit = tv->edit;
+
+ cur_pos = g_utf8_pointer_to_offset (edit->text, edit->text + edit->selection_start);
+
+ gtk_im_context_set_surrounding (context,
+ edit->text,
+ strlen (edit->text),
+ cur_pos
+ );
+
+ return TRUE;
+}
+
+static gboolean
+e_cell_text_delete_surrounding_cb (GtkIMContext *context,
+ gint offset,
+ gint n_chars,
+ ECellTextView *tv)
+{
+ CellEdit *edit = tv->edit;
+
+ gtk_editable_delete_text (GTK_EDITABLE (edit),
+ edit->selection_end + offset,
+ edit->selection_end + offset + n_chars);
+
+ return TRUE;
+}
+
static void
e_cell_text_init (ECellText *ect)
{
@@ -1595,7 +1823,10 @@ E_MAKE_TYPE(e_cell_text, "ECellText", ECellText, e_cell_text_class_init, e_cell_
ECell *
e_cell_text_construct (ECellText *cell, const char *fontname, GtkJustification justify)
{
- cell->font_name = g_strdup (fontname);
+ if(!cell)
+ return E_CELL(NULL);
+ if(fontname)
+ cell->font_name = g_strdup (fontname);
cell->justify = justify;
return E_CELL(cell);
}
@@ -1645,6 +1876,7 @@ get_position_from_xy (CellEdit *edit, gint x, gint y)
int index;
int trailing;
const char *text;
+
PangoLayout *layout = generate_layout (edit->text_view, edit->model_col, edit->view_col, edit->row, edit->cell_width);
ECellTextView *text_view = edit->text_view;
ECellText *ect = (ECellText *) ((ECellView *)text_view)->ecell;
@@ -1932,6 +2164,8 @@ _insert (ECellTextView *text_view, char *string, int value)
if (value <= 0) return;
+ edit->selection_start = MIN (strlen(edit->text), edit->selection_start);
+
temp = g_new (gchar, strlen (edit->text) + value + 1);
strncpy (temp, edit->text, edit->selection_start);
@@ -2052,7 +2286,7 @@ e_cell_text_view_command (ETextEventProcessor *tep, ETextEventProcessorCommand *
break;
case E_TEP_INSERT:
- if (edit->selection_end != edit->selection_start) {
+ if (!edit->preedit_length && edit->selection_end != edit->selection_start) {
_delete_selection (text_view);
}
_insert (text_view, command->string, command->value);
@@ -2173,12 +2407,14 @@ _selection_get (GtkInvisible *invisible,
{
switch (info) {
case E_SELECTION_PRIMARY:
- gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
- 8, edit->primary_selection, edit->primary_length);
+ gtk_selection_data_set (selection_data, UTF8_ATOM,
+ 8, edit->primary_selection,
+ edit->primary_length);
break;
case E_SELECTION_CLIPBOARD:
- gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
- 8, edit->clipboard_selection, edit->clipboard_length);
+ gtk_selection_data_set (selection_data, UTF8_ATOM,
+ 8, edit->clipboard_selection,
+ edit->clipboard_length);
break;
}
}
@@ -2191,7 +2427,9 @@ _selection_received (GtkInvisible *invisible,
guint time,
CellEdit *edit)
{
- if (selection_data->length < 0 || selection_data->type != GDK_SELECTION_TYPE_STRING) {
+ if (selection_data->length < 0 ||
+ !(selection_data->type == UTF8_ATOM ||
+ selection_data->type == GDK_SELECTION_TYPE_STRING)) {
return;
} else {
ETextEventProcessorCommand command;
@@ -2212,11 +2450,11 @@ static GtkWidget *e_cell_text_view_get_invisible (CellEdit *edit)
gtk_selection_add_target (invisible,
GDK_SELECTION_PRIMARY,
- GDK_SELECTION_TYPE_STRING,
+ UTF8_ATOM,
E_SELECTION_PRIMARY);
gtk_selection_add_target (invisible,
clipboard_atom,
- GDK_SELECTION_TYPE_STRING,
+ UTF8_ATOM,
E_SELECTION_CLIPBOARD);
g_signal_connect (invisible, "selection_get",
@@ -2273,7 +2511,7 @@ e_cell_text_view_get_selection (CellEdit *edit, GdkAtom selection, guint32 time)
invisible = e_cell_text_view_get_invisible (edit);
gtk_selection_convert (invisible,
selection,
- GDK_SELECTION_TYPE_STRING,
+ UTF8_ATOM,
time);
#endif
}
diff --git a/widgets/table/e-cell-text.h b/widgets/table/e-cell-text.h
index 466fc54f1a..6c51f32fd8 100644
--- a/widgets/table/e-cell-text.h
+++ b/widgets/table/e-cell-text.h
@@ -36,7 +36,7 @@
#ifndef _E_CELL_TEXT_H_
#define _E_CELL_TEXT_H_
-
+#include <gtk/gtkmenu.h>
#include <libgnomecanvas/gnome-canvas.h>
#include <gal/e-table/e-cell.h>
diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h
index b6c4e01e71..2ba74c01f5 100644
--- a/widgets/table/e-cell.h
+++ b/widgets/table/e-cell.h
@@ -59,7 +59,9 @@ typedef enum {
E_CELL_EDITING = 1 << 4,
- E_CELL_CURSOR = 1 << 5
+ E_CELL_CURSOR = 1 << 5,
+
+ E_CELL_PREEDIT = 1 << 6
} ECellFlags;
typedef enum {
diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c
index 1015920e57..4acff10b2c 100644
--- a/widgets/table/e-table-item.c
+++ b/widgets/table/e-table-item.c
@@ -2703,18 +2703,17 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
case GDK_ISO_Enter:
case GDK_3270_Enter:
if (eti_editing (eti)){
- e_table_item_leave_edit_(eti);
-#if 0
ecell_view = eti->cell_views [eti->editing_col];
return_val = eti_e_cell_event (eti, ecell_view, e, e->key.time,
- view_to_model_col(eti, eti->editing_col),
- eti->editing_col, eti->editing_row, E_CELL_EDITING | E_CELL_CURSOR);
-#endif
+ view_to_model_col (eti, eti->editing_col),
+ eti->editing_col, eti->editing_row, E_CELL_EDITING | E_CELL_CURSOR | E_CELL_PREEDIT);
+ if (!return_val)
+ break;
}
g_signal_emit (eti, eti_signals [KEY_PRESS], 0,
- model_to_view_row(eti, cursor_row), cursor_col, e, &return_val);
+ model_to_view_row (eti, cursor_row), cursor_col, e, &return_val);
if (!return_val)
- return_val = e_selection_model_key_press(E_SELECTION_MODEL (eti->selection), (GdkEventKey *) e);
+ return_val = e_selection_model_key_press (E_SELECTION_MODEL (eti->selection), (GdkEventKey *) e);
break;
default:
diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c
index 6d0c4ee112..ffad7b3071 100644
--- a/widgets/table/e-table.c
+++ b/widgets/table/e-table.c
@@ -1102,14 +1102,20 @@ static gint
table_canvas_focus_event_cb (GtkWidget *widget, GdkEventFocus *event, gpointer data)
{
GnomeCanvas *canvas;
+ ECanvas *ecanvas;
ETable *etable;
gtk_widget_queue_draw (widget);
+ canvas = GNOME_CANVAS (widget);
+ ecanvas = E_CANVAS (widget);
- if (!event->in)
+ if (!event->in) {
+ gtk_im_context_focus_out(ecanvas->im_context);
return TRUE;
+ } else {
+ gtk_im_context_focus_in(ecanvas->im_context);
+ }
- canvas = GNOME_CANVAS (widget);
etable = E_TABLE (data);
if (!canvas->focused_item && etable->group)
diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c
index bda5f46eac..d68198507c 100644
--- a/widgets/text/e-text.c
+++ b/widgets/text/e-text.c
@@ -142,6 +142,8 @@ static void e_text_update_primary_selection (EText *text);
static void e_text_paste (EText *text, GdkAtom selection);
static void e_text_insert(EText *text, const char *string);
+static void reset_layout_attrs (EText *text);
+
/* GtkEditable Methods */
static void e_text_editable_do_insert_text (GtkEditable *editable,
const gchar *text,
@@ -167,6 +169,8 @@ static gint e_text_editable_get_position (GtkEditable *editable);
static void e_text_commit_cb (GtkIMContext *context,
const gchar *str,
EText *text);
+static void e_text_preedit_changed_cb (GtkIMContext *context,
+ EText *text);
static gboolean e_text_retrieve_surrounding_cb (GtkIMContext *context,
EText *text);
static gboolean e_text_delete_surrounding_cb (GtkIMContext *context,
@@ -282,6 +286,56 @@ e_text_dispose (GObject *object)
}
static void
+insert_preedit_text (EText *text)
+{
+ PangoAttrList *attrs = NULL;
+ PangoAttrList *preedit_attrs = NULL;
+ gchar *preedit_string = NULL;
+ GString *tmp_string = g_string_new (NULL);
+ gint length = 0, cpos = 0, preedit_length = 0;
+
+ if (text->layout == NULL || !GTK_IS_IM_CONTEXT (text->im_context))
+ return;
+
+ text->text = e_text_model_get_text(text->model);
+ length = strlen (text->text);
+
+ g_string_prepend_len (tmp_string, text->text,length);
+
+ attrs = pango_attr_list_new ();
+
+ gtk_im_context_get_preedit_string (text->im_context,
+ &preedit_string, &preedit_attrs,
+ NULL);
+
+ if (preedit_string && g_utf8_validate (preedit_string, -1, NULL))
+ text->preedit_len = preedit_length = strlen (preedit_string);
+ else
+ text->preedit_len = preedit_length = 0;
+
+ cpos = g_utf8_offset_to_pointer (text->text, text->selection_start) - text->text;
+
+ if (preedit_length)
+ g_string_insert (tmp_string, cpos, preedit_string);
+
+ reset_layout_attrs (text);
+
+ pango_layout_set_text (text->layout, tmp_string->str, tmp_string->len);
+ if (preedit_length)
+ pango_attr_list_splice (attrs, preedit_attrs, cpos, preedit_length);
+ pango_layout_set_attributes (text->layout, attrs);
+
+ if (preedit_string)
+ g_free (preedit_string);
+ if (preedit_attrs)
+ pango_attr_list_unref (preedit_attrs);
+ if (tmp_string)
+ g_string_free (tmp_string, TRUE);
+ if (attrs)
+ pango_attr_list_unref (attrs);
+}
+
+static void
reset_layout_attrs (EText *text)
{
PangoAttrList *attrs = NULL;
@@ -1436,7 +1490,10 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
}
}
- if (!text->text)
+
+ insert_preedit_text (text);
+
+ if (!pango_layout_get_text (text->layout))
return;
if (text->stipple)
@@ -1558,7 +1615,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
PangoRectangle strong_pos, weak_pos;
char *offs = g_utf8_offset_to_pointer (text->text, text->selection_start);
- pango_layout_get_cursor_pos (text->layout, offs - text->text, &strong_pos, &weak_pos);
+ pango_layout_get_cursor_pos (text->layout, offs - text->text + text->preedit_len, &strong_pos, &weak_pos);
draw_pango_rectangle (drawable, main_gc, xpos, ypos, strong_pos);
if (strong_pos.x != weak_pos.x ||
strong_pos.y != weak_pos.y ||
@@ -2116,6 +2173,8 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event)
if (!text->im_context_signals_registered) {
g_signal_connect (text->im_context, "commit",
G_CALLBACK (e_text_commit_cb), text);
+ g_signal_connect (text->im_context, "preedit_changed",
+ G_CALLBACK (e_text_preedit_changed_cb), text);
g_signal_connect (text->im_context, "retrieve_surrounding",
G_CALLBACK (e_text_retrieve_surrounding_cb), text);
g_signal_connect (text->im_context, "delete_surrounding",
@@ -3610,6 +3669,7 @@ e_text_init (EText *text)
{
text->model = e_text_model_new ();
text->text = e_text_model_get_text (text->model);
+ text->preedit_len = 0;
text->layout = NULL;
text->revert = NULL;
@@ -3712,6 +3772,7 @@ E_MAKE_TYPE (e_text,
PARENT_TYPE)
+
/* IM Context Callbacks */
static void
e_text_commit_cb (GtkIMContext *context,
@@ -3722,16 +3783,28 @@ e_text_commit_cb (GtkIMContext *context,
if (text->selection_end != text->selection_start)
e_text_delete_selection (text);
e_text_insert (text, str);
- g_signal_emit (text, e_text_signals[E_TEXT_KEYPRESS], 0,
- 0 /* XXX ugh */, 0 /* XXX ugh */);
+ g_signal_emit (text, e_text_signals[E_TEXT_KEYPRESS], 0, 0, 0);
}
}
+static void
+e_text_preedit_changed_cb (GtkIMContext *context,
+ EText *etext)
+{
+ gchar *preedit_string = NULL;
+
+ gtk_im_context_get_preedit_string (context, &preedit_string,
+ NULL, NULL);
+
+ etext->preedit_len = strlen (preedit_string);
+
+ g_signal_emit (etext, e_text_signals[E_TEXT_KEYPRESS], 0, 0, 0);
+}
+
static gboolean
e_text_retrieve_surrounding_cb (GtkIMContext *context,
EText *text)
{
- printf ("e_text_retrieve_surrounding_cb\n");
gtk_im_context_set_surrounding (context,
text->text,
strlen (text->text),
@@ -3746,12 +3819,9 @@ e_text_delete_surrounding_cb (GtkIMContext *context,
gint n_chars,
EText *text)
{
- printf ("e_text_delete_surrounding_cb\n");
-#if 0
- gtk_editable_delete_text (GTK_EDITABLE (entry),
- entry->current_pos + offset,
- entry->current_pos + offset + n_chars);
-#endif
+ gtk_editable_delete_text (GTK_EDITABLE (text),
+ text->selection_end + offset,
+ text->selection_end + offset + n_chars);
return TRUE;
}
diff --git a/widgets/text/e-text.h b/widgets/text/e-text.h
index 0832c5d699..4eb3fa830b 100644
--- a/widgets/text/e-text.h
+++ b/widgets/text/e-text.h
@@ -108,6 +108,7 @@ struct _EText {
gint model_repos_signal_id;
const gchar *text; /* Text to display --- from the ETextModel */
+ gint preedit_len; /* preedit length to display */
PangoLayout *layout;
int num_lines; /* Number of lines of text */