eel r2128 - in trunk: . eel
- From: cneumair svn gnome org
- To: svn-commits-list gnome org
- Subject: eel r2128 - in trunk: . eel
- Date: Mon, 9 Jun 2008 22:53:36 +0000 (UTC)
Author: cneumair
Date: Mon Jun 9 22:53:36 2008
New Revision: 2128
URL: http://svn.gnome.org/viewvc/eel?rev=2128&view=rev
Log:
2008-06-10 Christian Neumair <cneumair gnome org>
* eel/eel-editable-label.c
(eel_editable_label_get_block_cursor_location),
(eel_editable_label_draw_cursor),
(eel_editable_label_toggle_overwrite):
Use block cursor in insert mode. Fixes #511617. Thanks to Arthur
Taylor.
Modified:
trunk/ChangeLog
trunk/eel/eel-editable-label.c
Modified: trunk/eel/eel-editable-label.c
==============================================================================
--- trunk/eel/eel-editable-label.c (original)
+++ trunk/eel/eel-editable-label.c Mon Jun 9 22:53:36 2008
@@ -1317,6 +1317,134 @@
pango_layout_get_cursor_pos (label->layout, index, strong_pos, weak_pos);
}
+/* Copied from gtkutil private function */
+static gboolean
+eel_editable_label_get_block_cursor_location (EelEditableLabel *label,
+ gint *index,
+ PangoRectangle *pos,
+ gboolean *at_line_end)
+{
+ const gchar *text;
+ const gchar *preedit_text;
+ PangoLayoutLine *layout_line;
+ PangoRectangle strong_pos, weak_pos;
+ gint line_no;
+ gboolean rtl;
+ PangoContext *context;
+ PangoFontMetrics *metrics;
+ const PangoFontDescription *font_desc;
+
+ eel_editable_label_ensure_layout (label, TRUE);
+
+ text = pango_layout_get_text (label->layout);
+ preedit_text = text + label->selection_anchor;
+ text = g_utf8_offset_to_pointer (preedit_text, label->preedit_cursor);
+ index[0] = label->selection_anchor + text - preedit_text;
+
+ pango_layout_index_to_pos (label->layout, index[0], pos);
+
+ index[1] = label->selection_anchor + g_utf8_next_char (text) - preedit_text;
+
+ if (pos->width != 0)
+ {
+ if (at_line_end)
+ *at_line_end = FALSE;
+ if (pos->width < 0) /* RTL char, shift x value back to top left of rect */
+ {
+ pos->x += pos->width;
+ pos->width = -pos->width;
+ }
+ return TRUE;
+ }
+
+ pango_layout_index_to_line_x (label->layout, index[0], FALSE, &line_no, NULL);
+ layout_line = pango_layout_get_line_readonly (label->layout, line_no);
+ if (layout_line == NULL)
+ return FALSE;
+
+ text = pango_layout_get_text (label->layout);
+ if (index[0] < layout_line->start_index + layout_line->length)
+ {
+ /* this may be a zero-width character in the middle of the line,
+ * or it could be a character where line is wrapped, we do want
+ * block cursor in latter case */
+ if (g_utf8_next_char (text + index[0]) - text !=
+ layout_line->start_index + layout_line->length)
+ {
+ /* zero-width character in the middle of the line, 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 (label->layout, index[0], &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;
+ }
+
+ context = pango_layout_get_context (label->layout);
+
+ /* 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)
+ {
+ if (layout_line->resolved_dir == PANGO_DIRECTION_RTL)
+ {
+ PangoLayoutIter *iter;
+ PangoRectangle line_rect;
+ gint i;
+ gint left, right;
+ const gchar *p;
+
+ p = g_utf8_prev_char (text + index[0]);
+
+ pango_layout_line_index_to_x (layout_line, p - text, FALSE, &left);
+ pango_layout_line_index_to_x (layout_line, p - text, TRUE, &right);
+ pos->x = MIN (left, right);
+
+ iter = pango_layout_get_iter (label->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 += line_rect.x;
+ }
+ else
+ rtl = FALSE;
+ }
+ else
+ {
+ rtl = pango_context_get_base_dir (context) == PANGO_DIRECTION_RTL;
+ }
+
+ font_desc = pango_layout_get_font_description (label->layout);
+ if (!font_desc)
+ font_desc = pango_context_get_font_description (context);
+
+ metrics = pango_context_get_metrics (context, font_desc, NULL);
+ pos->width = pango_font_metrics_get_approximate_char_width (metrics);
+ pango_font_metrics_unref (metrics);
+
+ if (rtl)
+ pos->x -= pos->width - 1;
+
+ if (at_line_end)
+ *at_line_end = TRUE;
+
+ return pos->width != 0;
+}
+
+
/* These functions are copies from gtk+, as they are not exported from gtk+ */
static GdkGC *
@@ -1347,7 +1475,7 @@
_eel_draw_insertion_cursor (GtkWidget *widget,
GdkDrawable *drawable,
GdkGC *gc,
- GdkRectangle *location,
+ GdkRectangle *location,
GtkTextDirection direction,
gboolean draw_arrow)
{
@@ -1416,8 +1544,11 @@
GtkTextDirection keymap_direction;
GtkTextDirection widget_direction;
- PangoRectangle strong_pos, weak_pos;
gboolean split_cursor;
+ gboolean block;
+ gboolean block_at_line_end;
+ gint range[2];
+ PangoRectangle strong_pos, weak_pos;
PangoRectangle *cursor1 = NULL;
PangoRectangle *cursor2 = NULL;
GdkRectangle cursor_location;
@@ -1430,54 +1561,98 @@
widget_direction = gtk_widget_get_direction (widget);
- eel_editable_label_get_cursor_pos (label, &strong_pos, &weak_pos);
+ if (label->overwrite_mode &&
+ eel_editable_label_get_block_cursor_location (label, range,
+ &strong_pos,
+ &block_at_line_end))
+ block = TRUE;
+ else
+ block = FALSE;
- g_object_get (gtk_widget_get_settings (widget),
- "gtk-split-cursor", &split_cursor,
- NULL);
+ if (!block)
+ {
+ eel_editable_label_get_cursor_pos (label, &strong_pos, &weak_pos);
- dir1 = widget_direction;
-
- if (split_cursor)
- {
- cursor1 = &strong_pos;
+ g_object_get (gtk_widget_get_settings (widget),
+ "gtk-split-cursor", &split_cursor,
+ NULL);
- if (strong_pos.x != weak_pos.x ||
- strong_pos.y != weak_pos.y)
+ dir1 = widget_direction;
+
+ if (split_cursor)
{
- dir2 = (widget_direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
- cursor2 = &weak_pos;
+ cursor1 = &strong_pos;
+
+ if (strong_pos.x != weak_pos.x ||
+ strong_pos.y != weak_pos.y)
+ {
+ dir2 = (widget_direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
+ cursor2 = &weak_pos;
+ }
}
- }
- else
- {
- if (keymap_direction == widget_direction)
- cursor1 = &strong_pos;
else
- cursor1 = &weak_pos;
- }
-
- cursor_location.x = xoffset + PANGO_PIXELS (cursor1->x);
- cursor_location.y = yoffset + PANGO_PIXELS (cursor1->y);
- cursor_location.width = 0;
- cursor_location.height = PANGO_PIXELS (cursor1->height);
-
- _eel_draw_insertion_cursor (widget, widget->window,
- label->primary_cursor_gc,
- &cursor_location, dir1,
- dir2 != GTK_TEXT_DIR_NONE);
+ {
+ if (keymap_direction == widget_direction)
+ cursor1 = &strong_pos;
+ else
+ cursor1 = &weak_pos;
+ }
- if (dir2 != GTK_TEXT_DIR_NONE)
- {
- cursor_location.x = xoffset + PANGO_PIXELS (cursor2->x);
- cursor_location.y = yoffset + PANGO_PIXELS (cursor2->y);
+ cursor_location.x = xoffset + PANGO_PIXELS (cursor1->x);
+ cursor_location.y = yoffset + PANGO_PIXELS (cursor1->y);
cursor_location.width = 0;
- cursor_location.height = PANGO_PIXELS (cursor2->height);
+ cursor_location.height = PANGO_PIXELS (cursor1->height);
_eel_draw_insertion_cursor (widget, widget->window,
- label->secondary_cursor_gc,
- &cursor_location, dir2, TRUE);
+ label->primary_cursor_gc,
+ &cursor_location, dir1,
+ dir2 != GTK_TEXT_DIR_NONE);
+
+ if (dir2 != GTK_TEXT_DIR_NONE)
+ {
+ cursor_location.x = xoffset + PANGO_PIXELS (cursor2->x);
+ cursor_location.y = yoffset + PANGO_PIXELS (cursor2->y);
+ cursor_location.width = 0;
+ cursor_location.height = PANGO_PIXELS (cursor2->height);
+
+ _eel_draw_insertion_cursor (widget, widget->window,
+ label->secondary_cursor_gc,
+ &cursor_location, dir2, TRUE);
+ }
}
+ else /* Block cursor */
+ {
+ GdkRegion *clip;
+
+ gdk_draw_rectangle (widget->window, label->primary_cursor_gc, TRUE,
+ xoffset + PANGO_PIXELS (strong_pos.x),
+ yoffset + PANGO_PIXELS (strong_pos.y),
+ PANGO_PIXELS (strong_pos.width),
+ PANGO_PIXELS (strong_pos.height));
+
+ if (!block_at_line_end)
+ {
+ clip = gdk_pango_layout_get_clip_region (label->layout,
+ xoffset, yoffset,
+ range, 1);
+
+ /* FIXME should use gtk_paint, but it can't use a clip
+ * region
+ */
+
+ gdk_gc_set_clip_region (label->primary_cursor_gc, clip);
+
+ gdk_draw_layout_with_colors (widget->window,
+ label->primary_cursor_gc,
+ xoffset, yoffset,
+ label->layout,
+ &widget->style->base[GTK_STATE_NORMAL],
+ NULL);
+
+ gdk_gc_set_clip_region (label->primary_cursor_gc, NULL);
+ gdk_region_destroy (clip);
+ }
+ }
}
}
@@ -3005,6 +3180,7 @@
eel_editable_label_toggle_overwrite (EelEditableLabel *label)
{
label->overwrite_mode = !label->overwrite_mode;
+ gtk_widget_queue_draw (GTK_WIDGET (label));
}
typedef struct
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]