summaryrefslogtreecommitdiff
path: root/gtk/gtktextiter.c
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2000-07-25 23:59:38 +0000
committerHavoc Pennington <hp@src.gnome.org>2000-07-25 23:59:38 +0000
commita4762fbff4739fbf0373c5528eb3a9855aa9299b (patch)
tree3fc0969e7a0a0761da5c5d92920ee04b07c5f528 /gtk/gtktextiter.c
parentf56297c5346cddb72b383161bbde9168824acb94 (diff)
downloadgtk+-a4762fbff4739fbf0373c5528eb3a9855aa9299b.tar.gz
update to reflect text widget changes.
2000-07-25 Havoc Pennington <hp@redhat.com> * gtk/testtext.c, gtk/testtextbuffer.c: update to reflect text widget changes. * gtk/gtktextview.h: To be consistent with usage of "line" throughout the API to mean "newline-terminated thingy", change MOVEMENT_LINE to be MOVEMENT_WRAPPED_LINE, and MOVEMENT_PARAGRAPH to MOVEMENT_LINE. (GtkTextView): Add flags for default editability, and whether to show the cursor. Add functions to get/set that. Add (gtk_text_view_get_iter_location): new function * gtk/gtktexttypes.h: Move GtkTextLine typedef from here to gtktextlayout.h (g_convert): Add g_convert temporarily, will go in glib in a bit * gtk/gtktexttagtable.h: include gtktexttag.h, and define GtkTextTagTableForeach instead of brokenly using GHFunc. Change gtk_text_tag_table_foreach() so it doesn't use GHFunc. * gtk/gtktexttagprivate.h: Remove GtkTextStyleValues from here, moved to public header. * gtk/gtktexttag.h: Rename the "elide" attribute of tags to "invisible", since "elide" was a bad name. (gtk_text_tag_get_priority): Added (GtkTextStyleValues): put this in public header, along with functions to use it. * gtk/gtktextmarkprivate.h: Include more headers, since we no longer include gtktextbtree.h. * gtk/gtktextmark.h: Add gtk_text_mark_ref, gtk_text_mark_unref, gtk_text_mark_deleted * gtk/gtktextlayout.h: Don't include the "really private" headers, only buffer/iter. Forward declare GtkTextLIne and GtkTextLineData to make this possible. Now we only need to install gtktextlayout.h, not gtktextbtree.h and gtktext*private.h. (However the Makefile.am isn't changed yet because of the logistics of merging gtk-hp-patches piecemeal) * gtk/gtktextiterprivate.h: include btree header, so it compiles; rename gtk_text_iter_get_line to gtk_text_iter_get_text_line since gtk_text_iter_get_line is now used in the public API for a different purpose. * gtk/gtktextiter.h: Clean up function names to be more consistent. Always call char offset "offset" and byte index "index". A "line" is always a line number. (gtk_text_iter_is_last): new function, more efficient than the existing way to check (gtk_text_iter_is_first): new function, also more efficient (gtk_text_iter_up_lines, gtk_text_iter_down_lines): Remove these (gtk_text_iter_next_char, gtk_text_iter_prev_char): Renamed from gtk_text_iter_forward_char, etc. (gtk_text_iter_forward_to_tag_toggle): Renamed from forward_find_tag_toggle, since this isn't a linear search (GtkTextCharPredicate): rename from GtkTextViewCharPredicate (gtk_text_iter_forward_search, gtk_text_iter_backward_search): New functions, search for a buffer substring. * gtk/gtktextbuffer.h: Add fields to store whether a paste is interactive and default editable (since we need to store that info until we receive the selection data). Remove all the _at_char and at_line etc. versions of functions; only have iterator versions. Add _interactive() versions of functions, that consider the editability of text. (FIXME add interactive flag to the insert/delete signals per Darin's suggestion) (gtk_text_buffer_get_tag_table): new function, demand-creates the tag table if necessary Remove declaration of gtk_text_buffer_get_iter_from_string (_gtk_text_buffer_get_btree): private/internal function, added. * gtk/gtktextbtree.h: Remove forward decl of GtkTextLineData. (gtk_text_line_is_last): new function
Diffstat (limited to 'gtk/gtktextiter.c')
-rw-r--r--gtk/gtktextiter.c703
1 files changed, 531 insertions, 172 deletions
diff --git a/gtk/gtktextiter.c b/gtk/gtktextiter.c
index 953045e0b4..48e6b17eda 100644
--- a/gtk/gtktextiter.c
+++ b/gtk/gtktextiter.c
@@ -2,6 +2,7 @@
#include "gtktextbtree.h"
#include "gtktextiterprivate.h"
#include "gtkdebug.h"
+#include <string.h>
#include <ctype.h>
typedef struct _GtkTextRealIter GtkTextRealIter;
@@ -34,9 +35,9 @@ struct _GtkTextRealIter {
and ditto for char offsets. */
gint segment_byte_offset;
gint segment_char_offset;
- /* These are here for binary-compatible expansion space. */
+ /* Pads are here for binary-compatible expansion space. */
gpointer pad1;
- gint pad2;
+ guint pad2;
};
/* These "set" functions should not assume any fields
@@ -114,7 +115,8 @@ iter_set_from_segment(GtkTextRealIter *iter,
/* This function ensures that the segment-dependent information is
truly computed lazily; often we don't need to do the full make_real
- work. */
+ work. This ensures the btree and line are valid, but doesn't
+ update the segments. */
static GtkTextRealIter*
gtk_text_iter_make_surreal(const GtkTextIter *_iter)
{
@@ -308,9 +310,9 @@ ensure_char_offsets(GtkTextRealIter *iter)
g_assert(iter->line_byte_offset >= 0);
gtk_text_line_byte_to_char_offsets(iter->line,
- iter->line_byte_offset,
- &iter->line_char_offset,
- &iter->segment_char_offset);
+ iter->line_byte_offset,
+ &iter->line_char_offset,
+ &iter->segment_char_offset);
}
}
@@ -322,9 +324,9 @@ ensure_byte_offsets(GtkTextRealIter *iter)
g_assert(iter->line_char_offset >= 0);
gtk_text_line_char_to_byte_offsets(iter->line,
- iter->line_char_offset,
- &iter->line_byte_offset,
- &iter->segment_byte_offset);
+ iter->line_char_offset,
+ &iter->line_byte_offset,
+ &iter->segment_byte_offset);
}
}
@@ -457,7 +459,7 @@ gtk_text_iter_get_segment_char(const GtkTextIter *iter)
/* This function does not require a still-valid
iterator */
GtkTextLine*
-gtk_text_iter_get_line(const GtkTextIter *iter)
+gtk_text_iter_get_text_line(const GtkTextIter *iter)
{
const GtkTextRealIter *real;
@@ -487,7 +489,7 @@ gtk_text_iter_get_btree(const GtkTextIter *iter)
*/
gint
-gtk_text_iter_get_char_index(const GtkTextIter *iter)
+gtk_text_iter_get_offset(const GtkTextIter *iter)
{
GtkTextRealIter *real;
@@ -512,7 +514,7 @@ gtk_text_iter_get_char_index(const GtkTextIter *iter)
}
gint
-gtk_text_iter_get_line_number(const GtkTextIter *iter)
+gtk_text_iter_get_line(const GtkTextIter *iter)
{
GtkTextRealIter *real;
@@ -533,7 +535,7 @@ gtk_text_iter_get_line_number(const GtkTextIter *iter)
}
gint
-gtk_text_iter_get_line_char(const GtkTextIter *iter)
+gtk_text_iter_get_line_offset(const GtkTextIter *iter)
{
GtkTextRealIter *real;
@@ -553,7 +555,7 @@ gtk_text_iter_get_line_char(const GtkTextIter *iter)
}
gint
-gtk_text_iter_get_line_byte(const GtkTextIter *iter)
+gtk_text_iter_get_line_index(const GtkTextIter *iter)
{
GtkTextRealIter *real;
@@ -691,6 +693,38 @@ gtk_text_iter_get_pixmap (const GtkTextIter *iter,
}
GSList*
+gtk_text_iter_get_marks (const GtkTextIter *iter)
+{
+ GtkTextRealIter *real;
+ GtkTextLineSegment *seg;
+ GSList *retval;
+
+ g_return_val_if_fail(iter != NULL, NULL);
+
+ real = gtk_text_iter_make_real(iter);
+
+ if (real == NULL)
+ return NULL;
+
+ check_invariants(iter);
+
+ retval = NULL;
+ seg = real->any_segment;
+ while (seg != real->segment)
+ {
+ if (seg->type == &gtk_text_left_mark_type ||
+ seg->type == &gtk_text_right_mark_type)
+ retval = g_slist_prepend(retval, (GtkTextMark*)seg);
+
+ seg = seg->next;
+ }
+
+ /* The returned list isn't guaranteed to be in any special order,
+ and it isn't. */
+ return retval;
+}
+
+GSList*
gtk_text_iter_get_toggled_tags (const GtkTextIter *iter,
gboolean toggled_on)
{
@@ -859,6 +893,43 @@ gtk_text_iter_has_tag (const GtkTextIter *iter,
}
gboolean
+gtk_text_iter_editable (const GtkTextIter *iter,
+ gboolean default_setting)
+{
+ GtkTextStyleValues *values;
+ gboolean retval;
+
+ values = gtk_text_style_values_new ();
+
+ values->editable = default_setting;
+
+ gtk_text_iter_get_style_values (iter, values);
+
+ retval = values->editable;
+
+ gtk_text_style_values_unref (values);
+
+ return retval;
+}
+
+static gchar*
+gtk_text_iter_get_language (const GtkTextIter *iter)
+{
+ GtkTextStyleValues *values;
+ gchar *retval;
+
+ values = gtk_text_style_values_new ();
+
+ gtk_text_iter_get_style_values (iter, values);
+
+ retval = g_strdup (values->language);
+
+ gtk_text_style_values_unref (values);
+
+ return retval;
+}
+
+gboolean
gtk_text_iter_starts_line (const GtkTextIter *iter)
{
GtkTextRealIter *real;
@@ -893,6 +964,29 @@ gtk_text_iter_ends_line (const GtkTextIter *iter)
return gtk_text_iter_get_char(iter) == '\n';
}
+gboolean
+gtk_text_iter_is_last (const GtkTextIter *iter)
+{
+ GtkTextRealIter *real;
+
+ g_return_val_if_fail(iter != NULL, FALSE);
+
+ real = gtk_text_iter_make_surreal(iter);
+
+ if (real == NULL)
+ return FALSE;
+
+ check_invariants(iter);
+
+ return gtk_text_line_is_last(real->line);
+}
+
+gboolean
+gtk_text_iter_is_first (const GtkTextIter *iter)
+{
+ return gtk_text_iter_get_offset (iter) == 0;
+}
+
gint
gtk_text_iter_get_chars_in_line (const GtkTextIter *iter)
{
@@ -933,10 +1027,45 @@ gtk_text_iter_get_chars_in_line (const GtkTextIter *iter)
return count;
}
+gboolean
+gtk_text_iter_get_style_values (const GtkTextIter *iter,
+ GtkTextStyleValues *values)
+{
+ GtkTextTag** tags;
+ gint tag_count = 0;
+
+ /* 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 FALSE;
+ }
+
+ /* Sort tags in ascending order of priority */
+ gtk_text_tag_array_sort (tags, tag_count);
+
+ gtk_text_style_values_fill_from_tags (values,
+ tags,
+ tag_count);
+
+ g_free (tags);
+
+ return TRUE;
+}
+
/*
* Increments/decrements
*/
+/* The return value of this indicates WHETHER WE MOVED.
+ * The return value of public functions indicates
+ * (MOVEMENT OCCURRED && NEW ITER IS DEREFERENCEABLE)
+ */
static gboolean
forward_line_leaving_caches_unmodified(GtkTextRealIter *real)
{
@@ -961,7 +1090,7 @@ forward_line_leaving_caches_unmodified(GtkTextRealIter *real)
real->segment = real->any_segment;
while (real->segment->char_count == 0)
real->segment = real->segment->next;
-
+
return TRUE;
}
else
@@ -1126,8 +1255,11 @@ gtk_text_iter_forward_indexable_segment(GtkTextIter *iter)
g_assert(gtk_text_iter_starts_line(iter));
check_invariants(iter);
-
- return TRUE;
+
+ if (gtk_text_iter_is_last (iter))
+ return FALSE;
+ else
+ return TRUE;
}
else
{
@@ -1145,10 +1277,12 @@ gtk_text_iter_backward_indexable_segment(GtkTextIter *iter)
{
g_warning("FIXME");
+
+ return FALSE;
}
gboolean
-gtk_text_iter_forward_char(GtkTextIter *iter)
+gtk_text_iter_next_char(GtkTextIter *iter)
{
GtkTextRealIter *real;
@@ -1166,7 +1300,7 @@ gtk_text_iter_forward_char(GtkTextIter *iter)
}
gboolean
-gtk_text_iter_backward_char(GtkTextIter *iter)
+gtk_text_iter_prev_char(GtkTextIter *iter)
{
g_return_val_if_fail(iter != NULL, FALSE);
@@ -1224,17 +1358,23 @@ gtk_text_iter_forward_chars(GtkTextIter *iter, gint count)
check_invariants(iter);
- current_char_index = gtk_text_iter_get_char_index(iter);
+ current_char_index = gtk_text_iter_get_offset(iter);
if (current_char_index == gtk_text_btree_char_count(real->tree))
return FALSE; /* can't move forward */
new_char_index = current_char_index + count;
- gtk_text_iter_set_char_index(iter, new_char_index);
+ gtk_text_iter_set_offset(iter, new_char_index);
check_invariants(iter);
- return TRUE;
+ /* Return FALSE if we're on the non-dereferenceable end
+ * iterator.
+ */
+ if (gtk_text_iter_is_last (iter))
+ return FALSE;
+ else
+ return TRUE;
}
}
@@ -1300,7 +1440,7 @@ gtk_text_iter_backward_chars(GtkTextIter *iter, gint count)
gint current_char_index;
gint new_char_index;
- current_char_index = gtk_text_iter_get_char_index(iter);
+ current_char_index = gtk_text_iter_get_offset(iter);
if (current_char_index == 0)
return FALSE; /* can't move backward */
@@ -1308,7 +1448,7 @@ gtk_text_iter_backward_chars(GtkTextIter *iter, gint count)
new_char_index = current_char_index - count;
if (new_char_index < 0)
new_char_index = 0;
- gtk_text_iter_set_char_index(iter, new_char_index);
+ gtk_text_iter_set_offset(iter, new_char_index);
check_invariants(iter);
@@ -1336,8 +1476,11 @@ gtk_text_iter_forward_line(GtkTextIter *iter)
adjust_line_number(real, 1);
check_invariants(iter);
-
- return TRUE;
+
+ if (gtk_text_iter_is_last (iter))
+ return FALSE;
+ else
+ return TRUE;
}
else
{
@@ -1423,13 +1566,13 @@ gtk_text_iter_forward_lines(GtkTextIter *iter, gint count)
{
gint old_line;
- old_line = gtk_text_iter_get_line_number(iter);
+ old_line = gtk_text_iter_get_line(iter);
- gtk_text_iter_set_line_number(iter, old_line + count);
+ gtk_text_iter_set_line(iter, old_line + count);
check_invariants(iter);
- return (gtk_text_iter_get_line_number(iter) != old_line);
+ return (gtk_text_iter_get_line(iter) != old_line);
}
}
@@ -1448,93 +1591,161 @@ gtk_text_iter_backward_lines(GtkTextIter *iter, gint count)
{
gint old_line;
- old_line = gtk_text_iter_get_line_number(iter);
+ old_line = gtk_text_iter_get_line(iter);
- gtk_text_iter_set_line_number(iter, MAX(old_line - count, 0));
+ gtk_text_iter_set_line(iter, MAX(old_line - count, 0));
- return (gtk_text_iter_get_line_number(iter) != old_line);
+ return (gtk_text_iter_get_line(iter) != old_line);
}
}
-static gboolean
-is_word_char(gunichar ch, gpointer user_data)
-{
- /* will likely need some i18n help FIXME */
- return isalpha(ch);
-}
+typedef gboolean (* FindLogAttrFunc) (PangoLogAttr *attrs,
+ gint offset,
+ gint min_offset,
+ gint len,
+ gint *found_offset);
static gboolean
-is_not_word_char(gunichar ch, gpointer user_data)
+find_word_end_func (PangoLogAttr *attrs,
+ gint offset,
+ gint min_offset,
+ gint len,
+ gint *found_offset)
{
- return !is_word_char(ch, user_data);
+ ++offset; /* We always go to the NEXT word end */
+
+ /* Find start 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)
+ ++offset;
+
+ *found_offset = offset;
+
+ return offset < min_offset + len;
}
static gboolean
-gtk_text_iter_is_in_word(const GtkTextIter *iter)
+find_word_start_func (PangoLogAttr *attrs,
+ gint offset,
+ gint min_offset,
+ gint len,
+ gint *found_offset)
{
- gint ch;
-
- ch = gtk_text_iter_get_char(iter);
+ --offset; /* We always go to the NEXT word start */
+
+ /* Find end of prev word */
+ while (offset >= min_offset &&
+ attrs[offset].is_white)
+ --offset;
+
+ /* Find start */
+ while (offset >= min_offset &&
+ !attrs[offset].is_word_stop)
+ --offset;
+
+ *found_offset = offset;
- return is_word_char(ch, NULL);
+ return offset >= min_offset;
}
-gboolean
-gtk_text_iter_forward_word_end(GtkTextIter *iter)
-{
- gboolean in_word;
+/* FIXME this function is very, very gratuitously slow */
+static gboolean
+find_by_log_attrs (GtkTextIter *iter,
+ FindLogAttrFunc func,
+ gboolean forward)
+{
+ GtkTextIter orig;
GtkTextIter start;
+ GtkTextIter end;
+ gchar *paragraph;
+ gint char_len, byte_len;
+ PangoLogAttr *attrs;
+ int offset;
+ gboolean found = 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);
- in_word = gtk_text_iter_is_in_word(iter);
+ paragraph = gtk_text_iter_get_text (&start, &end);
+ char_len = g_utf8_strlen (paragraph, -1);
+ byte_len = strlen (paragraph);
- if (!in_word)
+ offset = gtk_text_iter_get_line_offset (iter);
+
+ if (char_len > 0 && offset < char_len)
{
- if (!gtk_text_iter_forward_find_char(iter, is_word_char, NULL))
- return !gtk_text_iter_equal(iter, &start);
- else
- in_word = TRUE;
- }
+ gchar *lang;
+
+ attrs = g_new (PangoLogAttr, char_len);
+
+ lang = gtk_text_iter_get_language (iter);
- g_assert(in_word);
-
- gtk_text_iter_forward_find_char(iter, is_not_word_char, NULL);
+ pango_get_log_attrs (paragraph, byte_len, -1,
+ lang,
+ attrs);
- return !gtk_text_iter_equal(iter, &start);
-}
+ g_free (lang);
-gboolean
-gtk_text_iter_backward_word_start(GtkTextIter *iter)
-{
- gboolean in_word;
- GtkTextIter start;
+ found = (* func) (attrs, offset, 0, char_len, &offset);
+
+ g_free (attrs);
+ }
- g_return_val_if_fail(iter != NULL, FALSE);
-
- start = *iter;
+ g_free (paragraph);
- in_word = gtk_text_iter_is_in_word(iter);
-
- if (!in_word)
+ if (!found)
{
- if (!gtk_text_iter_backward_find_char(iter, is_word_char, NULL))
- return !gtk_text_iter_equal(iter, &start);
+ if (forward)
+ {
+ if (gtk_text_iter_forward_line (iter))
+ return find_by_log_attrs (iter, func, forward);
+ else
+ return FALSE;
+ }
else
- in_word = TRUE;
+ {
+ if (gtk_text_iter_backward_line (iter))
+ return find_by_log_attrs (iter, func, forward);
+ else
+ return FALSE;
+ }
}
+ else
+ {
+ gtk_text_iter_set_line_offset (iter, offset);
+
+ return
+ !gtk_text_iter_equal(iter, &orig) &&
+ !gtk_text_iter_is_last (iter);
+ }
+}
- g_assert(in_word);
-
- gtk_text_iter_backward_find_char(iter, is_not_word_char, NULL);
- gtk_text_iter_forward_char(iter); /* point to first char of word,
- not first non-word char. */
-
- return !gtk_text_iter_equal(iter, &start);
+gboolean
+gtk_text_iter_forward_word_end(GtkTextIter *iter)
+{
+ return find_by_log_attrs (iter, find_word_end_func, TRUE);
+}
+
+gboolean
+gtk_text_iter_backward_word_start(GtkTextIter *iter)
+{
+ return find_by_log_attrs (iter, find_word_start_func, FALSE);
}
+/* FIXME a loop around a truly slow function means
+ * a truly spectacularly slow function.
+ */
gboolean
gtk_text_iter_forward_word_ends(GtkTextIter *iter,
gint count)
@@ -1575,64 +1786,8 @@ gtk_text_iter_backward_word_starts(GtkTextIter *iter,
return TRUE;
}
-/* up/down lines maintain the char offset, while forward/backward lines
- always sets the char offset to 0. */
-gboolean
-gtk_text_iter_up_lines (GtkTextIter *iter,
- gint count)
-{
- gint char_offset;
-
- if (count < 0)
- return gtk_text_iter_down_lines(iter, 0 - count);
-
- char_offset = gtk_text_iter_get_line_char(iter);
-
- if (!gtk_text_iter_backward_line(iter))
- return FALSE;
- --count;
-
- while (count > 0)
- {
- if (!gtk_text_iter_backward_line(iter))
- break;
- --count;
- }
-
- gtk_text_iter_set_line_char(iter, char_offset);
-
- return TRUE;
-}
-
-gboolean
-gtk_text_iter_down_lines (GtkTextIter *iter,
- gint count)
-{
- gint char_offset;
-
- if (count < 0)
- return gtk_text_iter_up_lines(iter, 0 - count);
-
- char_offset = gtk_text_iter_get_line_char(iter);
-
- if (!gtk_text_iter_forward_line(iter))
- return FALSE;
- --count;
-
- while (count > 0)
- {
- if (!gtk_text_iter_forward_line(iter))
- break;
- --count;
- }
-
- gtk_text_iter_set_line_char(iter, char_offset);
-
- return TRUE;
-}
-
void
-gtk_text_iter_set_line_char(GtkTextIter *iter,
+gtk_text_iter_set_line_offset(GtkTextIter *iter,
gint char_on_line)
{
GtkTextRealIter *real;
@@ -1652,7 +1807,7 @@ gtk_text_iter_set_line_char(GtkTextIter *iter,
}
void
-gtk_text_iter_set_line_number(GtkTextIter *iter, gint line_number)
+gtk_text_iter_set_line(GtkTextIter *iter, gint line_number)
{
GtkTextLine *line;
gint real_line;
@@ -1678,7 +1833,7 @@ gtk_text_iter_set_line_number(GtkTextIter *iter, gint line_number)
}
void
-gtk_text_iter_set_char_index(GtkTextIter *iter, gint char_index)
+gtk_text_iter_set_offset(GtkTextIter *iter, gint char_index)
{
GtkTextLine *line;
GtkTextRealIter *real;
@@ -1737,13 +1892,13 @@ gtk_text_iter_forward_to_newline(GtkTextIter *iter)
g_return_val_if_fail(iter != NULL, FALSE);
- current_offset = gtk_text_iter_get_line_char(iter);
+ current_offset = gtk_text_iter_get_line_offset(iter);
new_offset = gtk_text_iter_get_chars_in_line(iter) - 1;
if (current_offset < new_offset)
{
/* Move to end of this line. */
- gtk_text_iter_set_line_char(iter, new_offset);
+ gtk_text_iter_set_line_offset(iter, new_offset);
return TRUE;
}
else
@@ -1760,8 +1915,8 @@ gtk_text_iter_forward_to_newline(GtkTextIter *iter)
}
gboolean
-gtk_text_iter_forward_find_tag_toggle (GtkTextIter *iter,
- GtkTextTag *tag)
+gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
+ GtkTextTag *tag)
{
GtkTextLine *next_line;
GtkTextLine *current_line;
@@ -1813,13 +1968,22 @@ gtk_text_iter_forward_find_tag_toggle (GtkTextIter *iter,
}
}
+ /* Check end iterator for tags */
+ if (gtk_text_iter_toggles_tag(iter, tag))
+ {
+ /* If there's a toggle here, it isn't indexable so
+ any_segment can't be the indexable segment. */
+ g_assert(real->any_segment != real->segment);
+ return TRUE;
+ }
+
/* Reached end of buffer */
return FALSE;
}
gboolean
-gtk_text_iter_backward_find_tag_toggle (GtkTextIter *iter,
- GtkTextTag *tag)
+gtk_text_iter_backward_to_tag_toggle (GtkTextIter *iter,
+ GtkTextTag *tag)
{
g_warning("FIXME");
@@ -1827,7 +1991,7 @@ gtk_text_iter_backward_find_tag_toggle (GtkTextIter *iter,
static gboolean
matches_pred(GtkTextIter *iter,
- GtkTextViewCharPredicate pred,
+ GtkTextCharPredicate pred,
gpointer user_data)
{
gint ch;
@@ -1839,13 +2003,13 @@ matches_pred(GtkTextIter *iter,
gboolean
gtk_text_iter_forward_find_char (GtkTextIter *iter,
- GtkTextViewCharPredicate pred,
+ GtkTextCharPredicate pred,
gpointer user_data)
{
g_return_val_if_fail(iter != NULL, FALSE);
g_return_val_if_fail(pred != NULL, FALSE);
- while (gtk_text_iter_forward_char(iter))
+ while (gtk_text_iter_next_char(iter))
{
if (matches_pred(iter, pred, user_data))
return TRUE;
@@ -1856,13 +2020,13 @@ gtk_text_iter_forward_find_char (GtkTextIter *iter,
gboolean
gtk_text_iter_backward_find_char (GtkTextIter *iter,
- GtkTextViewCharPredicate pred,
+ GtkTextCharPredicate pred,
gpointer user_data)
{
g_return_val_if_fail(iter != NULL, FALSE);
g_return_val_if_fail(pred != NULL, FALSE);
- while (gtk_text_iter_backward_char(iter))
+ while (gtk_text_iter_prev_char(iter))
{
if (matches_pred(iter, pred, user_data))
return TRUE;
@@ -1871,6 +2035,212 @@ gtk_text_iter_backward_find_char (GtkTextIter *iter,
return FALSE;
}
+static gboolean
+lines_match (const GtkTextIter *start,
+ const gchar **lines,
+ gboolean visible_only,
+ gboolean slice,
+ GtkTextIter *match_start)
+{
+ GtkTextIter next;
+ gchar *line_text;
+ const gchar *found;
+ gint offset;
+
+ if (*lines == NULL || **lines == '\0')
+ return TRUE;
+
+ next = *start;
+ gtk_text_iter_forward_line (&next);
+
+ gtk_text_iter_spew (start, "start");
+ gtk_text_iter_spew (&next, "next");
+
+ /* No more text in buffer, but *lines is nonempty */
+ if (gtk_text_iter_equal (start, &next))
+ {
+ return FALSE;
+ }
+
+ if (slice)
+ {
+ if (visible_only)
+ line_text = gtk_text_iter_get_visible_slice (start, &next);
+ else
+ line_text = gtk_text_iter_get_slice (start, &next);
+ }
+ else
+ {
+ /* FIXME */
+ g_warning ("Searching for non-slice text is currently broken (you must include 'unknown char' for pixmaps in order to match them)");
+ if (visible_only)
+ line_text = gtk_text_iter_get_visible_text (start, &next);
+ else
+ line_text = gtk_text_iter_get_text (start, &next);
+ }
+
+ if (match_start) /* if this is the first line we're matching */
+ found = strstr (line_text, *lines);
+ else
+ {
+ /* If it's not the first line, we have to match from the
+ * start of the line.
+ */
+ if (strncmp (line_text, *lines, strlen (*lines)) == 0)
+ found = line_text;
+ else
+ found = NULL;
+ }
+
+ if (found == NULL)
+ {
+ g_free (line_text);
+ return FALSE;
+ }
+
+ /* Get offset to start of search string */
+ offset = g_utf8_strlen (line_text, found - line_text);
+
+ next = *start;
+
+ /* If match start needs to be returned, set it to the
+ * start of the search string.
+ */
+ if (match_start)
+ {
+ *match_start = next;
+ gtk_text_iter_forward_chars (match_start, offset);
+ }
+
+ /* Go to end of search string */
+ offset += g_utf8_strlen (*lines, -1);
+
+ gtk_text_iter_forward_chars (&next, offset);
+
+ g_free (line_text);
+
+ ++lines;
+
+ /* pass NULL for match_start, since we don't need to find the
+ * start again.
+ */
+ return lines_match (&next, lines, visible_only, slice, NULL);
+}
+
+/* strsplit() that retains the delimiter as part of the string. */
+static gchar **
+strbreakup (const char *string,
+ const char *delimiter,
+ gint max_tokens)
+{
+ GSList *string_list = NULL, *slist;
+ gchar **str_array, *s;
+ guint i, n = 1;
+
+ g_return_val_if_fail (string != NULL, NULL);
+ g_return_val_if_fail (delimiter != NULL, NULL);
+
+ if (max_tokens < 1)
+ max_tokens = G_MAXINT;
+
+ s = strstr (string, delimiter);
+ if (s)
+ {
+ guint delimiter_len = strlen (delimiter);
+
+ do
+ {
+ guint len;
+ gchar *new_string;
+
+ len = s - string + delimiter_len;
+ new_string = g_new (gchar, len + 1);
+ strncpy (new_string, string, len);
+ new_string[len] = 0;
+ string_list = g_slist_prepend (string_list, new_string);
+ n++;
+ string = s + delimiter_len;
+ s = strstr (string, delimiter);
+ }
+ while (--max_tokens && s);
+ }
+ if (*string)
+ {
+ n++;
+ string_list = g_slist_prepend (string_list, g_strdup (string));
+ }
+
+ str_array = g_new (gchar*, n);
+
+ i = n - 1;
+
+ str_array[i--] = NULL;
+ for (slist = string_list; slist; slist = slist->next)
+ str_array[i--] = slist->data;
+
+ g_slist_free (string_list);
+
+ return str_array;
+}
+
+gboolean
+gtk_text_iter_forward_search (GtkTextIter *iter,
+ const char *str,
+ gboolean visible_only,
+ gboolean slice)
+{
+ gchar **lines = NULL;
+ GtkTextIter match;
+ gboolean retval = FALSE;
+ GtkTextIter search;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (str != NULL, FALSE);
+
+ if (*str == '\0')
+ return TRUE; /* we found the empty string */
+
+ /* locate all lines */
+
+ lines = strbreakup (str, "\n", -1);
+
+ search = *iter;
+
+ do
+ {
+ /* This loop has an inefficient worst-case, where
+ * gtk_text_iter_get_text() is called repeatedly on
+ * a single line.
+ */
+ if (lines_match (&search, (const gchar**)lines, visible_only, slice, &match))
+ {
+ retval = TRUE;
+
+ *iter = match;
+
+ break;
+ }
+ }
+ while (gtk_text_iter_forward_line (&search));
+
+ g_strfreev ((gchar**)lines);
+
+ return retval;
+}
+
+gboolean
+gtk_text_iter_backward_search (GtkTextIter *iter,
+ const char *str,
+ gboolean visible_only,
+ gboolean slice)
+{
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (str != NULL, FALSE);
+
+
+
+}
+
/*
* Comparisons
*/
@@ -1949,8 +2319,8 @@ gtk_text_iter_compare(const GtkTextIter *lhs, const GtkTextIter *rhs)
{
gint line1, line2;
- line1 = gtk_text_iter_get_line_number(lhs);
- line2 = gtk_text_iter_get_line_number(rhs);
+ line1 = gtk_text_iter_get_line(lhs);
+ line2 = gtk_text_iter_get_line(rhs);
if (line1 < line2)
return -1;
else if (line1 > line2)
@@ -2096,7 +2466,7 @@ gtk_text_btree_get_iter_at_first_toggle (GtkTextBTree *tree,
else
{
iter_init_from_byte_offset(iter, tree, line, 0);
- gtk_text_iter_forward_find_tag_toggle(iter, tag);
+ gtk_text_iter_forward_to_tag_toggle(iter, tag);
check_invariants(iter);
return TRUE;
}
@@ -2124,24 +2494,13 @@ gtk_text_btree_get_iter_at_last_toggle (GtkTextBTree *tree,
else
{
iter_init_from_byte_offset(iter, tree, line, -1);
- gtk_text_iter_backward_find_tag_toggle(iter, tag);
+ gtk_text_iter_backward_to_tag_toggle(iter, tag);
check_invariants(iter);
return TRUE;
}
}
gboolean
-gtk_text_btree_get_iter_from_string (GtkTextBTree *tree,
- GtkTextIter *iter,
- const gchar *string)
-{
- g_return_val_if_fail(iter != NULL, FALSE);
- g_return_val_if_fail(tree != NULL, FALSE);
-
- g_warning("FIXME");
-}
-
-gboolean
gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree,
GtkTextIter *iter,
const gchar *mark_name)
@@ -2176,7 +2535,7 @@ gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
iter_init_from_segment(iter, tree,
seg->body.mark.line, seg);
- g_assert(seg->body.mark.line == gtk_text_iter_get_line(iter));
+ g_assert(seg->body.mark.line == gtk_text_iter_get_text_line(iter));
check_invariants(iter);
}
@@ -2207,10 +2566,10 @@ gtk_text_iter_spew (const GtkTextIter *iter, const gchar *desc)
check_invariants(iter);
g_print(" %20s: line %d / char %d / line char %d / line byte %d\n",
desc,
- gtk_text_iter_get_line_number(iter),
- gtk_text_iter_get_char_index(iter),
- gtk_text_iter_get_line_char(iter),
- gtk_text_iter_get_line_byte(iter));
+ gtk_text_iter_get_line(iter),
+ gtk_text_iter_get_offset(iter),
+ gtk_text_iter_get_line_offset(iter),
+ gtk_text_iter_get_line_index(iter));
check_invariants(iter);
}
}