summaryrefslogtreecommitdiff
path: root/gtk/gtktextutil.c
diff options
context:
space:
mode:
authorYevgen Muntyan <muntyan@tamu.edu>2007-06-12 05:32:57 +0000
committerBehdad Esfahbod <behdad@src.gnome.org>2007-06-12 05:32:57 +0000
commitef1e05f7ded60ec3551ec4ab57fded69437a6837 (patch)
treed4c976d8416c781a92cbe59dcb17bd4eee9e1b51 /gtk/gtktextutil.c
parent15c693477897eb1bbc8aebae880ef979eae1ba94 (diff)
downloadgtk+-ef1e05f7ded60ec3551ec4ab57fded69437a6837.tar.gz
Implement block-cursor for overwrite mode. (#80378)
2007-06-12 Yevgen Muntyan <muntyan@tamu.edu> * gtk/gtkentry.c (gtk_entry_expose), (gtk_entry_toggle_overwrite), (gtk_entry_draw_cursor): * gtk/gtkstyle.c (_gtk_widget_get_cursor_gc), (_gtk_widget_get_cursor_color): * gtk/gtkstyle.h: * gtk/gtktextdisplay.c (gtk_text_renderer_prepare_run), (gtk_text_renderer_draw_shape), (text_renderer_set_state), (render_para): * gtk/gtktextlayout.c (gtk_text_layout_set_overwrite_mode), (gtk_text_layout_invalidate_cache), (get_block_cursor), (add_cursor), (gtk_text_layout_get_line_display), (_gtk_text_layout_get_block_cursor): * gtk/gtktextlayout.h: * gtk/gtktextutil.c (layout_get_char_width), (_gtk_text_util_get_block_cursor_location): * gtk/gtktextutil.h: * gtk/gtktextview.c (gtk_text_view_set_editable), (gtk_text_view_toggle_overwrite), (gtk_text_view_set_overwrite), (gtk_text_view_ensure_layout), (text_window_invalidate_cursors): Implement block-cursor for overwrite mode. (#80378) svn path=/trunk/; revision=18108
Diffstat (limited to 'gtk/gtktextutil.c')
-rw-r--r--gtk/gtktextutil.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/gtk/gtktextutil.c b/gtk/gtktextutil.c
index 4c6f16977a..f601e2f9bd 100644
--- a/gtk/gtktextutil.c
+++ b/gtk/gtktextutil.c
@@ -362,3 +362,146 @@ _gtk_text_util_create_rich_drag_icon (GtkWidget *widget,
return drawable;
}
+
+
+static gint
+layout_get_char_width (PangoLayout *layout)
+{
+ gint width;
+ PangoFontMetrics *metrics;
+ const PangoFontDescription *font_desc;
+ PangoContext *context = pango_layout_get_context (layout);
+
+ font_desc = pango_layout_get_font_description (layout);
+ if (!font_desc)
+ font_desc = pango_context_get_font_description (context);
+
+ metrics = pango_context_get_metrics (context, font_desc, NULL);
+ width = pango_font_metrics_get_approximate_char_width (metrics);
+ pango_font_metrics_unref (metrics);
+
+ return width;
+}
+
+/**
+ * _gtk_text_util_get_block_cursor_location
+ * @layout: a #PangoLayout
+ * @index: index at which cursor is located
+ * @rect: cursor location
+ *
+ * Returns: whether cursor should actually be drawn as a rectangle.
+ * It may not be the case if character at index is invisible.
+ **/
+gboolean
+_gtk_text_util_get_block_cursor_location (PangoLayout *layout,
+ gint index,
+ PangoRectangle *pos,
+ gboolean *at_line_end)
+{
+ PangoRectangle strong_pos, weak_pos;
+ PangoLayoutLine *layout_line;
+ gboolean rtl;
+ gint line_no;
+
+ g_return_val_if_fail (layout != NULL, FALSE);
+ g_return_val_if_fail (index >= 0, FALSE);
+ g_return_val_if_fail (pos != NULL, FALSE);
+
+ pango_layout_index_to_pos (layout, index, pos);
+
+ if (pos->width != 0)
+ {
+ /* cursor is at some visible character, good */
+ if (at_line_end)
+ *at_line_end = FALSE;
+ if (pos->width < 0)
+ {
+ pos->x += pos->width;
+ pos->width = -pos->width;
+ }
+ return TRUE;
+ }
+
+ pango_layout_index_to_line_x (layout, index, FALSE, &line_no, NULL);
+ g_return_val_if_fail (line_no >= 0, FALSE);
+ layout_line = pango_layout_get_line_readonly (layout, line_no);
+
+ /* end of layout, get last line */
+ if (!layout_line)
+ {
+ line_no -= 1;
+ layout_line = pango_layout_get_line_readonly (layout, line_no);
+ }
+
+ g_return_val_if_fail (layout_line != NULL, FALSE);
+
+ if (index < layout_line->start_index + layout_line->length)
+ {
+ /* cursor points to some zero-width character, do not
+ * bother with block cursor */
+ return FALSE;
+ }
+
+ /* Cursor is at the line end. It may be an empty line, or it could
+ * be on the left or on the right depending on text direction, or it
+ * even could be in the middle of visual layout in bidi text. */
+
+ pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
+
+ if (strong_pos.x != weak_pos.x)
+ {
+ /* do not show block cursor in this case, since the character typed
+ * in may or may not appear at the cursor position */
+ return FALSE;
+ }
+
+ /* In case when index points to the end of line, pos->x is always most right
+ * pixel of the layout line, so we need to correct it for RTL text. */
+ if (layout_line->length)
+ {
+ gint left, right;
+ const gchar *text;
+ const gchar *p;
+
+ text = pango_layout_get_text (layout);
+ p = g_utf8_prev_char (text + index);
+
+ pango_layout_line_index_to_x (layout_line, p - text, FALSE, &left);
+ pango_layout_line_index_to_x (layout_line, p - text, TRUE, &right);
+
+ if (MIN (left, right) <= 0)
+ {
+ /* last character is on the left, RTL */
+
+ PangoLayoutIter *iter;
+ PangoRectangle line_rect;
+ gint i;
+
+ iter = pango_layout_get_iter (layout);
+ for (i = 0; i < line_no; i++)
+ pango_layout_iter_next_line (iter);
+ pango_layout_iter_get_line_extents (iter, NULL, &line_rect);
+ pango_layout_iter_free (iter);
+
+ rtl = TRUE;
+ pos->x = MIN (left, right) + line_rect.x;
+ }
+ else
+ rtl = FALSE;
+ }
+ else
+ {
+ PangoContext *context = pango_layout_get_context (layout);
+ rtl = pango_context_get_base_dir (context) == PANGO_DIRECTION_RTL;
+ }
+
+ pos->width = layout_get_char_width (layout);
+
+ if (rtl)
+ pos->x -= pos->width - 1;
+
+ if (at_line_end)
+ *at_line_end = TRUE;
+
+ return pos->width != 0;
+}