From a07a5ecba7c1a6cc3c726d0529f30f75a32989ed Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 11 Oct 2005 14:39:17 +0000 Subject: [PATCH] Try to match an off toggle here with the matching on toggle if it 2005-10-11 Matthias Clasen * gtk/gtktextbtree.c (_gtk_text_btree_delete): Try to match an off toggle here with the matching on toggle if it immediately follows. This is a common case, and handling it here prevents quadratic blowup in cleanup_line() below. (#317125) * gtk/gtktextsegment.h: * gtk/gtktextsegment.c (_gtk_char_segment_new_from_two_strings): Pass the character counts into this function instead of computing them again. --- ChangeLog | 12 ++++++++++++ ChangeLog.pre-2-10 | 12 ++++++++++++ gtk/gtktextbtree.c | 39 ++++++++++++++++++++++++++++++--------- gtk/gtktextsegment.c | 20 +++++++++++++------- gtk/gtktextsegment.h | 4 +++- 5 files changed, 70 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index f3d469d9ce..350c8735dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-10-11 Matthias Clasen + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): Try to match an off + toggle here with the matching on toggle if it immediately follows. + This is a common case, and handling it here prevents quadratic blowup + in cleanup_line() below. (#317125) + + * gtk/gtktextsegment.h: + * gtk/gtktextsegment.c (_gtk_char_segment_new_from_two_strings): Pass + the character counts into this function instead of computing them + again. + 2005-10-10 Tommi Komulainen * gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index f3d469d9ce..350c8735dd 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,15 @@ +2005-10-11 Matthias Clasen + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): Try to match an off + toggle here with the matching on toggle if it immediately follows. + This is a common case, and handling it here prevents quadratic blowup + in cleanup_line() below. (#317125) + + * gtk/gtktextsegment.h: + * gtk/gtktextsegment.c (_gtk_char_segment_new_from_two_strings): Pass + the character counts into this function instead of computing them + again. + 2005-10-10 Tommi Komulainen * gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index 1e78da9eb5..98fc15d036 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -1,5 +1,5 @@ /* - * gtktextbtree.c -- + * Gtktextbtree.c -- * * This file contains code that manages the B-tree representation * of text for the text buffer and implements character and @@ -732,7 +732,7 @@ _gtk_text_btree_delete (GtkTextIter *start, * of the deletion range. */ GtkTextLineSegment *last_seg; /* The segment just after the end * of the deletion range. */ - GtkTextLineSegment *seg, *next; + GtkTextLineSegment *seg, *next, *next2; GtkTextLine *curline; GtkTextBTreeNode *curnode, *node; GtkTextBTree *tree; @@ -885,12 +885,29 @@ _gtk_text_btree_delete (GtkTextIter *start, seg->next = start_line->segments; start_line->segments = seg; } - else - { + else if (prev_seg->next && + seg->type == >k_text_toggle_off_type && + prev_seg->next->type == >k_text_toggle_on_type && + seg->body.toggle.info == prev_seg->next->body.toggle.info) + { + /* Try to match an off toggle with the matching on toggle + * if it immediately follows. This is a common case, and + * handling it here prevents quadratic blowup in + * cleanup_line() below. See bug 317125. + */ + next2 = prev_seg->next->next; + g_free ((char *)prev_seg->next); + prev_seg->next = next2; + g_free ((char *)seg); + seg = NULL; + } + else + { seg->next = prev_seg->next; prev_seg->next = seg; } - if (seg->type->leftGravity) + + if (seg && seg->type->leftGravity) { prev_seg = seg; } @@ -4718,16 +4735,20 @@ cleanup_line (GtkTextLine *line) while (changed) { changed = FALSE; - for (prev_p = &line->segments, seg = *prev_p; - seg != NULL; - prev_p = &(*prev_p)->next, seg = *prev_p) + prev_p = &line->segments; + for (seg = *prev_p; seg != NULL; seg = *prev_p) { if (seg->type->cleanupFunc != NULL) { *prev_p = (*seg->type->cleanupFunc)(seg, line); if (seg != *prev_p) - changed = TRUE; + { + changed = TRUE; + continue; + } } + + prev_p = &(*prev_p)->next; } } } diff --git a/gtk/gtktextsegment.c b/gtk/gtktextsegment.c index 390e14bcfc..3b961ad66b 100644 --- a/gtk/gtktextsegment.c +++ b/gtk/gtktextsegment.c @@ -211,8 +211,12 @@ _gtk_char_segment_new (const gchar *text, guint len) } GtkTextLineSegment* -_gtk_char_segment_new_from_two_strings (const gchar *text1, guint len1, - const gchar *text2, guint len2) +_gtk_char_segment_new_from_two_strings (const gchar *text1, + guint len1, + guint chars1, + const gchar *text2, + guint len2, + guint chars2) { GtkTextLineSegment *seg; @@ -227,9 +231,7 @@ _gtk_char_segment_new_from_two_strings (const gchar *text1, guint len1, memcpy (seg->body.chars + len1, text2, len2); seg->body.chars[len1+len2] = '\0'; - /* In principle this function could probably take chars1 and chars2 - as args, since it's typically used to merge two char segments */ - seg->char_count = g_utf8_strlen (seg->body.chars, seg->byte_count); + seg->char_count = chars1 + chars2; if (gtk_debug_flags & GTK_DEBUG_TEXT) char_segment_self_check (seg); @@ -326,8 +328,12 @@ char_segment_cleanup_func (segPtr, line) } newPtr = - _gtk_char_segment_new_from_two_strings (segPtr->body.chars, segPtr->byte_count, - segPtr2->body.chars, segPtr2->byte_count); + _gtk_char_segment_new_from_two_strings (segPtr->body.chars, + segPtr->byte_count, + segPtr->char_count, + segPtr2->body.chars, + segPtr2->byte_count, + segPtr2->char_count); newPtr->next = segPtr2->next; diff --git a/gtk/gtktextsegment.h b/gtk/gtktextsegment.h index def6e25852..691147b08c 100644 --- a/gtk/gtktextsegment.h +++ b/gtk/gtktextsegment.h @@ -158,8 +158,10 @@ GtkTextLineSegment *_gtk_char_segment_new (const gchar *text guint len); GtkTextLineSegment *_gtk_char_segment_new_from_two_strings (const gchar *text1, guint len1, + guint chars1, const gchar *text2, - guint len2); + guint len2, + guint chars2); GtkTextLineSegment *_gtk_toggle_segment_new (GtkTextTagInfo *info, gboolean on);