gtksourceview r1979 - in trunk: . gtksourceview



Author: muntyan
Date: Sat Aug  2 21:17:43 2008
New Revision: 1979
URL: http://svn.gnome.org/viewvc/gtksourceview?rev=1979&view=rev

Log:
2008-08-02  Yevgen Muntyan  <muntyan tamu edu>

	Bug 114337 - long lines kill GtkSourceView.
	Worked it around by disabling syntax highlighting if analyzing
	single line took more than 2 seconds.

	* gtksourceview/gtksourcecontextengine.c:
	(GtkSourceContextEnginePrivate::disabled): new field,
	(gtk_source_context_engine_update_highlight): check that field,
	(analyze_line): check elapsed time on every iteration and abort
	in two seconds,
	(update_syntax): check whether analyze_line() has disabled
	highlighting,
	(disable_highlighting): new function to turn highlighting off.



Modified:
   trunk/ChangeLog
   trunk/gtksourceview/gtksourcecontextengine.c

Modified: trunk/gtksourceview/gtksourcecontextengine.c
==============================================================================
--- trunk/gtksourceview/gtksourcecontextengine.c	(original)
+++ trunk/gtksourceview/gtksourcecontextengine.c	Sat Aug  2 21:17:43 2008
@@ -71,6 +71,10 @@
 /* Maximal amount of time allowed to spent in one cycle of background idle. */
 #define INCREMENTAL_UPDATE_TIME_SLICE	30
 
+/* Maximal amount of time allowed to spent highlihting a single line. If it
+ * is not enough, then highlighting is disabled. */
+#define MAX_TIME_FOR_ONE_LINE		2000
+
 #define GTK_SOURCE_CONTEXT_ENGINE_ERROR (gtk_source_context_engine_error_quark ())
 
 /* Returns the definition corrsponding to the specified id. */
@@ -405,6 +409,9 @@
 	/* Whether or not to actually highlight the buffer. */
 	gboolean		 highlight;
 
+	/* Whether highlighting was disabled because of errors. */
+	gboolean		 disabled;
+
 	/* Region covering the unhighlighted text. */
 	GtkTextRegion		*refresh_region;
 
@@ -1937,7 +1944,7 @@
 	gint end_line;
 	GtkSourceContextEngine *ce = GTK_SOURCE_CONTEXT_ENGINE (engine);
 
-	if (!ce->priv->highlight)
+	if (!ce->priv->highlight || ce->priv->disabled)
 		return;
 
 	invalid_line = get_invalid_line (ce);
@@ -2299,6 +2306,26 @@
 	}
 }
 
+/**
+ * disable_highlighting:
+ *
+ * @ce: #GtkSourceContextEngine.
+ *
+ * Dsiables highlighting in case of errors (currently if highlighting
+ * a single line took too long, so that highlighting doesn't freeze
+ * text editor).
+ */
+static void
+disable_highlighting (GtkSourceContextEngine *ce)
+{
+	if (!ce->priv->disabled)
+	{
+		ce->priv->disabled = TRUE;
+		gtk_source_context_engine_attach_buffer (GTK_SOURCE_ENGINE (ce), NULL);
+		/* FIXME maybe emit some signal here? */
+	}
+}
+
 static void
 set_tag_style_hash_cb (const char             *style,
 		       GSList                 *tags,
@@ -4483,6 +4510,7 @@
 {
 	gint line_pos = 0;
 	GList *end_segments = NULL;
+	GTimer *timer;
 
 	g_assert (SEGMENT_IS_CONTAINER (state));
 
@@ -4490,6 +4518,8 @@
                 ce->priv->hint2 = state->last_child;
         g_assert (!ce->priv->hint2 || ce->priv->hint2->parent == state);
 
+	timer = g_timer_new ();
+
 	/* Find the contexts in the line. */
 	while (line_pos <= line->byte_length)
 	{
@@ -4498,6 +4528,14 @@
 		if (!next_segment (ce, state, line, &line_pos, &new_state))
 			break;
 
+		if (g_timer_elapsed (timer, NULL) * 1000 > MAX_TIME_FOR_ONE_LINE)
+		{
+			g_critical (_("Highlighting a single line took too much time, "
+				      "syntax highlighting will be disabled"));
+			disable_highlighting (ce);
+			break;
+		}
+
 		g_assert (new_state != NULL);
 		g_assert (SEGMENT_IS_CONTAINER (new_state));
 
@@ -4516,6 +4554,10 @@
 			end_segments = g_list_prepend (end_segments, state);
 	}
 
+	g_timer_destroy (timer);
+	if (ce->priv->disabled)
+		return NULL;
+
 	/* Extend current state to the end of line. */
 	segment_extend (state, line->start_at + line->char_length);
 	g_assert (line_pos <= line->byte_length);
@@ -5459,6 +5501,10 @@
 
 		state = analyze_line (ce, state, &line);
 
+		/* At this point analyze_line() could have disabled highlighting */
+		if (ce->priv->disabled)
+			return;
+
 #ifdef ENABLE_CHECK_TREE
 		{
 			Segment *inv = get_invalid_segment (ce);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]