1 #include "gtktextiter.h"
2 #include "gtktextbtree.h"
3 #include "gtktextiterprivate.h"
7 typedef struct _GtkTextRealIter GtkTextRealIter;
9 struct _GtkTextRealIter {
10 /* Always-valid information */
13 /* At least one of these is always valid;
14 if invalid, they are -1.
16 If the line byte offset is valid, so is the segment byte offset;
17 and ditto for char offsets. */
18 gint line_byte_offset;
19 gint line_char_offset;
20 /* These two are valid if >= 0 */
21 gint cached_char_index;
22 gint cached_line_number;
23 /* Stamps to detect the buffer changing under us */
24 gint chars_changed_stamp;
25 gint segments_changed_stamp;
26 /* Valid if the segments_changed_stamp is up-to-date */
27 GtkTextLineSegment *segment; /* indexable segment we index */
28 GtkTextLineSegment *any_segment; /* first segment in our location,
29 maybe same as "segment" */
30 /* One of these will always be valid if segments_changed_stamp is
31 up-to-date. If invalid, they are -1.
33 If the line byte offset is valid, so is the segment byte offset;
34 and ditto for char offsets. */
35 gint segment_byte_offset;
36 gint segment_char_offset;
37 /* These are here for binary-compatible expansion space. */
42 /* These "set" functions should not assume any fields
43 other than the char stamp and the tree are valid.
46 iter_set_common(GtkTextRealIter *iter,
49 /* Update segments stamp */
50 iter->segments_changed_stamp =
51 gtk_text_btree_get_segments_changed_stamp(iter->tree);
55 iter->line_byte_offset = -1;
56 iter->line_char_offset = -1;
57 iter->segment_byte_offset = -1;
58 iter->segment_char_offset = -1;
59 iter->cached_char_index = -1;
60 iter->cached_line_number = -1;
64 iter_set_from_byte_offset(GtkTextRealIter *iter,
68 iter_set_common(iter, line);
70 gtk_text_line_byte_locate(iter->line,
74 &iter->segment_byte_offset,
75 &iter->line_byte_offset);
80 iter_set_from_char_offset(GtkTextRealIter *iter,
84 iter_set_common(iter, line);
86 gtk_text_line_char_locate(iter->line,
90 &iter->segment_char_offset,
91 &iter->line_char_offset);
95 iter_set_from_segment(GtkTextRealIter *iter,
97 GtkTextLineSegment *segment)
99 GtkTextLineSegment *seg;
102 /* This could theoretically be optimized by computing all the iter
103 fields in this same loop, but I'm skipping it for now. */
105 seg = line->segments;
106 while (seg != segment)
108 byte_offset += seg->byte_count;
112 iter_set_from_byte_offset(iter, line, byte_offset);
115 /* This function ensures that the segment-dependent information is
116 truly computed lazily; often we don't need to do the full make_real
118 static GtkTextRealIter*
119 gtk_text_iter_make_surreal(const GtkTextIter *_iter)
121 GtkTextRealIter *iter = (GtkTextRealIter*)_iter;
123 if (iter->chars_changed_stamp !=
124 gtk_text_btree_get_chars_changed_stamp(iter->tree))
126 g_warning("Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixmaps/widgets in the buffer have been modified since the iterator was created.\nYou must use marks, character numbers, or line numbers to preserve a position across buffer modifications.\nYou can apply tags and insert marks without invalidating your iterators, however.");
130 /* We don't update the segments information since we are becoming
131 only surreal. However we do invalidate the segments information
132 if appropriate, to be sure we segfault if we try to use it and we
133 should have used make_real. */
135 if (iter->segments_changed_stamp !=
136 gtk_text_btree_get_segments_changed_stamp(iter->tree))
138 iter->segment = NULL;
139 iter->any_segment = NULL;
140 /* set to segfault-causing values. */
141 iter->segment_byte_offset = -10000;
142 iter->segment_char_offset = -10000;
148 static GtkTextRealIter*
149 gtk_text_iter_make_real(const GtkTextIter *_iter)
151 GtkTextRealIter *iter;
153 iter = gtk_text_iter_make_surreal(_iter);
155 if (iter->segments_changed_stamp !=
156 gtk_text_btree_get_segments_changed_stamp(iter->tree))
158 if (iter->line_byte_offset >= 0)
160 iter_set_from_byte_offset(iter,
162 iter->line_byte_offset);
166 g_assert(iter->line_char_offset >= 0);
168 iter_set_from_char_offset(iter,
170 iter->line_char_offset);
174 g_assert(iter->segment != NULL);
175 g_assert(iter->any_segment != NULL);
176 g_assert(iter->segment->char_count > 0);
181 static GtkTextRealIter*
182 iter_init_common(GtkTextIter *_iter,
185 GtkTextRealIter *iter = (GtkTextRealIter*)_iter;
187 g_return_val_if_fail(iter != NULL, NULL);
188 g_return_val_if_fail(tree != NULL, NULL);
192 iter->chars_changed_stamp =
193 gtk_text_btree_get_chars_changed_stamp(iter->tree);
198 static GtkTextRealIter*
199 iter_init_from_segment(GtkTextIter *iter,
202 GtkTextLineSegment *segment)
204 GtkTextRealIter *real;
206 g_return_val_if_fail(line != NULL, NULL);
208 real = iter_init_common(iter, tree);
210 iter_set_from_segment(real, line, segment);
215 static GtkTextRealIter*
216 iter_init_from_byte_offset(GtkTextIter *iter,
219 gint line_byte_offset)
221 GtkTextRealIter *real;
223 g_return_val_if_fail(line != NULL, NULL);
225 real = iter_init_common(iter, tree);
227 iter_set_from_byte_offset(real, line, line_byte_offset);
232 static GtkTextRealIter*
233 iter_init_from_char_offset(GtkTextIter *iter,
236 gint line_char_offset)
238 GtkTextRealIter *real;
240 g_return_val_if_fail(line != NULL, NULL);
242 real = iter_init_common(iter, tree);
244 iter_set_from_char_offset(real, line, line_char_offset);
250 invalidate_segment(GtkTextRealIter *iter)
252 iter->segments_changed_stamp -= 1;
256 invalidate_char_index(GtkTextRealIter *iter)
258 iter->cached_char_index = -1;
262 invalidate_line_number(GtkTextRealIter *iter)
264 iter->cached_line_number = -1;
268 adjust_char_index(GtkTextRealIter *iter, gint count)
270 if (iter->cached_char_index >= 0)
271 iter->cached_char_index += count;
275 adjust_line_number(GtkTextRealIter *iter, gint count)
277 if (iter->cached_line_number >= 0)
278 iter->cached_line_number += count;
282 adjust_char_offsets(GtkTextRealIter *iter, gint count)
284 if (iter->line_char_offset >= 0)
286 iter->line_char_offset += count;
287 g_assert(iter->segment_char_offset >= 0);
288 iter->segment_char_offset += count;
293 adjust_byte_offsets(GtkTextRealIter *iter, gint count)
295 if (iter->line_byte_offset >= 0)
297 iter->line_byte_offset += count;
298 g_assert(iter->segment_byte_offset >= 0);
299 iter->segment_byte_offset += count;
304 ensure_char_offsets(GtkTextRealIter *iter)
306 if (iter->line_char_offset < 0)
308 g_assert(iter->line_byte_offset >= 0);
310 gtk_text_line_byte_to_char_offsets(iter->line,
311 iter->line_byte_offset,
312 &iter->line_char_offset,
313 &iter->segment_char_offset);
318 ensure_byte_offsets(GtkTextRealIter *iter)
320 if (iter->line_byte_offset < 0)
322 g_assert(iter->line_char_offset >= 0);
324 gtk_text_line_char_to_byte_offsets(iter->line,
325 iter->line_char_offset,
326 &iter->line_byte_offset,
327 &iter->segment_byte_offset);
333 check_invariants(const GtkTextIter *iter)
335 if (gtk_debug_flags & GTK_DEBUG_TEXT)
336 gtk_text_iter_check(iter);
339 #define check_invariants(x)
343 gtk_text_iter_get_buffer(const GtkTextIter *iter)
345 GtkTextRealIter *real;
347 g_return_val_if_fail(iter != NULL, NULL);
349 real = gtk_text_iter_make_surreal(iter);
354 check_invariants(iter);
356 return gtk_text_btree_get_buffer(real->tree);
360 gtk_text_iter_copy(const GtkTextIter *iter)
362 GtkTextIter *new_iter;
364 g_return_val_if_fail(iter != NULL, NULL);
366 new_iter = g_new(GtkTextIter, 1);
374 gtk_text_iter_free(GtkTextIter *iter)
376 g_return_if_fail(iter != NULL);
382 gtk_text_iter_get_indexable_segment(const GtkTextIter *iter)
384 GtkTextRealIter *real;
386 g_return_val_if_fail(iter != NULL, 0);
388 real = gtk_text_iter_make_real(iter);
393 check_invariants(iter);
395 g_assert(real->segment != NULL);
397 return real->segment;
401 gtk_text_iter_get_any_segment(const GtkTextIter *iter)
403 GtkTextRealIter *real;
405 g_return_val_if_fail(iter != NULL, 0);
407 real = gtk_text_iter_make_real(iter);
412 check_invariants(iter);
414 g_assert(real->any_segment != NULL);
416 return real->any_segment;
420 gtk_text_iter_get_segment_byte(const GtkTextIter *iter)
422 GtkTextRealIter *real;
424 g_return_val_if_fail(iter != NULL, 0);
426 real = gtk_text_iter_make_real(iter);
431 ensure_byte_offsets(real);
433 check_invariants(iter);
435 return real->segment_byte_offset;
439 gtk_text_iter_get_segment_char(const GtkTextIter *iter)
441 GtkTextRealIter *real;
443 g_return_val_if_fail(iter != NULL, 0);
445 real = gtk_text_iter_make_real(iter);
450 ensure_char_offsets(real);
452 check_invariants(iter);
454 return real->segment_char_offset;
457 /* This function does not require a still-valid
460 gtk_text_iter_get_line(const GtkTextIter *iter)
462 const GtkTextRealIter *real;
464 g_return_val_if_fail(iter != NULL, 0);
466 real = (const GtkTextRealIter*)iter;
471 /* This function does not require a still-valid
474 gtk_text_iter_get_btree(const GtkTextIter *iter)
476 const GtkTextRealIter *real;
478 g_return_val_if_fail(iter != NULL, 0);
480 real = (const GtkTextRealIter*)iter;
490 gtk_text_iter_get_char_index(const GtkTextIter *iter)
492 GtkTextRealIter *real;
494 g_return_val_if_fail(iter != NULL, 0);
496 real = gtk_text_iter_make_surreal(iter);
501 if (real->cached_char_index < 0)
503 real->cached_char_index =
504 gtk_text_line_char_index(real->line);
505 ensure_char_offsets(real);
506 real->cached_char_index += real->line_char_offset;
509 check_invariants(iter);
511 return real->cached_char_index;
515 gtk_text_iter_get_line_number(const GtkTextIter *iter)
517 GtkTextRealIter *real;
519 g_return_val_if_fail(iter != NULL, 0);
521 real = gtk_text_iter_make_surreal(iter);
526 if (real->cached_line_number < 0)
527 real->cached_line_number =
528 gtk_text_line_get_number(real->line);
530 check_invariants(iter);
532 return real->cached_line_number;
536 gtk_text_iter_get_line_char(const GtkTextIter *iter)
539 GtkTextRealIter *real;
541 g_return_val_if_fail(iter != NULL, 0);
543 real = gtk_text_iter_make_surreal(iter);
548 ensure_char_offsets(real);
550 check_invariants(iter);
552 return real->line_char_offset;
556 gtk_text_iter_get_line_byte(const GtkTextIter *iter)
558 GtkTextRealIter *real;
560 g_return_val_if_fail(iter != NULL, 0);
562 real = gtk_text_iter_make_surreal(iter);
567 ensure_byte_offsets(real);
569 check_invariants(iter);
571 return real->line_byte_offset;
579 gtk_text_iter_get_char(const GtkTextIter *iter)
581 GtkTextRealIter *real;
583 g_return_val_if_fail(iter != NULL, 0);
585 real = gtk_text_iter_make_real(iter);
590 check_invariants(iter);
592 /* FIXME probably want to special-case the end iterator
593 and either have an error or return 0 */
595 if (real->segment->type == >k_text_char_type)
599 ensure_byte_offsets(real);
601 gtk_text_utf_to_unichar(real->segment->body.chars +
602 real->segment_byte_offset,
609 /* Unicode "unknown character" 0xFFFD */
610 return gtk_text_unknown_char;
615 gtk_text_iter_get_slice (const GtkTextIter *start,
616 const GtkTextIter *end)
618 g_return_val_if_fail(start != NULL, NULL);
619 g_return_val_if_fail(end != NULL, NULL);
621 check_invariants(start);
622 check_invariants(end);
624 return gtk_text_btree_get_text(start, end, TRUE, TRUE);
628 gtk_text_iter_get_text (const GtkTextIter *start,
629 const GtkTextIter *end)
631 g_return_val_if_fail(start != NULL, NULL);
632 g_return_val_if_fail(end != NULL, NULL);
634 check_invariants(start);
635 check_invariants(end);
637 return gtk_text_btree_get_text(start, end, TRUE, FALSE);
641 gtk_text_iter_get_visible_slice (const GtkTextIter *start,
642 const GtkTextIter *end)
644 g_return_val_if_fail(start != NULL, NULL);
645 g_return_val_if_fail(end != NULL, NULL);
647 check_invariants(start);
648 check_invariants(end);
650 return gtk_text_btree_get_text(start, end, FALSE, TRUE);
654 gtk_text_iter_get_visible_text (const GtkTextIter *start,
655 const GtkTextIter *end)
657 g_return_val_if_fail(start != NULL, NULL);
658 g_return_val_if_fail(end != NULL, NULL);
660 check_invariants(start);
661 check_invariants(end);
663 return gtk_text_btree_get_text(start, end, FALSE, FALSE);
667 gtk_text_iter_get_pixmap (const GtkTextIter *iter,
671 GtkTextRealIter *real;
673 g_return_val_if_fail(iter != NULL, FALSE);
674 g_return_val_if_fail(pixmap != NULL, FALSE);
675 g_return_val_if_fail(mask != NULL, FALSE);
680 real = gtk_text_iter_make_real(iter);
685 check_invariants(iter);
687 if (real->segment->type != >k_text_pixmap_type)
691 *pixmap = real->segment->body.pixmap.pixmap;
692 *mask = real->segment->body.pixmap.pixmap;
699 gtk_text_iter_get_toggled_tags (const GtkTextIter *iter,
702 GtkTextRealIter *real;
703 GtkTextLineSegment *seg;
706 g_return_val_if_fail(iter != NULL, NULL);
708 real = gtk_text_iter_make_real(iter);
713 check_invariants(iter);
716 seg = real->any_segment;
717 while (seg != real->segment)
721 if (seg->type == >k_text_toggle_on_type)
723 retval = g_slist_prepend(retval, seg->body.toggle.info->tag);
728 if (seg->type == >k_text_toggle_off_type)
730 retval = g_slist_prepend(retval, seg->body.toggle.info->tag);
737 /* The returned list isn't guaranteed to be in any special order,
743 gtk_text_iter_begins_tag (const GtkTextIter *iter,
746 GtkTextRealIter *real;
747 GtkTextLineSegment *seg;
749 g_return_val_if_fail(iter != NULL, FALSE);
751 real = gtk_text_iter_make_real(iter);
756 check_invariants(iter);
758 seg = real->any_segment;
759 while (seg != real->segment)
761 if (seg->type == >k_text_toggle_on_type)
764 seg->body.toggle.info->tag == tag)
775 gtk_text_iter_ends_tag (const GtkTextIter *iter,
778 GtkTextRealIter *real;
779 GtkTextLineSegment *seg;
781 g_return_val_if_fail(iter != NULL, FALSE);
783 real = gtk_text_iter_make_real(iter);
788 check_invariants(iter);
790 seg = real->any_segment;
791 while (seg != real->segment)
793 if (seg->type == >k_text_toggle_off_type)
796 seg->body.toggle.info->tag == tag)
807 gtk_text_iter_toggles_tag (const GtkTextIter *iter,
810 GtkTextRealIter *real;
811 GtkTextLineSegment *seg;
813 g_return_val_if_fail(iter != NULL, FALSE);
815 real = gtk_text_iter_make_real(iter);
820 check_invariants(iter);
822 seg = real->any_segment;
823 while (seg != real->segment)
825 if ( (seg->type == >k_text_toggle_off_type ||
826 seg->type == >k_text_toggle_on_type) &&
828 seg->body.toggle.info->tag == tag) )
838 gtk_text_iter_has_tag (const GtkTextIter *iter,
841 GtkTextRealIter *real;
843 g_return_val_if_fail(iter != NULL, FALSE);
844 g_return_val_if_fail(GTK_IS_TEXT_TAG(tag), FALSE);
846 real = gtk_text_iter_make_surreal(iter);
851 check_invariants(iter);
853 if (real->line_byte_offset >= 0)
855 return gtk_text_line_byte_has_tag(real->line, real->tree,
856 real->line_byte_offset, tag);
860 g_assert(real->line_char_offset >= 0);
861 return gtk_text_line_char_has_tag(real->line, real->tree,
862 real->line_char_offset, tag);
867 gtk_text_iter_starts_line (const GtkTextIter *iter)
869 GtkTextRealIter *real;
871 g_return_val_if_fail(iter != NULL, FALSE);
873 real = gtk_text_iter_make_surreal(iter);
878 check_invariants(iter);
880 if (real->line_byte_offset >= 0)
882 return (real->line_byte_offset == 0);
886 g_assert(real->line_char_offset >= 0);
887 return (real->line_char_offset == 0);
892 gtk_text_iter_ends_line (const GtkTextIter *iter)
894 g_return_val_if_fail(iter != NULL, FALSE);
896 check_invariants(iter);
898 return gtk_text_iter_get_char(iter) == '\n';
902 gtk_text_iter_get_chars_in_line (const GtkTextIter *iter)
904 GtkTextRealIter *real;
906 GtkTextLineSegment *seg;
908 g_return_val_if_fail(iter != NULL, FALSE);
910 real = gtk_text_iter_make_surreal(iter);
915 check_invariants(iter);
917 if (real->line_char_offset >= 0)
919 /* We can start at the segments we've already found. */
920 count = real->line_char_offset - real->segment_char_offset;
921 seg = gtk_text_iter_get_indexable_segment(iter);
925 /* count whole line. */
926 seg = real->line->segments;
933 count += seg->char_count;
942 * Increments/decrements
946 forward_line_leaving_caches_unmodified(GtkTextRealIter *real)
948 GtkTextLine *new_line;
950 new_line = gtk_text_line_next(real->line);
952 g_assert(new_line != real->line);
954 if (new_line != NULL)
956 real->line = new_line;
958 real->line_byte_offset = 0;
959 real->line_char_offset = 0;
961 real->segment_byte_offset = 0;
962 real->segment_char_offset = 0;
964 /* Find first segments in new line */
965 real->any_segment = real->line->segments;
966 real->segment = real->any_segment;
967 while (real->segment->char_count == 0)
968 real->segment = real->segment->next;
974 /* There is no way to move forward; we were already
975 at the "end" index. (the end index is the last
976 line pointer, segment_byte_offset of 0) */
978 g_assert(real->line_char_offset == 0 ||
979 real->line_byte_offset == 0);
981 /* The only indexable segment allowed on the bogus
982 line at the end is a single char segment containing
984 if (real->segments_changed_stamp ==
985 gtk_text_btree_get_segments_changed_stamp(real->tree))
987 g_assert(real->segment->type == >k_text_char_type);
988 g_assert(real->segment->char_count == 1);
990 /* We leave real->line as-is */
997 forward_char(GtkTextRealIter *real)
999 GtkTextIter *iter = (GtkTextIter*)real;
1001 check_invariants((GtkTextIter*)real);
1003 ensure_char_offsets(real);
1005 if ( (real->segment_char_offset + 1) == real->segment->char_count)
1007 /* Need to move to the next segment; if no next segment,
1008 need to move to next line. */
1009 return gtk_text_iter_forward_indexable_segment(iter);
1013 /* Just moving within a segment. Keep byte count
1014 up-to-date, if it was already up-to-date. */
1016 g_assert(real->segment->type == >k_text_char_type);
1018 if (real->line_byte_offset >= 0)
1023 bytes = gtk_text_utf_to_unichar(real->segment->body.chars +
1024 real->segment_byte_offset,
1027 real->line_byte_offset += bytes;
1028 real->segment_byte_offset += bytes;
1030 g_assert(real->segment_byte_offset < real->segment->byte_count);
1033 real->line_char_offset += 1;
1034 real->segment_char_offset += 1;
1036 adjust_char_index(real, 1);
1038 g_assert(real->segment_char_offset < real->segment->char_count);
1040 /* We moved into the middle of a segment, so the any_segment
1041 must now be the segment we're in the middle of. */
1042 real->any_segment = real->segment;
1044 check_invariants((GtkTextIter*)real);
1051 gtk_text_iter_forward_indexable_segment(GtkTextIter *iter)
1053 /* Need to move to the next segment; if no next segment,
1054 need to move to next line. */
1055 GtkTextLineSegment *seg;
1056 GtkTextLineSegment *any_seg;
1057 GtkTextRealIter *real;
1061 g_return_val_if_fail(iter != NULL, FALSE);
1063 real = gtk_text_iter_make_real(iter);
1068 check_invariants(iter);
1070 if (real->line_char_offset >= 0)
1072 chars_skipped = real->segment->char_count - real->segment_char_offset;
1073 g_assert(chars_skipped > 0);
1078 if (real->line_byte_offset >= 0)
1080 bytes_skipped = real->segment->byte_count - real->segment_byte_offset;
1081 g_assert(bytes_skipped > 0);
1086 /* Get first segment of any kind */
1087 any_seg = real->segment->next;
1088 /* skip non-indexable segments, if any */
1090 while (seg != NULL && seg->char_count == 0)
1095 real->any_segment = any_seg;
1096 real->segment = seg;
1098 if (real->line_byte_offset >= 0)
1100 g_assert(bytes_skipped > 0);
1101 real->segment_byte_offset = 0;
1102 real->line_byte_offset += bytes_skipped;
1105 if (real->line_char_offset >= 0)
1107 g_assert(chars_skipped > 0);
1108 real->segment_char_offset = 0;
1109 real->line_char_offset += chars_skipped;
1110 adjust_char_index(real, chars_skipped);
1113 check_invariants(iter);
1119 /* End of the line */
1120 if (forward_line_leaving_caches_unmodified(real))
1122 adjust_line_number(real, 1);
1123 if (real->line_char_offset >= 0)
1124 adjust_char_index(real, chars_skipped);
1126 check_invariants(iter);
1128 g_assert(real->line_byte_offset == 0);
1129 g_assert(real->line_char_offset == 0);
1130 g_assert(real->segment_byte_offset == 0);
1131 g_assert(real->segment_char_offset == 0);
1132 g_assert(gtk_text_iter_starts_line(iter));
1134 check_invariants(iter);
1142 check_invariants(iter);
1150 gtk_text_iter_backward_indexable_segment(GtkTextIter *iter)
1157 gtk_text_iter_forward_char(GtkTextIter *iter)
1159 GtkTextRealIter *real;
1161 g_return_val_if_fail(iter != NULL, FALSE);
1163 real = gtk_text_iter_make_real(iter);
1169 check_invariants(iter);
1170 return forward_char(real);
1175 gtk_text_iter_backward_char(GtkTextIter *iter)
1177 g_return_val_if_fail(iter != NULL, FALSE);
1179 check_invariants(iter);
1181 return gtk_text_iter_backward_chars(iter, 1);
1185 Definitely we should try to linear scan as often as possible for
1186 movement within a single line, because we can't use the BTree to
1187 speed within-line searches up; for movement between lines, we would
1188 like to avoid the linear scan probably.
1190 Instead of using this constant, it might be nice to cache the line
1191 length in the iterator and linear scan if motion is within a single
1194 I guess you'd have to profile the various approaches.
1196 #define MAX_LINEAR_SCAN 300
1199 gtk_text_iter_forward_chars(GtkTextIter *iter, gint count)
1201 GtkTextRealIter *real;
1203 g_return_val_if_fail(iter != NULL, FALSE);
1205 real = gtk_text_iter_make_real(iter);
1209 else if (count == 0)
1212 return gtk_text_iter_backward_chars(iter, 0 - count);
1213 else if (count < MAX_LINEAR_SCAN)
1215 check_invariants(iter);
1219 if (!forward_char(real))
1224 return forward_char(real);
1228 gint current_char_index;
1229 gint new_char_index;
1231 check_invariants(iter);
1233 current_char_index = gtk_text_iter_get_char_index(iter);
1235 if (current_char_index == gtk_text_btree_char_count(real->tree))
1236 return FALSE; /* can't move forward */
1238 new_char_index = current_char_index + count;
1239 gtk_text_iter_set_char_index(iter, new_char_index);
1241 check_invariants(iter);
1248 gtk_text_iter_backward_chars(GtkTextIter *iter, gint count)
1250 GtkTextRealIter *real;
1252 g_return_val_if_fail(iter != NULL, FALSE);
1254 real = gtk_text_iter_make_real(iter);
1258 else if (count == 0)
1261 return gtk_text_iter_forward_chars(iter, 0 - count);
1263 ensure_char_offsets(real);
1264 check_invariants(iter);
1266 if (count <= real->segment_char_offset)
1268 /* Optimize the within-segment case */
1269 g_assert(real->segment->char_count > 0);
1270 g_assert(real->segment->type == >k_text_char_type);
1272 real->segment_char_offset -= count;
1273 g_assert(real->segment_char_offset >= 0);
1275 if (real->line_byte_offset >= 0)
1277 gint new_byte_offset;
1280 new_byte_offset = 0;
1282 while (i < real->segment_char_offset)
1286 gtk_text_utf_to_unichar(real->segment->body.chars + new_byte_offset,
1291 real->line_byte_offset -= (real->segment_byte_offset - new_byte_offset);
1292 real->segment_byte_offset = new_byte_offset;
1295 real->line_char_offset -= count;
1297 adjust_char_index(real, 0 - count);
1299 check_invariants(iter);
1305 /* We need to go back into previous segments. For now,
1306 just keep this really simple. */
1307 gint current_char_index;
1308 gint new_char_index;
1310 current_char_index = gtk_text_iter_get_char_index(iter);
1312 if (current_char_index == 0)
1313 return FALSE; /* can't move backward */
1315 new_char_index = current_char_index - count;
1316 if (new_char_index < 0)
1318 gtk_text_iter_set_char_index(iter, new_char_index);
1320 check_invariants(iter);
1327 gtk_text_iter_forward_line(GtkTextIter *iter)
1329 GtkTextRealIter *real;
1331 g_return_val_if_fail(iter != NULL, FALSE);
1333 real = gtk_text_iter_make_real(iter);
1338 check_invariants(iter);
1340 if (forward_line_leaving_caches_unmodified(real))
1342 invalidate_char_index(real);
1343 adjust_line_number(real, 1);
1345 check_invariants(iter);
1351 check_invariants(iter);
1357 gtk_text_iter_backward_line(GtkTextIter *iter)
1359 GtkTextLine *new_line;
1360 GtkTextRealIter *real;
1361 gboolean offset_will_change;
1364 g_return_val_if_fail(iter != NULL, FALSE);
1366 real = gtk_text_iter_make_real(iter);
1371 check_invariants(iter);
1373 new_line = gtk_text_line_previous(real->line);
1375 offset_will_change = FALSE;
1376 if (real->line_char_offset > 0)
1377 offset_will_change = TRUE;
1379 if (new_line != NULL)
1381 real->line = new_line;
1383 adjust_line_number(real, -1);
1387 if (!offset_will_change)
1391 invalidate_char_index(real);
1393 real->line_byte_offset = 0;
1394 real->line_char_offset = 0;
1396 real->segment_byte_offset = 0;
1397 real->segment_char_offset = 0;
1399 /* Find first segment in line */
1400 real->any_segment = real->line->segments;
1401 real->segment = gtk_text_line_byte_to_segment(real->line,
1404 g_assert(offset == 0);
1406 /* Note that if we are on the first line, we snap to the start
1407 of the first line and return TRUE, so TRUE means the
1408 iterator changed, not that the line changed; this is maybe
1409 a bit weird. I'm not sure there's an obvious right thing
1412 check_invariants(iter);
1418 gtk_text_iter_forward_lines(GtkTextIter *iter, gint count)
1421 return gtk_text_iter_backward_lines(iter, 0 - count);
1422 else if (count == 0)
1424 else if (count == 1)
1426 check_invariants(iter);
1427 return gtk_text_iter_forward_line(iter);
1433 old_line = gtk_text_iter_get_line_number(iter);
1435 gtk_text_iter_set_line_number(iter, old_line + count);
1437 check_invariants(iter);
1439 return (gtk_text_iter_get_line_number(iter) != old_line);
1444 gtk_text_iter_backward_lines(GtkTextIter *iter, gint count)
1447 return gtk_text_iter_forward_lines(iter, 0 - count);
1448 else if (count == 0)
1450 else if (count == 1)
1452 return gtk_text_iter_backward_line(iter);
1458 old_line = gtk_text_iter_get_line_number(iter);
1460 gtk_text_iter_set_line_number(iter, MAX(old_line - count, 0));
1462 return (gtk_text_iter_get_line_number(iter) != old_line);
1467 is_word_char(GtkTextUniChar ch, gpointer user_data)
1469 /* will likely need some i18n help FIXME */
1474 is_not_word_char(GtkTextUniChar ch, gpointer user_data)
1476 return !is_word_char(ch, user_data);
1480 gtk_text_iter_is_in_word(const GtkTextIter *iter)
1484 ch = gtk_text_iter_get_char(iter);
1486 return is_word_char(ch, NULL);
1490 gtk_text_iter_forward_word_end(GtkTextIter *iter)
1495 g_return_val_if_fail(iter != NULL, FALSE);
1499 in_word = gtk_text_iter_is_in_word(iter);
1503 if (!gtk_text_iter_forward_find_char(iter, is_word_char, NULL))
1504 return !gtk_text_iter_equal(iter, &start);
1511 gtk_text_iter_forward_find_char(iter, is_not_word_char, NULL);
1513 return !gtk_text_iter_equal(iter, &start);
1517 gtk_text_iter_backward_word_start(GtkTextIter *iter)
1522 g_return_val_if_fail(iter != NULL, FALSE);
1526 in_word = gtk_text_iter_is_in_word(iter);
1530 if (!gtk_text_iter_backward_find_char(iter, is_word_char, NULL))
1531 return !gtk_text_iter_equal(iter, &start);
1538 gtk_text_iter_backward_find_char(iter, is_not_word_char, NULL);
1539 gtk_text_iter_forward_char(iter); /* point to first char of word,
1540 not first non-word char. */
1542 return !gtk_text_iter_equal(iter, &start);
1546 gtk_text_iter_forward_word_ends(GtkTextIter *iter,
1549 g_return_val_if_fail(iter != NULL, FALSE);
1550 g_return_val_if_fail(count > 0, FALSE);
1552 if (!gtk_text_iter_forward_word_end(iter))
1558 if (!gtk_text_iter_forward_word_end(iter))
1566 gtk_text_iter_backward_word_starts(GtkTextIter *iter,
1569 g_return_val_if_fail(iter != NULL, FALSE);
1570 g_return_val_if_fail(count > 0, FALSE);
1572 if (!gtk_text_iter_backward_word_start(iter))
1578 if (!gtk_text_iter_backward_word_start(iter))
1585 /* up/down lines maintain the char offset, while forward/backward lines
1586 always sets the char offset to 0. */
1588 gtk_text_iter_up_lines (GtkTextIter *iter,
1594 return gtk_text_iter_down_lines(iter, 0 - count);
1596 char_offset = gtk_text_iter_get_line_char(iter);
1598 if (!gtk_text_iter_backward_line(iter))
1604 if (!gtk_text_iter_backward_line(iter))
1609 gtk_text_iter_set_line_char(iter, char_offset);
1615 gtk_text_iter_down_lines (GtkTextIter *iter,
1621 return gtk_text_iter_up_lines(iter, 0 - count);
1623 char_offset = gtk_text_iter_get_line_char(iter);
1625 if (!gtk_text_iter_forward_line(iter))
1631 if (!gtk_text_iter_forward_line(iter))
1636 gtk_text_iter_set_line_char(iter, char_offset);
1642 gtk_text_iter_set_line_char(GtkTextIter *iter,
1645 GtkTextRealIter *real;
1647 g_return_if_fail(iter != NULL);
1649 real = gtk_text_iter_make_surreal(iter);
1654 check_invariants(iter);
1656 iter_set_from_char_offset(real, real->line, char_on_line);
1658 check_invariants(iter);
1662 gtk_text_iter_set_line_number(GtkTextIter *iter, gint line_number)
1666 GtkTextRealIter *real;
1668 g_return_if_fail(iter != NULL);
1670 real = gtk_text_iter_make_surreal(iter);
1675 check_invariants(iter);
1677 line = gtk_text_btree_get_line(real->tree, line_number, &real_line);
1679 iter_set_from_char_offset(real, line, 0);
1681 /* We might as well cache this, since we know it. */
1682 real->cached_line_number = real_line;
1684 check_invariants(iter);
1688 gtk_text_iter_set_char_index(GtkTextIter *iter, gint char_index)
1691 GtkTextRealIter *real;
1693 gint real_char_index;
1695 g_return_if_fail(iter != NULL);
1697 real = gtk_text_iter_make_surreal(iter);
1702 check_invariants(iter);
1704 if (real->cached_char_index >= 0 &&
1705 real->cached_char_index == char_index)
1708 line = gtk_text_btree_get_line_at_char(real->tree,
1713 iter_set_from_char_offset(real, line, real_char_index - line_start);
1715 /* Go ahead and cache this since we have it. */
1716 real->cached_char_index = real_char_index;
1718 check_invariants(iter);
1722 gtk_text_iter_forward_to_end (GtkTextIter *iter)
1724 GtkTextBuffer *buffer;
1725 GtkTextRealIter *real;
1727 g_return_if_fail(iter != NULL);
1729 real = gtk_text_iter_make_surreal(iter);
1734 buffer = gtk_text_btree_get_buffer(real->tree);
1736 gtk_text_buffer_get_last_iter(buffer, iter);
1740 gtk_text_iter_forward_to_newline(GtkTextIter *iter)
1742 gint current_offset;
1745 g_return_val_if_fail(iter != NULL, FALSE);
1747 current_offset = gtk_text_iter_get_line_char(iter);
1748 new_offset = gtk_text_iter_get_chars_in_line(iter) - 1;
1750 if (current_offset < new_offset)
1752 /* Move to end of this line. */
1753 gtk_text_iter_set_line_char(iter, new_offset);
1758 /* Move to end of next line. */
1759 if (gtk_text_iter_forward_line(iter))
1761 gtk_text_iter_forward_to_newline(iter);
1770 gtk_text_iter_forward_find_tag_toggle (GtkTextIter *iter,
1773 GtkTextLine *next_line;
1774 GtkTextLine *current_line;
1775 GtkTextRealIter *real;
1777 g_return_val_if_fail(iter != NULL, FALSE);
1779 real = gtk_text_iter_make_real(iter);
1784 check_invariants(iter);
1786 current_line = real->line;
1787 next_line = gtk_text_line_next_could_contain_tag(current_line,
1790 while (gtk_text_iter_forward_indexable_segment(iter))
1792 /* If we went forward to a line that couldn't contain a toggle
1793 for the tag, then skip forward to a line that could contain
1794 it. This potentially skips huge hunks of the tree, so we
1795 aren't a purely linear search. */
1796 if (real->line != current_line)
1798 if (next_line == NULL)
1800 /* End of search. Set to end of buffer. */
1801 gtk_text_btree_get_last_iter(real->tree, iter);
1805 if (real->line != next_line)
1806 iter_set_from_byte_offset(real, next_line, 0);
1808 current_line = real->line;
1809 next_line = gtk_text_line_next_could_contain_tag(current_line,
1814 if (gtk_text_iter_toggles_tag(iter, tag))
1816 /* If there's a toggle here, it isn't indexable so
1817 any_segment can't be the indexable segment. */
1818 g_assert(real->any_segment != real->segment);
1823 /* Reached end of buffer */
1828 gtk_text_iter_backward_find_tag_toggle (GtkTextIter *iter,
1836 matches_pred(GtkTextIter *iter,
1837 GtkTextViewCharPredicate pred,
1842 ch = gtk_text_iter_get_char(iter);
1844 return (*pred) (ch, user_data);
1848 gtk_text_iter_forward_find_char (GtkTextIter *iter,
1849 GtkTextViewCharPredicate pred,
1852 g_return_val_if_fail(iter != NULL, FALSE);
1853 g_return_val_if_fail(pred != NULL, FALSE);
1855 while (gtk_text_iter_forward_char(iter))
1857 if (matches_pred(iter, pred, user_data))
1865 gtk_text_iter_backward_find_char (GtkTextIter *iter,
1866 GtkTextViewCharPredicate pred,
1869 g_return_val_if_fail(iter != NULL, FALSE);
1870 g_return_val_if_fail(pred != NULL, FALSE);
1872 while (gtk_text_iter_backward_char(iter))
1874 if (matches_pred(iter, pred, user_data))
1886 gtk_text_iter_equal(const GtkTextIter *lhs, const GtkTextIter *rhs)
1888 GtkTextRealIter *real_lhs;
1889 GtkTextRealIter *real_rhs;
1891 real_lhs = (GtkTextRealIter*)lhs;
1892 real_rhs = (GtkTextRealIter*)rhs;
1894 check_invariants(lhs);
1895 check_invariants(rhs);
1897 if (real_lhs->line != real_rhs->line)
1899 else if (real_lhs->line_byte_offset >= 0 &&
1900 real_rhs->line_byte_offset >= 0)
1901 return real_lhs->line_byte_offset == real_rhs->line_byte_offset;
1904 /* the ensure_char_offsets() calls do nothing if the char offsets
1905 are already up-to-date. */
1906 ensure_char_offsets(real_lhs);
1907 ensure_char_offsets(real_rhs);
1908 return real_lhs->line_char_offset == real_rhs->line_char_offset;
1913 gtk_text_iter_compare(const GtkTextIter *lhs, const GtkTextIter *rhs)
1915 GtkTextRealIter *real_lhs;
1916 GtkTextRealIter *real_rhs;
1918 real_lhs = gtk_text_iter_make_surreal(lhs);
1919 real_rhs = gtk_text_iter_make_surreal(rhs);
1921 check_invariants(lhs);
1922 check_invariants(rhs);
1924 if (real_lhs == NULL ||
1926 return -1; /* why not */
1928 if (real_lhs->line == real_rhs->line)
1930 gint left_index, right_index;
1932 if (real_lhs->line_byte_offset >= 0 &&
1933 real_rhs->line_byte_offset >= 0)
1935 left_index = real_lhs->line_byte_offset;
1936 right_index = real_rhs->line_byte_offset;
1940 /* the ensure_char_offsets() calls do nothing if
1941 the offsets are already up-to-date. */
1942 ensure_char_offsets(real_lhs);
1943 ensure_char_offsets(real_rhs);
1944 left_index = real_lhs->line_char_offset;
1945 right_index = real_rhs->line_char_offset;
1948 if (left_index < right_index)
1950 else if (left_index > right_index)
1959 line1 = gtk_text_iter_get_line_number(lhs);
1960 line2 = gtk_text_iter_get_line_number(rhs);
1963 else if (line1 > line2)
1971 gtk_text_iter_in_region (const GtkTextIter *iter,
1972 const GtkTextIter *start,
1973 const GtkTextIter *end)
1975 return gtk_text_iter_compare(iter, start) >= 0 &&
1976 gtk_text_iter_compare(iter, end) < 0;
1980 gtk_text_iter_reorder (GtkTextIter *first,
1981 GtkTextIter *second)
1983 g_return_if_fail(first != NULL);
1984 g_return_if_fail(second != NULL);
1986 if (gtk_text_iter_compare(first, second) > 0)
1997 * Init iterators from the BTree
2001 gtk_text_btree_get_iter_at_char (GtkTextBTree *tree,
2005 GtkTextRealIter *real = (GtkTextRealIter*)iter;
2006 gint real_char_index;
2010 g_return_if_fail(iter != NULL);
2011 g_return_if_fail(tree != NULL);
2013 line = gtk_text_btree_get_line_at_char(tree, char_index,
2014 &line_start, &real_char_index);
2016 iter_init_from_char_offset(iter, tree, line, real_char_index - line_start);
2018 real->cached_char_index = real_char_index;
2020 check_invariants(iter);
2024 gtk_text_btree_get_iter_at_line_char (GtkTextBTree *tree,
2029 GtkTextRealIter *real = (GtkTextRealIter*)iter;
2033 g_return_if_fail(iter != NULL);
2034 g_return_if_fail(tree != NULL);
2036 line = gtk_text_btree_get_line(tree, line_number, &real_line);
2038 iter_init_from_char_offset(iter, tree, line, char_on_line);
2040 /* We might as well cache this, since we know it. */
2041 real->cached_line_number = real_line;
2043 check_invariants(iter);
2047 gtk_text_btree_get_iter_at_line_byte (GtkTextBTree *tree,
2052 GtkTextRealIter *real = (GtkTextRealIter*)iter;
2056 g_return_if_fail(iter != NULL);
2057 g_return_if_fail(tree != NULL);
2059 line = gtk_text_btree_get_line(tree, line_number, &real_line);
2061 iter_init_from_byte_offset(iter, tree, line, byte_index);
2063 /* We might as well cache this, since we know it. */
2064 real->cached_line_number = real_line;
2066 check_invariants(iter);
2070 gtk_text_btree_get_iter_at_line (GtkTextBTree *tree,
2075 g_return_if_fail(iter != NULL);
2076 g_return_if_fail(tree != NULL);
2077 g_return_if_fail(line != NULL);
2079 iter_init_from_byte_offset(iter, tree, line, byte_offset);
2081 check_invariants(iter);
2085 gtk_text_btree_get_iter_at_first_toggle (GtkTextBTree *tree,
2091 g_return_val_if_fail(iter != NULL, FALSE);
2092 g_return_val_if_fail(tree != NULL, FALSE);
2094 line = gtk_text_btree_first_could_contain_tag(tree, tag);
2098 /* Set iter to last in tree */
2099 gtk_text_btree_get_last_iter(tree, iter);
2100 check_invariants(iter);
2105 iter_init_from_byte_offset(iter, tree, line, 0);
2106 gtk_text_iter_forward_find_tag_toggle(iter, tag);
2107 check_invariants(iter);
2113 gtk_text_btree_get_iter_at_last_toggle (GtkTextBTree *tree,
2119 g_return_val_if_fail(iter != NULL, FALSE);
2120 g_return_val_if_fail(tree != NULL, FALSE);
2122 line = gtk_text_btree_last_could_contain_tag(tree, tag);
2126 /* Set iter to first in tree */
2127 gtk_text_btree_get_iter_at_line_char(tree, iter, 0, 0);
2128 check_invariants(iter);
2133 iter_init_from_byte_offset(iter, tree, line, -1);
2134 gtk_text_iter_backward_find_tag_toggle(iter, tag);
2135 check_invariants(iter);
2141 gtk_text_btree_get_iter_from_string (GtkTextBTree *tree,
2143 const gchar *string)
2145 g_return_val_if_fail(iter != NULL, FALSE);
2146 g_return_val_if_fail(tree != NULL, FALSE);
2152 gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree,
2154 const gchar *mark_name)
2156 GtkTextLineSegment *mark;
2158 g_return_val_if_fail(iter != NULL, FALSE);
2159 g_return_val_if_fail(tree != NULL, FALSE);
2161 mark = gtk_text_btree_get_mark_by_name(tree, mark_name);
2167 gtk_text_btree_get_iter_at_mark(tree, iter, mark);
2168 check_invariants(iter);
2174 gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
2176 GtkTextLineSegment *mark)
2178 g_return_if_fail(iter != NULL);
2179 g_return_if_fail(tree != NULL);
2180 g_return_if_fail(mark->type == >k_text_left_mark_type ||
2181 mark->type == >k_text_right_mark_type);
2183 iter_init_from_segment(iter, tree, mark->body.mark.line, mark);
2184 g_assert(mark->body.mark.line == gtk_text_iter_get_line(iter));
2185 check_invariants(iter);
2189 gtk_text_btree_get_last_iter (GtkTextBTree *tree,
2192 g_return_if_fail(iter != NULL);
2193 g_return_if_fail(tree != NULL);
2195 gtk_text_btree_get_iter_at_char(tree,
2197 gtk_text_btree_char_count(tree));
2198 check_invariants(iter);
2202 gtk_text_iter_spew (const GtkTextIter *iter, const gchar *desc)
2204 GtkTextRealIter *real = (GtkTextRealIter*)iter;
2206 g_return_if_fail(iter != NULL);
2208 if (real->chars_changed_stamp != gtk_text_btree_get_chars_changed_stamp(real->tree))
2209 g_print(" %20s: <invalidated iterator>\n", desc);
2212 check_invariants(iter);
2213 g_print(" %20s: line %d / char %d / line char %d / line byte %d\n",
2215 gtk_text_iter_get_line_number(iter),
2216 gtk_text_iter_get_char_index(iter),
2217 gtk_text_iter_get_line_char(iter),
2218 gtk_text_iter_get_line_byte(iter));
2219 check_invariants(iter);
2224 gtk_text_iter_check(const GtkTextIter *iter)
2226 const GtkTextRealIter *real = (const GtkTextRealIter*)iter;
2227 gint line_char_offset, line_byte_offset, seg_char_offset, seg_byte_offset;
2228 GtkTextLineSegment *byte_segment;
2229 GtkTextLineSegment *byte_any_segment;
2230 GtkTextLineSegment *char_segment;
2231 GtkTextLineSegment *char_any_segment;
2232 gboolean segments_updated;
2234 /* We are going to check our class invariants for the Iter class. */
2236 if (real->chars_changed_stamp !=
2237 gtk_text_btree_get_chars_changed_stamp(real->tree))
2238 g_error("iterator check failed: invalid iterator");
2240 if (real->line_char_offset < 0 && real->line_byte_offset < 0)
2241 g_error("iterator check failed: both char and byte offsets are invalid");
2243 segments_updated = (real->segments_changed_stamp ==
2244 gtk_text_btree_get_segments_changed_stamp(real->tree));
2247 printf("checking iter, segments %s updated, byte %d char %d\n",
2248 segments_updated ? "are" : "aren't",
2249 real->line_byte_offset,
2250 real->line_char_offset);
2253 if (real->line_byte_offset == 97 &&
2254 real->line_char_offset == 95)
2257 if (segments_updated)
2259 if (real->segment_char_offset < 0 && real->segment_byte_offset < 0)
2260 g_error("iterator check failed: both char and byte segment offsets are invalid");
2262 if (real->segment->char_count == 0)
2263 g_error("iterator check failed: segment is not indexable.");
2265 if (real->line_char_offset >= 0 && real->segment_char_offset < 0)
2266 g_error("segment char offset is not properly up-to-date");
2268 if (real->line_byte_offset >= 0 && real->segment_byte_offset < 0)
2269 g_error("segment byte offset is not properly up-to-date");
2271 if (real->segment_byte_offset >= 0 &&
2272 real->segment_byte_offset >= real->segment->byte_count)
2273 g_error("segment byte offset is too large.");
2275 if (real->segment_char_offset >= 0 &&
2276 real->segment_char_offset >= real->segment->char_count)
2277 g_error("segment char offset is too large.");
2280 if (real->line_byte_offset >= 0)
2282 gtk_text_line_byte_locate(real->line, real->line_byte_offset,
2283 &byte_segment, &byte_any_segment,
2284 &seg_byte_offset, &line_byte_offset);
2286 if (line_byte_offset != real->line_byte_offset)
2287 g_error("wrong byte offset was stored in iterator");
2289 if (segments_updated)
2291 if (real->segment != byte_segment)
2292 g_error("wrong segment was stored in iterator");
2294 if (real->any_segment != byte_any_segment)
2295 g_error("wrong any_segment was stored in iterator");
2297 if (seg_byte_offset != real->segment_byte_offset)
2298 g_error("wrong segment byte offset was stored in iterator");
2302 if (real->line_char_offset >= 0)
2304 gtk_text_line_char_locate(real->line, real->line_char_offset,
2305 &char_segment, &char_any_segment,
2306 &seg_char_offset, &line_char_offset);
2308 if (line_char_offset != real->line_char_offset)
2309 g_error("wrong char offset was stored in iterator");
2311 if (segments_updated)
2313 if (real->segment != char_segment)
2314 g_error("wrong segment was stored in iterator");
2316 if (real->any_segment != char_any_segment)
2317 g_error("wrong any_segment was stored in iterator");
2319 if (seg_char_offset != real->segment_char_offset)
2320 g_error("wrong segment char offset was stored in iterator");
2324 if (real->line_char_offset >= 0 && real->line_byte_offset >= 0)
2326 if (byte_segment != char_segment)
2327 g_error("char and byte offsets did not point to the same segment");
2329 if (byte_any_segment != char_any_segment)
2330 g_error("char and byte offsets did not point to the same any segment");
2332 /* Make sure the segment offsets are equivalent, if it's a char
2334 if (char_segment->type == >k_text_char_type)
2336 gint byte_offset = 0;
2337 gint char_offset = 0;
2338 while (char_offset < seg_char_offset)
2342 gtk_text_utf_to_unichar(char_segment->body.chars + byte_offset,
2347 if (byte_offset != seg_byte_offset)
2348 g_error("byte offset did not correspond to char offset");
2351 gtk_text_view_num_utf_chars(char_segment->body.chars,
2354 if (char_offset != seg_char_offset)
2355 g_error("char offset did not correspond to byte offset");
2359 if (real->cached_line_number >= 0)
2363 should_be = gtk_text_line_get_number(real->line);
2364 if (real->cached_line_number != should_be)
2365 g_error("wrong line number was cached");
2368 if (real->cached_char_index >= 0)
2370 if (real->line_char_offset >= 0) /* only way we can check it
2371 efficiently, not a real
2376 char_index = gtk_text_line_char_index(real->line);
2377 char_index += real->line_char_offset;
2379 if (real->cached_char_index != char_index)
2380 g_error("wrong char index was cached");