From a760ad804e1603ca6ee7e164e6cc5dc12e0f3b41 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 13 Feb 2002 23:44:03 +0000 Subject: [PATCH] just go ahead and flush all the first validate stuff if it hasn't been 2002-02-13 Havoc Pennington * gtk/gtktextview.c (gtk_text_view_paint): just go ahead and flush all the first validate stuff if it hasn't been done, presumably someone called process_updates at a weird time. * tests/testtext.c (do_apply_colors): terminate on >= end, not > end, avoids infinite loop when end is at the end of the buffer. * gtk/gtktextbtree.c (_gtk_text_btree_delete): when creating a line data, we were adding it to the wrong line ("line" instead of "start_line") --- ChangeLog | 13 +++++ ChangeLog.pre-2-0 | 13 +++++ ChangeLog.pre-2-10 | 13 +++++ ChangeLog.pre-2-2 | 13 +++++ ChangeLog.pre-2-4 | 13 +++++ ChangeLog.pre-2-6 | 13 +++++ ChangeLog.pre-2-8 | 13 +++++ gtk/gtktextbtree.c | 16 ++++-- gtk/gtktextbtree.h | 10 ++++ gtk/gtktextbuffer.c | 9 ++++ gtk/gtktextlayout.c | 6 ++- gtk/gtktextview.c | 119 +++++++++++++++++++++++++++++--------------- tests/testtext.c | 2 +- 13 files changed, 205 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3be78ccf65..91483566a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2002-02-13 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_paint): just go ahead and flush + all the first validate stuff if it hasn't been done, presumably + someone called process_updates at a weird time. + + * tests/testtext.c (do_apply_colors): terminate on >= end, not > + end, avoids infinite loop when end is at the end of the buffer. + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): when creating a + line data, we were adding it to the wrong line ("line" instead of + "start_line") + 2002-02-13 Joe Shaw * gtk/gtktreeitem.c (gtk_tree_item_expose): Don't chain up to the diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 3be78ccf65..91483566a3 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,16 @@ +2002-02-13 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_paint): just go ahead and flush + all the first validate stuff if it hasn't been done, presumably + someone called process_updates at a weird time. + + * tests/testtext.c (do_apply_colors): terminate on >= end, not > + end, avoids infinite loop when end is at the end of the buffer. + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): when creating a + line data, we were adding it to the wrong line ("line" instead of + "start_line") + 2002-02-13 Joe Shaw * gtk/gtktreeitem.c (gtk_tree_item_expose): Don't chain up to the diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 3be78ccf65..91483566a3 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,16 @@ +2002-02-13 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_paint): just go ahead and flush + all the first validate stuff if it hasn't been done, presumably + someone called process_updates at a weird time. + + * tests/testtext.c (do_apply_colors): terminate on >= end, not > + end, avoids infinite loop when end is at the end of the buffer. + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): when creating a + line data, we were adding it to the wrong line ("line" instead of + "start_line") + 2002-02-13 Joe Shaw * gtk/gtktreeitem.c (gtk_tree_item_expose): Don't chain up to the diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 3be78ccf65..91483566a3 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,16 @@ +2002-02-13 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_paint): just go ahead and flush + all the first validate stuff if it hasn't been done, presumably + someone called process_updates at a weird time. + + * tests/testtext.c (do_apply_colors): terminate on >= end, not > + end, avoids infinite loop when end is at the end of the buffer. + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): when creating a + line data, we were adding it to the wrong line ("line" instead of + "start_line") + 2002-02-13 Joe Shaw * gtk/gtktreeitem.c (gtk_tree_item_expose): Don't chain up to the diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 3be78ccf65..91483566a3 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,16 @@ +2002-02-13 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_paint): just go ahead and flush + all the first validate stuff if it hasn't been done, presumably + someone called process_updates at a weird time. + + * tests/testtext.c (do_apply_colors): terminate on >= end, not > + end, avoids infinite loop when end is at the end of the buffer. + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): when creating a + line data, we were adding it to the wrong line ("line" instead of + "start_line") + 2002-02-13 Joe Shaw * gtk/gtktreeitem.c (gtk_tree_item_expose): Don't chain up to the diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 3be78ccf65..91483566a3 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,16 @@ +2002-02-13 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_paint): just go ahead and flush + all the first validate stuff if it hasn't been done, presumably + someone called process_updates at a weird time. + + * tests/testtext.c (do_apply_colors): terminate on >= end, not > + end, avoids infinite loop when end is at the end of the buffer. + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): when creating a + line data, we were adding it to the wrong line ("line" instead of + "start_line") + 2002-02-13 Joe Shaw * gtk/gtktreeitem.c (gtk_tree_item_expose): Don't chain up to the diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 3be78ccf65..91483566a3 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,16 @@ +2002-02-13 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_paint): just go ahead and flush + all the first validate stuff if it hasn't been done, presumably + someone called process_updates at a weird time. + + * tests/testtext.c (do_apply_colors): terminate on >= end, not > + end, avoids infinite loop when end is at the end of the buffer. + + * gtk/gtktextbtree.c (_gtk_text_btree_delete): when creating a + line data, we were adding it to the wrong line ("line" instead of + "start_line") + 2002-02-13 Joe Shaw * gtk/gtktreeitem.c (gtk_tree_item_expose): Don't chain up to the diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index 5f00fc088f..fa5aeb095f 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -575,6 +575,7 @@ _gtk_text_btree_delete (GtkTextIter *start, _gtk_text_btree_check (tree); /* Broadcast the need for redisplay before we break the iterators */ + DV (g_print ("invalidating due to deleting some text (%s)\n", G_STRLOC)); _gtk_text_btree_invalidate_region (tree, start, end); /* Save the byte offset so we can reset the iterators */ @@ -826,8 +827,8 @@ _gtk_text_btree_delete (GtkTextIter *start, * we do need to store our temporary sizes. So we * create the line data and assume a line w/h of 0. */ - ld = _gtk_text_line_data_new (view->layout, line); - _gtk_text_line_add_data (line, ld); + ld = _gtk_text_line_data_new (view->layout, start_line); + _gtk_text_line_add_data (start_line, ld); ld->width = 0; ld->height = 0; ld->valid = FALSE; @@ -1033,6 +1034,7 @@ _gtk_text_btree_insert (GtkTextIter *iter, 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); @@ -1081,6 +1083,7 @@ insert_pixbuf_or_widget_segment (GtkTextIter *iter, *iter = start; gtk_text_iter_forward_char (iter); /* skip forward past the segment */ + DV (g_print ("invalidating due to inserting pixbuf/widget (%s)\n", G_STRLOC)); _gtk_text_btree_invalidate_region (tree, &start, iter); } @@ -1414,9 +1417,9 @@ _gtk_text_btree_remove_view (GtkTextBTree *tree, } void -_gtk_text_btree_invalidate_region (GtkTextBTree *tree, - const GtkTextIter *start, - const GtkTextIter *end) +_gtk_text_btree_invalidate_region (GtkTextBTree *tree, + const GtkTextIter *start, + const GtkTextIter *end) { BTreeView *view; @@ -1526,6 +1529,7 @@ queue_tag_redisplay (GtkTextBTree *tree, { if (_gtk_text_tag_affects_size (tag)) { + DV (g_print ("invalidating due to size-affecting tag (%s)\n", G_STRLOC)); _gtk_text_btree_invalidate_region (tree, start, end); } else if (_gtk_text_tag_affects_nonsize_appearance (tag)) @@ -2448,6 +2452,7 @@ redisplay_mark (GtkTextLineSegment *mark) end = iter; gtk_text_iter_forward_char (&end); + DV (g_print ("invalidating due to moving visible mark (%s)\n", G_STRLOC)); _gtk_text_btree_invalidate_region (mark->body.mark.tree, &iter, &end); } @@ -5411,6 +5416,7 @@ tag_changed_cb (GtkTextTagTable *table, { /* Must be a last toggle if there was a first one. */ _gtk_text_btree_get_iter_at_last_toggle (tree, &end, tag); + DV (g_print ("invalidating due to tag change (%s)\n", G_STRLOC)); _gtk_text_btree_invalidate_region (tree, &start, &end); diff --git a/gtk/gtktextbtree.h b/gtk/gtktextbtree.h index b3ae5fb93f..dea958ec37 100644 --- a/gtk/gtktextbtree.h +++ b/gtk/gtktextbtree.h @@ -1,6 +1,16 @@ #ifndef GTK_TEXT_BTREE_H #define GTK_TEXT_BTREE_H +#if 0 +#define DEBUG_VALIDATION_AND_SCROLLING +#endif + +#ifdef DEBUG_VALIDATION_AND_SCROLLING +#define DV(x) (x) +#else +#define DV(x) +#endif + #include #include #include diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index 7650d41e2a..63a7f68883 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -850,6 +850,15 @@ gtk_text_buffer_real_insert_range (GtkTextBuffer *buffer, range_start = start; range_end = start; + + /* FIXME if you insert a range into itself, this can loop infinitely because + * the region being copied keeps growing as we insert. The fix is probably to create a + * copy of what's being inserted, or to save two regions, the region before + * the insertion point and the region after. + * + * http://bugzilla.gnome.org/show_bug.cgi?id=71412 + */ + while (TRUE) { gint start_offset; diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index 806d147f32..15358c95e9 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -293,6 +293,7 @@ gtk_text_layout_default_style_changed (GtkTextLayout *layout) { g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout)); + DV (g_print ("invalidating all due to default style change (%s)\n", G_STRLOC)); gtk_text_layout_invalidate_all (layout); } @@ -335,6 +336,7 @@ gtk_text_layout_set_contexts (GtkTextLayout *layout, layout->rtl_context = rtl_context; g_object_ref (G_OBJECT (rtl_context)); + DV (g_print ("invalidating all due to new pango contexts (%s)\n", G_STRLOC)); gtk_text_layout_invalidate_all (layout); } @@ -391,6 +393,7 @@ gtk_text_layout_set_screen_width (GtkTextLayout *layout, gint width) layout->screen_width = width; + DV (g_print ("invalidating all due to new screen width (%s)\n", G_STRLOC)); gtk_text_layout_invalidate_all (layout); } @@ -919,7 +922,8 @@ gtk_text_layout_real_wrap (GtkTextLayout *layout, GtkTextLineDisplay *display; g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), NULL); - + g_return_val_if_fail (line != NULL, NULL); + if (line_data == NULL) { line_data = _gtk_text_line_data_new (layout, line); diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index ceb9987d67..77b99bbe6a 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -82,9 +82,6 @@ * */ -#define SCREEN_WIDTH(widget) text_window_get_width (GTK_TEXT_VIEW (widget)->text_window) -#define SCREEN_HEIGHT(widget) text_window_get_height (GTK_TEXT_VIEW (widget)->text_window) - #if 0 #define DEBUG_VALIDATION_AND_SCROLLING #endif @@ -95,6 +92,9 @@ #define DV(x) #endif +#define SCREEN_WIDTH(widget) text_window_get_width (GTK_TEXT_VIEW (widget)->text_window) +#define SCREEN_HEIGHT(widget) text_window_get_height (GTK_TEXT_VIEW (widget)->text_window) + struct _GtkTextPendingScroll { GtkTextMark *mark; @@ -312,9 +312,10 @@ static void gtk_text_view_queue_scroll (GtkTextView *text_view, gdouble xalign, gdouble yalign); -static gboolean gtk_text_view_flush_scroll (GtkTextView *text_view); -static void gtk_text_view_update_adjustments (GtkTextView *text_view); -static void gtk_text_view_invalidate (GtkTextView *text_view); +static gboolean gtk_text_view_flush_scroll (GtkTextView *text_view); +static void gtk_text_view_update_adjustments (GtkTextView *text_view); +static void gtk_text_view_invalidate (GtkTextView *text_view); +static void gtk_text_view_flush_first_validate (GtkTextView *text_view); static void gtk_text_view_update_im_spot_location (GtkTextView *text_view); @@ -1146,7 +1147,8 @@ gtk_text_view_set_buffer (GtkTextView *text_view, if (GTK_WIDGET_VISIBLE (text_view)) gtk_widget_queue_draw (GTK_WIDGET (text_view)); - + + DV(g_print ("Invalidating due to set_buffer\n")); gtk_text_view_invalidate (text_view); } @@ -1547,7 +1549,10 @@ gtk_text_view_flush_scroll (GtkTextView *text_view) DV(g_print(G_STRLOC"\n")); if (text_view->pending_scroll == NULL) - return FALSE; + { + DV (g_print ("in flush scroll, no pending scroll\n")); + return FALSE; + } scroll = text_view->pending_scroll; @@ -2365,6 +2370,7 @@ gtk_text_view_remove_validate_idles (GtkTextView *text_view) { if (text_view->first_validate_idle != 0) { + DV (g_print ("Removing first validate idle: %s\n", G_STRLOC)); g_source_remove (text_view->first_validate_idle); text_view->first_validate_idle = 0; } @@ -2938,19 +2944,11 @@ gtk_text_view_size_allocate (GtkWidget *widget, if (yoffset_changed) gtk_adjustment_value_changed (vadj); - if (text_view->first_validate_idle != 0) - { - /* The GTK resize loop processes all the pending exposes right - * after doing the resize stuff, so the idle sizer won't have a - * chance to run. So we do the work here. - */ - - g_source_remove (text_view->first_validate_idle); - text_view->first_validate_idle = 0; - - if (!gtk_text_view_flush_scroll (text_view)) - gtk_text_view_validate_onscreen (text_view); - } + /* The GTK resize loop processes all the pending exposes right + * after doing the resize stuff, so the idle sizer won't have a + * chance to run. So we do the work here. + */ + gtk_text_view_flush_first_validate (text_view); /* widget->window doesn't get auto-redrawn as the layout is computed, so has to * be invalidated @@ -3004,23 +3002,18 @@ gtk_text_view_validate_onscreen (GtkTextView *text_view) g_assert (text_view->onscreen_validated); } -static gboolean -first_validate_callback (gpointer data) +static void +gtk_text_view_flush_first_validate (GtkTextView *text_view) { - GtkTextView *text_view = data; - - GDK_THREADS_ENTER (); - - /* Note that some of this code is duplicated at the end of size_allocate, - * keep in sync with that. - */ - - DV(g_print(G_STRLOC"\n")); + if (text_view->first_validate_idle == 0) + return; /* Do this first, which means that if an "invalidate" * occurs during any of this process, a new first_validate_callback * will be installed, and we'll start again. */ + DV (g_print ("removing first validate in %s\n", G_STRLOC)); + g_source_remove (text_view->first_validate_idle); text_view->first_validate_idle = 0; /* be sure we have up-to-date screen size set on the @@ -3047,8 +3040,23 @@ first_validate_callback (gpointer data) DV(g_print(">Leaving first validate idle ("G_STRLOC")\n")); g_assert (text_view->onscreen_validated); - } +} + +static gboolean +first_validate_callback (gpointer data) +{ + GtkTextView *text_view = data; + + GDK_THREADS_ENTER (); + + /* Note that some of this code is duplicated at the end of size_allocate, + * keep in sync with that. + */ + + DV(g_print(G_STRLOC"\n")); + + gtk_text_view_flush_first_validate (text_view); GDK_THREADS_LEAVE (); @@ -3082,11 +3090,12 @@ incremental_validate_callback (gpointer data) static void gtk_text_view_invalidate (GtkTextView *text_view) -{ +{ + DV (g_print (">Invalidate, onscreen_validated = %d now FALSE ("G_STRLOC")\n", + text_view->onscreen_validated)); + text_view->onscreen_validated = FALSE; - DV(g_print(">Invalidate, onscreen_validated = FALSE ("G_STRLOC")\n")); - if (!text_view->first_validate_idle) { text_view->first_validate_idle = g_idle_add_full (GTK_PRIORITY_RESIZE - 2, first_validate_callback, text_view, NULL); @@ -3110,6 +3119,7 @@ invalidated_handler (GtkTextLayout *layout, text_view = GTK_TEXT_VIEW (data); + DV (g_print ("Invalidating due to layout invalidate signal\n")); gtk_text_view_invalidate (text_view); } @@ -3205,7 +3215,10 @@ changed_handler (GtkTextLayout *layout, } if (yoffset_changed) - gtk_adjustment_value_changed (get_vadjustment (text_view)); + { + DV(g_print ("Changing scroll position (%s)\n", G_STRLOC)); + gtk_adjustment_value_changed (get_vadjustment (text_view)); + } /* FIXME be smarter about which anchored widgets we update */ @@ -4007,19 +4020,37 @@ gtk_text_view_paint (GtkWidget *widget, GtkTextView *text_view; GList *child_exposes; GList *tmp_list; + GdkRegion *updates; text_view = GTK_TEXT_VIEW (widget); g_return_if_fail (text_view->layout != NULL); g_return_if_fail (text_view->xoffset >= 0); g_return_if_fail (text_view->yoffset >= 0); - - DV (g_print (G_STRLOC": first_validate_idle: %d\n", - text_view->first_validate_idle)); + + while (text_view->first_validate_idle != 0) + { + DV (g_print (G_STRLOC": first_validate_idle: %d\n", + text_view->first_validate_idle)); + gtk_text_view_flush_first_validate (text_view); + } + + /* More regions could have become invalid in the above loop */ + updates = gdk_window_get_update_area (text_view->text_window->bin_window); + if (updates) + { + GdkRectangle rect; + + gdk_region_get_clipbox (updates, &rect); + + gdk_rectangle_union (area, &rect, area); + + gdk_region_destroy (updates); + } if (!text_view->onscreen_validated) { - g_warning (G_STRLOC ": somehow some text lines were modified or scrolling occurred since the last validation of lines on the screen - this is a known bug, no need to report."); + g_warning (G_STRLOC ": somehow some text lines were modified or scrolling occurred since the last validation of lines on the screen - may be a text widget bug."); G_BREAKPOINT (); } @@ -4957,6 +4988,7 @@ move_mark_to_pointer_and_scroll (GtkTextView *text_view, GtkTextMark *mark = gtk_text_buffer_get_mark (get_buffer (text_view), mark_name); + /* This may invalidate the layout */ DV(g_print (G_STRLOC": move mark\n")); gtk_text_buffer_move_mark (get_buffer (text_view), mark, @@ -4965,6 +4997,9 @@ move_mark_to_pointer_and_scroll (GtkTextView *text_view, DV(g_print (G_STRLOC": scrolling onscreen\n")); gtk_text_view_scroll_mark_onscreen (text_view, mark); } + + DV (g_print ("first validate idle leaving %s is %d\n", + G_STRLOC, text_view->first_validate_idle)); } static gint @@ -5865,6 +5900,8 @@ gtk_text_view_value_changed (GtkAdjustment *adj, /* process exposes */ if (GTK_WIDGET_REALIZED (text_view)) { + DV (g_print ("Processing updates (%s)", G_STRLOC)); + if (text_view->left_window) gdk_window_process_updates (text_view->left_window->bin_window, TRUE); diff --git a/tests/testtext.c b/tests/testtext.c index e153fe204f..e9c67dc22d 100644 --- a/tests/testtext.c +++ b/tests/testtext.c @@ -1086,7 +1086,7 @@ do_apply_colors (gpointer callback_data, gtk_text_iter_forward_char (&next); gtk_text_iter_forward_char (&next); - if (gtk_text_iter_compare (&next, &end) > 0) + if (gtk_text_iter_compare (&next, &end) >= 0) { next = end; done = TRUE;