summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog38
-rw-r--r--ChangeLog.pre-2-038
-rw-r--r--ChangeLog.pre-2-1038
-rw-r--r--ChangeLog.pre-2-238
-rw-r--r--ChangeLog.pre-2-438
-rw-r--r--ChangeLog.pre-2-638
-rw-r--r--ChangeLog.pre-2-838
-rw-r--r--gdk/gdkdraw.c7
-rw-r--r--gtk/gtkentry.c14
-rw-r--r--gtk/gtktextbuffer.c60
-rw-r--r--gtk/gtktextdisplay.c4
-rw-r--r--gtk/gtktextiter.c110
-rw-r--r--gtk/gtktextiter.h3
-rw-r--r--gtk/gtktextlayout.c178
-rw-r--r--gtk/gtktextlayout.h30
-rw-r--r--gtk/gtktextmark.c26
-rw-r--r--gtk/gtktextmark.h12
-rw-r--r--gtk/gtktextview.c144
-rw-r--r--gtk/gtktextview.h17
19 files changed, 740 insertions, 131 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f525e6152..49b9f5c17a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,40 @@
-2000-12-01 <alexl@redhat.com>
+2000-11-30 Havoc Pennington <hp@pobox.com>
+
+ * gtk/gtktextdisplay.c (gtk_text_layout_draw): don't create
+ dangling pointers to the appearance attributes from the
+ line display
+
+ * gdk/gdkdraw.c (gdk_drawable_get_image): allow negative
+ width/height to mean "full width/height of drawable"
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Implement double/triple
+ click to select word/line
+
+ * gtk/gtktextiter.c (test_log_attrs): include paragraph delimiters
+ when getting log attrs. Get a slice, so that pixmaps and stuff
+ are properly handled.
+
+ * gtk/gtktextbuffer.c (paste): Fix pasting to work properly if you
+ paste into the selection (replaces selection now, previously
+ crashed or added to selection). Reveals longstanding btree bug -
+ select multiple lines, middle-click on the selection, boom. This
+ isn't related to my changes though.
+
+ * gtk/gtkentry.c (gtk_entry_move_forward_word): Update to reflect
+ PangoLogAttrs changes
+ (gtk_entry_move_backward_word): ditto
+
+ * gtk/gtktextlayout.h, gtk/gtktextlayout.c: Make the iter motion
+ functions return bool whether the iter moved onto a
+ dereferenceable position.
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Add a bunch of public
+ functions for motion in terms of display lines.
+
+ * gtk/gtktextmark.c (gtk_text_mark_get_buffer): Add function to
+ get the buffer a mark is inside
+
+2000-12-01 Alexander Larsson <alexl@redhat.com>
* gdk/linux-fb/Makefile.am:
* modules/linux-fb/Makefile.am:
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index 6f525e6152..49b9f5c17a 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,4 +1,40 @@
-2000-12-01 <alexl@redhat.com>
+2000-11-30 Havoc Pennington <hp@pobox.com>
+
+ * gtk/gtktextdisplay.c (gtk_text_layout_draw): don't create
+ dangling pointers to the appearance attributes from the
+ line display
+
+ * gdk/gdkdraw.c (gdk_drawable_get_image): allow negative
+ width/height to mean "full width/height of drawable"
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Implement double/triple
+ click to select word/line
+
+ * gtk/gtktextiter.c (test_log_attrs): include paragraph delimiters
+ when getting log attrs. Get a slice, so that pixmaps and stuff
+ are properly handled.
+
+ * gtk/gtktextbuffer.c (paste): Fix pasting to work properly if you
+ paste into the selection (replaces selection now, previously
+ crashed or added to selection). Reveals longstanding btree bug -
+ select multiple lines, middle-click on the selection, boom. This
+ isn't related to my changes though.
+
+ * gtk/gtkentry.c (gtk_entry_move_forward_word): Update to reflect
+ PangoLogAttrs changes
+ (gtk_entry_move_backward_word): ditto
+
+ * gtk/gtktextlayout.h, gtk/gtktextlayout.c: Make the iter motion
+ functions return bool whether the iter moved onto a
+ dereferenceable position.
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Add a bunch of public
+ functions for motion in terms of display lines.
+
+ * gtk/gtktextmark.c (gtk_text_mark_get_buffer): Add function to
+ get the buffer a mark is inside
+
+2000-12-01 Alexander Larsson <alexl@redhat.com>
* gdk/linux-fb/Makefile.am:
* modules/linux-fb/Makefile.am:
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 6f525e6152..49b9f5c17a 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,4 +1,40 @@
-2000-12-01 <alexl@redhat.com>
+2000-11-30 Havoc Pennington <hp@pobox.com>
+
+ * gtk/gtktextdisplay.c (gtk_text_layout_draw): don't create
+ dangling pointers to the appearance attributes from the
+ line display
+
+ * gdk/gdkdraw.c (gdk_drawable_get_image): allow negative
+ width/height to mean "full width/height of drawable"
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Implement double/triple
+ click to select word/line
+
+ * gtk/gtktextiter.c (test_log_attrs): include paragraph delimiters
+ when getting log attrs. Get a slice, so that pixmaps and stuff
+ are properly handled.
+
+ * gtk/gtktextbuffer.c (paste): Fix pasting to work properly if you
+ paste into the selection (replaces selection now, previously
+ crashed or added to selection). Reveals longstanding btree bug -
+ select multiple lines, middle-click on the selection, boom. This
+ isn't related to my changes though.
+
+ * gtk/gtkentry.c (gtk_entry_move_forward_word): Update to reflect
+ PangoLogAttrs changes
+ (gtk_entry_move_backward_word): ditto
+
+ * gtk/gtktextlayout.h, gtk/gtktextlayout.c: Make the iter motion
+ functions return bool whether the iter moved onto a
+ dereferenceable position.
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Add a bunch of public
+ functions for motion in terms of display lines.
+
+ * gtk/gtktextmark.c (gtk_text_mark_get_buffer): Add function to
+ get the buffer a mark is inside
+
+2000-12-01 Alexander Larsson <alexl@redhat.com>
* gdk/linux-fb/Makefile.am:
* modules/linux-fb/Makefile.am:
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index 6f525e6152..49b9f5c17a 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,4 +1,40 @@
-2000-12-01 <alexl@redhat.com>
+2000-11-30 Havoc Pennington <hp@pobox.com>
+
+ * gtk/gtktextdisplay.c (gtk_text_layout_draw): don't create
+ dangling pointers to the appearance attributes from the
+ line display
+
+ * gdk/gdkdraw.c (gdk_drawable_get_image): allow negative
+ width/height to mean "full width/height of drawable"
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Implement double/triple
+ click to select word/line
+
+ * gtk/gtktextiter.c (test_log_attrs): include paragraph delimiters
+ when getting log attrs. Get a slice, so that pixmaps and stuff
+ are properly handled.
+
+ * gtk/gtktextbuffer.c (paste): Fix pasting to work properly if you
+ paste into the selection (replaces selection now, previously
+ crashed or added to selection). Reveals longstanding btree bug -
+ select multiple lines, middle-click on the selection, boom. This
+ isn't related to my changes though.
+
+ * gtk/gtkentry.c (gtk_entry_move_forward_word): Update to reflect
+ PangoLogAttrs changes
+ (gtk_entry_move_backward_word): ditto
+
+ * gtk/gtktextlayout.h, gtk/gtktextlayout.c: Make the iter motion
+ functions return bool whether the iter moved onto a
+ dereferenceable position.
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Add a bunch of public
+ functions for motion in terms of display lines.
+
+ * gtk/gtktextmark.c (gtk_text_mark_get_buffer): Add function to
+ get the buffer a mark is inside
+
+2000-12-01 Alexander Larsson <alexl@redhat.com>
* gdk/linux-fb/Makefile.am:
* modules/linux-fb/Makefile.am:
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index 6f525e6152..49b9f5c17a 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,4 +1,40 @@
-2000-12-01 <alexl@redhat.com>
+2000-11-30 Havoc Pennington <hp@pobox.com>
+
+ * gtk/gtktextdisplay.c (gtk_text_layout_draw): don't create
+ dangling pointers to the appearance attributes from the
+ line display
+
+ * gdk/gdkdraw.c (gdk_drawable_get_image): allow negative
+ width/height to mean "full width/height of drawable"
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Implement double/triple
+ click to select word/line
+
+ * gtk/gtktextiter.c (test_log_attrs): include paragraph delimiters
+ when getting log attrs. Get a slice, so that pixmaps and stuff
+ are properly handled.
+
+ * gtk/gtktextbuffer.c (paste): Fix pasting to work properly if you
+ paste into the selection (replaces selection now, previously
+ crashed or added to selection). Reveals longstanding btree bug -
+ select multiple lines, middle-click on the selection, boom. This
+ isn't related to my changes though.
+
+ * gtk/gtkentry.c (gtk_entry_move_forward_word): Update to reflect
+ PangoLogAttrs changes
+ (gtk_entry_move_backward_word): ditto
+
+ * gtk/gtktextlayout.h, gtk/gtktextlayout.c: Make the iter motion
+ functions return bool whether the iter moved onto a
+ dereferenceable position.
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Add a bunch of public
+ functions for motion in terms of display lines.
+
+ * gtk/gtktextmark.c (gtk_text_mark_get_buffer): Add function to
+ get the buffer a mark is inside
+
+2000-12-01 Alexander Larsson <alexl@redhat.com>
* gdk/linux-fb/Makefile.am:
* modules/linux-fb/Makefile.am:
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index 6f525e6152..49b9f5c17a 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,4 +1,40 @@
-2000-12-01 <alexl@redhat.com>
+2000-11-30 Havoc Pennington <hp@pobox.com>
+
+ * gtk/gtktextdisplay.c (gtk_text_layout_draw): don't create
+ dangling pointers to the appearance attributes from the
+ line display
+
+ * gdk/gdkdraw.c (gdk_drawable_get_image): allow negative
+ width/height to mean "full width/height of drawable"
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Implement double/triple
+ click to select word/line
+
+ * gtk/gtktextiter.c (test_log_attrs): include paragraph delimiters
+ when getting log attrs. Get a slice, so that pixmaps and stuff
+ are properly handled.
+
+ * gtk/gtktextbuffer.c (paste): Fix pasting to work properly if you
+ paste into the selection (replaces selection now, previously
+ crashed or added to selection). Reveals longstanding btree bug -
+ select multiple lines, middle-click on the selection, boom. This
+ isn't related to my changes though.
+
+ * gtk/gtkentry.c (gtk_entry_move_forward_word): Update to reflect
+ PangoLogAttrs changes
+ (gtk_entry_move_backward_word): ditto
+
+ * gtk/gtktextlayout.h, gtk/gtktextlayout.c: Make the iter motion
+ functions return bool whether the iter moved onto a
+ dereferenceable position.
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Add a bunch of public
+ functions for motion in terms of display lines.
+
+ * gtk/gtktextmark.c (gtk_text_mark_get_buffer): Add function to
+ get the buffer a mark is inside
+
+2000-12-01 Alexander Larsson <alexl@redhat.com>
* gdk/linux-fb/Makefile.am:
* modules/linux-fb/Makefile.am:
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 6f525e6152..49b9f5c17a 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,4 +1,40 @@
-2000-12-01 <alexl@redhat.com>
+2000-11-30 Havoc Pennington <hp@pobox.com>
+
+ * gtk/gtktextdisplay.c (gtk_text_layout_draw): don't create
+ dangling pointers to the appearance attributes from the
+ line display
+
+ * gdk/gdkdraw.c (gdk_drawable_get_image): allow negative
+ width/height to mean "full width/height of drawable"
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Implement double/triple
+ click to select word/line
+
+ * gtk/gtktextiter.c (test_log_attrs): include paragraph delimiters
+ when getting log attrs. Get a slice, so that pixmaps and stuff
+ are properly handled.
+
+ * gtk/gtktextbuffer.c (paste): Fix pasting to work properly if you
+ paste into the selection (replaces selection now, previously
+ crashed or added to selection). Reveals longstanding btree bug -
+ select multiple lines, middle-click on the selection, boom. This
+ isn't related to my changes though.
+
+ * gtk/gtkentry.c (gtk_entry_move_forward_word): Update to reflect
+ PangoLogAttrs changes
+ (gtk_entry_move_backward_word): ditto
+
+ * gtk/gtktextlayout.h, gtk/gtktextlayout.c: Make the iter motion
+ functions return bool whether the iter moved onto a
+ dereferenceable position.
+
+ * gtk/gtktextview.h, gtk/gtktextview.c: Add a bunch of public
+ functions for motion in terms of display lines.
+
+ * gtk/gtktextmark.c (gtk_text_mark_get_buffer): Add function to
+ get the buffer a mark is inside
+
+2000-12-01 Alexander Larsson <alexl@redhat.com>
* gdk/linux-fb/Makefile.am:
* modules/linux-fb/Makefile.am:
diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c
index facc185e9c..fcab539e58 100644
--- a/gdk/gdkdraw.c
+++ b/gdk/gdkdraw.c
@@ -486,9 +486,12 @@ gdk_drawable_get_image (GdkDrawable *drawable,
g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (x >= 0, NULL);
g_return_val_if_fail (y >= 0, NULL);
- g_return_val_if_fail (width >= 0, NULL);
- g_return_val_if_fail (height >= 0, NULL);
+ if (width < 0 || height < 0)
+ gdk_drawable_get_size (drawable,
+ width < 0 ? &width : NULL,
+ height < 0 ? &height : NULL);
+
composite =
GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
x, y,
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 865f261b9a..45c7f05927 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -2111,20 +2111,12 @@ gtk_entry_move_forward_word (GtkEntry *entry,
gint n_attrs;
pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
-
- /* Advance over white space */
- while (new_pos < n_attrs && log_attrs[new_pos].is_white)
- new_pos++;
- /* Find the next word beginning */
+ /* Find the next word end */
new_pos++;
- while (new_pos < n_attrs && !log_attrs[new_pos].is_word_stop)
+ while (new_pos < n_attrs && !log_attrs[new_pos].is_word_end)
new_pos++;
- /* Back up over white space */
- while (new_pos > 0 && log_attrs[new_pos - 1].is_white)
- new_pos--;
-
g_free (log_attrs);
g_object_unref (G_OBJECT (layout));
}
@@ -2155,7 +2147,7 @@ gtk_entry_move_backward_word (GtkEntry *entry,
new_pos = start - 1;
/* Find the previous word beginning */
- while (new_pos > 0 && !log_attrs[new_pos].is_word_stop)
+ while (new_pos > 0 && !log_attrs[new_pos].is_word_start)
new_pos--;
g_free (log_attrs);
diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c
index 9cd8dbba9f..db770bab66 100644
--- a/gtk/gtktextbuffer.c
+++ b/gtk/gtktextbuffer.c
@@ -2172,24 +2172,40 @@ pre_paste_prep (ClipboardRequest *request_data,
GtkTextIter *insert_point)
{
GtkTextBuffer *buffer = request_data->buffer;
+
+ get_paste_point (buffer, insert_point, TRUE);
+ /* If we're going to replace the selection, we insert before it to
+ * avoid messing it up, then we delete the selection after inserting.
+ */
if (request_data->replace_selection)
{
GtkTextIter start, end;
if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+ *insert_point = start;
+ }
+}
+
+static void
+post_paste_cleanup (ClipboardRequest *request_data)
+{
+ if (request_data->replace_selection)
+ {
+ GtkTextIter start, end;
+
+ if (gtk_text_buffer_get_selection_bounds (request_data->buffer,
+ &start, &end))
{
if (request_data->interactive)
- gtk_text_buffer_delete_interactive (buffer,
+ gtk_text_buffer_delete_interactive (request_data->buffer,
&start,
&end,
request_data->default_editable);
else
- gtk_text_buffer_delete (buffer, &start, &end);
+ gtk_text_buffer_delete (request_data->buffer, &start, &end);
}
}
-
- get_paste_point (buffer, insert_point, TRUE);
}
/* Called when we request a paste and receive the text data
@@ -2214,6 +2230,8 @@ clipboard_text_received (GtkClipboard *clipboard,
else
gtk_text_buffer_insert (buffer, &insert_point,
str, -1);
+
+ post_paste_cleanup (request_data);
}
g_object_unref (G_OBJECT (buffer));
@@ -2253,6 +2271,33 @@ selection_data_get_buffer (GtkSelectionData *selection_data,
return src_buffer;
}
+#if 0
+/* These are pretty handy functions; maybe something like them
+ * should be in the public API. Also, there are other places in this
+ * file where they could be used.
+ */
+static gpointer
+save_iter (const GtkTextIter *iter,
+ gboolean left_gravity)
+{
+ return gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (iter),
+ NULL,
+ iter,
+ TRUE);
+}
+
+static void
+restore_iter (const GtkTextIter *iter,
+ gpointer save_id)
+{
+ gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (save_id),
+ (GtkTextIter*) iter,
+ save_id);
+ gtk_text_buffer_delete_mark (gtk_text_mark_get_buffer (save_id),
+ save_id);
+}
+#endif
+
static void
paste_from_buffer (ClipboardRequest *request_data,
GtkTextBuffer *src_buffer,
@@ -2274,6 +2319,8 @@ paste_from_buffer (ClipboardRequest *request_data,
end,
request_data->interactive);
}
+
+ post_paste_cleanup (request_data);
g_object_unref (G_OBJECT (src_buffer));
}
@@ -2392,13 +2439,14 @@ paste (GtkTextBuffer *buffer,
* replace the selection with the new text, otherwise, you
* simply insert the new text at the point where the click
* occured, unselecting any selected text. The replace_selection
- * flag toggles this behavior. FIXME set the flag based on something.
+ * flag toggles this behavior.
*/
data->replace_selection = FALSE;
get_paste_point (buffer, &paste_point, FALSE);
if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end) &&
- gtk_text_iter_in_range (&paste_point, &start, &end))
+ (gtk_text_iter_in_range (&paste_point, &start, &end) ||
+ gtk_text_iter_equal (&paste_point, &end)))
data->replace_selection = TRUE;
if (is_clipboard)
diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c
index e5a6d3b721..b02ade89f4 100644
--- a/gtk/gtktextdisplay.c
+++ b/gtk/gtktextdisplay.c
@@ -796,7 +796,9 @@ gtk_text_layout_draw (GtkTextLayout *layout,
current_y += line_display->height;
gtk_text_layout_free_line_display (layout, line_display);
-
+ render_state->last_appearance = NULL;
+ render_state->last_bg_appearance = NULL;
+
tmp_list = g_slist_next (tmp_list);
}
diff --git a/gtk/gtktextiter.c b/gtk/gtktextiter.c
index 1d90ceb433..d73e0a8589 100644
--- a/gtk/gtktextiter.c
+++ b/gtk/gtktextiter.c
@@ -2368,14 +2368,9 @@ find_word_end_func (PangoLogAttr *attrs,
{
++offset; /* We always go to the NEXT word end */
- /* Find start of next word */
+ /* Find end of next word */
while (offset < min_offset + len &&
- !attrs[offset].is_word_stop)
- ++offset;
-
- /* Find end */
- while (offset < min_offset + len &&
- !attrs[offset].is_white)
+ !attrs[offset].is_word_end)
++offset;
*found_offset = offset;
@@ -2384,6 +2379,16 @@ find_word_end_func (PangoLogAttr *attrs,
}
static gboolean
+is_word_end_func (PangoLogAttr *attrs,
+ gint offset,
+ gint min_offset,
+ gint len,
+ gint *found_offset)
+{
+ return attrs[offset].is_word_end;
+}
+
+static gboolean
find_word_start_func (PangoLogAttr *attrs,
gint offset,
gint min_offset,
@@ -2392,14 +2397,9 @@ find_word_start_func (PangoLogAttr *attrs,
{
--offset; /* We always go to the NEXT word start */
- /* Find end of prev word */
+ /* Find start of prev word */
while (offset >= min_offset &&
- attrs[offset].is_white)
- --offset;
-
- /* Find start */
- while (offset >= min_offset &&
- !attrs[offset].is_word_stop)
+ !attrs[offset].is_word_start)
--offset;
*found_offset = offset;
@@ -2407,31 +2407,53 @@ find_word_start_func (PangoLogAttr *attrs,
return offset >= min_offset;
}
-/* FIXME this function is very, very gratuitously slow */
static gboolean
-find_by_log_attrs (GtkTextIter *iter,
- FindLogAttrFunc func,
- gboolean forward)
+is_word_start_func (PangoLogAttr *attrs,
+ gint offset,
+ gint min_offset,
+ gint len,
+ gint *found_offset)
+{
+ return attrs[offset].is_word_start;
+}
+
+static gboolean
+inside_word_func (PangoLogAttr *attrs,
+ gint offset,
+ gint min_offset,
+ gint len,
+ gint *found_offset)
+{
+ /* Find next word start or end */
+ while (offset >= min_offset &&
+ !(attrs[offset].is_word_start || attrs[offset].is_word_end))
+ --offset;
+
+ return attrs[offset].is_word_start;
+}
+
+static gboolean
+test_log_attrs (GtkTextIter *iter,
+ FindLogAttrFunc func,
+ gint *found_offset)
{
- GtkTextIter orig;
GtkTextIter start;
GtkTextIter end;
gchar *paragraph;
gint char_len, byte_len;
PangoLogAttr *attrs;
int offset;
- gboolean found = FALSE;
+ gboolean result = FALSE;
g_return_val_if_fail (iter != NULL, FALSE);
- orig = *iter;
start = *iter;
end = *iter;
gtk_text_iter_set_line_offset (&start, 0);
- gtk_text_iter_forward_to_newline (&end);
+ gtk_text_iter_forward_line (&end);
- paragraph = gtk_text_iter_get_text (&start, &end);
+ paragraph = gtk_text_iter_get_slice (&start, &end);
char_len = g_utf8_strlen (paragraph, -1);
byte_len = strlen (paragraph);
@@ -2451,13 +2473,32 @@ find_by_log_attrs (GtkTextIter *iter,
g_free (lang);
- found = (* func) (attrs, offset, 0, char_len, &offset);
+ result = (* func) (attrs, offset, 0, char_len, found_offset);
g_free (attrs);
}
g_free (paragraph);
+ return result;
+}
+
+/* FIXME this function is very, very gratuitously slow */
+static gboolean
+find_by_log_attrs (GtkTextIter *iter,
+ FindLogAttrFunc func,
+ gboolean forward)
+{
+ GtkTextIter orig;
+ gint offset = 0;
+ gboolean found = FALSE;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ orig = *iter;
+
+ found = test_log_attrs (iter, func, &offset);
+
if (!found)
{
if (forward)
@@ -2502,7 +2543,7 @@ gtk_text_iter_backward_word_start (GtkTextIter *iter)
*/
gboolean
gtk_text_iter_forward_word_ends (GtkTextIter *iter,
- gint count)
+ gint count)
{
g_return_val_if_fail (iter != NULL, FALSE);
g_return_val_if_fail (count > 0, FALSE);
@@ -2540,6 +2581,25 @@ gtk_text_iter_backward_word_starts (GtkTextIter *iter,
return TRUE;
}
+
+gboolean
+gtk_text_iter_starts_word (const GtkTextIter *iter)
+{
+ return test_log_attrs (iter, is_word_start_func, NULL);
+}
+
+gboolean
+gtk_text_iter_ends_word (const GtkTextIter *iter)
+{
+ return test_log_attrs (iter, is_word_end_func, NULL);
+}
+
+gboolean
+gtk_text_iter_inside_word (const GtkTextIter *iter)
+{
+ return test_log_attrs (iter, inside_word_func, NULL);
+}
+
void
gtk_text_iter_set_line_offset (GtkTextIter *iter,
gint char_on_line)
diff --git a/gtk/gtktextiter.h b/gtk/gtktextiter.h
index caadecb2a2..1c32fdaeb0 100644
--- a/gtk/gtktextiter.h
+++ b/gtk/gtktextiter.h
@@ -124,6 +124,9 @@ GSList *gtk_text_iter_get_tags (const GtkTextIter *iter);
gboolean gtk_text_iter_editable (const GtkTextIter *iter,
gboolean default_setting);
+gboolean gtk_text_iter_starts_word (const GtkTextIter *iter);
+gboolean gtk_text_iter_ends_word (const GtkTextIter *iter);
+gboolean gtk_text_iter_inside_word (const GtkTextIter *iter);
gboolean gtk_text_iter_starts_line (const GtkTextIter *iter);
gboolean gtk_text_iter_ends_line (const GtkTextIter *iter);
diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c
index c43320e505..877eadc3e9 100644
--- a/gtk/gtktextlayout.c
+++ b/gtk/gtktextlayout.c
@@ -2209,7 +2209,6 @@ find_display_line_below (GtkTextLayout *layout,
while (line && !found_line)
{
GtkTextLineDisplay *display = gtk_text_layout_get_line_display (layout, line, FALSE);
- gint byte_index = 0;
PangoLayoutIter *layout_iter;
layout_iter = pango_layout_get_iter (display->layout);
@@ -2221,7 +2220,7 @@ find_display_line_below (GtkTextLayout *layout,
gint first_y, last_y;
PangoLayoutLine *layout_line = pango_layout_iter_get_line (layout_iter);
- found_byte = byte_index;
+ found_byte = layout_line->start_index;
if (line_top >= y)
{
@@ -2231,8 +2230,6 @@ find_display_line_below (GtkTextLayout *layout,
pango_layout_iter_get_line_yrange (layout_iter, &first_y, &last_y);
line_top += (last_y - first_y) / PANGO_SCALE;
-
- byte_index += layout_line->length;
}
while (pango_layout_iter_next_line (layout_iter));
@@ -2278,8 +2275,6 @@ find_display_line_above (GtkTextLayout *layout,
{
GtkTextLineDisplay *display = gtk_text_layout_get_line_display (layout, line, FALSE);
PangoRectangle logical_rect;
-
- gint byte_index = 0;
PangoLayoutIter *layout_iter;
gint tmp_top;
@@ -2296,7 +2291,7 @@ find_display_line_above (GtkTextLayout *layout,
gint first_y, last_y;
PangoLayoutLine *layout_line = pango_layout_iter_get_line (layout_iter);
- found_byte = byte_index;
+ found_byte = layout_line->start_index;
pango_layout_iter_get_line_yrange (layout_iter, &first_y, &last_y);
@@ -2305,11 +2300,8 @@ find_display_line_above (GtkTextLayout *layout,
if (tmp_top < y)
{
found_line = line;
- found_byte = byte_index;
goto done;
}
-
- byte_index += layout_line->length;
}
while (pango_layout_iter_next_line (layout_iter));
@@ -2383,7 +2375,7 @@ gtk_text_layout_clamp_iter_to_vrange (GtkTextLayout *layout,
* Move the iterator to the beginning of the previous line. The lines
* of a wrapped paragraph are treated as distinct for this operation.
**/
-void
+gboolean
gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
GtkTextIter *iter)
{
@@ -2392,11 +2384,14 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
gint line_byte;
GSList *tmp_list;
PangoLayoutLine *layout_line;
+ GtkTextIter orig;
+
+ g_return_val_if_fail (layout != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
- g_return_if_fail (layout != NULL);
- g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
- g_return_if_fail (iter != NULL);
-
+ orig = *iter;
+
line = gtk_text_iter_get_text_line (iter);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
line_byte = line_display_iter_to_index (layout, display, iter);
@@ -2410,49 +2405,49 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
if (prev_line)
{
- gint byte_offset = 0;
-
gtk_text_layout_free_line_display (layout, display);
display = gtk_text_layout_get_line_display (layout, prev_line, FALSE);
- tmp_list = pango_layout_get_lines (display->layout);
-
+ tmp_list = pango_layout_get_lines (display->layout);
+
while (tmp_list->next)
{
layout_line = tmp_list->data;
tmp_list = tmp_list->next;
-
- byte_offset += layout_line->length;
}
- line_display_index_to_iter (layout, display, iter, byte_offset, 0);
+ line_display_index_to_iter (layout, display, iter,
+ layout_line->start_index + layout_line->length, 0);
}
else
line_display_index_to_iter (layout, display, iter, 0, 0);
}
else
{
- gint prev_offset = 0;
- gint byte_offset = layout_line->length;
+ gint prev_offset = layout_line->start_index;
tmp_list = tmp_list->next;
while (tmp_list)
{
layout_line = tmp_list->data;
- if (line_byte < byte_offset + layout_line->length || !tmp_list->next)
+ if (line_byte < layout_line->start_index + layout_line->length ||
+ !tmp_list->next)
{
line_display_index_to_iter (layout, display, iter, prev_offset, 0);
break;
}
- prev_offset = byte_offset;
- byte_offset += layout_line->length;
+ prev_offset = layout_line->start_index;
tmp_list = tmp_list->next;
}
}
gtk_text_layout_free_line_display (layout, display);
+
+ return
+ !gtk_text_iter_equal (iter, &orig) &&
+ !gtk_text_iter_is_last (iter);
}
/**
@@ -2464,27 +2459,28 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
* lines of a wrapped paragraph are treated as distinct for
* this operation.
**/
-void
+gboolean
gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
GtkTextIter *iter)
{
GtkTextLine *line;
GtkTextLineDisplay *display;
gint line_byte;
-
+ GtkTextIter orig;
gboolean found = FALSE;
gboolean found_after = FALSE;
gboolean first = TRUE;
- g_return_if_fail (layout != NULL);
- g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
- g_return_if_fail (iter != NULL);
+ g_return_val_if_fail (layout != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ orig = *iter;
+
line = gtk_text_iter_get_text_line (iter);
while (line && !found_after)
{
- gint byte_offset = 0;
GSList *tmp_list;
display = gtk_text_layout_get_line_display (layout, line, FALSE);
@@ -2504,13 +2500,13 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
if (found)
{
- line_display_index_to_iter (layout, display, iter, byte_offset, 0);
+ line_display_index_to_iter (layout, display, iter,
+ layout_line->start_index, 0);
found_after = TRUE;
}
- else if (line_byte < byte_offset + layout_line->length || !tmp_list->next)
+ else if (line_byte < layout_line->start_index + layout_line->length || !tmp_list->next)
found = TRUE;
-
- byte_offset += layout_line->length;
+
tmp_list = tmp_list->next;
}
@@ -2518,6 +2514,10 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
line = gtk_text_line_next (line);
}
+
+ return
+ !gtk_text_iter_equal (iter, &orig) &&
+ !gtk_text_iter_is_last (iter);
}
/**
@@ -2528,7 +2528,7 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
*
* Move to the beginning or end of a display line.
**/
-void
+gboolean
gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
GtkTextIter *iter,
gint direction)
@@ -2536,13 +2536,15 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
GtkTextLine *line;
GtkTextLineDisplay *display;
gint line_byte;
- gint byte_offset = 0;
GSList *tmp_list;
+ GtkTextIter orig;
+
+ g_return_val_if_fail (layout != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
- g_return_if_fail (layout != NULL);
- g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
- g_return_if_fail (iter != NULL);
-
+ orig = *iter;
+
line = gtk_text_iter_get_text_line (iter);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
line_byte = line_display_iter_to_index (layout, display, iter);
@@ -2552,10 +2554,10 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
{
PangoLayoutLine *layout_line = tmp_list->data;
- if (line_byte < byte_offset + layout_line->length || !tmp_list->next)
+ if (line_byte < layout_line->start_index + layout_line->length || !tmp_list->next)
{
line_display_index_to_iter (layout, display, iter,
- direction < 0 ? byte_offset : byte_offset + layout_line->length,
+ direction < 0 ? layout_line->start_index : layout_line->start_index + layout_line->length,
0);
/* FIXME: As a bad hack, we move back one position when we
@@ -2567,12 +2569,66 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
break;
}
-
- byte_offset += layout_line->length;
+
tmp_list = tmp_list->next;
}
gtk_text_layout_free_line_display (layout, display);
+
+ return
+ !gtk_text_iter_equal (iter, &orig) &&
+ !gtk_text_iter_is_last (iter);
+}
+
+
+/**
+ * gtk_text_layout_iter_starts_line:
+ * @layout: a #GtkTextLayout
+ * @iter: iterator to test
+ *
+ * Tests whether an iterator is at the start of a display line.
+ **/
+gboolean
+gtk_text_layout_iter_starts_line (GtkTextLayout *layout,
+ const GtkTextIter *iter)
+{
+ GtkTextLine *line;
+ GtkTextLineDisplay *display;
+ gint line_byte;
+ GSList *tmp_list;
+
+ g_return_val_if_fail (layout != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ line = gtk_text_iter_get_text_line (iter);
+ display = gtk_text_layout_get_line_display (layout, line, FALSE);
+ line_byte = line_display_iter_to_index (layout, display, iter);
+
+ tmp_list = pango_layout_get_lines (display->layout);
+ while (tmp_list)
+ {
+ PangoLayoutLine *layout_line = tmp_list->data;
+
+ if (line_byte < layout_line->start_index + layout_line->length ||
+ !tmp_list->next)
+ {
+ /* We're located on this line of the para delimiters before
+ * it
+ */
+ gtk_text_layout_free_line_display (layout, display);
+
+ if (line_byte == layout_line->start_index)
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_assert_not_reached ();
+ return FALSE;
}
/**
@@ -2593,7 +2649,6 @@ gtk_text_layout_move_iter_to_x (GtkTextLayout *layout,
GtkTextLine *line;
GtkTextLineDisplay *display;
gint line_byte;
- gint byte_offset = 0;
PangoLayoutIter *layout_iter;
g_return_if_fail (layout != NULL);
@@ -2611,7 +2666,7 @@ gtk_text_layout_move_iter_to_x (GtkTextLayout *layout,
{
PangoLayoutLine *layout_line = pango_layout_iter_get_line (layout_iter);
- if (line_byte < byte_offset + layout_line->length ||
+ if (line_byte < layout_line->start_index + layout_line->length ||
pango_layout_iter_at_last_line (layout_iter))
{
PangoRectangle logical_rect;
@@ -2628,8 +2683,6 @@ gtk_text_layout_move_iter_to_x (GtkTextLayout *layout,
break;
}
-
- byte_offset += layout_line->length;
}
while (pango_layout_iter_next_line (layout_iter));
@@ -2657,16 +2710,19 @@ gtk_text_layout_move_iter_to_x (GtkTextLayout *layout,
* is moved off of the end of a run.
**/
-void
+gboolean
gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
GtkTextIter *iter,
gint count)
{
GtkTextLineDisplay *display = NULL;
+ GtkTextIter orig;
+
+ g_return_val_if_fail (layout != NULL, FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
- g_return_if_fail (layout != NULL);
- g_return_if_fail (iter != NULL);
-
+ orig = *iter;
+
while (count != 0)
{
GtkTextLine *line = gtk_text_iter_get_text_line (iter);
@@ -2715,8 +2771,8 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
line = gtk_text_line_previous (line);
if (!line)
- return;
-
+ goto done;
+
gtk_text_layout_free_line_display (layout, display);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
new_index = gtk_text_line_byte_count (line);
@@ -2725,7 +2781,7 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
{
line = gtk_text_line_next (line);
if (!line)
- return;
+ goto done;
gtk_text_layout_free_line_display (layout, display);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
@@ -2738,6 +2794,12 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
}
gtk_text_layout_free_line_display (layout, display);
+
+ done:
+
+ return
+ !gtk_text_iter_equal (iter, &orig) &&
+ !gtk_text_iter_is_last (iter);
}
void
diff --git a/gtk/gtktextlayout.h b/gtk/gtktextlayout.h
index 81e8824f01..8977a97eb7 100644
--- a/gtk/gtktextlayout.h
+++ b/gtk/gtktextlayout.h
@@ -339,20 +339,22 @@ gboolean gtk_text_layout_clamp_iter_to_vrange (GtkTextLayout *layout,
gint top,
gint bottom);
-void gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
- GtkTextIter *iter,
- gint direction);
-void gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
- GtkTextIter *iter);
-void gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
- GtkTextIter *iter);
-void gtk_text_layout_move_iter_to_x (GtkTextLayout *layout,
- GtkTextIter *iter,
- gint x);
-void gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
- GtkTextIter *iter,
- gint count);
-
+gboolean gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
+ GtkTextIter *iter,
+ gint direction);
+gboolean gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
+ GtkTextIter *iter);
+gboolean gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
+ GtkTextIter *iter);
+void gtk_text_layout_move_iter_to_x (GtkTextLayout *layout,
+ GtkTextIter *iter,
+ gint x);
+gboolean gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
+ GtkTextIter *iter,
+ gint count);
+
+gboolean gtk_text_layout_iter_starts_line (GtkTextLayout *layout,
+ const GtkTextIter *iter);
/* Don't use these. Use gtk_text_view_add_child_at_anchor().
* These functions are defined in gtktextchild.c, but here
diff --git a/gtk/gtktextmark.c b/gtk/gtktextmark.c
index 4e20eb300c..e18ea3295e 100644
--- a/gtk/gtktextmark.c
+++ b/gtk/gtktextmark.c
@@ -179,7 +179,7 @@ gtk_text_mark_get_deleted (GtkTextMark *mark)
{
GtkTextLineSegment *seg;
- g_return_val_if_fail (mark != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
seg = mark->segment;
@@ -189,6 +189,30 @@ gtk_text_mark_get_deleted (GtkTextMark *mark)
return seg->body.mark.tree == NULL;
}
+/**
+ * gtk_text_mark_get_buffer:
+ * @mark: a #GtkTextMark
+ *
+ * Gets the buffer this mark is located inside,
+ * or NULL if the mark is deleted.
+ *
+ * Return value: the mark's #GtkTextBuffer
+ **/
+GtkTextBuffer*
+gtk_text_mark_get_buffer (GtkTextMark *mark)
+{
+ GtkTextLineSegment *seg;
+
+ g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
+
+ seg = mark->segment;
+
+ if (seg->body.mark.tree == NULL)
+ return NULL;
+ else
+ return gtk_text_btree_get_buffer (seg->body.mark.tree);
+}
+
/*
* Macro that determines the size of a mark segment:
*/
diff --git a/gtk/gtktextmark.h b/gtk/gtktextmark.h
index e2130c5acd..3b2d0fc9aa 100644
--- a/gtk/gtktextmark.h
+++ b/gtk/gtktextmark.h
@@ -81,12 +81,14 @@ struct _GtkTextMarkClass
GType gtk_text_mark_get_type (void) G_GNUC_CONST;
-void gtk_text_mark_set_visible (GtkTextMark *mark,
- gboolean setting);
-gboolean gtk_text_mark_get_visible (GtkTextMark *mark);
+void gtk_text_mark_set_visible (GtkTextMark *mark,
+ gboolean setting);
+gboolean gtk_text_mark_get_visible (GtkTextMark *mark);
+
/* FIXME gconst */
-const char *gtk_text_mark_get_name (GtkTextMark *mark);
-gboolean gtk_text_mark_get_deleted (GtkTextMark *mark);
+const char * gtk_text_mark_get_name (GtkTextMark *mark);
+gboolean gtk_text_mark_get_deleted (GtkTextMark *mark);
+GtkTextBuffer* gtk_text_mark_get_buffer (GtkTextMark *mark);
#ifdef __cplusplus
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 489a04e037..78ac46a6aa 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -2637,7 +2637,69 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
gtk_text_view_popup_menu (text_view, event);
}
}
+ else if ((event->type == GDK_2BUTTON_PRESS ||
+ event->type == GDK_3BUTTON_PRESS) &&
+ event->button == 1)
+ {
+ GtkTextIter start, end;
+
+ /* End the selection drag, otherwise we'd clear the new
+ * word/line selection on button release
+ */
+ gtk_text_view_end_selection_drag (text_view, event);
+
+ gtk_text_layout_get_iter_at_pixel (text_view->layout,
+ &start,
+ event->x + text_view->xoffset,
+ event->y + text_view->yoffset);
+ end = start;
+
+ if (event->type == GDK_2BUTTON_PRESS)
+ {
+ if (gtk_text_iter_inside_word (&start))
+ {
+ if (!gtk_text_iter_starts_word (&start))
+ gtk_text_iter_backward_word_start (&start);
+
+ if (!gtk_text_iter_ends_word (&end))
+ gtk_text_iter_forward_word_end (&end);
+ }
+ }
+ else if (event->type == GDK_3BUTTON_PRESS)
+ {
+ if (gtk_text_view_starts_display_line (text_view, &start))
+ {
+ /* If on a display line boundary, we assume the user
+ * clicked off the end of a line and we therefore select
+ * the line before the boundary.
+ */
+ gtk_text_view_backward_display_line_start (text_view, &start);
+ }
+ else
+ {
+ /* start isn't on the start of a line, so we move it to the
+ * start, and move end to the end unless it's already there.
+ */
+ gtk_text_view_backward_display_line_start (text_view, &start);
+
+ if (!gtk_text_view_starts_display_line (text_view, &end))
+ gtk_text_view_forward_display_line_end (text_view, &end);
+ }
+ }
+
+ gtk_text_buffer_move_mark (get_buffer (text_view),
+ gtk_text_buffer_get_selection_bound (get_buffer (text_view)),
+ &start);
+ gtk_text_buffer_move_mark (get_buffer (text_view),
+ gtk_text_buffer_get_insert (get_buffer (text_view)),
+ &end);
+
+ text_view->just_selected_element = TRUE;
+
+ return TRUE;
+ }
+
return FALSE;
}
@@ -2661,6 +2723,11 @@ gtk_text_view_button_release_event (GtkWidget *widget, GdkEventButton *event)
if (gtk_text_view_end_selection_drag (GTK_TEXT_VIEW (widget), event))
return TRUE;
+ else if (text_view->just_selected_element)
+ {
+ text_view->just_selected_element = FALSE;
+ return FALSE;
+ }
else
{
/* Unselect everything; probably we were dragging, or clicked
@@ -5457,3 +5524,80 @@ gtk_text_view_move_child (GtkTextView *text_view,
}
+
+/* Iterator operations */
+
+gboolean
+gtk_text_view_forward_display_line (GtkTextView *text_view,
+ GtkTextIter *iter)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ gtk_text_view_ensure_layout (text_view);
+
+ return gtk_text_layout_move_iter_to_next_line (text_view->layout, iter);
+}
+
+gboolean
+gtk_text_view_backward_display_line (GtkTextView *text_view,
+ GtkTextIter *iter)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ gtk_text_view_ensure_layout (text_view);
+
+ return gtk_text_layout_move_iter_to_previous_line (text_view->layout, iter);
+}
+
+gboolean
+gtk_text_view_forward_display_line_end (GtkTextView *text_view,
+ GtkTextIter *iter)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ gtk_text_view_ensure_layout (text_view);
+
+ return gtk_text_layout_move_iter_to_line_end (text_view->layout, iter, 1);
+}
+
+gboolean
+gtk_text_view_backward_display_line_start (GtkTextView *text_view,
+ GtkTextIter *iter)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ gtk_text_view_ensure_layout (text_view);
+
+ return gtk_text_layout_move_iter_to_line_end (text_view->layout, iter, -1);
+}
+
+gboolean
+gtk_text_view_starts_display_line (GtkTextView *text_view,
+ const GtkTextIter *iter)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ gtk_text_view_ensure_layout (text_view);
+
+ return gtk_text_layout_iter_starts_line (text_view->layout, iter);
+}
+
+gboolean
+gtk_text_view_move_visually (GtkTextView *text_view,
+ GtkTextIter *iter,
+ gint count)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ gtk_text_view_ensure_layout (text_view);
+
+ return gtk_text_layout_move_iter_visually (text_view->layout, iter, count);
+}
+
+
diff --git a/gtk/gtktextview.h b/gtk/gtktextview.h
index 880cff302e..edcc8f2870 100644
--- a/gtk/gtktextview.h
+++ b/gtk/gtktextview.h
@@ -87,7 +87,9 @@ struct _GtkTextView
guint overwrite_mode : 1;
guint cursor_visible : 1;
guint need_im_reset : 1; /* If we have reset the IM since the last character entered */
-
+ /* just selected a word or line via double/triple click */
+ guint just_selected_element : 1;
+
GtkTextWindow *text_window;
GtkTextWindow *left_window;
GtkTextWindow *right_window;
@@ -226,6 +228,19 @@ void gtk_text_view_set_text_window_size (GtkTextView *text_view,
gint width,
gint height);
+gboolean gtk_text_view_forward_display_line (GtkTextView *text_view,
+ GtkTextIter *iter);
+gboolean gtk_text_view_backward_display_line (GtkTextView *text_view,
+ GtkTextIter *iter);
+gboolean gtk_text_view_forward_display_line_end (GtkTextView *text_view,
+ GtkTextIter *iter);
+gboolean gtk_text_view_backward_display_line_start (GtkTextView *text_view,
+ GtkTextIter *iter);
+gboolean gtk_text_view_starts_display_line (GtkTextView *text_view,
+ const GtkTextIter *iter);
+gboolean gtk_text_view_move_visually (GtkTextView *text_view,
+ GtkTextIter *iter,
+ gint count);
/* Adding child widgets */
void gtk_text_view_add_child_at_anchor (GtkTextView *text_view,