--- gtkhtml-3.3.2/src/gtkhtml-private.h.imcommit 2004-05-14 07:24:15.000000000 -0400
+++ gtkhtml-3.3.2/src/gtkhtml-private.h 2004-09-21 17:40:45.896197864 -0400
@@ -57,6 +57,7 @@
gint im_pre_len;
gint im_pre_pos;
GtkHTMLFontStyle im_orig_style;
+ gboolean im_hide_cursor;
gboolean im_block_reset;
HTMLObject *dnd_object;
--- gtkhtml-3.3.2/src/gtkhtml.c.imcommit 2004-09-16 18:17:19.000000000 -0400
+++ gtkhtml-3.3.2/src/gtkhtml.c 2004-09-21 17:40:46.036176584 -0400
@@ -1009,7 +1009,7 @@
html_engine_unrealize (html->engine);
- gtk_im_context_set_client_window (html->priv->im_context, widget->window);
+ gtk_im_context_set_client_window (html->priv->im_context, NULL);
html_image_factory_stop_animations (html->engine->image_factory);
@@ -2993,130 +2993,151 @@
}
}
+/* Removes the current preedit string if any; note that it doesn't reset
+ * im_pre_pos/im_pre_len, so it must be followed by a call to update_preedit
+ */
static void
-gtk_html_im_commit_cb (GtkIMContext *context, const gchar *str, GtkHTML *html)
+remove_preedit (GtkHTML *html)
{
- gboolean state = html->priv->im_block_reset;
- gint pos;
-
- if (html->priv->im_pre_len > 0) {
- D_IM (printf ("IM delete last preedit %d + %d\n", html->priv->im_pre_pos, html->priv->im_pre_len);)
-
- html_undo_freeze (html->engine->undo);
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos);
- html_engine_set_mark (html->engine);
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos + html->priv->im_pre_len);
- html_engine_delete (html->engine);
- html->priv->im_pre_len = 0;
- html_undo_thaw (html->engine->undo);
- }
-
- pos = html->engine->cursor->position;
- if (html->engine->mark && html->engine->mark->position > pos)
- pos = html->engine->mark->position;
-
- html->priv->im_block_reset = TRUE;
- D_IM (printf ("IM commit %s\n", str);)
-
- /* Move cusor before preedit pos and commit the string */
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos);
- html_engine_paste_text (html->engine, str, -1);
- /* Add preedit pos with number of str committed and move back */
- html->priv->im_pre_pos += g_utf8_strlen (str, -1);
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos);
-
- html->priv->im_block_reset = state;
-
- D_IM (printf ("IM commit pos: %d pre_pos: %d\n", pos, html->priv->im_pre_pos);)
-
- if (html->priv->im_pre_pos >= pos)
- html->priv->im_pre_pos += html->engine->cursor->position - pos;
-}
+ if (html->priv->im_pre_len > 0) {
+ gboolean state = html->priv->im_block_reset;
+ html->priv->im_block_reset = TRUE;
+
+ html_undo_freeze (html->engine->undo);
+ html_engine_selection_push (html->engine);
-static void
-gtk_html_im_preedit_start_cb (GtkIMContext *context, GtkHTML *html)
-{
- html->priv->im_pre_len = 0;
+ html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos);
+ html_engine_set_mark (html->engine);
+ html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos + html->priv->im_pre_len);
+ html_engine_delete (html->engine);
+
+ html_engine_selection_pop (html->engine);
+ html_undo_thaw (html->engine->undo);
+
+ html->priv->im_block_reset = state;
+ } else {
+ /* The current style can get confused while we are have a preedit string
+ * in place, so we save the current style before we start preediting, and
+ * restore it when the preedit string vanishes. (See bug #66204)
+ */
+ html->priv->im_orig_style = html_engine_get_font_style (html->engine);
+ }
}
static void
-gtk_html_im_preedit_changed_cb (GtkIMContext *context, GtkHTML *html)
+update_preedit (GtkHTML *html)
{
PangoAttrList *attrs;
gchar *preedit_string;
- gint cursor_pos, initial_position;
+ gint cursor_pos, preedit_position;
gboolean state = html->priv->im_block_reset;
- gboolean pop_selection = FALSE;
- gint deleted = 0;
+ gboolean had_selection = FALSE;
+ gboolean had_preedit = html->priv->im_pre_len > 0;
+ gboolean hide_cursor;
- D_IM (printf ("IM preedit changed cb [begin] cursor %d(%p) mark %d(%p) active: %d\n",
- html->engine->cursor ? html->engine->cursor->position : 0, html->engine->cursor,
- html->engine->mark ? html->engine->mark->position : 0, html->engine->mark,
- html_engine_is_selection_active (html->engine));)
html->priv->im_block_reset = TRUE;
+ html_undo_freeze (html->engine->undo);
+
+ /* The handling of the combination of a selection and a preedit string
+ * is imperfect because the selection runs from the 'mark' to the cursor,
+ * so we can't display the selection plus a separate cursor.
+ *
+ * What we do is display the preedit text after the selection (even if
+ * the cursor is at the beginning of the selection), and hide the cursor.
+ * It is generally going to be less confusing not to display a cursor
+ * at all then to display a cursor in the wrong location. Putting the
+ * preedit text after the selection has the handy side effect that the
+ * preedit string doesn't affect the selection bounds.
+ */
if (html_engine_is_selection_active (html->engine)) {
- D_IM (printf ("IM push selection\n");)
html_engine_selection_push (html->engine);
+
+ preedit_position = MAX (html_cursor_get_position (html->engine->mark),
+ html_cursor_get_position (html->engine->cursor));
+
+ /* We need to temporarily remove the selection, or when we paste in the preedit text,
+ * it will replace the selection.
+ */
html_engine_disable_selection (html->engine);
+ html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, preedit_position);
html_engine_edit_selection_updater_update_now (html->engine->selection_updater);
- pop_selection = TRUE;
+ had_selection = TRUE;
}
- initial_position = html->engine->cursor->position;
- D_IM (printf ("IM initial position %d\n", initial_position);)
- html_undo_freeze (html->engine->undo);
-
- if (html->priv->im_pre_len > 0) {
- D_IM (printf ("IM delete last preedit %d + %d\n", html->priv->im_pre_pos, html->priv->im_pre_len);)
-
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos);
- html_engine_set_mark (html->engine);
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos + html->priv->im_pre_len);
- html_engine_delete (html->engine);
- deleted = html->priv->im_pre_len;
- } else
- html->priv->im_orig_style = html_engine_get_font_style (html->engine);
-
- gtk_im_context_get_preedit_string (html->priv->im_context, &preedit_string, &attrs, &cursor_pos);
-
- D_IM (printf ("IM preedit changed to %s\n", preedit_string);)
+ /* Insert the new preedit string
+ */
+ gtk_im_context_get_preedit_string (html->priv->im_context,
+ &preedit_string, &attrs, &cursor_pos);
+
html->priv->im_pre_len = g_utf8_strlen (preedit_string, -1);
+ cursor_pos = CLAMP (cursor_pos, 0, html->priv->im_pre_len); /* Paranoia */
if (html->priv->im_pre_len > 0) {
- cursor_pos = CLAMP (cursor_pos, 0, html->priv->im_pre_len);
html->priv->im_pre_pos = html->engine->cursor->position;
html_engine_paste_text_with_extra_attributes (html->engine, preedit_string, html->priv->im_pre_len, attrs);
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos + cursor_pos);
- } else
+ } else if (had_preedit)
html_engine_set_font_style (html->engine, 0, html->priv->im_orig_style);
+
g_free (preedit_string);
+ pango_attr_list_unref (attrs);
- if (pop_selection) {
- gint position= html->engine->cursor->position, cpos, mpos;
- D_IM (printf ("IM pop selection\n");)
- g_assert (html_engine_selection_stack_top (html->engine, &cpos, &mpos));
- if (position < MAX (cpos, mpos) + html->priv->im_pre_len - deleted)
- g_assert (html_engine_selection_stack_top_modify (html->engine, html->priv->im_pre_len - deleted));
- html_engine_selection_pop (html->engine);
+ /* Update the cursor hiding
+ */
+ hide_cursor = had_selection && html->priv->im_pre_len > 0;
+ if (hide_cursor != html->priv->im_hide_cursor) {
+ if (hide_cursor)
+ html_engine_hide_cursor (html->engine);
+ else
+ html_engine_show_cursor (html->engine);
+
+ html->priv->im_hide_cursor = hide_cursor;
}
- /* that works for now, but idealy we should be able to have cursor positioned outside selection, so that preedit
- cursor is in the right place */
- if (html->priv->im_pre_len == 0)
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine,
- initial_position >= html->priv->im_pre_pos + deleted ? initial_position - deleted : initial_position);
+
+ /* Get the correct cursor and mark for the new preedit string
+ */
+ if (had_selection)
+ html_engine_selection_pop (html->engine);
+ else if (html->priv->im_pre_len > 0)
+ html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos + cursor_pos);
if (html->engine->freeze_count == 1)
html_engine_thaw_idle_flush (html->engine);
- /* FIXME gtk_im_context_set_cursor_location (im_context, &area); */
+
html->priv->im_block_reset = state;
html_undo_thaw (html->engine->undo);
+}
- D_IM (printf ("IM preedit changed cb [end] cursor %d(%p) mark %d(%p) active: %d\n",
- html->engine->cursor ? html->engine->cursor->position : 0, html->engine->cursor,
- html->engine->mark ? html->engine->mark->position : 0, html->engine->mark,
- html_engine_is_selection_active (html->engine));)
+static void
+gtk_html_im_commit_cb (GtkIMContext *context, const gchar *str, GtkHTML *html)
+{
+ gboolean state = html->priv->im_block_reset;
+
+ html->priv->im_block_reset = TRUE;
+
+ D_IM (printf ("IM commit %s\n", str);)
+
+ remove_preedit (html);
+
+ html_engine_paste_text (html->engine, str, -1);
+
+ update_preedit (html);
+
+ html->priv->im_block_reset = state;
+}
+
+static void
+gtk_html_im_preedit_start_cb (GtkIMContext *context, GtkHTML *html)
+{
+ html->priv->im_pre_len = 0;
+}
+
+static void
+gtk_html_im_preedit_changed_cb (GtkIMContext *context, GtkHTML *html)
+{
+ remove_preedit (html);
+ update_preedit (html);
}
static gchar *
@@ -3127,6 +3148,7 @@
gchar *text = NULL;
if (!html_object_is_text (o)) {
+ *offset = 0;
if (e->cursor->offset == 0) {
prev = html_object_prev_not_slave (o);
if (html_object_is_text (prev)) {
@@ -3142,7 +3164,6 @@
} else
return NULL;
}
- *offset = 0;
} else
*offset = e->cursor->offset;
@@ -3163,10 +3184,14 @@
static gboolean
gtk_html_im_retrieve_surrounding_cb (GtkIMContext *context, GtkHTML *html)
{
- gint offset;
+ gint cursor_offset, cursor_index;
+ gchar *str;
+
+ D_IM (printf ("IM gtk_html_im_retrieve_surrounding_cb\n"));
- D_IM (printf ("IM gtk_html_im_retrieve_surrounding_cb\n");)
- gtk_im_context_set_surrounding (context, get_surrounding_text (html->engine, &offset), -1, offset);
+ str = get_surrounding_text (html->engine, &cursor_offset);
+ cursor_index = g_utf8_offset_to_pointer (str, cursor_offset) - str;
+ gtk_im_context_set_surrounding (context, str, -1, cursor_index);
return TRUE;
}
@@ -3182,8 +3207,9 @@
html_engine_set_mark (html->engine);
html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, orig_position + offset + n_chars);
html_engine_delete (html->engine);
- if (offset >= 0)
- html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, orig_position);
+ if (offset < 0)
+ orig_position -= MIN (n_chars, - offset);
+ html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, orig_position);
}
return TRUE;
}
--- gtkhtml-3.3.2/src/htmlengine-edit-cut-and-paste.c.imcommit 2004-09-16 17:49:53.000000000 -0400
+++ gtkhtml-3.3.2/src/htmlengine-edit-cut-and-paste.c 2004-09-21 17:40:46.039176128 -0400
@@ -460,11 +460,11 @@
place_cursor_before_mark (HTMLEngine *e)
{
if (e->mark->position < e->cursor->position) {
- HTMLCursor *tmp;
+ HTMLCursor tmp;
- tmp = e->cursor;
- e->cursor = e->mark;
- e->mark = tmp;
+ html_cursor_copy (&tmp, e->cursor);
+ html_cursor_copy (e->cursor, e->mark);
+ html_cursor_copy (e->mark, &tmp);
}
}
@@ -1713,12 +1713,10 @@
while (start->position < end->position) {
if (start->object->parent->parent == end->object->parent->parent) {
- if (e->mark)
- html_cursor_destroy (e->mark);
- html_cursor_destroy (e->cursor);
- e->mark = start;
- e->cursor = end;
- start = end = NULL;
+ if (!e->mark)
+ e->mark = html_cursor_new ();
+ html_cursor_copy (e->mark, start);
+ html_cursor_copy (e->cursor, end);
delete_object (e, NULL, NULL, HTML_UNDO_UNDO, TRUE);
break;
} else {
@@ -1750,10 +1748,8 @@
}
}
- if (start)
- html_cursor_destroy (start);
- if (end)
- html_cursor_destroy (end);
+ html_cursor_destroy (start);
+ html_cursor_destroy (end);
html_cursor_jump_to_position (e->cursor, e, start_position);
}
html_undo_level_end (e->undo);