Try to match an off toggle here with the matching on toggle if it
2005-10-11 Matthias Clasen <mclasen@redhat.com> * 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.
This commit is contained in:
parent
8ad0abb867
commit
a07a5ecba7
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
2005-10-11 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
|
* 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 <tommi.komulainen@iki.fi>
|
2005-10-10 Tommi Komulainen <tommi.komulainen@iki.fi>
|
||||||
|
|
||||||
* gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error
|
* gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
|
2005-10-11 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
|
* 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 <tommi.komulainen@iki.fi>
|
2005-10-10 Tommi Komulainen <tommi.komulainen@iki.fi>
|
||||||
|
|
||||||
* gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error
|
* gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* gtktextbtree.c --
|
* Gtktextbtree.c --
|
||||||
*
|
*
|
||||||
* This file contains code that manages the B-tree representation
|
* This file contains code that manages the B-tree representation
|
||||||
* of text for the text buffer and implements character and
|
* of text for the text buffer and implements character and
|
||||||
@ -732,7 +732,7 @@ _gtk_text_btree_delete (GtkTextIter *start,
|
|||||||
* of the deletion range. */
|
* of the deletion range. */
|
||||||
GtkTextLineSegment *last_seg; /* The segment just after the end
|
GtkTextLineSegment *last_seg; /* The segment just after the end
|
||||||
* of the deletion range. */
|
* of the deletion range. */
|
||||||
GtkTextLineSegment *seg, *next;
|
GtkTextLineSegment *seg, *next, *next2;
|
||||||
GtkTextLine *curline;
|
GtkTextLine *curline;
|
||||||
GtkTextBTreeNode *curnode, *node;
|
GtkTextBTreeNode *curnode, *node;
|
||||||
GtkTextBTree *tree;
|
GtkTextBTree *tree;
|
||||||
@ -885,12 +885,29 @@ _gtk_text_btree_delete (GtkTextIter *start,
|
|||||||
seg->next = start_line->segments;
|
seg->next = start_line->segments;
|
||||||
start_line->segments = seg;
|
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;
|
seg->next = prev_seg->next;
|
||||||
prev_seg->next = seg;
|
prev_seg->next = seg;
|
||||||
}
|
}
|
||||||
if (seg->type->leftGravity)
|
|
||||||
|
if (seg && seg->type->leftGravity)
|
||||||
{
|
{
|
||||||
prev_seg = seg;
|
prev_seg = seg;
|
||||||
}
|
}
|
||||||
@ -4718,16 +4735,20 @@ cleanup_line (GtkTextLine *line)
|
|||||||
while (changed)
|
while (changed)
|
||||||
{
|
{
|
||||||
changed = FALSE;
|
changed = FALSE;
|
||||||
for (prev_p = &line->segments, seg = *prev_p;
|
prev_p = &line->segments;
|
||||||
seg != NULL;
|
for (seg = *prev_p; seg != NULL; seg = *prev_p)
|
||||||
prev_p = &(*prev_p)->next, seg = *prev_p)
|
|
||||||
{
|
{
|
||||||
if (seg->type->cleanupFunc != NULL)
|
if (seg->type->cleanupFunc != NULL)
|
||||||
{
|
{
|
||||||
*prev_p = (*seg->type->cleanupFunc)(seg, line);
|
*prev_p = (*seg->type->cleanupFunc)(seg, line);
|
||||||
if (seg != *prev_p)
|
if (seg != *prev_p)
|
||||||
changed = TRUE;
|
{
|
||||||
|
changed = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prev_p = &(*prev_p)->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,8 +211,12 @@ _gtk_char_segment_new (const gchar *text, guint len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GtkTextLineSegment*
|
GtkTextLineSegment*
|
||||||
_gtk_char_segment_new_from_two_strings (const gchar *text1, guint len1,
|
_gtk_char_segment_new_from_two_strings (const gchar *text1,
|
||||||
const gchar *text2, guint len2)
|
guint len1,
|
||||||
|
guint chars1,
|
||||||
|
const gchar *text2,
|
||||||
|
guint len2,
|
||||||
|
guint chars2)
|
||||||
{
|
{
|
||||||
GtkTextLineSegment *seg;
|
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);
|
memcpy (seg->body.chars + len1, text2, len2);
|
||||||
seg->body.chars[len1+len2] = '\0';
|
seg->body.chars[len1+len2] = '\0';
|
||||||
|
|
||||||
/* In principle this function could probably take chars1 and chars2
|
seg->char_count = chars1 + 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);
|
|
||||||
|
|
||||||
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
||||||
char_segment_self_check (seg);
|
char_segment_self_check (seg);
|
||||||
@ -326,8 +328,12 @@ char_segment_cleanup_func (segPtr, line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
newPtr =
|
newPtr =
|
||||||
_gtk_char_segment_new_from_two_strings (segPtr->body.chars, segPtr->byte_count,
|
_gtk_char_segment_new_from_two_strings (segPtr->body.chars,
|
||||||
segPtr2->body.chars, segPtr2->byte_count);
|
segPtr->byte_count,
|
||||||
|
segPtr->char_count,
|
||||||
|
segPtr2->body.chars,
|
||||||
|
segPtr2->byte_count,
|
||||||
|
segPtr2->char_count);
|
||||||
|
|
||||||
newPtr->next = segPtr2->next;
|
newPtr->next = segPtr2->next;
|
||||||
|
|
||||||
|
@ -158,8 +158,10 @@ GtkTextLineSegment *_gtk_char_segment_new (const gchar *text
|
|||||||
guint len);
|
guint len);
|
||||||
GtkTextLineSegment *_gtk_char_segment_new_from_two_strings (const gchar *text1,
|
GtkTextLineSegment *_gtk_char_segment_new_from_two_strings (const gchar *text1,
|
||||||
guint len1,
|
guint len1,
|
||||||
|
guint chars1,
|
||||||
const gchar *text2,
|
const gchar *text2,
|
||||||
guint len2);
|
guint len2,
|
||||||
|
guint chars2);
|
||||||
GtkTextLineSegment *_gtk_toggle_segment_new (GtkTextTagInfo *info,
|
GtkTextLineSegment *_gtk_toggle_segment_new (GtkTextTagInfo *info,
|
||||||
gboolean on);
|
gboolean on);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user