*/
#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
+#include <config.h>
#include "gtktextiter.h"
#include "gtktextbtree.h"
#include "gtktextiterprivate.h"
#include "gtkdebug.h"
+#include "gtkalias.h"
#include <string.h>
#define FIX_OVERFLOWS(varname) if ((varname) == G_MININT) (varname) = G_MININT + 1
return real->segment_byte_offset == 0 || real->segment_char_offset == 0;
}
-#if 1
+#ifdef G_ENABLE_DEBUG
static void
check_invariants (const GtkTextIter *iter)
{
_gtk_text_iter_check (iter);
}
#else
-#define check_invariants (x)
+#define check_invariants(x)
#endif
/**
g_return_val_if_fail (iter != NULL, NULL);
- new_iter = g_new (GtkTextIter, 1);
+ new_iter = g_slice_new (GtkTextIter);
*new_iter = *iter;
{
g_return_if_fail (iter != NULL);
- g_free (iter);
+ g_slice_free (GtkTextIter, iter);
}
GType
static GType our_type = 0;
if (our_type == 0)
- our_type = g_boxed_type_register_static ("GtkTypeTextIter",
+ our_type = g_boxed_type_register_static ("GtkTextIter",
(GBoxedCopyFunc) gtk_text_iter_copy,
(GBoxedFreeFunc) gtk_text_iter_free);
{
GtkTextRealIter *real;
- g_return_val_if_fail (iter != NULL, 0);
+ g_return_val_if_fail (iter != NULL, NULL);
real = gtk_text_iter_make_real (iter);
{
GtkTextRealIter *real;
- g_return_val_if_fail (iter != NULL, 0);
+ g_return_val_if_fail (iter != NULL, NULL);
real = gtk_text_iter_make_real (iter);
{
const GtkTextRealIter *real;
- g_return_val_if_fail (iter != NULL, 0);
+ g_return_val_if_fail (iter != NULL, NULL);
real = (const GtkTextRealIter*)iter;
{
const GtkTextRealIter *real;
- g_return_val_if_fail (iter != NULL, 0);
+ g_return_val_if_fail (iter != NULL, NULL);
real = (const GtkTextRealIter*)iter;
* @iter: an iterator
*
* Returns the Unicode character at this iterator. (Equivalent to
- * operator* on a C++ iterator.) If the iterator points at a
+ * operator* on a C++ iterator.) If the element at this iterator is a
* non-character element, such as an image embedded in the buffer, the
* Unicode "unknown" character 0xFFFC is returned. If invoked on
* the end iterator, zero is returned; zero is not a valid Unicode character.
* gtk_text_iter_get_pixbuf:
* @iter: an iterator
*
- * If the location pointed to by @iter contains a pixbuf, the pixbuf
- * is returned (with no new reference count added). Otherwise,
+ * If the element at @iter is a pixbuf, the pixbuf is returned
+ * (with no new reference count added). Otherwise,
* %NULL is returned.
*
* Return value: the pixbuf at @iter
* gtk_text_iter_get_child_anchor:
* @iter: an iterator
*
- * If the location pointed to by @iter contains a child anchor, the
+ * If the location at @iter contains a child anchor, the
* anchor is returned (with no new reference count added). Otherwise,
* %NULL is returned.
*
gboolean
gtk_text_iter_ends_line (const GtkTextIter *iter)
{
- GtkTextRealIter *real;
gunichar wc;
g_return_val_if_fail (iter != NULL, FALSE);
- real = gtk_text_iter_make_real (iter);
-
check_invariants (iter);
/* Only one character has type G_UNICODE_PARAGRAPH_SEPARATOR in
return TRUE;
else if (wc == '\n')
{
+ GtkTextIter tmp = *iter;
+
/* need to determine if a \r precedes the \n, in which case
- * we aren't the end of the line
+ * we aren't the end of the line.
+ * Note however that if \r and \n are on different lines, they
+ * both are terminators. This for instance may happen after
+ * deleting some text:
+
+ 1 some text\r delete 'a' 1 some text\r
+ 2 a\n ---------> 2 \n
+ 3 ... 3 ...
+
*/
- GtkTextIter tmp = *iter;
+
+ if (gtk_text_iter_get_line_offset (&tmp) == 0)
+ return TRUE;
+
if (!gtk_text_iter_backward_char (&tmp))
return TRUE;
gint count;
GtkTextLineSegment *seg;
- g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter != NULL, 0);
real = gtk_text_iter_make_surreal (iter);
gint count;
GtkTextLineSegment *seg;
- g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter != NULL, 0);
real = gtk_text_iter_make_surreal (iter);
}
}
-
+#if 0
/* The return value of this indicates WHETHER WE MOVED.
* The return value of public functions indicates
* (MOVEMENT OCCURRED && NEW ITER IS DEREFERENCEABLE)
+ *
+ * This function is currently unused, thus it is #if-0-ed. It is
+ * left here, since it's non-trivial code that might be useful in
+ * the future.
*/
static gboolean
backward_line_leaving_caches_unmodified (GtkTextRealIter *real)
return FALSE;
}
}
+#endif
/* The return value indicates (MOVEMENT OCCURRED && NEW ITER IS
* DEREFERENCEABLE)
g_assert (real->segment->char_count > 0);
g_assert (real->segment->type == >k_text_char_type);
- real->segment_char_offset -= count;
- g_assert (real->segment_char_offset >= 0);
-
if (real->line_byte_offset >= 0)
{
+ const char *p;
gint new_byte_offset;
- gint i;
-
- new_byte_offset = 0;
- i = 0;
- while (i < real->segment_char_offset)
- {
- const char * start = real->segment->body.chars + new_byte_offset;
- new_byte_offset += g_utf8_next_char (start) - start;
- ++i;
- }
+ /* if in the last fourth of the segment walk backwards */
+ if (count < real->segment_char_offset / 4)
+ p = g_utf8_offset_to_pointer (real->segment->body.chars + real->segment_byte_offset,
+ -count);
+ else
+ p = g_utf8_offset_to_pointer (real->segment->body.chars,
+ real->segment_char_offset - count);
+ new_byte_offset = p - real->segment->body.chars;
real->line_byte_offset -= (real->segment_byte_offset - new_byte_offset);
real->segment_byte_offset = new_byte_offset;
}
+ real->segment_char_offset -= count;
real->line_char_offset -= count;
adjust_char_index (real, 0 - count);
}
}
+/**
+ * gtk_text_iter_forward_visible_line:
+ * @iter: an iterator
+ *
+ * Moves @iter to the start of the next visible line. Returns %TRUE if there
+ * was a next line to move to, and %FALSE if @iter was simply moved to
+ * the end of the buffer and is now not dereferenceable, or if @iter was
+ * already at the end of the buffer.
+ *
+ * Return value: whether @iter can be dereferenced
+ *
+ * Since: 2.8
+ **/
+gboolean
+gtk_text_iter_forward_visible_line (GtkTextIter *iter)
+{
+ while (gtk_text_iter_forward_line (iter))
+ {
+ if (!_gtk_text_btree_char_is_invisible (iter))
+ return TRUE;
+ else
+ {
+ do
+ {
+ if (!gtk_text_iter_forward_char (iter))
+ return FALSE;
+
+ if (!_gtk_text_btree_char_is_invisible (iter))
+ return TRUE;
+ }
+ while (!gtk_text_iter_ends_line (iter));
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_text_iter_backward_visible_line:
+ * @iter: an iterator
+ *
+ * Moves @iter to the start of the previous visible line. Returns %TRUE if
+ * @iter could be moved; i.e. if @iter was at character offset 0, this
+ * function returns %FALSE. Therefore if @iter was already on line 0,
+ * but not at the start of the line, @iter is snapped to the start of
+ * the line and the function returns %TRUE. (Note that this implies that
+ * in a loop calling this function, the line number may not change on
+ * every iteration, if your first iteration is on line 0.)
+ *
+ * Return value: whether @iter moved
+ *
+ * Since: 2.8
+ **/
+gboolean
+gtk_text_iter_backward_visible_line (GtkTextIter *iter)
+{
+ while (gtk_text_iter_backward_line (iter))
+ {
+ if (!_gtk_text_btree_char_is_invisible (iter))
+ return TRUE;
+ else
+ {
+ do
+ {
+ if (!gtk_text_iter_backward_char (iter))
+ return FALSE;
+
+ if (!_gtk_text_btree_char_is_invisible (iter))
+ return TRUE;
+ }
+ while (!gtk_text_iter_starts_line (iter));
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_text_iter_forward_visible_lines:
+ * @iter: a #GtkTextIter
+ * @count: number of lines to move forward
+ *
+ * Moves @count visible lines forward, if possible (if @count would move
+ * past the start or end of the buffer, moves to the start or end of
+ * the buffer). The return value indicates whether the iterator moved
+ * onto a dereferenceable position; if the iterator didn't move, or
+ * moved onto the end iterator, then %FALSE is returned. If @count is 0,
+ * the function does nothing and returns %FALSE. If @count is negative,
+ * moves backward by 0 - @count lines.
+ *
+ * Return value: whether @iter moved and is dereferenceable
+ *
+ * Since: 2.8
+ **/
+gboolean
+gtk_text_iter_forward_visible_lines (GtkTextIter *iter,
+ gint count)
+{
+ FIX_OVERFLOWS (count);
+
+ if (count < 0)
+ return gtk_text_iter_backward_visible_lines (iter, 0 - count);
+ else if (count == 0)
+ return FALSE;
+ else if (count == 1)
+ {
+ check_invariants (iter);
+ return gtk_text_iter_forward_visible_line (iter);
+ }
+ else
+ {
+ while (gtk_text_iter_forward_visible_line (iter) && count > 0)
+ count--;
+ return count == 0;
+ }
+}
+
+/**
+ * gtk_text_iter_backward_visible_lines:
+ * @iter: a #GtkTextIter
+ * @count: number of lines to move backward
+ *
+ * Moves @count visible lines backward, if possible (if @count would move
+ * past the start or end of the buffer, moves to the start or end of
+ * the buffer). The return value indicates whether the iterator moved
+ * onto a dereferenceable position; if the iterator didn't move, or
+ * moved onto the end iterator, then %FALSE is returned. If @count is 0,
+ * the function does nothing and returns %FALSE. If @count is negative,
+ * moves forward by 0 - @count lines.
+ *
+ * Return value: whether @iter moved and is dereferenceable
+ *
+ * Since: 2.8
+ **/
+gboolean
+gtk_text_iter_backward_visible_lines (GtkTextIter *iter,
+ gint count)
+{
+ FIX_OVERFLOWS (count);
+
+ if (count < 0)
+ return gtk_text_iter_forward_visible_lines (iter, 0 - count);
+ else if (count == 0)
+ return FALSE;
+ else if (count == 1)
+ {
+ return gtk_text_iter_backward_visible_line (iter);
+ }
+ else
+ {
+ while (gtk_text_iter_backward_visible_line (iter) && count > 0)
+ count--;
+ return count == 0;
+ }
+}
+
typedef gboolean (* FindLogAttrFunc) (const PangoLogAttr *attrs,
gint offset,
gint min_offset,
!(attrs[offset].is_word_start || attrs[offset].is_word_end))
--offset;
- return attrs[offset].is_word_start;
+ if (offset >= 0)
+ return attrs[offset].is_word_start;
+ else
+ return FALSE;
}
/* Sentence funcs */
}
}
+static gboolean
+find_visible_by_log_attrs (GtkTextIter *iter,
+ FindLogAttrFunc func,
+ gboolean forward,
+ gboolean already_moved_initially)
+{
+ GtkTextIter pos;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ pos = *iter;
+
+ while (find_by_log_attrs (&pos, func, forward, already_moved_initially))
+ {
+ if (!_gtk_text_btree_char_is_invisible (&pos))
+ {
+ *iter = pos;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+typedef gboolean (* OneStepFunc) (GtkTextIter *iter);
+typedef gboolean (* MultipleStepFunc) (GtkTextIter *iter, gint count);
+
+static gboolean
+move_multiple_steps (GtkTextIter *iter,
+ gint count,
+ OneStepFunc step_forward,
+ MultipleStepFunc n_steps_backward)
+{
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ FIX_OVERFLOWS (count);
+
+ if (count == 0)
+ return FALSE;
+
+ if (count < 0)
+ return n_steps_backward (iter, -count);
+
+ if (!step_forward (iter))
+ return FALSE;
+ --count;
+
+ while (count > 0)
+ {
+ if (!step_forward (iter))
+ break;
+ --count;
+ }
+
+ return !gtk_text_iter_is_end (iter);
+}
+
+
/**
* gtk_text_iter_forward_word_end:
* @iter: a #GtkTextIter
gtk_text_iter_forward_word_ends (GtkTextIter *iter,
gint count)
{
- g_return_val_if_fail (iter != NULL, FALSE);
-
- FIX_OVERFLOWS (count);
-
- if (count == 0)
- return FALSE;
-
- if (count < 0)
- return gtk_text_iter_backward_word_starts (iter, -count);
-
- if (!gtk_text_iter_forward_word_end (iter))
- return FALSE;
- --count;
-
- while (count > 0)
- {
- if (!gtk_text_iter_forward_word_end (iter))
- break;
- --count;
- }
-
- return !gtk_text_iter_is_end (iter);
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_forward_word_end,
+ gtk_text_iter_backward_word_starts);
}
/**
gtk_text_iter_backward_word_starts (GtkTextIter *iter,
gint count)
{
- g_return_val_if_fail (iter != NULL, FALSE);
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_backward_word_start,
+ gtk_text_iter_forward_word_ends);
+}
- FIX_OVERFLOWS (count);
-
- if (count < 0)
- return gtk_text_iter_forward_word_ends (iter, -count);
+/**
+ * gtk_text_iter_forward_visible_word_end:
+ * @iter: a #GtkTextIter
+ *
+ * Moves forward to the next visible word end. (If @iter is currently on a
+ * word end, moves forward to the next one after that.) Word breaks
+ * are determined by Pango and should be correct for nearly any
+ * language (if not, the correct fix would be to the Pango word break
+ * algorithms).
+ *
+ * Return value: %TRUE if @iter moved and is not the end iterator
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_iter_forward_visible_word_end (GtkTextIter *iter)
+{
+ return find_visible_by_log_attrs (iter, find_word_end_func, TRUE, FALSE);
+}
- if (!gtk_text_iter_backward_word_start (iter))
- return FALSE;
- --count;
+/**
+ * gtk_text_iter_backward_visible_word_start:
+ * @iter: a #GtkTextIter
+ *
+ * Moves backward to the previous visible word start. (If @iter is currently
+ * on a word start, moves backward to the next one after that.) Word breaks
+ * are determined by Pango and should be correct for nearly any
+ * language (if not, the correct fix would be to the Pango word break
+ * algorithms).
+ *
+ * Return value: %TRUE if @iter moved and is not the end iterator
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_iter_backward_visible_word_start (GtkTextIter *iter)
+{
+ return find_visible_by_log_attrs (iter, find_word_start_func, FALSE, FALSE);
+}
- while (count > 0)
- {
- if (!gtk_text_iter_backward_word_start (iter))
- break;
- --count;
- }
+/**
+ * gtk_text_iter_forward_visible_word_ends:
+ * @iter: a #GtkTextIter
+ * @count: number of times to move
+ *
+ * Calls gtk_text_iter_forward_visible_word_end() up to @count times.
+ *
+ * Return value: %TRUE if @iter moved and is not the end iterator
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_iter_forward_visible_word_ends (GtkTextIter *iter,
+ gint count)
+{
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_forward_visible_word_end,
+ gtk_text_iter_backward_visible_word_starts);
+}
- return !gtk_text_iter_is_end (iter);
+/**
+ * gtk_text_iter_backward_visible_word_starts
+ * @iter: a #GtkTextIter
+ * @count: number of times to move
+ *
+ * Calls gtk_text_iter_backward_visible_word_start() up to @count times.
+ *
+ * Return value: %TRUE if @iter moved and is not the end iterator
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_iter_backward_visible_word_starts (GtkTextIter *iter,
+ gint count)
+{
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_backward_visible_word_start,
+ gtk_text_iter_forward_visible_word_ends);
}
/**
gtk_text_iter_forward_sentence_ends (GtkTextIter *iter,
gint count)
{
- g_return_val_if_fail (iter != NULL, FALSE);
-
- if (count == 0)
- return FALSE;
-
- if (count < 0)
- return gtk_text_iter_backward_sentence_starts (iter, -count);
-
- if (!gtk_text_iter_forward_sentence_end (iter))
- return FALSE;
- --count;
-
- while (count > 0)
- {
- if (!gtk_text_iter_forward_sentence_end (iter))
- break;
- --count;
- }
-
- return !gtk_text_iter_is_end (iter);
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_forward_sentence_end,
+ gtk_text_iter_backward_sentence_starts);
}
/**
gtk_text_iter_backward_sentence_starts (GtkTextIter *iter,
gint count)
{
- g_return_val_if_fail (iter != NULL, FALSE);
-
- if (count < 0)
- return gtk_text_iter_forward_sentence_ends (iter, -count);
-
- if (!gtk_text_iter_backward_sentence_start (iter))
- return FALSE;
- --count;
-
- while (count > 0)
- {
- if (!gtk_text_iter_backward_sentence_start (iter))
- break;
- --count;
- }
-
- return !gtk_text_iter_is_end (iter);
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_backward_sentence_start,
+ gtk_text_iter_forward_sentence_ends);
}
static gboolean
*
* Like gtk_text_iter_forward_cursor_position(), but moves backward.
*
- * Return value: %TRUE if we moved and the new position is dereferenceable
+ * Return value: %TRUE if we moved
**/
gboolean
gtk_text_iter_backward_cursor_position (GtkTextIter *iter)
gtk_text_iter_forward_cursor_positions (GtkTextIter *iter,
gint count)
{
- g_return_val_if_fail (iter != NULL, FALSE);
-
- FIX_OVERFLOWS (count);
-
- if (count == 0)
- return FALSE;
-
- if (count < 0)
- return gtk_text_iter_backward_cursor_positions (iter, -count);
-
- if (!gtk_text_iter_forward_cursor_position (iter))
- return FALSE;
- --count;
-
- while (count > 0)
- {
- if (!gtk_text_iter_forward_cursor_position (iter))
- break;
- --count;
- }
-
- return !gtk_text_iter_is_end (iter);
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_forward_cursor_position,
+ gtk_text_iter_backward_cursor_positions);
}
/**
gtk_text_iter_backward_cursor_positions (GtkTextIter *iter,
gint count)
{
- g_return_val_if_fail (iter != NULL, FALSE);
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_backward_cursor_position,
+ gtk_text_iter_forward_cursor_positions);
+}
- FIX_OVERFLOWS (count);
-
- if (count == 0)
- return FALSE;
+/**
+ * gtk_text_iter_forward_visible_cursor_position:
+ * @iter: a #GtkTextIter
+ *
+ * Moves @iter forward to the next visible cursor position. See
+ * gtk_text_iter_forward_cursor_position() for details.
+ *
+ * Return value: %TRUE if we moved and the new position is dereferenceable
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_iter_forward_visible_cursor_position (GtkTextIter *iter)
+{
+ return find_visible_by_log_attrs (iter, find_forward_cursor_pos_func, TRUE, FALSE);
+}
- if (count < 0)
- return gtk_text_iter_forward_cursor_positions (iter, -count);
-
- if (!gtk_text_iter_backward_cursor_position (iter))
- return FALSE;
- --count;
+/**
+ * gtk_text_iter_backward_visible_cursor_position:
+ * @iter: a #GtkTextIter
+ *
+ * Moves @iter forward to the previous visible cursor position. See
+ * gtk_text_iter_backward_cursor_position() for details.
+ *
+ * Return value: %TRUE if we moved and the new position is dereferenceable
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_iter_backward_visible_cursor_position (GtkTextIter *iter)
+{
+ return find_visible_by_log_attrs (iter, find_backward_cursor_pos_func, FALSE, FALSE);
+}
- while (count > 0)
- {
- if (!gtk_text_iter_backward_cursor_position (iter))
- break;
- --count;
- }
+/**
+ * gtk_text_iter_forward_visible_cursor_positions:
+ * @iter: a #GtkTextIter
+ * @count: number of positions to move
+ *
+ * Moves up to @count visible cursor positions. See
+ * gtk_text_iter_forward_cursor_position() for details.
+ *
+ * Return value: %TRUE if we moved and the new position is dereferenceable
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_iter_forward_visible_cursor_positions (GtkTextIter *iter,
+ gint count)
+{
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_forward_visible_cursor_position,
+ gtk_text_iter_backward_visible_cursor_positions);
+}
- return !gtk_text_iter_is_end (iter);
+/**
+ * gtk_text_iter_backward_visible_cursor_positions:
+ * @iter: a #GtkTextIter
+ * @count: number of positions to move
+ *
+ * Moves up to @count visible cursor positions. See
+ * gtk_text_iter_backward_cursor_position() for details.
+ *
+ * Return value: %TRUE if we moved and the new position is dereferenceable
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_text_iter_backward_visible_cursor_positions (GtkTextIter *iter,
+ gint count)
+{
+ return move_multiple_steps (iter, count,
+ gtk_text_iter_backward_visible_cursor_position,
+ gtk_text_iter_forward_visible_cursor_positions);
}
/**
g_return_if_fail (iter != NULL);
+ gtk_text_iter_set_line_offset (iter, 0);
+
pos = *iter;
/* For now we use a ludicrously slow implementation */
gtk_text_iter_forward_line (iter);
}
-static gint
-bytes_in_char (GtkTextIter *iter)
-{
- return g_unichar_to_utf8 (gtk_text_iter_get_char (iter), NULL);
-}
-
/**
* gtk_text_iter_set_visible_line_index:
* @iter: a #GtkTextIter
* in the index.
**/
void
-gtk_text_iter_set_visible_line_index (GtkTextIter *iter,
- gint byte_on_line)
+gtk_text_iter_set_visible_line_index (GtkTextIter *iter,
+ gint byte_on_line)
{
- gint bytes_seen = 0;
+ GtkTextRealIter *real;
+ gint bytes_in_line = 0;
+ gint offset = 0;
GtkTextIter pos;
-
- g_return_if_fail (iter != NULL);
+ GtkTextLineSegment *seg;
+ g_return_if_fail (iter != NULL);
+
+ gtk_text_iter_set_line_offset (iter, 0);
+
+ bytes_in_line = gtk_text_iter_get_bytes_in_line (iter);
+
pos = *iter;
- /* For now we use a ludicrously slow implementation */
- while (bytes_seen < byte_on_line)
+ real = gtk_text_iter_make_real (&pos);
+
+ if (real == NULL)
+ return;
+
+ ensure_byte_offsets (real);
+
+ check_invariants (&pos);
+
+ seg = _gtk_text_iter_get_indexable_segment (&pos);
+
+ while (seg != NULL && byte_on_line > 0)
{
if (!_gtk_text_btree_char_is_invisible (&pos))
- bytes_seen += bytes_in_char (&pos);
-
- if (!gtk_text_iter_forward_char (&pos))
- break;
+ {
+ if (byte_on_line < seg->byte_count)
+ {
+ iter_set_from_byte_offset (real, real->line, offset + byte_on_line);
+ byte_on_line = 0;
+ break;
+ }
+ else
+ byte_on_line -= seg->byte_count;
+ }
- if (bytes_seen >= byte_on_line)
- break;
+ offset += seg->byte_count;
+ _gtk_text_iter_forward_indexable_segment (&pos);
+ seg = _gtk_text_iter_get_indexable_segment (&pos);
}
- if (bytes_seen > byte_on_line)
- g_warning ("%s: Incorrect visible byte index %d falls in the middle of a UTF-8 "
- "character; this will crash the text buffer. "
- "Byte indexes must refer to the start of a character.",
- G_STRLOC, byte_on_line);
-
- if (_gtk_text_iter_get_text_line (&pos) == _gtk_text_iter_get_text_line (iter))
+ if (byte_on_line == 0)
*iter = pos;
else
gtk_text_iter_forward_line (iter);
{
if (limit == NULL ||
(limit &&
- gtk_text_iter_compare (&end, limit) < 0))
+ gtk_text_iter_compare (&end, limit) <= 0))
{
retval = TRUE;
g_strfreev (win->lines);
}
-static gchar*
-my_strrstr (const gchar *haystack,
- const gchar *needle)
-{
- /* FIXME GLib should have a nice implementation in it, this
- * is slow-ass crap.
- */
-
- gint haystack_len = strlen (haystack);
- gint needle_len = strlen (needle);
- const gchar *needle_end = needle + needle_len;
- const gchar *haystack_rend = haystack - 1;
- const gchar *needle_rend = needle - 1;
- const gchar *p;
-
- p = haystack + haystack_len;
- while (p != haystack)
- {
- const gchar *n = needle_end - 1;
- const gchar *s = p - 1;
- while (s != haystack_rend &&
- n != needle_rend &&
- *s == *n)
- {
- --n;
- --s;
- }
-
- if (n == needle_rend)
- return (gchar*)++s;
-
- --p;
- }
-
- return NULL;
-}
-
/**
* gtk_text_iter_backward_search:
* @iter: a #GtkTextIter where the search begins
* end in '\n', so this will only match at the
* end of the first line, which is correct.
*/
- first_line_match = my_strrstr (*win.lines, *lines);
+ first_line_match = g_strrstr (*win.lines, *lines);
if (first_line_match &&
vectors_equal_ignoring_trailing (lines + 1, win.lines + 1))
else
{
iter_init_from_byte_offset (iter, tree, line, 0);
- gtk_text_iter_forward_to_tag_toggle (iter, tag);
+
+ if (!gtk_text_iter_toggles_tag (iter, tag))
+ gtk_text_iter_forward_to_tag_toggle (iter, tag);
+
check_invariants (iter);
return TRUE;
}
g_error ("Iterator was on last line (past the end iterator)");
}
+#define __GTK_TEXT_ITER_C__
+#include "gtkaliasdef.c"