*/
#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
-#include <config.h>
+#include "config.h"
#include "gtktextiter.h"
#include "gtktextbtree.h"
#include "gtktextiterprivate.h"
+#include "gtkintl.h"
#include "gtkdebug.h"
#include "gtkalias.h"
#include <string.h>
typedef struct _GtkTextRealIter GtkTextRealIter;
-struct _GtkTextRealIter
+struct G_GNUC_MAY_ALIAS _GtkTextRealIter
{
/* Always-valid information */
GtkTextBTree *tree;
return real;
}
-static inline void
-invalidate_segment (GtkTextRealIter *iter)
-{
- iter->segments_changed_stamp -= 1;
-}
-
static inline void
invalidate_char_index (GtkTextRealIter *iter)
{
iter->cached_char_index = -1;
}
-static inline void
-invalidate_line_number (GtkTextRealIter *iter)
-{
- iter->cached_line_number = -1;
-}
-
static inline void
adjust_char_index (GtkTextRealIter *iter, gint count)
{
iter->cached_line_number += count;
}
-static inline void
-adjust_char_offsets (GtkTextRealIter *iter, gint count)
-{
- if (iter->line_char_offset >= 0)
- {
- iter->line_char_offset += count;
- g_assert (iter->segment_char_offset >= 0);
- iter->segment_char_offset += count;
- }
-}
-
-static inline void
-adjust_byte_offsets (GtkTextRealIter *iter, gint count)
-{
- if (iter->line_byte_offset >= 0)
- {
- iter->line_byte_offset += count;
- g_assert (iter->segment_byte_offset >= 0);
- iter->segment_byte_offset += count;
- }
-}
-
static inline void
ensure_char_offsets (GtkTextRealIter *iter)
{
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 ("GtkTextIter",
+ our_type = g_boxed_type_register_static (I_("GtkTextIter"),
(GBoxedCopyFunc) gtk_text_iter_copy,
(GBoxedFreeFunc) gtk_text_iter_free);
/* No tags, use default style */
if (tags == NULL || tag_count == 0)
{
- if (tags)
- g_free (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)
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;
/* No tags, use default style */
if (tags == NULL || tag_count == 0)
{
- if (tags)
- g_free (tags);
+ g_free (tags);
return FALSE;
}
- /* Sort tags in ascending order of priority */
- _gtk_text_tag_array_sort (tags, tag_count);
-
_gtk_text_attributes_fill_from_tags (values,
tags,
tag_count);
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;
- p = g_utf8_offset_to_pointer (real->segment->body.chars,
- real->segment_char_offset);
+ /* 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_line:
* @iter: an iterator
*
- * Moves @iter to the start of the next 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.
+ * Moves @iter to the start of the next line. If the iter is already on the
+ * last line of the buffer, moves the iter to the end of the current line.
+ * If after the operation, the iter is at the end of the buffer and not
+ * dereferencable, returns %FALSE. Otherwise, returns %TRUE.
*
* Return value: whether @iter can be dereferenced
**/
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;
- gint skipped = 0;
+ GtkTextRealIter *real;
+ 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);
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);
- else skipped++;
-
- 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;