diff options
author | Havoc Pennington <hp@redhat.com> | 2000-11-07 21:01:02 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2000-11-07 21:01:02 +0000 |
commit | f1de9df0511db6e82ee12c8e7f78d68d7a31cbbe (patch) | |
tree | e7c7ec7be138908bef2c5395d50ab6710f86f6d9 | |
parent | 163dc54dea828d41fe12eb762c730e57444d63f3 (diff) | |
download | gtk+-f1de9df0511db6e82ee12c8e7f78d68d7a31cbbe.tar.gz |
rename to gtk_text_mark_get_visible
2000-11-07 Havoc Pennington <hp@redhat.com>
* gtk/gtktextmark.c (gtk_text_mark_is_visible): rename
to gtk_text_mark_get_visible
* gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix
bug that was generating an invalid iterator
* gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to
ensure_char_offsets() in front of code placing the iter in an
invalid state.
* gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary):
make override_location arg const
(paste): Replace the selection if we paste into the
current selection
* gtk/gtkselection.h: Remove "GtkSelectioData"
(struct _GtkSelectionData): move the definition here.
* gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection):
Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies
* gtk/gtktextiter.c (gtk_text_iter_get_tags): New function
* gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement
(gtk_text_buffer_insert_range_interactive): implement
(gtk_text_buffer_get_tags): Remove, replaced by
gtk_text_iter_get_tags()
* gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search
limit parameter, to avoid infinite linear scan.
(gtk_text_iter_backward_search): Add search limit
(gtk_text_iter_forward_find_char): Add search limit
(gtk_text_iter_backward_find_char): Add search limit
-rw-r--r-- | ChangeLog | 36 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 36 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 36 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 36 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 36 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 36 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 36 | ||||
-rw-r--r-- | gtk/gtkselection.c | 2 | ||||
-rw-r--r-- | gtk/gtkselection.h | 26 | ||||
-rw-r--r-- | gtk/gtktextbtree.c | 32 | ||||
-rw-r--r-- | gtk/gtktextbuffer.c | 621 | ||||
-rw-r--r-- | gtk/gtktextbuffer.h | 10 | ||||
-rw-r--r-- | gtk/gtktextiter.c | 249 | ||||
-rw-r--r-- | gtk/gtktextiter.h | 29 | ||||
-rw-r--r-- | gtk/gtktextlayout.c | 2 | ||||
-rw-r--r-- | gtk/gtktextmark.c | 4 | ||||
-rw-r--r-- | gtk/gtktextmark.h | 2 | ||||
-rw-r--r-- | gtk/gtktextsegment.c | 3 | ||||
-rw-r--r-- | gtk/gtktextview.c | 8 | ||||
-rw-r--r-- | gtk/gtkwidget.h | 19 | ||||
-rw-r--r-- | gtk/testtext.c | 6 | ||||
-rw-r--r-- | tests/testtext.c | 6 |
22 files changed, 1059 insertions, 212 deletions
@@ -1,3 +1,39 @@ +2000-11-07 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename + to gtk_text_mark_get_visible + + * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix + bug that was generating an invalid iterator + + * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to + ensure_char_offsets() in front of code placing the iter in an + invalid state. + + * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary): + make override_location arg const + (paste): Replace the selection if we paste into the + current selection + + * gtk/gtkselection.h: Remove "GtkSelectioData" + (struct _GtkSelectionData): move the definition here. + + * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection): + Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies + + * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function + + * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement + (gtk_text_buffer_insert_range_interactive): implement + (gtk_text_buffer_get_tags): Remove, replaced by + gtk_text_iter_get_tags() + + * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search + limit parameter, to avoid infinite linear scan. + (gtk_text_iter_backward_search): Add search limit + (gtk_text_iter_forward_find_char): Add search limit + (gtk_text_iter_backward_find_char): Add search limit + 2000-11-07 Alexander Larsson <alla@lysator.liu.se> * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c, diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 66126a253a..9547e7dae9 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,39 @@ +2000-11-07 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename + to gtk_text_mark_get_visible + + * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix + bug that was generating an invalid iterator + + * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to + ensure_char_offsets() in front of code placing the iter in an + invalid state. + + * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary): + make override_location arg const + (paste): Replace the selection if we paste into the + current selection + + * gtk/gtkselection.h: Remove "GtkSelectioData" + (struct _GtkSelectionData): move the definition here. + + * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection): + Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies + + * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function + + * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement + (gtk_text_buffer_insert_range_interactive): implement + (gtk_text_buffer_get_tags): Remove, replaced by + gtk_text_iter_get_tags() + + * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search + limit parameter, to avoid infinite linear scan. + (gtk_text_iter_backward_search): Add search limit + (gtk_text_iter_forward_find_char): Add search limit + (gtk_text_iter_backward_find_char): Add search limit + 2000-11-07 Alexander Larsson <alla@lysator.liu.se> * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 66126a253a..9547e7dae9 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,39 @@ +2000-11-07 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename + to gtk_text_mark_get_visible + + * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix + bug that was generating an invalid iterator + + * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to + ensure_char_offsets() in front of code placing the iter in an + invalid state. + + * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary): + make override_location arg const + (paste): Replace the selection if we paste into the + current selection + + * gtk/gtkselection.h: Remove "GtkSelectioData" + (struct _GtkSelectionData): move the definition here. + + * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection): + Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies + + * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function + + * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement + (gtk_text_buffer_insert_range_interactive): implement + (gtk_text_buffer_get_tags): Remove, replaced by + gtk_text_iter_get_tags() + + * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search + limit parameter, to avoid infinite linear scan. + (gtk_text_iter_backward_search): Add search limit + (gtk_text_iter_forward_find_char): Add search limit + (gtk_text_iter_backward_find_char): Add search limit + 2000-11-07 Alexander Larsson <alla@lysator.liu.se> * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c, diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 66126a253a..9547e7dae9 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,39 @@ +2000-11-07 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename + to gtk_text_mark_get_visible + + * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix + bug that was generating an invalid iterator + + * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to + ensure_char_offsets() in front of code placing the iter in an + invalid state. + + * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary): + make override_location arg const + (paste): Replace the selection if we paste into the + current selection + + * gtk/gtkselection.h: Remove "GtkSelectioData" + (struct _GtkSelectionData): move the definition here. + + * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection): + Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies + + * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function + + * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement + (gtk_text_buffer_insert_range_interactive): implement + (gtk_text_buffer_get_tags): Remove, replaced by + gtk_text_iter_get_tags() + + * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search + limit parameter, to avoid infinite linear scan. + (gtk_text_iter_backward_search): Add search limit + (gtk_text_iter_forward_find_char): Add search limit + (gtk_text_iter_backward_find_char): Add search limit + 2000-11-07 Alexander Larsson <alla@lysator.liu.se> * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c, diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 66126a253a..9547e7dae9 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,39 @@ +2000-11-07 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename + to gtk_text_mark_get_visible + + * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix + bug that was generating an invalid iterator + + * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to + ensure_char_offsets() in front of code placing the iter in an + invalid state. + + * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary): + make override_location arg const + (paste): Replace the selection if we paste into the + current selection + + * gtk/gtkselection.h: Remove "GtkSelectioData" + (struct _GtkSelectionData): move the definition here. + + * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection): + Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies + + * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function + + * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement + (gtk_text_buffer_insert_range_interactive): implement + (gtk_text_buffer_get_tags): Remove, replaced by + gtk_text_iter_get_tags() + + * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search + limit parameter, to avoid infinite linear scan. + (gtk_text_iter_backward_search): Add search limit + (gtk_text_iter_forward_find_char): Add search limit + (gtk_text_iter_backward_find_char): Add search limit + 2000-11-07 Alexander Larsson <alla@lysator.liu.se> * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c, diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 66126a253a..9547e7dae9 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,39 @@ +2000-11-07 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename + to gtk_text_mark_get_visible + + * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix + bug that was generating an invalid iterator + + * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to + ensure_char_offsets() in front of code placing the iter in an + invalid state. + + * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary): + make override_location arg const + (paste): Replace the selection if we paste into the + current selection + + * gtk/gtkselection.h: Remove "GtkSelectioData" + (struct _GtkSelectionData): move the definition here. + + * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection): + Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies + + * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function + + * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement + (gtk_text_buffer_insert_range_interactive): implement + (gtk_text_buffer_get_tags): Remove, replaced by + gtk_text_iter_get_tags() + + * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search + limit parameter, to avoid infinite linear scan. + (gtk_text_iter_backward_search): Add search limit + (gtk_text_iter_forward_find_char): Add search limit + (gtk_text_iter_backward_find_char): Add search limit + 2000-11-07 Alexander Larsson <alla@lysator.liu.se> * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c, diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 66126a253a..9547e7dae9 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,39 @@ +2000-11-07 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextmark.c (gtk_text_mark_is_visible): rename + to gtk_text_mark_get_visible + + * gtk/gtktextlayout.c (gtk_text_layout_move_iter_to_line_end): fix + bug that was generating an invalid iterator + + * gtk/gtktextiter.c (gtk_text_iter_get_offset): move call to + ensure_char_offsets() in front of code placing the iter in an + invalid state. + + * gtk/gtktextbuffer.c (gtk_text_buffer_paste_primary): + make override_location arg const + (paste): Replace the selection if we paste into the + current selection + + * gtk/gtkselection.h: Remove "GtkSelectioData" + (struct _GtkSelectionData): move the definition here. + + * gtk/gtktextbuffer.c (gtk_text_buffer_update_primary_selection): + Export the GTK_TEXT_BUFFER_CONTENTS target for in-process copies + + * gtk/gtktextiter.c (gtk_text_iter_get_tags): New function + + * gtk/gtktextbuffer.c (gtk_text_buffer_insert_range): implement + (gtk_text_buffer_insert_range_interactive): implement + (gtk_text_buffer_get_tags): Remove, replaced by + gtk_text_iter_get_tags() + + * gtk/gtktextiter.c (gtk_text_iter_forward_search): Add a search + limit parameter, to avoid infinite linear scan. + (gtk_text_iter_backward_search): Add search limit + (gtk_text_iter_forward_find_char): Add search limit + (gtk_text_iter_backward_find_char): Add search limit + 2000-11-07 Alexander Larsson <alla@lysator.liu.se> * gdk/linux-fb/gdkcolor-fb.c, gdk/linux-fb/gdkdnd-fb.c, diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c index e09da3d65e..fdfb1aa157 100644 --- a/gtk/gtkselection.c +++ b/gtk/gtkselection.c @@ -1720,7 +1720,7 @@ gtk_selection_default_handler (GtkWidget *widget, } -GtkSelectioData* +GtkSelectionData* gtk_selection_data_copy (GtkSelectionData *selection_data) { GtkSelectionData *new_data; diff --git a/gtk/gtkselection.h b/gtk/gtkselection.h index 668fec4b3a..4c109d5531 100644 --- a/gtk/gtkselection.h +++ b/gtk/gtkselection.h @@ -36,10 +36,30 @@ extern "C" { #endif /* __cplusplus */ -typedef struct _GtkSelectionData GtkSelectioData; typedef struct _GtkTargetList GtkTargetList; typedef struct _GtkTargetEntry GtkTargetEntry; +/* The contents of a selection are returned in a GtkSelectionData + * structure. selection/target identify the request. type specifies + * the type of the return; if length < 0, and the data should be + * ignored. This structure has object semantics - no fields should be + * modified directly, they should not be created directly, and + * pointers to them should not be stored beyond the duration of a + * callback. (If the last is changed, we'll need to add reference + * counting.) The time field gives the timestamp at which the data was + * sent. + */ + +struct _GtkSelectionData +{ + GdkAtom selection; + GdkAtom target; + GdkAtom type; + gint format; + guchar *data; + gint length; +}; + struct _GtkTargetEntry { gchar *target; guint flags; @@ -125,8 +145,8 @@ gint gtk_selection_notify (GtkWidget *widget, GdkEventSelection *event); gint gtk_selection_property_notify (GtkWidget *widget, GdkEventProperty *event); -GtkSelectioData *gtk_selection_data_copy (GtkSelectionData *data); -void gtk_selection_data_free (GtkSelectionData *data); +GtkSelectionData *gtk_selection_data_copy (GtkSelectionData *data); +void gtk_selection_data_free (GtkSelectionData *data); diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index b73ba456c6..8654c29235 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -2435,13 +2435,13 @@ ensure_not_off_end (GtkTextBTree *tree, } static GtkTextLineSegment* -real_set_mark (GtkTextBTree *tree, - GtkTextMark *existing_mark, - const gchar *name, - gboolean left_gravity, +real_set_mark (GtkTextBTree *tree, + GtkTextMark *existing_mark, + const gchar *name, + gboolean left_gravity, const GtkTextIter *where, - gboolean should_exist, - gboolean redraw_selections) + gboolean should_exist, + gboolean redraw_selections) { GtkTextLineSegment *mark; GtkTextIter iter; @@ -2465,10 +2465,14 @@ real_set_mark (GtkTextBTree *tree, } /* OK if !should_exist and it does already exist, in that case - we just move it. */ - + * we just move it. + */ + iter = *where; + if (gtk_debug_flags & GTK_DEBUG_TEXT) + gtk_text_iter_check (&iter); + if (mark != NULL) { if (redraw_selections && @@ -2519,6 +2523,9 @@ real_set_mark (GtkTextBTree *tree, mark); } + if (gtk_debug_flags & GTK_DEBUG_TEXT) + gtk_text_iter_check (&iter); + /* Link mark into new location */ gtk_text_btree_link_segment (mark, &iter); @@ -2531,6 +2538,12 @@ real_set_mark (GtkTextBTree *tree, redisplay_mark_if_visible (mark); + if (gtk_debug_flags & GTK_DEBUG_TEXT) + gtk_text_iter_check (&iter); + + if (gtk_debug_flags & GTK_DEBUG_TEXT) + gtk_text_btree_check (tree); + return mark; } @@ -3716,7 +3729,8 @@ gtk_text_line_byte_to_char_offsets (GtkTextLine *line, g_assert (seg->char_count > 0); /* indexable. */ /* offset is now the number of bytes into the current segment we - want to go. Count chars into the current segment. */ + * want to go. Count chars into the current segment. + */ if (seg->type == >k_text_char_type) { diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index c3fcf25e17..b48629e667 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -43,6 +43,7 @@ struct _ClipboardRequest gboolean interactive; gboolean default_editable; gboolean is_clipboard; + gboolean replace_selection; }; enum { @@ -66,7 +67,8 @@ enum { TARGET_STRING, TARGET_TEXT, TARGET_COMPOUND_TEXT, - TARGET_UTF8_STRING + TARGET_UTF8_STRING, + TARGET_TEXT_BUFFER_CONTENTS }; static void gtk_text_buffer_init (GtkTextBuffer *tkxt_buffer); @@ -494,6 +496,10 @@ gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer, * want to prevent insertions at ineditable locations if the insertion * results from a user action (is interactive). * + * @default_editable indicates the editability of text that doesn't + * have a tag affecting editability applied to it. Typically the + * result of gtk_text_view_get_editable() is appropriate here. + * * Return value: whether text was actually inserted **/ gboolean @@ -525,6 +531,10 @@ gtk_text_buffer_insert_interactive (GtkTextBuffer *buffer, * Calls gtk_text_buffer_insert_interactive () at the cursor * position. * + * @default_editable indicates the editability of text that doesn't + * have a tag affecting editability applied to it. Typically the + * result of gtk_text_view_get_editable() is appropriate here. + * * Return value: whether text was actually inserted **/ gboolean @@ -546,6 +556,301 @@ gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buffer, default_editable); } +static gboolean +possibly_not_text (gunichar ch, + gpointer user_data) +{ + return ch == 0xFFFD; +} + +static void +insert_text_range (GtkTextBuffer *buffer, + GtkTextIter *iter, + const GtkTextIter *orig_start, + const GtkTextIter *orig_end, + gboolean interactive) +{ + gchar *text; + + text = gtk_text_iter_get_text (orig_start, orig_end); + + gtk_text_buffer_emit_insert (buffer, iter, text, -1, interactive); + + g_free (text); +} + +typedef struct _Range Range; +struct _Range +{ + GtkTextBuffer *buffer; + GtkTextMark *start_mark; + GtkTextMark *end_mark; + GtkTextMark *whole_end_mark; + GtkTextIter *range_start; + GtkTextIter *range_end; + GtkTextIter *whole_end; +}; + +static Range* +save_range (GtkTextIter *range_start, + GtkTextIter *range_end, + GtkTextIter *whole_end) +{ + Range *r; + + r = g_new (Range, 1); + + r->buffer = gtk_text_iter_get_buffer (range_start); + g_object_ref (G_OBJECT (r->buffer)); + + r->start_mark = + gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start), + NULL, + range_start, + TRUE); + r->end_mark = + gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start), + NULL, + range_end, + FALSE); + + r->whole_end_mark = + gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start), + NULL, + whole_end, + FALSE); + + r->range_start = range_start; + r->range_end = range_end; + r->whole_end = whole_end; + + return r; +} + +static void +restore_range (Range *r) +{ + gtk_text_buffer_get_iter_at_mark (r->buffer, + r->range_start, + r->start_mark); + + gtk_text_buffer_get_iter_at_mark (r->buffer, + r->range_end, + r->end_mark); + + gtk_text_buffer_get_iter_at_mark (r->buffer, + r->whole_end, + r->whole_end_mark); + + gtk_text_buffer_delete_mark (r->buffer, r->start_mark); + gtk_text_buffer_delete_mark (r->buffer, r->end_mark); + gtk_text_buffer_delete_mark (r->buffer, r->whole_end_mark); + + g_object_unref (G_OBJECT (r->buffer)); + g_free (r); +} + +static void +insert_range_untagged (GtkTextBuffer *buffer, + GtkTextIter *iter, + const GtkTextIter *orig_start, + const GtkTextIter *orig_end, + gboolean interactive) +{ + GtkTextIter range_start; + GtkTextIter range_end; + GtkTextIter start, end; + GtkTextBuffer *src_buffer; + Range *r; + + if (gtk_text_iter_equal (orig_start, orig_end)) + return; + + start = *orig_start; + end = *orig_end; + + src_buffer = gtk_text_iter_get_buffer (&start); + + range_start = start; + range_end = start; + + while (TRUE) + { + if (gtk_text_iter_equal (&range_start, &range_end)) + { + /* Figure out how to move forward */ + + g_assert (gtk_text_iter_compare (&range_end, &end) <= 0); + + if (gtk_text_iter_equal (&range_end, &end)) + { + /* nothing left to do */ + break; + } + else if (gtk_text_iter_get_char (&range_end) == 0xFFFD) + { + GdkPixbuf *pixbuf = NULL; + GtkTextChildAnchor *anchor = NULL; + pixbuf = gtk_text_iter_get_pixbuf (&range_end); + anchor = gtk_text_iter_get_child_anchor (&range_end); + + if (pixbuf) + { + r = save_range (&range_start, + &range_end, + &end); + + gtk_text_buffer_insert_pixbuf (buffer, + iter, + pixbuf); + + restore_range (r); + r = NULL; + + gtk_text_iter_next_char (&range_end); + + range_start = range_end; + } + else if (anchor) + { + /* Just skip anchors */ + + gtk_text_iter_next_char (&range_end); + range_start = range_end; + } + else + { + /* The 0xFFFD was in a text segment, so + * keep going. + */ + gtk_text_iter_forward_find_char (&range_end, + possibly_not_text, NULL, + &end); + + g_assert (gtk_text_iter_compare (&range_end, &end) <= 0); + } + } + else + { + /* Text segment starts here, so forward search to + * find its possible endpoint + */ + gtk_text_iter_forward_find_char (&range_end, + possibly_not_text, NULL, + &end); + + g_assert (gtk_text_iter_compare (&range_end, &end) <= 0); + } + } + else + { + r = save_range (&range_start, + &range_end, + &end); + + insert_text_range (buffer, + iter, + &range_start, + &range_end, + interactive); + + restore_range (r); + r = NULL; + + range_start = range_end; + } + } +} + +static void +gtk_text_buffer_real_insert_range (GtkTextBuffer *buffer, + GtkTextIter *iter, + const GtkTextIter *orig_start, + const GtkTextIter *orig_end, + gboolean interactive) +{ + /* Find each range of uniformly-tagged text, insert it, + * then apply the tags. + */ + GtkTextIter start = *orig_start; + GtkTextIter end = *orig_end; + GtkTextIter range_start; + GtkTextIter range_end; + GtkTextBuffer *src_buffer; + Range *r; + + if (gtk_text_iter_equal (orig_start, orig_end)) + return; + + src_buffer = gtk_text_iter_get_buffer (orig_start); + + gtk_text_iter_reorder (&start, &end); + + range_start = start; + range_end = start; + + while (TRUE) + { + gint start_offset; + GtkTextIter start_iter; + GSList *tags; + GSList *tmp_list; + + gtk_text_iter_spew (&range_start, "range_start"); + gtk_text_iter_spew (&range_end, "range_end"); + gtk_text_iter_spew (&end, "end"); + + if (gtk_text_iter_equal (&range_start, &end)) + break; /* All done */ + + g_assert (gtk_text_iter_compare (&range_start, &end) < 0); + + gtk_text_iter_forward_to_tag_toggle (&range_end, NULL); + + g_assert (!gtk_text_iter_equal (&range_start, &range_end)); + + /* Clamp to the end iterator */ + if (gtk_text_iter_compare (&range_end, &end) > 0) + range_end = end; + + /* We have a range with unique tags; insert it, and + * apply all tags. + */ + start_offset = gtk_text_iter_get_offset (iter); + + r = save_range (&range_start, &range_end, &end); + + printf ("Source range is %d to %d\n", + gtk_text_iter_get_offset (&range_start), + gtk_text_iter_get_offset (&range_end)); + + insert_range_untagged (buffer, iter, &range_start, &range_end, interactive); + + restore_range (r); + r = NULL; + + gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_offset); + + printf ("Dest range is %d to %d\n", + gtk_text_iter_get_offset (&start_iter), + gtk_text_iter_get_offset (iter)); + + tags = gtk_text_iter_get_tags (&range_start); + tmp_list = tags; + while (tmp_list != NULL) + { + gtk_text_buffer_apply_tag (buffer, + tmp_list->data, + &start_iter, + iter); + + tmp_list = g_slist_next (tmp_list); + } + g_slist_free (tags); + + range_start = range_end; + } +} /** * gtk_text_buffer_insert_range: @@ -576,11 +881,27 @@ gtk_text_buffer_insert_range (GtkTextBuffer *buffer, g_return_if_fail (gtk_text_iter_get_buffer (start) != gtk_text_iter_get_buffer (end)); g_return_if_fail (gtk_text_iter_get_buffer (start)->tag_table != - buffer->tag_table); + buffer->tag_table); - /* FIXME */ + gtk_text_buffer_real_insert_range (buffer, iter, start, end, FALSE); } +/** + * gtk_text_buffer_insert_range_interactive: + * @buffer: a #GtkTextBuffer + * @iter: a position in @buffer + * @start: a position in a #GtkTextBuffer + * @end: another position in the same buffer as @start + * @default_editable: default editability of the buffer + * + * Same as gtk_text_buffer_insert_range(), but does nothing if the + * insertion point isn't editable. The @default_editable parameter + * indicates whether the text is editable at @iter if no tags + * enclosing @iter affect editability. Typically the result of + * gtk_text_view_get_editable() is appropriate here. + * + * Returns: whether an insertion was possible at @iter + **/ gboolean gtk_text_buffer_insert_range_interactive (GtkTextBuffer *buffer, GtkTextIter *iter, @@ -598,9 +919,13 @@ gtk_text_buffer_insert_range_interactive (GtkTextBuffer *buffer, buffer->tag_table, FALSE); - /* FIXME */ - - return FALSE; + if (gtk_text_iter_editable (iter, default_editable)) + { + gtk_text_buffer_real_insert_range (buffer, iter, start, end, TRUE); + return TRUE; + } + else + return FALSE; } /** @@ -981,7 +1306,9 @@ gtk_text_buffer_get_text (GtkTextBuffer *buffer, * embedded images, so byte and character indexes into * the returned string <emphasis>do</emphasis> correspond to byte * and character indexes into the buffer. Contrast with - * gtk_text_buffer_get_text (). + * gtk_text_buffer_get_text (). Note that 0xFFFD can occur in normal + * text as well, so it is not a reliable indicator that a pixbuf or + * widget is in the buffer. * * Return value: an allocated UTF-8 string **/ @@ -1707,38 +2034,6 @@ gtk_text_buffer_get_char_count (GtkTextBuffer *buffer) return gtk_text_btree_char_count (get_btree (buffer)); } -GSList* -gtk_text_buffer_get_tags (GtkTextBuffer *buffer, - const GtkTextIter *iter) -{ - GSList *retval = NULL; - GtkTextTag** tags; - gint count = 0; - - tags = gtk_text_btree_get_tags (iter, &count); - - if (count > 0) - { - gint i; - - gtk_text_tag_array_sort (tags, count); - - i = 0; - while (i < count) - { - retval = g_slist_prepend (retval, tags[i]); - ++i; - } - - retval = g_slist_reverse (retval); - } - - if (tags) - g_free (tags); - - return retval; -} - /* Called when we lose the primary selection. */ static void @@ -1771,89 +2066,110 @@ clipboard_get_cb (GtkClipboard *clipboard, gpointer data) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data); - gchar *str; GtkTextIter start, end; if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end)) { - /* Extract the selected text */ - str = gtk_text_iter_get_visible_text (&start, &end); - gtk_selection_data_set_text (selection_data, str); - g_free (str); + if (selection_data->target == + gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE)) + { + /* Provide the address of the buffer; this will only be + * used within-process + */ + gtk_selection_data_set (selection_data, + gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE), + 8, /* bytes */ + (void*)&buffer, + sizeof (buffer)); + } + else + { + gchar *str; + + str = gtk_text_iter_get_visible_text (&start, &end); + gtk_selection_data_set_text (selection_data, str); + g_free (str); + } } } -/* Called when we request a paste and receive the data - */ static void -clipboard_received (GtkClipboard *clipboard, - const gchar *str, - gpointer data) +get_paste_point (GtkTextBuffer *buffer, + GtkTextIter *iter, + gboolean clear_afterward) { - ClipboardRequest *request_data = data; - GtkTextBuffer *buffer = request_data->buffer; + GtkTextIter insert_point; + GtkTextMark *paste_point_override; - if (str) - { - gboolean reselect; - GtkTextIter insert_point; - GtkTextMark *paste_point_override; + paste_point_override = gtk_text_buffer_get_mark (buffer, + "gtk_paste_point_override"); - paste_point_override = gtk_text_buffer_get_mark (buffer, - "gtk_paste_point_override"); + if (paste_point_override != NULL) + { + gtk_text_buffer_get_iter_at_mark (buffer, &insert_point, + paste_point_override); + if (clear_afterward) + gtk_text_buffer_delete_mark (buffer, + gtk_text_buffer_get_mark (buffer, + "gtk_paste_point_override")); + } + else + { + gtk_text_buffer_get_iter_at_mark (buffer, &insert_point, + gtk_text_buffer_get_mark (buffer, + "insert")); + } - if (paste_point_override != NULL) - { - gtk_text_buffer_get_iter_at_mark (buffer, &insert_point, - paste_point_override); - gtk_text_buffer_delete_mark (buffer, - gtk_text_buffer_get_mark (buffer, - "gtk_paste_point_override")); - } - else - { - gtk_text_buffer_get_iter_at_mark (buffer, &insert_point, - gtk_text_buffer_get_mark (buffer, - "insert")); - } + *iter = insert_point; +} - reselect = FALSE; +static void +pre_paste_prep (ClipboardRequest *request_data, + GtkTextIter *insert_point) +{ + GtkTextBuffer *buffer = request_data->buffer; - /* FIXME ALL OF THIS - I think that the "best method" is that when pasting - * with the cursor inside the selection area, you 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. - * - * This probably is best implemented as a "replace_selection" flag in - * ClipboardRequest. - */ -#if 0 - if ((TRUE/* Text is selected FIXME */) && - (!buffer->have_selection || request_data->is_clipboard)) + if (request_data->replace_selection) + { + GtkTextIter start, end; + + if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end)) { - reselect = TRUE; - - if (buffer->have_selection) - { - /* FIXME Delete currently-selected chars but don't give up X - selection since we'll use the newly-pasted stuff as - a new X selection */ - - } + if (request_data->interactive) + gtk_text_buffer_delete_interactive (buffer, + &start, + &end, + request_data->default_editable); else - ; /* FIXME Delete selected chars and give up X selection */ + gtk_text_buffer_delete (buffer, &start, &end); } -#endif + } + + get_paste_point (buffer, insert_point, TRUE); +} + +/* Called when we request a paste and receive the text data + */ +static void +clipboard_text_received (GtkClipboard *clipboard, + const gchar *str, + gpointer data) +{ + ClipboardRequest *request_data = data; + GtkTextBuffer *buffer = request_data->buffer; + if (str) + { + GtkTextIter insert_point; + + pre_paste_prep (request_data, &insert_point); + if (request_data->interactive) gtk_text_buffer_insert_interactive (buffer, &insert_point, str, -1, request_data->default_editable); else gtk_text_buffer_insert (buffer, &insert_point, str, -1); - - if (reselect) - ; /* FIXME Select the region of text we just inserted */ } g_object_unref (G_OBJECT (buffer)); @@ -1861,13 +2177,74 @@ clipboard_received (GtkClipboard *clipboard, } static void +clipboard_buffer_received (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + gpointer data) +{ + ClipboardRequest *request_data = data; + GtkTextBuffer *buffer = request_data->buffer; + GdkWindow *owner; + GtkTextBuffer *src_buffer = NULL; + GtkTextIter src_start, src_end; + GtkTextIter insert_point; + + /* If we can get the owner, the selection is in-process */ + owner = gdk_selection_owner_get (selection_data->selection); + + if (owner == NULL) + goto try_another_target; + + if (selection_data->type != gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE)) + goto try_another_target; + + if (selection_data->length != sizeof (src_buffer)) + return; + + memcpy (&src_buffer, selection_data->data, sizeof (src_buffer)); + + 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 (buffer)) + goto try_another_target; + + /* We're about to emit a bunch of signals, so be safe */ + g_object_ref (G_OBJECT (src_buffer)); + + pre_paste_prep (request_data, &insert_point); + + if (gtk_text_buffer_get_selection_bounds (src_buffer, + &src_start, + &src_end)) + { + gtk_text_buffer_real_insert_range (buffer, + &insert_point, + &src_start, + &src_end, + request_data->interactive); + } + + g_object_unref (G_OBJECT (src_buffer)); + + return; + + try_another_target: + + /* Request the text selection instead */ + gtk_clipboard_request_text (clipboard, + clipboard_text_received, + data); +} + +static void gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer) { static const GtkTargetEntry targets[] = { { "STRING", 0, TARGET_STRING }, { "TEXT", 0, TARGET_TEXT }, { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, - { "UTF8_STRING", 0, TARGET_UTF8_STRING } + { "UTF8_STRING", 0, TARGET_UTF8_STRING }, + { "GTK_TEXT_BUFFER_CONTENTS", 0, TARGET_TEXT_BUFFER_CONTENTS } }; GtkTextIter start; @@ -1897,25 +2274,42 @@ gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer) static void paste (GtkTextBuffer *buffer, - gboolean is_clipboard, - gboolean interactive, - gboolean default_editable) + gboolean is_clipboard, + gboolean interactive, + gboolean default_editable) { ClipboardRequest *data = g_new (ClipboardRequest, 1); - + GtkTextIter paste_point; + GtkTextIter start, end; + data->buffer = buffer; g_object_ref (G_OBJECT (buffer)); data->interactive = interactive; data->default_editable = default_editable; - gtk_clipboard_request_text (gtk_clipboard_get (is_clipboard ? GDK_NONE : GDK_SELECTION_PRIMARY), - clipboard_received, data); + /* When pasting with the cursor inside the selection area, you + * 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. + */ + 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)) + data->replace_selection = TRUE; + + gtk_clipboard_request_contents (gtk_clipboard_get (is_clipboard ? GDK_NONE : GDK_SELECTION_PRIMARY), + + gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE), + clipboard_buffer_received, data); } void -gtk_text_buffer_paste_primary (GtkTextBuffer *buffer, - GtkTextIter *override_location, - gboolean default_editable) +gtk_text_buffer_paste_primary (GtkTextBuffer *buffer, + const GtkTextIter *override_location, + gboolean default_editable) { if (override_location != NULL) gtk_text_buffer_create_mark (buffer, @@ -1962,11 +2356,12 @@ cut_or_copy (GtkTextBuffer *buffer, gboolean default_editable) { /* We prefer to cut the selected region between selection_bound and - insertion point. If that region is empty, then we cut the region - between the "anchor" and the insertion point (this is for C-space - and M-w and other Emacs-style copy/yank keys). Note that insert - and selection_bound are guaranteed to exist, but the anchor only - exists sometimes. */ + * insertion point. If that region is empty, then we cut the region + * between the "anchor" and the insertion point (this is for + * C-space and M-w and other Emacs-style copy/yank keys). Note that + * insert and selection_bound are guaranteed to exist, but the + * anchor only exists sometimes. + */ GtkTextIter start; GtkTextIter end; diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h index c1b5fcdd58..54844e1465 100644 --- a/gtk/gtktextbuffer.h +++ b/gtk/gtktextbuffer.h @@ -283,10 +283,6 @@ void gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer *buffer, /* There's no get_first_iter because you just get the iter for line or char 0 */ -GSList *gtk_text_buffer_get_tags (GtkTextBuffer *buffer, - const GtkTextIter *iter); - - /* Used to keep track of whether the buffer needs saving; anytime the buffer contents change, the modified flag is turned on. Whenever you save, turn it off. Tags and marks do not affect the modified @@ -297,9 +293,9 @@ gboolean gtk_text_buffer_modified (GtkTextBuffer *buffer); void gtk_text_buffer_set_modified (GtkTextBuffer *buffer, gboolean setting); -void gtk_text_buffer_paste_primary (GtkTextBuffer *buffer, - GtkTextIter *override_location, - gboolean default_editable); +void gtk_text_buffer_paste_primary (GtkTextBuffer *buffer, + const GtkTextIter *override_location, + gboolean default_editable); void gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer, gboolean default_editable); void gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer); diff --git a/gtk/gtktextiter.c b/gtk/gtktextiter.c index e57855551a..f7713d3099 100644 --- a/gtk/gtktextiter.c +++ b/gtk/gtktextiter.c @@ -580,11 +580,14 @@ gtk_text_iter_get_offset (const GtkTextIter *iter) if (real == NULL) return 0; + check_invariants (iter); + if (real->cached_char_index < 0) { + ensure_char_offsets (real); + real->cached_char_index = gtk_text_line_char_index (real->line); - ensure_char_offsets (real); real->cached_char_index += real->line_char_offset; } @@ -722,7 +725,7 @@ gtk_text_iter_get_char (const GtkTextIter *iter) else if (real->segment->type == >k_text_char_type) { ensure_byte_offsets (real); - + return g_utf8_get_char (real->segment->body.chars + real->segment_byte_offset); } @@ -743,7 +746,9 @@ gtk_text_iter_get_char (const GtkTextIter *iter) * character 0xFFFD for iterable non-character elements in the buffer, * such as images. Because images are encoded in the slice, byte and * character offsets in the returned array will correspond to byte - * offsets in the text buffer. + * offsets in the text buffer. Note that 0xFFFD can occur in normal + * text as well, so it is not a reliable indicator that a pixbuf or + * widget is in the buffer. * * Return value: slice of text from the buffer **/ @@ -1170,6 +1175,56 @@ gtk_text_iter_has_tag (const GtkTextIter *iter, } /** + * gtk_text_iter_get_tags: + * @iter: a #GtkTextIter + * + * Returns a list of tags that apply to @iter, in ascending order of + * priority (highest-priority tags are last). The #GtkTextTag in the + * list don't have a reference added, but you have to free the list + * itself. + * + * Return value: list of #GtkTextTag + **/ +GSList* +gtk_text_iter_get_tags (const GtkTextIter *iter) +{ + GtkTextTag** tags; + gint tag_count = 0; + gint i; + GSList *retval; + + g_return_val_if_fail (iter != NULL, NULL); + + /* Get the tags at this spot */ + tags = gtk_text_btree_get_tags (iter, &tag_count); + + /* No tags, use default style */ + if (tags == NULL || tag_count == 0) + { + if (tags) + g_free (tags); + + return NULL; + } + + /* Sort tags in ascending order of priority */ + gtk_text_tag_array_sort (tags, tag_count); + + retval = NULL; + i = 0; + while (i < tag_count) + { + retval = g_slist_prepend (retval, tags[i]); + ++i; + } + + g_free (tags); + + /* Return tags in ascending order of priority */ + return g_slist_reverse (retval); +} + +/** * gtk_text_iter_editable: * @iter: an iterator * @default_setting: TRUE if text is editable by default @@ -2654,7 +2709,9 @@ gtk_text_iter_forward_to_newline (GtkTextIter *iter) * #GtkTextTag @tag, or to the next toggle of any tag if * @tag is NULL. If no matching tag toggles are found, * returns FALSE, otherwise TRUE. Does not return toggles - * located at @iter, only toggles after @iter. + * located at @iter, only toggles after @iter. Sets @iter to + * the location of the toggle, or to the end of the buffer + * if no toggle is found. * * Return value: whether we found a tag toggle after @iter **/ @@ -2734,7 +2791,9 @@ gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter, * #GtkTextTag @tag, or to the next toggle of any tag if * @tag is NULL. If no matching tag toggles are found, * returns FALSE, otherwise TRUE. Does not return toggles - * located at @iter, only toggles before @iter. + * located at @iter, only toggles before @iter. Sets @iter + * to the location of the toggle, or the start of the buffer + * if no toggle is found. * * Return value: whether we found a tag toggle before @iter **/ @@ -2836,16 +2895,37 @@ matches_pred (GtkTextIter *iter, return (*pred) (ch, user_data); } +/** + * gtk_text_iter_forward_find_char: + * @iter: a #GtkTextIter + * @pred: a function to be called on each character + * @user_data: user data for @pred + * @limit: search limit, or %NULL for none + * + * Advances @iter, calling @pred on each character. If + * @pred returns %TRUE, returns %TRUE and stops scanning. + * If @pred never returns %TRUE, @iter is set to @limit if + * @limit is non-%NULL, otherwise to the end iterator. + * + * Return value: whether a match was found + **/ gboolean -gtk_text_iter_forward_find_char (GtkTextIter *iter, +gtk_text_iter_forward_find_char (GtkTextIter *iter, GtkTextCharPredicate pred, - gpointer user_data) + gpointer user_data, + const GtkTextIter *limit) { g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (pred != NULL, FALSE); - while (gtk_text_iter_next_char (iter)) - { + if (limit && + gtk_text_iter_compare (iter, limit) >= 0) + return FALSE; + + while ((limit == NULL || + !gtk_text_iter_equal (limit, iter)) && + gtk_text_iter_next_char (iter)) + { if (matches_pred (iter, pred, user_data)) return TRUE; } @@ -2854,14 +2934,21 @@ gtk_text_iter_forward_find_char (GtkTextIter *iter, } gboolean -gtk_text_iter_backward_find_char (GtkTextIter *iter, +gtk_text_iter_backward_find_char (GtkTextIter *iter, GtkTextCharPredicate pred, - gpointer user_data) + gpointer user_data, + const GtkTextIter *limit) { g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (pred != NULL, FALSE); - while (gtk_text_iter_prev_char (iter)) + if (limit && + gtk_text_iter_compare (iter, limit) <= 0) + return FALSE; + + while ((limit == NULL || + !gtk_text_iter_equal (limit, iter)) && + gtk_text_iter_prev_char (iter)) { if (matches_pred (iter, pred, user_data)) return TRUE; @@ -3060,13 +3147,28 @@ strbreakup (const char *string, return str_array; } +/** + * gtk_text_iter_forward_search: + * @iter: start of search + * @str: a search string + * @visible_only: if %TRUE, search only visible text + * @slice: if %TRUE, @str contains 0xFFFD when we want to match widgets, pixbufs + * @match_start: return location for start of match, or %NULL + * @match_end: return location for end of match, or %NULL + * @limit: bound for the search, or %NULL for the end of the buffer + * + * + * + * Return value: whether a match was found + **/ gboolean gtk_text_iter_forward_search (const GtkTextIter *iter, const gchar *str, gboolean visible_only, gboolean slice, GtkTextIter *match_start, - GtkTextIter *match_end) + GtkTextIter *match_end, + const GtkTextIter *limit) { gchar **lines = NULL; GtkTextIter match; @@ -3076,12 +3178,21 @@ gtk_text_iter_forward_search (const GtkTextIter *iter, g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (str != NULL, FALSE); + if (limit && + gtk_text_iter_compare (iter, limit) >= 0) + return FALSE; + if (*str == '\0') { /* If we can move one char, return the empty string there */ match = *iter; + if (gtk_text_iter_next_char (&match)) { + if (limit && + gtk_text_iter_equal (&match, limit)) + return FALSE; + if (match_start) *match_start = match; if (match_end) @@ -3106,17 +3217,26 @@ gtk_text_iter_forward_search (const GtkTextIter *iter, */ GtkTextIter end; + if (limit && + gtk_text_iter_compare (&search, limit) >= 0) + break; + if (lines_match (&search, (const gchar**)lines, visible_only, slice, &match, &end)) { - retval = TRUE; - - if (match_start) - *match_start = match; - - if (match_end) - *match_end = end; - + if (limit == NULL || + (limit && + gtk_text_iter_compare (&end, limit) < 0)) + { + retval = TRUE; + + if (match_start) + *match_start = match; + + if (match_end) + *match_end = end; + } + break; } } @@ -3345,13 +3465,28 @@ my_strrstr (const gchar *haystack, return NULL; } +/** + * gtk_text_iter_backward_search: + * @iter: a #GtkTextIter where the search begins + * @str: search string + * @visible_only: if %TRUE search only visible text + * @slice: if %TRUE the search string contains 0xFFFD to match pixbufs, widgets + * @match_start: return location for start of match, or %NULL + * @match_end: return location for end of match, or %NULL + * @limit: location of last possible @match_start, or %NULL for start of buffer + * + * + * + * Return value: whether a match was found + **/ gboolean gtk_text_iter_backward_search (const GtkTextIter *iter, const gchar *str, gboolean visible_only, gboolean slice, GtkTextIter *match_start, - GtkTextIter *match_end) + GtkTextIter *match_end, + const GtkTextIter *limit) { gchar **lines = NULL; gchar **l; @@ -3362,11 +3497,18 @@ gtk_text_iter_backward_search (const GtkTextIter *iter, g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (str != NULL, FALSE); + if (limit && + gtk_text_iter_compare (limit, iter) > 0) + return FALSE; + if (*str == '\0') { /* If we can move one char, return the empty string there */ GtkTextIter match = *iter; + if (limit && gtk_text_iter_equal (limit, &match)) + return FALSE; + if (gtk_text_iter_prev_char (&match)) { if (match_start) @@ -3404,6 +3546,13 @@ gtk_text_iter_backward_search (const GtkTextIter *iter, { gchar *first_line_match; + if (limit && + gtk_text_iter_compare (limit, &win.first_line_end) > 0) + { + /* We're now before the search limit, abort. */ + goto out; + } + /* If there are multiple lines, the first line will * end in '\n', so this will only match at the * end of the first line, which is correct. @@ -3416,17 +3565,22 @@ gtk_text_iter_backward_search (const GtkTextIter *iter, /* Match! */ gint offset; GtkTextIter next; - + GtkTextIter start_tmp; + /* Offset to start of search string */ offset = g_utf8_strlen (*win.lines, first_line_match - *win.lines); next = win.first_line_start; + start_tmp = next; + forward_chars_with_skipping (&start_tmp, offset, + visible_only, !slice); + + if (limit && + gtk_text_iter_compare (limit, &start_tmp) > 0) + goto out; /* match was bogus */ + if (match_start) - { - *match_start = next; - forward_chars_with_skipping (match_start, offset, - visible_only, !slice); - } + *match_start = start_tmp; /* Go to end of search string */ l = lines; @@ -3451,7 +3605,7 @@ gtk_text_iter_backward_search (const GtkTextIter *iter, out: lines_window_free (&win); g_strfreev (lines); - + return retval; } @@ -3655,7 +3809,7 @@ void gtk_text_btree_get_iter_at_line (GtkTextBTree *tree, GtkTextIter *iter, GtkTextLine *line, - gint byte_offset) + gint byte_offset) { g_return_if_fail (iter != NULL); g_return_if_fail (tree != NULL); @@ -3822,13 +3976,13 @@ gtk_text_iter_check (const GtkTextIter *iter) { const GtkTextRealIter *real = (const GtkTextRealIter*)iter; gint line_char_offset, line_byte_offset, seg_char_offset, seg_byte_offset; - GtkTextLineSegment *byte_segment; - GtkTextLineSegment *byte_any_segment; - GtkTextLineSegment *char_segment; - GtkTextLineSegment *char_any_segment; + GtkTextLineSegment *byte_segment = NULL; + GtkTextLineSegment *byte_any_segment = NULL; + GtkTextLineSegment *char_segment = NULL; + GtkTextLineSegment *char_any_segment = NULL; gboolean segments_updated; - /* We are going to check our class invariants for the Iter class. */ + /* This function checks our class invariants for the Iter class. */ g_assert (sizeof (GtkTextIter) == sizeof (GtkTextRealIter)); @@ -3891,6 +4045,15 @@ gtk_text_iter_check (const GtkTextIter *iter) if (seg_byte_offset != real->segment_byte_offset) g_error ("wrong segment byte offset was stored in iterator"); + + if (byte_segment->type == >k_text_char_type) + { + const gchar *p; + p = byte_segment->body.chars + seg_byte_offset; + + if (!gtk_text_byte_begins_utf8_char (p)) + g_error ("broken iterator byte index pointed into the middle of a character"); + } } } @@ -3904,7 +4067,7 @@ gtk_text_iter_check (const GtkTextIter *iter) g_error ("wrong char offset was stored in iterator"); if (segments_updated) - { + { if (real->segment != char_segment) g_error ("wrong segment was stored in iterator"); @@ -3913,6 +4076,17 @@ gtk_text_iter_check (const GtkTextIter *iter) if (seg_char_offset != real->segment_char_offset) g_error ("wrong segment char offset was stored in iterator"); + + if (char_segment->type == >k_text_char_type) + { + const gchar *p; + p = g_utf8_offset_to_pointer (char_segment->body.chars, + seg_char_offset); + + /* hmm, not likely to happen eh */ + if (!gtk_text_byte_begins_utf8_char (p)) + g_error ("broken iterator char offset pointed into the middle of a character"); + } } } @@ -3945,6 +4119,9 @@ gtk_text_iter_check (const GtkTextIter *iter) if (char_offset != seg_char_offset) g_error ("char offset did not correspond to byte offset"); + + if (!gtk_text_byte_begins_utf8_char (char_segment->body.chars + seg_byte_offset)) + g_error ("byte index for iterator does not index the start of a character"); } } diff --git a/gtk/gtktextiter.h b/gtk/gtktextiter.h index 3e649d0b40..caadecb2a2 100644 --- a/gtk/gtktextiter.h +++ b/gtk/gtktextiter.h @@ -119,6 +119,7 @@ gboolean gtk_text_iter_toggles_tag (const GtkTextIter *iter, gboolean gtk_text_iter_has_tag (const GtkTextIter *iter, GtkTextTag *tag); +GSList *gtk_text_iter_get_tags (const GtkTextIter *iter); gboolean gtk_text_iter_editable (const GtkTextIter *iter, gboolean default_setting); @@ -170,8 +171,9 @@ gboolean gtk_text_iter_forward_to_newline (GtkTextIter *iter); /* returns TRUE if a toggle was found; NULL for the tag pointer - means "any tag toggle", otherwise the next toggle of the - specified tag is located. */ + * means "any tag toggle", otherwise the next toggle of the + * specified tag is located. + */ gboolean gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter, GtkTextTag *tag); @@ -180,27 +182,30 @@ gboolean gtk_text_iter_backward_to_tag_toggle (GtkTextIter *iter, typedef gboolean (* GtkTextCharPredicate) (gunichar ch, gpointer user_data); -gboolean gtk_text_iter_forward_find_char (GtkTextIter *iter, - GtkTextCharPredicate pred, - gpointer user_data); - -gboolean gtk_text_iter_backward_find_char (GtkTextIter *iter, - GtkTextCharPredicate pred, - gpointer user_data); +gboolean gtk_text_iter_forward_find_char (GtkTextIter *iter, + GtkTextCharPredicate pred, + gpointer user_data, + const GtkTextIter *limit); +gboolean gtk_text_iter_backward_find_char (GtkTextIter *iter, + GtkTextCharPredicate pred, + gpointer user_data, + const GtkTextIter *limit); gboolean gtk_text_iter_forward_search (const GtkTextIter *iter, const gchar *str, gboolean visible_only, gboolean slice, GtkTextIter *match_start, - GtkTextIter *match_end); + GtkTextIter *match_end, + const GtkTextIter *limit); + gboolean gtk_text_iter_backward_search (const GtkTextIter *iter, const gchar *str, gboolean visible_only, gboolean slice, GtkTextIter *match_start, - GtkTextIter *match_end); - + GtkTextIter *match_end, + const GtkTextIter *limit); /* diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index cba5557b31..9f84c001ef 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -2235,7 +2235,7 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout, { gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), iter, line, - direction < 0 ? byte_offset : layout_line->length); + direction < 0 ? byte_offset : byte_offset + layout_line->length); /* FIXME: Move back one position to avoid going to next line */ diff --git a/gtk/gtktextmark.c b/gtk/gtktextmark.c index 13587007bc..4e20eb300c 100644 --- a/gtk/gtktextmark.c +++ b/gtk/gtktextmark.c @@ -128,7 +128,7 @@ gtk_text_mark_finalize (GObject *obj) } /** - * gtk_text_mark_is_visible: + * gtk_text_mark_get_visible: * @mark: a #GtkTextMark * * Returns %TRUE if the mark is visible (i.e. a cursor is displayed @@ -137,7 +137,7 @@ gtk_text_mark_finalize (GObject *obj) * Return value: %TRUE if visible **/ gboolean -gtk_text_mark_is_visible (GtkTextMark *mark) +gtk_text_mark_get_visible (GtkTextMark *mark) { GtkTextLineSegment *seg; diff --git a/gtk/gtktextmark.h b/gtk/gtktextmark.h index cdcaeab4bc..e2130c5acd 100644 --- a/gtk/gtktextmark.h +++ b/gtk/gtktextmark.h @@ -83,7 +83,7 @@ GType gtk_text_mark_get_type (void) G_GNUC_CONST; void gtk_text_mark_set_visible (GtkTextMark *mark, gboolean setting); -gboolean gtk_text_mark_is_visible (GtkTextMark *mark); +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); diff --git a/gtk/gtktextsegment.c b/gtk/gtktextsegment.c index 66f0a672b9..33d1083317 100644 --- a/gtk/gtktextsegment.c +++ b/gtk/gtktextsegment.c @@ -102,6 +102,9 @@ gtk_text_line_segment_split (const GtkTextIter *iter) count = gtk_text_iter_get_line_index (iter); + if (gtk_debug_flags & GTK_DEBUG_TEXT) + gtk_text_iter_check (iter); + prev = NULL; seg = line->segments; diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index bc054fb173..1dedcaf068 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -2040,14 +2040,14 @@ emit_event_on_tags (GtkWidget *widget, text_view = GTK_TEXT_VIEW (widget); - tags = gtk_text_buffer_get_tags (get_buffer (text_view), iter); + tags = gtk_text_iter_get_tags (iter); tmp = tags; while (tmp != NULL) { GtkTextTag *tag = tmp->data; - if (gtk_text_tag_event (tag, GTK_OBJECT (widget), event, iter)) + if (gtk_text_tag_event (tag, G_OBJECT (widget), event, iter)) { retval = TRUE; break; @@ -2818,10 +2818,10 @@ find_whitepace_region (const GtkTextIter *center, *start = *center; *end = *center; - if (gtk_text_iter_backward_find_char (start, not_whitespace, NULL)) + if (gtk_text_iter_backward_find_char (start, not_whitespace, NULL, NULL)) gtk_text_iter_next_char (start); /* we want the first whitespace... */ if (whitespace (gtk_text_iter_get_char (end), NULL)) - gtk_text_iter_forward_find_char (end, not_whitespace, NULL); + gtk_text_iter_forward_find_char (end, not_whitespace, NULL, NULL); return !gtk_text_iter_equal (start, end); } diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index b55a2a1b99..e89c3857ec 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -141,25 +141,6 @@ struct _GtkRequisition gint height; }; -/* The contents of a selection are returned in a GtkSelectionData - structure. selection/target identify the request. - type specifies the type of the return; if length < 0, and - the data should be ignored. This structure has object semantics - - no fields should be modified directly, they should not be created - directly, and pointers to them should not be stored beyond the duration of - a callback. (If the last is changed, we'll need to add reference - counting.) The time field gives the timestamp at which the data was sent. */ - -struct _GtkSelectionData -{ - GdkAtom selection; - GdkAtom target; - GdkAtom type; - gint format; - guchar *data; - gint length; -}; - /* The widget is the base of the tree for displayable objects. * (A displayable object is one which takes up some amount * of screen real estate). It provides a common base and interface diff --git a/gtk/testtext.c b/gtk/testtext.c index d62545f7ae..12cfcd0899 100644 --- a/gtk/testtext.c +++ b/gtk/testtext.c @@ -1351,7 +1351,8 @@ buffer_search (Buffer *buffer, if (forward) { while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE, - &match_start, &match_end)) + &match_start, &match_end, + NULL)) { ++i; gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, @@ -1363,7 +1364,8 @@ buffer_search (Buffer *buffer, else { while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE, - &match_start, &match_end)) + &match_start, &match_end, + NULL)) { ++i; gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, diff --git a/tests/testtext.c b/tests/testtext.c index d62545f7ae..12cfcd0899 100644 --- a/tests/testtext.c +++ b/tests/testtext.c @@ -1351,7 +1351,8 @@ buffer_search (Buffer *buffer, if (forward) { while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE, - &match_start, &match_end)) + &match_start, &match_end, + NULL)) { ++i; gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, @@ -1363,7 +1364,8 @@ buffer_search (Buffer *buffer, else { while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE, - &match_start, &match_end)) + &match_start, &match_end, + NULL)) { ++i; gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, |