* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include <config.h>
#include <string.h>
#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
#include "gtktextview.h"
#include "gtkimmulticontext.h"
#include "gdk/gdkkeysyms.h"
+#include "gtkprivate.h"
#include "gtksizegroup.h" /* FIXME http://bugzilla.gnome.org/show_bug.cgi?id=72258 */
#include "gtktextutil.h"
#include "gtkwindow.h"
+#include "gtkalias.h"
/* How scrolling, validation, exposes, etc. work.
*
#define SCREEN_WIDTH(widget) text_window_get_width (GTK_TEXT_VIEW (widget)->text_window)
#define SCREEN_HEIGHT(widget) text_window_get_height (GTK_TEXT_VIEW (widget)->text_window)
+#define SPACE_FOR_CURSOR 1
+
struct _GtkTextPendingScroll
{
GtkTextMark *mark;
SET_ANCHOR,
INSERT_AT_CURSOR,
DELETE_FROM_CURSOR,
+ BACKSPACE,
CUT_CLIPBOARD,
COPY_CLIPBOARD,
PASTE_CLIPBOARD,
TOGGLE_OVERWRITE,
MOVE_FOCUS,
+ MOVE_VIEWPORT,
+ SELECT_ALL,
LAST_SIGNAL
};
PROP_INDENT,
PROP_TABS,
PROP_CURSOR_VISIBLE,
+ PROP_BUFFER,
+ PROP_OVERWRITE,
+ PROP_ACCEPTS_TAB,
LAST_PROP
};
GtkStyle *previous_style);
static void gtk_text_view_direction_changed (GtkWidget *widget,
GtkTextDirection previous_direction);
+static void gtk_text_view_grab_notify (GtkWidget *widget,
+ gboolean was_grabbed);
static void gtk_text_view_state_changed (GtkWidget *widget,
GtkStateType previous_state);
static gint gtk_text_view_expose_event (GtkWidget *widget,
GdkEventExpose *expose);
static void gtk_text_view_draw_focus (GtkWidget *widget);
-static void gtk_text_view_grab_focus (GtkWidget *widget);
static gboolean gtk_text_view_focus (GtkWidget *widget,
GtkDirectionType direction);
+static void gtk_text_view_select_all (GtkWidget *widget,
+ gboolean select);
/* Source side drag signals */
static void gtk_text_view_page_horizontally (GtkTextView *text_view,
gint count,
gboolean extend_selection);
+static void gtk_text_view_move_viewport (GtkTextView *text_view,
+ GtkScrollStep step,
+ gint count);
static void gtk_text_view_set_anchor (GtkTextView *text_view);
static void gtk_text_view_scroll_pages (GtkTextView *text_view,
gint count,
static void gtk_text_view_delete_from_cursor (GtkTextView *text_view,
GtkDeleteType type,
gint count);
+static void gtk_text_view_backspace (GtkTextView *text_view);
static void gtk_text_view_cut_clipboard (GtkTextView *text_view);
static void gtk_text_view_copy_clipboard (GtkTextView *text_view);
static void gtk_text_view_paste_clipboard (GtkTextView *text_view);
const GtkTextIter *location,
GtkTextMark *mark,
gpointer data);
+static void gtk_text_view_get_cursor_location (GtkTextView *text_view,
+ GdkRectangle *pos);
static void gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view,
gint *x,
gint *y);
GtkWidget *child);
static void gtk_text_view_forall (GtkContainer *container,
gboolean include_internals,
- GtkCallback callback,
+ GtkCallback callback,
gpointer callback_data);
/* FIXME probably need the focus methods. */
gint dy);
static void text_window_invalidate_rect (GtkTextWindow *win,
GdkRectangle *rect);
+static void text_window_invalidate_cursors (GtkTextWindow *win);
static gint text_window_get_width (GtkTextWindow *win);
static gint text_window_get_height (GtkTextWindow *win);
-enum
-{
- TARGET_STRING,
- TARGET_TEXT,
- TARGET_COMPOUND_TEXT,
- TARGET_UTF8_STRING,
- TARGET_TEXT_BUFFER_CONTENTS
-};
-
static const GtkTargetEntry target_table[] = {
- { "GTK_TEXT_BUFFER_CONTENTS", GTK_TARGET_SAME_APP,
- TARGET_TEXT_BUFFER_CONTENTS },
- { "UTF8_STRING", 0, TARGET_UTF8_STRING },
- { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
- { "TEXT", 0, TARGET_TEXT },
- { "STRING", 0, TARGET_STRING }
+ { "GTK_TEXT_BUFFER_CONTENTS", GTK_TARGET_SAME_APP, 0 },
};
static GtkContainerClass *parent_class = NULL;
(GInstanceInitFunc) gtk_text_view_init,
};
- our_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkTextView",
+ our_type = g_type_register_static (GTK_TYPE_CONTAINER, I_("GtkTextView"),
&our_info, 0);
}
widget_class->unrealize = gtk_text_view_unrealize;
widget_class->style_set = gtk_text_view_style_set;
widget_class->direction_changed = gtk_text_view_direction_changed;
+ widget_class->grab_notify = gtk_text_view_grab_notify;
widget_class->state_changed = gtk_text_view_state_changed;
widget_class->size_request = gtk_text_view_size_request;
widget_class->size_allocate = gtk_text_view_size_allocate;
widget_class->focus_out_event = gtk_text_view_focus_out_event;
widget_class->motion_notify_event = gtk_text_view_motion_event;
widget_class->expose_event = gtk_text_view_expose_event;
- widget_class->grab_focus = gtk_text_view_grab_focus;
widget_class->focus = gtk_text_view_focus;
widget_class->drag_begin = gtk_text_view_drag_begin;
klass->set_anchor = gtk_text_view_set_anchor;
klass->insert_at_cursor = gtk_text_view_insert_at_cursor;
klass->delete_from_cursor = gtk_text_view_delete_from_cursor;
+ klass->backspace = gtk_text_view_backspace;
klass->cut_clipboard = gtk_text_view_cut_clipboard;
klass->copy_clipboard = gtk_text_view_copy_clipboard;
klass->paste_clipboard = gtk_text_view_paste_clipboard;
g_object_class_install_property (gobject_class,
PROP_PIXELS_ABOVE_LINES,
- g_param_spec_int ("pixels_above_lines",
- _("Pixels Above Lines"),
- _("Pixels of blank space above paragraphs"),
+ g_param_spec_int ("pixels-above-lines",
+ P_("Pixels Above Lines"),
+ P_("Pixels of blank space above paragraphs"),
0,
G_MAXINT,
0,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_PIXELS_BELOW_LINES,
- g_param_spec_int ("pixels_below_lines",
- _("Pixels Below Lines"),
- _("Pixels of blank space below paragraphs"),
+ g_param_spec_int ("pixels-below-lines",
+ P_("Pixels Below Lines"),
+ P_("Pixels of blank space below paragraphs"),
0,
G_MAXINT,
0,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_PIXELS_INSIDE_WRAP,
- g_param_spec_int ("pixels_inside_wrap",
- _("Pixels Inside Wrap"),
- _("Pixels of blank space between wrapped lines in a paragraph"),
+ g_param_spec_int ("pixels-inside-wrap",
+ P_("Pixels Inside Wrap"),
+ P_("Pixels of blank space between wrapped lines in a paragraph"),
0,
G_MAXINT,
0,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_EDITABLE,
g_param_spec_boolean ("editable",
- _("Editable"),
- _("Whether the text can be modified by the user"),
+ P_("Editable"),
+ P_("Whether the text can be modified by the user"),
TRUE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_WRAP_MODE,
- g_param_spec_enum ("wrap_mode",
- _("Wrap Mode"),
- _("Whether to wrap lines never, at word boundaries, or at character boundaries"),
+ g_param_spec_enum ("wrap-mode",
+ P_("Wrap Mode"),
+ P_("Whether to wrap lines never, at word boundaries, or at character boundaries"),
GTK_TYPE_WRAP_MODE,
GTK_WRAP_NONE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_JUSTIFICATION,
g_param_spec_enum ("justification",
- _("Justification"),
- _("Left, right, or center justification"),
+ P_("Justification"),
+ P_("Left, right, or center justification"),
GTK_TYPE_JUSTIFICATION,
GTK_JUSTIFY_LEFT,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_LEFT_MARGIN,
- g_param_spec_int ("left_margin",
- _("Left Margin"),
- _("Width of the left margin in pixels"),
+ g_param_spec_int ("left-margin",
+ P_("Left Margin"),
+ P_("Width of the left margin in pixels"),
0,
G_MAXINT,
0,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_RIGHT_MARGIN,
- g_param_spec_int ("right_margin",
- _("Right Margin"),
- _("Width of the right margin in pixels"),
+ g_param_spec_int ("right-margin",
+ P_("Right Margin"),
+ P_("Width of the right margin in pixels"),
0,
G_MAXINT,
0,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_INDENT,
g_param_spec_int ("indent",
- _("Indent"),
- _("Amount to indent the paragraph, in pixels"),
+ P_("Indent"),
+ P_("Amount to indent the paragraph, in pixels"),
0,
G_MAXINT,
0,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_TABS,
g_param_spec_boxed ("tabs",
- _("Tabs"),
- _("Custom tabs for this text"),
+ P_("Tabs"),
+ P_("Custom tabs for this text"),
PANGO_TYPE_TAB_ARRAY,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_CURSOR_VISIBLE,
- g_param_spec_boolean ("cursor_visible",
- _("Cursor Visible"),
- _("If the insertion cursor is shown"),
+ g_param_spec_boolean ("cursor-visible",
+ P_("Cursor Visible"),
+ P_("If the insertion cursor is shown"),
TRUE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_BUFFER,
+ g_param_spec_object ("buffer",
+ P_("Buffer"),
+ P_("The buffer which is displayed"),
+ GTK_TYPE_TEXT_BUFFER,
+ GTK_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_OVERWRITE,
+ g_param_spec_boolean ("overwrite",
+ P_("Overwrite mode"),
+ P_("Whether entered text overwrites existing contents"),
+ FALSE,
+ GTK_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_ACCEPTS_TAB,
+ g_param_spec_boolean ("accepts-tab",
+ P_("Accepts tab"),
+ P_("Whether Tab will result in a tab character being entered"),
+ TRUE,
+ GTK_PARAM_READWRITE));
+
+ /*
+ * Style properties
+ */
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boxed ("error-underline-color",
+ P_("Error underline color"),
+ P_("Color with which to draw error-indication underlines"),
+ GDK_TYPE_COLOR,
+ GTK_PARAM_READABLE));
/*
* Signals
*/
- signals[MOVE_CURSOR] =
- g_signal_new ("move_cursor",
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ /**
+ * GtkTextView::move-cursor:
+ * @widget: the object which received the signal
+ * @step: the granularity of the move, as a #GtkMovementStep
+ * @count: the number of @step units to move
+ * @extend_selection: %TRUE if the move should extend the selection
+ *
+ * The ::move-cursor signal is a keybinding signal which gets emitted
+ * when the user initiates a cursor movement.
+ *
+ * Applications should not connect to it, but may emit it with
+ * g_signal_emit_by_name() if they need to control scrolling
+ * programmatically.
+ *
+ */
+ signals[MOVE_CURSOR] =
+ g_signal_new (I_("move_cursor"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, move_cursor),
- NULL, NULL,
- _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
+ NULL, NULL,
+ _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
G_TYPE_NONE, 3,
- GTK_TYPE_MOVEMENT_STEP,
- G_TYPE_INT,
+ GTK_TYPE_MOVEMENT_STEP,
+ G_TYPE_INT,
G_TYPE_BOOLEAN);
signals[PAGE_HORIZONTALLY] =
- g_signal_new ("page_horizontally",
+ g_signal_new (I_("page_horizontally"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, page_horizontally),
G_TYPE_INT,
G_TYPE_BOOLEAN);
+ signals[MOVE_VIEWPORT] =
+ _gtk_binding_signal_new (I_("move_viewport"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_text_view_move_viewport),
+ NULL, NULL,
+ _gtk_marshal_VOID__ENUM_INT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_SCROLL_STEP,
+ G_TYPE_INT);
+
signals[SET_ANCHOR] =
- g_signal_new ("set_anchor",
+ g_signal_new (I_("set_anchor"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, set_anchor),
G_TYPE_NONE, 0);
signals[INSERT_AT_CURSOR] =
- g_signal_new ("insert_at_cursor",
+ g_signal_new (I_("insert_at_cursor"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, insert_at_cursor),
G_TYPE_STRING);
signals[DELETE_FROM_CURSOR] =
- g_signal_new ("delete_from_cursor",
+ g_signal_new (I_("delete_from_cursor"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, delete_from_cursor),
GTK_TYPE_DELETE_TYPE,
G_TYPE_INT);
+ signals[BACKSPACE] =
+ g_signal_new (I_("backspace"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkTextViewClass, backspace),
+ NULL, NULL,
+ _gtk_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
signals[CUT_CLIPBOARD] =
- g_signal_new ("cut_clipboard",
+ g_signal_new (I_("cut_clipboard"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, cut_clipboard),
G_TYPE_NONE, 0);
signals[COPY_CLIPBOARD] =
- g_signal_new ("copy_clipboard",
+ g_signal_new (I_("copy_clipboard"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, copy_clipboard),
G_TYPE_NONE, 0);
signals[PASTE_CLIPBOARD] =
- g_signal_new ("paste_clipboard",
+ g_signal_new (I_("paste_clipboard"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, paste_clipboard),
G_TYPE_NONE, 0);
signals[TOGGLE_OVERWRITE] =
- g_signal_new ("toggle_overwrite",
+ g_signal_new (I_("toggle_overwrite"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, toggle_overwrite),
G_TYPE_NONE, 0);
signals[MOVE_FOCUS] =
- g_signal_new ("move_focus",
+ g_signal_new (I_("move_focus"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, move_focus),
GTK_TYPE_DIRECTION_TYPE);
signals[SET_SCROLL_ADJUSTMENTS] =
- g_signal_new ("set_scroll_adjustments",
+ g_signal_new (I_("set_scroll_adjustments"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTextViewClass, set_scroll_adjustments),
widget_class->set_scroll_adjustments_signal = signals[SET_SCROLL_ADJUSTMENTS];
signals[POPULATE_POPUP] =
- g_signal_new ("populate_popup",
+ g_signal_new (I_("populate_popup"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTextViewClass, populate_popup),
G_TYPE_NONE, 1,
GTK_TYPE_MENU);
+ signals[SELECT_ALL] =
+ _gtk_binding_signal_new (I_("select_all"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_text_view_select_all),
+ NULL, NULL,
+ _gtk_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1,
+ G_TYPE_BOOLEAN, TRUE);
+
+
/*
* Key bindings
*/
add_move_binding (binding_set, GDK_KP_Page_Down, GDK_CONTROL_MASK,
GTK_MOVEMENT_HORIZONTAL_PAGES, 1);
- /* Select all
- */
+ /* Select all */
gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK,
- "move_cursor", 3,
- GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
- G_TYPE_INT, -1,
- G_TYPE_BOOLEAN, FALSE);
- gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK,
- "move_cursor", 3,
- GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
- G_TYPE_INT, 1,
- G_TYPE_BOOLEAN, TRUE);
+ "select_all", 1,
+ G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
- "move_cursor", 3,
- GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
- G_TYPE_INT, -1,
- G_TYPE_BOOLEAN, FALSE);
- gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
- "move_cursor", 3,
- GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
- G_TYPE_INT, 1,
- G_TYPE_BOOLEAN, TRUE);
-
- /* Unselect all
- */
+ "select_all", 1,
+ G_TYPE_BOOLEAN, TRUE);
+
+ /* Unselect all */
gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK,
- "move_cursor", 3,
- GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
- G_TYPE_INT, 0,
- G_TYPE_BOOLEAN, FALSE);
+ "select_all", 1,
+ G_TYPE_BOOLEAN, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "select_all", 1,
+ G_TYPE_BOOLEAN, FALSE);
/* Deleting text */
gtk_binding_entry_add_signal (binding_set, GDK_Delete, 0,
G_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
- "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_CHARS,
- G_TYPE_INT, -1);
+ "backspace", 0);
/* Make this do the same as Backspace, to help with mis-typing */
gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_SHIFT_MASK,
- "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_CHARS,
- G_TYPE_INT, -1);
+ "backspace", 0);
gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
"delete_from_cursor", 2,
0,
target_table, G_N_ELEMENTS (target_table),
GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ gtk_drag_dest_add_text_targets (widget);
text_view->virtual_cursor_x = -1;
text_view->virtual_cursor_y = -1;
text_view->cursor_visible = TRUE;
+ text_view->accepts_tab = TRUE;
+
text_view->text_window = text_window_new (GTK_TEXT_WINDOW_TEXT,
widget, 200, 200);
gtk_text_buffer_add_selection_clipboard (text_view->buffer, clipboard);
}
}
+
+ g_object_notify (G_OBJECT (text_view), "buffer");
if (GTK_WIDGET_VISIBLE (text_view))
gtk_widget_queue_draw (GTK_WIDGET (text_view));
gtk_text_view_ensure_layout (text_view);
gtk_text_layout_get_iter_at_pixel (text_view->layout,
- iter,
- x,
- y);
+ iter, x, y);
+}
+
+/**
+ * gtk_text_view_get_iter_at_position:
+ * @text_view: a #GtkTextView
+ * @iter: a #GtkTextIter
+ * @trailing: location to store an integer indicating where
+ * in the grapheme the user clicked. It will either be
+ * zero, or the number of characters in the grapheme.
+ * 0 represents the trailing edge of the grapheme.
+ * @x: x position, in buffer coordinates
+ * @y: y position, in buffer coordinates
+ *
+ * Retrieves the iterator pointing to the character at buffer
+ * coordinates @x and @y. Buffer coordinates are coordinates for
+ * the entire buffer, not just the currently-displayed portion.
+ * If you have coordinates from an event, you have to convert
+ * those to buffer coordinates with
+ * gtk_text_view_window_to_buffer_coords().
+ *
+ * Note that this is different from gtk_text_view_get_iter_at_location(),
+ * which returns cursor locations, i.e. positions <emphasis>between</emphasis>
+ * characters.
+ *
+ * Since: 2.6
+ **/
+void
+gtk_text_view_get_iter_at_position (GtkTextView *text_view,
+ GtkTextIter *iter,
+ gint *trailing,
+ gint x,
+ gint y)
+{
+ g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
+ g_return_if_fail (iter != NULL);
+
+ gtk_text_view_ensure_layout (text_view);
+
+ gtk_text_layout_get_iter_at_position (text_view->layout,
+ iter, trailing, x, y);
}
/**
scroll->use_align,
scroll->xalign,
scroll->yalign);
-
+
free_pending_scroll (scroll);
return retval;
gtk_text_layout_get_size (text_view->layout, &width, &height);
/* Make room for the cursor after the last character in the widest line */
- width++;
+ width += SPACE_FOR_CURSOR;
if (text_view->width != width || text_view->height != height)
{
+ if (text_view->width != width)
+ text_view->width_changed = TRUE;
+
text_view->width = width;
text_view->height = height;
gtk_text_view_ensure_layout (text_view);
gtk_text_layout_set_screen_width (text_view->layout,
- SCREEN_WIDTH (text_view));
+ MAX (1, SCREEN_WIDTH (text_view) - SPACE_FOR_CURSOR));
}
static void
gtk_text_view_update_im_spot_location (GtkTextView *text_view)
{
GdkRectangle area;
- gint cursor_x_pos, cursor_y_pos;
if (text_view->layout == NULL)
return;
- gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos);
+ gtk_text_view_get_cursor_location (text_view, &area);
- area.x = cursor_x_pos;
- area.y = cursor_y_pos;
- area.width = area.height = 0;
+ area.x -= text_view->xoffset;
+ area.y -= text_view->yoffset;
+
+ /* Width returned by Pango indicates direction of cursor,
+ * by it's sign more than the size of cursor.
+ */
+ area.width = 0;
gtk_im_context_set_cursor_location (text_view->im_context, &area);
}
}
}
- g_object_notify (G_OBJECT (text_view), "wrap_mode");
+ g_object_notify (G_OBJECT (text_view), "wrap-mode");
}
/**
gtk_text_layout_default_style_changed (text_view->layout);
}
- g_object_notify (G_OBJECT (text_view), "pixels_above_lines");
+ g_object_notify (G_OBJECT (text_view), "pixels-above-lines");
}
}
gtk_text_layout_default_style_changed (text_view->layout);
}
- g_object_notify (G_OBJECT (text_view), "pixels_below_lines");
+ g_object_notify (G_OBJECT (text_view), "pixels-below-lines");
}
}
gtk_text_layout_default_style_changed (text_view->layout);
}
- g_object_notify (G_OBJECT (text_view), "pixels_inside_wrap");
+ g_object_notify (G_OBJECT (text_view), "pixels-inside-wrap");
}
}
gtk_text_layout_default_style_changed (text_view->layout);
}
- g_object_notify (G_OBJECT (text_view), "left_margin");
+ g_object_notify (G_OBJECT (text_view), "left-margin");
}
}
gtk_text_layout_default_style_changed (text_view->layout);
}
- g_object_notify (G_OBJECT (text_view), "right_margin");
+ g_object_notify (G_OBJECT (text_view), "right-margin");
}
}
}
}
- g_object_notify (G_OBJECT (text_view), "cursor_visible");
+ g_object_notify (G_OBJECT (text_view), "cursor-visible");
}
}
gtk_text_view_set_cursor_visible (text_view, g_value_get_boolean (value));
break;
+ case PROP_OVERWRITE:
+ gtk_text_view_set_overwrite (text_view, g_value_get_boolean (value));
+ break;
+
+ case PROP_BUFFER:
+ gtk_text_view_set_buffer (text_view, GTK_TEXT_BUFFER (g_value_get_object (value)));
+ break;
+
+ case PROP_ACCEPTS_TAB:
+ gtk_text_view_set_accepts_tab (text_view, g_value_get_boolean (value));
+ break;
+
default:
g_assert_not_reached ();
break;
g_value_set_boolean (value, text_view->cursor_visible);
break;
+ case PROP_BUFFER:
+ g_value_set_object (value, get_buffer (text_view));
+ break;
+
+ case PROP_OVERWRITE:
+ g_value_set_boolean (value, text_view->overwrite_mode);
+ break;
+
+ case PROP_ACCEPTS_TAB:
+ g_value_set_boolean (value, text_view->accepts_tab);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
text_view = GTK_TEXT_VIEW (widget);
gtk_widget_style_get (widget,
- "interior_focus", &interior_focus,
- "focus_line_width", &focus_width,
+ "interior-focus", &interior_focus,
+ "focus-line-width", &focus_width,
NULL);
if (interior_focus)
&child_loc,
child->anchor);
+ /* Since anchored children are only ever allocated from
+ * gtk_text_layout_get_line_display() we have to make sure
+ * that the display line caching in the layout doesn't
+ * get in the way. Invalidating the layout around the anchor
+ * achieves this.
+ */
+ if (GTK_WIDGET_ALLOC_NEEDED (child->widget))
+ {
+ GtkTextIter end = child_loc;
+ gtk_text_iter_forward_char (&end);
+ gtk_text_layout_invalidate (text_view->layout, &child_loc, &end);
+ }
+
gtk_text_layout_validate_yrange (text_view->layout,
&child_loc,
0, 1);
*/
gtk_widget_style_get (widget,
- "interior_focus", &interior_focus,
- "focus_line_width", &focus_width,
+ "interior-focus", &interior_focus,
+ "focus-line-width", &focus_width,
NULL);
if (interior_focus)
if (old_req.width != new_req.width ||
old_req.height != new_req.height)
{
- /* FIXME http://bugzilla.gnome.org/show_bug.cgi?id=72258 */
- _gtk_size_group_queue_resize (widget);
+ gtk_widget_queue_resize_no_redraw (widget);
}
}
}
text_view->mouse_cursor_obscured = TRUE;
}
+static void
+gtk_text_view_unobscure_mouse_cursor (GtkTextView *text_view)
+{
+ if (text_view->mouse_cursor_obscured)
+ {
+ GdkCursor *cursor;
+
+ cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)),
+ GDK_XTERM);
+ gdk_window_set_cursor (text_view->text_window->bin_window, cursor);
+ gdk_cursor_unref (cursor);
+ text_view->mouse_cursor_obscured = FALSE;
+ }
+}
+
+static void
+gtk_text_view_grab_notify (GtkWidget *widget,
+ gboolean was_grabbed)
+{
+ if (!was_grabbed)
+ gtk_text_view_unobscure_mouse_cursor (GTK_TEXT_VIEW (widget));
+}
+
+
/*
* Events
*/
/* this won't actually insert the newline if the cursor isn't
* editable
*/
+ gtk_text_view_reset_im_context (text_view);
gtk_text_view_commit_text (text_view, "\n");
obscure = TRUE;
event->keyval == GDK_KP_Tab) &&
!(event->state & GDK_CONTROL_MASK))
{
- /* If the text widget isn't editable overall, move the focus
- * instead
+ /* If the text widget isn't editable overall, or if the application
+ * has turned off "accepts_tab", move the focus instead
*/
- if (text_view->editable)
+ if (text_view->accepts_tab && text_view->editable)
{
+ gtk_text_view_reset_im_context (text_view);
gtk_text_view_commit_text (text_view, "\t");
obscure = TRUE;
}
text_view = GTK_TEXT_VIEW (widget);
- text_view->disable_scroll_on_focus = TRUE;
gtk_widget_grab_focus (widget);
- text_view->disable_scroll_on_focus = FALSE;
if (event->window != text_view->text_window->bin_window)
{
event->y + text_view->yoffset);
gtk_text_buffer_place_cursor (get_buffer (text_view), &iter);
-
+ gtk_text_view_check_cursor_blink (text_view);
+
text_view->pending_place_cursor_button = 0;
return FALSE;
{
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
- if (text_view->mouse_cursor_obscured)
- {
- GdkCursor *cursor;
-
- cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
- GDK_XTERM);
- gdk_window_set_cursor (text_view->text_window->bin_window, cursor);
- gdk_cursor_unref (cursor);
- text_view->mouse_cursor_obscured = FALSE;
- }
+ gtk_text_view_unobscure_mouse_cursor (text_view);
if (event->window == text_view->text_window->bin_window &&
text_view->drag_start_x >= 0)
while (tmp_list != NULL)
{
GtkWidget *child = tmp_list->data;
-
+
gtk_container_propagate_expose (GTK_CONTAINER (text_view),
child,
event);
if (event->window == widget->window)
gtk_text_view_draw_focus (widget);
- /* Propagate exposes to all children not in the buffer. */
+ /* Propagate exposes to all unanchored children.
+ * Anchored children are handled in gtk_text_view_paint().
+ */
tmp_list = GTK_TEXT_VIEW (widget)->children;
while (tmp_list != NULL)
{
/* propagate_expose checks that event->window matches
* child->window
*/
- if (vc->type != GTK_TEXT_WINDOW_TEXT)
+ if (!vc->anchor)
gtk_container_propagate_expose (GTK_CONTAINER (widget),
vc->widget,
event);
/* We clear the focus if we are in interior focus mode. */
gtk_widget_style_get (widget,
- "interior_focus", &interior_focus,
+ "interior-focus", &interior_focus,
NULL);
if (GTK_WIDGET_DRAWABLE (widget))
}
}
-static void
-gtk_text_view_grab_focus (GtkWidget *widget)
-{
- GtkTextView *text_view;
-
- text_view = GTK_TEXT_VIEW (widget);
-
- GTK_WIDGET_CLASS (parent_class)->grab_focus (widget);
-
- if (!text_view->disable_scroll_on_focus)
- gtk_text_view_scroll_mark_onscreen (text_view,
- gtk_text_buffer_get_mark (get_buffer (text_view),
- "insert"));
-}
-
static gboolean
gtk_text_view_focus (GtkWidget *widget,
GtkDirectionType direction)
#endif
if (gtk_debug_flags & GTK_DEBUG_UPDATES)
return FALSE;
-
- g_object_get (settings, "gtk-cursor-blink", &blink, NULL);
- return blink;
+
+ if (text_view->editable)
+ {
+ GtkTextMark *insert;
+ GtkTextIter iter;
+
+ insert = gtk_text_buffer_get_insert (get_buffer (text_view));
+ gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, insert);
+
+ if (gtk_text_iter_editable (&iter, text_view->editable))
+ {
+ g_object_get (settings, "gtk-cursor-blink", &blink, NULL);
+ return blink;
+ }
+ }
+
+ return FALSE;
}
static gint
text_view = GTK_TEXT_VIEW (data);
+ if (!GTK_WIDGET_HAS_FOCUS (text_view))
+ {
+ g_warning ("GtkTextView - did not receive focus-out-event. If you\n"
+ "connect a handler to this signal, it must return\n"
+ "FALSE so the entry gets the event as well");
+ }
+
g_assert (text_view->layout);
g_assert (GTK_WIDGET_HAS_FOCUS (text_view));
g_assert (text_view->cursor_visible);
text_view->blink_timeout = g_timeout_add (get_cursor_time (text_view) * CURSOR_ON_MULTIPLIER,
blink_cb,
text_view);
-
- gtk_text_layout_set_cursor_visible (text_view->layout,
- !visible);
+
+ /* Block changed_handler while changing the layout's cursor visibility
+ * because it would expose the whole paragraph. Instead, we expose
+ * the cursor's area(s) manually below.
+ */
+ g_signal_handlers_block_by_func (text_view->layout,
+ changed_handler,
+ text_view);
+
+ gtk_text_layout_set_cursor_visible (text_view->layout, !visible);
+
+ g_signal_handlers_unblock_by_func (text_view->layout,
+ changed_handler,
+ text_view);
+
+ text_window_invalidate_cursors (text_view->text_window);
GDK_THREADS_LEAVE ();
{
if (text_view->layout != NULL &&
text_view->cursor_visible &&
- GTK_WIDGET_HAS_FOCUS (text_view))
+ GTK_WIDGET_HAS_FOCUS (text_view) &&
+ cursor_blinks (text_view))
{
- if (cursor_blinks (text_view))
+ if (text_view->blink_timeout == 0)
{
- if (text_view->blink_timeout == 0)
- {
- gtk_text_layout_set_cursor_visible (text_view->layout, TRUE);
-
- text_view->blink_timeout = g_timeout_add (get_cursor_time (text_view) * CURSOR_OFF_MULTIPLIER,
- blink_cb,
- text_view);
- }
+ gtk_text_layout_set_cursor_visible (text_view->layout, TRUE);
+
+ text_view->blink_timeout = g_timeout_add (get_cursor_time (text_view) * CURSOR_OFF_MULTIPLIER,
+ blink_cb,
+ text_view);
}
- else
- gtk_text_layout_set_cursor_visible (text_view->layout, TRUE);
}
else
{
gtk_text_view_stop_cursor_blink (text_view);
+ gtk_text_layout_set_cursor_visible (text_view->layout, TRUE);
}
}
static void
-gtk_text_view_pend_cursor_blink(GtkTextView *text_view)
+gtk_text_view_pend_cursor_blink (GtkTextView *text_view)
{
if (text_view->layout != NULL &&
text_view->cursor_visible &&
GTK_WIDGET_HAS_FOCUS (text_view) &&
cursor_blinks (text_view))
{
- if (text_view->blink_timeout != 0)
- {
- g_source_remove (text_view->blink_timeout);
- text_view->blink_timeout = 0;
- }
-
+ gtk_text_view_stop_cursor_blink (text_view);
gtk_text_layout_set_cursor_visible (text_view->layout, TRUE);
text_view->blink_timeout = g_timeout_add (get_cursor_time (text_view) * CURSOR_PEND_MULTIPLIER,
* Key binding handlers
*/
-static void
+static gboolean
gtk_text_view_move_iter_by_lines (GtkTextView *text_view,
GtkTextIter *newplace,
gint count)
{
+ gboolean ret = TRUE;
+
while (count < 0)
{
- gtk_text_layout_move_iter_to_previous_line (text_view->layout, newplace);
+ ret = gtk_text_layout_move_iter_to_previous_line (text_view->layout, newplace);
count++;
}
while (count > 0)
{
- gtk_text_layout_move_iter_to_next_line (text_view->layout, newplace);
+ ret = gtk_text_layout_move_iter_to_next_line (text_view->layout, newplace);
count--;
}
+
+ return ret;
}
static void
"insert",
new_location);
else
- gtk_text_buffer_place_cursor (get_buffer (text_view),
- new_location);
+ gtk_text_buffer_place_cursor (get_buffer (text_view),
+ new_location);
+ gtk_text_view_check_cursor_blink (text_view);
}
static void
gint cursor_x_pos = 0;
+ if (!text_view->cursor_visible)
+ {
+ GtkScrollStep scroll_step;
+
+ switch (step)
+ {
+ case GTK_MOVEMENT_LOGICAL_POSITIONS:
+ case GTK_MOVEMENT_VISUAL_POSITIONS:
+ case GTK_MOVEMENT_WORDS:
+ scroll_step = GTK_SCROLL_HORIZONTAL_STEPS;
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
+ scroll_step = GTK_SCROLL_HORIZONTAL_ENDS;
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINES:
+ case GTK_MOVEMENT_PARAGRAPHS:
+ case GTK_MOVEMENT_PARAGRAPH_ENDS:
+ scroll_step = GTK_SCROLL_STEPS;
+ break;
+ case GTK_MOVEMENT_PAGES:
+ scroll_step = GTK_SCROLL_PAGES;
+ break;
+ case GTK_MOVEMENT_HORIZONTAL_PAGES:
+ scroll_step = GTK_SCROLL_HORIZONTAL_PAGES;
+ break;
+ case GTK_MOVEMENT_BUFFER_ENDS:
+ scroll_step = GTK_SCROLL_ENDS;
+ break;
+ default:
+ scroll_step = GTK_SCROLL_PAGES;
+ break;
+ }
+
+ gtk_text_view_move_viewport (text_view, scroll_step, count);
+
+ return;
+ }
+
gtk_text_view_reset_im_context (text_view);
if (step == GTK_MOVEMENT_PAGES)
{
gtk_text_view_scroll_pages (text_view, count, extend_selection);
+ gtk_text_view_check_cursor_blink (text_view);
gtk_text_view_pend_cursor_blink (text_view);
return;
}
else if (step == GTK_MOVEMENT_HORIZONTAL_PAGES)
{
gtk_text_view_scroll_hpages (text_view, count, extend_selection);
+ gtk_text_view_check_cursor_blink (text_view);
gtk_text_view_pend_cursor_blink (text_view);
return;
}
case GTK_MOVEMENT_WORDS:
if (count < 0)
gtk_text_iter_backward_visible_word_starts (&newplace, -count);
- else if (count > 0)
- gtk_text_iter_forward_visible_word_ends (&newplace, count);
+ else if (count > 0)
+ {
+ if (!gtk_text_iter_forward_visible_word_ends (&newplace, count))
+ gtk_text_iter_forward_to_line_end (&newplace);
+ }
break;
case GTK_MOVEMENT_DISPLAY_LINES:
- gtk_text_view_move_iter_by_lines (text_view, &newplace, count);
- gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
+ if (count < 0)
+ {
+ if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
+ gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
+ else
+ gtk_text_iter_set_line_offset (&newplace, 0);
+ }
+ if (count > 0)
+ {
+ if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
+ gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
+ else
+ gtk_text_iter_forward_to_line_end (&newplace);
+ }
break;
case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
gtk_text_iter_forward_to_line_end (&newplace);
--count;
}
- gtk_text_iter_forward_lines (&newplace, count);
+ gtk_text_iter_forward_visible_lines (&newplace, count);
gtk_text_iter_forward_to_line_end (&newplace);
}
else if (count < 0)
{
if (gtk_text_iter_get_line_offset (&newplace) > 0)
- {
- gtk_text_iter_set_line_offset (&newplace, 0);
- ++count;
- }
- gtk_text_iter_forward_lines (&newplace, count);
+ gtk_text_iter_set_line_offset (&newplace, 0);
+ gtk_text_iter_forward_visible_lines (&newplace, count);
gtk_text_iter_set_line_offset (&newplace, 0);
}
break;
"insert"));
if (step == GTK_MOVEMENT_DISPLAY_LINES)
- {
- gtk_text_view_set_virtual_cursor_pos (text_view, cursor_x_pos, -1);
- }
+ gtk_text_view_set_virtual_cursor_pos (text_view, cursor_x_pos, -1);
}
+ gtk_text_view_check_cursor_blink (text_view);
gtk_text_view_pend_cursor_blink (text_view);
}
count, extend_selection);
}
+
+static void
+gtk_text_view_move_viewport (GtkTextView *text_view,
+ GtkScrollStep step,
+ gint count)
+{
+ GtkAdjustment *adjustment;
+ gdouble increment;
+
+ switch (step)
+ {
+ case GTK_SCROLL_STEPS:
+ case GTK_SCROLL_PAGES:
+ case GTK_SCROLL_ENDS:
+ adjustment = get_vadjustment (text_view);
+ break;
+ case GTK_SCROLL_HORIZONTAL_STEPS:
+ case GTK_SCROLL_HORIZONTAL_PAGES:
+ case GTK_SCROLL_HORIZONTAL_ENDS:
+ adjustment = get_hadjustment (text_view);
+ break;
+ default:
+ adjustment = get_vadjustment (text_view);
+ break;
+ }
+
+ switch (step)
+ {
+ case GTK_SCROLL_STEPS:
+ case GTK_SCROLL_HORIZONTAL_STEPS:
+ increment = adjustment->step_increment;
+ break;
+ case GTK_SCROLL_PAGES:
+ case GTK_SCROLL_HORIZONTAL_PAGES:
+ increment = adjustment->page_increment;
+ break;
+ case GTK_SCROLL_ENDS:
+ case GTK_SCROLL_HORIZONTAL_ENDS:
+ increment = adjustment->upper - adjustment->lower;
+ break;
+ default:
+ increment = 0.0;
+ break;
+ }
+
+ set_adjustment_clamped (adjustment, adjustment->value + count * increment);
+}
+
static void
gtk_text_view_set_anchor (GtkTextView *text_view)
{
gint y0, y1;
g_return_if_fail (text_view->vadjustment != NULL);
-
- cancel_pending_scroll (text_view);
adj = text_view->vadjustment;
- /* Validate the region that will be brought into view by the cursor motion
+ /* Make sure we start from the current cursor position, even
+ * if it was offscreen, but don't queue more scrolls if we're
+ * already behind.
+ */
+ if (text_view->pending_scroll)
+ cancel_pending_scroll (text_view);
+ else
+ gtk_text_view_scroll_mark_onscreen (text_view,
+ gtk_text_buffer_get_mark (get_buffer (text_view),
+ "insert"));
+
+/* Validate the region that will be brought into view by the cursor motion
*/
if (count < 0)
{
g_return_if_fail (text_view->hadjustment != NULL);
- cancel_pending_scroll (text_view);
-
adj = text_view->hadjustment;
+ /* Make sure we start from the current cursor position, even
+ * if it was offscreen, but don't queue more scrolls if we're
+ * already behind.
+ */
+ if (text_view->pending_scroll)
+ cancel_pending_scroll (text_view);
+ else
+ gtk_text_view_scroll_mark_onscreen (text_view,
+ gtk_text_buffer_get_mark (get_buffer (text_view),
+ "insert"));
+
/* Validate the line that we're moving within.
*/
gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
else if (count > 0 && adj->value >= (adj->upper - adj->page_size - 1e-12))
{
/* already at far right, just be sure we are at the end */
- gtk_text_iter_forward_to_line_end (&new_insert);
+ if (!gtk_text_iter_ends_line (&new_insert))
+ gtk_text_iter_forward_to_line_end (&new_insert);
move_cursor (text_view, &new_insert, extend_selection);
}
else
}
}
+static void
+gtk_text_view_backspace (GtkTextView *text_view)
+{
+ GtkTextIter insert;
+
+ gtk_text_view_reset_im_context (text_view);
+
+ /* Backspace deletes the selection, if one exists */
+ if (gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE,
+ text_view->editable))
+ return;
+
+ gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
+ &insert,
+ gtk_text_buffer_get_mark (get_buffer (text_view),
+ "insert"));
+
+ if (gtk_text_buffer_backspace (get_buffer (text_view), &insert,
+ TRUE, text_view->editable))
+ {
+ DV(g_print (G_STRLOC": scrolling onscreen\n"));
+ gtk_text_view_scroll_mark_onscreen (text_view,
+ gtk_text_buffer_get_mark (get_buffer (text_view), "insert"));
+ }
+}
+
static void
gtk_text_view_cut_clipboard (GtkTextView *text_view)
{
gtk_text_view_toggle_overwrite (GtkTextView *text_view)
{
text_view->overwrite_mode = !text_view->overwrite_mode;
+ g_object_notify (G_OBJECT (text_view), "overwrite");
+}
+
+/**
+ * gtk_text_view_get_overwrite:
+ * @text_view: a #GtkTextView
+ *
+ * Returns whether the #GtkTextView is in overwrite mode or not.
+ *
+ * Return value: whether @text_view is in overwrite mode or not.
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_view_get_overwrite (GtkTextView *text_view)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+
+ return text_view->overwrite_mode;
+}
+
+/**
+ * gtk_text_view_set_overwrite:
+ * @text_view: a #GtkTextView
+ * @overwrite: %TRUE to turn on overwrite mode, %FALSE to turn it off
+ *
+ * Changes the #GtkTextView overwrite mode.
+ *
+ * Since: 2.4
+ **/
+void
+gtk_text_view_set_overwrite (GtkTextView *text_view,
+ gboolean overwrite)
+{
+ g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
+ overwrite = overwrite != FALSE;
+
+ if (text_view->overwrite_mode != overwrite)
+ {
+ text_view->overwrite_mode = overwrite;
+
+ g_object_notify (G_OBJECT (text_view), "overwrite");
+ }
+}
+
+/**
+ * gtk_text_view_set_accepts_tab:
+ * @text_view: A #GtkTextView
+ * @accepts_tab: %TRUE if pressing the Tab key should insert a tab character, %FALSE, if pressing the Tab key should move the keyboard focus.
+ *
+ * Sets the behavior of the text widget when the Tab key is pressed. If @accepts_tab
+ * is %TRUE a tab character is inserted. If @accepts_tab is %FALSE the keyboard focus
+ * is moved to the next widget in the focus chain.
+ *
+ * Since: 2.4
+ **/
+void
+gtk_text_view_set_accepts_tab (GtkTextView *text_view,
+ gboolean accepts_tab)
+{
+ g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
+
+ accepts_tab = accepts_tab != FALSE;
+
+ if (text_view->accepts_tab != accepts_tab)
+ {
+ text_view->accepts_tab = accepts_tab;
+
+ g_object_notify (G_OBJECT (text_view), "accepts-tab");
+ }
+}
+
+/**
+ * gtk_text_view_get_accepts_tab:
+ * @text_view: A #GtkTextView
+ *
+ * Returns whether pressing the Tab key inserts a tab characters.
+ * gtk_text_view_set_accepts_tab().
+ *
+ * Return value: %TRUE if pressing the Tab key inserts a tab character, %FALSE if pressing the Tab key moves the keyboard focus.
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_view_get_accepts_tab (GtkTextView *text_view)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+
+ return text_view->accepts_tab;
}
static void
/*
* Move @start and @end to the boundaries of the selection unit (indicated by
- * @granularity) which contained @start initially. Return wether @start was
- * contained in a selection unit at all (which may not be the case for words).
+ * @granularity) which contained @start initially.
+ * If the selction unit is SELECT_WORDS and @start is not contained in a word
+ * the selection is extended to all the white spaces between the end of the
+ * word preceding @start and the start of the one following.
*/
-static gboolean
+static void
extend_selection (GtkTextView *text_view,
SelectionGranularity granularity,
GtkTextIter *start,
GtkTextIter *end)
{
- gboolean extend = TRUE;
-
*end = *start;
if (granularity == SELECT_WORDS)
gtk_text_iter_backward_visible_word_start (start);
if (!gtk_text_iter_ends_word (end))
- gtk_text_iter_forward_visible_word_end (end);
+ {
+ if (!gtk_text_iter_forward_visible_word_end (end))
+ gtk_text_iter_forward_to_end (end);
+ }
}
else
- extend = FALSE;
+ {
+ GtkTextIter tmp;
+
+ tmp = *start;
+ if (gtk_text_iter_backward_visible_word_start (&tmp))
+ gtk_text_iter_forward_visible_word_end (&tmp);
+
+ if (gtk_text_iter_get_line (&tmp) == gtk_text_iter_get_line (start))
+ *start = tmp;
+ else
+ gtk_text_iter_set_line_offset (start, 0);
+
+ tmp = *end;
+ if (!gtk_text_iter_forward_visible_word_end (&tmp))
+ gtk_text_iter_forward_to_end (&tmp);
+
+ if (gtk_text_iter_ends_word (&tmp))
+ gtk_text_iter_backward_visible_word_start (&tmp);
+
+ if (gtk_text_iter_get_line (&tmp) == gtk_text_iter_get_line (end))
+ *end = tmp;
+ else
+ gtk_text_iter_forward_to_line_end (end);
+ }
}
else if (granularity == SELECT_LINES)
{
gtk_text_view_forward_display_line_end (text_view, end);
}
}
-
- return extend;
}
static gint
event->x + text_view->xoffset,
event->y + text_view->yoffset);
- if (extend_selection (text_view, granularity, &start, &end))
- {
- /* Extend selection */
- gtk_text_buffer_get_iter_at_mark (buffer,
- &ins,
- gtk_text_buffer_get_insert (buffer));
- gtk_text_buffer_get_iter_at_mark (buffer,
+ extend_selection (text_view, granularity, &start, &end);
+
+ /* Extend selection */
+ gtk_text_buffer_get_iter_at_mark (buffer,
+ &ins,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_buffer_get_iter_at_mark (buffer,
&bound,
gtk_text_buffer_get_selection_bound (buffer));
- if (gtk_text_iter_compare (&ins, &bound) < 0)
- {
- old_start = ins;
- old_end = bound;
- }
- else
- {
- old_start = bound;
- old_end = ins;
- }
-
- if (gtk_text_iter_compare (&start, &old_start) < 0)
- {
- /* newly selected unit before the current selection */
- ins = start;
- bound = old_end;
- }
- else if (gtk_text_iter_compare (&old_end, &end) < 0)
- {
- /* newly selected unit after the current selection */
- ins = end;
- bound = old_start;
- }
- else if (gtk_text_iter_equal (&ins, &old_start))
- {
- /* newly selected unit inside the current selection
- at the start */
- if (!gtk_text_iter_equal (&ins, &start))
- ins = end;
- }
- else
- {
- /* newly selected unit inside the current selection
- at the end */
- if (!gtk_text_iter_equal (&ins, &end))
- ins = start;
- }
+ if (gtk_text_iter_compare (&ins, &bound) < 0)
+ {
+ old_start = ins;
+ old_end = bound;
+ }
+ else
+ {
+ old_start = bound;
+ old_end = ins;
+ }
- gtk_text_buffer_select_range (buffer, &ins, &bound);
+ if (gtk_text_iter_compare (&start, &old_start) < 0)
+ {
+ /* newly selected unit before the current selection */
+ ins = start;
+ bound = old_end;
}
+ else if (gtk_text_iter_compare (&old_end, &end) < 0)
+ {
+ /* newly selected unit after the current selection */
+ ins = end;
+ bound = old_start;
+ }
+ else if (gtk_text_iter_equal (&ins, &old_start))
+ {
+ /* newly selected unit inside the current selection at the start */
+ if (!gtk_text_iter_equal (&ins, &start))
+ ins = end;
+ }
+ else
+ {
+ /* newly selected unit inside the current selection at the end */
+ if (!gtk_text_iter_equal (&ins, &end))
+ ins = start;
+ }
+
+ gtk_text_buffer_select_range (buffer, &ins, &bound);
gtk_text_view_scroll_mark_onscreen (text_view,
gtk_text_buffer_get_mark (buffer,
"insert"));
}
-
/* If we had to scroll offscreen, insert a timeout to do so
* again. Note that in the timeout, even if the mouse doesn't
* move, due to this scroll xoffset/yoffset will have changed
}
gtk_text_buffer_select_range (buffer, &end, &start);
-
+ gtk_text_view_check_cursor_blink (text_view);
+
text_view->selection_drag_handler = g_signal_connect (text_view,
"motion_notify_event",
G_CALLBACK (selection_motion_event_handler),
{
if (text_view->layout)
{
- gboolean split_cursor;
- GtkTextDirection new_dir;
GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (text_view));
-
+ GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
+ GtkTextDirection new_cursor_dir;
+ GtkTextDirection new_keyboard_dir;
+ gboolean split_cursor;
+
g_object_get (settings,
"gtk-split-cursor", &split_cursor,
NULL);
+
+ if (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_RTL)
+ new_keyboard_dir = GTK_TEXT_DIR_RTL;
+ else
+ new_keyboard_dir = GTK_TEXT_DIR_LTR;
+
if (split_cursor)
- {
- new_dir = GTK_TEXT_DIR_NONE;
- }
+ new_cursor_dir = GTK_TEXT_DIR_NONE;
else
- {
- GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
- new_dir = (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
- GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
- }
+ new_cursor_dir = new_keyboard_dir;
- if (text_view->layout->cursor_direction != new_dir)
- gtk_text_layout_set_cursor_direction (text_view->layout, new_dir);
+ gtk_text_layout_set_cursor_direction (text_view->layout, new_cursor_dir);
+ gtk_text_layout_set_keyboard_direction (text_view->layout, new_keyboard_dir);
}
}
}
}
+static gchar*
+_gtk_text_view_get_selected_text (GtkTextView *text_view)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ gchar *text = NULL;
+
+ buffer = gtk_text_view_get_buffer (text_view);
+
+ if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+ text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+
+ return text;
+}
+
/*
* DND feature
*/
+static void
+drag_begin_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer data)
+{
+ GtkTextView *text_view;
+ gchar *text;
+ GdkPixmap *pixmap = NULL;
+
+ g_signal_handlers_disconnect_by_func (widget, drag_begin_cb, NULL);
+
+ text_view = GTK_TEXT_VIEW (widget);
+
+ text = _gtk_text_view_get_selected_text (text_view);
+ pixmap = _gtk_text_util_create_drag_icon (widget, text, -1);
+
+ if (pixmap)
+ gtk_drag_set_icon_pixmap (context,
+ gdk_drawable_get_colormap (pixmap),
+ pixmap,
+ NULL,
+ -2, -2);
+ else
+ gtk_drag_set_icon_default (context);
+
+ if (pixmap)
+ g_object_unref (pixmap);
+ g_free (text);
+}
+
static void
gtk_text_view_start_selection_dnd (GtkTextView *text_view,
const GtkTextIter *iter,
GdkEventMotion *event)
{
GdkDragContext *context;
- GtkTargetList *target_list;
+ GtkTargetList *target_list;
text_view->drag_start_x = -1;
text_view->drag_start_y = -1;
target_list = gtk_target_list_new (target_table,
G_N_ELEMENTS (target_table));
+ gtk_target_list_add_text_targets (target_list, 0);
+ g_signal_connect (text_view, "drag-begin",
+ G_CALLBACK (drag_begin_cb), NULL);
context = gtk_drag_begin (GTK_WIDGET (text_view), target_list,
GDK_ACTION_COPY | GDK_ACTION_MOVE,
1, (GdkEvent*)event);
gtk_target_list_unref (target_list);
-
- gtk_drag_set_icon_default (context);
}
static void
text_view = GTK_TEXT_VIEW (widget);
- if (selection_data->target == gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
+ if (selection_data->target == gdk_atom_intern_static_string ("GTK_TEXT_BUFFER_CONTENTS"))
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);
gtk_selection_data_set (selection_data,
- gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
+ gdk_atom_intern_static_string ("GTK_TEXT_BUFFER_CONTENTS"),
8, /* bytes */
(void*)&buffer,
sizeof (buffer));
GtkTextIter drop_point;
GtkTextView *text_view;
gboolean success = FALSE;
+ GtkTextBuffer *buffer = NULL;
text_view = GTK_TEXT_VIEW (widget);
if (!text_view->dnd_mark)
goto done;
- gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
+ buffer = get_buffer (text_view);
+
+ gtk_text_buffer_get_iter_at_mark (buffer,
&drop_point,
text_view->dnd_mark);
if (!gtk_text_iter_can_insert (&drop_point, text_view->editable))
goto done;
- if (selection_data->target == gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
+ success = TRUE;
+
+ gtk_text_buffer_begin_user_action (buffer);
+
+ if (selection_data->target == gdk_atom_intern_static_string ("GTK_TEXT_BUFFER_CONTENTS"))
{
GtkTextBuffer *src_buffer = NULL;
GtkTextIter start, end;
g_return_if_fail (GTK_IS_TEXT_BUFFER (src_buffer));
if (gtk_text_buffer_get_tag_table (src_buffer) !=
- gtk_text_buffer_get_tag_table (get_buffer (text_view)))
+ gtk_text_buffer_get_tag_table (buffer))
copy_tags = FALSE;
if (gtk_text_buffer_get_selection_bounds (src_buffer,
&end))
{
if (copy_tags)
- gtk_text_buffer_insert_range_interactive (get_buffer (text_view),
+ gtk_text_buffer_insert_range_interactive (buffer,
&drop_point,
&start,
&end,
gchar *str;
str = gtk_text_iter_get_visible_text (&start, &end);
- gtk_text_buffer_insert_interactive (get_buffer (text_view),
+ gtk_text_buffer_insert_interactive (buffer,
&drop_point, str, -1,
text_view->editable);
g_free (str);
}
else
insert_text_data (text_view, &drop_point, selection_data);
-
- gtk_text_buffer_place_cursor (get_buffer (text_view), &drop_point);
-
- success = TRUE;
-
+
done:
gtk_drag_finish (context, success,
success && context->action == GDK_ACTION_MOVE,
time);
+
+ if (success)
+ {
+ gtk_text_buffer_get_iter_at_mark (buffer,
+ &drop_point,
+ text_view->dnd_mark);
+ gtk_text_buffer_place_cursor (buffer, &drop_point);
+
+ gtk_text_buffer_end_user_action (buffer);
+ }
}
static GtkAdjustment*
{
dx = text_view->xoffset - (gint)adj->value;
text_view->xoffset = adj->value;
+
+ /* If the change is due to a size change we need
+ * to invalidate the entire text window because there might be
+ * right-aligned or centered text
+ */
+ if (text_view->width_changed)
+ {
+ gdk_window_invalidate_rect (text_view->text_window->bin_window, NULL, FALSE);
+
+ text_view->width_changed = FALSE;
+ }
}
else if (adj == text_view->vadjustment)
{
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);
+ gtk_text_buffer_delete_interactive (text_view->buffer, &start, &end,
+ text_view->editable);
return TRUE;
}
}
static void
-gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view,
- gint *x,
- gint *y)
+gtk_text_view_get_cursor_location (GtkTextView *text_view,
+ GdkRectangle *pos)
{
- GdkRectangle strong_pos;
GtkTextIter insert;
-
+
gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert,
gtk_text_buffer_get_mark (get_buffer (text_view),
"insert"));
+ gtk_text_layout_get_cursor_locations (text_view->layout, &insert, pos, NULL);
+}
+
+static void
+gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view,
+ gint *x,
+ gint *y)
+{
+ GdkRectangle pos;
+
if ((x && text_view->virtual_cursor_x == -1) ||
(y && text_view->virtual_cursor_y == -1))
- gtk_text_layout_get_cursor_locations (text_view->layout, &insert, &strong_pos, NULL);
+ gtk_text_view_get_cursor_location (text_view, &pos);
if (x)
{
if (text_view->virtual_cursor_x != -1)
*x = text_view->virtual_cursor_x;
else
- *x = strong_pos.x;
+ *x = pos.x;
}
if (y)
if (text_view->virtual_cursor_x != -1)
*y = text_view->virtual_cursor_y;
else
- *y = strong_pos.y + strong_pos.height / 2;
+ *y = pos.y + pos.height / 2;
}
}
gint x,
gint y)
{
- GdkRectangle strong_pos;
- GtkTextIter insert;
-
- gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert,
- gtk_text_buffer_get_mark (get_buffer (text_view),
- "insert"));
+ GdkRectangle pos;
if (x == -1 || y == -1)
- gtk_text_layout_get_cursor_locations (text_view->layout, &insert, &strong_pos, NULL);
+ gtk_text_view_get_cursor_location (text_view, &pos);
- text_view->virtual_cursor_x = (x == -1) ? strong_pos.x : x;
- text_view->virtual_cursor_y = (y == -1) ? strong_pos.y + strong_pos.height / 2 : y;
+ text_view->virtual_cursor_x = (x == -1) ? pos.x : x;
+ text_view->virtual_cursor_y = (y == -1) ? pos.y + pos.height / 2 : y;
}
/* Quick hack of a popup menu
{
GtkWidget *menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
- g_object_set_data (G_OBJECT (menuitem), "gtk-signal", (char *)signal);
+ g_object_set_data (G_OBJECT (menuitem), I_("gtk-signal"), (char *)signal);
g_signal_connect (menuitem, "activate",
G_CALLBACK (activate_cb), text_view);
}
static void
-select_all_cb (GtkWidget *menuitem,
- GtkTextView *text_view)
+gtk_text_view_select_all (GtkWidget *widget,
+ gboolean select)
{
+ GtkTextView *text_view = GTK_TEXT_VIEW (widget);
GtkTextBuffer *buffer;
- GtkTextIter start_iter, end_iter;
+ GtkTextIter start_iter, end_iter, insert;
buffer = text_view->buffer;
- gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
- gtk_text_buffer_move_mark_by_name (buffer, "insert", &start_iter);
- gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &end_iter);
- gtk_text_buffer_copy_clipboard (buffer, gtk_clipboard_get (GDK_NONE));
+ if (select)
+ {
+ gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
+ gtk_text_buffer_select_range (buffer, &start_iter, &end_iter);
+ }
+ else
+ {
+ gtk_text_buffer_get_iter_at_mark (buffer, &insert,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &insert);
+ }
+}
+
+static void
+select_all_cb (GtkWidget *menuitem,
+ GtkTextView *text_view)
+{
+ gtk_text_view_select_all (GTK_WIDGET (text_view), TRUE);
}
static void
GtkTextIter iter;
GtkRequisition req;
GdkScreen *screen;
-
+ gint monitor_num;
+ GdkRectangle monitor;
+
text_view = GTK_TEXT_VIEW (user_data);
widget = GTK_WIDGET (text_view);
*x = root_x + (widget->allocation.width / 2 - req.width / 2);
*y = root_y + (widget->allocation.height / 2 - req.height / 2);
}
-
+
/* Ensure sanity */
*x = CLAMP (*x, root_x, (root_x + widget->allocation.width));
*y = CLAMP (*y, root_y, (root_y + widget->allocation.height));
- *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
- *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
+ monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
+ gtk_menu_set_monitor (menu, monitor_num);
+ gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+
+ *x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width));
+ *y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height));
+
+ *push_in = FALSE;
}
typedef struct
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
- menuitem = gtk_menu_item_new_with_mnemonic (_("Select _All"));
+ menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
g_signal_connect (menuitem, "activate",
G_CALLBACK (select_all_cb), text_view);
gtk_widget_show (menuitem);
menuitem = gtk_menu_item_new_with_mnemonic (_("Input _Methods"));
gtk_widget_show (menuitem);
+ gtk_widget_set_sensitive (menuitem, can_insert);
+
submenu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (text_view),
GDK_SELECTION_CLIPBOARD),
- gdk_atom_intern ("TARGETS", FALSE),
+ gdk_atom_intern_static_string ("TARGETS"),
popup_targets_received,
info);
}
&attributes,
attributes_mask);
+ gdk_window_set_back_pixmap (win->window, NULL, FALSE);
+
gdk_window_show (win->window);
gdk_window_set_user_data (win->window, win->widget);
#if 0
{
- GdkColor color = { 0, 65535, 0, 0 };
- GdkGC *gc = gdk_gc_new (win->bin_window);
- gdk_gc_set_rgb_fg_color (gc, &color);
- gdk_draw_rectangle (win->bin_window,
- gc, TRUE, window_rect.x, window_rect.y,
- window_rect.width, window_rect.height);
- g_object_unref (gc);
+ cairo_t *cr = gdk_cairo_create (win->bin_window);
+ gdk_cairo_rectangle (cr, &window_rect);
+ cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); /* red */
+ cairo_fill (cr);
+ cairo_destroy (cr);
}
#endif
}
+static void
+text_window_invalidate_cursors (GtkTextWindow *win)
+{
+ GtkTextView *text_view = GTK_TEXT_VIEW (win->widget);
+ GtkTextIter iter;
+ GdkRectangle strong;
+ GdkRectangle weak;
+ gboolean draw_arrow;
+ gfloat cursor_aspect_ratio;
+ gint stem_width;
+ gint arrow_width;
+
+ gtk_text_buffer_get_iter_at_mark (text_view->buffer, &iter,
+ gtk_text_buffer_get_insert (text_view->buffer));
+
+ gtk_text_layout_get_cursor_locations (text_view->layout, &iter,
+ &strong, &weak);
+
+ /* cursor width calculation as in gtkstyle.c:draw_insertion_cursor(),
+ * ignoring the text direction be exposing both sides of the cursor
+ */
+
+ draw_arrow = (strong.x != weak.x || strong.y != weak.y);
+
+ gtk_widget_style_get (win->widget,
+ "cursor-aspect-ratio", &cursor_aspect_ratio,
+ NULL);
+
+ stem_width = strong.height * cursor_aspect_ratio + 1;
+ arrow_width = stem_width + 1;
+
+ /* round up to the next even number */
+ if (stem_width & 1)
+ stem_width++;
+
+ strong.x -= stem_width / 2;
+ strong.width += stem_width;
+
+ if (draw_arrow)
+ {
+ strong.x -= arrow_width;
+ strong.width += arrow_width * 2;
+ }
+
+ text_window_invalidate_rect (win, &strong);
+
+ if (draw_arrow) /* == have weak */
+ {
+ stem_width = weak.height * cursor_aspect_ratio + 1;
+ arrow_width = stem_width + 1;
+
+ /* round up to the next even number */
+ if (stem_width & 1)
+ stem_width++;
+
+ weak.x -= stem_width / 2;
+ weak.width += stem_width;
+
+ weak.x -= arrow_width;
+ weak.width += arrow_width * 2;
+
+ text_window_invalidate_rect (win, &weak);
+ }
+}
+
static gint
text_window_get_width (GtkTextWindow *win)
{
g_object_ref (vc->anchor);
g_object_set_data (G_OBJECT (child),
- "gtk-text-view-child",
+ I_("gtk-text-view-child"),
vc);
gtk_text_child_anchor_register_child (anchor, child, layout);
vc->y = y;
g_object_set_data (G_OBJECT (child),
- "gtk-text-view-child",
+ I_("gtk-text-view-child"),
vc);
return vc;
text_view_child_free (GtkTextViewChild *child)
{
g_object_set_data (G_OBJECT (child->widget),
- "gtk-text-view-child", NULL);
+ I_("gtk-text-view-child"), NULL);
if (child->anchor)
{
return gtk_text_layout_move_iter_visually (text_view->layout, iter, count);
}
+
+#define __GTK_TEXT_VIEW_C__
+#include "gtkaliasdef.c"