+static void
+ensure_end_iter_line (GtkTextBTree *tree)
+{
+ if (tree->end_iter_line_stamp != tree->chars_changed_stamp)
+ {
+ gint real_line;
+
+ /* n_lines is without the magic line at the end */
+ g_assert (_gtk_text_btree_line_count (tree) >= 1);
+
+ tree->end_iter_line = _gtk_text_btree_get_line_no_last (tree, -1, &real_line);
+
+ tree->end_iter_line_stamp = tree->chars_changed_stamp;
+ }
+}
+
+static void
+ensure_end_iter_segment (GtkTextBTree *tree)
+{
+ if (tree->end_iter_segment_stamp != tree->segments_changed_stamp)
+ {
+ GtkTextLineSegment *seg;
+ GtkTextLineSegment *last_with_chars;
+
+ ensure_end_iter_line (tree);
+
+ last_with_chars = NULL;
+
+ seg = tree->end_iter_line->segments;
+ while (seg != NULL)
+ {
+ if (seg->char_count > 0)
+ last_with_chars = seg;
+ seg = seg->next;
+ }
+
+ tree->end_iter_segment = last_with_chars;
+
+ /* We know the last char in the last line is '\n' */
+ tree->end_iter_segment_byte_index = last_with_chars->byte_count - 1;
+ tree->end_iter_segment_char_offset = last_with_chars->char_count - 1;
+
+ tree->end_iter_segment_stamp = tree->segments_changed_stamp;
+
+ g_assert (tree->end_iter_segment->type == >k_text_char_type);
+ g_assert (tree->end_iter_segment->body.chars[tree->end_iter_segment_byte_index] == '\n');
+ }
+}
+
+gboolean
+_gtk_text_line_contains_end_iter (GtkTextLine *line,
+ GtkTextBTree *tree)
+{
+ ensure_end_iter_line (tree);
+
+ return line == tree->end_iter_line;
+}
+
+gboolean
+_gtk_text_btree_is_end (GtkTextBTree *tree,
+ GtkTextLine *line,
+ GtkTextLineSegment *seg,
+ int byte_index,
+ int char_offset)
+{
+ g_return_val_if_fail (byte_index >= 0 || char_offset >= 0, FALSE);
+
+ /* Do this first to avoid walking segments in most cases */
+ if (!_gtk_text_line_contains_end_iter (line, tree))
+ return FALSE;
+
+ ensure_end_iter_segment (tree);
+
+ if (seg != tree->end_iter_segment)
+ return FALSE;
+
+ if (byte_index >= 0)
+ return byte_index == tree->end_iter_segment_byte_index;
+ else
+ return char_offset == tree->end_iter_segment_char_offset;
+}
+