Created
May 14, 2015 03:03
-
-
Save lf94/2726757d6b15151a83bc to your computer and use it in GitHub Desktop.
GNOME GtkTextView/GtkTextBuffer's buffer data management
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void | |
_gtk_text_btree_insert (GtkTextIter *iter, | |
const gchar *text, | |
gint len) | |
{ | |
GtkTextLineSegment *prev_seg; /* The segment just before the first | |
* new segment (NULL means new segment | |
* is at beginning of line). */ | |
GtkTextLineSegment *cur_seg; /* Current segment; new characters | |
* are inserted just after this one. | |
* NULL means insert at beginning of | |
* line. */ | |
GtkTextLine *line; /* Current line (new segments are | |
* added to this line). */ | |
GtkTextLineSegment *seg; | |
GtkTextLine *newline; | |
int chunk_len; /* # characters in current chunk. */ | |
gint sol; /* start of line */ | |
gint eol; /* Pointer to character just after last | |
* one in current chunk. | |
*/ | |
gint delim; /* index of paragraph delimiter */ | |
int line_count_delta; /* Counts change to total number of | |
* lines in file. | |
*/ | |
int char_count_delta; /* change to number of chars */ | |
GtkTextBTree *tree; | |
gint start_byte_index; | |
GtkTextLine *start_line; | |
g_return_if_fail (text != NULL); | |
g_return_if_fail (iter != NULL); | |
if (len < 0) | |
len = strlen (text); | |
/* extract iterator info */ | |
tree = _gtk_text_iter_get_btree (iter); | |
line = _gtk_text_iter_get_text_line (iter); | |
start_line = line; | |
start_byte_index = gtk_text_iter_get_line_index (iter); | |
/* Get our insertion segment split. Note this assumes line allows | |
* char insertions, which isn't true of the "last" line. But iter | |
* should not be on that line, as we assert here. | |
*/ | |
g_assert (!_gtk_text_line_is_last (line, tree)); | |
prev_seg = gtk_text_line_segment_split (iter); | |
cur_seg = prev_seg; | |
/* Invalidate all iterators */ | |
chars_changed (tree); | |
segments_changed (tree); | |
/* | |
* Chop the text up into lines and create a new segment for | |
* each line, plus a new line for the leftovers from the | |
* previous line. | |
*/ | |
eol = 0; | |
sol = 0; | |
line_count_delta = 0; | |
char_count_delta = 0; | |
while (eol < len) | |
{ | |
sol = eol; | |
pango_find_paragraph_boundary (text + sol, | |
len - sol, | |
&delim, | |
&eol); | |
/* make these relative to the start of the text */ | |
delim += sol; | |
eol += sol; | |
g_assert (eol >= sol); | |
g_assert (delim >= sol); | |
g_assert (eol >= delim); | |
g_assert (sol >= 0); | |
g_assert (eol <= len); | |
chunk_len = eol - sol; | |
g_assert (g_utf8_validate (&text[sol], chunk_len, NULL)); | |
seg = _gtk_char_segment_new (&text[sol], chunk_len); | |
char_count_delta += seg->char_count; | |
if (cur_seg == NULL) | |
{ | |
seg->next = line->segments; | |
line->segments = seg; | |
} | |
else | |
{ | |
seg->next = cur_seg->next; | |
cur_seg->next = seg; | |
} | |
if (delim == eol) | |
{ | |
/* chunk didn't end with a paragraph separator */ | |
g_assert (eol == len); | |
break; | |
} | |
/* | |
* The chunk ended with a newline, so create a new GtkTextLine | |
* and move the remainder of the old line to it. | |
*/ | |
newline = gtk_text_line_new (); | |
gtk_text_line_set_parent (newline, line->parent); | |
newline->next = line->next; | |
line->next = newline; | |
newline->segments = seg->next; | |
seg->next = NULL; | |
line = newline; | |
cur_seg = NULL; | |
line_count_delta++; | |
} | |
/* | |
* Cleanup the starting line for the insertion, plus the ending | |
* line if it's different. | |
*/ | |
cleanup_line (start_line); | |
if (line != start_line) | |
{ | |
cleanup_line (line); | |
} | |
post_insert_fixup (tree, line, line_count_delta, char_count_delta); | |
/* Invalidate our region, and reset the iterator the user | |
passed in to point to the end of the inserted text. */ | |
{ | |
GtkTextIter start; | |
GtkTextIter end; | |
_gtk_text_btree_get_iter_at_line (tree, | |
&start, | |
start_line, | |
start_byte_index); | |
end = start; | |
/* We could almost certainly be more efficient here | |
by saving the information from the insertion loop | |
above. FIXME */ | |
gtk_text_iter_forward_chars (&end, char_count_delta); | |
DV (g_print ("invalidating due to inserting some text (%s)\n", G_STRLOC)); | |
_gtk_text_btree_invalidate_region (tree, &start, &end, FALSE); | |
/* Convenience for the user */ | |
*iter = end; | |
gtk_text_btree_resolve_bidi (&start, &end); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment